diff -Nru circuits-3.1.0+ds1/bin/circuits.bench circuits-3.2.2/bin/circuits.bench --- circuits-3.1.0+ds1/bin/circuits.bench 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/bin/circuits.bench 2021-10-19 16:23:49.000000000 +0000 @@ -8,11 +8,15 @@ """ -import sys import math import optparse +import sys from time import sleep +from circuits import ( + Component, Debugger, Event, Manager, __version__ as systemVersion, handler, +) + if sys.platform == "win32": from time import clock as time else: @@ -31,10 +35,6 @@ psyco = None # NOQA -from circuits import __version__ as systemVersion -from circuits import handler, Event, Component, Manager, Debugger - - USAGE = "%prog [options]" VERSION = "%prog v" + systemVersion diff -Nru circuits-3.1.0+ds1/bin/htpasswd circuits-3.2.2/bin/htpasswd --- circuits-3.1.0+ds1/bin/htpasswd 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/bin/htpasswd 2021-10-19 16:23:49.000000000 +0000 @@ -14,8 +14,8 @@ import os -import sys import random +import sys from hashlib import md5, sha1 from optparse import OptionParser diff -Nru circuits-3.1.0+ds1/CHANGES.rst circuits-3.2.2/CHANGES.rst --- circuits-3.1.0+ds1/CHANGES.rst 2014-10-31 23:12:37.000000000 +0000 +++ circuits-3.2.2/CHANGES.rst 2021-10-19 16:23:49.000000000 +0000 @@ -5,7 +5,71 @@ Change Log ========== +- :release:`3.2.2 ETA <2021-10-19>` +- :support:`298` Added support for Python 3.10 +- :feature:`132` The initial `request` containing the `session` has been added to the websocket dispatcher events in `circuits.web.websockets` +- :feature:`96` `circuits.tools.graph()` has been split into smaller functions (for creating `dot`, `ascii`, `png` separately) +- :bug:`197` Exceptions during initialization of `Poller`s is now handlded via an `error` Event +- :bug:`197` Exceptions during `socket.accept()` are now re-raised in the main thread +- :bug:`261` A workaroung for websocket clients has been added, which prevents that the first websocket is not lost +- :bug:`307` Various format string syntaxes have been relaxed so that they don't cause exceptions on non string input +- :doc:`-` typos in docstrings/comments have been fixed +- :security:`293` HTML escaping of error responses, 3XX redirects and Powered-by texts has been fixed +- :security:`251` A HTTP header injection vulnerability in `circuits.web.websockets.client` has been fixed +- :security:`289` potential XSS attacks via crafted files in directory listing is now prevented via HTML escaping in the `circuits.web.dispatchers.static` component. +- :bug:`291` HTTP `Connection` header values are now correctly evaluated case insensitive in `websocket` components +- :bug:`292` HTTP `Connection` header values are now correctly evaluated case insensitive in `web.client` components +- :bug:`-` Fixed Python 3 compatibility for `circuits.web.tools.validate_etag()` with `MD5` hashes +- :bug:`238` Reverted changes fixed by upstream `http-parser` library +- :bug:`285` `circuits.web.parsers.http` has been upgraded to latest upstream `http-parser` version +- :bug:`285` requests with chunked transfer encoding are not dispatched if the message body is not yet received completely +- :bug:`253` `circuits.io.serial`: add readline argument to only fire read events for full lines +- :bug:`252` `circuits.io.serial`: missing encoding parameter has been added +- :release:`3.2.1 <2020-10-30>` +- :support:`-` Added support for Python 3.6, 3.7, 3.8, 3.9-dev +- :support:`152` Dropped the support for Python 2.6 and 3.x < 3.4 +- :bug:`176` Generator expressions don't raise StopIteration anymore +- :feature:`-` The exception handling has been improoved +- :feature:`273` Added a `bufsize` argument to the `__init__` of BaseServer +- :bug:`270` fix TLS support for websockets (unhandled SSLWantReadError) +- :bug:`263` Improove error handling during TLS handshake +- :bug:`269` Fix error handling when TLS handshake fails +- :bug:`266` Fix python2 `str(circuits.core.values.Value())` +- :bug:`264` Improoved robustness of IRC messages +- :bug:`257` Fix WSGI component for Python 2.7 and Python 3 +- :bug:`254` Fix CRLF injection in IRC protocol +- :feature:`245` IRC: enhance stripping of colors +- :feature:`249` Add `irc.utils.irc_color_to_ansi()` +- :bug:`241` Adjust `circuits.tools.graph()` to API change in `networkx` +- :feature:`240` Added `auto_add` to `circuits.io.notify` +- :feature:`231` Add support for `STOMP` protocol +- :bug:`238` Fix parsing HTTP request without headers +- :bug:`235` the `prefix` in the `Debugger` might be a `callable` now +- :feature:`233` `circuits.core.values.Value` is now `__str__` compatible with Python 2 +- :feature:`212` Improves the API for session management and adds expire support +- :feature:`224` Add new HTTP status code `308 moved permanently` (:rfc:`7538`) +- :feature:`214` Implement `STARTTLS` for sockets as `event` +- :feature:`-` Add support to set additional socket options +- :bug:`198` Made pushing onto the event queue via `fire` threadsafe. +- :feature:`202` Removed `EventType` metaclass +- :bug:`-` Fixed `manager.join()` +- :bug:`202` Removed the (unused) internal cache from `EventType`. +- :feature:`168` Add interface for selecting the websocket subprotocol +- :bug:`54` Fix a memory leak due to `on_done` handlers +- :bug:`-` Fix python3 compatibility when parsing `HTTP` request body +- :bug:`-` Fix error handling if error contains traceback instance +- :bug:`187` Fix parsing and decoding of `application/x-www-urlencoded` payloads +- :bug:`185` Fix Denial of Service socket/memory leak for not connected clients +- :bug:`184` Fix websocket data parsing if content is larger than BUFSIZE +- :bug:`170` Fix crash from deleting undefined variables +- :bug:`173` Fix the type difference between _current_thread and _flushing_thread +- :bug:`123` Fixes bug in the `complete` event +- :bug:`165` Fix `Host` HTTP header parsing when `circuits.web.Server` is bound to a `UNIX` Socket + +- :release:`3.2 <2016-06-02>` +- :bug:`119` Fixed bug in ``circuits.web.url.parse_url()`` that caused a + display issue with port bindings on ports 80 and 443. - :release:`3.1 <2014-11-01>` - :bug:`-` Bridge waits for event processing on the other side before proxy handler ends. Now it is possible to collect values from remote handlers in %_success event. - :bug:`-` Rename the FallbackErrorHandler to FallbackExceptionHandler and the event it listens to to exception diff -Nru circuits-3.1.0+ds1/circuits/app/daemon.py circuits-3.2.2/circuits/app/daemon.py --- circuits-3.1.0+ds1/circuits/app/daemon.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/circuits/app/daemon.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,28 +1,27 @@ -# Module: daemon -# Date: 20th June 2009 -# Author: James Mills, prologic at shortcircuit dot net dot au - - """Daemon Component Component to daemonize a system into the background and detach it from its controlling PTY. Supports PID file writing, logging stdin, stdout and stderr and changing the current working directory. """ - - +from os import ( + _exit, chdir, closerange, dup2, fork, getpid, remove, setsid, umask, +) from os.path import isabs +from resource import RLIM_INFINITY, RLIMIT_NOFILE, getrlimit from sys import stderr, stdin, stdout -from os import _exit, chdir, dup2, setsid, fork, getpid, remove, umask - -from circuits.core import handler, Component, Event +from circuits.core import Component, Event, handler class daemonize(Event): """daemonize Event""" +class daemonized(Event): + """daemonized Event""" + + class deletepid(Event): """"deletepid Event""" @@ -84,8 +83,8 @@ _exit(0) except OSError as e: stderr.write( - "fork #1 failed: {0:d} ({0:s})\n".format( - e.errno, str(e) + "fork #1 failed: {:d} ({})\n".format( + e.errno, e ) ) @@ -104,8 +103,8 @@ _exit(0) except OSError as e: stderr.write( - "fork #2 failed: {0:d} ({0:s})\n".format( - e.errno, str(e) + "fork #2 failed: {:d} ({})\n".format( + e.errno, e ) ) @@ -115,6 +114,12 @@ stdout.flush() stderr.flush() + maxfd = getrlimit(RLIMIT_NOFILE)[1] + if maxfd == RLIM_INFINITY: + maxfd = 2048 + + closerange(0, maxfd) + si = open(self.stdin, "r") so = open(self.stdout, "a+") se = open(self.stderr, "a+") @@ -124,6 +129,7 @@ dup2(se.fileno(), stderr.fileno()) self.fire(writepid()) + self.fire(daemonized(self)) def registered(self, component, manager): if component == self and manager.root.running: diff -Nru circuits-3.1.0+ds1/circuits/app/dropprivileges.py circuits-3.2.2/circuits/app/dropprivileges.py --- circuits-3.1.0+ds1/circuits/app/dropprivileges.py 1970-01-01 00:00:00.000000000 +0000 +++ circuits-3.2.2/circuits/app/dropprivileges.py 2021-10-19 16:23:49.000000000 +0000 @@ -0,0 +1,50 @@ +from grp import getgrnam +from os import getuid, setgid, setgroups, setuid, umask +from pwd import getpwnam +from traceback import format_exc + +from circuits.core import BaseComponent, handler + + +class DropPrivileges(BaseComponent): + + def init(self, user="nobody", group="nobody", umask=0o077, **kwargs): + self.user = user + self.group = group + self.umask = umask + + def drop_privileges(self): + if getuid() > 0: + # Running as non-root. Ignore. + return + + try: + # Get the uid/gid from the name + uid = getpwnam(self.user).pw_uid + gid = getgrnam(self.group).gr_gid + except KeyError as error: + print("ERROR: Could not drop privileges {}".format(error)) + print(format_exc()) + raise SystemExit(-1) + + try: + # Remove group privileges + setgroups([]) + + # Try setting the new uid/gid + setgid(gid) + setuid(uid) + + if self.umask is not None: + umask(self.umask) + except Exception as error: + print("ERROR: Could not drop privileges {}".format(error)) + print(format_exc()) + raise SystemExit(-1) + + @handler("ready", channel="*") + def on_ready(self, server, bind): + try: + self.drop_privileges() + finally: + self.unregister() diff -Nru circuits-3.1.0+ds1/circuits/app/__init__.py circuits-3.2.2/circuits/app/__init__.py --- circuits-3.1.0+ds1/circuits/app/__init__.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/circuits/app/__init__.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,18 +1,12 @@ -# Package: app -# Date: 20th June 2009 -# Author: James Mills, prologic at shortcircuit dot net dot au - """Application Components Contains various components useful for application development and tasks common to applications. - -:copyright: CopyRight (C) 2004-2013 by James Mills -:license: MIT (See: LICENSE) """ - from .daemon import Daemon +from .dropprivileges import DropPrivileges -__all__ = ("Daemon",) +__all__ = ("Daemon", "DropPrivileges",) # flake8: noqa +# pylama: skip=1 diff -Nru circuits-3.1.0+ds1/circuits/core/bridge.py circuits-3.2.2/circuits/core/bridge.py --- circuits-3.1.0+ds1/circuits/core/bridge.py 2014-10-22 08:37:49.000000000 +0000 +++ circuits-3.2.2/circuits/core/bridge.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,45 +1,51 @@ -# Module: bridge -# Date: 2nd April 2006 -# Author: James Mills, prologic at shortcircuit dot net dot au - """Bridge The Bridge Component is used for inter-process communications between processes. Bridge is used internally when a Component is started in "process mode" via :meth:`circuits.core.manager.start`. Typically a Pipe is used as the socket transport between two sides of a Bridge -(*there must be a :class:`~Bridge` instnace on both sides*). - +(*there must be a :class:`~Bridge` instance on both sides*). """ import traceback +from .components import BaseComponent +from .events import Event, exception +from .handlers import handler +from .values import Value + try: from cPickle import dumps, loads except ImportError: from pickle import dumps, loads # NOQA -from .values import Value -from .events import Event, exception -from .handlers import handler -from .components import BaseComponent -from ..six import b +_sentinel = b'~~~' + + +class ipc(Event): + """ipc Event + + Send an event to a child/parent process + """ + + def __init__(self, event, channel=None): + """ + :param event: Event to execute remotely. + :type event: :class:`circuits.core.events.Event` -_sentinel = b('~~~') + :param channel: IPC Channel (channel to use on child/parent). + :type channel: str + """ + + super(ipc, self).__init__(event, channel=channel) class Bridge(BaseComponent): channel = "bridge" - ignore = [ - "registered", "unregistered", "started", "stopped", "error", - "value_changed", "generate_events", "read", "write", "close", - "connected", "connect", "disconnect", "disconnected", "_read", - "_write", "ready", "read_value_changed", "prepare_unregister" - ] - def init(self, socket, channel=channel): + self._buffer = b"" self._socket = socket self._values = dict() @@ -64,43 +70,69 @@ event.remote = True self.fire(event, self.channel) - @handler("value_changed", channel="*") def _on_value_changed(self, value): try: eid = self._values[value] + if value.errors: + Bridge.__adapt_error_value(value) self.__write(eid, value) - except: + except Exception: pass @handler("read") def _on_read(self, data): - data = data.split(_sentinel) - for item in data[:-1]: + self._buffer += data + items = self._buffer.split(_sentinel) + + if items[-1] != "": + self._buffer = items.pop() + + for item in filter(None, items): self._process_packet(*loads(item)) - def send(self, eid, event): + def __send(self, eid, event): try: if isinstance(event, exception): Bridge.__adapt_exception(event) self._values[eid] = event.value self.__write(eid, event) - except: + except Exception: pass def __write(self, eid, data): - self._socket.write(dumps((eid, data))+_sentinel) + self._socket.write(dumps((eid, data)) + _sentinel) + + @handler("ipc") + def _on_ipc(self, event, ipc_event, channel=None): + """Send event to a child/parentprocess + + Event handler to run an event on a child/parent process + (the event definition is :class:`circuits.core.bridge.ipc`) - @handler(channel="*", priority=100.0) - def _on_event(self, event, *args, **kwargs): - if event.name in self.ignore or getattr(event, "remote", False) \ - or event.name.endswith('_done') \ - or event.name.endswith('_success') \ - or event.name.endswith('_complete'): - return + :param event: The event triggered (by the handler) + :type event: :class:`circuits.node.events.remote` - eid = hash(event) - self.send(eid, event) + :param ipc_event: Event to execute in child/parent process. + :type ipc_event: :class:`circuits.core.events.Event` + + :param channel: Remote channel (channel to use on peer). + :type channel: str + + :return: The result of remote event + :rtype: generator + + :Example: + ``# hello is your event to execute in the child process + result = yield self.fire(ipc(hello())) + print(result.value)`` + """ + + ipc_event.channels = (channel,) if channel is not None else event.channels + event.value.value = ipc_event.value = Value(ipc_event, self) + + eid = hash(ipc_event) + self.__send(eid, ipc_event) yield self.wait(Bridge.__waiting_event(eid)) @staticmethod @@ -110,4 +142,9 @@ @staticmethod def __adapt_exception(ex): fevent_value = ex.kwargs['fevent'].value - fevent_value._value = (fevent_value[0], fevent_value[1], traceback.extract_tb(fevent_value[2])) + Bridge.__adapt_error_value(fevent_value) + + @staticmethod + def __adapt_error_value(value): + if not isinstance(value[2], list): + value._value = (value[0], value[1], traceback.extract_tb(value[2])) diff -Nru circuits-3.1.0+ds1/circuits/core/components.py circuits-3.2.2/circuits/core/components.py --- circuits-3.1.0+ds1/circuits/core/components.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/circuits/core/components.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,22 +1,21 @@ -# Package: components -# Date: 11th April 2010 -# Author: James Mills, prologic at shortcircuit dot net dot au - """ This module defines the BaseComponent and its subclass Component. """ - +from inspect import getmembers from itertools import chain from types import MethodType -from inspect import getmembers -from collections import Callable +try: + from collections import Callable +except ImportError: + from collections.abc import Callable -from .manager import Manager -from .handlers import handler, HandlerMetaClass from .events import Event, registered, unregistered +from .handlers import HandlerMetaClass, handler +from .manager import Manager class prepare_unregister(Event): + """ This event is fired when a component is about to be unregistered from the component tree. Unregistering a component actually @@ -50,6 +49,7 @@ class BaseComponent(Manager): + """ This is the base class for all components in a circuits based application. Components can (and should, except for root components) be registered @@ -91,7 +91,8 @@ if getattr(v, "handler", False)] ) - overridden = lambda x: x in handlers and handlers[x].override + def overridden(x): + return x in handlers and handlers[x].override for base in cls.__bases__: if issubclass(cls, base): @@ -171,7 +172,7 @@ :class:`~.events.unregistered` event is fired. """ - if self.unregister_pending or self.parent == self: + if self.unregister_pending or self.parent is self: return self # tick shouldn't be called anymore, although component is still in tree diff -Nru circuits-3.1.0+ds1/circuits/core/debugger.py circuits-3.2.2/circuits/core/debugger.py --- circuits-3.1.0+ds1/circuits/core/debugger.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/circuits/core/debugger.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,25 +1,18 @@ -# Module: debugger -# Date: 2nd April 2006 -# Author: James Mills, prologic at shortcircuit dot net dot au - - """ Debugger component used to debug each event in a system by printing each event to sys.stderr or to a Logger Component instance. """ - - import os import sys -from traceback import format_exc from signal import SIGINT, SIGTERM - +from traceback import format_exc, format_exception_only from .components import BaseComponent from .handlers import handler, reprhandler class Debugger(BaseComponent): + """Create a new Debugger Component Creates a new Debugger Component that listens to all events in the system @@ -77,12 +70,14 @@ else: handler = reprhandler(handler) - msg = "ERROR {0:s} ({1:s}) ({2:s}): {3:s}\n".format( - handler, repr(fevent), repr(error_type), repr(value) + msg = "ERROR {} ({!r}) ({!r}): {!r}\n".format( + handler, fevent, error_type, value ) s.append(msg) + s.append('Traceback (most recent call last):\n') s.extend(traceback) + s.extend(format_exception_only(error_type, value)) s.append("\n") if self.logger is not None: @@ -118,7 +113,10 @@ s = repr(event) if self.prefix: - s = "%s: %s" % (self.prefix, s) + if hasattr(self.prefix, '__call__'): + s = "%s: %s" % (self.prefix(), s) + else: + s = "%s: %s" % (self.prefix, s) if self.trim: s = "%s ...>" % s[:self.trim] diff -Nru circuits-3.1.0+ds1/circuits/core/events.py circuits-3.2.2/circuits/core/events.py --- circuits-3.1.0+ds1/circuits/core/events.py 2014-09-24 09:45:33.000000000 +0000 +++ circuits-3.2.2/circuits/core/events.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,37 +1,12 @@ -# Package: events -# Date: 11th April 2010 -# Author: James Mills, prologic at shortcircuit dot net dot au - - """ This module defines the basic event class and common events. """ - - from inspect import ismethod - - -class EventType(type): - - __cache__ = {} - - def __new__(cls, name, bases, ns): - key = (cls, name, bases) - - try: - return cls.__cache__[key] - except KeyError: - cls = type.__new__(cls, name, bases, ns) - - setattr(cls, "name", ns.get("name", cls.__name__)) - - return cls +from traceback import format_tb class Event(object): - __metaclass__ = EventType - channels = () "The channels this message is sent to." @@ -44,12 +19,12 @@ waitingHandlers = 0 @classmethod - def create(cls, name, *args, **kwargs): - return type(cls)(name, (cls,), {})(*args, **kwargs) + def create(cls, _name, *args, **kwargs): + return type(cls)(_name, (cls,), {})(*args, **kwargs) def child(self, name, *args, **kwargs): e = Event.create( - "{0:s}_{1:s}".format(self.name, name), *args, **kwargs + "{:s}_{:s}".format(self.name, name), *args, **kwargs ) e.parent = self return e @@ -192,6 +167,7 @@ class exception(Event): + """exception Event This event is sent for any exceptions that occur during the execution @@ -201,7 +177,7 @@ :type type: type :param value: exception object - :type value: exceptions.TypeError + :type value: exceptions.Exceptions :param traceback: traceback of exception :type traceback: traceback @@ -214,11 +190,16 @@ """ def __init__(self, type, value, traceback, handler=None, fevent=None): - super(exception, self).__init__(type, value, traceback, + super(exception, self).__init__(type, value, + self.format_traceback(traceback), handler=handler, fevent=fevent) + def format_traceback(self, traceback): + return format_tb(traceback) + class started(Event): + """started Event This Event is sent when a Component or Manager has started running. @@ -232,6 +213,7 @@ class stopped(Event): + """stopped Event This Event is sent when a Component or Manager has stopped running. @@ -245,6 +227,7 @@ class signal(Event): + """signal Event This Event is sent when a Component receives a signal. @@ -261,6 +244,7 @@ class registered(Event): + """registered Event This Event is sent when a Component has registered with another Component @@ -279,6 +263,7 @@ class unregistered(Event): + """unregistered Event This Event is sent when a Component has been unregistered from its @@ -287,6 +272,7 @@ class generate_events(Event): + """generate_events Event This Event is sent by the circuits core. All components that generate @@ -340,8 +326,7 @@ """ with self._lock: - if time_left >= 0 and (self._time_left < 0 - or self._time_left > time_left): + if time_left >= 0 and (self._time_left < 0 or self._time_left > time_left): self._time_left = time_left if self._time_left == 0 and self.handler is not None: m = getattr( diff -Nru circuits-3.1.0+ds1/circuits/core/handlers.py circuits-3.2.2/circuits/core/handlers.py --- circuits-3.1.0+ds1/circuits/core/handlers.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/circuits/core/handlers.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,13 +1,12 @@ -# Package: handlers -# Date: 11th April 2010 -# Author: James Mills, prologic at shortcircuit dot net dot au - """ This module define the @handler decorator/function and the HandlesType type. """ +try: + from collections import Callable +except ImportError: + from collections.abc import Callable -from inspect import getargspec -from collections import Callable +from circuits.tools import getargspec def handler(*names, **kwargs): @@ -90,11 +89,12 @@ class Unknown(object): + """Unknown Dummy Component""" def reprhandler(handler): - format = "" + format = "" channel = getattr(handler, "channel", "*") if channel is None: @@ -104,7 +104,7 @@ if isinstance(channel, Manager): channel = "" - names = ".".join(handler.names) + names = ",".join(handler.names) instance = getattr( handler, "im_self", getattr( @@ -114,7 +114,9 @@ method = handler.__name__ - return format % (channel, names, instance, method) + priority = "[%0.2f]" % (handler.priority,) if handler.priority else "" + + return format % (channel, names, priority, instance, method) class HandlerMetaClass(type): @@ -125,4 +127,7 @@ callables = (x for x in ns.items() if isinstance(x[1], Callable)) for name, callable in callables: if not (name.startswith("_") or hasattr(callable, "handler")): - setattr(cls, name, handler(name)(callable)) + try: + setattr(cls, name, handler(name)(callable)) + except ValueError as e: + raise ValueError('{} - {} {}'.format(str(e), repr(cls), name)) diff -Nru circuits-3.1.0+ds1/circuits/core/helpers.py circuits-3.2.2/circuits/core/helpers.py --- circuits-3.1.0+ds1/circuits/core/helpers.py 2014-10-05 02:23:20.000000000 +0000 +++ circuits-3.2.2/circuits/core/helpers.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,16 +1,15 @@ """ .. codeauthor: mnl """ - - +from signal import SIGINT, SIGTERM from sys import stderr from threading import Event -from signal import SIGINT, SIGTERM +from traceback import format_exception_only +from circuits.core.handlers import reprhandler -from .handlers import handler from .components import BaseComponent -from circuits.core.handlers import reprhandler +from .handlers import handler class FallBackGenerator(BaseComponent): @@ -70,6 +69,7 @@ class FallBackExceptionHandler(BaseComponent): + """ If there is no handler for error events in the component hierarchy, this component's handler is added automatically. It simply prints @@ -86,17 +86,20 @@ else: handler = reprhandler(handler) - msg = "ERROR {0:s} ({1:s}) ({2:s}): {3:s}\n".format( - handler, repr(fevent), repr(error_type), repr(value) + msg = "ERROR {} ({!r}) ({!r}): {!r}\n".format( + handler, fevent, error_type, value ) s.append(msg) + s.append('Traceback (most recent call last):\n') s.extend(traceback) + s.extend(format_exception_only(error_type, value)) s.append("\n") stderr.write("".join(s)) class FallBackSignalHandler(BaseComponent): + """ If there is no handler for signal events in the component hierarchy, this component's handler is added automatically. It simply terminates the diff -Nru circuits-3.1.0+ds1/circuits/core/__init__.py circuits-3.2.2/circuits/core/__init__.py --- circuits-3.1.0+ds1/circuits/core/__init__.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/circuits/core/__init__.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,31 +1,22 @@ -# Package: core -# Date: 2nd April 2006 -# Author: James Mills, prologic at shortcircuit dot net dot au - """Core This package contains the essential core parts of the circuits framework. """ - - +from .bridge import Bridge, ipc +from .components import BaseComponent, Component +from .debugger import Debugger from .events import Event -from .bridge import Bridge -from .loader import Loader -from .manager import Manager, TimeoutError from .handlers import handler, reprhandler -from .components import BaseComponent, Component - -from .values import Value - +from .loader import Loader +from .manager import Manager, TimeoutError, sleep from .timers import Timer - -from .workers import task, Worker - -from .debugger import Debugger +from .values import Value +from .workers import Worker, task __all__ = ( "handler", "BaseComponent", "Component", "Event", "task", - "Worker", "Bridge", "Debugger", "Timer", "Manager", "TimeoutError", + "Worker", "ipc", "Bridge", "Debugger", "Timer", "Manager", "TimeoutError", ) # flake8: noqa +# pylama: skip=1 diff -Nru circuits-3.1.0+ds1/circuits/core/loader.py circuits-3.2.2/circuits/core/loader.py --- circuits-3.1.0+ds1/circuits/core/loader.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/circuits/core/loader.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,22 +1,18 @@ -# Package: loader -# Date: 16th March 2011 -# Author: James Mills, jamesmills at comops dot com dot au - """ This module implements a generic Loader suitable for dynamically loading components from other modules. This supports loading from local paths, eggs and zip archives. Both setuptools and distribute are fully supported. """ - import sys from inspect import getmembers, getmodule, isclass +from .components import BaseComponent from .handlers import handler from .utils import safeimport -from .components import BaseComponent class Loader(BaseComponent): + """Create a new Loader Component Creates a new Loader Component that enables dynamic loading of @@ -44,9 +40,8 @@ module = safeimport(name) if module is not None: - test = lambda x: isclass(x) \ - and issubclass(x, BaseComponent) \ - and getmodule(x) is module + def test(x): + return isclass(x) and issubclass(x, BaseComponent) and getmodule(x) is module components = [x[1] for x in getmembers(module, test)] if components: diff -Nru circuits-3.1.0+ds1/circuits/core/manager.py circuits-3.2.2/circuits/core/manager.py --- circuits-3.1.0+ds1/circuits/core/manager.py 2014-10-05 06:28:12.000000000 +0000 +++ circuits-3.2.2/circuits/core/manager.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,29 +1,27 @@ -# Package: manager -# Date: 11th April 2010 -# Author: James Mills, prologic at shortcircuit dot net dot au - - """ This module defines the Manager class. """ - - import atexit -from os import getpid, kill +from collections import deque +from heapq import heappop, heappush from inspect import isfunction -from uuid import uuid4 as uuid -from operator import attrgetter -from types import GeneratorType from itertools import chain, count -from signal import SIGINT, SIGTERM -from heapq import heappush, heappop -from weakref import WeakValueDictionary -from traceback import format_exc, format_tb +from multiprocessing import Process, current_process +from operator import attrgetter +from os import getpid, kill +from signal import SIGINT, SIGTERM, signal as set_signal_handler from sys import exc_info as _exc_info, stderr -from signal import signal as set_signal_handler -from threading import current_thread, Thread, RLock -from multiprocessing import current_process, Process +from threading import RLock, Thread, current_thread +from time import time +from traceback import format_exc +from types import GeneratorType +from uuid import uuid4 as uuid +from ..six import Iterator, create_bound_method, next +from ..tools import tryimport +from .events import Event, exception, generate_events, signal, started, stopped +from .handlers import handler +from .values import Value try: from signal import SIGKILL @@ -31,13 +29,6 @@ SIGKILL = SIGTERM -from .values import Value -from ..tools import tryimport -from .handlers import handler -from ..six import create_bound_method, next -from .events import exception, generate_events, signal, started, stopped, Event - - thread = tryimport(("thread", "_thread")) @@ -45,19 +36,23 @@ class UnregistrableError(Exception): + """Raised if a component cannot be registered as child.""" class TimeoutError(Exception): + """Raised if wait event timeout occurred""" class CallValue(object): + def __init__(self, value): self.value = value class ExceptionWrapper(object): + def __init__(self, exception): self.exception = exception @@ -65,6 +60,49 @@ return self.exception +class Sleep(Iterator): + + def __init__(self, seconds): + self._task = None + + try: + self.expiry = time() + float(seconds) + except ValueError: + raise TypeError("a float is required") + + def __iter__(self): + return self + + def __repr__(self): + return "sleep({!r})".format(self.expiry - time()) + + def __next__(self): + if time() >= self.expiry: + raise StopIteration() + return self + + @property + def expired(self): + return time() >= self.expiry + + @property + def task(self): + return self._task + + @task.setter + def task(self, task): + self._task = task + + +def sleep(seconds): + """ + Delay execution of a coroutine for a given number of seconds. + The argument may be a floating point number for subsecond precision. + """ + + return Sleep(seconds) + + class Dummy(object): channel = None @@ -74,7 +112,60 @@ del Dummy +class _State(object): + + __slots__ = ('task', 'run', 'flag', 'event', 'timeout', 'parent', 'task_event', 'tick_handler') + + def __init__(self, timeout): + self.task = None + self.run = False + self.flag = False + self.event = None + self.timeout = timeout + self.parent = None + self.task_event = None + self.tick_handler = None + + +class _EventQueue(object): + __slots__ = ('_queue', '_priority_queue', '_counter', '_flush_batch') + + def __init__(self): + self._queue = deque() + self._priority_queue = [] + self._counter = count() + self._flush_batch = 0 + + def __len__(self): + return len(self._queue) + len(self._priority_queue) + + def drainFrom(self, other_queue): + self._queue.extend(other_queue._queue) + other_queue._queue.clear() + # Queue is currently flushing events /o\ + assert not len(other_queue._priority_queue) + + def append(self, event, channel, priority): + self._queue.append((priority, next(self._counter), (event, channel))) + + def dispatchEvents(self, dispatcher): + if self._flush_batch == 0: + # FIXME: Might be faster to use heapify instead of pop + + # heappush. Though, with regards to thread safety this + # appears to be the better approach. + self._flush_batch = count = len(self._queue) + while count: + count -= 1 + heappush(self._priority_queue, self._queue.popleft()) + + while self._flush_batch > 0: + self._flush_batch -= 1 # Decrement first! + (event, channels) = heappop(self._priority_queue)[2] + dispatcher(event, channels, self._flush_batch) + + class Manager(object): + """ The manager class has two roles. As a base class for component implementation, it provides methods for event and handler management. @@ -131,8 +222,7 @@ def __init__(self, *args, **kwargs): "initializes x; see x.__class__.__doc__ for signature" - self._queue = [] - self._counter = count() + self._queue = _EventQueue() self._tasks = set() self._cache = dict() @@ -142,8 +232,6 @@ self._flush_batch = 0 self._cache_needs_refresh = False - self._values = WeakValueDictionary() - self._executing_thread = None self._flushing_thread = None self._running = False @@ -154,12 +242,19 @@ self.root = self.parent = self self.components = set() + def __nonzero__(self): + "x.__nonzero__() <==> bool(x)" + + return True + + __bool__ = __nonzero__ + def __repr__(self): "x.__repr__() <==> repr(x)" name = self.__class__.__name__ - channel = "/{0:s}".format(str(getattr(self, "channel", ""))) + channel = "/{}".format(getattr(self, "channel", "")) q = len(self._queue) state = "R" if self.running else "S" @@ -220,14 +315,14 @@ def __sub__(self, y): """x.__sub__(y) <==> x-y - (Optional) Convenience operator to unregister y from x.manager + (Optional) Convenience operator to unregister y from x.parent Equivalent to: y.unregister() @return: x @rtype Component or Manager """ - if y.manager is not y: + if y.parent is not y: y.unregister() return self @@ -241,7 +336,7 @@ @rtype Component or Manager """ - if y.manager is not y: + if y.parent is not y: y.unregister() return self @@ -340,8 +435,7 @@ self.root._executing_thread = component._executing_thread component._executing_thread = None self.components.add(component) - self.root._queue.extend(list(component._queue)) - component._queue = [] + self.root._queue.drainFrom(component._queue) self.root._cache_needs_refresh = True def unregisterChild(self, component): @@ -350,8 +444,9 @@ def _fire(self, event, channel, priority=0): # check if event is fired while handling an event - if thread.get_ident() == (self._executing_thread or \ - self._flushing_thread) and not isinstance(event, signal): + th = (self._executing_thread or self._flushing_thread) + if thread.get_ident() == (th.ident if th else None) and \ + not isinstance(event, signal): if self._currently_handling is not None and \ getattr(self._currently_handling, "cause", None): # if the currently handled event wants to track the @@ -360,14 +455,7 @@ event.effects = 1 self._currently_handling.effects += 1 - heappush( - self._queue, - ( - priority, - next(self._counter), - (event, channel) - ) - ) + self._queue.append(event, channel, priority) # the event comes from another thread else: @@ -385,25 +473,9 @@ # operations that assume its value to remain unchanged. handling = self._currently_handling + self._queue.append(event, channel, priority) if isinstance(handling, generate_events): - heappush( - self._queue, - ( - priority, - next(self._counter), - (event, channel) - ) - ) handling.reduce_time_left(0) - else: - heappush( - self._queue, - ( - priority, - next(self._counter), - (event, channel) - ) - ) def fireEvent(self, event, *channels, **kwargs): """Fire an event into the system. @@ -419,9 +491,7 @@ """ if not channels: - channels = event.channels \ - or (getattr(self, "channel", "*"),) \ - or ("*",) + channels = event.channels or (getattr(self, "channel", "*"),) or ("*",) event.channels = channels @@ -439,55 +509,49 @@ if g in self.root._tasks: self.root._tasks.remove(g) - def waitEvent(self, event, *channels, **kwargs): + def waitEvent(self, event, *channels, **kwargs): # noqa + # XXX: C901: This has a high McCabe complexity score of 16. + # TODO: Refactor this method. + if isinstance(event, Event): event_object = event event_name = event.name + channels = event.channels or channels else: event_object = None event_name = event - state = { - 'run': False, - 'flag': False, - 'event': None, - 'timeout': kwargs.get("timeout", -1) - } + state = _State(timeout=kwargs.get("timeout", -1)) def _on_event(self, event, *args, **kwargs): - if not state['run'] and ( + if not state.run and ( event_object is None or event is event_object - ): + ): self.removeHandler(_on_event_handler, event_name) event.alert_done = True - state['run'] = True - state['event'] = event + state.run = True + state.event = event def _on_done(self, event, *args, **kwargs): - if state['event'] == event.parent: - state['flag'] = True - self.registerTask((state['task_event'], - state['task'], - state['parent'])) - if state['timeout'] > 0: - self.removeHandler( - state['tick_handler'], - "generate_events" - ) + if state.event == event.parent: + state.flag = True + self.registerTask((state.task_event, state.task, state.parent)) + if state.timeout > 0: + self.removeHandler(state.tick_handler, "generate_events") def _on_tick(self): - if state['timeout'] == 0: + if state.timeout == 0: self.registerTask( ( - state['task_event'], + state.task_event, (e for e in (ExceptionWrapper(TimeoutError()),)), - state['parent'] + state.parent ) ) self.removeHandler(_on_done_handler, "%s_done" % event_name) self.removeHandler(_on_tick_handler, "generate_events") - elif state['timeout'] > 0: - state['timeout'] -= 1 + elif state.timeout > 0: + state.timeout -= 1 if not channels: channels = (None,) @@ -497,17 +561,16 @@ handler(event_name, channel=channel)(_on_event)) _on_done_handler = self.addHandler( handler("%s_done" % event_name, channel=channel)(_on_done)) - if state['timeout'] >= 0: - _on_tick_handler = state['tick_handler'] = self.addHandler( + if state.timeout >= 0: + _on_tick_handler = state.tick_handler = self.addHandler( handler("generate_events", channel=channel)(_on_tick)) yield state - if not state['timeout']: - self.removeHandler(_on_done_handler, "%s_done" % event_name) + self.removeHandler(_on_done_handler, "%s_done" % event_name) - if state["event"] is not None: - yield CallValue(state["event"].value) + if state.event is not None: + yield CallValue(state.event.value) wait = waitEvent @@ -533,13 +596,8 @@ # events. Note that _flush can be called recursively. old_flushing = self._flushing_thread try: - self._flushing_thread = thread.get_ident() - if self._flush_batch == 0: - self._flush_batch = len(self._queue) - while self._flush_batch > 0: - self._flush_batch -= 1 # Decrement first! - priority, count, (event, channels) = heappop(self._queue) - self._dispatcher(event, channels, self._flush_batch) + self._flushing_thread = current_thread() + self._queue.dispatchEvents(self._dispatcher) finally: self._flushing_thread = old_flushing @@ -554,7 +612,10 @@ flush = flushEvents - def _dispatcher(self, event, channels, remaining): + def _dispatcher(self, event, channels, remaining): # noqa + # XXX: C901: This has a high McCabe complexity score of 22. + # TODO: Refactor this method. + if event.cancelled: return @@ -571,11 +632,11 @@ self._cache.clear() self._cache_needs_refresh = False try: # try/except is fastest if successful in most cases - handlers = self._cache[(event.name, channels)] + event_handlers = self._cache[(event.name, channels)] except KeyError: h = (self.getHandlers(event, channel) for channel in channels) - handlers = sorted( + event_handlers = sorted( chain(*h), key=attrgetter("priority"), reverse=True @@ -583,15 +644,15 @@ if isinstance(event, generate_events): from .helpers import FallBackGenerator - handlers.append(FallBackGenerator()._on_generate_events) - elif isinstance(event, exception) and len(handlers) == 0: + event_handlers.append(FallBackGenerator()._on_generate_events) + elif isinstance(event, exception) and len(event_handlers) == 0: from .helpers import FallBackExceptionHandler - handlers.append(FallBackExceptionHandler()._on_exception) - elif isinstance(event, signal) and len(handlers) == 0: + event_handlers.append(FallBackExceptionHandler()._on_exception) + elif isinstance(event, signal) and len(event_handlers) == 0: from .helpers import FallBackSignalHandler - handlers.append(FallBackSignalHandler()._on_signal) + event_handlers.append(FallBackSignalHandler()._on_signal) - self._cache[(event.name, channels)] = handlers + self._cache[(event.name, channels)] = event_handlers if isinstance(event, generate_events): with self._lock: @@ -601,7 +662,7 @@ elif self._tasks: event.reduce_time_left(TIMEOUT) # From now on, firing an event will reduce time left - # to 0, which prevents handlers from waiting (or wakes + # to 0, which prevents event handlers from waiting (or wakes # them up with resume if they should be waiting already) else: self._currently_handling = event @@ -609,36 +670,28 @@ value = None err = None - for handler in handlers: - event.handler = handler + for event_handler in event_handlers: + event.handler = event_handler try: - if handler.event: - value = handler(event, *eargs, **ekwargs) + if event_handler.event: + value = event_handler(event, *eargs, **ekwargs) else: - value = handler(*eargs, **ekwargs) - except (KeyboardInterrupt, SystemExit): + value = event_handler(*eargs, **ekwargs) + except KeyboardInterrupt: self.stop() - except: - etype, evalue, etraceback = _exc_info() - traceback = format_tb(etraceback) - err = (etype, evalue, traceback) - + except SystemExit as e: + self.stop(e.code) + except BaseException: + value = err = _exc_info() event.value.errors = True - value = err - if event.failure: self.fire( event.child("failure", event, err), *event.channels ) - self.fire( - exception( - etype, evalue, traceback, - handler=handler, fevent=event - ) - ) + self.fire(exception(*err, handler=event_handler, fevent=event)) if value is not None: if isinstance(value, GeneratorType): @@ -649,7 +702,7 @@ event.value.value = value # it is kind of a temporal hack to allow processing - # of tasks, added in one of handlers here + # of tasks, added in one of event handlers here if isinstance(event, generate_events) and self._tasks: event.reduce_time_left(TIMEOUT) @@ -663,8 +716,8 @@ if event.waitingHandlers: return - # The "%s_Done" event is for internal use by waitEvent only. - # Use the "%s_Success" event in you application if you are + # The "%s_done" event is for internal use by waitEvent only. + # Use the "%s_success" event in your application if you are # interested in being notified about the last handler for # an event having been invoked. if event.alert_done: @@ -737,22 +790,22 @@ return self.__thread, None def join(self): - if getattr(self, "_thread", None) is not None: + if self.__thread is not None: return self.__thread.join() - if getattr(self, "_process", None) is not None: + if self.__process is not None: return self.__process.join() - def stop(self): + def stop(self, code=None): """ Stop this manager. Invoking this method causes an invocation of ``run()`` to return. """ - if self.__process is not None and self.__process.is_alive(): + if self.__process not in (None, current_process()) and self.__process.is_alive(): self.__process.terminate() self.__process.join(TIMEOUT) - + if self.__process.is_alive(): kill(self.__process.pid, SIGKILL) @@ -767,7 +820,13 @@ for _ in range(3): self.tick() - def processTask(self, event, task, parent=None): + if code is not None: + raise SystemExit(code) + + def processTask(self, event, task, parent=None): # noqa + # XXX: C901: This has a high McCabe complexity score of 16. + # TODO: Refactor this method. + value = None try: value = next(task) @@ -784,9 +843,9 @@ # in the waitEvent generator # self.registerTask((event, value, parent)) task_state = next(value) - task_state['task_event'] = event - task_state['task'] = value - task_state['parent'] = parent + task_state.task_event = event + task_state.task = value + task_state.parent = parent else: event.waitingHandlers -= 1 if value is not None: @@ -797,9 +856,9 @@ self.unregisterTask((event, task, None)) # First yielded value is always the task state task_state = next(value) - task_state['task_event'] = event - task_state['task'] = value - task_state['parent'] = task + task_state.task_event = event + task_state.task = value + task_state.parent = task # The below code is delegated to handlers # in the waitEvent generator # self.registerTask((event, value, task)) @@ -813,24 +872,34 @@ self.registerTask((event, value_generator, parent)) else: raise value.extract() + elif isinstance(value, Sleep): + if value is not task: + value.task = (event, task, parent) + self.registerTask((event, value, parent)) + self.unregisterTask((event, task, parent)) elif value is not None: event.value.value = value except StopIteration: event.waitingHandlers -= 1 self.unregisterTask((event, task, parent)) + if parent: self.registerTask((event, parent, None)) + elif hasattr(task, "task"): + # XXX: The subtask is considered a "waiting handler" + event.waitingHandlers += 1 + self.registerTask(task.task) elif event.waitingHandlers == 0: event.value.inform(True) self._eventDone(event) - except (KeyboardInterrupt, SystemExit): + except KeyboardInterrupt: self.stop() - except: + except SystemExit as e: + self.stop(e.code) + except BaseException: self.unregisterTask((event, task, parent)) - etype, evalue, etraceback = _exc_info() - traceback = format_tb(etraceback) - err = (etype, evalue, etraceback) + err = _exc_info() event.value.value = err event.value.errors = True @@ -839,12 +908,7 @@ if event.failure: self.fire(event.child("failure", event, err), *event.channels) - self.fire( - exception( - etype, evalue, traceback, - handler=None, fevent=event - ) - ) + self.fire(exception(*err, handler=None, fevent=event)) def tick(self, timeout=-1): """ @@ -868,7 +932,8 @@ if self._running: self.fire(generate_events(self._lock, timeout), "*") - self._queue and self.flush() + if len(self._queue): + self.flush() def run(self, socket=None): """ @@ -912,13 +977,13 @@ # Fading out, handle remaining work from stop event for _ in range(3): self.tick() - except Exception as e: - stderr.write("Unhandled ERROR: {0:s}\n".format(str(e))) + except Exception as exc: + stderr.write("Unhandled ERROR: {}\n".format(exc)) stderr.write(format_exc()) finally: try: self.tick() - except: + except Exception: pass self.root._executing_thread = None diff -Nru circuits-3.1.0+ds1/circuits/core/pollers.py circuits-3.2.2/circuits/core/pollers.py --- circuits-3.1.0+ds1/circuits/core/pollers.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/circuits/core/pollers.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,7 +1,3 @@ -# Module: pollers -# Date: 15th September 2008 -# Author: James Mills - """Poller Components for asynchronous file and socket I/O. This module contains Poller components that enable polling of file or socket @@ -10,34 +6,41 @@ - Poll - EPoll """ - import os -import select import platform +import select +import sys from errno import EBADF, EINTR from select import error as SelectError -from socket import error as SocketError, create_connection, \ - socket as create_socket, AF_INET, SOCK_STREAM, socket +from socket import ( + AF_INET, SOCK_STREAM, create_connection, error as SocketError, socket, +) from threading import Thread + from circuits.core.handlers import handler +from circuits.six import reraise -from .events import Event from .components import BaseComponent +from .events import Event class _read(Event): + """_read Event""" class _write(Event): + """_write Event""" class _error(Event): + """_error Event""" class _disconnect(Event): + """_disconnect Event""" @@ -57,19 +60,25 @@ def _create_control_con(self): if platform.system() == "Linux": return os.pipe() - server = create_socket(AF_INET, SOCK_STREAM) + server = socket(AF_INET, SOCK_STREAM) server.bind(("localhost", 0)) server.listen(1) res_list = [] + exc = [] def accept(): - sock, _ = server.accept() - sock.setblocking(False) - res_list.append(sock) + try: + sock, _ = server.accept() + sock.setblocking(False) + res_list.append(sock) + except EnvironmentError: + exc.append(sys.exc_info()) at = Thread(target=accept) at.start() clnt_sock = create_connection(server.getsockname()) at.join() + if exc: + reraise(*exc[0]) return (res_list[0], clnt_sock) @handler("generate_events", priority=-9) @@ -97,7 +106,7 @@ return self._ctrl_recv.recv(1) else: return os.read(self._ctrl_recv, 1) - except: + except (EnvironmentError, EOFError): return b"\0" def addReader(self, source, fd): @@ -141,6 +150,7 @@ class Select(BasePoller): + """Select(...) -> new Select Poller Component Creates a new Select Poller Component that uses the select poller @@ -173,10 +183,10 @@ r, w, _ = select.select(self._read, self._write, []) else: r, w, _ = select.select(self._read, self._write, [], timeout) - except ValueError as e: + except ValueError: # Possibly a file descriptor has gone negative? return self._preenDescriptors() - except TypeError as e: + except TypeError: # Something *totally* invalid (object w/o fileno, non-integral # result) was passed return self._preenDescriptors() @@ -209,6 +219,7 @@ class Poll(BasePoller): + """Poll(...) -> new Poll Poller Component Creates a new Poll Poller Component that uses the poll poller @@ -223,11 +234,7 @@ self._map = {} self._poller = select.poll() - self._disconnected_flag = ( - select.POLLHUP - | select.POLLERR - | select.POLLNVAL - ) + self._disconnected_flag = (select.POLLHUP | select.POLLERR | select.POLLNVAL) self._read.append(self._ctrl_recv) self._updateRegistration(self._ctrl_recv) @@ -322,6 +329,7 @@ class EPoll(BasePoller): + """EPoll(...) -> new EPoll Poller Component Creates a new EPoll Poller Component that uses the epoll poller @@ -432,6 +440,7 @@ class KQueue(BasePoller): + """KQueue(...) -> new KQueue Poller Component Creates a new KQueue Poller Component that uses the kqueue poller @@ -544,6 +553,7 @@ elif event.filter == select.KQ_FILTER_READ: self.fire(_read(sock), self.getTarget(sock)) + Poller = Select __all__ = ("BasePoller", "Poller", "Select", "Poll", "EPoll", "KQueue") diff -Nru circuits-3.1.0+ds1/circuits/core/timers.py circuits-3.2.2/circuits/core/timers.py --- circuits-3.1.0+ds1/circuits/core/timers.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/circuits/core/timers.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,18 +1,15 @@ -# Module: timers -# Date: 04th August 2004 -# Author: James Mills - """Timer component to facilitate timed events.""" -from circuits.core.handlers import handler - -from time import time, mktime from datetime import datetime +from time import mktime, time + +from circuits.core.handlers import handler from .components import BaseComponent class Timer(BaseComponent): + """Timer Component A timer is a component that fires an event once after a certain @@ -33,7 +30,9 @@ :param persist: An optional keyword argument which if ``True`` will cause the event to be fired repeatedly once per configured interval until the timer - is unregistered. **Default:** ``False`` + is unregistered. If ``False``, the event fires + exactly once after the specified interval, and + the timer is unregistered. **Default:** ``False`` :type persist: ``bool`` """ diff -Nru circuits-3.1.0+ds1/circuits/core/utils.py circuits-3.2.2/circuits/core/utils.py --- circuits-3.1.0+ds1/circuits/core/utils.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/circuits/core/utils.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,14 +1,8 @@ -# Module: utils -# Date: 11th April 2010 -# Author: James Mills, prologic at shortcircuit dot net dot au - """Utils This module defines utilities used by circuits. """ - import sys - from imp import reload @@ -44,6 +38,7 @@ if components: return components[0] + findcmp = findtype @@ -61,7 +56,7 @@ return reload(sys.modules[name]) else: return __import__(name, globals(), locals(), [""]) - except: + except Exception: for name in sys.modules.copy(): - if not name in modules: + if name not in modules: del sys.modules[name] diff -Nru circuits-3.1.0+ds1/circuits/core/values.py circuits-3.2.2/circuits/core/values.py --- circuits-3.1.0+ds1/circuits/core/values.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/circuits/core/values.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,17 +1,13 @@ -# Package: values -# Date: 11th April 2010 -# Author: James Mills, prologic at shortcircuit dot net dot au - """ This defines the Value object used by components and events. """ - - +from ..six import PY2, python_2_unicode_compatible, string_types, text_type from .events import Event -from ..six import string_types +@python_2_unicode_compatible class Value(object): + """Create a new future Value Object Creates a new future Value Object which is used by Event Objects and the @@ -25,8 +21,8 @@ :type manager: A Manager/Component instance. :ivar result: True if this value has been changed. - :ivar errors: True if while setting this value an exception occured. - :ivar notify: True or an event name to notify of changes to this value + :ivar errors: True if while setting this value an exception occurred. + :ivar notify: True or an event name to notify of changes to this value This is a Future/Promise implementation. """ @@ -63,7 +59,7 @@ def __iter__(self): return iter(map(lambda v: v.value if isinstance(v, Value) else v, - self.value)) + self.value)) def __repr__(self): "x.__repr__() <==> repr(x)" @@ -72,12 +68,13 @@ if self.result: value = repr(self.value) - format = " str(x)" - + if PY2: + return text_type(self.value).encode('utf-8') return str(self.value) def inform(self, force=False): diff -Nru circuits-3.1.0+ds1/circuits/core/workers.py circuits-3.2.2/circuits/core/workers.py --- circuits-3.1.0+ds1/circuits/core/workers.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/circuits/core/workers.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,36 +1,30 @@ -# Module: workers -# Date: 6th February 2011 -# Author: James Mills, prologic at shortcircuit dot net dot au - """Workers -Worker components used to perform "work" in independent threads or -processes. Worker(s) are typically used by a Pool (circuits.core.pools) -to create a pool of workers. Worker(s) are not registered with a Manager -or another Component - instead they are managed by the Pool. If a Worker -is used independently it should not be registered as it causes its -main event handler ``_on_task`` to execute in the other thread blocking it. -""" +Worker is a component used to perform "work" in independent threads or +processes. Simply create an instance of Worker() with either `process=True` +to create a pool of workers using sub-processes for CPU-bound work or `False` +(the default) for a thread pool of workers for I/O bound work. +Then fire `task()` events with a function and *args and **kwargs to pass +to the function when called from within the workers. +""" +from multiprocessing import Pool as ProcessPool, cpu_count +from multiprocessing.pool import ThreadPool from threading import current_thread from weakref import WeakKeyDictionary -from multiprocessing import cpu_count -from multiprocessing.pool import ThreadPool -from multiprocessing import Pool as ProcessPool +from .components import BaseComponent from .events import Event from .handlers import handler -from .components import BaseComponent - DEFAULT_WORKERS = 10 class task(Event): + """task Event This Event is used to initiate a new task to be performed by a Worker - or a Pool of Worker(s). :param f: The function to be executed. :type f: function @@ -52,11 +46,16 @@ class Worker(BaseComponent): + """A thread/process Worker Component - This Component creates a Worker (either a thread or process) which - when given a ``Task``, will execute the given function in the task - in the background in its thread/process. + This Component creates a pool of workers (either a thread or process) + and executures the supplied function from a `task()` event passing + supplied arguments and keyword-arguments to the function. + + A `task_success` event is fired upon successful execution of the function + and `task_failure` if it failed and threw an exception. The `task()` event + can also be "waited" upon by using the `.call()` and `.wait()` primitives. :param process: True to start this Worker as a process (Thread otherwise) :type process: bool diff -Nru circuits-3.1.0+ds1/circuits/__init__.py circuits-3.2.2/circuits/__init__.py --- circuits-3.1.0+ds1/circuits/__init__.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/circuits/__init__.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,27 +1,42 @@ -# Package: circuits -# Date: 3rd October 2008 -# Author: James Mills, prologic at shortcircuit dot net dot au - """Lightweight Event driven and Asynchronous Application Framework circuits is a **Lightweight** **Event** driven and **Asynchronous** **Application Framework** for the `Python Programming Language`_ with a strong **Component** Architecture. -:copyright: CopyRight (C) 2004-2013 by James Mills +:copyright: CopyRight (C) 2004-2016 by James Mills :license: MIT (See: LICENSE) .. _Python Programming Language: http://www.python.org/ """ - __author__ = "James Mills" __date__ = "24th February 2013" -from .version import version as __version__ - -from .core import Event -from .core import task, Worker -from .core import handler, reprhandler, BaseComponent, Component -from .core import Debugger, Bridge, Loader, Manager, Timer, TimeoutError +try: + from .version import version as __version__ +except ImportError: + __version__ = "unknown" + +from .core import ( + BaseComponent, Bridge, Component, Debugger, Event, Loader, Manager, + TimeoutError, Timer, Worker, handler, ipc, reprhandler, sleep, task, +) + +# See http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages +try: + __import__('pkg_resources').declare_namespace(__name__) +except ImportError: + from pkgutil import extend_path + __path__ = extend_path(__path__, __name__) + import os + from .six import exec_ + fd = None + for _path in __path__: + _path = os.path.join(_path, '__init__.py') + if _path != __file__ and os.path.exists(_path): + with open(_path) as fd: + exec_(fd, globals()) + del os, extend_path, _path, fd, exec_ # flake8: noqa +# pylama:skip=1 diff -Nru circuits-3.1.0+ds1/circuits/io/events.py circuits-3.2.2/circuits/io/events.py --- circuits-3.1.0+ds1/circuits/io/events.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/circuits/io/events.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,82 +1,95 @@ -# Module: events -# Date: 10th June 2011 -# Author: James Mills - """I/O Events This module implements commonly used I/O events used by other I/O modules. """ - from circuits.core import Event class eof(Event): + """eof Event""" class seek(Event): + """seek Event""" class read(Event): + """read Event""" class close(Event): + """close Event""" class write(Event): + """write Event""" class error(Event): + """error Event""" class open(Event): + """open Event""" class opened(Event): + """opened Event""" class closed(Event): + """closed Event""" class ready(Event): + """ready Event""" class started(Event): + """started Event""" class stopped(Event): + """stopped Event""" class moved(Event): + """moved Event""" class created(Event): + """created Event""" class deleted(Event): + """deleted Event""" class accessed(Event): + """accessed Event""" class modified(Event): + """modified Event""" class unmounted(Event): + """unmounted Event""" diff -Nru circuits-3.1.0+ds1/circuits/io/file.py circuits-3.2.2/circuits/io/file.py --- circuits-3.1.0+ds1/circuits/io/file.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/circuits/io/file.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,12 +1,7 @@ -# Module: file -# Date: 4th August 2004 -# Author: James Mills - """File I/O This module implements a wrapper for basic File I/O. """ - try: from os import O_NONBLOCK except ImportError: @@ -15,16 +10,15 @@ pass from collections import deque -from os import read as fd_read -from os import write as fd_write -from sys import getdefaultencoding from errno import EINTR, EWOULDBLOCK +from os import read as fd_read, write as fd_write +from sys import getdefaultencoding -from circuits.tools import tryimport -from circuits.core.utils import findcmp -from circuits.core import handler, Component, Event +from circuits.core import Component, Event, handler from circuits.core.pollers import BasePoller, Poller -from circuits.six import binary_type, string_types, PY3 +from circuits.core.utils import findcmp +from circuits.six import PY3, binary_type, string_types +from circuits.tools import tryimport from .events import close, closed, eof, error, opened, read, ready @@ -35,6 +29,7 @@ class _open(Event): + """_open Event""" @@ -135,7 +130,7 @@ try: self._fd.close() - except: + except EnvironmentError: pass self.fire(closed()) @@ -160,11 +155,11 @@ self.close() else: self._poller.discard(self._fd) - except (OSError, IOError) as e: - if e.args[0] in (EWOULDBLOCK, EINTR): + except (OSError, IOError) as exc: + if exc.args[0] in (EWOULDBLOCK, EINTR): return else: - self.fire(error(e)) + self.fire(error(exc)) self._close() def seek(self, offset, whence=0): diff -Nru circuits-3.1.0+ds1/circuits/io/__init__.py circuits-3.2.2/circuits/io/__init__.py --- circuits-3.1.0+ds1/circuits/io/__init__.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/circuits/io/__init__.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,19 +1,14 @@ -# Module: io -# Date: 4th August 2004 -# Author: James Mills - """I/O Support This package contains various I/O Components. Provided are a generic File Component, StdIn, StdOut and StdErr components. Instances of StdIn, StdOut and StdErr are also created by importing this package. """ - import sys +from .events import close, open, seek, write from .file import File from .process import Process -from .events import close, open, seek, write try: from .notify import Notify @@ -33,3 +28,4 @@ pass # flake8: noqa +# pylama: skip=1 diff -Nru circuits-3.1.0+ds1/circuits/io/notify.py circuits-3.2.2/circuits/io/notify.py --- circuits-3.1.0+ds1/circuits/io/notify.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/circuits/io/notify.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,12 +1,7 @@ -# Module: notify -# Date: 2nd March 2009 -# Author: James Mills, prologic at shortcircuit dot net dot au - """File Notification Support A Component wrapping the inotify API using the pyinotify library. """ - try: from pyinotify import IN_UNMOUNT from pyinotify import WatchManager, Notifier, ALL_EVENTS @@ -14,30 +9,33 @@ from pyinotify import IN_CREATE, IN_DELETE, IN_DELETE_SELF, IN_MOVE_SELF from pyinotify import IN_CLOSE_NOWRITE, IN_OPEN, IN_MOVED_FROM, IN_MOVED_TO except ImportError: - raise Exception("No pyinotify support available. Is pyinotify installed?") + raise ImportError("No pyinotify support available. Is pyinotify installed?") -from circuits.core.utils import findcmp -from circuits.core import handler, BaseComponent +from circuits.core import BaseComponent, handler from circuits.core.pollers import BasePoller, Poller +from circuits.core.utils import findcmp -from .events import accessed, closed, created, deleted, modified, moved, opened, ready, unmounted +from .events import ( + accessed, closed, created, deleted, modified, moved, opened, ready, + unmounted, +) MASK = ALL_EVENTS EVENT_MAP = { - IN_MOVED_TO: moved, - IN_MOVE_SELF: moved, - IN_MOVED_FROM: moved, - IN_CLOSE_WRITE: closed, - IN_CLOSE_NOWRITE: closed, - IN_OPEN: opened, - IN_DELETE_SELF: deleted, - IN_DELETE: deleted, - IN_CREATE: created, - IN_ACCESS: accessed, - IN_MODIFY: modified, - IN_ATTRIB: modified, - IN_UNMOUNT: unmounted, + IN_MOVED_TO: moved, + IN_MOVE_SELF: moved, + IN_MOVED_FROM: moved, + IN_CLOSE_WRITE: closed, + IN_CLOSE_NOWRITE: closed, + IN_OPEN: opened, + IN_DELETE_SELF: deleted, + IN_DELETE: deleted, + IN_CREATE: created, + IN_ACCESS: accessed, + IN_MODIFY: modified, + IN_ATTRIB: modified, + IN_UNMOUNT: unmounted, } @@ -63,9 +61,9 @@ if mask & k: self.fire(v(name, path, pathname, dir)) - def add_path(self, path, mask=None, recursive=False): + def add_path(self, path, mask=None, recursive=False, auto_add=True): mask = mask or MASK - self._wm.add_watch(path, mask, rec=recursive) + self._wm.add_watch(path, mask, rec=recursive, auto_add=auto_add) def remove_path(self, path, recursive=False): wd = self._wm.get_wd(path) diff -Nru circuits-3.1.0+ds1/circuits/io/process.py circuits-3.2.2/circuits/io/process.py --- circuits-3.1.0+ds1/circuits/io/process.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/circuits/io/process.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,20 +1,28 @@ -# Module: process -# Date: 4th January 2013 -# Author: James Mills - """Process This module implements a wrapper for basic ``subprocess.Popen`` functionality. """ - from io import BytesIO -from subprocess import Popen, PIPE +from subprocess import PIPE, Popen +from circuits import BaseComponent, Event, handler from circuits.core.manager import TIMEOUT -from circuits import handler, BaseComponent +from .events import close, started, write from .file import File -from .events import started, stopped, write + + +class terminated(Event): + """terminated Event + + This Event is sent when a process is completed + + :param args: (process) + :type tuple: tuple + """ + + def __init__(self, *args): + super(terminated, self).__init__(*args) class Process(BaseComponent): @@ -77,39 +85,31 @@ ).register(self) self._stderr_read_handler = self.addHandler( - handler("read", channel="{0:d}.stderr".format(self.p.pid))( - self.__class__._on_stderr_read + handler("read", channel=self._stderr.channel)( + lambda self, data: self.stderr.write(data) ) ) self._stdout_read_handler = self.addHandler( - handler("read", channel="{0:d}.stdout".format(self.p.pid))( - self.__class__._on_stdout_read + handler("read", channel=self._stdout.channel)( + lambda self, data: self.stdout.write(data) ) ) self._stderr_closed_handler = self.addHandler( - handler("closed", channel="{0:d}.stderr".format(self.p.pid))( - self.__class__._on_stderr_closed + handler("closed", channel=self._stderr.channel)( + lambda self: setattr(self, '_stderr_closed', True) ) ) self._stdout_closed_handler = self.addHandler( - handler("closed", channel="{0:d}.stdout".format(self.p.pid))( - self.__class__._on_stdout_closed + handler("closed", channel=self._stdout.channel)( + lambda self: setattr(self, '_stdout_closed', True) ) ) self.fire(started(self)) - @staticmethod - def _on_stdout_closed(self): - self._stdout_closed = True - - @staticmethod - def _on_stderr_closed(self): - self._stderr_closed = True - def stop(self): if self.p is not None: self.p.terminate() @@ -131,14 +131,6 @@ if getattr(self, "p", None) is not None: return self.p.poll() - @staticmethod - def _on_stderr_read(self, data): - self.stderr.write(data) - - @staticmethod - def _on_stdout_read(self, data): - self.stdout.write(data) - @handler("generate_events") def _on_generate_events(self, event): if self.p is not None and self._status is None: @@ -151,7 +143,10 @@ self.removeHandler(self._stdout_read_handler) self.removeHandler(self._stderr_closed_handler) self.removeHandler(self._stdout_closed_handler) - self.fire(stopped(self)) + + self.fire(terminated(self)) + self.fire(close(), self._stdin.channel, self._stdout.channel, self._stderr.channel) + event.reduce_time_left(0) event.stop() else: diff -Nru circuits-3.1.0+ds1/circuits/io/serial.py circuits-3.2.2/circuits/io/serial.py --- circuits-3.1.0+ds1/circuits/io/serial.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/circuits/io/serial.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,23 +1,16 @@ -# Module: serial -# Date: 4th August 2004 -# Author: James Mills - """Serial I/O This module implements basic Serial (RS232) I/O. """ - -import os -import select from collections import deque -from circuits.core import Component, handler, Event +from circuits.core import Component, Event, handler from circuits.core.pollers import BasePoller, Poller from circuits.core.utils import findcmp +from circuits.six import binary_type from circuits.tools import tryimport -from circuits.six import binary_type, string_types -from .events import closed, error, opened, read, ready, close +from .events import close, closed, error, opened, read, ready serial = tryimport("serial") @@ -26,6 +19,7 @@ class _open(Event): + """_open Event""" @@ -34,7 +28,7 @@ channel = "serial" def __init__(self, port, baudrate=115200, bufsize=BUFSIZE, - timeout=TIMEOUT, channel=channel): + timeout=TIMEOUT, encoding='UTF-8', readline=False, channel=channel): super(Serial, self).__init__(channel=channel) if serial is None: @@ -43,6 +37,8 @@ self._port = port self._baudrate = baudrate self._bufsize = bufsize + self._encoding = encoding + self._readline = readline self._serial = None self._poller = None @@ -59,7 +55,8 @@ self._baudrate = baudrate or self._baudrate self._bufsize = bufsize or self._bufsize - self._serial = serial.Serial(port=self._port, baudrate=self._baudrate, timeout=0) + self._serial = serial.Serial( + port=self._port, baudrate=self._baudrate, timeout=0) self._fd = self._serial.fileno() # not portable! self._poller.addReader(self, self._fd) @@ -104,7 +101,7 @@ try: self._serial.close() - except: + except EnvironmentError: pass self.fire(closed()) @@ -117,14 +114,17 @@ def _read(self): try: - data = self._serial.read(self._bufsize) + if self._readline: + data = self._serial.readline(self._bufsize) + else: + data = self._serial.read(self._bufsize) if not isinstance(data, binary_type): data = data.encode(self._encoding) if data: self.fire(read(data)).notify = True - except (OSError, IOError) as e: - self.fire(error(e)) + except (OSError, IOError) as exc: + self.fire(error(exc)) self._close() def _write(self, data): @@ -134,7 +134,7 @@ try: nbytes = self._serial.write(data) - except (serial.SerialTimeoutException) as e: + except serial.SerialTimeoutException: nbytes = 0 if nbytes < len(data): self._buffer.appendleft(data[nbytes:]) diff -Nru circuits-3.1.0+ds1/circuits/net/events.py circuits-3.2.2/circuits/net/events.py --- circuits-3.1.0+ds1/circuits/net/events.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/circuits/net/events.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,16 +1,12 @@ -# Module: events -# Date: 21st September 2013 -# Author: James Mills - """Networking Events This module implements commonly used Networking events used by socket components. """ - from circuits.core import Event class connect(Event): + """connect Event This Event is sent when a new client connection has arrived on a server. @@ -34,6 +30,7 @@ class disconnect(Event): + """disconnect Event This Event is sent when a client connection has closed on a server. @@ -46,13 +43,14 @@ :type tuple: tuple """ - def __init__(self, *args): + def __init__(self, *args, **kwargs): "x.__init__(...) initializes x; see x.__class__.__doc__ for signature" - super(disconnect, self).__init__(*args) + super(disconnect, self).__init__(*args, **kwargs) class connected(Event): + """connected Event This Event is sent when a client has successfully connected. @@ -74,6 +72,7 @@ class disconnected(Event): + """disconnected Event This Event is sent when a client has disconnected @@ -89,6 +88,7 @@ class read(Event): + """read Event This Event is sent when a client or server connection has read any data. @@ -107,6 +107,7 @@ class error(Event): + """error Event This Event is sent when a client or server connection has an error. @@ -124,7 +125,27 @@ super(error, self).__init__(*args) +class unreachable(Event): + + """unreachable Event + + This Event is sent when a server is unreachable for a client + + :param host: Server hostname or IP + :type str: str + + :param port: Server port + :type int: int + """ + + def __init__(self, host, port, reason=None): + "x.__init__(...) initializes x; see x.__class__.__doc__ for signature" + + super(unreachable, self).__init__(host, port, reason) + + class broadcast(Event): + """broadcast Event This Event is used by the UDPServer/UDPClient sockets to send a message on the ```` @@ -145,6 +166,7 @@ class write(Event): + """write Event This Event is used to notify a client, client connection or server that @@ -165,6 +187,7 @@ class close(Event): + """close Event This Event is used to notify a client, client connection or server that @@ -185,6 +208,7 @@ class ready(Event): + """ready Event This Event is used to notify the rest of the system that the underlying @@ -211,6 +235,7 @@ class closed(Event): + """closed Event This Event is sent when a server has closed its listening socket. @@ -218,3 +243,21 @@ .. note:: This event is for Server components. """ + + +class starttls(Event): + + """starttls Event + + This event can be fired to upgrade the socket connection to a TLS + secured connection. + + .. note:: + This event is currently only available for Server Components. + + :param sock: The client socket where to start TLS. + :type sock: socket.socket + """ + + def __init__(self, sock): + super(starttls, self).__init__(sock) diff -Nru circuits-3.1.0+ds1/circuits/net/__init__.py circuits-3.2.2/circuits/net/__init__.py --- circuits-3.1.0+ds1/circuits/net/__init__.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/circuits/net/__init__.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,12 +1,5 @@ -# Package: net -# Date: 7th April 2010 -# Author: James Mills, prologic at shortcircuit dot net dot au - """Networking Components This package contains components that implement network sockets and protocols for implementing client and server network applications. - -:copyright: CopyRight (C) 2004-2013 by James Mills -:license: MIT (See: LICENSE) """ diff -Nru circuits-3.1.0+ds1/circuits/net/sockets.py circuits-3.2.2/circuits/net/sockets.py --- circuits-3.1.0+ds1/circuits/net/sockets.py 2014-09-20 22:36:35.000000000 +0000 +++ circuits-3.2.2/circuits/net/sockets.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,28 +1,38 @@ -# Module: sockets -# Date: 04th August 2004 -# Author: James Mills - """Socket Components This module contains various Socket Components for use with Networking. """ - import os import select from collections import defaultdict, deque - -from errno import EAGAIN, EALREADY, EBADF -from errno import ECONNABORTED, EINPROGRESS, EINTR, EISCONN, EMFILE, ENFILE -from errno import ENOBUFS, ENOMEM, ENOTCONN, EPERM, EPIPE, EINVAL, EWOULDBLOCK +from errno import ( + EAGAIN, EALREADY, EBADF, ECONNABORTED, EINPROGRESS, EINTR, EINVAL, EISCONN, + EMFILE, ENFILE, ENOBUFS, ENOMEM, ENOTCONN, EPERM, EPIPE, EWOULDBLOCK, +) +from socket import ( + AF_INET, AF_INET6, IPPROTO_IP, IPPROTO_TCP, SO_BROADCAST, SO_REUSEADDR, + SOCK_DGRAM, SOCK_STREAM, SOL_SOCKET, TCP_NODELAY, error as SocketError, + gaierror, getaddrinfo, getfqdn, gethostbyname, gethostname, socket, +) +from time import time from _socket import socket as SocketType -from socket import gaierror -from socket import error as SocketError -from socket import getfqdn, gethostbyname, socket, getaddrinfo, gethostname +from circuits.core import BaseComponent, handler +from circuits.core.pollers import BasePoller, Poller +from circuits.core.utils import findcmp +from circuits.six import binary_type + +from .events import ( + close, closed, connect, connected, disconnect, disconnected, error, read, + ready, unreachable, write, +) + +try: + from socket import AF_UNIX +except ImportError: + AF_UNIX = None -from socket import AF_INET, AF_INET6, IPPROTO_TCP, SOCK_STREAM, SOCK_DGRAM -from socket import SOL_SOCKET, SO_BROADCAST, SO_REUSEADDR, TCP_NODELAY try: from ssl import wrap_socket as ssl_socket @@ -34,26 +44,55 @@ import warnings warnings.warn("No SSL support available.") HAS_SSL = 0 + CERT_NONE = None + PROTOCOL_SSLv23 = None -from circuits.six import binary_type -from circuits.core.utils import findcmp -from circuits.core import handler, BaseComponent -from circuits.core.pollers import BasePoller, Poller +BUFSIZE = 4096 # 4KB Buffer +BACKLOG = 5000 # 5K Concurrent Connections -from .events import close, closed, connect, connected, disconnect, disconnected, error, read, ready, write +def do_handshake(sock, on_done=None, on_error=None, extra_args=None): + """SSL Async Handshake -BUFSIZE = 4096 # 4KB Buffer -BACKLOG = 5000 # 5K Concurrent Connections + :param on_done: Function called when handshake is complete + :type on_done: :function: + + :param on_error: Function called when handshake errored + :type on_error: :function: + """ + + extra_args = extra_args or () + + while True: + try: + sock.do_handshake() + break + except SSLError as err: + if err.args[0] == SSL_ERROR_WANT_READ: + select.select([sock], [], []) + elif err.args[0] == SSL_ERROR_WANT_WRITE: + select.select([], [sock], []) + else: + callable(on_error) and on_error(sock, err) + return + + yield + + callable(on_done) and on_done(sock, *extra_args) class Client(BaseComponent): channel = "client" - def __init__(self, bind=None, bufsize=BUFSIZE, channel=channel): - super(Client, self).__init__(channel=channel) + socket_family = AF_INET + socket_type = SOCK_STREAM + socket_protocol = IPPROTO_IP + socket_options = [] + + def __init__(self, bind=None, bufsize=BUFSIZE, channel=channel, **kwargs): + super(Client, self).__init__(channel=channel, **kwargs) if isinstance(bind, SocketType): self._bind = bind.getsockname() @@ -127,6 +166,9 @@ try: self._sock.shutdown(2) + except SocketError: + pass + try: self._sock.close() except SocketError: pass @@ -142,10 +184,15 @@ def _read(self): try: - if self.secure and self._ssock: - data = self._ssock.read(self._bufsize) - else: - data = self._sock.recv(self._bufsize) + try: + if self.secure and self._ssock: + data = self._ssock.read(self._bufsize) + else: + data = self._sock.recv(self._bufsize) + except SSLError as exc: + if exc.errno in (SSL_ERROR_WANT_READ, SSL_ERROR_WANT_WRITE): + return + raise if data: self.fire(read(data)).notify = True @@ -199,41 +246,34 @@ elif self._poller.isWriting(self._sock): self._poller.removeWriter(self._sock) + def _create_socket(self): + sock = socket(self.socket_family, self.socket_type, self.socket_protocol) -def _do_handshake_for_non_blocking(ssock): - """ - This is how to do handshake for an ssl socket with underlying - non-blocking socket (according to the Python doc). - """ - while True: - try: - ssock.do_handshake() - break - except SSLError as err: - if err.args[0] == SSL_ERROR_WANT_READ: - select.select([ssock], [], []) - elif err.args[0] == SSL_ERROR_WANT_WRITE: - select.select([], [ssock], []) - else: - raise + for option in self.socket_options: + sock.setsockopt(*option) + sock.setblocking(False) + if self._bind is not None: + sock.bind(self._bind) + return sock class TCPClient(Client): socket_family = AF_INET + socket_type = SOCK_STREAM + socket_protocol = IPPROTO_TCP + socket_options = [ + (IPPROTO_TCP, TCP_NODELAY, 1), + ] - def _create_socket(self): - sock = socket(self.socket_family, SOCK_STREAM, IPPROTO_TCP) - if self._bind is not None: - sock.bind(self._bind) - - sock.setblocking(False) - sock.setsockopt(IPPROTO_TCP, TCP_NODELAY, 1) + def init(self, connect_timeout=5, *args, **kwargs): + self.connect_timeout = connect_timeout - return sock - - @handler("connect") + @handler("connect") # noqa def connect(self, host, port, secure=False, **kwargs): + # XXX: C901: This has a high McCacbe complexity score of 10. + # TODO: Refactor this! + self.host = host self.port = port self.secure = secure @@ -241,6 +281,7 @@ if self.secure: self.certfile = kwargs.get("certfile", None) self.keyfile = kwargs.get("keyfile", None) + self.ca_certs = kwargs.get("ca_certs", None) try: r = self._sock.connect((host, port)) @@ -251,25 +292,42 @@ else: r = e.args[0] - if r in (EISCONN, EWOULDBLOCK, EINPROGRESS, EALREADY): - self._connected = True - else: + if r not in (EISCONN, EWOULDBLOCK, EINPROGRESS, EALREADY): + self.fire(unreachable(host, port, e)) self.fire(error(e)) self._close() return - self._connected = True + stop_time = time() + self.connect_timeout + while time() < stop_time: + try: + self._sock.getpeername() + self._connected = True + break + except Exception: + yield - self._poller.addReader(self, self._sock) + if not self._connected: + self.fire(unreachable(host, port)) + return + + def on_done(sock): + self._poller.addReader(self, sock) + self.fire(connected(host, port)) if self.secure: - self._ssock = ssl_socket( - self._sock, self.keyfile, self.certfile, + def on_error(sock, err): + self.fire(error(sock, err)) + self._close() + + self._sock = ssl_socket( + self._sock, self.keyfile, self.certfile, ca_certs=self.ca_certs, do_handshake_on_connect=False ) - _do_handshake_for_non_blocking(self._ssock) - - self.fire(connected(host, port)) + for _ in do_handshake(self._sock, on_done, on_error): + yield + else: + on_done(self._sock) class TCP6Client(TCPClient): @@ -282,30 +340,27 @@ class UNIXClient(Client): - def _create_socket(self): - from socket import AF_UNIX - - sock = socket(AF_UNIX, SOCK_STREAM) - if self._bind is not None: - sock.bind(self._bind) - - sock.setblocking(False) - - return sock + socket_family = AF_UNIX + socket_type = SOCK_STREAM + socket_options = [] @handler("ready") def ready(self, component): if self._poller is not None and self._connected: self._poller.addReader(self, self._sock) - @handler("connect") + @handler("connect") # noqa def connect(self, path, secure=False, **kwargs): + # XXX: C901: This has a high McCacbe complexity score of 10. + # TODO: Refactor this! + self.path = path self.secure = secure if self.secure: self.certfile = kwargs.get("certfile", None) self.keyfile = kwargs.get("keyfile", None) + self.ca_certs = kwargs.get("ca_certs", None) try: r = self._sock.connect_ex(path) @@ -324,23 +379,32 @@ self._poller.addReader(self, self._sock) if self.secure: + def on_done(sock): + self.fire(connected(gethostname(), path)) + + def on_error(sock, err): + self.fire(error(err)) + self._ssock = ssl_socket( - self._sock, self.keyfile, self.certfile, + self._sock, self.keyfile, self.certfile, ca_certs=self.ca_certs, do_handshake_on_connect=False ) - _do_handshake_for_non_blocking(self._ssock) - - self.fire(connected(gethostname(), path)) + for _ in do_handshake(self._ssock, on_done, on_error): + yield + else: + self.fire(connected(gethostname(), path)) class Server(BaseComponent): channel = "server" + socket_protocol = IPPROTO_IP def __init__(self, bind, secure=False, backlog=BACKLOG, bufsize=BUFSIZE, channel=channel, **kwargs): super(Server, self).__init__(channel=channel) + self.socket_options = self.socket_options[:] + kwargs.get('socket_options', []) self._bind = self.parse_bind_parameter(bind) self._backlog = backlog @@ -356,14 +420,16 @@ self._poller = None self._buffers = defaultdict(deque) - self.secure = secure + self.__starttls = set() - if self.secure: - self.certfile = kwargs.get("certfile", None) - self.keyfile = kwargs.get("keyfile", None) - self.cert_reqs = kwargs.get("cert_reqs", CERT_NONE) - self.ssl_version = kwargs.get("ssl_version", PROTOCOL_SSLv23) - self.ca_certs = kwargs.get("ca_certs", None) + self.secure = secure + self.certfile = kwargs.get("certfile") + self.keyfile = kwargs.get("keyfile", None) + self.cert_reqs = kwargs.get("cert_reqs", CERT_NONE) + self.ssl_version = kwargs.get("ssl_version", PROTOCOL_SSLv23) + self.ca_certs = kwargs.get("ca_certs", None) + if self.secure and not self.certfile: + raise RuntimeError("certfile must be specified for server-side operations") def parse_bind_parameter(self, bind_parameter): return parse_ipv4_parameter(bind_parameter) @@ -410,9 +476,13 @@ self._poller.addReader(self, self._sock) self.fire(ready(self, (self.host, self.port))) else: - self._poller = Poller().register(self) - self._poller.addReader(self, self._sock) - self.fire(ready(self, (self.host, self.port))) + try: + self._poller = Poller().register(self) + except EnvironmentError as err: + self.fire(error(err)) + else: + self._poller.addReader(self, self._sock) + self.fire(ready(self, (self.host, self.port))) @handler("stopped", channel="*") def _on_stopped(self, component): @@ -427,6 +497,7 @@ def _close(self, sock): if sock is None: return + if sock != self._sock and sock not in self._clients: return @@ -440,8 +511,14 @@ else: self._sock = None + if sock in self.__starttls: + self.__starttls.remove(sock) + try: sock.shutdown(2) + except SocketError: + pass + try: sock.close() except SocketError: pass @@ -508,27 +585,6 @@ def _accept(self): try: newsock, host = self._sock.accept() - if self.secure and HAS_SSL: - sslsock = ssl_socket( - newsock, - server_side=True, - keyfile=self.keyfile, - ca_certs=self.ca_certs, - certfile=self.certfile, - cert_reqs=self.cert_reqs, - ssl_version=self.ssl_version, - do_handshake_on_connect=False - ) - try: - _do_handshake_for_non_blocking(sslsock) - newsock = sslsock - except SSLError as e: - self.fire(error(self._sock, e)) - newsock.shutdown(2) - newsock.close() - return - else: - newsock = sslsock except SocketError as e: if e.args[0] in (EWOULDBLOCK, EAGAIN): return @@ -555,10 +611,53 @@ else: raise - newsock.setblocking(False) - self._poller.addReader(self, newsock) - self._clients.append(newsock) - self.fire(connect(newsock, *host)) + if self.secure and HAS_SSL: + for _ in self._do_handshake(newsock): + yield + else: + self._on_accept_done(newsock) + + def _do_handshake(self, sock, fire_connect_event=True): + sslsock = ssl_socket( + sock, + server_side=True, + keyfile=self.keyfile, + ca_certs=self.ca_certs, + certfile=self.certfile, + cert_reqs=self.cert_reqs, + ssl_version=self.ssl_version, + do_handshake_on_connect=False + ) + + for _ in do_handshake(sslsock, self._on_accept_done, self._on_handshake_error, (fire_connect_event,)): + yield _ + + def _on_accept_done(self, sock, fire_connect_event=True): + sock.setblocking(False) + self._poller.addReader(self, sock) + self._clients.append(sock) + if fire_connect_event: + try: + self.fire(connect(sock, *sock.getpeername())) + except SocketError as exc: + # errno 107 (ENOTCONN): the client already disconnected + self._on_handshake_error(sock, exc) + + def _on_handshake_error(self, sock, err): + self.fire(error(sock, err)) + self._close(sock) + + @handler('starttls') + def starttls(self, sock): + if not HAS_SSL: + raise RuntimeError('Cannot start TLS. No TLS support.') + if sock in self.__starttls: + raise RuntimeError('Cannot reuse socket for already started STARTTLS.') + self.__starttls.add(sock) + self._poller.removeReader(sock) + self._clients.remove(sock) + for _ in self._do_handshake(sock, False): + yield @handler("_disconnect", priority=1) def _on_disconnect(self, sock): @@ -567,7 +666,7 @@ @handler("_read", priority=1) def _on_read(self, sock): if sock == self._sock: - self._accept() + return self._accept() else: self._read(sock) @@ -584,18 +683,28 @@ elif self._poller.isWriting(sock): self._poller.removeWriter(sock) + def _create_socket(self): + sock = socket(self.socket_family, self.socket_type, self.socket_protocol) + + for option in self.socket_options: + sock.setsockopt(*option) + sock.setblocking(False) + if self._bind is not None: + sock.bind(self._bind) + return sock + class TCPServer(Server): socket_family = AF_INET + socket_type = SOCK_STREAM + socket_options = [ + (SOL_SOCKET, SO_REUSEADDR, 1), + (IPPROTO_TCP, TCP_NODELAY, 1), + ] def _create_socket(self): - sock = socket(self.socket_family, SOCK_STREAM) - - sock.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1) - sock.setsockopt(IPPROTO_TCP, TCP_NODELAY, 1) - sock.setblocking(False) - sock.bind(self._bind) + sock = super(TCPServer, self)._create_socket() sock.listen(self._backlog) return sock @@ -643,17 +752,17 @@ class UNIXServer(Server): - def _create_socket(self): - from socket import AF_UNIX + socket_family = AF_UNIX + socket_type = SOCK_STREAM + socket_options = [ + (SOL_SOCKET, SO_REUSEADDR, 1), + ] + def _create_socket(self): if os.path.exists(self._bind): os.unlink(self._bind) - sock = socket(AF_UNIX, SOCK_STREAM) - sock.bind(self._bind) - - sock.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1) - sock.setblocking(False) + sock = super(UNIXServer, self)._create_socket() sock.listen(self._backlog) return sock @@ -662,18 +771,11 @@ class UDPServer(Server): socket_family = AF_INET - - def _create_socket(self): - sock = socket(self.socket_family, SOCK_DGRAM) - - sock.bind(self._bind) - - sock.setsockopt(SOL_SOCKET, SO_BROADCAST, 1) - sock.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1) - - sock.setblocking(False) - - return sock + socket_type = SOCK_DGRAM + socket_options = [ + (SOL_SOCKET, SO_BROADCAST, 1), + (SOL_SOCKET, SO_REUSEADDR, 1) + ] def _close(self, sock): self._poller.discard(sock) diff -Nru circuits-3.1.0+ds1/circuits/net/utils.py circuits-3.2.2/circuits/net/utils.py --- circuits-3.1.0+ds1/circuits/net/utils.py 1970-01-01 00:00:00.000000000 +0000 +++ circuits-3.2.2/circuits/net/utils.py 2021-10-19 16:23:49.000000000 +0000 @@ -0,0 +1,17 @@ +"""Utilities""" + +from circuits.six import iterbytes + + +def is_ssl_handshake(buf): + """Detect an SSLv2 or SSLv3 handshake""" + + # SSLv3, TLS 1.1 - 1.3 + v = buf[:3] + if v in ("\x16\x03\x00", "\x16\x03\x01", "\x16\x03\x02", "\x16\x03\x03", "\x16\x03\x04"): + return True + + # SSLv2 + v = list(iterbytes(buf[:2])) + [0x00, 0x00] + if (v[0] & 0x80 == 0x80) and ((v[0] & 0x7f) << 8 | v[1]) > 9: + return True diff -Nru circuits-3.1.0+ds1/circuits/node/client.py circuits-3.2.2/circuits/node/client.py --- circuits-3.1.0+ds1/circuits/node/client.py 2014-09-24 09:54:43.000000000 +0000 +++ circuits-3.2.2/circuits/node/client.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,81 +1,80 @@ -# Module: client -# Date: ... -# Author: ... - -"""Client - -... -""" - -from weakref import WeakValueDictionary - +from circuits import BaseComponent, handler +from circuits.net.events import close, connect from circuits.net.sockets import TCPClient -from circuits import handler, BaseComponent -from circuits.net.events import close, connect, write -from .utils import dump_event, load_value - -DELIMITER = b"\r\n\r\n" +from .protocol import Protocol class Client(BaseComponent): - """Client - - ... - """ - channel = "node" + """Node Client (peer)""" + channel = "node_client" - def __init__(self, host, port, channel=channel, **kwargs): + def __init__(self, host, port, channel=channel, + receive_event_firewall=None, send_event_firewall=None, + **kwargs): + """Create new connection for a node. + + :param hostname: hostname to connect. + :type hostname: str + + :param port: port to connect. + :type port: int + + :param channel: An optional keyword argument which if defined, + set channel used for node event. + **Default:** ``node_client`` + :type channel: str + + :param receive_event_firewall: An optional keyword argument which if + defined, function or method to call for + check if event is allowed for sending. + **Default:** ``None`` (no firewall) + :type receive_event_firewall: function + :type receive_event_firewall: method + + :param send_event_firewall: An optional keyword argument which if + defined, function or method to call for + check if event is allowed for executing + **Default:** ``None`` (no firewall) + :type send_event_firewall: function + :type send_event_firewall: method + """ super(Client, self).__init__(channel=channel, **kwargs) - self._host = host - self._port = port + self.__host = host + self.__port = port + self.__protocol = Protocol( + receive_event_firewall=receive_event_firewall, + send_event_firewall=send_event_firewall, + channel=channel + ).register(self) - self._nid = 0 - self._buffer = b"" - self._values = {} - - TCPClient(channel=self.channel, **kwargs).register(self) + TCPClient(channel=channel, **kwargs).register(self) @handler("ready") def _on_ready(self, component): - self.fire(connect(self._host, self._port)) - - def _process_packet(self, packet): - value, id, errors = load_value(packet) - - if id in self._values: - self._values[id].value = value - self._values[id].errors = errors + self.connect() def close(self): + """Close the connection""" self.fire(close()) - def connect(self, host, port): - self.fire(connect(host, port)) - - def send(self, event, e): - id = self._nid - self._nid += 1 - - self._values[id] = event.value - data = dump_event(e, id) - packet = data.encode("utf-8") + DELIMITER - - self.fire(write(packet)) - - while not self._values[id].result: - yield - - del(self._values[id]) + def connect(self): + """Create the connection""" + self.fire(connect(self.__host, self.__port)) + + def send(self, event): + """Send event through the connection + + :param event: Event to send. + :type event: :class:`circuits.core.events.Event` + + :return: The result object of the sended event + :rtype: generator + """ + return self.__protocol.send(event) @handler("read") def _on_read(self, data): - self._buffer += data - - delimiter = self._buffer.find(DELIMITER) - if delimiter > 0: - packet = self._buffer[:delimiter].decode("utf-8") - self._buffer = self._buffer[(delimiter + len(DELIMITER)):] - self._process_packet(packet) + self.__protocol.add_buffer(data) diff -Nru circuits-3.1.0+ds1/circuits/node/events.py circuits-3.2.2/circuits/node/events.py --- circuits-3.1.0+ds1/circuits/node/events.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/circuits/node/events.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,24 +1,51 @@ -# Module: events -# Date: ... -# Author: ... +from circuits import Event -"""Events -... -""" +class connected_to(Event): + + """Connected to a peer""" + + def __init__(self, connection_name, hostname, port, client_channel, + client_obj): + """ + :param connection_name: Connection name. + :type connection_name: str + + :param hostname: hostname of the remote system. + :type hostname: str + + :param port: connection port of the remote system. + :type port: int + + :param client_channel: Channel used for client event. + :type client_channel: str + + :param client_obj: Client object. + :type client_obj: :class:`circuits.net.sockets.Client` + """ + super(connected_to, self).__init__( + connection_name, hostname, port, client_channel, client_obj + ) -from circuits import Event +class disconnected_from(connected_to): -class packet(Event): - """packet Event""" + """Disconnected from a peer""" class remote(Event): - """remote Event - ... - """ + """send event to a peer""" - def __init__(self, event, node, channel=None): - super(remote, self).__init__(event, node, channel=None) + def __init__(self, event, connection_name, channel=None): + """ + :param event: Event to execute remotely. + :type event: :class:`circuits.core.events.Event` + + :param connection_name: Connection name. + :type connection_name: str + + :param channel: Remote channel (channel to use on peer). + :type channel: str + """ + super(remote, self).__init__(event, connection_name, channel=channel) diff -Nru circuits-3.1.0+ds1/circuits/node/__init__.py circuits-3.2.2/circuits/node/__init__.py --- circuits-3.1.0+ds1/circuits/node/__init__.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/circuits/node/__init__.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,13 +1,9 @@ -# Module: node -# Date: ... -# Author: ... - """Node -Distributed and Inter-Processing support for circuits +Distributed processing support for circuits. """ - -from .node import Node from .events import remote +from .node import Node # flake8: noqa +# pylama: skip=1 diff -Nru circuits-3.1.0+ds1/circuits/node/node.py circuits-3.2.2/circuits/node/node.py --- circuits-3.1.0+ds1/circuits/node/node.py 2014-09-24 09:54:43.000000000 +0000 +++ circuits-3.2.2/circuits/node/node.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,61 +1,203 @@ -# Module: node -# Date: ... -# Author: ... - """Node -... +this module manage node (start server, add peer, ...) +.. seealso:: Examples in :dir:`examples.node` """ +from circuits import BaseComponent, Timer, handler +from circuits.net.events import connect from .client import Client +from .events import connected_to, disconnected_from, remote from .server import Server -from circuits import handler, BaseComponent - class Node(BaseComponent): + """Node - ... + this class manage node (start server, add peer, ...) + .. seealso:: Examples in :dir:`examples.node` """ + channel = 'node' + __peers = {} - channel = "node" + def __init__(self, port=None, channel=channel, **kwargs): + """Start node system. - def __init__(self, bind=None, channel=channel, **kwargs): + :param port: An optional keyword argument which if defined, + start server on this port. + **Default:** ``None`` (don't start the server) + :type port: int + + :param server_ip: An optional keyword argument which define + ip where the socket has listen to. + **Default:** ``0.0.0.0`` (all ip is allowed) + :type server_ip: str + + :param channel: An optional keyword argument which if defined, + set channel used for node event. **Default:** ``node`` + :type channel: str + + :param receive_event_firewall: An optional keyword argument which if + defined, set function or method to call + to check if event is allowed for sending. + **Default:** ``None`` (no firewall) + :type receive_event_firewall: function + :type receive_event_firewall: method + + :param send_event_firewall: An optional keyword argument which if + defined, set function or method to call to + check if event is allowed for executing + **Default:** ``None`` (no firewall) + :type send_event_firewall: function + :type send_event_firewall: method + """ super(Node, self).__init__(channel=channel, **kwargs) - self.bind = bind - self.nodes = {} - self.__client_event_firewall = kwargs.get( - 'client_event_firewall', - None - ) - - if self.bind is not None: + if port is not None: self.server = Server( - self.bind, - channel=channel, - **kwargs - ).register(self) + port, channel=channel, **kwargs).register(self) else: self.server = None - def add(self, name, host, port, **kwargs): - channel = kwargs['channel'] if 'channel' in kwargs else \ - '%s_client_%s' % (self.channel, name) - node = Client(host, port, channel=channel, **kwargs) - node.register(self) - - self.nodes[name] = node - return channel - - @handler("remote") - def _on_remote(self, event, e, client_name, channel=None): - if self.__client_event_firewall and \ - not self.__client_event_firewall(event, client_name, channel): - return - - node = self.nodes[client_name] - if channel is not None: - e.channels = (channel,) - return node.send(event, e) + def add(self, connection_name, hostname, port, **kwargs): + """Add new peer to the node. + + :param connection_name: Connection name. + :type connection_name: str + + :param hostname: hostname of the remote node. + :type hostname: str + + :param port: port of the remote node. + :type port: int + + :param auto_remote_event: An optional keyword argument which if + defined, bind events automatically to remote + execution. **Default:** ``{}`` (no events) + :type auto_remote_event: dict + + :param channel: An optional keyword argument which if defined, + set channel used for client event. If this keyword is + not defined the method will generate the channel name + automatically. + :type channel: str + + :param reconnect_delay: An optional keyword argument which if defined, + set auto reconnect delay. + **Default:** ``10`` (seconde) + :type reconnect_delay: int + + :param receive_event_firewall: An optional keyword argument which if + defined, function or method to call for + check if event is allowed for sending. + **Default:** ``None`` (no firewall) + :type receive_event_firewall: method + + :param send_event_firewall: An optional keyword argument which if + defined, setfunction or method to call to + check if event is allowed for executing + **Default:** ``None`` (no firewall) + :type send_event_firewall: method + + :return: Channel used on client event. + :rtype: str + """ + # automatic send event to peer + auto_remote_event = kwargs.pop('auto_remote_event', {}) + for event_name in auto_remote_event: + for channel in auto_remote_event[event_name]: + @handler(event_name, channel=channel) + def event_handle(self, event, *args, **kwargs): + yield self.call(remote(event, connection_name)) + self.addHandler(event_handle) + + client_channel = kwargs.pop( + 'channel', + '%s_client_%s' % (self.channel, connection_name) + ) + reconnect_delay = kwargs.pop('reconnect_delay', 10) + client = Client(hostname, port, channel=client_channel, **kwargs) + + # connected event binding + @handler('connected', channel=client_channel) + def connected(self, hostname, port): + self.fire(connected_to( + connection_name, hostname, port, client_channel, client + )) + self.addHandler(connected) + + # disconnected event binding + @handler('disconnected', 'unreachable', channel=client_channel) + def disconnected(self, event, *args, **kwargs): + if event.name == 'disconnected': + self.fire(disconnected_from( + connection_name, hostname, port, client_channel, client + )) + + # auto reconnect + if reconnect_delay > 0: + Timer( + reconnect_delay, + connect(hostname, port), + client_channel + ).register(self) + + self.addHandler(disconnected) + + client.register(self) + self.__peers[connection_name] = client + return client_channel + + def get_connection_names(self): + """Get connections names + + :return: The list of connections names + :rtype: list of str + """ + return list(self.__peers) + + def get_peer(self, connection_name): + """Get a client object by name + + :param connection_name: Connection name. + :type connection_name: str + + :return: The Client object + :rtype: :class:`circuits.node.client.Client` + """ + return self.__peers[connection_name] if connection_name in self.__peers\ + else None + + @handler('remote', channel='*') + def __on_remote(self, event, remote_event, connection_name, channel=None): + """Send event to peer + + Event handler to run an event on peer (the event definition is + :class:`circuits.node.events.remote`) + + :param event: The event triggered (by the handler) + :type event: :class:`circuits.node.events.remote` + + :param remote_event: Event to execute remotely. + :type remote_event: :class:`circuits.core.events.Event` + + :param connection_name: Connection name (peer selection). + :type connection_name: str + + :param channel: Remote channel (channel to use on peer). + :type channel: str + + :return: The result of remote event + :rtype: generator + + :Example: + ``# hello is your event to execute remotely + # peer_test is peer name + result = yield self.fire(remote(hello())), 'peer_test') + print(result.value)`` + """ + node = self.__peers[connection_name] + remote_event.channels = (channel,) if channel is not None \ + else event.channels + return node.send(remote_event) diff -Nru circuits-3.1.0+ds1/circuits/node/protocol.py circuits-3.2.2/circuits/node/protocol.py --- circuits-3.1.0+ds1/circuits/node/protocol.py 1970-01-01 00:00:00.000000000 +0000 +++ circuits-3.2.2/circuits/node/protocol.py 2021-10-19 16:23:49.000000000 +0000 @@ -0,0 +1,130 @@ +from circuits import Component, handler +from circuits.core import Value +from circuits.net.events import write + +from .utils import dump_event, dump_value, load_event, load_value + +DELIMITER = b'~~~' + + +class Protocol(Component): + __buffer = b'' + __nid = 0 + __events = {} + + def init(self, sock=None, server=None, **kwargs): + self.__server = server + self.__sock = sock + self.__receive_event_firewall = kwargs.get('receive_event_firewall', + None) + self.__send_event_firewall = kwargs.get('send_event_firewall', None) + + def add_buffer(self, data=''): + if data: + self.__buffer += data + + packets = self.__buffer.split(DELIMITER) + self.__buffer = b'' + + for packet in packets: + try: + self.__process_packet(packet) + except ValueError: + self.__buffer = packet + + @handler(channel='node_result', priority=100) + def result_handler(self, event, *args, **kwargs): + if event.name.endswith('_success'): + source_event = args[0] + + if getattr(args[0], 'node_call_id', False) is not False: + self.send_result(source_event.node_call_id, source_event.value) + + def send(self, event): + if self.__send_event_firewall and \ + not self.__send_event_firewall(event, self.__sock): + yield Value(event, self) + + else: + id = self.__nid + self.__nid += 1 + + packet = dump_event(event, id).encode('utf-8') + DELIMITER + self.__send(packet) + + if not getattr(event, 'node_without_result', False): + self.__events[id] = event + while not hasattr(self.__events[id], 'remote_finish'): + yield + + del (self.__events[id]) + yield event.value + + def send_result(self, id, value): + value.node_call_id = id + value.node_sock = self.__sock + packet = dump_value(value).encode('utf-8') + DELIMITER + self.__send(packet) + + def __send(self, packet): + if self.__server is not None: + self.fire(write(self.__sock, packet)) + else: + self.fire(write(packet)) + + def __process_packet(self, packet): + packet = packet.decode('utf-8') + + if '"value":' in packet: + self.__process_packet_value(packet) + + else: + self.__process_packet_call(packet) + + def __process_packet_call(self, packet): + event, id = load_event(packet) + + if self.__receive_event_firewall and \ + not self.__receive_event_firewall(event, self.__sock): + self.send_result(id, Value(event, self)) + else: + event.success = True # fire %s_success event + event.success_channels = ('node_result',) + event.node_call_id = id + event.node_sock = self.__sock + + # convert byte to str + event.args = [arg.decode('utf-8') if isinstance(arg, bytes) else + arg for arg in event.args] + + for i in event.kwargs: + v = event.kwargs[i] + index = i.decode('utf-8') if isinstance(i, bytes) else i + value = v.decode('utf-8') if isinstance(v, bytes) else v + + del (event.kwargs[i]) + event.kwargs[index] = value + + self.fire(event, *event.channels) + + def __process_packet_value(self, packet): + value, id, error, meta = load_value(packet) + + if id in self.__events: + # convert byte to str + value = value.decode( + 'utf-8') if isinstance(value, bytes) else value + error = error.decode( + 'utf-8') if isinstance(error, bytes) else error + + if not hasattr(self.__events[id], 'value') \ + or not self.__events[id].value: + self.__events[id].value = Value(self.__events[id], self) + + # save result + self.__events[id].value.setValue(value) + self.__events[id].errors = error + self.__events[id].remote_finish = True + + for k, v in dict(meta).items(): + setattr(self.__events[id], k, v) diff -Nru circuits-3.1.0+ds1/circuits/node/server.py circuits-3.2.2/circuits/node/server.py --- circuits-3.1.0+ds1/circuits/node/server.py 2014-09-24 09:54:43.000000000 +0000 +++ circuits-3.2.2/circuits/node/server.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,81 +1,137 @@ -# Module: server -# Date: ... -# Author: ... - -"""Server - -... -""" - -from circuits.core import Value - -from circuits.net.events import write +from circuits import BaseComponent, handler from circuits.net.sockets import TCPServer -from circuits import handler, BaseComponent, Event - -from .utils import load_event, dump_value -DELIMITER = b"\r\n\r\n" +from .protocol import Protocol class Server(BaseComponent): - """Server - ... - """ + """Node server.""" - channel = "node" + channel = 'node' + __protocols = {} - def __init__(self, bind, channel=channel, **kwargs): + def __init__(self, port, server_ip='0.0.0.0', channel=channel, + receive_event_firewall=None, send_event_firewall=None, + **kwargs): + """Create server on node system. + + :param port: start server on this port. + :type port: int + + :param server_ip: An optional keyword argument which which define + ip where the socket has listen to. + **Default:** ``0.0.0.0`` (all ip is allowed) + :type server_ip: str + + :param channel: An optional keyword argument which if defined, + set channel used for node event. **Default:** ``node`` + :type channel: str + + :param receive_event_firewall: An optional keyword argument which if + defined, set function or method to call + to check if event is allowed for sending + **Default:** ``None`` (no firewall) + :type receive_event_firewall: function + :type receive_event_firewall: method + + :param send_event_firewall: An optional keyword argument which if + defined, set function or method to call to + check if event is allowed for executing + **Default:** ``None`` (no firewall) + :type send_event_firewall: function + :type send_event_firewall: method + """ super(Server, self).__init__(channel=channel, **kwargs) - self._buffers = {} - self.__server_event_firewall = kwargs.get( - 'server_event_firewall', - None - ) - - self.transport = TCPServer(bind, channel=self.channel, **kwargs).register(self) - - @handler('_process_packet') - def _process_packet(self, sock, packet): - event, id = load_event(packet) - - if self.__server_event_firewall and \ - not self.__server_event_firewall(event, sock): - value = Value(event, self) - - else: - value = yield self.call(event, *event.channels) - - value.notify = True - value.node_trn = id - value.node_sock = sock - self.send(value) - - def send(self, v): - data = dump_value(v) - packet = data.encode("utf-8") + DELIMITER - self.fire(write(v.node_sock, packet)) + bind = (server_ip, port) + self.server = TCPServer(bind, channel=self.channel, **kwargs) + self.server.register(self) + self.__receive_event_firewall = receive_event_firewall + self.__send_event_firewall = send_event_firewall + + def send(self, event, sock, no_result=False): + """Send event to peer + + :param event: Event to execute remotely. + :type event: :class:`circuits.core.events.Event` + + :param sock: Client's socket (peer selection). + :type sock: :class:`socket.socket` + + :param no_result: An optional keyword argument which if True + don't return the event result. + **Default:** ``False`` (wait the result) + :type no_result: bool + + :return: The result of remote event + :rtype: generator + """ + iterator = self.__protocols[sock].send(event) + if no_result: + event.node_without_result = True + try: + next(iterator) + except StopIteration: + pass + return iterator + + def send_to(self, event, socks): + """Send event to multiple peer + + :param event: Event to execute remotely. + :type event: :class:`circuits.core.events.Event` + + :param socks: Client's socket list (peer selection). + :type socks: list of :class:`socket.socket` + """ + for sock in socks: + self.send(event, sock, no_result=True) + + def send_all(self, event): + """Send event to all peer + + :param event: Event to execute remotely. + :type event: :class:`circuits.core.events.Event` + """ + self.send_to(event, list(self.__protocols)) - @handler("read") + @handler('read') def _on_read(self, sock, data): - buffer = self._buffers.get(sock, b"") - - buffer += data - - delimiter = buffer.find(DELIMITER) - if delimiter > 0: - packet = buffer[:delimiter].decode("utf-8") - self._buffers[sock] = buffer[(delimiter + len(DELIMITER)):] - self.fire(Event.create('_process_packet', sock, packet)) + self.__protocols[sock].add_buffer(data) @property def host(self): - if hasattr(self, "transport"): - return self.transport.host + if hasattr(self, 'server'): + return self.server.host @property def port(self): - if hasattr(self, "transport"): - return self.transport.port + if hasattr(self, 'server'): + return self.server.port + + def get_socks(self): + """Get clients sockets list + + :return: The list of client socket + :rtype: list of :class:`socket.socket` + """ + return list(self.__protocols) + + @handler('connect') + def __connect_peer(self, sock, host, port): + self.__protocols[sock] = Protocol( + sock=sock, + server=self.server, + receive_event_firewall=self.__receive_event_firewall, + send_event_firewall=self.__send_event_firewall, + channel=self.channel + ).register(self) + + @handler('disconnect') + def __disconnect_peer(self, sock): + for s in self.__protocols.copy(): + try: + s.getpeername() + except Exception: + del self.__protocols[s] diff -Nru circuits-3.1.0+ds1/circuits/node/utils.py circuits-3.2.2/circuits/node/utils.py --- circuits-3.1.0+ds1/circuits/node/utils.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/circuits/node/utils.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,23 +1,19 @@ -# Package: utils -# Date: ... -# Author: ... - -"""Utils - -... -""" - - import json from circuits.core import Event -from circuits.six import bytes_to_str, text_type +from circuits.six import PY3, text_type + +META_EXCLUDE = set(dir(Event())) +META_EXCLUDE.add("node_call_id") +META_EXCLUDE.add("node_sock") +META_EXCLUDE.add("node_without_result") +META_EXCLUDE.add("success_channels") def load_event(s): data = json.loads(s) - name = bytes_to_str(data["name"].encode("utf-8")) + name = data["name"] if PY3 else data["name"].encode("utf-8") args = [] for arg in data["args"]: @@ -38,10 +34,17 @@ e.notify = bool(data["notify"]) e.channels = tuple(data["channels"]) + for k, v in dict(data["meta"]).items(): + setattr(e, k, v) + return e, data["id"] def dump_event(e, id): + meta = {} + for name in list(set(dir(e)) - META_EXCLUDE): + meta[name] = getattr(e, name) + data = { "id": id, "name": e.name, @@ -50,21 +53,29 @@ "success": e.success, "failure": e.failure, "channels": e.channels, - "notify": e.notify + "notify": e.notify, + "meta": meta } return json.dumps(data) def dump_value(v): + meta = {} + e = v.event + if e: + for name in list(set(dir(e)) - META_EXCLUDE): + meta[name] = getattr(e, name) + data = { - "id": v.node_trn, + "id": v.node_call_id, "errors": v.errors, "value": v._value, + "meta": meta } return json.dumps(data) def load_value(v): data = json.loads(v) - return data['value'], data['id'], data['errors'] + return data['value'], data['id'], data['errors'], data['meta'] diff -Nru circuits-3.1.0+ds1/circuits/protocols/http.py circuits-3.2.2/circuits/protocols/http.py --- circuits-3.1.0+ds1/circuits/protocols/http.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/circuits/protocols/http.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,14 +1,15 @@ - from io import BytesIO -from circuits.core import handler, BaseComponent, Event +from circuits.core import BaseComponent, Event, handler class request(Event): + """request Event""" class response(Event): + """response Event""" @@ -26,7 +27,7 @@ self.reason = HTTP_STATUS_CODES[self.status] def __repr__(self): - return "".format( + return "".format( self.status, self.reason, self.headers.get("Content-Type"), diff -Nru circuits-3.1.0+ds1/circuits/protocols/__init__.py circuits-3.2.2/circuits/protocols/__init__.py --- circuits-3.1.0+ds1/circuits/protocols/__init__.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/circuits/protocols/__init__.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,13 +1,6 @@ -# Package: protocols -# Date: 13th March 2009 -# Author: James Mills, prologic at shortcircuit dot net dot au - - """Networking Protocols This package contains components that implement various networking protocols. """ - - from .irc import IRC # noqa from .line import Line # noqa diff -Nru circuits-3.1.0+ds1/circuits/protocols/irc/commands.py circuits-3.2.2/circuits/protocols/irc/commands.py --- circuits-3.1.0+ds1/circuits/protocols/irc/commands.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/circuits/protocols/irc/commands.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,8 +1,3 @@ -# Module: commands -# Date: 11th August 2014 -# Author: James Mills - - """Internet Relay Chat Protocol commands""" @@ -38,8 +33,8 @@ return request(Message("JOIN", channels, keys)) -def PART(channels): - return request(Message("PART", channels)) +def PART(channels, message=None): + return request(Message("PART", channels, message)) def PRIVMSG(receivers, message): diff -Nru circuits-3.1.0+ds1/circuits/protocols/irc/events.py circuits-3.2.2/circuits/protocols/irc/events.py --- circuits-3.1.0+ds1/circuits/protocols/irc/events.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/circuits/protocols/irc/events.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,8 +1,3 @@ -# Module: events -# Date: 11th August 2014 -# Author: James Mills - - """Internet Relay Chat Protocol events""" @@ -10,12 +5,15 @@ class response(Event): + """response Event (Server and Client)""" class reply(Event): + """reply Event (Server)""" class request(Event): + """request Event (Client)""" diff -Nru circuits-3.1.0+ds1/circuits/protocols/irc/__init__.py circuits-3.2.2/circuits/protocols/irc/__init__.py --- circuits-3.1.0+ds1/circuits/protocols/irc/__init__.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/circuits/protocols/irc/__init__.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,26 +1,19 @@ -# Package: irc -# Date: 04th August 2004 -# Author: James Mills - - """Internet Relay Chat Protocol This package implements the Internet Relay Chat Protocol or commonly known as IRC. Support for both server and client is implemented. """ - - -from .commands import * -from .numerics import * -from .protocol import IRC -from .message import Message -from .events import response, reply -from .utils import joinprefix, parsemsg, parseprefix, strip - +from .commands import * # noqa +from .events import reply, response # noqa +from .message import Message # noqa +from .numerics import * # noqa +from .protocol import IRC # noqa +from .utils import ( # noqa + irc_color_to_ansi, joinprefix, parsemsg, parseprefix, strip, +) sourceJoin = joinprefix sourceSplit = parseprefix - # pylama:skip=1 diff -Nru circuits-3.1.0+ds1/circuits/protocols/irc/message.py circuits-3.2.2/circuits/protocols/irc/message.py --- circuits-3.1.0+ds1/circuits/protocols/irc/message.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/circuits/protocols/irc/message.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,11 +1,8 @@ -# Module: message -# Date: 11th August 2014 -# Author: James Mills - - """Internet Relay Chat message""" +from circuits.six import PY3, string_types, text_type + from .utils import parsemsg @@ -16,16 +13,19 @@ class Message(object): def __init__(self, command, *args, **kwargs): - for arg in args[:-1]: - if " " in arg: - raise Error("Space can only appear in the very last arg") - self.command = command - self.args = list(filter(lambda x: x is not None, list(args))) - self.prefix = str(kwargs["prefix"]) if "prefix" in kwargs else None + self.prefix = text_type(kwargs["prefix"]) if "prefix" in kwargs else None self.encoding = kwargs.get("encoding", "utf-8") self.add_nick = kwargs.get("add_nick", False) + self.args = [arg if isinstance(arg, text_type) else arg.decode(self.encoding) for arg in args if arg is not None] + self._check_args() + + def _check_args(self): + if any(type(arg)(' ') in arg in arg for arg in self.args[:-1] if isinstance(arg, string_types)): + raise Error("Space can only appear in the very last arg") + if any(type(arg)('\n') in arg for arg in self.args if isinstance(arg, string_types)): + raise Error("No newline allowed") @staticmethod def from_string(s): @@ -36,30 +36,31 @@ return Message(command, *args, prefix=prefix) + def __str__(self): + return self.__unicode__() if PY3 else self.__bytes__() + def __bytes__(self): - return str(self).encode(self.encoding) + return text_type(self).encode(self.encoding) - def __str__(self): + def __unicode__(self): + self._check_args() args = self.args[:] - for arg in args[:-1]: - if arg is not None and " " in arg: - raise Error("Space can only appear in the very last arg") - if len(args) > 0 and " " in args[-1]: - args[-1] = ":{0:s}".format(args[-1]) + if args and u" " in args[-1] and not args[-1].startswith(u":"): + args[-1] = u":{}".format(args[-1]) - return "{prefix:s}{command:s} {args:s}\r\n".format( + return u"{prefix}{command} {args}\r\n".format( prefix=( - ":{0:s} ".format(self.prefix) + u":{} ".format(self.prefix) if self.prefix is not None - else "" + else u"" ), - command=str(self.command), - args=" ".join(args) + command=text_type(self.command), + args=u" ".join(args) ) def __repr__(self): - return "\"{0:s}\"".format(str(self)[:-2]) + return repr(text_type(self)[:-2]) def __eq__(self, other): return isinstance(other, Message) \ diff -Nru circuits-3.1.0+ds1/circuits/protocols/irc/numerics.py circuits-3.2.2/circuits/protocols/irc/numerics.py --- circuits-3.1.0+ds1/circuits/protocols/irc/numerics.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/circuits/protocols/irc/numerics.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,8 +1,3 @@ -# Module: numerics -# Date: 11 August 2014 -# Author: James Mills - - """Internet Relay Chat Protocol numerics""" diff -Nru circuits-3.1.0+ds1/circuits/protocols/irc/protocol.py circuits-3.2.2/circuits/protocols/irc/protocol.py --- circuits-3.1.0+ds1/circuits/protocols/irc/protocol.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/circuits/protocols/irc/protocol.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,30 +1,21 @@ -# Module: protocol -# Date: 11th August 2014 -# Author: James Mills - - """Internet Relay Chat Protocol""" from re import compile as compile_regex - from circuits import Component - from circuits.net.events import write from circuits.protocols.line import Line - from .commands import PONG +from .events import response from .utils import parsemsg -from .message import Message -from .events import reply, response - NUMERIC = compile_regex("[0-9]+") class IRC(Component): + """IRC Protocol Component Creates a new IRC Component instance that implements the IRC Protocol. @@ -98,8 +89,4 @@ if len(args) == 2: # Client read self.fire(PONG(args[1])) - else: - # Server read - self.fire(reply(args[0], Message("PONG", args[2]))) - - event.stop() + event.stop() diff -Nru circuits-3.1.0+ds1/circuits/protocols/irc/replies.py circuits-3.2.2/circuits/protocols/irc/replies.py --- circuits-3.1.0+ds1/circuits/protocols/irc/replies.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/circuits/protocols/irc/replies.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,14 +1,6 @@ -# Module: replies -# Date: 11th August 2014 -# Author: James Mills - - """Internet Relay Chat Protocol replies""" -from operator import attrgetter - - from .message import Message @@ -17,63 +9,282 @@ return Message(*args, **kwargs) +def ERROR(host, reason=None): + return Message(u"ERROR", u":Closing link: {0} ({1})".format(host, reason or u"")) + + +def JOIN(name, prefix=None): + return Message(u"JOIN", name, prefix=prefix) + + +def KICK(channel, nick, reason=None, prefix=None): + return Message(u"KICK", channel, nick, reason, prefix=prefix) + + +def MODE(target, modes, params=None, prefix=None): + if params is None: + return Message(u"MODE", target, modes, prefix=prefix) + return Message(u"MODE", target, modes, u" ".join(params), prefix=prefix) + + +def PART(channel, nick, reason=None, prefix=None): + return Message(u"PART", channel, nick, reason, prefix=prefix) + + +def PING(server): + return Message(u"PING", u":{0}".format(server)) + + +def PONG(server, text): + return Message(u"PONG", server, u":{0}".format(text)) + + +def TOPIC(channel, topic, prefix=None): + return Message(u"TOPIC", channel, topic, prefix=prefix) + + def RPL_WELCOME(network): - return _M("001", "Welcome to the {0:s} IRC Network".format(network)) + return _M(u"001", u"Welcome to the {0} IRC Network".format(network)) def RPL_YOURHOST(host, version): - return _M("002", "Your host is {0:s} running {1:s}".format(host, version)) + return _M(u"002", u"Your host is {0} running {1}".format(host, version)) -def ERR_NOMOTD(): - return _M("422", "MOTD file is missing") +def RPL_CREATED(date): + return _M(u"003", u"This server was created {0}".format(date)) -def ERR_NOSUCHNICK(nick): - return _M("401", nick, "No such nick") +def RPL_MYINFO(server, version, umodes, chmodes): + return _M(u"004", server, version, umodes, chmodes) -def ERR_NOSUCHCHANNEL(channel): - return _M("403", channel, "No such channel") +def RPL_ISUPPORT(features): + return _M(u"005", *(features + (u"are supported by this server",))) + +def RPL_UMODEIS(modes): + return _M(u"221", modes) -def RPL_WHOREPLY(user, mask, server): - # H = Here - # G = Away - # * = IRCOp - # @ = Channel Op - # + = Voiced +def RPL_LUSERCLIENT(nusers, nservices, nservers): return _M( - "352", mask, - user.userinfo.user, user.userinfo.host, - server, user.nick, - "G" if user.away else "H", - "0 " + user.userinfo.name + u"251", + u"There are {0} users and {1} services on {2} servers".format( + nusers, nservices, nservers + ) ) +def RPL_LUSEROP(noperators): + return _M(u"252", u"{0}".format(noperators), u"operator(s) online") + + +def RPL_LUSERUNKOWN(nunknown): + return _M(u"253", u"{0}".format(nunknown), u"unknown connection(s)") + + +def RPL_LUSERCHANNELS(nchannels): + return _M(u"254", u"{0}".format(nchannels), u"channels formed") + + +def RPL_LUSERME(nclients, nservers): + return _M(u"255", u"I have {0} clients and {1} servers".format(nclients, nservers)) + + +def RPL_AWAY(nick, message): + return _M(u"301", nick, u":{0}".format(message)) + + +def RPL_UNAWAY(): + return _M(u"305", u"You are no longer marked as being away") + + +def RPL_NOWAWAY(): + return _M(u"306", u"You have been marked as being away") + + +def RPL_WHOISUSER(nick, user, host, realname): + return _M(u"311", nick, user, host, u"*", u":{0}".format(realname)) + + +def RPL_WHOISSERVER(nick, server, server_info): + return _M(u"312", nick, server, server_info) + + +def RPL_WHOISOPERATOR(nick): + return _M(u"313", nick, u"is an IRC operator") + + def RPL_ENDOFWHO(mask): - return _M("315", mask, "End of WHO list") + return _M(u"315", mask, u"End of WHO list") + + +def RPL_WHOISIDLE(nick, idle, signon): + return _M( + u"317", nick, + u"{0}".format(idle), u"{0}".format(signon), + u"seconds idle, signon time" + ) + + +def RPL_ENDOFWHOIS(nick): + return _M(u"318", nick, u"End of WHOIS list") + + +def RPL_WHOISCHANNELS(nick, channels): + return _M(u"319", nick, u":{0}".format(u" ".join(channels))) + + +def RPL_LISTSTART(header=None): + return _M(u"321", header or u"Channels :Users Name") + + +def RPL_LIST(channel, nvisible, topic): + return _M(u"322", channel, u"{0}".format(nvisible), topic) + + +def RPL_LISTEND(): + return _M(u"323", u"End of LIST") + + +def RPL_CHANNELMODEIS(channel, mode, params=None): + if params is None: + return _M(u"324", channel, mode) + return _M(u"324", channel, mode, params) def RPL_NOTOPIC(channel): - return _M("331", channel, "No topic is set") + return _M(u"331", channel, u"No topic is set") + +def RPL_TOPIC(channel, topic): + return _M(u"332", channel, topic) -def RPL_NAMEREPLY(channel): - prefix = "=" - nicks = " ".join(map(attrgetter("nick"), channel.users)) - return _M("353", prefix, channel.name, nicks) +def RPL_TOPICWHO(channel, setter, timestamp): + return _M(u"333", channel, setter, u"{0}".format(timestamp)) -def RPL_ENDOFNAMES(): - return _M("366", "End of NAMES list") + +def RPL_INVITING(channel, nick): + return _M(u"341", u"{0} {1}".format(channel, nick)) + + +def RPL_SUMMONING(user): + return _M(u"342", u"{0} :Summoning user to IRC".format(user)) + + +def RPL_INVITELIST(channel, invitemask): + return _M(u"346", u"{0} {1}".format(channel, invitemask)) + + +def RPL_ENDOFINVITELIST(channel): + return _M(u"347", u"{0} :End of channel invite list".format(channel)) + + +def RPL_VERSION(name, version, hostname, url): + return _M(u"351", name, version, hostname, url) + + +def RPL_WHOREPLY(channel, user, host, server, nick, status, hops, name): + return _M( + u"352", channel, user, host, server, nick, status, u":{0} {1}".format(hops, name) + ) + + +def RPL_NAMEREPLY(channel, names): + return _M(u"353", u"=", channel, u" ".join(names)) + + +def RPL_ENDOFNAMES(channel): + return _M(u"366", channel, u"End of NAMES list") + + +def RPL_MOTD(text): + return _M(u"372", u"- {0}".format(text)) + + +def RPL_MOTDSTART(server): + return _M(u"375", u"- {0} Message of the day -".format(server)) + + +def RPL_ENDOFMOTD(): + return _M(u"376", u"End of MOTD command") + + +def RPL_YOUREOPER(): + return _M(u"381", u"You are now an IRC operator") + + +def ERR_NOSUCHNICK(nick): + return _M(u"401", nick, u"No such nick") + + +def ERR_NOSUCHCHANNEL(channel): + return _M(u"403", channel, u"No such channel") + + +def ERR_CANNOTSENDTOCHAN(channel): + return _M(u"404", channel, u"Cannot send to channel") + + +def ERR_TOOMANYCHANNELS(channel): + return _M(u"405", channel, u"You have joined too many channels") def ERR_UNKNOWNCOMMAND(command): - return _M("421", command, "Unknown command") + return _M(u"421", command, u"Unknown command") + + +def ERR_NOMOTD(): + return _M(u"422", u"MOTD file is missing") + + +def ERR_NONICKNAMEGIVEN(): + return _M(u"431", u"No nickname given") + + +def ERR_ERRONEUSNICKNAME(nick): + return _M(u"432", nick, u"Erroneous nickname") def ERR_NICKNAMEINUSE(nick): - return _M("433", nick, "Nickname is already in use") + return _M(u"433", nick, u"Nickname is already in use") + + +def ERR_USERNOTINCHANNEL(nick, channel): + return _M(u"441", nick, channel, u"They aren't on that channel") + + +def ERR_NOTREGISTERED(): + return _M(u"451", "You have not registered") + + +def ERR_NEEDMOREPARAMS(command): + return _M(u"461", command, u"Need more parameters") + + +def ERR_PASSWDMISMATCH(): + return _M(u"464", u"Password incorrect") + + +def ERR_UNKNOWNMODE(mode, channel=None): + if channel is None: + return _M(u"472", mode, u"is unknown mode char to me") + return _M(u"472", mode, u"is unknown mode char to me for channel {}".format(channel)) + + +def ERR_CHANOPRIVSNEEDED(channel): + return _M(u"482", channel, u"You're not channel operator") + + +def ERR_NOPRIVILEGES(): + return _M(u"481", u"Permission Denied- You're not an IRC operator") + + +def ERR_NOOPERHOST(): + return _M(u"491", u"No O-lines for your host") + + +def ERR_USERSDONTMATCH(): + return _M(u"502", u"Cannot change mode for other users") diff -Nru circuits-3.1.0+ds1/circuits/protocols/irc/utils.py circuits-3.2.2/circuits/protocols/irc/utils.py --- circuits-3.1.0+ds1/circuits/protocols/irc/utils.py 2014-10-31 09:22:22.000000000 +0000 +++ circuits-3.2.2/circuits/protocols/irc/utils.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,15 +1,11 @@ -# Module: utils -# Date: 11th August 2014 -# Author: James Mills - - """Internet Relay Chat Utilities""" from re import compile as compile_regex - PREFIX = compile_regex("([^!].*)!(.*)@(.*)") +COLOR_CODE = compile_regex(r'(?:(\d\d?)(?:(,)(\d\d?))?)?') +COLOR = compile_regex(r"\x03(?:(\d\d?)(?:,(\d\d?))?)?") class Error(Exception): @@ -30,11 +26,19 @@ """ if len(s) > 0: - if s[0] == ":": + if s[0] == u":": s = s[1:] if color: - s = s.replace("\x01", "") - s = s.replace("\x02", "") + s = s.replace(u"\x01", u"") + s = s.replace(u"\x02", u"") # bold + s = s.replace(u"\x1d", u"") # italics + s = s.replace(u"\x1f", u"") # underline + s = s.replace(u"\x1e", u"") # strikethrough + s = s.replace(u"\x11", u"") # monospace + s = s.replace(u"\x16", u"") # reverse color + s = COLOR.sub(u"", s) # color codes + s = s.replace(u"\x03", u"") # color + s = s.replace(u"\x0f", u"") # reset return s @@ -48,7 +52,7 @@ :returns str: a string in the form of !@ """ - return "{0:s}!{1:s}@{2:s}".format(nick or "", user or "", host or "") + return u"{0}!{1}@{2}".format(nick or u"", user or u"", host or u"") def parseprefix(prefix): @@ -64,7 +68,7 @@ if m is not None: return m.groups() else: - return prefix, None, None + return prefix or None, None, None def parsemsg(s, encoding="utf-8"): @@ -76,23 +80,112 @@ :returns tuple: parsed message in the form of (prefix, command, args) """ - s = s.decode(encoding) + s = s.decode(encoding, 'replace') - prefix = "" + prefix = u"" trailing = [] - if s[0] == ":": - prefix, s = s[1:].split(" ", 1) + if s and s[0] == u":": + prefix, s = s[1:].split(u" ", 1) prefix = parseprefix(prefix) - if s.find(" :") != -1: - s, trailing = s.split(" :", 1) + if s.find(u" :") != -1: + s, trailing = s.split(u" :", 1) args = s.split() args.append(trailing) else: args = s.split() - command = str(args.pop(0)) - - return prefix, command, args + args = iter(args) + command = next(args, None) + command = command and str(command) + + return prefix, command, list(args) + + +def irc_color_to_ansi(data, reset=True): + """Maps IRC color codes to ANSI terminal escape sequences""" + + def ansi(*seq): + return u"\33[{}m".format(u";".join(u"{:02}".format(x) for x in seq if x)) + + ansi_default_fg = 39 + ansi_default_bg = 49 + color_map_fg = { + 0: 37, 1: 30, 2: 34, 3: 32, 4: 31, 5: 36, 6: 35, 7: 33, 8: 93, 9: 92, + 10: 36, 11: 96, 12: 94, 13: 95, 14: 90, 15: 37, + 16: 52, 17: 94, 18: 100, 19: 58, 20: 22, 21: 29, 22: 23, 23: 24, + 24: 17, 25: 54, 26: 53, 27: 89, 28: 88, 29: 130, 30: 142, 31: 64, + 32: 28, 33: 35, 34: 30, 35: 25, 36: 18, 37: 91, 38: 90, 39: 125, + 40: 124, 41: 166, 42: 184, 43: 106, 44: 34, 45: 49, 46: 37, 47: 33, + 48: 19, 49: 129, 50: 127, 51: 161, 52: 196, 53: 208, 54: 226, + 55: 154, 56: 46, 57: 86, 58: 51, 59: 75, 60: 21, 61: 171, 62: 201, + 63: 198, 64: 203, 65: 215, 66: 227, 67: 191, 68: 83, 69: 122, 70: 87, + 71: 111, 72: 63, 73: 177, 74: 207, 75: 205, 76: 217, 77: 223, 78: 229, + 79: 193, 80: 157, 81: 158, 82: 159, 83: 153, 84: 147, 85: 183, 86: 219, + 87: 212, 88: 16, 89: 233, 90: 235, 91: 237, 92: 239, 93: 241, 94: 244, + 95: 247, 96: 250, 97: 254, 98: 231, 99: ansi_default_fg + } + color_map_bg = { + 0: 47, 1: 40, 2: 44, 3: 42, 4: 41, 5: 46, 6: 45, 7: 43, 8: 103, 10: 46, 14: 97, 15: 47, 99: ansi_default_bg + } + + enable_char = { + u'\x16': 1, u'\x1d': 3, u'\x1e': 9, u'\x1f': 4, u'\x16': 7 + } + revert_char = { + u'\x02': 22, u'\x1d': 23, u'\x1f': 24, u'\x16': 27, u'\x1e': 29 + } + + def escape(data): + ignore = set() + start = [] + current_fg = ansi_default_fg + current_bg = ansi_default_bg + for i, char in enumerate(data): + if i in ignore: + continue + if char == u'\x0f': # reset + start = [] + yield ansi(0) + elif char in start and char in revert_char: + start.remove(char) + yield ansi(revert_char[char]) + elif char in enable_char: + start.append(char) + yield ansi(enable_char[char]) + elif char == u'\x03': + i += 1 + m = COLOR_CODE.match(data[i:i + 5]) + colors = [] + if m: + fg, has_bg, bg = m.groups() + if fg: + ignore.update(range(i, i + len(fg))) + colors.append(color_map_fg.get(int(fg), current_fg)) + current_fg = int(fg) + if has_bg: + ignore.update(range(i + len(fg), i + len(fg) + 1)) + if bg: + ignore.update(range(i + len(fg) + 1, i + len(fg) + 1 + len(bg))) + colors.append(color_map_bg.get(int(bg), current_bg)) + current_bg = int(bg) + if char in start: + start.remove(char) + if colors: + start.append(char) + yield ansi(*colors) + else: + yield ansi(ansi_default_fg, ansi_default_bg) + #elif char == u'\x04': + # if char[i + 1:i + 6].isdigit(): + # ignore.update(range(i, i + 6)) + # # TODO: parse hex representation + #elif char == u'\x11': # monospace + # start.append(char) + else: + yield char + if start and reset: + yield ansi(0) + return u"".join(escape(data)) diff -Nru circuits-3.1.0+ds1/circuits/protocols/line.py circuits-3.2.2/circuits/protocols/line.py --- circuits-3.1.0+ds1/circuits/protocols/line.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/circuits/protocols/line.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,22 +1,14 @@ -# Module: line -# Date: 04th February 2010 -# Author: James Mills - """Line Protocol This module implements the basic Line protocol. This module can be used in both server and client implementations. """ - import re -from circuits.core import handler, Event, BaseComponent - -from circuits.six import b +from circuits.core import BaseComponent, Event, handler - -LINESEP = re.compile(b("\r?\n")) +LINESEP = re.compile(b"\r?\n") def splitLines(s, buffer): @@ -33,10 +25,12 @@ class line(Event): + """line Event""" class Line(BaseComponent): + """Line Protocol Implements the Line Protocol. diff -Nru circuits-3.1.0+ds1/circuits/protocols/stomp/client.py circuits-3.2.2/circuits/protocols/stomp/client.py --- circuits-3.1.0+ds1/circuits/protocols/stomp/client.py 1970-01-01 00:00:00.000000000 +0000 +++ circuits-3.2.2/circuits/protocols/stomp/client.py 2021-10-19 16:23:49.000000000 +0000 @@ -0,0 +1,293 @@ +# -*- coding: utf-8 -*- +""" Circuits component for handling Stomp Connection """ + +import logging +import ssl +import time +import traceback + +from circuits import BaseComponent, Timer +from circuits.core.handlers import handler +from circuits.protocols.stomp.events import ( + client_heartbeat, connected, connection_failed, disconnected, + heartbeat_timeout, message, on_stomp_error, server_heartbeat, +) +from circuits.protocols.stomp.transport import EnhancedStompFrameTransport + +try: + from stompest.config import StompConfig + from stompest.protocol import StompSpec, StompSession + from stompest.sync import Stomp + from stompest.error import StompConnectionError, StompError + from stompest.sync.client import LOG_CATEGORY +except ImportError: + raise ImportError("No stomp support available. Is stompest installed?") + + +StompSpec.DEFAULT_VERSION = '1.2' +ACK_CLIENT_INDIVIDUAL = StompSpec.ACK_CLIENT_INDIVIDUAL +ACK_AUTO = StompSpec.ACK_AUTO +ACK_CLIENT = StompSpec.ACK_CLIENT +ACK_MODES = (ACK_CLIENT_INDIVIDUAL, ACK_AUTO, ACK_CLIENT) + +LOG = logging.getLogger(__name__) + + +class StompClient(BaseComponent): + """ Send and Receive messages from a STOMP queue """ + channel = "stomp" + + def init(self, host, port, username=None, password=None, + connect_timeout=3, connected_timeout=3, + version=StompSpec.VERSION_1_2, accept_versions=["1.0", "1.1", "1.2"], + heartbeats=(0, 0), ssl_context=None, + use_ssl=True, + key_file=None, + cert_file=None, + ca_certs=None, + ssl_version=ssl.PROTOCOL_SSLv23, + key_file_password=None, + proxy_host=None, + proxy_port=None, + proxy_user=None, + proxy_password=None, + channel=channel): + """ Initialize StompClient. Called after __init__ """ + self.channel = channel + if proxy_host: + LOG.info("Connect to %s:%s through proxy %s:%d", host, port, proxy_host, proxy_port) + else: + LOG.info("Connect to %s:%s", host, port) + + if use_ssl and not ssl_context: + + ssl_params = dict(key_file=key_file, + cert_file=cert_file, + ca_certs=ca_certs, + ssl_version=ssl_version, + password=key_file_password) + LOG.info("Request to use old-style socket wrapper: %s", ssl_params) + ssl_context = ssl_params + + if use_ssl: + uri = "ssl://%s:%s" % (host, port) + else: + uri = "tcp://%s:%s" % (host, port) + + # Configure failover options so it only tries to connect once + self._stomp_server = "failover:(%s)?maxReconnectAttempts=1,startupMaxReconnectAttempts=1" % uri + + self._stomp_config = StompConfig(uri=self._stomp_server, sslContext=ssl_context, + version=version, + login=username, + passcode=password) + + self._heartbeats = heartbeats + self._accept_versions = accept_versions + self._connect_timeout = connect_timeout + self._connected_timeout = connected_timeout + Stomp._transportFactory = EnhancedStompFrameTransport + Stomp._transportFactory.proxy_host = proxy_host + Stomp._transportFactory.proxy_port = proxy_port + Stomp._transportFactory.proxy_user = proxy_user + Stomp._transportFactory.proxy_password = proxy_password + self._client = Stomp(self._stomp_config) + self._subscribed = {} + self.server_heartbeat = None + self.client_heartbeat = None + self.ALLOWANCE = 2 # multiplier for heartbeat timeouts + + @property + def connected(self): + if self._client.session: + return self._client.session.state == StompSession.CONNECTED + else: + return False + + @property + def subscribed(self): + return self._subscribed.keys() + + @property + def stomp_logger(self): + return LOG_CATEGORY + + @handler("disconnect") + def _disconnect(self, receipt=None): + if self.connected: + self._client.disconnect(receipt=receipt) + self._client.close(flush=True) + self.fire(disconnected(reconnect=False)) + self._subscribed = {} + return "disconnected" + + def start_heartbeats(self): + LOG.info("Client HB: %s Server HB: %s", self._client.clientHeartBeat, self._client.serverHeartBeat) + if self._client.clientHeartBeat: + if self.client_heartbeat: + # Timer already exists, just reset it + self.client_heartbeat.reset() + else: + LOG.info("Client will send heartbeats to server") + # Send heartbeats at 80% of agreed rate + self.client_heartbeat = Timer((self._client.clientHeartBeat / 1000.0) * 0.8, + client_heartbeat(), persist=True) + self.client_heartbeat.register(self) + else: + LOG.info("No Client heartbeats will be sent") + + if self._client.serverHeartBeat: + if self.server_heartbeat: + # Timer already exists, just reset it + self.server_heartbeat.reset() + else: + LOG.info("Requested heartbeats from server.") + # Allow a grace period on server heartbeats + self.server_heartbeat = Timer((self._client.serverHeartBeat / 1000.0) * self.ALLOWANCE, + server_heartbeat(), persist=True) + self.server_heartbeat.register(self) + else: + LOG.info("Expecting no heartbeats from Server") + + @handler("connect") + def connect(self, event, host=None, *args, **kwargs): + """ connect to Stomp server """ + LOG.info("Connect to Stomp...") + try: + self._client.connect(heartBeats=self._heartbeats, + host=host, + versions=self._accept_versions, + connectTimeout=self._connect_timeout, + connectedTimeout=self._connected_timeout) + LOG.info("State after Connection Attempt: %s", self._client.session.state) + if self.connected: + LOG.info("Connected to %s", self._stomp_server) + self.fire(connected()) + self.start_heartbeats() + return "success" + + except StompConnectionError: + LOG.debug(traceback.format_exc()) + self.fire(connection_failed(self._stomp_server)) + event.success = False + return "fail" + + @handler("server_heartbeat") + def check_server_heartbeat(self, event): + """ Confirm that heartbeat from server hasn't timed out """ + now = time.time() + last = self._client.lastReceived or 0 + if last: + elapsed = now - last + else: + elapsed = -1 + LOG.debug("Last received data %d seconds ago", elapsed) + if ((self._client.serverHeartBeat / 1000.0) * self.ALLOWANCE + last) < now: + LOG.error("Server heartbeat timeout. %d seconds since last heartbeat. Disconnecting.", elapsed) + event.success = False + self.fire(heartbeat_timeout()) + if self.connected: + self._client.disconnect() + # TODO: Try to auto-reconnect? + + @handler("client_heartbeat") + def send_heartbeat(self, event): + if self.connected: + LOG.debug("Sending heartbeat") + try: + self._client.beat() + except StompConnectionError: + event.success = False + self.fire(disconnected()) + + @handler("generate_events") + def generate_events(self, event): + if not self.connected: + return + try: + if self._client.canRead(1): + frame = self._client.receiveFrame() + LOG.debug("Recieved frame %s", frame) + self.fire(message(frame)) + except StompConnectionError: + self.fire(disconnected()) + + @handler("send") + def send(self, event, destination, body, headers=None, receipt=None): + LOG.debug("send()") + if not self.connected: + LOG.error("Can't send when Stomp is disconnected") + self.fire(on_stomp_error(None, Exception("Message send attempted with stomp disconnected"))) + event.success = False + return + try: + self._client.send(destination, body=body.encode('utf-8'), headers=headers, receipt=receipt) + LOG.debug("Message sent") + except StompConnectionError: + event.success = False + self.fire(disconnected()) + except StompError as err: + LOG.error("Error sending ack") + event.success = False + self.fire(on_stomp_error(None, err)) + + @handler("subscribe") + def _subscribe(self, event, destination, ack=ACK_CLIENT_INDIVIDUAL): + if ack not in ACK_MODES: + raise ValueError("Invalid client ack mode specified") + LOG.info("Subscribe to message destination %s", destination) + try: + # Set ID to match destination name for easy reference later + frame, token = self._client.subscribe(destination, + headers={StompSpec.ACK_HEADER: ack, + 'id': destination}) + self._subscribed[destination] = token + except StompConnectionError: + event.success = False + self.fire(disconnected()) + except StompError as err: + event.success = False + LOG.debug(traceback.format_exc()) + self.fire(on_stomp_error(None, err)) + + @handler("unsubscribe") + def _unsubscribe(self, event, destination): + if destination not in self._subscribed: + LOG.error("Unsubscribe Request Ignored. Not subscribed to %s", destination) + return + try: + token = self._subscribed.pop(destination) + frame = self._client.unsubscribe(token) + LOG.debug("Unsubscribed: %s", frame) + except StompConnectionError: + event.success = False + self.fire(disconnected()) + except StompError as err: + LOG.error("Error sending ack") + event.success = False + self.fire(on_stomp_error(frame, err)) + + @handler("message") + def on_message(self, event, headers, message): + LOG.info("Stomp message received") + + @handler("ack") + def ack_frame(self, event, frame): + LOG.debug("ack_frame()") + try: + self._client.ack(frame) + LOG.debug("Ack Sent") + except StompConnectionError: + LOG.error("Error sending ack") + event.success = False + self.fire(disconnected()) + except StompError as err: + LOG.error("Error sending ack") + event.success = False + self.fire(on_stomp_error(frame, err)) + + def get_subscription(self, frame): + """ Get subscription from frame """ + LOG.info(self._subscribed) + _, token = self._client.message(frame) + return self._subscribed[token] diff -Nru circuits-3.1.0+ds1/circuits/protocols/stomp/events.py circuits-3.2.2/circuits/protocols/stomp/events.py --- circuits-3.1.0+ds1/circuits/protocols/stomp/events.py 1970-01-01 00:00:00.000000000 +0000 +++ circuits-3.2.2/circuits/protocols/stomp/events.py 2021-10-19 16:23:49.000000000 +0000 @@ -0,0 +1,108 @@ +# -*- coding: utf-8 -*- +""" Circuits events for STOMP Client """ + +import logging + +from circuits import Event + +LOG = logging.getLogger(__name__) + + +class stomp_event(Event): + """A Circuits event with less verbose repr""" + success = True + + def _repr(self): + return "" + + def __repr__(self): + "x.__repr__() <==> repr(x)" + + if len(self.channels) > 1: + channels = repr(self.channels) + elif len(self.channels) == 1: + channels = str(self.channels[0]) + else: + channels = "" + + data = self._repr() + + return u"<%s[%s] (%s)>" % (self.name, channels, data) + + +class disconnected(stomp_event): + def __init__(self, reconnect=True, receipt=None): + super(disconnected, self).__init__(receipt=receipt) + self.reconnect = reconnect + + +class disconnect(stomp_event): + pass + + +class message(stomp_event): + def __init__(self, frame): + super(message, self).__init__(headers=frame.headers, + message=frame.body) + self.frame = frame + + +class send(stomp_event): + def __init__(self, headers, body, destination): + super(send, self).__init__(headers=headers, + body=body, + destination=destination) + + +class client_heartbeat(stomp_event): + pass + + +class server_heartbeat(stomp_event): + pass + + +class connect(stomp_event): + def __init__(self, subscribe=False, host=None): + super(connect, self).__init__(host=host) + self.subscribe = subscribe + + +class connected(stomp_event): + pass + + +class connection_failed(stomp_event): + reconnect = True + + +class on_stomp_error(stomp_event): + def __init__(self, frame, err): + headers = frame.headers if frame else {} + body = frame.body if frame else None + super(on_stomp_error, self).__init__(headers=headers, + message=body, + error=err) + self.frame = frame + + +class heartbeat_timeout(stomp_event): + pass + + +class subscribe(stomp_event): + def __init__(self, destination, **kwargs): + super(subscribe, self).__init__(destination=destination, **kwargs) + self.destination = destination + + +class unsubscribe(stomp_event): + def __init__(self, destination): + super(unsubscribe, self).__init__(destination=destination) + self.destination = destination + + +class ack(stomp_event): + def __init__(self, frame): + super(ack, self).__init__(frame=frame) + self.frame = frame diff -Nru circuits-3.1.0+ds1/circuits/protocols/stomp/__init__.py circuits-3.2.2/circuits/protocols/stomp/__init__.py --- circuits-3.1.0+ds1/circuits/protocols/stomp/__init__.py 1970-01-01 00:00:00.000000000 +0000 +++ circuits-3.2.2/circuits/protocols/stomp/__init__.py 2021-10-19 16:23:49.000000000 +0000 @@ -0,0 +1,9 @@ +"""STOMP Protocol + +This package contains a component implementing the STOMP Client protocol. +This can be used with products such as ActiveMQ, RabbitMQ, etc +""" +from .client import StompClient + +__all__ = ('StompClient',) +# pylama:skip=1 diff -Nru circuits-3.1.0+ds1/circuits/protocols/stomp/transport.py circuits-3.2.2/circuits/protocols/stomp/transport.py --- circuits-3.1.0+ds1/circuits/protocols/stomp/transport.py 1970-01-01 00:00:00.000000000 +0000 +++ circuits-3.2.2/circuits/protocols/stomp/transport.py 2021-10-19 16:23:49.000000000 +0000 @@ -0,0 +1,89 @@ +""" stompest StompFrameTransport allowing for ssl.wrap_socket """ + +import logging +import socket +import ssl + +try: + from stompest.sync.transport import StompFrameTransport + from stompest.error import StompConnectionError +except ImportError: + raise ImportError("No stomp support available. Is stompest installed?") + +LOG = logging.getLogger(__name__) + + +class EnhancedStompFrameTransport(StompFrameTransport): + """ add support for older ssl module and http proxy """ + + proxy_host = None + proxy_port = None + proxy_user = None + proxy_password = None + + @staticmethod + def match_hostname(cert, hostname): + """ Check that hostname matches cert """ + names = [] + # Python 3 has an ssl.match_hostname method, which does hostname validation. + try: + ssl.match_hostname(cert, hostname) + return + except AttributeError: + # We don't have the backported python 3 ssl module, do a simplified check + for sub in cert.get('subject', ()): + for key, value in sub: + if key == 'commonName': + names.append(value) + if value == hostname: + return + raise RuntimeError("{0} does not match the expected value in the certificate {1}".format(hostname, str(names))) + + def connect(self, timeout=None): + """ Allow older versions of ssl module, allow http proxy connections """ + LOG.debug("stomp_transport.connect()") + ssl_params = None + if isinstance(self.sslContext, dict): + # This is actually a dictionary of ssl parameters for wrapping the socket + ssl_params = self.sslContext + self.sslContext = None + + try: + if self.proxy_host: + try: + # Don't try to import this unless we need it + import socks + except ImportError: + raise ImportError("No http proxy support available. Is pysocks installed?") + + LOG.info("Connecting through proxy %s", self.proxy_host) + self._socket = socks.socksocket() + self._socket.set_proxy(socks.HTTP, self.proxy_host, self.proxy_port, True, + username=self.proxy_user, password=self.proxy_password) + else: + self._socket = socket.socket() + + self._socket.settimeout(timeout) + self._socket.connect((self.host, self.port)) + + if ssl_params: + # For cases where we don't have a modern SSLContext (so no SNI) + cert_required = ssl.CERT_REQUIRED if ssl_params["ca_certs"] else ssl.CERT_NONE + self._socket = ssl.wrap_socket( + self._socket, + keyfile=ssl_params['key_file'], + certfile=ssl_params['cert_file'], + cert_reqs=cert_required, + ca_certs=ssl_params['ca_certs'], + ssl_version=ssl_params['ssl_version']) + if cert_required: + LOG.info("Performing manual hostname check") + cert = self._socket.getpeercert() + self.match_hostname(cert, self.host) + + if self.sslContext: + self._socket = self.sslContext.wrap_socket(self._socket, server_hostname=self.host) + + except IOError as e: + raise StompConnectionError('Could not establish connection [%s]' % e) + self._parser.reset() diff -Nru circuits-3.1.0+ds1/circuits/protocols/websocket.py circuits-3.2.2/circuits/protocols/websocket.py --- circuits-3.1.0+ds1/circuits/protocols/websocket.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/circuits/protocols/websocket.py 2021-10-19 16:23:49.000000000 +0000 @@ -2,17 +2,17 @@ .. codeauthor: mnl """ - import os import random -from circuits.six import string_types -from circuits.core.handlers import handler from circuits.core.components import BaseComponent -from circuits.net.events import write, read, close +from circuits.core.handlers import handler +from circuits.net.events import close, read, write +from circuits.six import string_types class WebSocketCodec(BaseComponent): + """WebSocket Protocol Implements the Data Framing protocol for WebSocket. @@ -48,6 +48,7 @@ self._pending_type = None self._close_received = False self._close_sent = False + self._buffer = bytearray() messages = self._parse_messages(bytearray(data)) for message in messages: @@ -58,7 +59,7 @@ @handler("registered") def _on_registered(self, component, parent): - if component == self: + if component is self: @handler("read", priority=10, channel=parent.channel) def _on_read_raw(self, event, *args): if self._sock is not None: @@ -89,6 +90,7 @@ msgs = [] # one chunk of bytes may result in several messages if self._close_received: return msgs + data = self._buffer + data while data: # extract final flag, opcode and masking final = bool(data[0] & 0x80 != 0) @@ -110,7 +112,9 @@ offset += 4 # if not enough bytes available yet, retry after next read if len(data) - offset < payload_length: + self._buffer = data break + self._buffer = bytearray() # rest of _buffer is payload msg = data[offset:offset + payload_length] if masking: # unmask diff -Nru circuits-3.1.0+ds1/circuits/six.py circuits-3.2.2/circuits/six.py --- circuits-3.1.0+ds1/circuits/six.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/circuits/six.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,15 +1,40 @@ +# Copyright (c) 2010-2017 Benjamin Peterson +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. """Utilities for writing code that runs on Python 2 and 3""" +from __future__ import absolute_import + +import functools +import itertools +import operator import sys import types -import operator __author__ = "Benjamin Peterson " -__version__ = "1.2.0" +__version__ = "1.10.0" -# True if we are running on Python 3. +# Useful for very coarse version differentiation. +PY2 = sys.version_info[0] == 2 PY3 = sys.version_info[0] == 3 +PY34 = sys.version_info[0:2] >= (3, 4) if PY3: string_types = str, @@ -17,8 +42,7 @@ class_types = type, text_type = str binary_type = bytes - byteindex = lambda x, i: x[i] - iterbytes = lambda x: iter(x) + MAXSIZE = sys.maxsize else: string_types = basestring, @@ -27,12 +51,13 @@ text_type = unicode binary_type = str - if sys.platform == "java": + if sys.platform.startswith("java"): # Jython always uses 32 bits. MAXSIZE = int((1 << 31) - 1) else: # It's possible to have sizeof(long) != sizeof(Py_ssize_t). class X(object): + def __len__(self): return 1 << 31 try: @@ -43,13 +68,7 @@ else: # 64-bit MAXSIZE = int((1 << 63) - 1) - del X - - def byteindex(data, index): - return ord(data[index]) - - def iterbytes(data): - return (ord (char) for char in data) + del X def _add_doc(func, doc): @@ -70,9 +89,13 @@ def __get__(self, obj, tp): result = self._resolve() - setattr(obj, self.name, result) - # This is a bit ugly, but it avoids running this again. - delattr(tp, self.name) + setattr(obj, self.name, result) # Invokes __set__. + try: + # This is a bit ugly, but it avoids running this again by + # removing this descriptor. + delattr(obj.__class__, self.name) + except AttributeError: + pass return result @@ -90,6 +113,27 @@ def _resolve(self): return _import_module(self.mod) + def __getattr__(self, attr): + _module = self._resolve() + value = getattr(_module, attr) + setattr(self, attr, value) + return value + + +class _LazyModule(types.ModuleType): + + def __init__(self, name): + super(_LazyModule, self).__init__(name) + self.__doc__ = self.__class__.__doc__ + + def __dir__(self): + attrs = ["__doc__", "__name__"] + attrs += [attr.name for attr in self._moved_attributes] + return attrs + + # Subclasses should override this + _moved_attributes = [] + class MovedAttribute(_LazyDescr): @@ -116,30 +160,112 @@ return getattr(module, self.attr) +class _SixMetaPathImporter(object): + + """ + A meta path importer to import six.moves and its submodules. + + This class implements a PEP302 finder and loader. It should be compatible + with Python 2.5 and all existing versions of Python3 + """ + + def __init__(self, six_module_name): + self.name = six_module_name + self.known_modules = {} + + def _add_module(self, mod, *fullnames): + for fullname in fullnames: + self.known_modules[self.name + "." + fullname] = mod + + def _get_module(self, fullname): + return self.known_modules[self.name + "." + fullname] + + def find_module(self, fullname, path=None): + if fullname in self.known_modules: + return self + return None + + def __get_module(self, fullname): + try: + return self.known_modules[fullname] + except KeyError: + raise ImportError("This loader does not know module " + fullname) + + def load_module(self, fullname): + try: + # in case of a reload + return sys.modules[fullname] + except KeyError: + pass + mod = self.__get_module(fullname) + if isinstance(mod, MovedModule): + mod = mod._resolve() + else: + mod.__loader__ = self + sys.modules[fullname] = mod + return mod + + def is_package(self, fullname): + """ + Return true, if the named module is a package. + + We need this method to get correct spec objects with + Python 3.4 (see PEP451) + """ + return hasattr(self.__get_module(fullname), "__path__") + + def get_code(self, fullname): + """Return None + + Required, if is_package is implemented""" + self.__get_module(fullname) # eventually raises ImportError + return None + get_source = get_code # same as get_code + +_importer = _SixMetaPathImporter(__name__) + + +class _MovedItems(_LazyModule): -class _MovedItems(types.ModuleType): """Lazy loading of moved objects""" + __path__ = [] # mark as package _moved_attributes = [ MovedAttribute("cStringIO", "cStringIO", "io", "StringIO"), MovedAttribute("filter", "itertools", "builtins", "ifilter", "filter"), + MovedAttribute("filterfalse", "itertools", "itertools", "ifilterfalse", "filterfalse"), MovedAttribute("input", "__builtin__", "builtins", "raw_input", "input"), + MovedAttribute("intern", "__builtin__", "sys"), MovedAttribute("map", "itertools", "builtins", "imap", "map"), - MovedAttribute("reload_module", "__builtin__", "imp", "reload"), + MovedAttribute("getcwd", "os", "os", "getcwdu", "getcwd"), + MovedAttribute("getcwdb", "os", "os", "getcwd", "getcwdb"), + MovedAttribute("range", "__builtin__", "builtins", "xrange", "range"), + MovedAttribute("reload_module", "__builtin__", "importlib" if PY34 else "imp", "reload"), MovedAttribute("reduce", "__builtin__", "functools"), + MovedAttribute("shlex_quote", "pipes", "shlex", "quote"), MovedAttribute("StringIO", "StringIO", "io"), + MovedAttribute("UserDict", "UserDict", "collections"), + MovedAttribute("UserList", "UserList", "collections"), + MovedAttribute("UserString", "UserString", "collections"), MovedAttribute("xrange", "__builtin__", "builtins", "xrange", "range"), MovedAttribute("zip", "itertools", "builtins", "izip", "zip"), - + MovedAttribute("zip_longest", "itertools", "itertools", "izip_longest", "zip_longest"), MovedModule("builtins", "__builtin__"), MovedModule("configparser", "ConfigParser"), MovedModule("copyreg", "copy_reg"), + MovedModule("dbm_gnu", "gdbm", "dbm.gnu"), + MovedModule("_dummy_thread", "dummy_thread", "_dummy_thread"), MovedModule("http_cookiejar", "cookielib", "http.cookiejar"), MovedModule("http_cookies", "Cookie", "http.cookies"), MovedModule("html_entities", "htmlentitydefs", "html.entities"), MovedModule("html_parser", "HTMLParser", "html.parser"), MovedModule("http_client", "httplib", "http.client"), + MovedModule("email_mime_base", "email.MIMEBase", "email.mime.base"), + MovedModule("email_mime_image", "email.MIMEImage", "email.mime.image"), + MovedModule("email_mime_multipart", "email.MIMEMultipart", "email.mime.multipart"), + MovedModule("email_mime_nonmultipart", "email.MIMENonMultipart", "email.mime.nonmultipart"), + MovedModule("email_mime_text", "email.MIMEText", "email.mime.text"), MovedModule("BaseHTTPServer", "BaseHTTPServer", "http.server"), MovedModule("CGIHTTPServer", "CGIHTTPServer", "http.server"), MovedModule("SimpleHTTPServer", "SimpleHTTPServer", "http.server"), @@ -147,12 +273,14 @@ MovedModule("queue", "Queue"), MovedModule("reprlib", "repr"), MovedModule("socketserver", "SocketServer"), + MovedModule("_thread", "thread", "_thread"), MovedModule("tkinter", "Tkinter"), MovedModule("tkinter_dialog", "Dialog", "tkinter.dialog"), MovedModule("tkinter_filedialog", "FileDialog", "tkinter.filedialog"), MovedModule("tkinter_scrolledtext", "ScrolledText", "tkinter.scrolledtext"), MovedModule("tkinter_simpledialog", "SimpleDialog", "tkinter.simpledialog"), MovedModule("tkinter_tix", "Tix", "tkinter.tix"), + MovedModule("tkinter_ttk", "ttk", "tkinter.ttk"), MovedModule("tkinter_constants", "Tkconstants", "tkinter.constants"), MovedModule("tkinter_dnd", "Tkdnd", "tkinter.dnd"), MovedModule("tkinter_colorchooser", "tkColorChooser", @@ -164,14 +292,196 @@ MovedModule("tkinter_messagebox", "tkMessageBox", "tkinter.messagebox"), MovedModule("tkinter_tksimpledialog", "tkSimpleDialog", "tkinter.simpledialog"), + MovedModule("urllib_parse", __name__ + ".moves.urllib_parse", "urllib.parse"), + MovedModule("urllib_error", __name__ + ".moves.urllib_error", "urllib.error"), + MovedModule("urllib", __name__ + ".moves.urllib", __name__ + ".moves.urllib"), MovedModule("urllib_robotparser", "robotparser", "urllib.robotparser"), - MovedModule("winreg", "_winreg"), + MovedModule("xmlrpc_client", "xmlrpclib", "xmlrpc.client"), + MovedModule("xmlrpc_server", "SimpleXMLRPCServer", "xmlrpc.server"), ] +# Add windows specific modules. +if sys.platform == "win32": + _moved_attributes += [ + MovedModule("winreg", "_winreg"), + ] + for attr in _moved_attributes: setattr(_MovedItems, attr.name, attr) + if isinstance(attr, MovedModule): + _importer._add_module(attr, "moves." + attr.name) +del attr + +_MovedItems._moved_attributes = _moved_attributes + +moves = _MovedItems(__name__ + ".moves") +_importer._add_module(moves, "moves") + + +class Module_six_moves_urllib_parse(_LazyModule): + + """Lazy loading of moved objects in six.moves.urllib_parse""" + + +_urllib_parse_moved_attributes = [ + MovedAttribute("ParseResult", "urlparse", "urllib.parse"), + MovedAttribute("SplitResult", "urlparse", "urllib.parse"), + MovedAttribute("parse_qs", "urlparse", "urllib.parse"), + MovedAttribute("parse_qsl", "urlparse", "urllib.parse"), + MovedAttribute("urldefrag", "urlparse", "urllib.parse"), + MovedAttribute("urljoin", "urlparse", "urllib.parse"), + MovedAttribute("urlparse", "urlparse", "urllib.parse"), + MovedAttribute("urlsplit", "urlparse", "urllib.parse"), + MovedAttribute("urlunparse", "urlparse", "urllib.parse"), + MovedAttribute("urlunsplit", "urlparse", "urllib.parse"), + MovedAttribute("quote", "urllib", "urllib.parse"), + MovedAttribute("quote_plus", "urllib", "urllib.parse"), + MovedAttribute("unquote", "urllib", "urllib.parse"), + MovedAttribute("unquote_plus", "urllib", "urllib.parse"), + MovedAttribute("urlencode", "urllib", "urllib.parse"), + MovedAttribute("splitquery", "urllib", "urllib.parse"), + MovedAttribute("splittag", "urllib", "urllib.parse"), + MovedAttribute("splituser", "urllib", "urllib.parse"), + MovedAttribute("splitvalue", "urllib", "urllib.parse"), + MovedAttribute("uses_fragment", "urlparse", "urllib.parse"), + MovedAttribute("uses_netloc", "urlparse", "urllib.parse"), + MovedAttribute("uses_params", "urlparse", "urllib.parse"), + MovedAttribute("uses_query", "urlparse", "urllib.parse"), + MovedAttribute("uses_relative", "urlparse", "urllib.parse"), +] +for attr in _urllib_parse_moved_attributes: + setattr(Module_six_moves_urllib_parse, attr.name, attr) +del attr + +Module_six_moves_urllib_parse._moved_attributes = _urllib_parse_moved_attributes + +_importer._add_module(Module_six_moves_urllib_parse(__name__ + ".moves.urllib_parse"), + "moves.urllib_parse", "moves.urllib.parse") + + +class Module_six_moves_urllib_error(_LazyModule): + + """Lazy loading of moved objects in six.moves.urllib_error""" + + +_urllib_error_moved_attributes = [ + MovedAttribute("URLError", "urllib2", "urllib.error"), + MovedAttribute("HTTPError", "urllib2", "urllib.error"), + MovedAttribute("ContentTooShortError", "urllib", "urllib.error"), +] +for attr in _urllib_error_moved_attributes: + setattr(Module_six_moves_urllib_error, attr.name, attr) +del attr + +Module_six_moves_urllib_error._moved_attributes = _urllib_error_moved_attributes + +_importer._add_module(Module_six_moves_urllib_error(__name__ + ".moves.urllib.error"), + "moves.urllib_error", "moves.urllib.error") + + +class Module_six_moves_urllib_request(_LazyModule): + + """Lazy loading of moved objects in six.moves.urllib_request""" + + +_urllib_request_moved_attributes = [ + MovedAttribute("urlopen", "urllib2", "urllib.request"), + MovedAttribute("install_opener", "urllib2", "urllib.request"), + MovedAttribute("build_opener", "urllib2", "urllib.request"), + MovedAttribute("pathname2url", "urllib", "urllib.request"), + MovedAttribute("url2pathname", "urllib", "urllib.request"), + MovedAttribute("getproxies", "urllib", "urllib.request"), + MovedAttribute("Request", "urllib2", "urllib.request"), + MovedAttribute("OpenerDirector", "urllib2", "urllib.request"), + MovedAttribute("HTTPDefaultErrorHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPRedirectHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPCookieProcessor", "urllib2", "urllib.request"), + MovedAttribute("ProxyHandler", "urllib2", "urllib.request"), + MovedAttribute("BaseHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPPasswordMgr", "urllib2", "urllib.request"), + MovedAttribute("HTTPPasswordMgrWithDefaultRealm", "urllib2", "urllib.request"), + MovedAttribute("AbstractBasicAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPBasicAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("ProxyBasicAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("AbstractDigestAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPDigestAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("ProxyDigestAuthHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPSHandler", "urllib2", "urllib.request"), + MovedAttribute("FileHandler", "urllib2", "urllib.request"), + MovedAttribute("FTPHandler", "urllib2", "urllib.request"), + MovedAttribute("CacheFTPHandler", "urllib2", "urllib.request"), + MovedAttribute("UnknownHandler", "urllib2", "urllib.request"), + MovedAttribute("HTTPErrorProcessor", "urllib2", "urllib.request"), + MovedAttribute("urlretrieve", "urllib", "urllib.request"), + MovedAttribute("urlcleanup", "urllib", "urllib.request"), + MovedAttribute("URLopener", "urllib", "urllib.request"), + MovedAttribute("FancyURLopener", "urllib", "urllib.request"), + MovedAttribute("proxy_bypass", "urllib", "urllib.request"), +] +for attr in _urllib_request_moved_attributes: + setattr(Module_six_moves_urllib_request, attr.name, attr) +del attr + +Module_six_moves_urllib_request._moved_attributes = _urllib_request_moved_attributes + +_importer._add_module(Module_six_moves_urllib_request(__name__ + ".moves.urllib.request"), + "moves.urllib_request", "moves.urllib.request") + + +class Module_six_moves_urllib_response(_LazyModule): + + """Lazy loading of moved objects in six.moves.urllib_response""" + + +_urllib_response_moved_attributes = [ + MovedAttribute("addbase", "urllib", "urllib.response"), + MovedAttribute("addclosehook", "urllib", "urllib.response"), + MovedAttribute("addinfo", "urllib", "urllib.response"), + MovedAttribute("addinfourl", "urllib", "urllib.response"), +] +for attr in _urllib_response_moved_attributes: + setattr(Module_six_moves_urllib_response, attr.name, attr) +del attr + +Module_six_moves_urllib_response._moved_attributes = _urllib_response_moved_attributes + +_importer._add_module(Module_six_moves_urllib_response(__name__ + ".moves.urllib.response"), + "moves.urllib_response", "moves.urllib.response") + + +class Module_six_moves_urllib_robotparser(_LazyModule): + + """Lazy loading of moved objects in six.moves.urllib_robotparser""" + + +_urllib_robotparser_moved_attributes = [ + MovedAttribute("RobotFileParser", "robotparser", "urllib.robotparser"), +] +for attr in _urllib_robotparser_moved_attributes: + setattr(Module_six_moves_urllib_robotparser, attr.name, attr) del attr -moves = sys.modules["six.moves"] = _MovedItems("moves") +Module_six_moves_urllib_robotparser._moved_attributes = _urllib_robotparser_moved_attributes + +_importer._add_module(Module_six_moves_urllib_robotparser(__name__ + ".moves.urllib.robotparser"), + "moves.urllib_robotparser", "moves.urllib.robotparser") + + +class Module_six_moves_urllib(types.ModuleType): + + """Create a six.moves.urllib namespace that resembles the Python 3 namespace""" + __path__ = [] # mark as package + parse = _importer._get_module("moves.urllib_parse") + error = _importer._get_module("moves.urllib_error") + request = _importer._get_module("moves.urllib_request") + response = _importer._get_module("moves.urllib_response") + robotparser = _importer._get_module("moves.urllib_robotparser") + + def __dir__(self): + return ['parse', 'error', 'request', 'response', 'robotparser'] + +_importer._add_module(Module_six_moves_urllib(__name__ + ".moves.urllib"), + "moves.urllib") def add_move(move): @@ -194,22 +504,18 @@ _meth_func = "__func__" _meth_self = "__self__" + _func_closure = "__closure__" _func_code = "__code__" _func_defaults = "__defaults__" - - _iterkeys = "keys" - _itervalues = "values" - _iteritems = "items" + _func_globals = "__globals__" else: _meth_func = "im_func" _meth_self = "im_self" + _func_closure = "func_closure" _func_code = "func_code" _func_defaults = "func_defaults" - - _iterkeys = "iterkeys" - _itervalues = "itervalues" - _iteritems = "iteritems" + _func_globals = "func_globals" try: @@ -220,23 +526,33 @@ next = advance_iterator -if PY3: - create_bound_method = types.MethodType +try: + callable = callable +except NameError: + def callable(obj): + return any("__call__" in klass.__dict__ for klass in type(obj).__mro__) + +if PY3: def get_unbound_function(unbound): return unbound - Iterator = object + create_bound_method = types.MethodType - def callable(obj): - return any("__call__" in klass.__dict__ for klass in type(obj).__mro__) -else: - def create_bound_method(function, instance): - return types.MethodType(function, instance, instance.__class__) + def create_unbound_method(func, cls): + return func + Iterator = object +else: def get_unbound_function(unbound): return unbound.im_func + def create_bound_method(func, obj): + return types.MethodType(func, obj, obj.__class__) + + def create_unbound_method(func, cls): + return types.MethodType(func, None, cls) + class Iterator(object): def next(self): @@ -249,94 +565,190 @@ get_method_function = operator.attrgetter(_meth_func) get_method_self = operator.attrgetter(_meth_self) +get_function_closure = operator.attrgetter(_func_closure) get_function_code = operator.attrgetter(_func_code) get_function_defaults = operator.attrgetter(_func_defaults) +get_function_globals = operator.attrgetter(_func_globals) -def iterkeys(d): - """Return an iterator over the keys of a dictionary.""" - return iter(getattr(d, _iterkeys)()) - -def itervalues(d): - """Return an iterator over the values of a dictionary.""" - return iter(getattr(d, _itervalues)()) - -def iteritems(d): - """Return an iterator over the (key, value) pairs of a dictionary.""" - return iter(getattr(d, _iteritems)()) +if PY3: + def iterkeys(d, **kw): + return iter(d.keys(**kw)) + + def itervalues(d, **kw): + return iter(d.values(**kw)) + + def iteritems(d, **kw): + return iter(d.items(**kw)) + + def iterlists(d, **kw): + return iter(d.lists(**kw)) + + viewkeys = operator.methodcaller("keys") + + viewvalues = operator.methodcaller("values") + + viewitems = operator.methodcaller("items") +else: + def iterkeys(d, **kw): + return d.iterkeys(**kw) + + def itervalues(d, **kw): + return d.itervalues(**kw) + + def iteritems(d, **kw): + return d.iteritems(**kw) + + def iterlists(d, **kw): + return d.iterlists(**kw) + + viewkeys = operator.methodcaller("viewkeys") + + viewvalues = operator.methodcaller("viewvalues") + + viewitems = operator.methodcaller("viewitems") + +_add_doc(iterkeys, "Return an iterator over the keys of a dictionary.") +_add_doc(itervalues, "Return an iterator over the values of a dictionary.") +_add_doc(iteritems, + "Return an iterator over the (key, value) pairs of a dictionary.") +_add_doc(iterlists, + "Return an iterator over the (key, [values]) pairs of a dictionary.") if PY3: - def b(s, encoding='utf-8'): - return s.encode(encoding) - def u(s, encoding='utf-8'): + def b(s): + return s.encode("latin-1") + + def u(s): return s - def bytes_to_str(b): - return str(b, "unicode_escape") - if sys.version_info[1] <= 1: - def int2byte(i): - return bytes((i,)) - else: - # This is about 2x faster than the implementation above on 3.2+ - int2byte = operator.methodcaller("to_bytes", 1, "big") + unichr = chr + import struct + int2byte = struct.Struct(">B").pack + del struct + byte2int = operator.itemgetter(0) + indexbytes = operator.getitem + iterbytes = iter import io StringIO = io.StringIO BytesIO = io.BytesIO + _assertCountEqual = "assertCountEqual" + if sys.version_info[1] <= 1: + _assertRaisesRegex = "assertRaisesRegexp" + _assertRegex = "assertRegexpMatches" + else: + _assertRaisesRegex = "assertRaisesRegex" + _assertRegex = "assertRegex" else: - def b(s, encoding='utf-8'): - return s - def u(s, encoding='utf-8'): - return unicode(s, encoding) - def bytes_to_str(s): + def b(s): return s + # Workaround for standalone backslash + + def u(s): + return unicode(s.replace(r'\\', r'\\\\'), "unicode_escape") + unichr = unichr int2byte = chr + + def byte2int(bs): + return ord(bs[0]) + + def indexbytes(buf, i): + return ord(buf[i]) + iterbytes = functools.partial(itertools.imap, ord) import StringIO StringIO = BytesIO = StringIO.StringIO + _assertCountEqual = "assertItemsEqual" + _assertRaisesRegex = "assertRaisesRegexp" + _assertRegex = "assertRegexpMatches" _add_doc(b, """Byte literal""") _add_doc(u, """Text literal""") -if PY3: - import builtins - exec_ = getattr(builtins, "exec") +def assertCountEqual(self, *args, **kwargs): + return getattr(self, _assertCountEqual)(*args, **kwargs) - def reraise(tp, value, tb=None): - if value.__traceback__ is not tb: - raise value.with_traceback(tb) - raise value +def assertRaisesRegex(self, *args, **kwargs): + return getattr(self, _assertRaisesRegex)(*args, **kwargs) + +def assertRegex(self, *args, **kwargs): + return getattr(self, _assertRegex)(*args, **kwargs) - print_ = getattr(builtins, "print") - del builtins + +if PY3: + exec_ = getattr(moves.builtins, "exec") + + def reraise(tp, value, tb=None): + try: + if value is None: + value = tp() + if value.__traceback__ is not tb: + raise value.with_traceback(tb) + raise value + finally: + value = None + tb = None else: - def exec_(code, globs=None, locs=None): + def exec_(_code_, _globs_=None, _locs_=None): """Execute code in a namespace.""" - if globs is None: + if _globs_ is None: frame = sys._getframe(1) - globs = frame.f_globals - if locs is None: - locs = frame.f_locals + _globs_ = frame.f_globals + if _locs_ is None: + _locs_ = frame.f_locals del frame - elif locs is None: - locs = globs - exec("""exec code in globs, locs""") - + elif _locs_ is None: + _locs_ = _globs_ + exec("""exec _code_ in _globs_, _locs_""") exec_("""def reraise(tp, value, tb=None): - raise tp, value, tb + try: + raise tp, value, tb + finally: + tb = None +""") +if sys.version_info[:2] == (3, 2): + exec_("""def raise_from(value, from_value): + try: + if from_value is None: + raise value + raise value from from_value + finally: + value = None """) +elif sys.version_info[:2] > (3, 2): + exec_("""def raise_from(value, from_value): + try: + raise value from from_value + finally: + value = None +""") +else: + def raise_from(value, from_value): + raise value +print_ = getattr(moves.builtins, "print", None) +if print_ is None: def print_(*args, **kwargs): - """The new-style print function.""" + """The new-style print function for Python 2.4 and 2.5.""" fp = kwargs.pop("file", sys.stdout) if fp is None: return + def write(data): if not isinstance(data, basestring): data = str(data) + # If the file has an encoding, encode unicode with it. + if (isinstance(fp, file) and + isinstance(data, unicode) and + fp.encoding is not None): + errors = getattr(fp, "errors", None) + if errors is None: + errors = "strict" + data = data.encode(fp.encoding, errors) fp.write(data) want_unicode = False sep = kwargs.pop("sep", None) @@ -373,10 +785,96 @@ write(sep) write(arg) write(end) +if sys.version_info[:2] < (3, 3): + _print = print_ + + def print_(*args, **kwargs): + fp = kwargs.get("file", sys.stdout) + flush = kwargs.pop("flush", False) + _print(*args, **kwargs) + if flush and fp is not None: + fp.flush() _add_doc(reraise, """Reraise an exception.""") +if sys.version_info[0:2] < (3, 4): + def wraps(wrapped, assigned=functools.WRAPPER_ASSIGNMENTS, + updated=functools.WRAPPER_UPDATES): + def wrapper(f): + f = functools.wraps(wrapped, assigned, updated)(f) + f.__wrapped__ = wrapped + return f + return wrapper +else: + wraps = functools.wraps + -def with_metaclass(meta, base=object): +def with_metaclass(meta, *bases): """Create a base class with a metaclass.""" - return meta("NewBase", (base,), {}) + # This requires a bit of explanation: the basic idea is to make a dummy + # metaclass for one level of class instantiation that replaces itself with + # the actual metaclass. + class metaclass(meta): + + def __new__(cls, name, this_bases, d): + return meta(name, bases, d) + return type.__new__(metaclass, 'temporary_class', (), {}) + + +def add_metaclass(metaclass): + """Class decorator for creating a class with a metaclass.""" + def wrapper(cls): + orig_vars = cls.__dict__.copy() + slots = orig_vars.get('__slots__') + if slots is not None: + if isinstance(slots, str): + slots = [slots] + for slots_var in slots: + orig_vars.pop(slots_var) + orig_vars.pop('__dict__', None) + orig_vars.pop('__weakref__', None) + return metaclass(cls.__name__, cls.__bases__, orig_vars) + return wrapper + + +def python_2_unicode_compatible(klass): + """ + A decorator that defines __unicode__ and __str__ methods under Python 2. + Under Python 3 it does nothing. + + To support Python 2 and 3 with a single code base, define a __str__ method + returning text and apply this decorator to the class. + """ + if PY2: + if '__str__' not in klass.__dict__: + raise ValueError("@python_2_unicode_compatible cannot be applied " + "to %s because it doesn't define __str__()." % + klass.__name__) + klass.__unicode__ = klass.__str__ + klass.__str__ = lambda self: self.__unicode__().encode('utf-8') + return klass + + +# Complete the moves implementation. +# This code is at the end of this module to speed up module loading. +# Turn this module into a package. +__path__ = [] # required for PEP 302 and PEP 451 +__package__ = __name__ # see PEP 366 @ReservedAssignment +if globals().get("__spec__") is not None: + __spec__.submodule_search_locations = [] # PEP 451 @UndefinedVariable +# Remove other six meta path importers, since they cause problems. This can +# happen if six is removed from sys.modules and then reloaded. (Setuptools does +# this for some reason.) +if sys.meta_path: + for i, importer in enumerate(sys.meta_path): + # Here's some real nastiness: Another "instance" of the six module might + # be floating around. Therefore, we can't use isinstance() to check for + # the six meta path importer, since the other six instance will have + # inserted an importer with different class. + if (type(importer).__name__ == "_SixMetaPathImporter" and + importer.name == __name__): + del sys.meta_path[i] + break + del i, importer +# Finally, add the importer to the meta path import hook. +sys.meta_path.append(_importer) diff -Nru circuits-3.1.0+ds1/circuits/tools/__init__.py circuits-3.2.2/circuits/tools/__init__.py --- circuits-3.1.0+ds1/circuits/tools/__init__.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/circuits/tools/__init__.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,13 +1,9 @@ -# Module: __init__ -# Date: 8th November 2008 -# Author: James Mills, prologic at shortcircuit dot net dot au - """Circuits Tools circuits.tools contains a standard set of tools for circuits. These tools are installed as executables with a prefix of "circuits." """ - +import inspect as _inspect from functools import wraps from warnings import warn, warn_explicit @@ -21,13 +17,18 @@ try: m = __import__(module, globals(), locals()) return getattr(m, obj) if obj is not None else m - except: + except Exception: pass if message is not None: warn(message) +def getargspec(func): + getargs = _inspect.getfullargspec if hasattr(_inspect, 'getfullargspec') else _inspect.getargspec + return getargs(func)[:4] + + def walk(x, f, d=0, v=None): if not v: v = set() @@ -65,66 +66,109 @@ x.unregister() -def graph(x, name=None): - """Display a directed graph of the Component structure of x +def _graph(x): + """Create a directed graph of the Component structure of x :param x: A Component or Manager to graph :type x: Component or Manager - - :param name: A name for the graph (defaults to x's name) - :type name: str - - @return: A directed graph representing x's Component structure. - @rtype: str """ networkx = tryimport("networkx") pygraphviz = tryimport("pygraphviz") plt = tryimport("matplotlib.pyplot", "pyplot") - if networkx is not None and pygraphviz is not None and plt is not None: - graph_edges = [] - for (u, v, d) in edges(x): - graph_edges.append((u.name, v.name, float(d))) - - g = networkx.DiGraph() - g.add_weighted_edges_from(graph_edges) - - elarge = [(u, v) for (u, v, d) in g.edges(data=True) - if d["weight"] > 3.0] - esmall = [(u, v) for (u, v, d) in g.edges(data=True) - if d["weight"] <= 3.0] - - pos = networkx.spring_layout(g) # positions for all nodes - - # nodes - networkx.draw_networkx_nodes(g, pos, node_size=700) - - # edges - networkx.draw_networkx_edges(g, pos, edgelist=elarge, width=1) - networkx.draw_networkx_edges( - g, pos, edgelist=esmall, width=1, - alpha=0.5, edge_color="b", style="dashed" - ) - - # labels - networkx.draw_networkx_labels( - g, pos, font_size=10, font_family="sans-serif" - ) + if not all([networkx, pygraphviz, plt]): + return None, None + + graph_edges = [] + for (u, v, d) in edges(x): + graph_edges.append((u.name, v.name, float(d))) + + g = networkx.DiGraph() + g.add_weighted_edges_from(graph_edges) + + elarge = [(u, v) for (u, v, d) in g.edges(data=True) if d["weight"] > 3.0] + esmall = [(u, v) for (u, v, d) in g.edges(data=True) if d["weight"] <= 3.0] - plt.axis("off") + pos = networkx.spring_layout(g) # positions for all nodes - plt.savefig("{0:s}.png".format(name or x.name)) - networkx.write_dot(g, "{0:s}.dot".format(name or x.name)) + # nodes + networkx.draw_networkx_nodes(g, pos, node_size=700) - plt.clf() + # edges + networkx.draw_networkx_edges(g, pos, edgelist=elarge, width=1) + networkx.draw_networkx_edges( + g, pos, edgelist=esmall, width=1, + alpha=0.5, edge_color="b", style="dashed" + ) + # labels + networkx.draw_networkx_labels( + g, pos, font_size=10, font_family="sans-serif" + ) + + plt.axis("off") + + plt.clf() + return plt, g + + +def graph_ascii(x): + """Display a directed graph of the Component structure of x + + :param x: A Component or Manager to graph + :type x: Component or Manager + + @return: A directed graph representing x's Component structure. + @rtype: str + """ def printer(d, x): return "%s* %s" % (" " * d, x) return "\n".join(walk(x, printer)) +def graph_dot(x, name=None): + """ + :param x: A Component or Manager to graph + :type x: Component or Manager + + :param name: A name for the graph (defaults to x's name) + :type name: str + """ + + networkx = tryimport("networkx") + plt, g = _graph(x) + if g is not None: + networkx.drawing.nx_agraph.write_dot(g, "{}.dot".format(name or x.name)) + + +def graph_png(x, name=None): + """ + :param x: A Component or Manager to graph + :type x: Component or Manager + + :param name: A name for the graph (defaults to x's name) + :type name: str + """ + plt, g = _graph(x) + if plt is not None: + plt.savefig("{}.png".format(name or x.name)) + + +def graph(x, name=None): + """ + :param x: A Component or Manager to graph + :type x: Component or Manager + + :param name: A name for the graph (defaults to x's name) + :type name: str + """ + graph_dot(x, name) + graph_png(x, name) + return graph_ascii(x) + + def inspect(x): """Display an inspection report of the Component or Manager x @@ -158,7 +202,7 @@ @wraps(f) def wrapper(*args, **kwargs): warn_explicit( - "Call to deprecated function {0:s}".format(f.__name__), + "Call to deprecated function {}".format(f.__name__), category=DeprecationWarning, filename=getattr(f, _func_code).co_filename, lineno=getattr(f, _func_code).co_firstlineno + 1 diff -Nru circuits-3.1.0+ds1/circuits/version.py circuits-3.2.2/circuits/version.py --- circuits-3.1.0+ds1/circuits/version.py 2014-10-31 23:12:23.000000000 +0000 +++ circuits-3.2.2/circuits/version.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,11 +0,0 @@ -# Package: version -# Date: 12th October 2013 -# Author: James Mills, j dot mills at griffith dot edu dot au - -"""Version Module - -So we only have to maintain version information in one place! -""" - -version_info = (3, 1, 0) # (major, minor, patch, dev?) -version = ".".join(map(str, version_info)) diff -Nru circuits-3.1.0+ds1/circuits/web/client.py circuits-3.2.2/circuits/web/client.py --- circuits-3.1.0+ds1/circuits/web/client.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/circuits/web/client.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,14 +1,9 @@ - -try: - from urllib.parse import urlparse -except ImportError: - from urlparse import urlparse # NOQA - +from circuits.core import BaseComponent, Event, handler +from circuits.net.events import close, connect, write +from circuits.net.sockets import TCPClient from circuits.protocols.http import HTTP +from circuits.six.moves.urllib_parse import urlparse from circuits.web.headers import Headers -from circuits.net.sockets import TCPClient -from circuits.net.events import close, connect, write -from circuits.core import handler, BaseComponent, Event def parse_url(url): @@ -45,6 +40,7 @@ class request(Event): + """request Event This Event is used to initiate a new request. @@ -56,7 +52,7 @@ :type url: str """ - def __init__(self, method, path, body=None, headers={}): + def __init__(self, method, path, body=None, headers=None): "x.__init__(...) initializes x; see x.__class__.__doc__ for signature" super(request, self).__init__(method, path, body, headers) @@ -92,19 +88,19 @@ event.stop() @handler("request") - def request(self, method, url, body=None, headers={}): + def request(self, method, url, body=None, headers=None): host, port, path, secure = parse_url(url) if not self._transport.connected: self.fire(connect(host, port, secure)) yield self.wait("connected", self._transport.channel) - headers = Headers([(k, v) for k, v in headers.items()]) + headers = Headers([(k, v) for k, v in (headers or {}).items()]) # Clients MUST include Host header in HTTP/1.1 requests (RFC 2616) if "Host" not in headers: - headers["Host"] = "{0:s}{1:s}".format( - host, "" if port in (80, 443) else ":{0:d}".format(port) + headers["Host"] = "{}{}".format( + host, "" if port in (80, 443) else ":{:d}".format(port) ) if body is not None: @@ -121,7 +117,7 @@ @handler("response") def _on_response(self, response): self._response = response - if response.headers.get("Connection") == "close": + if response.headers.get("Connection", "").lower() == "close": self.fire(close(), self._transport) return response diff -Nru circuits-3.1.0+ds1/circuits/web/constants.py circuits-3.2.2/circuits/web/constants.py --- circuits-3.1.0+ds1/circuits/web/constants.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/circuits/web/constants.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,12 +1,7 @@ -# Module: constants -# Date: 4th February 2009 -# Author: James Mills, prologic at shortcircuit dot net dot au - """Global Constants This module implements required shared global constants. """ - from circuits import __version__ SERVER_PROTOCOL = (1, 1) @@ -36,13 +31,17 @@

%(name)s

%(description)s
%(traceback)s
-
- Powered by %(version)s -
+ %(powered_by)s """ +POWERED_BY = """ +
+ Powered by %(version)s +
+""" + HTTP_STATUS_CODES = { 100: "Continue", 101: "Switching Protocols", diff -Nru circuits-3.1.0+ds1/circuits/web/controllers.py circuits-3.2.2/circuits/web/controllers.py --- circuits-3.1.0+ds1/circuits/web/controllers.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/circuits/web/controllers.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,22 +1,20 @@ -# Module: controllers -# Date: 6th November 2008 -# Author: James Mills, prologic at shortcircuit dot net dot au - """Controllers This module implements ... """ - import json -from inspect import getargspec -from collections import Callable from functools import update_wrapper +try: + from collections import Callable +except ImportError: + from collections.abc import Callable -from circuits.core import handler, BaseComponent +from circuits.core import BaseComponent, handler +from circuits.tools import getargspec from . import tools -from .wrappers import Response from .errors import forbidden, httperror, notfound, redirect +from .wrappers import Response def expose(*channels, **config): @@ -143,14 +141,11 @@ self.cookie = self.request.cookie if hasattr(self.request, "session"): self.session = self.request.session + self.response.headers["Content-Type"] = "application/json" result = f(self, *args, **kwargs) - if (isinstance(result, httperror) - or isinstance(result, Response)): + if (isinstance(result, httperror) or isinstance(result, Response)): return result else: - self.response.headers["Content-Type"] = ( - "application/json" - ) return json.dumps(result) finally: if hasattr(self, "request"): diff -Nru circuits-3.1.0+ds1/circuits/web/dispatchers/dispatcher.py circuits-3.2.2/circuits/web/dispatchers/dispatcher.py --- circuits-3.1.0+ds1/circuits/web/dispatchers/dispatcher.py 2014-10-18 09:06:54.000000000 +0000 +++ circuits-3.2.2/circuits/web/dispatchers/dispatcher.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,27 +1,19 @@ -# Module: dispatcher -# Date: 13th September 2007 -# Author: James Mills, prologic at shortcircuit dot net dot au - """Dispatcher This module implements a basic URL to Channel dispatcher. This is the default dispatcher used by circuits.web """ - try: from urllib import quote, unquote except ImportError: from urllib.parse import quote, unquote # NOQA +from circuits import BaseComponent, Event, handler from circuits.six import text_type - -from circuits import handler, BaseComponent, Event - -from circuits.web.utils import parse_qs +from circuits.web.controllers import BaseController from circuits.web.events import response -from circuits.web.errors import httperror from circuits.web.processors import process -from circuits.web.controllers import BaseController +from circuits.web.utils import parse_qs def resolve_path(paths, parts): diff -Nru circuits-3.1.0+ds1/circuits/web/dispatchers/__init__.py circuits-3.2.2/circuits/web/dispatchers/__init__.py --- circuits-3.1.0+ds1/circuits/web/dispatchers/__init__.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/circuits/web/dispatchers/__init__.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,19 +1,15 @@ -# Package: dispatchers -# Date: 26th February 2011 -# Author: James Mills, prologic at shortcircuit dot net dot au - """Dispatchers This package contains various circuits.web dispatchers By default a ``circuits.web.Server`` Component uses the ``dispatcher.Dispatcher`` """ - -from .static import Static -from .xmlrpc import XMLRPC -from .jsonrpc import JSONRPC +from ..websockets.dispatcher import WebSocketsDispatcher from .dispatcher import Dispatcher +from .jsonrpc import JSONRPC +from .static import Static from .virtualhosts import VirtualHosts -from ..websockets.dispatcher import WebSocketsDispatcher +from .xmlrpc import XMLRPC # flake8: noqa +# pylama: skip=1 diff -Nru circuits-3.1.0+ds1/circuits/web/dispatchers/jsonrpc.py circuits-3.2.2/circuits/web/dispatchers/jsonrpc.py --- circuits-3.1.0+ds1/circuits/web/dispatchers/jsonrpc.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/circuits/web/dispatchers/jsonrpc.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,22 +1,17 @@ -# Module: jsonrpc -# Date: 13th September 2007 -# Author: James Mills, prologic at shortcircuit dot net dot au - """JSON RPC This module implements a JSON RPC dispatcher that translates incoming RPC calls over JSON into RPC events. """ - +from circuits import BaseComponent, Event, handler +from circuits.six import binary_type from circuits.tools import tryimport json = tryimport(("json", "simplejson")) -from circuits.six import binary_type -from circuits import handler, Event, BaseComponent - class rpc(Event): + """RPC Event""" @@ -44,21 +39,16 @@ try: data = req.body.read().decode(self.encoding) o = json.loads(data) - id, method, params = o["id"], o["method"], o["params"] + id, method, params = o["id"], o["method"], o.get("params", {}) if isinstance(params, dict): params = dict([(str(k), v) for k, v in params.iteritems()]) - if "." in method: - channel, name = method.split(".", 1) - else: - channel, name = self.rpc_channel, method - - name = str(name) if not isinstance(name, binary_type) else name + method = str(method) if not isinstance(method, binary_type) else method if isinstance(params, dict): - value = yield self.call(rpc.create(name, **params), channel) + value = yield self.call(rpc.create(method, **params), self.rpc_channel) else: - value = yield self.call(rpc.create(name, *params), channel) + value = yield self.call(rpc.create(method, *params), self.rpc_channel) yield self._response(id, value.value) except Exception as e: diff -Nru circuits-3.1.0+ds1/circuits/web/dispatchers/static.py circuits-3.2.2/circuits/web/dispatchers/static.py --- circuits-3.1.0+ds1/circuits/web/dispatchers/static.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/circuits/web/dispatchers/static.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,23 +1,17 @@ -# Module: static -# Date: 13th September 2007 -# Author: James Mills, prologic at shortcircuit dot net dot au - """Static This modStatic implements a Static dispatcher used to serve up static resources and an optional apache-style directory listing. """ - import os from string import Template - try: - from urllib import quote, unquote + from html import escape except ImportError: - from urllib.parse import quote, unquote # NOQA - -from circuits import handler, BaseComponent + from cgi import escape +from circuits import BaseComponent, handler +from circuits.six.moves.urllib_parse import quote, unquote from circuits.web.tools import serve_file DEFAULT_DIRECTORY_INDEX_TEMPLATE = """ @@ -48,11 +42,12 @@ channel = "web" def __init__(self, path=None, docroot=None, - defaults=("index.html", "index.xhtml",), dirlisting=False): - super(Static, self).__init__() + defaults=("index.html", "index.xhtml",), dirlisting=False, **kwargs): + super(Static, self).__init__(**kwargs) self.path = path - self.docroot = os.path.abspath(docroot) if docroot is not None else os.path.abspath(os.getcwd()) + self.docroot = os.path.abspath( + docroot) if docroot is not None else os.path.abspath(os.getcwd()) self.defaults = defaults self.dirlisting = dirlisting @@ -77,7 +72,7 @@ return if not location.startswith(os.path.dirname(self.docroot)): - return # hacking attemp e.g. /foo/../../../../../etc/shadow + return # hacking attempt e.g. /foo/../../../../../etc/shadow # Is it a file we can serve directly? if os.path.isfile(location): @@ -116,7 +111,7 @@ url_up = os.path.join("/", os.path.split(path)[0]) else: url_up = os.path.join(cur_dir, "..") - url_up = '
  • %s
  • ' % (url_up, "..") + url_up = '
  • %s
  • ' % (escape(url_up, True), "..") listing = [] for item in os.listdir(directory): @@ -127,11 +122,11 @@ ) if os.path.isdir(location): li = '
  • %s/
  • ' % ( - quote(url), item + escape(quote(url), True), escape(item) ) else: li = '
  • %s
  • ' % ( - quote(url), item + escape(quote(url), True), escape(item) ) listing.append(li) diff -Nru circuits-3.1.0+ds1/circuits/web/dispatchers/virtualhosts.py circuits-3.2.2/circuits/web/dispatchers/virtualhosts.py --- circuits-3.1.0+ds1/circuits/web/dispatchers/virtualhosts.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/circuits/web/dispatchers/virtualhosts.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,22 +1,14 @@ -# Module: virtualhost -# Date: 13th September 2007 -# Author: James Mills, prologic at shortcircuit dot net dot au - """VirtualHost This module implements a virtual host dispatcher that sends requests for configured virtual hosts to different dispatchers. """ - -try: - from urllib.parse import urljoin -except ImportError: - from urlparse import urljoin # NOQA - -from circuits import handler, BaseComponent +from circuits import BaseComponent, handler +from circuits.six.moves.urllib_parse import urljoin class VirtualHosts(BaseComponent): + """Forward to anotehr Dispatcher based on the Host header. This can be useful when running multiple sites within one server. diff -Nru circuits-3.1.0+ds1/circuits/web/dispatchers/xmlrpc.py circuits-3.2.2/circuits/web/dispatchers/xmlrpc.py --- circuits-3.1.0+ds1/circuits/web/dispatchers/xmlrpc.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/circuits/web/dispatchers/xmlrpc.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,23 +1,18 @@ -# Module: xmlrpc -# Date: 13th September 2007 -# Author: James Mills, prologic at shortcircuit dot net dot au - """XML RPC This module implements a XML RPC dispatcher that translates incoming RPC calls over XML into RPC events. """ - try: from xmlrpc.client import dumps, loads, Fault -except ImportError: - from xmlrpclib import dumps, loads, Fault # NOQA +except ImportError: # pragma: no cover + from xmlrpclib import dumps, loads, Fault -from circuits.six import binary_type -from circuits import handler, Event, BaseComponent +from circuits import BaseComponent, Event, handler class rpc(Event): + """rpc Event""" @@ -43,17 +38,15 @@ data = req.body.read() params, method = loads(data) - if "." in method: - channel, name = method.split(".", 1) - else: - channel, name = self.rpc_channel, method - - name = str(name) if not isinstance(name, binary_type) else name + if not isinstance(method, (str, bytes, type(u''))): + method = str(method) + if not isinstance(method, bytes) and str is bytes: # Python 2 + method = method.encode(self.encoding) - value = yield self.call(rpc.create(name, *params), channel) + value = yield self.call(rpc.create(method, *params), self.rpc_channel) yield self._response(value.value) - except Exception as e: - yield self._error(1, "%s: %s" % (type(e), e)) + except Exception as exc: + yield self._error(1, "%s: %s" % (type(exc).__name__, exc)) finally: event.stop() diff -Nru circuits-3.1.0+ds1/circuits/web/errors.py circuits-3.2.2/circuits/web/errors.py --- circuits-3.1.0+ds1/circuits/web/errors.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/circuits/web/errors.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,32 +1,30 @@ -# Module: errors -# Date: 11th February 2009 -# Author: James Mills, prologic at shortcircuit dot net dot au - """Errors This module implements a set of standard HTTP Errors. """ - -from cgi import escape - -try: - from urllib.parse import urljoin as _urljoin -except ImportError: - from urlparse import urljoin as _urljoin # NOQA +import json +import traceback from circuits import Event from ..six import string_types -from .constants import SERVER_URL, SERVER_VERSION -from .constants import DEFAULT_ERROR_MESSAGE, HTTP_STATUS_CODES +from .constants import ( + DEFAULT_ERROR_MESSAGE, HTTP_STATUS_CODES, POWERED_BY, SERVER_URL, + SERVER_VERSION, +) + +try: + from html import escape +except ImportError: + from cgi import escape # Deprecated since version 3.2 class httperror(Event): + """An event for signaling an HTTP error""" code = 500 description = "" - contenttype = "text/html" def __init__(self, request, response, code=None, **kwargs): """ @@ -51,8 +49,9 @@ ) if self.error is not None: + stack = self.error[2] if isinstance(self.error[2], (list, tuple)) else traceback.format_tb(self.error[2]) self.traceback = "ERROR: (%s) %s\n%s" % ( - self.error[0], self.error[1], "".join(self.error[2]) + self.error[0], self.error[1], "".join(stack) ) else: self.traceback = "" @@ -60,15 +59,17 @@ self.response.close = True self.response.status = self.code - self.response.headers["Content-Type"] = self.contenttype + powered_by = POWERED_BY % { + "url": escape(SERVER_URL, True), + "version": escape(SERVER_VERSION) + } if getattr(request.server, 'display_banner', False) else "" self.data = { "code": self.code, "name": HTTP_STATUS_CODES.get(self.code, "???"), "description": self.description, - "traceback": escape(self.traceback), - "url": SERVER_URL, - "version": SERVER_VERSION + "traceback": self.traceback, + "powered_by": powered_by } def sanitize(self): @@ -78,7 +79,24 @@ def __str__(self): self.sanitize() - return DEFAULT_ERROR_MESSAGE % self.data + + if self.code < 200 or self.code in (204, 205, 304): + return '' + + if "json" in self.response.headers.get("Content-Type", ""): + index = ["code", "name", "description"] + if self.request.print_debug: + index.append("traceback") + return json.dumps(dict((key, self.data[key]) for key in index)) + + if not self.request.print_debug: + self.data["traceback"] = '' + + # FIXME: description is a possible XSS attack vector + return DEFAULT_ERROR_MESSAGE % { + key: (escape(value, True) if key not in ('powered_by', 'description') and not isinstance(value, (int, float)) else value) + for key, value in self.data.items() + } def __repr__(self): return "<%s %d %s>" % ( @@ -89,24 +107,28 @@ class forbidden(httperror): + """An event for signaling the HTTP Forbidden error""" code = 403 class unauthorized(httperror): + """An event for signaling the HTTP Unauthorized error""" code = 401 class notfound(httperror): + """An event for signaling the HTTP Not Fouond error""" code = 404 class redirect(httperror): + """An event for signaling the HTTP Redirect response""" def __init__(self, request, response, urls, code=None): @@ -144,7 +166,7 @@ super(redirect, self).__init__(request, response, code) - if code in (300, 301, 302, 303, 307): + if code in (300, 301, 302, 303, 307, 308): response.headers["Content-Type"] = "text/html" # "The ... URI SHOULD be given by the Location field # in the response." @@ -155,15 +177,17 @@ # new URI(s)." msg = {300: "This resource can be found at %s.", 301: ("This resource has permanently moved to " - "%s."), + '%s.'), 302: ("This resource resides temporarily at " - "%s."), + '%s.'), 303: ("This resource can be found at " - "%s."), + '%s.'), 307: ("This resource has moved temporarily to " - "%s."), + '%s.'), + 308: ("This resource has permanently moved to " + '%s.'), }[code] - response.body = "
    \n".join([msg % (u, u) for u in urls]) + response.body = "
    \n".join([msg % (escape(u, True), escape(u)) for u in urls]) # Previous code may have set C-L, so we have to reset it # (allow finalize to set it). response.headers.pop("Content-Length", None) diff -Nru circuits-3.1.0+ds1/circuits/web/events.py circuits-3.2.2/circuits/web/events.py --- circuits-3.1.0+ds1/circuits/web/events.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/circuits/web/events.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,18 +1,12 @@ -# Module: events -# Date: 3rd February 2009 -# Author: James Mills, prologic at shortcircuit dot net dot au - - """Events This module implements the necessary Events needed. """ - - from circuits import Event class request(Event): + """request(Event) -> request Event args: request, response @@ -24,6 +18,7 @@ class response(Event): + """response(Event) -> response Event args: request, response @@ -35,6 +30,7 @@ class stream(Event): + """stream(Event) -> stream Event args: request, response @@ -46,4 +42,5 @@ class terminate(Event): + """terminate Event""" diff -Nru circuits-3.1.0+ds1/circuits/web/exceptions.py circuits-3.2.2/circuits/web/exceptions.py --- circuits-3.1.0+ds1/circuits/web/exceptions.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/circuits/web/exceptions.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,20 +1,16 @@ -# Module: exceptions -# Date: 10th July 2010 -# Author: James Mills, prologic at shortcircuit dot net dot au - """Exceptions This module implements a set of standard HTTP Errors as Python Exceptions. Note: This code is mostly borrowed from werkzeug and adapted for circuits.web """ - from inspect import isclass from .constants import HTTP_STATUS_CODES class HTTPException(Exception): + """ Baseclass for all HTTP exceptions. This exception can be called by WSGI applications to render a default error page or you can catch the subclasses @@ -38,10 +34,11 @@ return HTTP_STATUS_CODES.get(self.code, '') def __repr__(self): - return '<%s \'%s\'>' % (self.__class__.__name__, self) + return '<%s %r>' % (self.__class__.__name__, str(self)) class BadRequest(HTTPException): + """*400* `Bad Request` Raise if the browser sends something to the application the application @@ -55,6 +52,7 @@ class UnicodeError(HTTPException): + """ raised by the request functions if they were unable to decode the incoming data properly. @@ -62,6 +60,7 @@ class Unauthorized(HTTPException): + """*401* `Unauthorized` Raise if the user is not authorized. Also used if you want to use HTTP @@ -79,6 +78,7 @@ class Forbidden(HTTPException): + """*403* `Forbidden` Raise if the user doesn't have the permission for the requested resource @@ -92,6 +92,7 @@ class NotFound(HTTPException): + """*404* `Not Found` Raise if a resource does not exist and never existed. @@ -105,6 +106,7 @@ class MethodNotAllowed(HTTPException): + """*405* `Method Not Allowed` Raise if the server used a method the resource does not handle. For @@ -126,6 +128,7 @@ class NotAcceptable(HTTPException): + """*406* `Not Acceptable` Raise if the server can't return any content conforming to the @@ -142,6 +145,7 @@ class RequestTimeout(HTTPException): + """*408* `Request Timeout` Raise to signalize a timeout. @@ -154,6 +158,7 @@ class Gone(HTTPException): + """*410* `Gone` Raise if a resource existed previously and went away without new location. @@ -167,6 +172,7 @@ class LengthRequired(HTTPException): + """*411* `Length Required` Raise if the browser submitted data but no ``Content-Length`` header which @@ -180,6 +186,7 @@ class PreconditionFailed(HTTPException): + """*412* `Precondition Failed` Status code used in combination with ``If-Match``, ``If-None-Match``, or @@ -193,6 +200,7 @@ class RequestEntityTooLarge(HTTPException): + """*413* `Request Entity Too Large` The status code one should return if the data submitted exceeded a given @@ -205,6 +213,7 @@ class RequestURITooLarge(HTTPException): + """*414* `Request URI Too Large` Like *413* but for too long URLs. @@ -217,6 +226,7 @@ class UnsupportedMediaType(HTTPException): + """*415* `Unsupported Media Type` The status code returned if the server is unable to handle the media type @@ -230,6 +240,7 @@ class RangeUnsatisfiable(HTTPException): + """*416* `Range Unsatisfiable` The status code returned if the server is unable to satisfy the request range @@ -242,6 +253,7 @@ class InternalServerError(HTTPException): + """*500* `Internal Server Error` Raise if an internal server error occurred. This is a good fallback if an @@ -256,6 +268,7 @@ class NotImplemented(HTTPException): + """*501* `Not Implemented` Raise if the application does not support the action requested by the @@ -269,6 +282,7 @@ class BadGateway(HTTPException): + """*502* `Bad Gateway` If you do proxying in your application you should return this status code @@ -283,6 +297,7 @@ class ServiceUnavailable(HTTPException): + """*503* `Service Unavailable` Status code you should return if a service is temporarily unavailable. @@ -309,6 +324,7 @@ self.status = status + __all__ = [ x[0] for x in list(globals().items()) if isclass(x[1]) and issubclass(x[1], HTTPException) diff -Nru circuits-3.1.0+ds1/circuits/web/headers.py circuits-3.2.2/circuits/web/headers.py --- circuits-3.1.0+ds1/circuits/web/headers.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/circuits/web/headers.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,17 +1,13 @@ -# Module: headers -# Date: 1st February 2009 November 2008 -# Author: James Mills, prologic at shortcircuit dot net dot au - """Headers Support This module implements support for parsing and handling headers. """ - import re -from circuits.six import iteritems, u, b + +from circuits.six import b, iteritems, u # Regular expression that matches `special' characters in parameters, the -# existance of which force quoting of the parameter value. +# existence of which force quoting of the parameter value. tspecials = re.compile(r'[ \(\)<>@,;:\\"/\[\]\?=]') q_separator = re.compile(r'; *q *=') @@ -54,6 +50,7 @@ class HeaderElement(object): + """An element (with parameters) from an HTTP header's element list.""" def __init__(self, value, params=None): @@ -107,6 +104,7 @@ class AcceptElement(HeaderElement): + """An element (with parameters) from an Accept* header's element list. AcceptElement objects are comparable; the more-preferred object will be @@ -151,6 +149,7 @@ class CaseInsensitiveDict(dict): + """A case-insensitive dict subclass. Each key is changed on entry to str(key).title(). @@ -201,6 +200,26 @@ class Headers(CaseInsensitiveDict): + """ + This class implements a storage for headers as key value pairs. + The underlying model of a case insensitive dict matches the requirements + for headers quite well, because usually header keys are unique. If + several values may be associated with a header key, most HTTP headers + represent the values as an enumeration using a comma as item separator. + + There is, however one exception (currently) to this rule. In order to + set several cookies, there should be multiple headers with the same + key, each setting one cookie ("Set-Cookie: some_cookie"). + + This is modeled by having either a string (common case) or a list + (cookie case) as value in the underlying dict. In order to allow + easy iteration over all headers as they appear in the HTTP request, + the items() method expands associated lists of values. So if you have + { "Set-Cookie": [ "cookie1", "cookie2" ] }, the items() method returns + the two pairs ("Set-Cookie", "cookie1") and ("Set-Cookie", "cookie2"). + This is convenient for most use cases. The only drawback is that + len(keys()) is not equal to len(items()) for this specialized dict. + """ def elements(self, key): """Return a sorted list of HeaderElements for the given header.""" @@ -208,7 +227,10 @@ def get_all(self, name): """Return a list of all the values for the named field.""" - return [val.strip() for val in self.get(name, '').split(',')] + value = self.get(name, '') + if isinstance(value, list): + return value + return [val.strip() for val in value.split(',')] def __repr__(self): return "Headers(%s)" % repr(list(self.items())) @@ -217,14 +239,36 @@ headers = ["%s: %s\r\n" % (k, v) for k, v in self.items()] return "".join(headers) + '\r\n' + def items(self): + for k, v in super(Headers, self).items(): + if isinstance(v, list): + for vv in v: + yield (str(k), str(vv)) + else: + yield (str(k), str(v)) + def __bytes__(self): return str(self).encode("latin1") def append(self, key, value): - if not key in self: - self[key] = value + """ + If a header with the given name already exists, the value is + normally appended to the existing value separated by a comma. + + If, however, the already existing entry associated key with a + value of type list (as is the case for "Set-Cookie"), + the new value is appended to that list. + """ + if key not in self: + if key.lower() == "set-cookie": + self[key] = [value] + else: + self[key] = value else: - self[key] = ", ".join([self[key], value]) + if isinstance(self[key], list): + self[key].append(value) + else: + self[key] = ", ".join([self[key], value]) def add_header(self, _name, _value, **_params): """Extended header setting. diff -Nru circuits-3.1.0+ds1/circuits/web/_httpauth.py circuits-3.2.2/circuits/web/_httpauth.py --- circuits-3.1.0+ds1/circuits/web/_httpauth.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/circuits/web/_httpauth.py 2021-10-19 16:23:49.000000000 +0000 @@ -21,6 +21,19 @@ SUPPORTED_ALGORITHM - list of supported 'Digest' algorithms SUPPORTED_QOP - list of supported 'Digest' 'qop'. """ +import time +from hashlib import md5, sha1 + +try: + from base64 import decodebytes as base64_decodebytes +except ImportError: + from base64 import b64decode as base64_decodebytes # NOQA + +try: + from urllib.request import parse_http_list, parse_keqv_list +except ImportError: + from urllib2 import parse_http_list, parse_keqv_list # NOQA + __version__ = 1, 0, 1 __author__ = "Tiago Cogumbreiro " __credits__ = """ @@ -62,21 +75,9 @@ "calculateNonce", "SUPPORTED_QOP") ############################################################################### -import time - -try: - from base64 import decodebytes as base64_decodebytes -except ImportError: - from base64 import b64decode as base64_decodebytes # NOQA - -try: - from urllib.request import parse_http_list, parse_keqv_list -except ImportError: - from urllib2 import parse_http_list, parse_keqv_list # NOQA - -from hashlib import md5 MD5 = "MD5" +SHA1 = "SHA1" MD5_SESS = "MD5-sess" AUTH = "auth" AUTH_INT = "auth-int" @@ -90,7 +91,7 @@ DIGEST_AUTH_ENCODERS = { MD5: lambda val: md5(val).hexdigest(), MD5_SESS: lambda val: md5(val).hexdigest(), -# SHA: lambda val: sha.new (val).hexdigest (), + SHA1: lambda val: sha1.new(val).hexdigest(), } @@ -98,7 +99,6 @@ """This is an auxaliary function that calculates 'nonce' value. It is used to handle sessions.""" - global SUPPORTED_ALGORITHM, DIGEST_AUTH_ENCODERS assert algorithm in SUPPORTED_ALGORITHM try: @@ -115,7 +115,7 @@ def digestAuth(realm, algorithm=MD5, nonce=None, qop=AUTH): """Challenges the client for a Digest authentication.""" - global SUPPORTED_ALGORITHM, DIGEST_AUTH_ENCODERS, SUPPORTED_QOP + assert algorithm in SUPPORTED_ALGORITHM assert qop in SUPPORTED_QOP @@ -178,6 +178,7 @@ password = password.decode("utf-8") return {"username": username, "password": password} + AUTH_SCHEMES = { "basic": _parseBasicAuthorization, "digest": _parseDigestAuthorization, @@ -189,8 +190,6 @@ the HTTP header to a map itself. If the parsing fails 'None' is returned. """ - global AUTH_SCHEMES - auth_scheme, auth_params = credentials.split(" ", 1) auth_scheme = auth_scheme.lower() @@ -361,6 +360,7 @@ except TypeError: return encrypt(auth_map["password"]) == password + AUTH_RESPONSES = { "basic": _checkBasicResponse, "digest": _checkDigestResponse, @@ -384,7 +384,7 @@ The 'A1' argument is only used in MD5_SESS algorithm based responses. Check md5SessionKey() for more info. """ - global AUTH_RESPONSES + checker = AUTH_RESPONSES[auth_map["auth_scheme"]] return checker( auth_map, password, method=method, encrypt=encrypt, **kwargs diff -Nru circuits-3.1.0+ds1/circuits/web/http.py circuits-3.2.2/circuits/web/http.py --- circuits-3.1.0+ds1/circuits/web/http.py 2014-10-05 23:16:30.000000000 +0000 +++ circuits-3.2.2/circuits/web/http.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,47 +1,29 @@ -# Module: http -# Date: 13th September 2007 -# Author: James Mills, prologic at shortcircuit dot net dot au - - """Hyper Text Transfer Protocol This module implements the server side Hyper Text Transfer Protocol or commonly known as HTTP. """ - - from io import BytesIO +from socket import socket -try: - from urllib.parse import quote - from urllib.parse import urlparse, urlunparse -except ImportError: - from urllib import quote # NOQA - from urlparse import urlparse, urlunparse # NOQA - - -from circuits.six import text_type +from circuits.core import BaseComponent, Value, handler from circuits.net.events import close, write -from circuits.core import handler, BaseComponent, Value +from circuits.net.utils import is_ssl_handshake +from circuits.six import text_type +from circuits.six.moves.urllib_parse import quote from . import wrappers -from .url import parse_url -from .utils import is_ssl_handshake -from .exceptions import HTTPException -from .events import request, response, stream -from .parsers import HttpParser, BAD_FIRST_LINE +from .constants import SERVER_PROTOCOL, SERVER_VERSION from .errors import httperror, notfound, redirect -from .exceptions import Redirect as RedirectException -from .constants import SERVER_VERSION, SERVER_PROTOCOL +from .events import request, response, stream +from .exceptions import HTTPException, Redirect as RedirectException +from .parsers import BAD_FIRST_LINE, HttpParser +from .url import parse_url +from .utils import is_unix_socket MAX_HEADER_FRAGENTS = 20 HTTP_ENCODING = 'utf-8' -try: - unicode -except NameError: - unicode = str - class HTTP(BaseComponent): """HTTP Protocol Component @@ -69,15 +51,7 @@ self._server = server self._encoding = encoding - url = "{0:s}://{1:s}{2:s}".format( - (server.secure and "https") or "http", - server.host or "0.0.0.0", - ":{0:d}".format(server.port or 80) - if server.port not in (80, 443) - else "" - ) - self.uri = parse_url(url) - + self._uri = None self._clients = {} self._buffers = {} @@ -91,16 +65,33 @@ @property def scheme(self): - if not hasattr(self, "_server"): - return return "https" if self._server.secure else "http" @property def base(self): - if not hasattr(self, "uri"): - return + if self.uri is None: + return "" return self.uri.utf8().rstrip(b"/").decode(self._encoding) + @property + def uri(self): + return self._uri + + @handler("ready", priority=1.0) + def _on_ready(self, server, bind): + if is_unix_socket(server.host): + url = server.host + else: + url = "{}://{}{}".format( + (server.secure and "https") or "http", + server.host or "0.0.0.0", + ":{0:d}".format(server.port or 80) + if server.port not in (80, 443) + else "" + ) + + self._uri = parse_url(url) + @handler("stream") # noqa def _on_stream(self, res, data): sock = res.request.sock @@ -289,7 +280,7 @@ res.close = not parser.should_keep_alive() clen = int(req.headers.get("Content-Length", "0")) - if clen and not parser.is_message_complete(): + if (clen or req.headers.get("Transfer-Encoding") == "chunked") and not parser.is_message_complete(): return if hasattr(sock, "getpeercert"): @@ -301,6 +292,10 @@ else: e = request(req, res) + if req.protocol != (1, 0) and not req.headers.get("Host"): + del self._buffers[sock] + return self.fire(httperror(req, res, 400, description="No host header defined")) + # Guard against unwanted request paths (SECURITY). path = req.path _path = req.uri._path @@ -442,8 +437,13 @@ req = res.request elif isinstance(fevent.value.parent.event, request): req, res = fevent.value.parent.event.args[:2] - else: + elif len(fevent.args[2:]) == 4: req, res = fevent.args[2:] + elif len(fevent.args) == 2 and isinstance(fevent.args[0], socket): + req = wrappers.Request(fevent.args[0], server=self._server) + res = wrappers.Response(req, self._encoding, 500) + else: + return if isinstance(evalue, HTTPException): code = evalue.code diff -Nru circuits-3.1.0+ds1/circuits/web/__init__.py circuits-3.2.2/circuits/web/__init__.py --- circuits-3.1.0+ds1/circuits/web/__init__.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/circuits/web/__init__.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,21 +1,16 @@ -# Module: __init__ -# Date: 3rd October 2008 -# Author: James Mills, prologic at shortcircuit dot net dot au - """Circuits Library - Web circuits.web contains the circuits full stack web server that is HTTP and WSGI compliant. """ - +from .controllers import BaseController, Controller, expose +from .dispatchers import XMLRPC, Dispatcher, Static, VirtualHosts +from .errors import forbidden, httperror, notfound, redirect +from .events import request, response, stream from .loggers import Logger -from .sessions import Sessions -from .url import parse_url, URL from .servers import BaseServer, Server -from .controllers import expose, Controller -from .events import request, response, stream -from .errors import httperror, forbidden, notfound, redirect -from .dispatchers import Static, Dispatcher, VirtualHosts, XMLRPC +from .sessions import Sessions +from .url import URL, parse_url try: from .dispatchers import JSONRPC @@ -28,3 +23,4 @@ pass # flake8: noqa +# pylama: skip=1 diff -Nru circuits-3.1.0+ds1/circuits/web/loggers.py circuits-3.2.2/circuits/web/loggers.py --- circuits-3.1.0+ds1/circuits/web/loggers.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/circuits/web/loggers.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,35 +1,25 @@ -# Module: loggers -# Date: 6th November 2008 -# Author: James Mills, prologic at shortcircuit dot net dot au - """Logger Component This module implements Logger Components. """ - +import datetime import os import sys -import datetime from io import IOBase -from email._parseaddr import _monthnames -from circuits.six import string_types -from circuits.core import handler, BaseComponent +from circuits.core import BaseComponent, handler +from circuits.six import string_types, text_type def formattime(): - now = datetime.datetime.now() - month = _monthnames[now.month - 1].capitalize() - return ("[%02d/%s/%04d:%02d:%02d:%02d]" % - (now.day, month, now.year, now.hour, now.minute, now.second)) + return datetime.datetime.now().strftime('[%d/%b/%Y:%H:%M:%S]') class Logger(BaseComponent): channel = "web" - format = "%(h)s %(l)s %(u)s %(t)s " \ - "\"%(r)s\" %(s)s %(b)s \"%(f)s\" \"%(a)s\"" + format = '%(h)s %(l)s %(u)s %(t)s "%(r)s" %(s)s %(b)s "%(f)s" "%(a)s"' def __init__(self, file=None, logger=None, **kwargs): super(Logger, self).__init__(**kwargs) @@ -69,7 +59,7 @@ "a": inheaders.get("User-Agent", ""), } for k, v in list(atoms.items()): - if isinstance(v, str): + if isinstance(v, text_type): v = v.encode("utf8") elif not isinstance(v, str): v = str(v) @@ -77,7 +67,7 @@ # and backslash for us. All we have to do is strip the quotes. v = repr(v)[1:-1] # Escape double-quote. - atoms[k] = v.replace("\"", "\\\"") + atoms[k] = v.replace('"', '\\"') if self.logger is not None: self.logger.info(self.format % atoms) diff -Nru circuits-3.1.0+ds1/circuits/web/main.py circuits-3.2.2/circuits/web/main.py --- circuits-3.1.0+ds1/circuits/web/main.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/circuits/web/main.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,19 +1,23 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- - - """Main circutis.web Web Server and Testing Tool. """ - - import os -from sys import stderr from hashlib import md5 from optparse import OptionParser -from wsgiref.validate import validator +from sys import stderr from wsgiref.simple_server import make_server +from wsgiref.validate import validator + +import circuits +from circuits import Component, Debugger, Manager, handler +from circuits.core.pollers import Select +from circuits.tools import graph, inspect +from circuits.web import BaseServer, Controller, Logger, Server, Static +from circuits.web.tools import check_auth, digest_auth +from circuits.web.wsgi import Application try: import hotshot @@ -22,16 +26,6 @@ hostshot = None -import circuits -from circuits import handler, Component, Manager, Debugger - -from circuits.core.pollers import Select -from circuits.tools import inspect, graph - -from circuits.web.wsgi import Application -from circuits.web.tools import check_auth, digest_auth -from circuits.web import BaseServer, Controller, Logger, Server, Static - try: from circuits.core.pollers import Poll except ImportError: diff -Nru circuits-3.1.0+ds1/circuits/web/parsers/http.py circuits-3.2.2/circuits/web/parsers/http.py --- circuits-3.1.0+ds1/circuits/web/parsers/http.py 2014-09-20 22:36:35.000000000 +0000 +++ circuits-3.2.2/circuits/web/parsers/http.py 2021-10-19 16:23:49.000000000 +0000 @@ -3,31 +3,20 @@ # This file is part of http-parser released under the MIT license. # See the NOTICE for more information. # -# This module is liberally borrowed (with modifications) from: https://raw.githubusercontent.com/benoitc/http-parser/master/http_parser/pyparser.py - - +# This module is liberally borrowed (with modifications) from: +# https://raw.githubusercontent.com/benoitc/http-parser/master/http_parser/pyparser.py import re import zlib - -try: - import urlparse - from urllib import unquote -except ImportError: - import urllib.parse as urlparse # NOQA - from urllib.parse import unquote # NOQA - - -from circuits.six import b, bytes_to_str, MAXSIZE - +from circuits.six import MAXSIZE, PY3 +from circuits.six.moves.urllib_parse import urlsplit from ..headers import Headers - METHOD_RE = re.compile("^[A-Z0-9$-_.]{1,20}$") -VERSION_RE = re.compile("^HTTP/(\d+).(\d+)$") -STATUS_RE = re.compile("^(\d{3})(?:\s+([\s\w]*))$") -HEADER_RE = re.compile("[\x00-\x1F\x7F()<>@,;:/\[\]={} \t\\\\\"]") +VERSION_RE = re.compile(r"^HTTP/(\d+).(\d+)$") +STATUS_RE = re.compile(r"^(\d{3})(?:\s+([\s\w]*))$") +HEADER_RE = re.compile('[\\x00-\\x1F\\x7F()<>@,;:/\\[\\]={} \\t\\\\"]') # errors BAD_FIRST_LINE = 0 @@ -36,14 +25,17 @@ class InvalidRequestLine(Exception): + """ error raised when first line is invalid """ class InvalidHeader(Exception): + """ error raised on invalid header """ class InvalidChunkSize(Exception): + """ error raised when we parse an invalid chunk size """ @@ -83,6 +75,7 @@ self.__on_message_complete = False self.__decompress_obj = None + self.__decompress_first_try = True def get_version(self): return self._version @@ -110,17 +103,17 @@ def recv_body(self): """ return last chunk of the parsed body""" - body = b("").join(self._body) + body = b"".join(self._body) self._body = [] self._partial_body = False return body def recv_body_into(self, barray): - """ Receive the last chunk of the parsed bodyand store the data + """ Receive the last chunk of the parsed body and store the data in a buffer rather than creating a new string. """ - l = len(barray) - body = b("").join(self._body) - m = min(len(body), l) + length = len(barray) + body = b"".join(self._body) + m = min(len(body), length) data, rest = body[:m], body[m:] barray[0:m] = data if not rest: @@ -133,7 +126,9 @@ def is_upgrade(self): """ Do we get upgrade header in the request. Useful for websockets """ - return self._headers.get('connection', "").lower() == "upgrade" + hconn = self._headers.get('connection', "").lower() + hconn_parts = [x.strip() for x in hconn.split(',')] + return "upgrade" in hconn_parts def is_headers_complete(self): """ return True if all headers have been parsed. """ @@ -169,25 +164,27 @@ # end of body can be passed manually by putting a length of 0 if length == 0: - self.on_message_complete = True + self.__on_message_complete = True return length # start to parse nb_parsed = 0 while True: if not self.__on_firstline: - idx = data.find(b("\r\n")) + idx = data.find(b"\r\n") if idx < 0: self._buf.append(data) return len(data) else: self.__on_firstline = True self._buf.append(data[:idx]) - first_line = bytes_to_str(b("").join(self._buf)) + first_line = b"".join(self._buf) + if PY3: + first_line = str(first_line, 'unicode_escape') nb_parsed = nb_parsed + idx + 2 - rest = data[idx+2:] - data = b("") + rest = data[idx + 2:] + data = b"" if self._parse_firstline(first_line): self._buf = [rest] else: @@ -195,12 +192,13 @@ elif not self.__on_headers_complete: if data: self._buf.append(data) - data = b("") + data = b"" try: - to_parse = b("").join(self._buf) + to_parse = b"".join(self._buf) ret = self._parse_headers(to_parse) - if not ret: + + if ret is False: return length nb_parsed = nb_parsed + (len(to_parse) - ret) except InvalidHeader as e: @@ -213,7 +211,7 @@ if data: self._buf.append(data) - data = b("") + data = b"" ret = self._parse_body() if ret is None: @@ -261,7 +259,7 @@ # status matchs = STATUS_RE.match(bits[1]) if matchs is None: - raise InvalidRequestLine("Invalid status %" % bits[1]) + raise InvalidRequestLine("Invalid status: {!r}".format(bits[1])) self._status = bits[1] self._status_code = int(matchs.group(1)) @@ -279,7 +277,7 @@ # URI self._url = bits[1] - parts = urlparse.urlsplit(bits[1]) + parts = urlsplit(bits[1]) self._scheme = parts.scheme or None self._path = parts.path or "" self._query_string = parts.query or "" @@ -295,7 +293,7 @@ self._version = (int(match.group(1)), int(match.group(2))) # update environ - if hasattr(self, 'environ'): + if hasattr(self, '_environ'): self._environ.update({ "PATH_INFO": self._path, "QUERY_STRING": self._query_string, @@ -304,13 +302,22 @@ "SERVER_PROTOCOL": bits[2]}) def _parse_headers(self, data): - idx = data.find(b("\r\n\r\n")) + if data == b'\r\n': + self.__on_headers_complete = True + self._buf = [] + return 0 + idx = data.find(b"\r\n\r\n") if idx < 0: # we don't have all headers - return False + if self._status_code == 204 and data == b"\r\n": + self._buf = [] + self.__on_headers_complete = True + return 0 + else: + return False # Split lines on \r\n keeping the \r\n on each line - lines = [bytes_to_str(line) + "\r\n" - for line in data[:idx].split(b("\r\n"))] + lines = [(str(line, 'unicode_escape') if PY3 else line) + "\r\n" + for line in data[:idx].split(b"\r\n")] # Parse headers into key/value pairs paying attention # to continuation lines. @@ -323,11 +330,18 @@ name = name.rstrip(" \t").upper() if HEADER_RE.search(name): raise InvalidHeader("invalid header name %s" % name) + + if value.endswith("\r\n"): + value = value[:-2] + name, value = name.strip(), [value.lstrip()] # Consume value continuation lines while len(lines) and lines[0].startswith((" ", "\t")): - value.append(lines.pop(0)) + curr = lines.pop(0) + if curr.endswith("\r\n"): + curr = curr[:-2] + value.append(curr) value = ''.join(value).rstrip() # store new header value @@ -355,23 +369,39 @@ encoding = self._headers.get('content-encoding') if self.decompress: if encoding == "gzip": - self.__decompress_obj = zlib.decompressobj(16+zlib.MAX_WBITS) + self.__decompress_obj = zlib.decompressobj(16 + zlib.MAX_WBITS) + self.__decompress_first_try = False elif encoding == "deflate": self.__decompress_obj = zlib.decompressobj() - rest = data[idx+4:] + rest = data[idx + 4:] self._buf = [rest] self.__on_headers_complete = True return len(rest) def _parse_body(self): - if not self._chunked: - body_part = b("").join(self._buf) + if self._status_code == 204 and len(self._buf) == 0: + self.__on_message_complete = True + return + elif not self._chunked: + body_part = b"".join(self._buf) + if not body_part and self._clen is None: + if not self._status: # message complete only for servers + self.__on_message_complete = True + return self._clen_rest -= len(body_part) # maybe decompress if self.__decompress_obj is not None: - body_part = self.__decompress_obj.decompress(body_part) + if not self.__decompress_first_try: + body_part = self.__decompress_obj.decompress(body_part) + else: + try: + body_part = self.__decompress_obj.decompress(body_part) + except zlib.error: + self.__decompress_obj.decompressobj = zlib.decompressobj(-zlib.MAX_WBITS) + body_part = self.__decompress_obj.decompress(body_part) + self.__decompress_first_try = False self._partial_body = True self._body.append(body_part) @@ -381,7 +411,7 @@ self.__on_message_complete = True return else: - data = b("").join(self._buf) + data = b"".join(self._buf) try: size, rest = self._parse_chunk_size(data) @@ -413,11 +443,11 @@ return len(rest) def _parse_chunk_size(self, data): - idx = data.find(b("\r\n")) + idx = data.find(b"\r\n") if idx < 0: return None, None - line, rest_chunk = data[:idx], data[idx+2:] - chunk_size = line.split(b(";"), 1)[0].strip() + line, rest_chunk = data[:idx], data[idx + 2:] + chunk_size = line.split(b";", 1)[0].strip() try: chunk_size = int(chunk_size, 16) except ValueError: @@ -429,7 +459,7 @@ return chunk_size, rest_chunk def _parse_trailers(self, data): - idx = data.find(b("\r\n\r\n")) + idx = data.find(b"\r\n\r\n") - if data[:2] == b("\r\n"): + if data[:2] == b"\r\n": self._trailers = self._parse_headers(data[:idx]) diff -Nru circuits-3.1.0+ds1/circuits/web/parsers/__init__.py circuits-3.2.2/circuits/web/parsers/__init__.py --- circuits-3.1.0+ds1/circuits/web/parsers/__init__.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/circuits/web/parsers/__init__.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,11 +1,8 @@ -# Package: parsers -# Date: 26th March 2013 -# Author: James Mills, prologic at shortcircuit dot net dot au - """circuits.web parsers""" +from .http import BAD_FIRST_LINE, HttpParser from .multipart import MultipartParser from .querystring import QueryStringParser -from .http import HttpParser, BAD_FIRST_LINE # flake8: noqa +# pylama: skip=1 diff -Nru circuits-3.1.0+ds1/circuits/web/parsers/multipart.py circuits-3.2.2/circuits/web/parsers/multipart.py --- circuits-3.1.0+ds1/circuits/web/parsers/multipart.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/circuits/web/parsers/multipart.py 2021-10-19 16:23:49.000000000 +0000 @@ -37,19 +37,18 @@ __version__ = '0.1' __license__ = 'MIT' +import re from tempfile import TemporaryFile from wsgiref.headers import Headers -import re, sys -try: - from urlparse import parse_qs -except ImportError: # pragma: no cover (fallback for Python 2.5) - from cgi import parse_qs + +from circuits.six import text_type +from circuits.six.moves.urllib_parse import parse_qs + try: from io import BytesIO -except ImportError: # pragma: no cover (fallback for Python 2.5) +except ImportError: # pragma: no cover (fallback for Python 2.5) from StringIO import StringIO as BytesIO -from circuits.six import text_type ############################################################################## ################################ Helper & Misc ################################ @@ -57,28 +56,52 @@ # Some of these were copied from bottle: http://bottle.paws.de/ try: - from collections import MutableMapping as DictMixin -except ImportError: # pragma: no cover (fallback for Python 2.5) - from UserDict import DictMixin + from collections.abc import MutableMapping +except ImportError: # pragma: no cover (fallback for Python 2.5) + try: + from collections import MutableMapping + except ImportError: # pragma: no cover (fallback for Python 2.5) + from UserDict import DictMixin as MutableMapping + + +class MultiDict(MutableMapping): -class MultiDict(DictMixin): """ A dict that remembers old values for each key """ + def __init__(self, *a, **k): self.dict = dict() for k, v in dict(*a, **k).iteritems(): self[k] = v - def __len__(self): return len(self.dict) - def __iter__(self): return iter(self.dict) - def __contains__(self, key): return key in self.dict - def __delitem__(self, key): del self.dict[key] - def keys(self): return self.dict.keys() - def __getitem__(self, key): return self.get(key, KeyError, -1) - def __setitem__(self, key, value): self.append(key, value) - - def append(self, key, value): self.dict.setdefault(key, []).append(value) - def replace(self, key, value): self.dict[key] = [value] - def getall(self, key): return self.dict.get(key) or [] + def __len__(self): + return len(self.dict) + + def __iter__(self): + return iter(self.dict) + + def __contains__(self, key): + return key in self.dict + + def __delitem__(self, key): + del self.dict[key] + + def keys(self): + return self.dict.keys() + + def __getitem__(self, key): + return self.get(key, KeyError, -1) + + def __setitem__(self, key, value): + self.append(key, value) + + def append(self, key, value): + self.dict.setdefault(key, []).append(value) + + def replace(self, key, value): + self.dict[key] = [value] + + def getall(self, key): + return self.dict.get(key) or [] def get(self, key, default=None, index=-1): if key not in self.dict and default != KeyError: @@ -90,16 +113,20 @@ for value in values: yield key, value -def tob(data, enc='utf8'): # Convert strings to bytes (py2 and py3) + +def tob(data, enc='utf8'): # Convert strings to bytes (py2 and py3) return data.encode(enc) if isinstance(data, text_type) else data -def copy_file(stream, target, maxread=-1, buffer_size=2*16): + +def copy_file(stream, target, maxread=-1, buffer_size=2 * 16): ''' Read from :stream and write to :target until :maxread or EOF. ''' size, read = 0, stream.read while 1: - to_read = buffer_size if maxread < 0 else min(buffer_size, maxread-size) + to_read = buffer_size if maxread < 0 else min( + buffer_size, maxread - size) part = read(to_read) - if not part: return size + if not part: + return size target.write(part) size += len(part) @@ -109,24 +136,28 @@ _special = re.escape('()<>@,;:\\"/[]?={} \t') _re_special = re.compile('[%s]' % _special) -_qstr = '"(?:\\\\.|[^"])*"' # Quoted string -_value = '(?:[^%s]+|%s)' % (_special, _qstr) # Save or quoted string +_qstr = '"(?:\\\\.|[^"])*"' # Quoted string +_value = '(?:[^%s]+|%s)' % (_special, _qstr) # Save or quoted string _option = '(?:;|^)\s*([^%s]+)\s*=\s*(%s)' % (_special, _value) -_re_option = re.compile(_option) # key=value part of an Content-Type like header +# key=value part of an Content-Type like header +_re_option = re.compile(_option) + def header_quote(val): if not _re_special.search(val): return val - return '"' + val.replace('\\','\\\\').replace('"','\\"') + '"' + return '"' + val.replace('\\', '\\\\').replace('"', '\\"') + '"' + def header_unquote(val, filename=False): if val[0] == val[-1] == '"': val = val[1:-1] - if val[1:3] == ':\\' or val[:2] == '\\\\': - val = val.split('\\')[-1] # fix ie6 bug: full path --> filename - return val.replace('\\\\','\\').replace('\\"','"') + if val[1:3] == ':\\' or val[:2] == '\\\\': + val = val.split('\\')[-1] # fix ie6 bug: full path --> filename + return val.replace('\\\\', '\\').replace('\\"', '"') return val + def parse_options_header(header, options=None): if ';' not in header: return header.lower().strip(), {} @@ -134,7 +165,7 @@ options = options or {} for match in _re_option.finditer(tail): key = match.group(1).lower() - value = header_unquote(match.group(2), key=='filename') + value = header_unquote(match.group(2), key == 'filename') options[key] = value return ctype, options @@ -143,17 +174,18 @@ ############################################################################## -class MultipartError(ValueError): pass +class MultipartError(ValueError): + pass class MultipartParser(object): - + def __init__(self, stream, boundary, content_length=-1, - disk_limit=2**30, mem_limit=2**20, memfile_limit=2**18, - buffer_size=2**16, charset='latin1'): + disk_limit=2 ** 30, mem_limit=2 ** 20, memfile_limit=2 ** 18, + buffer_size=2 ** 16, charset='latin1'): ''' Parse a multipart/form-data byte stream. This object is an iterator over the parts of the message. - + :param stream: A file-like stream. Must implement ``.read(size)``. :param boundary: The multipart boundary as a byte string. :param content_length: The maximum number of bytes to read. @@ -165,11 +197,11 @@ self.mem_limit = min(mem_limit, self.disk_limit) self.buffer_size = min(buffer_size, self.mem_limit) self.charset = charset - if self.buffer_size - 6 < len(boundary): # "--boundary--\r\n" + if self.buffer_size - 6 < len(boundary): # "--boundary--\r\n" raise MultipartError('Boundary does not fit into buffer_size.') self._done = [] self._part_iter = None - + def __iter__(self): ''' Iterate over the parts of the multipart message. ''' if not self._part_iter: @@ -179,11 +211,11 @@ for part in self._part_iter: self._done.append(part) yield part - + def parts(self): ''' Returns a list with all parts of the multipart message. ''' return list(iter(self)) - + def get(self, name, default=None): ''' Return the first part with that name or a default value (None). ''' for part in self: @@ -206,18 +238,18 @@ _bcrnl = tob('\r\n') _bcr = _bcrnl[:1] _bnl = _bcrnl[1:] - _bempty = _bcrnl[:0] # b'rn'[:0] -> b'' - buffer = _bempty # buffer for the last (partial) line + _bempty = _bcrnl[:0] # b'rn'[:0] -> b'' + buffer = _bempty # buffer for the last (partial) line while 1: data = read(maxbuf if maxread < 0 else min(maxbuf, maxread)) maxread -= len(data) - lines = (buffer+data).splitlines(True) + lines = (buffer + data).splitlines(True) len_first_line = len(lines[0]) # be sure that the first line does not become too big if len_first_line > self.buffer_size: # at the same time don't split a '\r\n' accidentally - if (len_first_line == self.buffer_size+1 and - lines[0].endswith(_bcrnl)): + if (len_first_line == self.buffer_size + 1 and + lines[0].endswith(_bcrnl)): splitpos = self.buffer_size - 1 else: splitpos = self.buffer_size @@ -227,25 +259,30 @@ buffer = lines[-1] lines = lines[:-1] for line in lines: - if line.endswith(_bcrnl): yield line[:-2], _bcrnl - elif line.endswith(_bnl): yield line[:-1], _bnl - elif line.endswith(_bcr): yield line[:-1], _bcr - else: yield line, _bempty + if line.endswith(_bcrnl): + yield line[:-2], _bcrnl + elif line.endswith(_bnl): + yield line[:-1], _bnl + elif line.endswith(_bcr): + yield line[:-1], _bcr + else: + yield line, _bempty if not data: break - + def _iterparse(self): lines, line = self._lineiter(), '' separator = tob('--') + tob(self.boundary) terminator = tob('--') + tob(self.boundary) + tob('--') # Consume first boundary. Ignore leading blank lines for line, nl in lines: - if line: break + if line: + break if line != separator: raise MultipartError("Stream does not start with boundary") # For each part in stream... - mem_used, disk_used = 0, 0 # Track used resources to prevent DoS - is_tail = False # True if the last line was incomplete (cutted) + mem_used, disk_used = 0, 0 # Track used resources to prevent DoS + is_tail = False # True if the last line was incomplete (cutted) opts = {'buffer_size': self.buffer_size, 'memfile_limit': self.memfile_limit, 'charset': self.charset} @@ -256,13 +293,15 @@ yield part break elif line == separator and not is_tail: - if part.is_buffered(): mem_used += part.size - else: disk_used += part.size + if part.is_buffered(): + mem_used += part.size + else: + disk_used += part.size part.file.seek(0) yield part part = MultipartPart(**opts) else: - is_tail = not nl # The next line continues this one + is_tail = not nl # The next line continues this one part.feed(line, nl) if part.is_buffered(): if part.size + mem_used > self.mem_limit: @@ -271,11 +310,11 @@ raise MultipartError("Disk limit reached.") if line != terminator: raise MultipartError("Unexpected end of multipart stream.") - + class MultipartPart(object): - - def __init__(self, buffer_size=2**16, memfile_limit=2**18, charset='latin1'): + + def __init__(self, buffer_size=2 ** 16, memfile_limit=2 ** 18, charset='latin1'): self.headerlist = [] self.headers = None self.file = False @@ -293,12 +332,13 @@ def write_header(self, line, nl): line = line.decode(self.charset or 'latin1') - if not nl: raise MultipartError('Unexpected end of line in header.') - if not line.strip(): # blank line -> end of header segment + if not nl: + raise MultipartError('Unexpected end of line in header.') + if not line.strip(): # blank line -> end of header segment self.finish_header() elif line[0] in ' \t' and self.headerlist: name, value = self.headerlist.pop() - self.headerlist.append((name, value+line.strip())) + self.headerlist.append((name, value + line.strip())) else: if ':' not in line: raise MultipartError("Syntax error in header: No colon.") @@ -306,7 +346,8 @@ self.headerlist.append((name.strip(), value.strip())) def write_body(self, line, nl): - if not line and not nl: return # This does not even flush the buffer + if not line and not nl: + return # This does not even flush the buffer self.size += len(line) + len(self._buf) self.file.write(self._buf + line) self._buf = nl @@ -321,9 +362,9 @@ def finish_header(self): self.file = BytesIO() self.headers = Headers(self.headerlist) - cdis = self.headers.get('Content-Disposition','') - ctype = self.headers.get('Content-Type','') - clen = self.headers.get('Content-Length','-1') + cdis = self.headers.get('Content-Disposition', '') + ctype = self.headers.get('Content-Type', '') + self.headers.get('Content-Length', '-1') if not cdis: raise MultipartError('Content-Disposition header is missing.') self.disposition, self.options = parse_options_header(cdis) @@ -331,7 +372,7 @@ self.filename = self.options.get('filename') self.content_type, options = parse_options_header(ctype) self.charset = options.get('charset') or self.charset - self.content_length = int(self.headers.get('Content-Length','-1')) + self.content_length = int(self.headers.get('Content-Length', '-1')) def is_buffered(self): ''' Return true if the data is fully buffered in memory.''' @@ -345,7 +386,7 @@ val = self.file.read() self.file.seek(pos) return val.decode(self.charset) - + def save_as(self, path): fp = open(path, 'wb') pos = self.file.tell() @@ -360,6 +401,7 @@ #################################### WSGI #################################### ############################################################################## + def parse_form_data(environ, charset='utf8', strict=False, **kw): ''' Parse form data from an environ dict and return a (forms, files) tuple. Both tuple values are dictionaries with the form-field name as a key @@ -368,16 +410,16 @@ The files-dictionary contains :class:`MultipartPart` instances, either because the form-field was a file-upload or the value is to big to fit into memory limits. - + :param environ: An WSGI environment dict. :param charset: The charset to use if unsure. (default: utf8) :param strict: If True, raise :exc:`MultipartError` on any parsing errors. These are silently ignored by default. ''' - + forms, files = MultiDict(), MultiDict() try: - if environ.get('REQUEST_METHOD','GET').upper() not in ('POST', 'PUT'): + if environ.get('REQUEST_METHOD', 'GET').upper() not in ('POST', 'PUT'): raise MultipartError("Request method other than POST or PUT.") content_length = int(environ.get('CONTENT_LENGTH', '-1')) content_type = environ.get('CONTENT_TYPE', '') @@ -387,21 +429,21 @@ stream = environ.get('wsgi.input') or BytesIO() kw['charset'] = charset = options.get('charset', charset) if content_type == 'multipart/form-data': - boundary = options.get('boundary','') + boundary = options.get('boundary', '') if not boundary: raise MultipartError("No boundary for multipart/form-data.") for part in MultipartParser(stream, boundary, content_length, **kw): if part.filename or not part.is_buffered(): files[part.name] = part - else: # TODO: Big form-fields are in the files dict. really? + else: # TODO: Big form-fields are in the files dict. really? forms[part.name] = part.value elif content_type in ('application/x-www-form-urlencoded', 'application/x-url-encoded'): - mem_limit = kw.get('mem_limit', 2**20) + mem_limit = kw.get('mem_limit', 2 ** 20) if content_length > mem_limit: raise MultipartError("Request to big. Increase MAXMEM.") data = stream.read(mem_limit).decode(charset) - if stream.read(1): # These is more that does not fit mem_limit + if stream.read(1): # These is more that does not fit mem_limit raise MultipartError("Request to big. Increase MAXMEM.") data = parse_qs(data, keep_blank_values=True) for key, values in data.iteritems(): @@ -410,6 +452,6 @@ else: raise MultipartError("Unsupported content type.") except MultipartError: - if strict: raise + if strict: + raise return forms, files - diff -Nru circuits-3.1.0+ds1/circuits/web/parsers/querystring.py circuits-3.2.2/circuits/web/parsers/querystring.py --- circuits-3.1.0+ds1/circuits/web/parsers/querystring.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/circuits/web/parsers/querystring.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,13 +1,7 @@ # -*- coding: utf-8 -*- - -try: - from urlparse import parse_qsl -except ImportError: - from urllib.parse import parse_qsl # NOQA - - from circuits.six import iteritems, string_types +from circuits.six.moves.urllib_parse import parse_qsl class QueryStringToken(object): @@ -54,7 +48,7 @@ key = pair[0] value = pair[1] - #faster than invoking a regex + # faster than invoking a regex try: key.index("[") self.parse(key, value) @@ -143,5 +137,3 @@ if len(buf) > 0: yield QueryStringToken.KEY, buf - else: - raise StopIteration() diff -Nru circuits-3.1.0+ds1/circuits/web/processors.py circuits-3.2.2/circuits/web/processors.py --- circuits-3.1.0+ds1/circuits/web/processors.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/circuits/web/processors.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,9 +1,10 @@ import re from cgi import parse_header +from circuits.six import PY3 + from .headers import HeaderElement -from .parsers import MultipartParser -from .parsers import QueryStringParser +from .parsers import MultipartParser, QueryStringParser def process_multipart(request, params): @@ -36,8 +37,22 @@ def process_urlencoded(request, params, encoding="utf-8"): params.update(QueryStringParser(request.qs).result) - body = request.body.getvalue().decode(encoding) - params.update(QueryStringParser(body).result) + body = request.body.getvalue() + if PY3: + body = body.decode(encoding) + result = QueryStringParser(body).result + for key, value in result.items(): + params[_decode_value(key, encoding)] = _decode_value(value, encoding) + + +def _decode_value(value, encoding): + if isinstance(value, bytes): + value = value.decode(encoding) + elif isinstance(value, list): + value = [_decode_value(val, encoding) for val in value] + elif isinstance(value, dict): + value = dict((key.decode(encoding), _decode_value(val, encoding)) for key, val in value.iteritems()) + return value def process(request, params): diff -Nru circuits-3.1.0+ds1/circuits/web/servers.py circuits-3.2.2/circuits/web/servers.py --- circuits-3.1.0+ds1/circuits/web/servers.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/circuits/web/servers.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,28 +1,21 @@ -# Module: server -# Date: 6th November 2008 -# Author: James Mills, prologic at shortcircuit dot net dot au - - """Web Servers This module implements the several Web Server components. """ - - from sys import stderr - from circuits import io +from circuits.core import BaseComponent, Timer, handler from circuits.net.events import close, read, write -from circuits.net.sockets import TCPServer, UNIXServer -from circuits.core import handler, BaseComponent, Timer +from circuits.net.sockets import BUFSIZE, TCPServer, UNIXServer -from .http import HTTP -from .events import terminate from .dispatchers import Dispatcher +from .events import terminate +from .http import HTTP class BaseServer(BaseComponent): + """Create a Base Web Server Create a Base Web Server (HTTP) bound to the IP Address / Port or @@ -56,11 +49,13 @@ channel = "web" def __init__(self, bind, encoding="utf-8", secure=False, certfile=None, - channel=channel): + channel=channel, display_banner=True, bufsize=BUFSIZE): "x.__init__(...) initializes x; see x.__class__.__doc__ for signature" super(BaseServer, self).__init__(channel=channel) + self._display_banner = display_banner + if isinstance(bind, (int, list, tuple,)): SocketType = TCPServer else: @@ -70,7 +65,8 @@ bind, secure=secure, certfile=certfile, - channel=channel + channel=channel, + bufsize=bufsize ).register(self) self.http = HTTP( @@ -88,6 +84,10 @@ return self.server.port @property + def display_banner(self): + return getattr(self, "_display_banner", False) + + @property def secure(self): if hasattr(self, "server"): return self.server.secure @@ -114,13 +114,14 @@ @handler("ready") def _on_ready(self, server, bind): stderr.write( - "{0:s} ready! Listening on: {1:s}\n".format( + "{} ready! Listening on: {}\n".format( self.http.version, self.http.base ) ) class Server(BaseServer): + """Create a Web Server Create a Web Server (HTTP) complete with the default Dispatcher to @@ -139,6 +140,7 @@ class FakeSock(): + def getpeername(self): return (None, None) diff -Nru circuits-3.1.0+ds1/circuits/web/sessions.py circuits-3.2.2/circuits/web/sessions.py --- circuits-3.1.0+ds1/circuits/web/sessions.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/circuits/web/sessions.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,21 +1,15 @@ -# Module: sessions -# Date: 22nd February 2009 -# Author: James Mills, prologic at shortcircuit dot net dot au - - """Session Components This module implements Session Components that can be used to store and access persistent information. """ - - -from uuid import uuid4 as uuid -from hashlib import sha1 as sha +from abc import ABCMeta, abstractmethod from collections import defaultdict +from hashlib import sha1 as sha +from uuid import uuid4 as uuid - -from circuits import handler, Component +from circuits import Component, handler +from circuits.six import with_metaclass def who(request, encoding="utf-8"): @@ -24,7 +18,7 @@ ip = request.remote.ip agent = request.headers.get("User-Agent", "") - return sha("{0:s}{1:s}".format(ip, agent).encode(encoding)).hexdigest() + return sha("{}{}".format(ip, agent).encode(encoding)).hexdigest() def create_session(request): @@ -34,7 +28,7 @@ of the users IP Address and User Agent in the form of ``sid/who``. """ - return "{0:s}/{1:s}".format(uuid().hex, who(request)) + return "{}/{}".format(uuid().hex, who(request)) def verify_session(request, sid): @@ -56,30 +50,92 @@ return sid -class Sessions(Component): +class Session(dict): - channel = "web" + def __init__(self, sid, data, store): + super(Session, self).__init__(data) - def __init__(self, name="circuits.session", channel=channel): - super(Sessions, self).__init__(channel=channel) + self._sid = sid + self._store = store - self._name = name + @property + def sid(self): + return self._sid + + @property + def store(self): + return self._store + + def expire(self): + self.store.delete(self.sid) + + def __enter__(self): + return self + + def __exit__(self, exc_type, exc_value, traceback): + if exc_type is None: + self.store.save(self.sid, self) + + +class Store(with_metaclass(ABCMeta, object)): + + @abstractmethod + def delete(self, sid): + """Delete the session data identified by sid""" + + @abstractmethod + def load(self, sid): + """Load the session data identified by sid""" + + @abstractmethod + def save(self, sid): + """Save the session data identified by sid""" + + +class MemoryStore(Store): + + def __init__(self): self._data = defaultdict(dict) + @property + def data(self): + return self._data + + def delete(self, sid): + del self.data[sid] + def load(self, sid): - return self._data[sid] + return Session(sid, self.data[sid], self) def save(self, sid, data): - """Save User Session Data for sid""" + self.data[sid] = data + + +class Sessions(Component): + + channel = "web" + + def __init__(self, name="circuits", store=MemoryStore, channel=channel): + super(Sessions, self).__init__(channel=channel) + + self._name = name + self._store = store() + + @property + def name(self): + return self._name + + @property + def store(self): + return self._store @handler("request", priority=10) def request(self, request, response): - if self._name in request.cookie: + if self.name in request.cookie: sid = request.cookie[self._name].value sid = verify_session(request, sid) else: sid = create_session(request) - request.sid = sid - request.session = self.load(sid) - response.cookie[self._name] = sid + request.session = self.store.load(sid) + response.cookie[self.name] = sid diff -Nru circuits-3.1.0+ds1/circuits/web/tools.py circuits-3.2.2/circuits/web/tools.py --- circuits-3.1.0+ds1/circuits/web/tools.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/circuits/web/tools.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,22 +1,27 @@ -# Module: tools -# Date: 16th February 2009 -# Author: James Mills, prologic at shortcircuit dot net dot au - """Tools This module implements tools used throughout circuits.web. -These tools can also be used within Controlelrs and request handlers. +These tools can also be used within Controllers and request handlers. """ - -import os -import stat import hashlib import mimetypes -import collections -from time import mktime -from email.utils import formatdate +import os +import stat from datetime import datetime, timedelta from email.generator import _make_boundary +from email.utils import formatdate +from time import mktime +try: + from collections import Callable +except ImportError: + from collections.abc import Callable + +from circuits import BaseComponent, handler +from circuits.web.wrappers import Host + +from . import _httpauth +from .errors import httperror, notfound, redirect, unauthorized +from .utils import compress, get_ranges mimetypes.init() mimetypes.add_type("image/x-dwg", ".dwg") @@ -24,10 +29,6 @@ mimetypes.add_type("text/javascript", ".js") mimetypes.add_type("application/xhtml+xml", ".xhtml") -from . import _httpauth -from .utils import get_ranges, compress -from .errors import httperror, notfound, redirect, unauthorized - def expires(request, response, secs=0, force=False): """Tool for influencing cache mechanisms using the 'Expires' header. @@ -230,7 +231,7 @@ if (not etag) and autotags: if status == 200: etag = response.collapse_body() - etag = '"%s"' % hashlib.md5.new(etag).hexdigest() + etag = '"%s"' % hashlib.new('md5', etag).hexdigest() response.headers['ETag'] = etag response.ETag = etag @@ -316,7 +317,7 @@ if not encrypt: encrypt = _httpauth.DIGEST_AUTH_ENCODERS[_httpauth.MD5] - if isinstance(users, collections.Callable): + if isinstance(users, Callable): try: # backward compatibility users = users() # expect it to return a dictionary @@ -396,7 +397,7 @@ return unauthorized(request, response) -def gzip(response, level=4, mime_types=['text/html', 'text/plain']): +def gzip(response, level=4, mime_types=("text/html", "text/plain",)): """Try to gzip the response body if Content-Type in mime_types. response.headers['Content-Type'] must be set to one of the @@ -453,3 +454,22 @@ return httperror( response.request, response, 406, description="identity, gzip" ) + + +class ReverseProxy(BaseComponent): + + headers = ('X-Real-IP', 'X-Forwarded-For') + + def init(self, headers=None): + """Web Component for identifying the original client IP when a reverse proxy is used + + :param headers: List of HTTP headers to read the original client IP + """ + + if headers: + self.headers = headers + + @handler('request', priority=1) + def _on_request(self, req, *_): + ip = [v for v in map(req.headers.get, self.headers) if v] + req.remote = ip and Host(ip[0], "", ip[0]) or req.remote diff -Nru circuits-3.1.0+ds1/circuits/web/url.py circuits-3.2.2/circuits/web/url.py --- circuits-3.1.0+ds1/circuits/web/url.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/circuits/web/url.py 2021-10-19 16:23:49.000000000 +0000 @@ -20,20 +20,15 @@ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - '''This is a module for dealing with urls. In particular, sanitizing them.''' -import re import codecs +import re -try: - from urllib.parse import quote, unquote - from urllib.parse import urljoin, urlparse, urlunparse -except ImportError: - from urllib import quote, unquote # NOQA - from urlparse import urljoin, urlparse, urlunparse # NOQA - -from circuits.six import b, string_types, text_type +from circuits.six import string_types, text_type +from circuits.six.moves.urllib_parse import ( + quote, unquote, urljoin, urlparse, urlunparse, +) # Come codes that we'll need IDNA = codecs.lookup('idna') @@ -54,6 +49,7 @@ class URL(object): + ''' For more information on how and what we parse / sanitize: http://tools.ietf.org/html/rfc1808.html @@ -70,15 +66,19 @@ else: parsed = urlparse(url.decode(encoding).encode('utf-8')) - try: - port = str(parsed.port).encode("utf-8") - except ValueError: + if isinstance(parsed.port, int): + port = ( + str(parsed.port).encode("utf-8") + if parsed.port not in (80, 443) + else None + ) + else: port = None return cls( parsed.scheme, parsed.hostname, port, parsed.path, parsed.params, - parsed.query, parsed.fragment + parsed.query, parsed.fragment ) def __init__(self, scheme, host, port, path, @@ -87,15 +87,15 @@ self._scheme = scheme self._host = host self._port = port - self._path = path or b('/') - self._params = re.sub(b('^;+'), b(''), params) + self._path = path or b'/' + self._params = re.sub(b'^;+', b'', params) self._params = re.sub( - b('^;|;$'), b(''), re.sub(b(';{2,}'), b(';'), self._params) + b'^;|;$', b'', re.sub(b';{2,}', b';', self._params) ) # Strip off extra leading ?'s - self._query = query.lstrip(b('?')) + self._query = query.lstrip(b'?') self._query = re.sub( - b('^&|&$'), b(''), re.sub(b('&{2,}'), b('&'), self._query) + b'^&|&$', b'', re.sub(b'&{2,}', b'&', self._query) ) self._fragment = fragment @@ -134,7 +134,7 @@ def __eq__(self, other): '''Return true if this url is /exactly/ equal to another''' - if isinstance(other, basestring): + if isinstance(other, string_types): return self.__eq__(self.parse(other, 'utf-8')) return ( self._scheme == other._scheme and @@ -157,11 +157,11 @@ def canonical(self): '''Canonicalize this url. This includes reordering parameters and args to have a consistent ordering''' - self._query = b('&').join( - sorted([q for q in self._query.split(b('&'))]) + self._query = b'&'.join( + sorted([q for q in self._query.split(b'&')]) ) - self._params = b(';').join( - sorted([q for q in self._params.split(b(';'))]) + self._params = b';'.join( + sorted([q for q in self._params.split(b';')]) ) return self @@ -183,29 +183,33 @@ def abspath(self): '''Clear out any '..' and excessive slashes from the path''' # Remove double forward-slashes from the path - path = re.sub(b('\/{2,}'), b('/'), self._path) + path = re.sub(br'\/{2,}', b'/', self._path) # With that done, go through and remove all the relative references unsplit = [] - for part in path.split(b('/')): + directory = False + for part in path.split(b'/'): # If we encounter the parent directory, and there's # a segment to pop off, then we should pop it off. - if part == b('..') and (not unsplit or unsplit.pop() is not None): - pass - elif part != b('.'): + if part == b'..' and (not unsplit or unsplit.pop() is not None): + directory = True + elif part != b'.': + directory = False unsplit.append(part) + else: + directory = True # With all these pieces, assemble! - if self._path.endswith(b('.')): + if directory: # If the path ends with a period, then it refers to a directory, # not a file path - self._path = b('/').join(unsplit) + b('/') - else: - self._path = b('/').join(unsplit) + unsplit.append(b'/') + self._path = b'/'.join(unsplit) return self def lower(self): '''Lowercase the hostname''' - self._host = self._host.lower() + if self._host is not None: + self._host = self._host.lower() return self def sanitize(self): @@ -226,7 +230,7 @@ '''Return the url in an arbitrary encoding''' netloc = self._host if self._port: - netloc += (b(':') + bytes(self._port)) + netloc += (b':' + bytes(self._port)) result = urlunparse(( self._scheme, netloc, self._path, diff -Nru circuits-3.1.0+ds1/circuits/web/utils.py circuits-3.2.2/circuits/web/utils.py --- circuits-3.1.0+ds1/circuits/web/utils.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/circuits/web/utils.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,32 +1,19 @@ -# Module: utils -# Date: 13th September 2007 -# Author: James Mills, prologic at shortcircuit dot net dot au - """Utilities This module implements utility functions. """ - +import os import re -import zlib -import time +import stat import struct -from math import sqrt -from io import TextIOWrapper +import time +import zlib from cgi import FieldStorage -from collections import MutableMapping - -try: - from urllib.parse import urljoin as _urljoin -except ImportError: - from urlparse import urljoin as _urljoin # NOQA - -try: - from urllib.parse import parse_qs as _parse_qs -except ImportError: - from cgi import parse_qs as _parse_qs # NOQA +from io import TextIOWrapper +from math import sqrt -from circuits.six import iterbytes +from circuits.net.utils import is_ssl_handshake # noqa +from circuits.six.moves.urllib_parse import parse_qs as _parse_qs from .exceptions import RangeUnsatisfiable, RequestEntityTooLarge @@ -34,13 +21,22 @@ image_map_pattern = re.compile("^[0-9]+,[0-9]+$") +def is_unix_socket(path): + if not os.path.exists(path): + return False + + mode = os.stat(path).st_mode + + return stat.S_ISSOCK(mode) + + def average(xs): return sum(xs) * 1.0 / len(xs) def variance(xs): avg = average(xs) - return list(map(lambda x: (x - avg)**2, xs)) + return list(map(lambda x: (x - avg) ** 2, xs)) def stddev(xs): @@ -202,185 +198,3 @@ raise RangeUnsatisfiable() return result - - -class IOrderedDict(dict, MutableMapping): - 'Dictionary that remembers insertion order with insensitive key' - # An inherited dict maps keys to values. - # The inherited dict provides __getitem__, __len__, __contains__, and get. - # The remaining methods are order-aware. - # Big-O running times for all methods are the same as for regular dictionaries. - - # The internal self.__map dictionary maps keys to links in a doubly linked list. - # The circular doubly linked list starts and ends with a sentinel element. - # The sentinel element never gets deleted (this simplifies the algorithm). - # Each link is stored as a list of length three: [PREV, NEXT, KEY]. - - def __init__(self, *args, **kwds): - '''Initialize an ordered dictionary. Signature is the same as for - regular dictionaries, but keyword arguments are not recommended - because their insertion order is arbitrary. - - ''' - if len(args) > 1: - raise TypeError('expected at most 1 arguments, got %d' % len(args)) - try: - self.__root - except AttributeError: - self.__root = root = [None, None, None] # sentinel node - PREV = 0 - NEXT = 1 - root[PREV] = root[NEXT] = root - self.__map = {} - self.__lower = {} - self.update(*args, **kwds) - - def __setitem__(self, key, value, PREV=0, NEXT=1, dict_setitem=dict.__setitem__): - 'od.__setitem__(i, y) <==> od[i]=y' - # Setting a new item creates a new link which goes at the end of the linked - # list, and the inherited dictionary is updated with the new key/value pair. - if key not in self: - root = self.__root - last = root[PREV] - last[NEXT] = root[PREV] = self.__map[key] = [last, root, key] - self.__lower[key.lower()] = key - key = self.__lower[key.lower()] - dict_setitem(self, key, value) - - def __delitem__(self, key, PREV=0, NEXT=1, dict_delitem=dict.__delitem__): - 'od.__delitem__(y) <==> del od[y]' - # Deleting an existing item uses self.__map to find the link which is - # then removed by updating the links in the predecessor and successor nodes. - if key in self: - key = self.__lower.pop(key.lower()) - - dict_delitem(self, key) - link = self.__map.pop(key) - link_prev = link[PREV] - link_next = link[NEXT] - link_prev[NEXT] = link_next - link_next[PREV] = link_prev - - def __getitem__(self, key, dict_getitem=dict.__getitem__): - if key in self: - key = self.__lower.get(key.lower()) - return dict_getitem(self, key) - - def __contains__(self, key): - return key.lower() in self.__lower - - def __iter__(self, NEXT=1, KEY=2): - 'od.__iter__() <==> iter(od)' - # Traverse the linked list in order. - root = self.__root - curr = root[NEXT] - while curr is not root: - yield curr[KEY] - curr = curr[NEXT] - - def __reversed__(self, PREV=0, KEY=2): - 'od.__reversed__() <==> reversed(od)' - # Traverse the linked list in reverse order. - root = self.__root - curr = root[PREV] - while curr is not root: - yield curr[KEY] - curr = curr[PREV] - - def __reduce__(self): - 'Return state information for pickling' - items = [[k, self[k]] for k in self] - tmp = self.__map, self.__root - del self.__map, self.__root - inst_dict = vars(self).copy() - self.__map, self.__root = tmp - if inst_dict: - return (self.__class__, (items,), inst_dict) - return self.__class__, (items,) - - def clear(self): - 'od.clear() -> None. Remove all items from od.' - try: - for node in self.__map.values(): - del node[:] - self.__root[:] = [self.__root, self.__root, None] - self.__map.clear() - except AttributeError: - pass - dict.clear(self) - - def get(self, key, default=None): - if key in self: - return self[key] - return default - - setdefault = MutableMapping.setdefault - update = MutableMapping.update - pop = MutableMapping.pop - keys = MutableMapping.keys - values = MutableMapping.values - items = MutableMapping.items - __ne__ = MutableMapping.__ne__ - - def popitem(self, last=True): - '''od.popitem() -> (k, v), return and remove a (key, value) pair. - Pairs are returned in LIFO order if last is true or FIFO order if false. - - ''' - if not self: - raise KeyError('dictionary is empty') - key = next(reversed(self) if last else iter(self)) - value = self.pop(key) - return key, value - - def __repr__(self): - 'od.__repr__() <==> repr(od)' - if not self: - return '%s()' % (self.__class__.__name__,) - return '%s(%r)' % (self.__class__.__name__, list(self.items())) - - def copy(self): - 'od.copy() -> a shallow copy of od' - return self.__class__(self) - - @classmethod - def fromkeys(cls, iterable, value=None): - '''OD.fromkeys(S[, v]) -> New ordered dictionary with keys from S - and values equal to v (which defaults to None). - - ''' - d = cls() - for key in iterable: - d[key] = value - return d - - def __eq__(self, other): - '''od.__eq__(y) <==> od==y. Comparison to another OD is order-sensitive - while comparison to a regular mapping is order-insensitive. - - ''' - if isinstance(other, IOrderedDict): - return ( - len(self) == len(other) - and set(self.items()) == set(other.items()) - ) - return dict.__eq__(self, other) - - def __del__(self): - self.clear() # eliminate cyclical references - - -def is_ssl_handshake(buf): - """Detect an SSLv2 or SSLv3 handshake""" - - # SSLv3 - - v = buf[:3] - if v in ["\x16\x03\x00", "\x16\x03\x01", "\x16\x03\x02"]: - return True - - # SSLv2 - - v = list(iterbytes(buf))[:2] - if (v[0] & 0x80 == 0x80) and ((v[0] & 0x7f) << 8 | v[1]) > 9: - return True diff -Nru circuits-3.1.0+ds1/circuits/web/websockets/client.py circuits-3.2.2/circuits/web/websockets/client.py --- circuits-3.1.0+ds1/circuits/web/websockets/client.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/circuits/web/websockets/client.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,29 +1,23 @@ -# Module: client -# Date: 4th January 2013 -# Author: mnl - +import base64 import os import random -import base64 +import re from errno import ECONNRESET from socket import error as SocketError -try: - from urllib.parse import urlparse -except ImportError: - from urlparse import urlparse # NOQA - -from circuits.web.headers import Headers -from circuits.protocols.http import HTTP +from circuits.core.components import BaseComponent from circuits.core.handlers import handler +from circuits.net.events import close, connect, write from circuits.net.sockets import TCPClient -from circuits.web.client import NotConnected -from circuits.core.components import BaseComponent -from circuits.net.events import connect, write, close +from circuits.protocols.http import HTTP from circuits.protocols.websocket import WebSocketCodec +from circuits.six.moves.urllib_parse import urlparse +from circuits.web.client import NotConnected +from circuits.web.headers import Headers class WebSocketClient(BaseComponent): + """ An RFC 6455 compliant WebSocket client component. Upon receiving a :class:`circuits.web.client.Connect` event, the component tries to @@ -46,7 +40,7 @@ channel = "wsclient" - def __init__(self, url, channel=channel, wschannel="ws", headers={}): + def __init__(self, url, channel=channel, wschannel="ws", headers=None): """ :param url: the URL to connect to. :param channel: the channel used by this component @@ -58,10 +52,11 @@ super(WebSocketClient, self).__init__(channel=channel) self._url = url - self._headers = headers + self._headers = headers or {} self._response = None self._pending = 0 self._wschannel = wschannel + self._codec = None self._transport = TCPClient(channel=self.channel).register(self) HTTP(channel=self.channel).register(self._transport) @@ -90,7 +85,7 @@ def _on_connected(self, host, port): headers = Headers([(k, v) for k, v in self._headers.items()]) # Clients MUST include Host header in HTTP/1.1 requests (RFC 2616) - if not "Host" in headers: + if "Host" not in headers: headers["Host"] = self._host \ + (":" + str(self._port)) if self._port else "" headers["Upgrade"] = "websocket" @@ -99,9 +94,12 @@ sec_key = os.urandom(16) except NotImplementedError: sec_key = "".join([chr(random.randint(0, 255)) for i in range(16)]) - headers["Sec-WebSocket-Key"] = base64.b64encode(sec_key).decode("latin1") + headers[ + "Sec-WebSocket-Key"] = base64.b64encode(sec_key).decode("latin1") headers["Sec-WebSocket-Version"] = "13" - command = "GET %s HTTP/1.1" % self._resource + UNSAFE_CHARS = re.compile('[^0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~]') + escaped_resource = UNSAFE_CHARS.sub('', self._resource.encode('ASCII', 'replace').decode('ASCII')) + command = "GET %s HTTP/1.1" % (escaped_resource,) message = "%s\r\n%s" % (command, headers) self._pending += 1 self.fire(write(message.encode('utf-8')), self._transport) @@ -111,11 +109,25 @@ def _on_response(self, response): self._response = response self._pending -= 1 - if response.headers.get("Connection") == "Close" \ + if response.headers.get("Connection", "").lower() == "close" \ or response.status != 101: self.fire(close(), self._transport) raise NotConnected() - WebSocketCodec(data=response.body.read(), channel=self._wschannel).register(self) + self._codec = WebSocketCodec( + data=response.body.read(), channel=self._wschannel).register(self) + + @handler('read') + def _on_read(self, event, *args): + # FIXME: every read-event is lost due to a race condition between + # WebSocketCodec().register() and the registered()-event of that instance. + if len(args) != 1: + return + if self._codec is not None and self._codec.parent is self: + if 'read' not in self._codec.events(): + event.stop() + self.fire(event.create('read', *args)) + else: + self.removeHandler(self._on_read) @handler("error", priority=10) def _on_error(self, event, error, *args, **kwargs): diff -Nru circuits-3.1.0+ds1/circuits/web/websockets/dispatcher.py circuits-3.2.2/circuits/web/websockets/dispatcher.py --- circuits-3.1.0+ds1/circuits/web/websockets/dispatcher.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/circuits/web/websockets/dispatcher.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,20 +1,14 @@ -# Module: dispatcher -# Date: 26th February 2011 -# Author: James Mills, prologic at shortcircuit dot net dot au - - import base64 import hashlib - -from circuits.six import b -from circuits.web.errors import httperror -from circuits import handler, BaseComponent +from circuits import BaseComponent, handler from circuits.net.events import connect, disconnect from circuits.protocols.websocket import WebSocketCodec +from circuits.web.errors import httperror class WebSocketsDispatcher(BaseComponent): + """ This class implements an RFC 6455 compliant WebSockets dispatcher that handles the WebSockets handshake and upgrades the connection. @@ -49,9 +43,16 @@ super(WebSocketsDispatcher, self).__init__(*args, **kwargs) + self._requests = {} self._path = path self._wschannel = wschannel - self._codecs = dict() + self._codecs = {} + + @handler("read", channel=wschannel, priority=100) + def _on_read_handler(self, event, socket, data): + if socket in self._requests: + event.request = self._requests[socket] + self.addHandler(_on_read_handler) @handler("request", priority=0.2) def _on_request(self, event, request, response): @@ -61,23 +62,21 @@ self._protocol_version = 13 headers = request.headers sec_key = headers.get("Sec-WebSocket-Key", "").encode("utf-8") + subprotocols = headers.elements("Sec-WebSocket-Protocol") connection_tokens = [s.strip() for s in headers.get("Connection", "").lower().split(",")] try: - if ("Host" not in headers - or headers.get("Upgrade", "").lower() != "websocket" - or "upgrade" not in connection_tokens - or sec_key is None - or len(base64.b64decode(sec_key)) != 16): - return httperror(request, response, code=400) + if ("Host" not in headers or headers.get("Upgrade", "").lower() != "websocket" or + "upgrade" not in connection_tokens or sec_key is None or len(base64.b64decode(sec_key)) != 16): + return httperror(request, response, code=400) if headers.get("Sec-WebSocket-Version", "") != "13": response.headers["Sec-WebSocket-Version"] = "13" return httperror(request, response, code=400) # Generate accept header information - msg = sec_key + b("258EAFA5-E914-47DA-95CA-C5AB0DC85B11") + msg = sec_key + b"258EAFA5-E914-47DA-95CA-C5AB0DC85B11" hasher = hashlib.sha1() hasher.update(msg) accept = base64.b64encode(hasher.digest()) @@ -91,7 +90,9 @@ pass response.headers["Upgrade"] = "WebSocket" response.headers["Connection"] = "Upgrade" - response.headers["Sec-WebSocket-Accept"] = accept.decode() + response.headers["Sec-WebSocket-Accept"] = accept.decode("ASCII") + if subprotocols: + response.headers["Sec-WebSocket-Protocol"] = self.select_subprotocol(subprotocols) codec = WebSocketCodec(request.sock, channel=self._wschannel) self._codecs[request.sock] = codec codec.register(self) @@ -99,21 +100,27 @@ finally: event.stop() + def select_subprotocol(self, subprotocols): + return subprotocols[0] + @handler("response_complete") def _on_response_complete(self, e, value): response = e.args[0] request = response.request if request.sock in self._codecs: - self.fire( - connect( - request.sock, - *request.sock.getpeername() - ), - self._wschannel + self._requests[request.sock] = request + cevent = connect( + request.sock, + *request.sock.getpeername() ) + cevent.request = request + self.fire(cevent, self._wschannel) @handler("disconnect") def _on_disconnect(self, sock): if sock in self._codecs: - self.fire(disconnect(sock), self._wschannel) + devent = disconnect(sock) + devent.request = self._requests.get(sock) + self.fire(devent, self._wschannel) del self._codecs[sock] + self._requests.pop(sock, None) diff -Nru circuits-3.1.0+ds1/circuits/web/websockets/__init__.py circuits-3.2.2/circuits/web/websockets/__init__.py --- circuits-3.1.0+ds1/circuits/web/websockets/__init__.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/circuits/web/websockets/__init__.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,10 +1,7 @@ -# Package: websockets -# Date: 26th March 2013 -# Author: James Mills, prologic at shortcircuit dot net dot au - """circuits.web websockets""" from .client import WebSocketClient from .dispatcher import WebSocketsDispatcher # flake8: noqa +# pylama: skip=1 diff -Nru circuits-3.1.0+ds1/circuits/web/wrappers.py circuits-3.2.2/circuits/web/wrappers.py --- circuits-3.1.0+ds1/circuits/web/wrappers.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/circuits/web/wrappers.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,40 +1,36 @@ -# Module: wrappers -# Date: 13th September 2007 -# Author: James Mills, prologic at shortcircuit dot net dot au - """Request/Response Wrappers This module implements the Request and Response objects. """ +from functools import partial +from io import BytesIO +from time import time +from circuits.net.sockets import BUFSIZE +from circuits.six import binary_type, text_type -from time import time -from io import BytesIO -from functools import partial +from .constants import HTTP_STATUS_CODES, SERVER_VERSION +from .errors import httperror +from .headers import Headers +from .url import parse_url try: from Cookie import SimpleCookie except ImportError: from http.cookies import SimpleCookie # NOQA -from .url import parse_url -from .headers import Headers -from ..six import binary_type -from .errors import httperror -from circuits.net.sockets import BUFSIZE -from .constants import HTTP_STATUS_CODES, SERVER_VERSION +try: + from email.utils import formatdate + formatdate = partial(formatdate, usegmt=True) +except ImportError: + from rfc822 import formatdate # NOQA + try: unicode except NameError: unicode = str -try: - from email.utils import formatdate - formatdate = partial(formatdate, usegmt=True) -except ImportError: - from rfc822 import formatdate as HTTPDate # NOQA - def file_generator(input, chunkSize=BUFSIZE): chunk = input.read(chunkSize) @@ -45,6 +41,7 @@ class Host(object): + """An internet address. name should be the client's host name. If not available (because no DNS @@ -103,10 +100,10 @@ return super(HTTPStatus, self).__eq__(other) def __str__(self): - return "{0:d} {1:s}".format(self._status, self._reason) + return "{:d} {}".format(self._status, self._reason) def __repr__(self): - return "".format( + return "".format( self._status, self._reason ) @@ -123,6 +120,7 @@ class Request(object): + """Creates a new Request object to hold information about a request. :param sock: The socket object of the request. @@ -169,6 +167,7 @@ self.path = path self.protocol = protocol self.qs = qs + self.print_debug = getattr(server, "display_banner", False) self.headers = headers or Headers() self.server = server @@ -177,11 +176,12 @@ if sock is not None: name = sock.getpeername() - if name is not None: - self.remote = Host(*name) - else: - name = sock.getsockname() - self.remote = Host(name, "", name) + try: + ip, port = name + name = None + except ValueError: # AF_UNIX + ip, port = None, None + self.remote = Host(ip, port, name) cookie = self.headers.get("Cookie") if cookie is not None: @@ -207,17 +207,20 @@ self.host = host self.port = port - base = "{0:s}://{1:s}{2:s}/".format( + base = "{}://{}{}/".format( self.scheme, self.host, - ":{0:d}".format(self.port) if self.port not in (80, 443) else "" + ":{0:d}".format(self.port) + if self.port not in (80, 443) + else "" ) + self.base = parse_url(base) - url = "{0:s}{1:s}{2:s}".format( + url = "{}{}{}".format( base, self.path, - "?{0:s}".format(self.qs) if self.qs else "" + "?{}".format(self.qs) if self.qs else "" ) self.uri = parse_url(url) self.uri.sanitize() @@ -228,8 +231,11 @@ class Body(object): + """Response Body""" + encode_errors = 'strict' + def __get__(self, response, cls=None): if response is None: return self @@ -245,6 +251,11 @@ value = [value] else: value = [] + elif isinstance(value, text_type): + if value: + value = [value.encode(response.encoding, self.encode_errors)] + else: + value = [] elif hasattr(value, "read"): response.stream = True value = file_generator(value) @@ -257,6 +268,7 @@ class Status(object): + """Response Status""" def __get__(self, response, cls=None): @@ -272,6 +284,7 @@ class Response(object): + """Response(sock, request) -> new Response object A Response object that holds the response to @@ -301,10 +314,11 @@ self.headers = Headers() self.headers["Date"] = formatdate() - if self.request.server is not None: - self.headers.add_header("Server", self.request.server.http.version) - else: - self.headers.add_header("X-Powered-By", SERVER_VERSION) + if getattr(self.request.server, "display_banner", False): + if self.request.server is not None: + self.headers.add_header("Server", request.server.http.version) + else: + self.headers.add_header("X-Powered-By", SERVER_VERSION) self.cookie = self.request.cookie @@ -320,16 +334,16 @@ def __str__(self): self.prepare() protocol = self.protocol - status = "{0:s}".format(self.status) - return "{0:s} {1:s}\r\n".format(protocol, status) + status = "{}".format(self.status) + return "{} {}\r\n".format(protocol, status) def __bytes__(self): - return str(self).encode(self.encoding) + return str(self).encode(self.encoding) # FIXME: this is wrong. HTTP headers must be ISO8859-1. This should only encode the body as UTF-8. def prepare(self): # Set a default content-Type if we don't have one. self.headers.setdefault( - "Content-Type", "text/html; charset={0:s}".format(self.encoding) + "Content-Type", "text/html; charset={}".format(self.encoding) ) cLength = None @@ -371,8 +385,7 @@ else: self.close = True - if (self.request.server is not None - and "Connection" not in self.headers): + if (self.request.server is not None and "Connection" not in self.headers): if self.protocol == "HTTP/1.1": if self.close: self.headers.add_header("Connection", "close") diff -Nru circuits-3.1.0+ds1/circuits/web/wsgi.py circuits-3.2.2/circuits/web/wsgi.py --- circuits-3.1.0+ds1/circuits/web/wsgi.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/circuits/web/wsgi.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,33 +1,23 @@ -# Module: wsgi -# Date: 6th November 2008 -# Author: James Mills, prologic at shortcircuit dot net dot au - """WSGI Components This module implements WSGI Components. """ - -try: - from urllib.parse import unquote -except ImportError: - from urllib import unquote # NOQA - from operator import itemgetter +from sys import exc_info as _exc_info from traceback import format_tb from types import GeneratorType -from sys import exc_info as _exc_info +from circuits.core import BaseComponent, handler from circuits.tools import tryimport -from circuits.core import handler, BaseComponent - -StringIO = tryimport(("cStringIO", "StringIO", "io"), "StringIO") +from circuits.web import wrappers -from .http import HTTP +from .dispatchers import Dispatcher +from .errors import httperror from .events import request from .headers import Headers -from .errors import httperror -from circuits.web import wrappers -from .dispatchers import Dispatcher +from .http import HTTP + +StringIO = tryimport(("cStringIO", "StringIO", "io"), "StringIO") def create_environ(errors, path, req): @@ -114,10 +104,10 @@ try: cl = int(headers.get("Content-Length", "0")) - except: + except ValueError: cl = 0 - req.body.write(env("wsgi.input").read(cl)) + req.body.write(env("wsgi.input").read(cl)) # FIXME: what about chunked encoding? req.body.seek(0) res = wrappers.Response(req) @@ -130,7 +120,7 @@ self.fire(request(self.request, self.response)) self._finished = False - while self or not self._finished: + while self._queue or not self._finished: self.tick() self.response.prepare() @@ -142,7 +132,7 @@ return body @handler("response", channel="web") - def response(self, event, response): + def on_response(self, event, response): self._finished = True event.stop() @@ -166,6 +156,7 @@ __nonzero__ = __bool__ + empty = _Empty() del _Empty @@ -213,7 +204,8 @@ try: body = app(environ, start_response) if isinstance(body, list): - body = "".join(body) + _body = type(body[0])() if body else "" + body = _body.join(body) elif isinstance(body, GeneratorType): res.body = body res.stream = True diff -Nru circuits-3.1.0+ds1/circuits.egg-info/dependency_links.txt circuits-3.2.2/circuits.egg-info/dependency_links.txt --- circuits-3.1.0+ds1/circuits.egg-info/dependency_links.txt 2014-10-31 23:13:39.000000000 +0000 +++ circuits-3.2.2/circuits.egg-info/dependency_links.txt 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ - diff -Nru circuits-3.1.0+ds1/circuits.egg-info/entry_points.txt circuits-3.2.2/circuits.egg-info/entry_points.txt --- circuits-3.1.0+ds1/circuits.egg-info/entry_points.txt 2014-10-31 23:13:39.000000000 +0000 +++ circuits-3.2.2/circuits.egg-info/entry_points.txt 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -[console_scripts] -circuits.web = circuits.web.main:main - diff -Nru circuits-3.1.0+ds1/circuits.egg-info/PKG-INFO circuits-3.2.2/circuits.egg-info/PKG-INFO --- circuits-3.1.0+ds1/circuits.egg-info/PKG-INFO 2014-10-31 23:13:39.000000000 +0000 +++ circuits-3.2.2/circuits.egg-info/PKG-INFO 1970-01-01 00:00:00.000000000 +0000 @@ -1,297 +0,0 @@ -Metadata-Version: 1.1 -Name: circuits -Version: 3.1.0 -Summary: Asynchronous Component based Event Application Framework -Home-page: http://circuitsframework.com/ -Author: James Mills -Author-email: prologic@shortcircuit.net.au -License: MIT -Download-URL: http://bitbucket.org/circuits/circuits/downloads/ -Description: .. _Python Programming Language: http://www.python.org/ - .. _#circuits IRC Channel: http://webchat.freenode.net/?randomnick=1&channels=circuits&uio=d4 - .. _FreeNode IRC Network: http://freenode.net - .. _Python Standard Library: http://docs.python.org/library/ - .. _MIT License: http://www.opensource.org/licenses/mit-license.php - .. _Create an Issue: https://bitbucket.org/circuits/circuits/issue/new - .. _Mailing List: http://groups.google.com/group/circuits-users - .. _Project Website: http://circuitsframework.com/ - .. _PyPi Page: http://pypi.python.org/pypi/circuits - .. _Read the Docs: http://circuits.readthedocs.org/en/latest/ - .. _View the ChangeLog: http://circuits.readthedocs.org/en/latest/changes.html - .. _Downloads Page: https://bitbucket.org/circuits/circuits/downloads - - - circuits is a **Lightweight** **Event** driven and **Asynchronous** - **Application Framework** for the `Python Programming Language`_ - with a strong **Component** Architecture. - - circuits also includes a lightweight, high performance and scalable - HTTP/WSGI compliant web server as well as various I/O and Networking - components. - - - Visit the `Project Website`_ - - `Read the Docs`_ - - Download it from the `Downloads Page`_ - - `View the ChangeLog`_ - - .. image:: https://pypip.in/v/circuits/badge.png?text=version - :target: https://pypi.python.org/pypi/circuits - :alt: Latest Version - - .. image:: https://pypip.in/py_versions/circuits/badge.svg - :target: https://pypi.python.org/pypi/circuits - :alt: Supported Python Versions - - .. image:: https://pypip.in/implementation/circuits/badge.svg - :target: https://pypi.python.org/pypi/circuits - :alt: Supported Python implementations - - .. image:: https://pypip.in/status/circuits/badge.svg - :target: https://pypi.python.org/pypi/circuits - :alt: Development Status - - .. image:: https://pypip.in/d/circuits/badge.png - :target: https://pypi.python.org/pypi/circuits - :alt: Number of Downloads - - .. image:: https://pypip.in/format/circuits/badge.svg - :target: https://pypi.python.org/pypi/circuits - :alt: Format - - .. image:: https://pypip.in/license/circuits/badge.svg - :target: https://pypi.python.org/pypi/circuits - :alt: License - - .. image:: https://requires.io/bitbucket/circuits/circuits/requirements.png?branch=default - :target: https://requires.io/bitbucket/circuits/circuits/requirements?branch=default - :alt: Requirements Status - - - Examples - -------- - - - Hello - ..... - - - .. code:: python - - #!/usr/bin/env python - - """circuits Hello World""" - - from circuits import Component, Event - - - class hello(Event): - """hello Event""" - - - class App(Component): - - def hello(self): - """Hello Event Handler""" - - print("Hello World!") - - def started(self, component): - """Started Event Handler - - This is fired internally when your application starts up and can be used to - trigger events that only occur once during startup. - """ - - self.fire(hello()) # Fire hello Event - - raise SystemExit(0) # Terminate the Application - - App().run() - - - Echo Server - ........... - - - .. code:: python - - #!/usr/bin/env python - - """Simple TCP Echo Server - - This example shows how you can create a simple TCP Server (an Echo Service) - utilizing the builtin Socket Components that the circuits library ships with. - """ - - from circuits import handler, Debugger - from circuits.net.sockets import TCPServer - - - class EchoServer(TCPServer): - - @handler("read") - def on_read(self, sock, data): - """Read Event Handler - - This is fired by the underlying Socket Component when there has been - new data read from the connected client. - - ..note :: By simply returning, client/server socket components listen - to ValueChagned events (feedback) to determine if a handler - returned some data and fires a subsequent Write event with - the value returned. - """ - - return data - - # Start and "run" the system. - # Bind to port 0.0.0.0:9000 - app = EchoServer(9000) - Debugger().register(app) - app.run() - - - Hello Web - ......... - - - .. code:: python - - #!/usr/bin/env python - - from circuits.web import Server, Controller - - - class Root(Controller): - - def index(self): - """Index Request Handler - - Controller(s) expose implicitly methods as request handlers. - Request Handlers can still be customized by using the ``@expose`` - decorator. For example exposing as a different path. - """ - - return "Hello World!" - - app = Server(("0.0.0.0", 9000)) - Root().register(app) - app.run() - - - More `examples `_... - - - - Features - -------- - - - event driven - - concurrency support - - component architecture - - asynchronous I/O components - - no required external dependencies - - full featured web framework (circuits.web) - - coroutine based synchronization primitives - - - Requirements - ------------ - - - circuits has no dependencies beyond the `Python Standard Library`_. - - - Supported Platforms - ------------------- - - - Linux, FreeBSD, Mac OS X, Windows - - Python 2.6, 2.7, 3.2, 3.3, 3.4 - - pypy 2.0, 2.1, 2.2 - - - Installation - ------------ - - The simplest and recommended way to install circuits is with pip. - You may install the latest stable release from PyPI with pip:: - - > pip install circuits - - If you do not have pip, you may use easy_install:: - - > easy_install circuits - - Alternatively, you may download the source package from the - `PyPi Page`_ or the `Downloads Page`_ extract it and install using:: - - > python setup.py install - - - .. note:: - You can install the `development version - `_ - via ``pip install circuits==dev``. - - - License - ------- - - circuits is licensed under the `MIT License`_. - - - Feedback - -------- - - We welcome any questions or feedback about bugs and suggestions on how to - improve circuits. Let us know what you think about circuits. `@pythoncircuits `_. - - Do you have suggestions for improvement? Then please `Create an Issue`_ - with details of what you would like to see. I'll take a look at it and - work with you to either incorporate the idea or find a better solution. - - - Community - --------- - - There is also a small community of circuits enthusiasts that you may - find on the `#circuits IRC Channel`_ on the `FreeNode IRC Network`_ - and the `Mailing List`_. - -Keywords: event framework distributed concurrent component asynchronous -Platform: POSIX -Classifier: Development Status :: 5 - Production/Stable -Classifier: Environment :: Console -Classifier: Environment :: No Input/Output (Daemon) -Classifier: Environment :: Other Environment -Classifier: Environment :: Plugins -Classifier: Environment :: Web Environment -Classifier: Intended Audience :: Developers -Classifier: Intended Audience :: Information Technology -Classifier: Intended Audience :: Science/Research -Classifier: Intended Audience :: System Administrators -Classifier: Intended Audience :: Telecommunications Industry -Classifier: License :: OSI Approved :: MIT License -Classifier: Natural Language :: English -Classifier: Operating System :: POSIX :: BSD -Classifier: Operating System :: POSIX :: Linux -Classifier: Operating System :: MacOS :: MacOS X -Classifier: Operating System :: Microsoft :: Windows -Classifier: Programming Language :: Python :: 2.6 -Classifier: Programming Language :: Python :: 2.7 -Classifier: Programming Language :: Python :: 3.1 -Classifier: Programming Language :: Python :: 3.2 -Classifier: Programming Language :: Python :: 3.3 -Classifier: Programming Language :: Python :: Implementation :: CPython -Classifier: Programming Language :: Python :: Implementation :: PyPy -Classifier: Topic :: Adaptive Technologies -Classifier: Topic :: Communications :: Chat :: Internet Relay Chat -Classifier: Topic :: Communications :: Email :: Mail Transport Agents -Classifier: Topic :: Database -Classifier: Topic :: Internet :: WWW/HTTP :: HTTP Servers -Classifier: Topic :: Internet :: WWW/HTTP :: WSGI :: Application -Classifier: Topic :: Internet :: WWW/HTTP :: WSGI :: Middleware -Classifier: Topic :: Internet :: WWW/HTTP :: WSGI :: Server -Classifier: Topic :: Software Development :: Libraries :: Application Frameworks -Classifier: Topic :: Software Development :: Libraries :: Python Modules -Classifier: Topic :: System :: Clustering -Classifier: Topic :: System :: Distributed Computing diff -Nru circuits-3.1.0+ds1/circuits.egg-info/SOURCES.txt circuits-3.2.2/circuits.egg-info/SOURCES.txt --- circuits-3.1.0+ds1/circuits.egg-info/SOURCES.txt 2014-10-31 23:13:39.000000000 +0000 +++ circuits-3.2.2/circuits.egg-info/SOURCES.txt 1970-01-01 00:00:00.000000000 +0000 @@ -1,1438 +0,0 @@ -CHANGES.rst -LICENSE -MANIFEST.in -Makefile -README.rst -requirements-dev.txt -requirements.txt -setup.cfg -setup.py -tox.ini -bin/circuits.bench -bin/htpasswd -circuits/__init__.py -circuits/six.py -circuits/version.py -circuits.egg-info/PKG-INFO -circuits.egg-info/SOURCES.txt -circuits.egg-info/dependency_links.txt -circuits.egg-info/entry_points.txt -circuits.egg-info/top_level.txt -circuits.egg-info/zip-safe -circuits/app/__init__.py -circuits/app/daemon.py -circuits/core/__init__.py -circuits/core/bridge.py -circuits/core/components.py -circuits/core/debugger.py -circuits/core/events.py -circuits/core/handlers.py -circuits/core/helpers.py -circuits/core/loader.py -circuits/core/manager.py -circuits/core/pollers.py -circuits/core/timers.py -circuits/core/utils.py -circuits/core/values.py -circuits/core/workers.py -circuits/io/__init__.py -circuits/io/events.py -circuits/io/file.py -circuits/io/notify.py -circuits/io/process.py -circuits/io/serial.py -circuits/net/__init__.py -circuits/net/events.py -circuits/net/sockets.py -circuits/node/__init__.py -circuits/node/client.py -circuits/node/events.py -circuits/node/node.py -circuits/node/server.py -circuits/node/utils.py -circuits/protocols/__init__.py -circuits/protocols/http.py -circuits/protocols/line.py -circuits/protocols/websocket.py -circuits/protocols/irc/__init__.py -circuits/protocols/irc/commands.py -circuits/protocols/irc/events.py -circuits/protocols/irc/message.py -circuits/protocols/irc/numerics.py -circuits/protocols/irc/protocol.py -circuits/protocols/irc/replies.py -circuits/protocols/irc/utils.py -circuits/tools/__init__.py -circuits/web/__init__.py -circuits/web/_httpauth.py -circuits/web/client.py -circuits/web/constants.py -circuits/web/controllers.py -circuits/web/errors.py -circuits/web/events.py -circuits/web/exceptions.py -circuits/web/headers.py -circuits/web/http.py -circuits/web/loggers.py -circuits/web/main.py -circuits/web/processors.py -circuits/web/servers.py -circuits/web/sessions.py -circuits/web/tools.py -circuits/web/url.py -circuits/web/utils.py -circuits/web/wrappers.py -circuits/web/wsgi.py -circuits/web/dispatchers/__init__.py -circuits/web/dispatchers/dispatcher.py -circuits/web/dispatchers/jsonrpc.py -circuits/web/dispatchers/static.py -circuits/web/dispatchers/virtualhosts.py -circuits/web/dispatchers/xmlrpc.py -circuits/web/parsers/__init__.py -circuits/web/parsers/http.py -circuits/web/parsers/multipart.py -circuits/web/parsers/querystring.py -circuits/web/websockets/__init__.py -circuits/web/websockets/client.py -circuits/web/websockets/dispatcher.py -docs/.requirements.txt.un~ -docs/Makefile -docs/check_docs.py -docs/circuits-docs.xml -docs/logo.png -docs/logo_small.png -docs/make.bat -docs/requirements.txt -docs/build/doctrees/changes.doctree -docs/build/doctrees/contributors.doctree -docs/build/doctrees/environment.pickle -docs/build/doctrees/faq.doctree -docs/build/doctrees/glossary.doctree -docs/build/doctrees/index.doctree -docs/build/doctrees/readme.doctree -docs/build/doctrees/roadmap.doctree -docs/build/doctrees/todo.doctree -docs/build/doctrees/api/circuits.app.daemon.doctree -docs/build/doctrees/api/circuits.app.doctree -docs/build/doctrees/api/circuits.core.bridge.doctree -docs/build/doctrees/api/circuits.core.components.doctree -docs/build/doctrees/api/circuits.core.debugger.doctree -docs/build/doctrees/api/circuits.core.doctree -docs/build/doctrees/api/circuits.core.events.doctree -docs/build/doctrees/api/circuits.core.handlers.doctree -docs/build/doctrees/api/circuits.core.helpers.doctree -docs/build/doctrees/api/circuits.core.loader.doctree -docs/build/doctrees/api/circuits.core.manager.doctree -docs/build/doctrees/api/circuits.core.pollers.doctree -docs/build/doctrees/api/circuits.core.timers.doctree -docs/build/doctrees/api/circuits.core.utils.doctree -docs/build/doctrees/api/circuits.core.values.doctree -docs/build/doctrees/api/circuits.core.workers.doctree -docs/build/doctrees/api/circuits.doctree -docs/build/doctrees/api/circuits.io.doctree -docs/build/doctrees/api/circuits.io.events.doctree -docs/build/doctrees/api/circuits.io.file.doctree -docs/build/doctrees/api/circuits.io.notify.doctree -docs/build/doctrees/api/circuits.io.process.doctree -docs/build/doctrees/api/circuits.io.serial.doctree -docs/build/doctrees/api/circuits.net.doctree -docs/build/doctrees/api/circuits.net.events.doctree -docs/build/doctrees/api/circuits.net.sockets.doctree -docs/build/doctrees/api/circuits.node.client.doctree -docs/build/doctrees/api/circuits.node.doctree -docs/build/doctrees/api/circuits.node.events.doctree -docs/build/doctrees/api/circuits.node.node.doctree -docs/build/doctrees/api/circuits.node.server.doctree -docs/build/doctrees/api/circuits.node.utils.doctree -docs/build/doctrees/api/circuits.protocols.doctree -docs/build/doctrees/api/circuits.protocols.http.doctree -docs/build/doctrees/api/circuits.protocols.irc.doctree -docs/build/doctrees/api/circuits.protocols.line.doctree -docs/build/doctrees/api/circuits.protocols.websocket.doctree -docs/build/doctrees/api/circuits.six.doctree -docs/build/doctrees/api/circuits.tools.doctree -docs/build/doctrees/api/circuits.version.doctree -docs/build/doctrees/api/circuits.web.client.doctree -docs/build/doctrees/api/circuits.web.constants.doctree -docs/build/doctrees/api/circuits.web.controllers.doctree -docs/build/doctrees/api/circuits.web.dispatchers.dispatcher.doctree -docs/build/doctrees/api/circuits.web.dispatchers.doctree -docs/build/doctrees/api/circuits.web.dispatchers.jsonrpc.doctree -docs/build/doctrees/api/circuits.web.dispatchers.static.doctree -docs/build/doctrees/api/circuits.web.dispatchers.virtualhosts.doctree -docs/build/doctrees/api/circuits.web.dispatchers.xmlrpc.doctree -docs/build/doctrees/api/circuits.web.doctree -docs/build/doctrees/api/circuits.web.errors.doctree -docs/build/doctrees/api/circuits.web.events.doctree -docs/build/doctrees/api/circuits.web.exceptions.doctree -docs/build/doctrees/api/circuits.web.headers.doctree -docs/build/doctrees/api/circuits.web.http.doctree -docs/build/doctrees/api/circuits.web.loggers.doctree -docs/build/doctrees/api/circuits.web.main.doctree -docs/build/doctrees/api/circuits.web.parsers.doctree -docs/build/doctrees/api/circuits.web.parsers.http.doctree -docs/build/doctrees/api/circuits.web.parsers.multipart.doctree -docs/build/doctrees/api/circuits.web.parsers.querystring.doctree -docs/build/doctrees/api/circuits.web.processors.doctree -docs/build/doctrees/api/circuits.web.servers.doctree -docs/build/doctrees/api/circuits.web.sessions.doctree -docs/build/doctrees/api/circuits.web.tools.doctree -docs/build/doctrees/api/circuits.web.url.doctree -docs/build/doctrees/api/circuits.web.utils.doctree -docs/build/doctrees/api/circuits.web.websockets.client.doctree -docs/build/doctrees/api/circuits.web.websockets.dispatcher.doctree -docs/build/doctrees/api/circuits.web.websockets.doctree -docs/build/doctrees/api/circuits.web.wrappers.doctree -docs/build/doctrees/api/circuits.web.wsgi.doctree -docs/build/doctrees/api/index.doctree -docs/build/doctrees/dev/contributing.doctree -docs/build/doctrees/dev/index.doctree -docs/build/doctrees/dev/introduction.doctree -docs/build/doctrees/dev/processes.doctree -docs/build/doctrees/dev/standards.doctree -docs/build/doctrees/examples/index.doctree -docs/build/doctrees/man/components.doctree -docs/build/doctrees/man/debugger.doctree -docs/build/doctrees/man/events.doctree -docs/build/doctrees/man/handlers.doctree -docs/build/doctrees/man/index.doctree -docs/build/doctrees/man/manager.doctree -docs/build/doctrees/man/values.doctree -docs/build/doctrees/man/misc/tools.doctree -docs/build/doctrees/start/downloading.doctree -docs/build/doctrees/start/index.doctree -docs/build/doctrees/start/installing.doctree -docs/build/doctrees/start/quick.doctree -docs/build/doctrees/start/requirements.doctree -docs/build/doctrees/tutorials/index.doctree -docs/build/doctrees/tutorials/telnet/index.doctree -docs/build/doctrees/tutorials/woof/index.doctree -docs/build/doctrees/web/features.doctree -docs/build/doctrees/web/gettingstarted.doctree -docs/build/doctrees/web/howtos.doctree -docs/build/doctrees/web/index.doctree -docs/build/doctrees/web/introduction.doctree -docs/build/doctrees/web/miscellaneous.doctree -docs/build/html/.buildinfo -docs/build/html/changes.html -docs/build/html/contributors.html -docs/build/html/faq.html -docs/build/html/genindex.html -docs/build/html/glossary.html -docs/build/html/index.html -docs/build/html/objects.inv -docs/build/html/py-modindex.html -docs/build/html/readme.html -docs/build/html/roadmap.html -docs/build/html/search.html -docs/build/html/searchindex.js -docs/build/html/todo.html -docs/build/html/_downloads/001.py -docs/build/html/_downloads/002.py -docs/build/html/_downloads/003.py -docs/build/html/_downloads/004.py -docs/build/html/_downloads/005.py -docs/build/html/_downloads/006.py -docs/build/html/_downloads/007.py -docs/build/html/_downloads/008.py -docs/build/html/_downloads/009.py -docs/build/html/_downloads/echoserver.py -docs/build/html/_downloads/handler_annotation.py -docs/build/html/_downloads/handler_returns.py -docs/build/html/_downloads/hello.py -docs/build/html/_downloads/helloweb.py -docs/build/html/_downloads/telnet.py -docs/build/html/_images/CircuitsWebServer.png -docs/build/html/_images/Telnet.png -docs/build/html/_images/graphviz-b83b24d47415abeb6163e2ff753b8a7fed644c3e.png -docs/build/html/_images/graphviz-b83b24d47415abeb6163e2ff753b8a7fed644c3e.png.map -docs/build/html/_images/graphviz-fa9bbccfbcc0c44bc0636e85a3c610dc406600cf.png -docs/build/html/_images/graphviz-fa9bbccfbcc0c44bc0636e85a3c610dc406600cf.png.map -docs/build/html/_sources/changes.txt -docs/build/html/_sources/contributors.txt -docs/build/html/_sources/faq.txt -docs/build/html/_sources/glossary.txt -docs/build/html/_sources/index.txt -docs/build/html/_sources/readme.txt -docs/build/html/_sources/roadmap.txt -docs/build/html/_sources/todo.txt -docs/build/html/_sources/api/circuits.app.daemon.txt -docs/build/html/_sources/api/circuits.app.txt -docs/build/html/_sources/api/circuits.core.bridge.txt -docs/build/html/_sources/api/circuits.core.components.txt -docs/build/html/_sources/api/circuits.core.debugger.txt -docs/build/html/_sources/api/circuits.core.events.txt -docs/build/html/_sources/api/circuits.core.handlers.txt -docs/build/html/_sources/api/circuits.core.helpers.txt -docs/build/html/_sources/api/circuits.core.loader.txt -docs/build/html/_sources/api/circuits.core.manager.txt -docs/build/html/_sources/api/circuits.core.pollers.txt -docs/build/html/_sources/api/circuits.core.timers.txt -docs/build/html/_sources/api/circuits.core.txt -docs/build/html/_sources/api/circuits.core.utils.txt -docs/build/html/_sources/api/circuits.core.values.txt -docs/build/html/_sources/api/circuits.core.workers.txt -docs/build/html/_sources/api/circuits.io.events.txt -docs/build/html/_sources/api/circuits.io.file.txt -docs/build/html/_sources/api/circuits.io.notify.txt -docs/build/html/_sources/api/circuits.io.process.txt -docs/build/html/_sources/api/circuits.io.serial.txt -docs/build/html/_sources/api/circuits.io.txt -docs/build/html/_sources/api/circuits.net.events.txt -docs/build/html/_sources/api/circuits.net.sockets.txt -docs/build/html/_sources/api/circuits.net.txt -docs/build/html/_sources/api/circuits.node.client.txt -docs/build/html/_sources/api/circuits.node.events.txt -docs/build/html/_sources/api/circuits.node.node.txt -docs/build/html/_sources/api/circuits.node.server.txt -docs/build/html/_sources/api/circuits.node.txt -docs/build/html/_sources/api/circuits.node.utils.txt -docs/build/html/_sources/api/circuits.protocols.http.txt -docs/build/html/_sources/api/circuits.protocols.irc.txt -docs/build/html/_sources/api/circuits.protocols.line.txt -docs/build/html/_sources/api/circuits.protocols.txt -docs/build/html/_sources/api/circuits.protocols.websocket.txt -docs/build/html/_sources/api/circuits.six.txt -docs/build/html/_sources/api/circuits.tools.txt -docs/build/html/_sources/api/circuits.txt -docs/build/html/_sources/api/circuits.version.txt -docs/build/html/_sources/api/circuits.web.client.txt -docs/build/html/_sources/api/circuits.web.constants.txt -docs/build/html/_sources/api/circuits.web.controllers.txt -docs/build/html/_sources/api/circuits.web.dispatchers.dispatcher.txt -docs/build/html/_sources/api/circuits.web.dispatchers.jsonrpc.txt -docs/build/html/_sources/api/circuits.web.dispatchers.static.txt -docs/build/html/_sources/api/circuits.web.dispatchers.txt -docs/build/html/_sources/api/circuits.web.dispatchers.virtualhosts.txt -docs/build/html/_sources/api/circuits.web.dispatchers.xmlrpc.txt -docs/build/html/_sources/api/circuits.web.errors.txt -docs/build/html/_sources/api/circuits.web.events.txt -docs/build/html/_sources/api/circuits.web.exceptions.txt -docs/build/html/_sources/api/circuits.web.headers.txt -docs/build/html/_sources/api/circuits.web.http.txt -docs/build/html/_sources/api/circuits.web.loggers.txt -docs/build/html/_sources/api/circuits.web.main.txt -docs/build/html/_sources/api/circuits.web.parsers.http.txt -docs/build/html/_sources/api/circuits.web.parsers.multipart.txt -docs/build/html/_sources/api/circuits.web.parsers.querystring.txt -docs/build/html/_sources/api/circuits.web.parsers.txt -docs/build/html/_sources/api/circuits.web.processors.txt -docs/build/html/_sources/api/circuits.web.servers.txt -docs/build/html/_sources/api/circuits.web.sessions.txt -docs/build/html/_sources/api/circuits.web.tools.txt -docs/build/html/_sources/api/circuits.web.txt -docs/build/html/_sources/api/circuits.web.url.txt -docs/build/html/_sources/api/circuits.web.utils.txt -docs/build/html/_sources/api/circuits.web.websockets.client.txt -docs/build/html/_sources/api/circuits.web.websockets.dispatcher.txt -docs/build/html/_sources/api/circuits.web.websockets.txt -docs/build/html/_sources/api/circuits.web.wrappers.txt -docs/build/html/_sources/api/circuits.web.wsgi.txt -docs/build/html/_sources/api/index.txt -docs/build/html/_sources/dev/contributing.txt -docs/build/html/_sources/dev/index.txt -docs/build/html/_sources/dev/introduction.txt -docs/build/html/_sources/dev/processes.txt -docs/build/html/_sources/dev/standards.txt -docs/build/html/_sources/examples/index.txt -docs/build/html/_sources/man/components.txt -docs/build/html/_sources/man/debugger.txt -docs/build/html/_sources/man/events.txt -docs/build/html/_sources/man/handlers.txt -docs/build/html/_sources/man/index.txt -docs/build/html/_sources/man/manager.txt -docs/build/html/_sources/man/values.txt -docs/build/html/_sources/man/misc/tools.txt -docs/build/html/_sources/start/downloading.txt -docs/build/html/_sources/start/index.txt -docs/build/html/_sources/start/installing.txt -docs/build/html/_sources/start/quick.txt -docs/build/html/_sources/start/requirements.txt -docs/build/html/_sources/tutorials/index.txt -docs/build/html/_sources/tutorials/telnet/index.txt -docs/build/html/_sources/tutorials/woof/index.txt -docs/build/html/_sources/web/features.txt -docs/build/html/_sources/web/gettingstarted.txt -docs/build/html/_sources/web/howtos.txt -docs/build/html/_sources/web/index.txt -docs/build/html/_sources/web/introduction.txt -docs/build/html/_sources/web/miscellaneous.txt -docs/build/html/_static/ajax-loader.gif -docs/build/html/_static/basic.css -docs/build/html/_static/comment-bright.png -docs/build/html/_static/comment-close.png -docs/build/html/_static/comment.png -docs/build/html/_static/default.css -docs/build/html/_static/doctools.js -docs/build/html/_static/down-pressed.png -docs/build/html/_static/down.png -docs/build/html/_static/file.png -docs/build/html/_static/jquery.js -docs/build/html/_static/logo.png -docs/build/html/_static/minus.png -docs/build/html/_static/plus.png -docs/build/html/_static/pygments.css -docs/build/html/_static/rtd.css -docs/build/html/_static/searchtools.js -docs/build/html/_static/sidebar.js -docs/build/html/_static/tracsphinx.css -docs/build/html/_static/underscore.js -docs/build/html/_static/up-pressed.png -docs/build/html/_static/up.png -docs/build/html/_static/websupport.js -docs/build/html/api/circuits.app.daemon.html -docs/build/html/api/circuits.app.html -docs/build/html/api/circuits.core.bridge.html -docs/build/html/api/circuits.core.components.html -docs/build/html/api/circuits.core.debugger.html -docs/build/html/api/circuits.core.events.html -docs/build/html/api/circuits.core.handlers.html -docs/build/html/api/circuits.core.helpers.html -docs/build/html/api/circuits.core.html -docs/build/html/api/circuits.core.loader.html -docs/build/html/api/circuits.core.manager.html -docs/build/html/api/circuits.core.pollers.html -docs/build/html/api/circuits.core.timers.html -docs/build/html/api/circuits.core.utils.html -docs/build/html/api/circuits.core.values.html -docs/build/html/api/circuits.core.workers.html -docs/build/html/api/circuits.html -docs/build/html/api/circuits.io.events.html -docs/build/html/api/circuits.io.file.html -docs/build/html/api/circuits.io.html -docs/build/html/api/circuits.io.notify.html -docs/build/html/api/circuits.io.process.html -docs/build/html/api/circuits.io.serial.html -docs/build/html/api/circuits.net.events.html -docs/build/html/api/circuits.net.html -docs/build/html/api/circuits.net.sockets.html -docs/build/html/api/circuits.node.client.html -docs/build/html/api/circuits.node.events.html -docs/build/html/api/circuits.node.html -docs/build/html/api/circuits.node.node.html -docs/build/html/api/circuits.node.server.html -docs/build/html/api/circuits.node.utils.html -docs/build/html/api/circuits.protocols.html -docs/build/html/api/circuits.protocols.http.html -docs/build/html/api/circuits.protocols.irc.html -docs/build/html/api/circuits.protocols.line.html -docs/build/html/api/circuits.protocols.websocket.html -docs/build/html/api/circuits.six.html -docs/build/html/api/circuits.tools.html -docs/build/html/api/circuits.version.html -docs/build/html/api/circuits.web.client.html -docs/build/html/api/circuits.web.constants.html -docs/build/html/api/circuits.web.controllers.html -docs/build/html/api/circuits.web.dispatchers.dispatcher.html -docs/build/html/api/circuits.web.dispatchers.html -docs/build/html/api/circuits.web.dispatchers.jsonrpc.html -docs/build/html/api/circuits.web.dispatchers.static.html -docs/build/html/api/circuits.web.dispatchers.virtualhosts.html -docs/build/html/api/circuits.web.dispatchers.xmlrpc.html -docs/build/html/api/circuits.web.errors.html -docs/build/html/api/circuits.web.events.html -docs/build/html/api/circuits.web.exceptions.html -docs/build/html/api/circuits.web.headers.html -docs/build/html/api/circuits.web.html -docs/build/html/api/circuits.web.http.html -docs/build/html/api/circuits.web.loggers.html -docs/build/html/api/circuits.web.main.html -docs/build/html/api/circuits.web.parsers.html -docs/build/html/api/circuits.web.parsers.http.html -docs/build/html/api/circuits.web.parsers.multipart.html -docs/build/html/api/circuits.web.parsers.querystring.html -docs/build/html/api/circuits.web.processors.html -docs/build/html/api/circuits.web.servers.html -docs/build/html/api/circuits.web.sessions.html -docs/build/html/api/circuits.web.tools.html -docs/build/html/api/circuits.web.url.html -docs/build/html/api/circuits.web.utils.html -docs/build/html/api/circuits.web.websockets.client.html -docs/build/html/api/circuits.web.websockets.dispatcher.html -docs/build/html/api/circuits.web.websockets.html -docs/build/html/api/circuits.web.wrappers.html -docs/build/html/api/circuits.web.wsgi.html -docs/build/html/api/index.html -docs/build/html/dev/contributing.html -docs/build/html/dev/index.html -docs/build/html/dev/introduction.html -docs/build/html/dev/processes.html -docs/build/html/dev/standards.html -docs/build/html/examples/index.html -docs/build/html/man/components.html -docs/build/html/man/debugger.html -docs/build/html/man/events.html -docs/build/html/man/handlers.html -docs/build/html/man/index.html -docs/build/html/man/manager.html -docs/build/html/man/values.html -docs/build/html/man/misc/tools.html -docs/build/html/start/downloading.html -docs/build/html/start/index.html -docs/build/html/start/installing.html -docs/build/html/start/quick.html -docs/build/html/start/requirements.html -docs/build/html/tutorials/index.html -docs/build/html/tutorials/telnet/index.html -docs/build/html/tutorials/woof/index.html -docs/build/html/web/features.html -docs/build/html/web/gettingstarted.html -docs/build/html/web/howtos.html -docs/build/html/web/index.html -docs/build/html/web/introduction.html -docs/build/html/web/miscellaneous.html -docs/source/.conf.py.un~ -docs/source/changes.rst -docs/source/conf.py -docs/source/contributors.rst -docs/source/faq.rst -docs/source/glossary.rst -docs/source/index.rst -docs/source/readme.rst -docs/source/roadmap.rst -docs/source/todo.rst -docs/source/_static/logo.png -docs/source/_static/rtd.css -docs/source/_static/tracsphinx.css -docs/source/_templates/layout.html -docs/source/_themes/om/genindex.html -docs/source/_themes/om/layout.html -docs/source/_themes/om/modindex.html -docs/source/_themes/om/search.html -docs/source/_themes/om/theme.conf -docs/source/_themes/om/static/default.css -docs/source/_themes/om/static/djangodocs.css -docs/source/_themes/om/static/docicons-behindscenes.png -docs/source/_themes/om/static/docicons-note.png -docs/source/_themes/om/static/docicons-philosophy.png -docs/source/_themes/om/static/homepage.css -docs/source/_themes/om/static/reset-fonts-grids.css -docs/source/api/circuits.app.daemon.rst -docs/source/api/circuits.app.rst -docs/source/api/circuits.core.bridge.rst -docs/source/api/circuits.core.components.rst -docs/source/api/circuits.core.debugger.rst -docs/source/api/circuits.core.events.rst -docs/source/api/circuits.core.handlers.rst -docs/source/api/circuits.core.helpers.rst -docs/source/api/circuits.core.loader.rst -docs/source/api/circuits.core.manager.rst -docs/source/api/circuits.core.pollers.rst -docs/source/api/circuits.core.rst -docs/source/api/circuits.core.timers.rst -docs/source/api/circuits.core.utils.rst -docs/source/api/circuits.core.values.rst -docs/source/api/circuits.core.workers.rst -docs/source/api/circuits.io.events.rst -docs/source/api/circuits.io.file.rst -docs/source/api/circuits.io.notify.rst -docs/source/api/circuits.io.process.rst -docs/source/api/circuits.io.rst -docs/source/api/circuits.io.serial.rst -docs/source/api/circuits.net.events.rst -docs/source/api/circuits.net.rst -docs/source/api/circuits.net.sockets.rst -docs/source/api/circuits.node.client.rst -docs/source/api/circuits.node.events.rst -docs/source/api/circuits.node.node.rst -docs/source/api/circuits.node.rst -docs/source/api/circuits.node.server.rst -docs/source/api/circuits.node.utils.rst -docs/source/api/circuits.protocols.http.rst -docs/source/api/circuits.protocols.irc.rst -docs/source/api/circuits.protocols.line.rst -docs/source/api/circuits.protocols.rst -docs/source/api/circuits.protocols.websocket.rst -docs/source/api/circuits.rst -docs/source/api/circuits.six.rst -docs/source/api/circuits.tools.rst -docs/source/api/circuits.version.rst -docs/source/api/circuits.web.client.rst -docs/source/api/circuits.web.constants.rst -docs/source/api/circuits.web.controllers.rst -docs/source/api/circuits.web.dispatchers.dispatcher.rst -docs/source/api/circuits.web.dispatchers.jsonrpc.rst -docs/source/api/circuits.web.dispatchers.rst -docs/source/api/circuits.web.dispatchers.static.rst -docs/source/api/circuits.web.dispatchers.virtualhosts.rst -docs/source/api/circuits.web.dispatchers.xmlrpc.rst -docs/source/api/circuits.web.errors.rst -docs/source/api/circuits.web.events.rst -docs/source/api/circuits.web.exceptions.rst -docs/source/api/circuits.web.headers.rst -docs/source/api/circuits.web.http.rst -docs/source/api/circuits.web.loggers.rst -docs/source/api/circuits.web.main.rst -docs/source/api/circuits.web.parsers.http.rst -docs/source/api/circuits.web.parsers.multipart.rst -docs/source/api/circuits.web.parsers.querystring.rst -docs/source/api/circuits.web.parsers.rst -docs/source/api/circuits.web.processors.rst -docs/source/api/circuits.web.rst -docs/source/api/circuits.web.servers.rst -docs/source/api/circuits.web.sessions.rst -docs/source/api/circuits.web.tools.rst -docs/source/api/circuits.web.url.rst -docs/source/api/circuits.web.utils.rst -docs/source/api/circuits.web.websockets.client.rst -docs/source/api/circuits.web.websockets.dispatcher.rst -docs/source/api/circuits.web.websockets.rst -docs/source/api/circuits.web.wrappers.rst -docs/source/api/circuits.web.wsgi.rst -docs/source/api/index.rst -docs/source/dev/contributing.rst -docs/source/dev/index.rst -docs/source/dev/introduction.rst -docs/source/dev/processes.rst -docs/source/dev/standards.rst -docs/source/examples/.echoserver.py.un~ -docs/source/examples/.helloweb.py.un~ -docs/source/examples/echoserver.py -docs/source/examples/hello.py -docs/source/examples/helloweb.py -docs/source/examples/index.rst -docs/source/images/CircuitsWebServer.png -docs/source/man/components.rst -docs/source/man/debugger.rst -docs/source/man/events.rst -docs/source/man/handlers.rst -docs/source/man/index.rst -docs/source/man/manager.rst -docs/source/man/values.rst -docs/source/man/examples/Telnet.dot -docs/source/man/examples/Telnet.png -docs/source/man/examples/handler_annotation.py -docs/source/man/examples/handler_returns.py -docs/source/man/misc/tools.rst -docs/source/start/downloading.rst -docs/source/start/index.rst -docs/source/start/installing.rst -docs/source/start/quick.rst -docs/source/start/requirements.rst -docs/source/tutorials/index.rst -docs/source/tutorials/telnet/Telnet.dot -docs/source/tutorials/telnet/index.rst -docs/source/tutorials/telnet/index.rst.bak -docs/source/tutorials/telnet/telnet.py -docs/source/tutorials/woof/.007.py.un~ -docs/source/tutorials/woof/001.py -docs/source/tutorials/woof/002.py -docs/source/tutorials/woof/003.py -docs/source/tutorials/woof/004.py -docs/source/tutorials/woof/005.py -docs/source/tutorials/woof/006.py -docs/source/tutorials/woof/007.py -docs/source/tutorials/woof/008.py -docs/source/tutorials/woof/009.py -docs/source/tutorials/woof/index.rst -docs/source/web/features.rst -docs/source/web/gettingstarted.rst -docs/source/web/howtos.rst -docs/source/web/index.rst -docs/source/web/introduction.rst -docs/source/web/miscellaneous.rst -examples/.wget.py.un~ -examples/99bottles.py -examples/cat.py -examples/chatserver.py -examples/circ.py -examples/dirwatch.py -examples/dnsclient.py -examples/dnsserver.py -examples/echoserial.py -examples/echoserver.py -examples/echoserverunix.py -examples/factorial.py -examples/filter.py -examples/hello.py -examples/hello_bridge.py -examples/index.rst -examples/ircbot.py -examples/ircclient.py -examples/ircd.py -examples/ping.py -examples/portforward.py -examples/proxy.py -examples/signals.py -examples/tail.py -examples/telnet.py -examples/timers.py -examples/wget.py -examples/node/hello_node.py -examples/node/nodeserver.py -examples/node/increment/client.py -examples/node/increment/server.py -examples/primitives/call.py -examples/primitives/fire.py -examples/primitives/wait.py -examples/testing/pytest/README.rst -examples/testing/pytest/conftest.py -examples/testing/pytest/hello.py -examples/testing/pytest/test_hello.py -examples/web/acldemo.py -examples/web/authdemo.py -examples/web/basecontrollers.py -examples/web/baseservers.py -examples/web/ca-chain.pem -examples/web/cert.pem -examples/web/controllers.py -examples/web/crud.py -examples/web/fileupload.py -examples/web/filtering.py -examples/web/forms.py -examples/web/httpauth.py -examples/web/jsoncontroller.py -examples/web/jsonrpc.py -examples/web/jsonserializer.py -examples/web/jsontool.py -examples/web/makotemplates.py -examples/web/server-cert.pem -examples/web/server-key.pem -examples/web/sessions.py -examples/web/shadowauth.py -examples/web/singleclickandrun.py -examples/web/ssl-forward-cert.py -examples/web/sslserver.py -examples/web/virtualhosts.py -examples/web/websocket.html -examples/web/websockets.py -examples/web/wiki.zip -examples/web/wsgi.py -examples/web/wsgiapp.py -examples/web/xmlrpc_demo.py -examples/web/static/css/base.css -examples/web/static/img/rss.gif -examples/web/static/img/valid-xhtml10.png -examples/web/static/img/vcss.gif -examples/web/terminal/terminal.py -examples/web/terminal/static/favicon.ico -examples/web/terminal/static/index.xhtml -examples/web/terminal/static/css/base.css -examples/web/terminal/static/js/jquery.js -examples/web/terminal/static/js/jquery.terminal.js -examples/web/terminal/static/js/main.js -examples/web/tpl/base.html -examples/web/tpl/index.html -examples/web/wiki/wiki.py -examples/web/wiki/defaultpages/BulletList -examples/web/wiki/defaultpages/CheatSheet -examples/web/wiki/defaultpages/DefinitionList -examples/web/wiki/defaultpages/FrontPage -examples/web/wiki/defaultpages/HeadingsPage -examples/web/wiki/defaultpages/HorizontalLine -examples/web/wiki/defaultpages/Indented -examples/web/wiki/defaultpages/Macros -examples/web/wiki/defaultpages/MixedList -examples/web/wiki/defaultpages/NoLineBreak -examples/web/wiki/defaultpages/NumberedList -examples/web/wiki/defaultpages/RenderedPre -examples/web/wiki/defaultpages/RenderedTable -examples/web/wiki/defaultpages/SandBox -examples/web/wiki/defaultpages/SiteMenu -examples/web/wiki/macros/__init__.py -examples/web/wiki/macros/html.py -examples/web/wiki/macros/include.py -examples/web/wiki/macros/utils.py -examples/web/wiki/macros/wiki.py -examples/web/wiki/static/Image.jpg -examples/web/wiki/static/favicon.ico -examples/web/wiki/static/css/pygments.css -examples/web/wiki/static/css/screen.css -examples/web/wiki/static/images/header_bg.png -examples/web/wiki/tpl/edit.html -examples/web/wiki/tpl/view.html -fabfile/__init__.py -fabfile/docker.py -fabfile/docs.py -fabfile/help.py -fabfile/utils.py -tests/__init__.py -tests/__init__.pyc -tests/conftest.py -tests/conftest.pyc -tests/main.py -tests/main.pyc -tests/__pycache__/__init__.cpython-32.pyc -tests/__pycache__/__init__.cpython-33.pyc -tests/__pycache__/__init__.cpython-34.pyc -tests/__pycache__/conftest.cpython-32.pyc -tests/__pycache__/conftest.cpython-33.pyc -tests/__pycache__/conftest.cpython-34.pyc -tests/app/__init__.py -tests/app/__init__.pyc -tests/app/app.py -tests/app/app.pyc -tests/app/test_daemon.py -tests/app/__pycache__/__init__.cpython-32.pyc -tests/app/__pycache__/__init__.cpython-33.pyc -tests/app/__pycache__/__init__.cpython-34.pyc -tests/app/__pycache__/app.cpython-32.pyc -tests/app/__pycache__/app.cpython-33.pyc -tests/app/__pycache__/app.cpython-34.pyc -tests/app/__pycache__/test_daemon.cpython-26-PYTEST.pyc -tests/app/__pycache__/test_daemon.cpython-27-PYTEST.pyc -tests/app/__pycache__/test_daemon.cpython-32-PYTEST.pyc -tests/app/__pycache__/test_daemon.cpython-33-PYTEST.pyc -tests/app/__pycache__/test_daemon.cpython-34-PYTEST.pyc -tests/core/.test_bridge.py.un~ -tests/core/__init__.py -tests/core/__init__.pyc -tests/core/app.py -tests/core/app.pyc -tests/core/signalapp.py -tests/core/signalapp.pyc -tests/core/test_bridge.py -tests/core/test_call_wait.py -tests/core/test_call_wait_order.py -tests/core/test_call_wait_timeout.py -tests/core/test_channel_selection.py -tests/core/test_complete.py -tests/core/test_component_repr.py -tests/core/test_component_setup.py -tests/core/test_component_targeting.py -tests/core/test_core.py -tests/core/test_debugger.py -tests/core/test_dynamic_handlers.py -tests/core/test_errors.py -tests/core/test_event.py -tests/core/test_event_priority.py -tests/core/test_feedback.py -tests/core/test_filters.py -tests/core/test_generate_events.py -tests/core/test_generator_value.py -tests/core/test_globals.py -tests/core/test_imports.py -tests/core/test_inheritence.py -tests/core/test_interface_query.py -tests/core/test_loader.py -tests/core/test_manager_repr.py -tests/core/test_new_filter.py -tests/core/test_priority.py -tests/core/test_signals.py -tests/core/test_timers.py -tests/core/test_utils.py -tests/core/test_value.py -tests/core/test_worker_process.py -tests/core/test_worker_thread.py -tests/core/__pycache__/__init__.cpython-32.pyc -tests/core/__pycache__/__init__.cpython-33.pyc -tests/core/__pycache__/__init__.cpython-34.pyc -tests/core/__pycache__/app.cpython-32.pyc -tests/core/__pycache__/app.cpython-33.pyc -tests/core/__pycache__/app.cpython-34.pyc -tests/core/__pycache__/signalapp.cpython-32.pyc -tests/core/__pycache__/signalapp.cpython-33.pyc -tests/core/__pycache__/signalapp.cpython-34.pyc -tests/core/__pycache__/test_bridge.cpython-26-PYTEST.pyc -tests/core/__pycache__/test_bridge.cpython-27-PYTEST.pyc -tests/core/__pycache__/test_bridge.cpython-32-PYTEST.pyc -tests/core/__pycache__/test_bridge.cpython-33-PYTEST.pyc -tests/core/__pycache__/test_bridge.cpython-34-PYTEST.pyc -tests/core/__pycache__/test_call_wait.cpython-26-PYTEST.pyc -tests/core/__pycache__/test_call_wait.cpython-27-PYTEST.pyc -tests/core/__pycache__/test_call_wait.cpython-32-PYTEST.pyc -tests/core/__pycache__/test_call_wait.cpython-33-PYTEST.pyc -tests/core/__pycache__/test_call_wait.cpython-34-PYTEST.pyc -tests/core/__pycache__/test_call_wait_order.cpython-26-PYTEST.pyc -tests/core/__pycache__/test_call_wait_order.cpython-27-PYTEST.pyc -tests/core/__pycache__/test_call_wait_order.cpython-32-PYTEST.pyc -tests/core/__pycache__/test_call_wait_order.cpython-33-PYTEST.pyc -tests/core/__pycache__/test_call_wait_order.cpython-34-PYTEST.pyc -tests/core/__pycache__/test_call_wait_timeout.cpython-26-PYTEST.pyc -tests/core/__pycache__/test_call_wait_timeout.cpython-27-PYTEST.pyc -tests/core/__pycache__/test_call_wait_timeout.cpython-32-PYTEST.pyc -tests/core/__pycache__/test_call_wait_timeout.cpython-33-PYTEST.pyc -tests/core/__pycache__/test_call_wait_timeout.cpython-34-PYTEST.pyc -tests/core/__pycache__/test_channel_selection.cpython-26-PYTEST.pyc -tests/core/__pycache__/test_channel_selection.cpython-27-PYTEST.pyc -tests/core/__pycache__/test_channel_selection.cpython-32-PYTEST.pyc -tests/core/__pycache__/test_channel_selection.cpython-33-PYTEST.pyc -tests/core/__pycache__/test_channel_selection.cpython-34-PYTEST.pyc -tests/core/__pycache__/test_complete.cpython-26-PYTEST.pyc -tests/core/__pycache__/test_complete.cpython-27-PYTEST.pyc -tests/core/__pycache__/test_complete.cpython-32-PYTEST.pyc -tests/core/__pycache__/test_complete.cpython-33-PYTEST.pyc -tests/core/__pycache__/test_complete.cpython-34-PYTEST.pyc -tests/core/__pycache__/test_component_repr.cpython-26-PYTEST.pyc -tests/core/__pycache__/test_component_repr.cpython-27-PYTEST.pyc -tests/core/__pycache__/test_component_repr.cpython-32-PYTEST.pyc -tests/core/__pycache__/test_component_repr.cpython-33-PYTEST.pyc -tests/core/__pycache__/test_component_repr.cpython-34-PYTEST.pyc -tests/core/__pycache__/test_component_setup.cpython-26-PYTEST.pyc -tests/core/__pycache__/test_component_setup.cpython-27-PYTEST.pyc -tests/core/__pycache__/test_component_setup.cpython-32-PYTEST.pyc -tests/core/__pycache__/test_component_setup.cpython-33-PYTEST.pyc -tests/core/__pycache__/test_component_setup.cpython-34-PYTEST.pyc -tests/core/__pycache__/test_component_targeting.cpython-26-PYTEST.pyc -tests/core/__pycache__/test_component_targeting.cpython-27-PYTEST.pyc -tests/core/__pycache__/test_component_targeting.cpython-32-PYTEST.pyc -tests/core/__pycache__/test_component_targeting.cpython-33-PYTEST.pyc -tests/core/__pycache__/test_component_targeting.cpython-34-PYTEST.pyc -tests/core/__pycache__/test_core.cpython-26-PYTEST.pyc -tests/core/__pycache__/test_core.cpython-27-PYTEST.pyc -tests/core/__pycache__/test_core.cpython-32-PYTEST.pyc -tests/core/__pycache__/test_core.cpython-33-PYTEST.pyc -tests/core/__pycache__/test_core.cpython-34-PYTEST.pyc -tests/core/__pycache__/test_debugger.cpython-26-PYTEST.pyc -tests/core/__pycache__/test_debugger.cpython-27-PYTEST.pyc -tests/core/__pycache__/test_debugger.cpython-32-PYTEST.pyc -tests/core/__pycache__/test_debugger.cpython-33-PYTEST.pyc -tests/core/__pycache__/test_debugger.cpython-34-PYTEST.pyc -tests/core/__pycache__/test_dynamic_handlers.cpython-26-PYTEST.pyc -tests/core/__pycache__/test_dynamic_handlers.cpython-27-PYTEST.pyc -tests/core/__pycache__/test_dynamic_handlers.cpython-32-PYTEST.pyc -tests/core/__pycache__/test_dynamic_handlers.cpython-33-PYTEST.pyc -tests/core/__pycache__/test_dynamic_handlers.cpython-34-PYTEST.pyc -tests/core/__pycache__/test_errors.cpython-26-PYTEST.pyc -tests/core/__pycache__/test_errors.cpython-27-PYTEST.pyc -tests/core/__pycache__/test_errors.cpython-32-PYTEST.pyc -tests/core/__pycache__/test_errors.cpython-33-PYTEST.pyc -tests/core/__pycache__/test_errors.cpython-34-PYTEST.pyc -tests/core/__pycache__/test_event.cpython-26-PYTEST.pyc -tests/core/__pycache__/test_event.cpython-27-PYTEST.pyc -tests/core/__pycache__/test_event.cpython-32-PYTEST.pyc -tests/core/__pycache__/test_event.cpython-33-PYTEST.pyc -tests/core/__pycache__/test_event.cpython-34-PYTEST.pyc -tests/core/__pycache__/test_event_priority.cpython-26-PYTEST.pyc -tests/core/__pycache__/test_event_priority.cpython-27-PYTEST.pyc -tests/core/__pycache__/test_event_priority.cpython-32-PYTEST.pyc -tests/core/__pycache__/test_event_priority.cpython-33-PYTEST.pyc -tests/core/__pycache__/test_event_priority.cpython-34-PYTEST.pyc -tests/core/__pycache__/test_feedback.cpython-26-PYTEST.pyc -tests/core/__pycache__/test_feedback.cpython-27-PYTEST.pyc -tests/core/__pycache__/test_feedback.cpython-32-PYTEST.pyc -tests/core/__pycache__/test_feedback.cpython-33-PYTEST.pyc -tests/core/__pycache__/test_feedback.cpython-34-PYTEST.pyc -tests/core/__pycache__/test_filters.cpython-26-PYTEST.pyc -tests/core/__pycache__/test_filters.cpython-27-PYTEST.pyc -tests/core/__pycache__/test_filters.cpython-32-PYTEST.pyc -tests/core/__pycache__/test_filters.cpython-33-PYTEST.pyc -tests/core/__pycache__/test_filters.cpython-34-PYTEST.pyc -tests/core/__pycache__/test_generate_events.cpython-26-PYTEST.pyc -tests/core/__pycache__/test_generate_events.cpython-27-PYTEST.pyc -tests/core/__pycache__/test_generate_events.cpython-32-PYTEST.pyc -tests/core/__pycache__/test_generate_events.cpython-33-PYTEST.pyc -tests/core/__pycache__/test_generate_events.cpython-34-PYTEST.pyc -tests/core/__pycache__/test_generator_value.cpython-26-PYTEST.pyc -tests/core/__pycache__/test_generator_value.cpython-27-PYTEST.pyc -tests/core/__pycache__/test_generator_value.cpython-32-PYTEST.pyc -tests/core/__pycache__/test_generator_value.cpython-33-PYTEST.pyc -tests/core/__pycache__/test_generator_value.cpython-34-PYTEST.pyc -tests/core/__pycache__/test_globals.cpython-26-PYTEST.pyc -tests/core/__pycache__/test_globals.cpython-27-PYTEST.pyc -tests/core/__pycache__/test_globals.cpython-32-PYTEST.pyc -tests/core/__pycache__/test_globals.cpython-33-PYTEST.pyc -tests/core/__pycache__/test_globals.cpython-34-PYTEST.pyc -tests/core/__pycache__/test_imports.cpython-26-PYTEST.pyc -tests/core/__pycache__/test_imports.cpython-27-PYTEST.pyc -tests/core/__pycache__/test_imports.cpython-32-PYTEST.pyc -tests/core/__pycache__/test_imports.cpython-33-PYTEST.pyc -tests/core/__pycache__/test_imports.cpython-34-PYTEST.pyc -tests/core/__pycache__/test_inheritence.cpython-26-PYTEST.pyc -tests/core/__pycache__/test_inheritence.cpython-27-PYTEST.pyc -tests/core/__pycache__/test_inheritence.cpython-32-PYTEST.pyc -tests/core/__pycache__/test_inheritence.cpython-33-PYTEST.pyc -tests/core/__pycache__/test_inheritence.cpython-34-PYTEST.pyc -tests/core/__pycache__/test_interface_query.cpython-26-PYTEST.pyc -tests/core/__pycache__/test_interface_query.cpython-27-PYTEST.pyc -tests/core/__pycache__/test_interface_query.cpython-32-PYTEST.pyc -tests/core/__pycache__/test_interface_query.cpython-33-PYTEST.pyc -tests/core/__pycache__/test_interface_query.cpython-34-PYTEST.pyc -tests/core/__pycache__/test_loader.cpython-26-PYTEST.pyc -tests/core/__pycache__/test_loader.cpython-27-PYTEST.pyc -tests/core/__pycache__/test_loader.cpython-32-PYTEST.pyc -tests/core/__pycache__/test_loader.cpython-33-PYTEST.pyc -tests/core/__pycache__/test_loader.cpython-34-PYTEST.pyc -tests/core/__pycache__/test_manager_repr.cpython-26-PYTEST.pyc -tests/core/__pycache__/test_manager_repr.cpython-27-PYTEST.pyc -tests/core/__pycache__/test_manager_repr.cpython-32-PYTEST.pyc -tests/core/__pycache__/test_manager_repr.cpython-33-PYTEST.pyc -tests/core/__pycache__/test_manager_repr.cpython-34-PYTEST.pyc -tests/core/__pycache__/test_new_filter.cpython-26-PYTEST.pyc -tests/core/__pycache__/test_new_filter.cpython-27-PYTEST.pyc -tests/core/__pycache__/test_new_filter.cpython-32-PYTEST.pyc -tests/core/__pycache__/test_new_filter.cpython-33-PYTEST.pyc -tests/core/__pycache__/test_new_filter.cpython-34-PYTEST.pyc -tests/core/__pycache__/test_priority.cpython-26-PYTEST.pyc -tests/core/__pycache__/test_priority.cpython-27-PYTEST.pyc -tests/core/__pycache__/test_priority.cpython-32-PYTEST.pyc -tests/core/__pycache__/test_priority.cpython-33-PYTEST.pyc -tests/core/__pycache__/test_priority.cpython-34-PYTEST.pyc -tests/core/__pycache__/test_signals.cpython-26-PYTEST.pyc -tests/core/__pycache__/test_signals.cpython-27-PYTEST.pyc -tests/core/__pycache__/test_signals.cpython-32-PYTEST.pyc -tests/core/__pycache__/test_signals.cpython-33-PYTEST.pyc -tests/core/__pycache__/test_signals.cpython-34-PYTEST.pyc -tests/core/__pycache__/test_timers.cpython-26-PYTEST.pyc -tests/core/__pycache__/test_timers.cpython-27-PYTEST.pyc -tests/core/__pycache__/test_timers.cpython-32-PYTEST.pyc -tests/core/__pycache__/test_timers.cpython-33-PYTEST.pyc -tests/core/__pycache__/test_timers.cpython-34-PYTEST.pyc -tests/core/__pycache__/test_utils.cpython-26-PYTEST.pyc -tests/core/__pycache__/test_utils.cpython-27-PYTEST.pyc -tests/core/__pycache__/test_utils.cpython-32-PYTEST.pyc -tests/core/__pycache__/test_utils.cpython-33-PYTEST.pyc -tests/core/__pycache__/test_utils.cpython-34-PYTEST.pyc -tests/core/__pycache__/test_value.cpython-26-PYTEST.pyc -tests/core/__pycache__/test_value.cpython-27-PYTEST.pyc -tests/core/__pycache__/test_value.cpython-32-PYTEST.pyc -tests/core/__pycache__/test_value.cpython-33-PYTEST.pyc -tests/core/__pycache__/test_value.cpython-34-PYTEST.pyc -tests/core/__pycache__/test_worker_process.cpython-26-PYTEST.pyc -tests/core/__pycache__/test_worker_process.cpython-27-PYTEST.pyc -tests/core/__pycache__/test_worker_process.cpython-32-PYTEST.pyc -tests/core/__pycache__/test_worker_process.cpython-33-PYTEST.pyc -tests/core/__pycache__/test_worker_process.cpython-34-PYTEST.pyc -tests/core/__pycache__/test_worker_thread.cpython-26-PYTEST.pyc -tests/core/__pycache__/test_worker_thread.cpython-27-PYTEST.pyc -tests/core/__pycache__/test_worker_thread.cpython-32-PYTEST.pyc -tests/core/__pycache__/test_worker_thread.cpython-33-PYTEST.pyc -tests/core/__pycache__/test_worker_thread.cpython-34-PYTEST.pyc -tests/io/__init__.py -tests/io/__init__.pyc -tests/io/test_file.py -tests/io/test_notify.py -tests/io/test_process.py -tests/io/__pycache__/__init__.cpython-32.pyc -tests/io/__pycache__/__init__.cpython-33.pyc -tests/io/__pycache__/__init__.cpython-34.pyc -tests/io/__pycache__/test_file.cpython-26-PYTEST.pyc -tests/io/__pycache__/test_file.cpython-27-PYTEST.pyc -tests/io/__pycache__/test_file.cpython-32-PYTEST.pyc -tests/io/__pycache__/test_file.cpython-33-PYTEST.pyc -tests/io/__pycache__/test_file.cpython-34-PYTEST.pyc -tests/io/__pycache__/test_notify.cpython-26-PYTEST.pyc -tests/io/__pycache__/test_notify.cpython-27-PYTEST.pyc -tests/io/__pycache__/test_notify.cpython-32-PYTEST.pyc -tests/io/__pycache__/test_notify.cpython-33-PYTEST.pyc -tests/io/__pycache__/test_notify.cpython-34-PYTEST.pyc -tests/io/__pycache__/test_process.cpython-26-PYTEST.pyc -tests/io/__pycache__/test_process.cpython-27-PYTEST.pyc -tests/io/__pycache__/test_process.cpython-32-PYTEST.pyc -tests/io/__pycache__/test_process.cpython-33-PYTEST.pyc -tests/io/__pycache__/test_process.cpython-34-PYTEST.pyc -tests/net/__init__.py -tests/net/__init__.pyc -tests/net/client.py -tests/net/client.pyc -tests/net/server.py -tests/net/server.pyc -tests/net/test_client.py -tests/net/test_pipe.py -tests/net/test_poller_reuse.py -tests/net/test_tcp.py -tests/net/test_udp.py -tests/net/test_unix.py -tests/net/__pycache__/__init__.cpython-32.pyc -tests/net/__pycache__/__init__.cpython-33.pyc -tests/net/__pycache__/__init__.cpython-34.pyc -tests/net/__pycache__/client.cpython-32.pyc -tests/net/__pycache__/client.cpython-33.pyc -tests/net/__pycache__/client.cpython-34.pyc -tests/net/__pycache__/server.cpython-32.pyc -tests/net/__pycache__/server.cpython-33.pyc -tests/net/__pycache__/server.cpython-34.pyc -tests/net/__pycache__/test_client.cpython-26-PYTEST.pyc -tests/net/__pycache__/test_client.cpython-27-PYTEST.pyc -tests/net/__pycache__/test_client.cpython-32-PYTEST.pyc -tests/net/__pycache__/test_client.cpython-33-PYTEST.pyc -tests/net/__pycache__/test_client.cpython-34-PYTEST.pyc -tests/net/__pycache__/test_pipe.cpython-26-PYTEST.pyc -tests/net/__pycache__/test_pipe.cpython-27-PYTEST.pyc -tests/net/__pycache__/test_pipe.cpython-32-PYTEST.pyc -tests/net/__pycache__/test_pipe.cpython-33-PYTEST.pyc -tests/net/__pycache__/test_pipe.cpython-34-PYTEST.pyc -tests/net/__pycache__/test_poller_reuse.cpython-26-PYTEST.pyc -tests/net/__pycache__/test_poller_reuse.cpython-27-PYTEST.pyc -tests/net/__pycache__/test_poller_reuse.cpython-32-PYTEST.pyc -tests/net/__pycache__/test_poller_reuse.cpython-33-PYTEST.pyc -tests/net/__pycache__/test_poller_reuse.cpython-34-PYTEST.pyc -tests/net/__pycache__/test_tcp.cpython-26-PYTEST.pyc -tests/net/__pycache__/test_tcp.cpython-27-PYTEST.pyc -tests/net/__pycache__/test_tcp.cpython-32-PYTEST.pyc -tests/net/__pycache__/test_tcp.cpython-33-PYTEST.pyc -tests/net/__pycache__/test_tcp.cpython-34-PYTEST.pyc -tests/net/__pycache__/test_udp.cpython-26-PYTEST.pyc -tests/net/__pycache__/test_udp.cpython-27-PYTEST.pyc -tests/net/__pycache__/test_udp.cpython-32-PYTEST.pyc -tests/net/__pycache__/test_udp.cpython-33-PYTEST.pyc -tests/net/__pycache__/test_udp.cpython-34-PYTEST.pyc -tests/net/__pycache__/test_unix.cpython-26-PYTEST.pyc -tests/net/__pycache__/test_unix.cpython-27-PYTEST.pyc -tests/net/__pycache__/test_unix.cpython-32-PYTEST.pyc -tests/net/__pycache__/test_unix.cpython-33-PYTEST.pyc -tests/net/__pycache__/test_unix.cpython-34-PYTEST.pyc -tests/node/test_node.py -tests/node/test_utils.py -tests/node/__pycache__/test_node.cpython-26-PYTEST.pyc -tests/node/__pycache__/test_node.cpython-27-PYTEST.pyc -tests/node/__pycache__/test_node.cpython-32-PYTEST.pyc -tests/node/__pycache__/test_node.cpython-33-PYTEST.pyc -tests/node/__pycache__/test_node.cpython-34-PYTEST.pyc -tests/node/__pycache__/test_utils.cpython-26-PYTEST.pyc -tests/node/__pycache__/test_utils.cpython-27-PYTEST.pyc -tests/node/__pycache__/test_utils.cpython-32-PYTEST.pyc -tests/node/__pycache__/test_utils.cpython-33-PYTEST.pyc -tests/node/__pycache__/test_utils.cpython-34-PYTEST.pyc -tests/protocols/.test_irc.py.un~ -tests/protocols/__init__.py -tests/protocols/__init__.pyc -tests/protocols/test_irc.py -tests/protocols/test_line.py -tests/protocols/__pycache__/__init__.cpython-32.pyc -tests/protocols/__pycache__/__init__.cpython-33.pyc -tests/protocols/__pycache__/__init__.cpython-34.pyc -tests/protocols/__pycache__/test_irc.cpython-26-PYTEST.pyc -tests/protocols/__pycache__/test_irc.cpython-27-PYTEST.pyc -tests/protocols/__pycache__/test_irc.cpython-32-PYTEST.pyc -tests/protocols/__pycache__/test_irc.cpython-33-PYTEST.pyc -tests/protocols/__pycache__/test_irc.cpython-34-PYTEST.pyc -tests/protocols/__pycache__/test_line.cpython-26-PYTEST.pyc -tests/protocols/__pycache__/test_line.cpython-27-PYTEST.pyc -tests/protocols/__pycache__/test_line.cpython-32-PYTEST.pyc -tests/protocols/__pycache__/test_line.cpython-33-PYTEST.pyc -tests/protocols/__pycache__/test_line.cpython-34-PYTEST.pyc -tests/tools/__init__.py -tests/tools/__init__.pyc -tests/tools/test_tools.py -tests/tools/__pycache__/__init__.cpython-32.pyc -tests/tools/__pycache__/__init__.cpython-33.pyc -tests/tools/__pycache__/__init__.cpython-34.pyc -tests/tools/__pycache__/test_tools.cpython-26-PYTEST.pyc -tests/tools/__pycache__/test_tools.cpython-27-PYTEST.pyc -tests/tools/__pycache__/test_tools.cpython-32-PYTEST.pyc -tests/tools/__pycache__/test_tools.cpython-33-PYTEST.pyc -tests/tools/__pycache__/test_tools.cpython-34-PYTEST.pyc -tests/web/__init__.py -tests/web/__init__.pyc -tests/web/cert.pem -tests/web/conftest.py -tests/web/conftest.pyc -tests/web/helpers.py -tests/web/helpers.pyc -tests/web/jsonrpclib.py -tests/web/jsonrpclib.pyc -tests/web/multipartform.py -tests/web/multipartform.pyc -tests/web/test_bad_requests.py -tests/web/test_basicauth.py -tests/web/test_call_wait.py -tests/web/test_client.py -tests/web/test_conn.py -tests/web/test_cookies.py -tests/web/test_core.py -tests/web/test_digestauth.py -tests/web/test_dispatcher.py -tests/web/test_dispatcher2.py -tests/web/test_dispatcher3.py -tests/web/test_disps.py -tests/web/test_exceptions.py -tests/web/test_expires.py -tests/web/test_expose.py -tests/web/test_generator.py -tests/web/test_gzip.py -tests/web/test_headers.py -tests/web/test_http.py -tests/web/test_json.py -tests/web/test_jsonrpc.py -tests/web/test_large_post.py -tests/web/test_logger.py -tests/web/test_methods.py -tests/web/test_multipartformdata.py -tests/web/test_null_response.py -tests/web/test_request_failure.py -tests/web/test_security.py -tests/web/test_serve_download.py -tests/web/test_serve_file.py -tests/web/test_servers.py -tests/web/test_sessions.py -tests/web/test_static.py -tests/web/test_unicode.py -tests/web/test_utils.py -tests/web/test_value.py -tests/web/test_vpath_args.py -tests/web/test_websockets.py -tests/web/test_wsgi_application.py -tests/web/test_wsgi_application_generator.py -tests/web/test_wsgi_application_yield.py -tests/web/test_wsgi_gateway.py -tests/web/test_wsgi_gateway_errors.py -tests/web/test_wsgi_gateway_generator.py -tests/web/test_wsgi_gateway_multiple_apps.py -tests/web/test_wsgi_gateway_null_response.py -tests/web/test_wsgi_gateway_write.py -tests/web/test_wsgi_gateway_yield.py -tests/web/test_xmlrpc.py -tests/web/test_yield.py -tests/web/websocket.py -tests/web/__pycache__/__init__.cpython-32.pyc -tests/web/__pycache__/__init__.cpython-33.pyc -tests/web/__pycache__/__init__.cpython-34.pyc -tests/web/__pycache__/conftest.cpython-32.pyc -tests/web/__pycache__/conftest.cpython-33.pyc -tests/web/__pycache__/conftest.cpython-34.pyc -tests/web/__pycache__/helpers.cpython-32.pyc -tests/web/__pycache__/helpers.cpython-33.pyc -tests/web/__pycache__/helpers.cpython-34.pyc -tests/web/__pycache__/jsonrpclib.cpython-32.pyc -tests/web/__pycache__/jsonrpclib.cpython-33.pyc -tests/web/__pycache__/jsonrpclib.cpython-34.pyc -tests/web/__pycache__/multipartform.cpython-32.pyc -tests/web/__pycache__/multipartform.cpython-33.pyc -tests/web/__pycache__/multipartform.cpython-34.pyc -tests/web/__pycache__/test_bad_requests.cpython-26-PYTEST.pyc -tests/web/__pycache__/test_bad_requests.cpython-27-PYTEST.pyc -tests/web/__pycache__/test_bad_requests.cpython-32-PYTEST.pyc -tests/web/__pycache__/test_bad_requests.cpython-33-PYTEST.pyc -tests/web/__pycache__/test_bad_requests.cpython-34-PYTEST.pyc -tests/web/__pycache__/test_basicauth.cpython-26-PYTEST.pyc -tests/web/__pycache__/test_basicauth.cpython-27-PYTEST.pyc -tests/web/__pycache__/test_basicauth.cpython-32-PYTEST.pyc -tests/web/__pycache__/test_basicauth.cpython-33-PYTEST.pyc -tests/web/__pycache__/test_basicauth.cpython-34-PYTEST.pyc -tests/web/__pycache__/test_call_wait.cpython-26-PYTEST.pyc -tests/web/__pycache__/test_call_wait.cpython-27-PYTEST.pyc -tests/web/__pycache__/test_call_wait.cpython-32-PYTEST.pyc -tests/web/__pycache__/test_call_wait.cpython-33-PYTEST.pyc -tests/web/__pycache__/test_call_wait.cpython-34-PYTEST.pyc -tests/web/__pycache__/test_client.cpython-26-PYTEST.pyc -tests/web/__pycache__/test_client.cpython-27-PYTEST.pyc -tests/web/__pycache__/test_client.cpython-32-PYTEST.pyc -tests/web/__pycache__/test_client.cpython-33-PYTEST.pyc -tests/web/__pycache__/test_client.cpython-34-PYTEST.pyc -tests/web/__pycache__/test_conn.cpython-26-PYTEST.pyc -tests/web/__pycache__/test_conn.cpython-27-PYTEST.pyc -tests/web/__pycache__/test_conn.cpython-32-PYTEST.pyc -tests/web/__pycache__/test_conn.cpython-33-PYTEST.pyc -tests/web/__pycache__/test_conn.cpython-34-PYTEST.pyc -tests/web/__pycache__/test_cookies.cpython-26-PYTEST.pyc -tests/web/__pycache__/test_cookies.cpython-27-PYTEST.pyc -tests/web/__pycache__/test_cookies.cpython-32-PYTEST.pyc -tests/web/__pycache__/test_cookies.cpython-33-PYTEST.pyc -tests/web/__pycache__/test_cookies.cpython-34-PYTEST.pyc -tests/web/__pycache__/test_core.cpython-26-PYTEST.pyc -tests/web/__pycache__/test_core.cpython-27-PYTEST.pyc -tests/web/__pycache__/test_core.cpython-32-PYTEST.pyc -tests/web/__pycache__/test_core.cpython-33-PYTEST.pyc -tests/web/__pycache__/test_core.cpython-34-PYTEST.pyc -tests/web/__pycache__/test_digestauth.cpython-26-PYTEST.pyc -tests/web/__pycache__/test_digestauth.cpython-27-PYTEST.pyc -tests/web/__pycache__/test_digestauth.cpython-32-PYTEST.pyc -tests/web/__pycache__/test_digestauth.cpython-33-PYTEST.pyc -tests/web/__pycache__/test_digestauth.cpython-34-PYTEST.pyc -tests/web/__pycache__/test_dispatcher.cpython-26-PYTEST.pyc -tests/web/__pycache__/test_dispatcher.cpython-27-PYTEST.pyc -tests/web/__pycache__/test_dispatcher.cpython-32-PYTEST.pyc -tests/web/__pycache__/test_dispatcher.cpython-33-PYTEST.pyc -tests/web/__pycache__/test_dispatcher.cpython-34-PYTEST.pyc -tests/web/__pycache__/test_dispatcher2.cpython-26-PYTEST.pyc -tests/web/__pycache__/test_dispatcher2.cpython-27-PYTEST.pyc -tests/web/__pycache__/test_dispatcher2.cpython-32-PYTEST.pyc -tests/web/__pycache__/test_dispatcher2.cpython-33-PYTEST.pyc -tests/web/__pycache__/test_dispatcher2.cpython-34-PYTEST.pyc -tests/web/__pycache__/test_dispatcher3.cpython-26-PYTEST.pyc -tests/web/__pycache__/test_dispatcher3.cpython-27-PYTEST.pyc -tests/web/__pycache__/test_dispatcher3.cpython-32-PYTEST.pyc -tests/web/__pycache__/test_dispatcher3.cpython-33-PYTEST.pyc -tests/web/__pycache__/test_dispatcher3.cpython-34-PYTEST.pyc -tests/web/__pycache__/test_disps.cpython-26-PYTEST.pyc -tests/web/__pycache__/test_disps.cpython-27-PYTEST.pyc -tests/web/__pycache__/test_disps.cpython-32-PYTEST.pyc -tests/web/__pycache__/test_disps.cpython-33-PYTEST.pyc -tests/web/__pycache__/test_disps.cpython-34-PYTEST.pyc -tests/web/__pycache__/test_exceptions.cpython-26-PYTEST.pyc -tests/web/__pycache__/test_exceptions.cpython-27-PYTEST.pyc -tests/web/__pycache__/test_exceptions.cpython-32-PYTEST.pyc -tests/web/__pycache__/test_exceptions.cpython-33-PYTEST.pyc -tests/web/__pycache__/test_exceptions.cpython-34-PYTEST.pyc -tests/web/__pycache__/test_expires.cpython-26-PYTEST.pyc -tests/web/__pycache__/test_expires.cpython-27-PYTEST.pyc -tests/web/__pycache__/test_expires.cpython-32-PYTEST.pyc -tests/web/__pycache__/test_expires.cpython-33-PYTEST.pyc -tests/web/__pycache__/test_expires.cpython-34-PYTEST.pyc -tests/web/__pycache__/test_expose.cpython-26-PYTEST.pyc -tests/web/__pycache__/test_expose.cpython-27-PYTEST.pyc -tests/web/__pycache__/test_expose.cpython-32-PYTEST.pyc -tests/web/__pycache__/test_expose.cpython-33-PYTEST.pyc -tests/web/__pycache__/test_expose.cpython-34-PYTEST.pyc -tests/web/__pycache__/test_generator.cpython-26-PYTEST.pyc -tests/web/__pycache__/test_generator.cpython-27-PYTEST.pyc -tests/web/__pycache__/test_generator.cpython-32-PYTEST.pyc -tests/web/__pycache__/test_generator.cpython-33-PYTEST.pyc -tests/web/__pycache__/test_generator.cpython-34-PYTEST.pyc -tests/web/__pycache__/test_gzip.cpython-26-PYTEST.pyc -tests/web/__pycache__/test_gzip.cpython-27-PYTEST.pyc -tests/web/__pycache__/test_gzip.cpython-32-PYTEST.pyc -tests/web/__pycache__/test_gzip.cpython-33-PYTEST.pyc -tests/web/__pycache__/test_gzip.cpython-34-PYTEST.pyc -tests/web/__pycache__/test_headers.cpython-26-PYTEST.pyc -tests/web/__pycache__/test_headers.cpython-27-PYTEST.pyc -tests/web/__pycache__/test_headers.cpython-32-PYTEST.pyc -tests/web/__pycache__/test_headers.cpython-33-PYTEST.pyc -tests/web/__pycache__/test_headers.cpython-34-PYTEST.pyc -tests/web/__pycache__/test_http.cpython-26-PYTEST.pyc -tests/web/__pycache__/test_http.cpython-27-PYTEST.pyc -tests/web/__pycache__/test_http.cpython-32-PYTEST.pyc -tests/web/__pycache__/test_http.cpython-33-PYTEST.pyc -tests/web/__pycache__/test_http.cpython-34-PYTEST.pyc -tests/web/__pycache__/test_json.cpython-26-PYTEST.pyc -tests/web/__pycache__/test_json.cpython-27-PYTEST.pyc -tests/web/__pycache__/test_json.cpython-32-PYTEST.pyc -tests/web/__pycache__/test_json.cpython-33-PYTEST.pyc -tests/web/__pycache__/test_json.cpython-34-PYTEST.pyc -tests/web/__pycache__/test_jsonrpc.cpython-26-PYTEST.pyc -tests/web/__pycache__/test_jsonrpc.cpython-27-PYTEST.pyc -tests/web/__pycache__/test_jsonrpc.cpython-32-PYTEST.pyc -tests/web/__pycache__/test_jsonrpc.cpython-33-PYTEST.pyc -tests/web/__pycache__/test_jsonrpc.cpython-34-PYTEST.pyc -tests/web/__pycache__/test_large_post.cpython-26-PYTEST.pyc -tests/web/__pycache__/test_large_post.cpython-27-PYTEST.pyc -tests/web/__pycache__/test_large_post.cpython-32-PYTEST.pyc -tests/web/__pycache__/test_large_post.cpython-33-PYTEST.pyc -tests/web/__pycache__/test_large_post.cpython-34-PYTEST.pyc -tests/web/__pycache__/test_logger.cpython-26-PYTEST.pyc -tests/web/__pycache__/test_logger.cpython-27-PYTEST.pyc -tests/web/__pycache__/test_logger.cpython-32-PYTEST.pyc -tests/web/__pycache__/test_logger.cpython-33-PYTEST.pyc -tests/web/__pycache__/test_logger.cpython-34-PYTEST.pyc -tests/web/__pycache__/test_methods.cpython-26-PYTEST.pyc -tests/web/__pycache__/test_methods.cpython-27-PYTEST.pyc -tests/web/__pycache__/test_methods.cpython-32-PYTEST.pyc -tests/web/__pycache__/test_methods.cpython-33-PYTEST.pyc -tests/web/__pycache__/test_methods.cpython-34-PYTEST.pyc -tests/web/__pycache__/test_multipartformdata.cpython-26-PYTEST.pyc -tests/web/__pycache__/test_multipartformdata.cpython-27-PYTEST.pyc -tests/web/__pycache__/test_multipartformdata.cpython-32-PYTEST.pyc -tests/web/__pycache__/test_multipartformdata.cpython-33-PYTEST.pyc -tests/web/__pycache__/test_multipartformdata.cpython-34-PYTEST.pyc -tests/web/__pycache__/test_null_response.cpython-26-PYTEST.pyc -tests/web/__pycache__/test_null_response.cpython-27-PYTEST.pyc -tests/web/__pycache__/test_null_response.cpython-32-PYTEST.pyc -tests/web/__pycache__/test_null_response.cpython-33-PYTEST.pyc -tests/web/__pycache__/test_null_response.cpython-34-PYTEST.pyc -tests/web/__pycache__/test_request_failure.cpython-26-PYTEST.pyc -tests/web/__pycache__/test_request_failure.cpython-27-PYTEST.pyc -tests/web/__pycache__/test_request_failure.cpython-32-PYTEST.pyc -tests/web/__pycache__/test_request_failure.cpython-33-PYTEST.pyc -tests/web/__pycache__/test_request_failure.cpython-34-PYTEST.pyc -tests/web/__pycache__/test_security.cpython-26-PYTEST.pyc -tests/web/__pycache__/test_security.cpython-27-PYTEST.pyc -tests/web/__pycache__/test_security.cpython-32-PYTEST.pyc -tests/web/__pycache__/test_security.cpython-33-PYTEST.pyc -tests/web/__pycache__/test_security.cpython-34-PYTEST.pyc -tests/web/__pycache__/test_serve_download.cpython-26-PYTEST.pyc -tests/web/__pycache__/test_serve_download.cpython-27-PYTEST.pyc -tests/web/__pycache__/test_serve_download.cpython-32-PYTEST.pyc -tests/web/__pycache__/test_serve_download.cpython-33-PYTEST.pyc -tests/web/__pycache__/test_serve_download.cpython-34-PYTEST.pyc -tests/web/__pycache__/test_serve_file.cpython-26-PYTEST.pyc -tests/web/__pycache__/test_serve_file.cpython-27-PYTEST.pyc -tests/web/__pycache__/test_serve_file.cpython-32-PYTEST.pyc -tests/web/__pycache__/test_serve_file.cpython-33-PYTEST.pyc -tests/web/__pycache__/test_serve_file.cpython-34-PYTEST.pyc -tests/web/__pycache__/test_servers.cpython-26-PYTEST.pyc -tests/web/__pycache__/test_servers.cpython-27-PYTEST.pyc -tests/web/__pycache__/test_servers.cpython-32-PYTEST.pyc -tests/web/__pycache__/test_servers.cpython-33-PYTEST.pyc -tests/web/__pycache__/test_servers.cpython-34-PYTEST.pyc -tests/web/__pycache__/test_sessions.cpython-26-PYTEST.pyc -tests/web/__pycache__/test_sessions.cpython-27-PYTEST.pyc -tests/web/__pycache__/test_sessions.cpython-32-PYTEST.pyc -tests/web/__pycache__/test_sessions.cpython-33-PYTEST.pyc -tests/web/__pycache__/test_sessions.cpython-34-PYTEST.pyc -tests/web/__pycache__/test_static.cpython-26-PYTEST.pyc -tests/web/__pycache__/test_static.cpython-27-PYTEST.pyc -tests/web/__pycache__/test_static.cpython-32-PYTEST.pyc -tests/web/__pycache__/test_static.cpython-33-PYTEST.pyc -tests/web/__pycache__/test_static.cpython-34-PYTEST.pyc -tests/web/__pycache__/test_unicode.cpython-26-PYTEST.pyc -tests/web/__pycache__/test_unicode.cpython-27-PYTEST.pyc -tests/web/__pycache__/test_unicode.cpython-32-PYTEST.pyc -tests/web/__pycache__/test_unicode.cpython-33-PYTEST.pyc -tests/web/__pycache__/test_unicode.cpython-34-PYTEST.pyc -tests/web/__pycache__/test_utils.cpython-26-PYTEST.pyc -tests/web/__pycache__/test_utils.cpython-27-PYTEST.pyc -tests/web/__pycache__/test_utils.cpython-32-PYTEST.pyc -tests/web/__pycache__/test_utils.cpython-33-PYTEST.pyc -tests/web/__pycache__/test_utils.cpython-34-PYTEST.pyc -tests/web/__pycache__/test_value.cpython-26-PYTEST.pyc -tests/web/__pycache__/test_value.cpython-27-PYTEST.pyc -tests/web/__pycache__/test_value.cpython-32-PYTEST.pyc -tests/web/__pycache__/test_value.cpython-33-PYTEST.pyc -tests/web/__pycache__/test_value.cpython-34-PYTEST.pyc -tests/web/__pycache__/test_vpath_args.cpython-26-PYTEST.pyc -tests/web/__pycache__/test_vpath_args.cpython-27-PYTEST.pyc -tests/web/__pycache__/test_vpath_args.cpython-32-PYTEST.pyc -tests/web/__pycache__/test_vpath_args.cpython-33-PYTEST.pyc -tests/web/__pycache__/test_vpath_args.cpython-34-PYTEST.pyc -tests/web/__pycache__/test_websockets.cpython-26-PYTEST.pyc -tests/web/__pycache__/test_websockets.cpython-27-PYTEST.pyc -tests/web/__pycache__/test_websockets.cpython-32-PYTEST.pyc -tests/web/__pycache__/test_websockets.cpython-33-PYTEST.pyc -tests/web/__pycache__/test_websockets.cpython-34-PYTEST.pyc -tests/web/__pycache__/test_wsgi_application.cpython-26-PYTEST.pyc -tests/web/__pycache__/test_wsgi_application.cpython-27-PYTEST.pyc -tests/web/__pycache__/test_wsgi_application.cpython-32-PYTEST.pyc -tests/web/__pycache__/test_wsgi_application.cpython-33-PYTEST.pyc -tests/web/__pycache__/test_wsgi_application.cpython-34-PYTEST.pyc -tests/web/__pycache__/test_wsgi_application_generator.cpython-26-PYTEST.pyc -tests/web/__pycache__/test_wsgi_application_generator.cpython-27-PYTEST.pyc -tests/web/__pycache__/test_wsgi_application_generator.cpython-32-PYTEST.pyc -tests/web/__pycache__/test_wsgi_application_generator.cpython-33-PYTEST.pyc -tests/web/__pycache__/test_wsgi_application_generator.cpython-34-PYTEST.pyc -tests/web/__pycache__/test_wsgi_application_yield.cpython-26-PYTEST.pyc -tests/web/__pycache__/test_wsgi_application_yield.cpython-27-PYTEST.pyc -tests/web/__pycache__/test_wsgi_application_yield.cpython-32-PYTEST.pyc -tests/web/__pycache__/test_wsgi_application_yield.cpython-33-PYTEST.pyc -tests/web/__pycache__/test_wsgi_application_yield.cpython-34-PYTEST.pyc -tests/web/__pycache__/test_wsgi_gateway.cpython-26-PYTEST.pyc -tests/web/__pycache__/test_wsgi_gateway.cpython-27-PYTEST.pyc -tests/web/__pycache__/test_wsgi_gateway.cpython-32-PYTEST.pyc -tests/web/__pycache__/test_wsgi_gateway.cpython-33-PYTEST.pyc -tests/web/__pycache__/test_wsgi_gateway.cpython-34-PYTEST.pyc -tests/web/__pycache__/test_wsgi_gateway_errors.cpython-26-PYTEST.pyc -tests/web/__pycache__/test_wsgi_gateway_errors.cpython-27-PYTEST.pyc -tests/web/__pycache__/test_wsgi_gateway_errors.cpython-32-PYTEST.pyc -tests/web/__pycache__/test_wsgi_gateway_errors.cpython-33-PYTEST.pyc -tests/web/__pycache__/test_wsgi_gateway_errors.cpython-34-PYTEST.pyc -tests/web/__pycache__/test_wsgi_gateway_generator.cpython-26-PYTEST.pyc -tests/web/__pycache__/test_wsgi_gateway_generator.cpython-27-PYTEST.pyc -tests/web/__pycache__/test_wsgi_gateway_generator.cpython-32-PYTEST.pyc -tests/web/__pycache__/test_wsgi_gateway_generator.cpython-33-PYTEST.pyc -tests/web/__pycache__/test_wsgi_gateway_generator.cpython-34-PYTEST.pyc -tests/web/__pycache__/test_wsgi_gateway_multiple_apps.cpython-26-PYTEST.pyc -tests/web/__pycache__/test_wsgi_gateway_multiple_apps.cpython-27-PYTEST.pyc -tests/web/__pycache__/test_wsgi_gateway_multiple_apps.cpython-32-PYTEST.pyc -tests/web/__pycache__/test_wsgi_gateway_multiple_apps.cpython-33-PYTEST.pyc -tests/web/__pycache__/test_wsgi_gateway_multiple_apps.cpython-34-PYTEST.pyc -tests/web/__pycache__/test_wsgi_gateway_null_response.cpython-26-PYTEST.pyc -tests/web/__pycache__/test_wsgi_gateway_null_response.cpython-27-PYTEST.pyc -tests/web/__pycache__/test_wsgi_gateway_null_response.cpython-32-PYTEST.pyc -tests/web/__pycache__/test_wsgi_gateway_null_response.cpython-33-PYTEST.pyc -tests/web/__pycache__/test_wsgi_gateway_null_response.cpython-34-PYTEST.pyc -tests/web/__pycache__/test_wsgi_gateway_write.cpython-26-PYTEST.pyc -tests/web/__pycache__/test_wsgi_gateway_write.cpython-27-PYTEST.pyc -tests/web/__pycache__/test_wsgi_gateway_write.cpython-32-PYTEST.pyc -tests/web/__pycache__/test_wsgi_gateway_write.cpython-33-PYTEST.pyc -tests/web/__pycache__/test_wsgi_gateway_write.cpython-34-PYTEST.pyc -tests/web/__pycache__/test_wsgi_gateway_yield.cpython-26-PYTEST.pyc -tests/web/__pycache__/test_wsgi_gateway_yield.cpython-27-PYTEST.pyc -tests/web/__pycache__/test_wsgi_gateway_yield.cpython-32-PYTEST.pyc -tests/web/__pycache__/test_wsgi_gateway_yield.cpython-33-PYTEST.pyc -tests/web/__pycache__/test_wsgi_gateway_yield.cpython-34-PYTEST.pyc -tests/web/__pycache__/test_xmlrpc.cpython-26-PYTEST.pyc -tests/web/__pycache__/test_xmlrpc.cpython-27-PYTEST.pyc -tests/web/__pycache__/test_xmlrpc.cpython-32-PYTEST.pyc -tests/web/__pycache__/test_xmlrpc.cpython-33-PYTEST.pyc -tests/web/__pycache__/test_xmlrpc.cpython-34-PYTEST.pyc -tests/web/__pycache__/test_yield.cpython-26-PYTEST.pyc -tests/web/__pycache__/test_yield.cpython-27-PYTEST.pyc -tests/web/__pycache__/test_yield.cpython-32-PYTEST.pyc -tests/web/__pycache__/test_yield.cpython-33-PYTEST.pyc -tests/web/__pycache__/test_yield.cpython-34-PYTEST.pyc -tests/web/static/#foobar.txt -tests/web/static/helloworld.txt -tests/web/static/largefile.txt -tests/web/static/test.css -tests/web/static/unicode.txt \ No newline at end of file diff -Nru circuits-3.1.0+ds1/circuits.egg-info/top_level.txt circuits-3.2.2/circuits.egg-info/top_level.txt --- circuits-3.1.0+ds1/circuits.egg-info/top_level.txt 2014-10-31 23:13:39.000000000 +0000 +++ circuits-3.2.2/circuits.egg-info/top_level.txt 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -circuits -fabfile -tests diff -Nru circuits-3.1.0+ds1/circuits.egg-info/zip-safe circuits-3.2.2/circuits.egg-info/zip-safe --- circuits-3.1.0+ds1/circuits.egg-info/zip-safe 2014-09-04 10:33:48.000000000 +0000 +++ circuits-3.2.2/circuits.egg-info/zip-safe 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ - diff -Nru circuits-3.1.0+ds1/CONTRIBUTING.md circuits-3.2.2/CONTRIBUTING.md --- circuits-3.1.0+ds1/CONTRIBUTING.md 1970-01-01 00:00:00.000000000 +0000 +++ circuits-3.2.2/CONTRIBUTING.md 2021-10-19 16:23:49.000000000 +0000 @@ -0,0 +1,129 @@ +# Welcome to the contributing guide for circuits! + +## Team members + +- James Mills [@prologic](https://github.com/prologic) (*Project Author and Maintainer*) +- [@Osso](https://github.com/Osso) +- [@treemo](https://github.com/treemo) +- [@spaceone](https://github.com/spaceone) +- [@y0no](https://github.com/y0no) + +## Learn & listen + +* Mailing list: [circuits-dev](https://groups.google.com/forum/#!forum/circuits-dev) +* IRC channel: [#circuits](http://webchat.freenode.net/?randomnick=1&channels=circuits&uio=d4) + on the [FreeNode IRC Network](http://freenode.net/) (``irc.freenode.net``).\ +* Blog: [James Mills circuits Blog](http://shortcircuit.net.au/~prologic/blog/tag/circuits/) + +## Adding new features + +Got a great new feature you'd like to add? Great! First let's discuss it either on +the [#circuits](http://webchat.freenode.net/?randomnick=1&channels=circuits&uio=d4) IRC Channel +or create a new [Discussion Issue](https://github.com/circuits/circuits/issues/new). + +Once we're all on the same page and we've nutted down the design and requirements together +let's get you hacking and take ownership of the new feature! + +* [Fork circuits](https://github.com/circuits/circuits/issues/14#fork-destination-box) +* Clone your newly created fork: + +```bash +$ git clone git@github.com:myuser/circuits.git +``` + +* Create a new feature branch: + +```bash +$ git checkout -b my-feature master +``` + +* Hack on your feature with your favorite editor or IDE! +* Commit and Push your changes up: + +```bash +$ git add -A +$ git commit -m "my fancy new feature. Closes #xx" +$ git push -u origin my-feature +``` + +* Create a new [Pull Request](https://github.com/circuits/circuits/compare/) + +That's it! Six easy steps to contributing a new feature! + +Generally we'll respond pretty quickly to new issues, pull requests and general +discussions on IRC. So come and join us! + +# Reporting Bugs + +Found a bug? Great! We wants to help fix it! + +* File a new [Bug Report](https://github.com/circuits/circuits/issues/new) +* Label it as a "Bug" + +When describing your bug report; please be concise and as detailed as you can +so we can easily work out what the problem is. It's also very helpful if you +are able to provide a test case that repeatedly demonstrates the bug at hand: + +Example: + +```python +from circuits import Event, Component + + +class test(Event): + """test Event""" + + +class App(Component): + + message = None + + def started(self): + self.message = "Hello World!" + self.stop() + + +def test(): + App().run() + + assert app.message == "Hello World!" +``` + +Obviously this test *would pass* but this is ideally what we'd like to see bug reports in the +form of; a reliable, repeatable way of demonstrating the bug. + +If you don't feel comfortable writing a test case; a good description is enough! +(*We'll take care of the hard work of ensuring the bug never occurs again!*) + +# Documentation + +Please help us with [Documentation](http://circuits.readthedocs.org/) + +Our documentation is written in [reStructuredText](http://en.wikipedia.org/wiki/ReStructuredText) +using the [Sphinx](http://sphinx-doc.org/) documentation toolkit. + +See: [Documentation Sources](https://github.com/circuits/circuits/tree/master/docs) + +You can contribute in these easy steps: + +1. Navigate our [Documentation Sources](https://github.com/circuits/circuits/tree/master/docs) +2. Find a document you wish to improve. +3. Click on the Pen (*Edit this file*) button. +4. Make your changes and submit a new Pull Request using the Github editor + +See: [Editing files in another user's repository](https://help.github.com/articles/editing-files-in-another-user-s-repository/) + +# Community +This section includes ideas on how non-developers can help with the project. Here's a few examples: + +* You can help us answer questions our users have here: [StackOverflow circuits-framework](http://stackoverflow.com/questions/tagged/circuits-framework) +* You can help build and design our website here: [circuitsframework.com](https://github.com/circuits/circuitsframework.com) +* You can help write blog posts about the project by: sharing them with the [Community](http://circuitsframework.com/Community) +* You can tweet about your use of circuits and tag [@pythoncircuits](https://twitter.com/pythoncircuits) + +* Create an example of the project in real world by building something or showing what others have built. +* Write about other people’s projects based on this project. Show how it’s used in daily life. Take screenshots and make videos! + +---- + +If you have further questions, contact: [James Mills](mailto:prologic+circuits@shortcircuit.net.au) ([@therealprologic](https://twitter.com/therealprologic) diff -Nru circuits-3.1.0+ds1/.coveragerc circuits-3.2.2/.coveragerc --- circuits-3.1.0+ds1/.coveragerc 1970-01-01 00:00:00.000000000 +0000 +++ circuits-3.2.2/.coveragerc 2021-10-19 16:23:49.000000000 +0000 @@ -0,0 +1,10 @@ +[run] +source = circuits +omit = + circuits/six.py + +[html] +directory = coverage + +[xml] +output = coverage.xml diff -Nru circuits-3.1.0+ds1/debian/changelog circuits-3.2.2/debian/changelog --- circuits-3.1.0+ds1/debian/changelog 2022-12-06 18:57:59.000000000 +0000 +++ circuits-3.2.2/debian/changelog 2022-12-14 16:15:09.000000000 +0000 @@ -1,3 +1,19 @@ +circuits (3.2.2-1) unstable; urgency=medium + + * New upstream version 3.2.2 (Closes: #1024860) + * Watch the upstream github instead of the PyPI tarball. + * Refresh patches. + * debian/control + - Add python3-setuptools-scm to Build-Depends. + - Update Homepage field. + - Bump Standards-Version to 4.6.1.0, no changes needed. + * debian/copyright + - Don't esclude built docs since they are not included anymore + - Update copyright years. + - Use my debian.org address. + + -- Daniele Tricoli Wed, 14 Dec 2022 17:15:09 +0100 + circuits (3.1.0+ds1-4) unstable; urgency=medium [ Debian Janitor ] diff -Nru circuits-3.1.0+ds1/debian/control circuits-3.2.2/debian/control --- circuits-3.1.0+ds1/debian/control 2022-12-06 18:57:59.000000000 +0000 +++ circuits-3.2.2/debian/control 2022-12-14 16:15:09.000000000 +0000 @@ -9,8 +9,9 @@ python3-sphinx, python3-all, python3-setuptools, -Standards-Version: 4.6.0.1 -Homepage: http://circuitsframework.com + python3-setuptools-scm +Standards-Version: 4.6.1.0 +Homepage: https://github.com/circuits/circuits Vcs-Git: https://salsa.debian.org/python-team/packages/circuits.git Vcs-Browser: https://salsa.debian.org/python-team/packages/circuits Testsuite: autopkgtest-pkg-python diff -Nru circuits-3.1.0+ds1/debian/copyright circuits-3.2.2/debian/copyright --- circuits-3.1.0+ds1/debian/copyright 2022-12-06 18:57:59.000000000 +0000 +++ circuits-3.2.2/debian/copyright 2022-12-14 16:15:09.000000000 +0000 @@ -2,7 +2,6 @@ Upstream-Name: circuits Upstream-Contact: James Mills Source: http://pypi.python.org/pypi/circuits -Files-Excluded: docs/build/html/* *.un~ Files: * Copyright: 2004-2015, James Mills @@ -10,7 +9,7 @@ Files: debian/* Copyright: 2008-2010, Sandro Tosi - 2011-2015, Daniele Tricoli + 2011-2022, Daniele Tricoli License: Expat Files: bin/htpasswd diff -Nru circuits-3.1.0+ds1/debian/gbp.conf circuits-3.2.2/debian/gbp.conf --- circuits-3.1.0+ds1/debian/gbp.conf 1970-01-01 00:00:00.000000000 +0000 +++ circuits-3.2.2/debian/gbp.conf 2022-12-14 16:15:09.000000000 +0000 @@ -0,0 +1,2 @@ +[DEFAULT] +debian-branch=debian/master diff -Nru circuits-3.1.0+ds1/debian/patches/01_disable_sphinxcontrib_extensions.patch circuits-3.2.2/debian/patches/01_disable_sphinxcontrib_extensions.patch --- circuits-3.1.0+ds1/debian/patches/01_disable_sphinxcontrib_extensions.patch 2022-12-06 18:57:59.000000000 +0000 +++ circuits-3.2.2/debian/patches/01_disable_sphinxcontrib_extensions.patch 2022-12-14 16:15:09.000000000 +0000 @@ -1,21 +1,19 @@ -From da50030623bba6b4a5223c86132857b20fb99dbc Mon Sep 17 00:00:00 2001 From: Daniele Tricoli Date: Thu, 8 Oct 2015 08:40:41 -0700 -Subject: Disable sphinxcontrib-releases because it's not packaged for +Subject: Disable sphinxcontrib-releases because it's not packaged for Debian. - Debian. -Last-Update: 2015-07-11 +Last-Update: 2022-12-14 Forwarded: not-needed Patch-Name: 01_disable_sphinxcontrib_extensions.patch --- - docs/source/conf.py | 10 +++++----- - 1 file changed, 5 insertions(+), 5 deletions(-) + docs/source/conf.py | 11 ++++++----- + 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/docs/source/conf.py b/docs/source/conf.py -index 23e3af7..0d20720 100644 +index 32915d1..a1a9860 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py -@@ -105,13 +105,13 @@ todo_include_todos = devel +@@ -93,13 +93,14 @@ todo_include_todos = devel # -- release and issues @@ -24,13 +22,14 @@ # 'releases' (changelog) settings -releases_debug = True --releases_issue_uri = "https://bitbucket.org/circuits/circuits/issue/%s" --releases_release_uri = "https://bitbucket.org/circuits/circuits/src/tip/?at=%s" +-releases_issue_uri = "https://github.com/circuits/circuits/issues/%s" +-releases_release_uri = "https://github.com/circuits/circuits/tree/%s" -releases_document_name = "changes" +# releases_debug = True -+# releases_issue_uri = "https://bitbucket.org/circuits/circuits/issue/%s" -+# releases_release_uri = "https://bitbucket.org/circuits/circuits/src/tip/?at=%s" ++# releases_issue_uri = "https://github.com/circuits/circuits/issues/%s" ++# releases_release_uri = "https://github.com/circuits/circuits/tree/%s" +# releases_document_name = "changes" ++ # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff -Nru circuits-3.1.0+ds1/debian/patches/02_remove_templatebuiltins_js.patch circuits-3.2.2/debian/patches/02_remove_templatebuiltins_js.patch --- circuits-3.1.0+ds1/debian/patches/02_remove_templatebuiltins_js.patch 2022-12-06 18:57:59.000000000 +0000 +++ circuits-3.2.2/debian/patches/02_remove_templatebuiltins_js.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,58 +0,0 @@ -From 96a0bec33599bf4574a2220078554a42ef52683d Mon Sep 17 00:00:00 2001 -From: Daniele Tricoli -Date: Thu, 8 Oct 2015 08:40:42 -0700 -Subject: Remove templatebuiltins.js because it contains names of Django - -builtin tags and filters not used in circuits documentation. -Forwarded: https://github.com/circuits/circuits/pull/106 -Last-Update: 2015-07-12 - -Patch-Name: 02_remove_templatebuiltins_js.patch ---- - docs/source/_themes/om/layout.html | 33 --------------------------------- - 1 file changed, 33 deletions(-) - -diff --git a/docs/source/_themes/om/layout.html b/docs/source/_themes/om/layout.html -index b550bdd..de1a7d1 100644 ---- a/docs/source/_themes/om/layout.html -+++ b/docs/source/_themes/om/layout.html -@@ -18,39 +18,6 @@ - - {% block extrahead %} - {{ super() }} -- -- - {% endblock %} - - {% block document %} diff -Nru circuits-3.1.0+ds1/debian/patches/03_disable-address-check.patch circuits-3.2.2/debian/patches/03_disable-address-check.patch --- circuits-3.1.0+ds1/debian/patches/03_disable-address-check.patch 2022-12-06 18:57:59.000000000 +0000 +++ circuits-3.2.2/debian/patches/03_disable-address-check.patch 2022-12-14 16:15:09.000000000 +0000 @@ -1,4 +1,3 @@ -From 253b3e297abc1de23bb287596d94c9b695a86628 Mon Sep 17 00:00:00 2001 From: Daniele Tricoli Date: Thu, 8 Oct 2015 08:40:43 -0700 Subject: Disable address check since these tests are conceived @@ -13,10 +12,10 @@ 1 file changed, 15 insertions(+) diff --git a/tests/web/test_logger.py b/tests/web/test_logger.py -index 91a0ca7..1a8e8f1 100644 +index 7d792eb..52e6540 100644 --- a/tests/web/test_logger.py +++ b/tests/web/test_logger.py -@@ -58,6 +58,11 @@ def test_file(webapp): +@@ -57,6 +57,11 @@ def test_file(webapp): d["f"] = "" d["a"] = "Python-urllib/%s" % sys.version[:3] @@ -28,7 +27,7 @@ keys = list(d.keys()) for k in keys: -@@ -93,6 +98,11 @@ def test_logger(webapp): +@@ -96,6 +101,11 @@ def test_logger(webapp): d["f"] = "" d["a"] = "Python-urllib/%s" % sys.version[:3] @@ -40,7 +39,7 @@ keys = list(d.keys()) for k in keys: -@@ -130,6 +140,11 @@ def test_filename(webapp, tmpdir): +@@ -137,6 +147,11 @@ def test_filename(webapp, tmpdir): d["f"] = "" d["a"] = "Python-urllib/%s" % sys.version[:3] diff -Nru circuits-3.1.0+ds1/debian/patches/04_remove-google-adsense.patch circuits-3.2.2/debian/patches/04_remove-google-adsense.patch --- circuits-3.1.0+ds1/debian/patches/04_remove-google-adsense.patch 2022-12-06 18:57:59.000000000 +0000 +++ circuits-3.2.2/debian/patches/04_remove-google-adsense.patch 2022-12-14 16:15:09.000000000 +0000 @@ -1,4 +1,3 @@ -From fdc003cba4a4af112369c30163915a9dcc960561 Mon Sep 17 00:00:00 2001 From: Daniele Tricoli Date: Thu, 8 Oct 2015 08:40:44 -0700 Subject: Remove Google AdSense tracking code. diff -Nru circuits-3.1.0+ds1/debian/patches/05_remove-privacy-breach-badges.patch circuits-3.2.2/debian/patches/05_remove-privacy-breach-badges.patch --- circuits-3.1.0+ds1/debian/patches/05_remove-privacy-breach-badges.patch 2022-12-06 18:57:59.000000000 +0000 +++ circuits-3.2.2/debian/patches/05_remove-privacy-breach-badges.patch 2022-12-14 16:15:09.000000000 +0000 @@ -1,4 +1,3 @@ -From dbb0370a5d0598e326945527332e41b2439f61a9 Mon Sep 17 00:00:00 2001 From: Daniele Tricoli Date: Thu, 8 Oct 2015 08:40:45 -0700 Subject: Remove badges fetched from external websites. @@ -8,49 +7,29 @@ Patch-Name: 05_remove-privacy-breach-badges.patch --- - README.rst | 32 -------------------------------- - 1 file changed, 32 deletions(-) + README.rst | 12 ------------ + 1 file changed, 12 deletions(-) diff --git a/README.rst b/README.rst -index a0ec47a..da212eb 100644 +index 9a43946..23f85ea 100644 --- a/README.rst +++ b/README.rst -@@ -25,38 +25,6 @@ components. - - Download it from the `Downloads Page`_ - - `View the ChangeLog`_ +@@ -13,18 +13,6 @@ + .. _Stackoverflow: http://stackoverflow.com/ + .. _Google+ Group: https://plus.google.com/communities/107775112577294599973 --.. image:: https://pypip.in/v/circuits/badge.png?text=version -- :target: https://pypi.python.org/pypi/circuits -- :alt: Latest Version -- --.. image:: https://pypip.in/py_versions/circuits/badge.svg -- :target: https://pypi.python.org/pypi/circuits -- :alt: Supported Python Versions -- --.. image:: https://pypip.in/implementation/circuits/badge.svg -- :target: https://pypi.python.org/pypi/circuits -- :alt: Supported Python implementations -- --.. image:: https://pypip.in/status/circuits/badge.svg -- :target: https://pypi.python.org/pypi/circuits -- :alt: Development Status -- --.. image:: https://pypip.in/d/circuits/badge.png -- :target: https://pypi.python.org/pypi/circuits -- :alt: Number of Downloads -- --.. image:: https://pypip.in/format/circuits/badge.svg -- :target: https://pypi.python.org/pypi/circuits -- :alt: Format -- --.. image:: https://pypip.in/license/circuits/badge.svg -- :target: https://pypi.python.org/pypi/circuits -- :alt: License -- --.. image:: https://requires.io/bitbucket/circuits/circuits/requirements.png?branch=default -- :target: https://requires.io/bitbucket/circuits/circuits/requirements?branch=default -- :alt: Requirements Status -- - - Examples - -------- +-.. image:: https://github.com/circuits/circuits/actions/workflows/python-app.yml/badge.svg +- :target: https://github.com/circuits/circuits/actions/workflows/python-app.yml +- :alt: Build Status +- +-.. image:: https://codecov.io/gh/circuits/circuits/branch/master/graph/badge.svg +- :target: https://codecov.io/gh/circuits/circuits +- :alt: Coverage +- +-.. image:: https://badge.waffle.io/circuits/circuits.png?label=ready&title=Ready +- :target: https://waffle.io/circuits/circuits +- :alt: Stories Ready +- + circuits is a **Lightweight** **Event** driven and **Asynchronous** + **Application Framework** for the `Python Programming Language`_ + with a strong **Component** Architecture. diff -Nru circuits-3.1.0+ds1/debian/patches/python-3.10.patch circuits-3.2.2/debian/patches/python-3.10.patch --- circuits-3.1.0+ds1/debian/patches/python-3.10.patch 2022-12-06 18:57:59.000000000 +0000 +++ circuits-3.2.2/debian/patches/python-3.10.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,97 +0,0 @@ -Description: compatibility with python 3.10 -Author: Steve Langasek -Bug-Debian: https://bugs.debian.org/1001244 -Last-Update: 2021-12-10 -Forwarded: no - -Index: circuits-3.1.0+ds1/circuits/core/handlers.py -=================================================================== ---- circuits-3.1.0+ds1.orig/circuits/core/handlers.py -+++ circuits-3.1.0+ds1/circuits/core/handlers.py -@@ -7,7 +7,7 @@ - """ - - from inspect import getargspec --from collections import Callable -+from collections.abc import Callable - - - def handler(*names, **kwargs): -Index: circuits-3.1.0+ds1/circuits/core/components.py -=================================================================== ---- circuits-3.1.0+ds1.orig/circuits/core/components.py -+++ circuits-3.1.0+ds1/circuits/core/components.py -@@ -9,7 +9,7 @@ - from itertools import chain - from types import MethodType - from inspect import getmembers --from collections import Callable -+from collections.abc import Callable - - from .manager import Manager - from .handlers import handler, HandlerMetaClass -Index: circuits-3.1.0+ds1/circuits/web/controllers.py -=================================================================== ---- circuits-3.1.0+ds1.orig/circuits/web/controllers.py -+++ circuits-3.1.0+ds1/circuits/web/controllers.py -@@ -9,7 +9,7 @@ - - import json - from inspect import getargspec --from collections import Callable -+from collections.abc import Callable - from functools import update_wrapper - - from circuits.core import handler, BaseComponent -Index: circuits-3.1.0+ds1/circuits/web/parsers/multipart.py -=================================================================== ---- circuits-3.1.0+ds1.orig/circuits/web/parsers/multipart.py -+++ circuits-3.1.0+ds1/circuits/web/parsers/multipart.py -@@ -57,7 +57,7 @@ - # Some of these were copied from bottle: http://bottle.paws.de/ - - try: -- from collections import MutableMapping as DictMixin -+ from collections.abc import MutableMapping as DictMixin - except ImportError: # pragma: no cover (fallback for Python 2.5) - from UserDict import DictMixin - -Index: circuits-3.1.0+ds1/circuits/web/tools.py -=================================================================== ---- circuits-3.1.0+ds1.orig/circuits/web/tools.py -+++ circuits-3.1.0+ds1/circuits/web/tools.py -@@ -316,7 +316,7 @@ - if not encrypt: - encrypt = _httpauth.DIGEST_AUTH_ENCODERS[_httpauth.MD5] - -- if isinstance(users, collections.Callable): -+ if isinstance(users, collections.abc.Callable): - try: - # backward compatibility - users = users() # expect it to return a dictionary -Index: circuits-3.1.0+ds1/circuits/web/utils.py -=================================================================== ---- circuits-3.1.0+ds1.orig/circuits/web/utils.py -+++ circuits-3.1.0+ds1/circuits/web/utils.py -@@ -14,7 +14,7 @@ - from math import sqrt - from io import TextIOWrapper - from cgi import FieldStorage --from collections import MutableMapping -+from collections.abc import MutableMapping - - try: - from urllib.parse import urljoin as _urljoin -Index: circuits-3.1.0+ds1/tests/conftest.py -=================================================================== ---- circuits-3.1.0+ds1.orig/tests/conftest.py -+++ circuits-3.1.0+ds1/tests/conftest.py -@@ -101,7 +101,7 @@ - def wait_for(obj, attr, value=True, timeout=3.0): - from circuits.core.manager import TIMEOUT - for i in range(int(timeout / TIMEOUT)): -- if isinstance(value, collections.Callable): -+ if isinstance(value, collections.abc.Callable): - if value(obj, attr): - return True - elif getattr(obj, attr) == value: diff -Nru circuits-3.1.0+ds1/debian/patches/series circuits-3.2.2/debian/patches/series --- circuits-3.1.0+ds1/debian/patches/series 2022-12-06 18:57:59.000000000 +0000 +++ circuits-3.2.2/debian/patches/series 2022-12-14 16:15:09.000000000 +0000 @@ -1,6 +1,4 @@ 01_disable_sphinxcontrib_extensions.patch -02_remove_templatebuiltins_js.patch 03_disable-address-check.patch 04_remove-google-adsense.patch 05_remove-privacy-breach-badges.patch -python-3.10.patch diff -Nru circuits-3.1.0+ds1/debian/rules circuits-3.2.2/debian/rules --- circuits-3.1.0+ds1/debian/rules 2022-12-06 18:57:59.000000000 +0000 +++ circuits-3.2.2/debian/rules 2022-12-14 16:15:09.000000000 +0000 @@ -7,12 +7,13 @@ dh $(@) --with python3,sphinxdoc --buildsystem=pybuild override_dh_auto_clean: + dh_auto_clean + rm -f circuits/version.py rm -rf build rm -rf docs/build/html rm -rf *.egg-info find . -name *.coverage.* -delete rm -f debian/manpages/circuits.*3.1 - dh_auto_clean override_dh_auto_build: dh_auto_build diff -Nru circuits-3.1.0+ds1/debian/watch circuits-3.2.2/debian/watch --- circuits-3.1.0+ds1/debian/watch 2022-12-06 18:57:59.000000000 +0000 +++ circuits-3.2.2/debian/watch 2022-12-14 16:15:09.000000000 +0000 @@ -1,3 +1,4 @@ -version=3 -opts=uversionmangle=s/(rc|a|b|c)/~$1/,dversionmangle=s/\+ds\d*$//,repacksuffix=+ds1 \ -https://pypi.debian.net/circuits/circuits-(.+)\.(?:zip|tgz|tbz|txz|(?:tar\.(?:gz|bz2|xz))) +version=4 +opts=filenamemangle=s/.+\/v?(\d\S+)\.tar\.gz/circuits-$1\.tar\.gz/ \ + https://github.com/circuits/circuits/tags .*/v?(\d\S+)\.tar\.gz + diff -Nru circuits-3.1.0+ds1/Dockerfile circuits-3.2.2/Dockerfile --- circuits-3.1.0+ds1/Dockerfile 1970-01-01 00:00:00.000000000 +0000 +++ circuits-3.2.2/Dockerfile 2021-10-19 16:23:49.000000000 +0000 @@ -0,0 +1,29 @@ +# Docker Image for circuits +# +# This image essentially packages up the circuits +# (a Python Application Framework*) and it's tool(s) +# into a Docker Image/Container. +# +# You can also use this Image as a Base Image for all your +# circuits Applications. +# +# Website: http://circuitsframework.com/ +# PyPi: https://pypi.python.org/pypi/circuits +# +# Usage Examples(s):: +# +# $ docker run -d -v /path/to/www:/var/www prologic/circuits circuits.web /var/www +# $ docker run -i -t prologic/circuits circuits.bench +# +# VERSION: 0.0.2 +# +# Last Updated: 20141115 + +FROM crux/python:onbuild +MAINTAINER James Mills + +# Services +EXPOSE 80 8000 443 + +# Volumes +VOLUME /var/www diff -Nru circuits-3.1.0+ds1/.dockerignore circuits-3.2.2/.dockerignore --- circuits-3.1.0+ds1/.dockerignore 1970-01-01 00:00:00.000000000 +0000 +++ circuits-3.2.2/.dockerignore 2021-10-19 16:23:49.000000000 +0000 @@ -0,0 +1,17 @@ +*~ +tmp +.git +.tox +.env +dist +.eggs +*.pyc +*.pyo +*.bak +*.xml +*.sw? +build +.cache +coverage +.coverage* +docs/build Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/api/circuits.app.daemon.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/api/circuits.app.daemon.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/api/circuits.app.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/api/circuits.app.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/api/circuits.core.bridge.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/api/circuits.core.bridge.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/api/circuits.core.components.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/api/circuits.core.components.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/api/circuits.core.debugger.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/api/circuits.core.debugger.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/api/circuits.core.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/api/circuits.core.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/api/circuits.core.events.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/api/circuits.core.events.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/api/circuits.core.handlers.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/api/circuits.core.handlers.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/api/circuits.core.helpers.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/api/circuits.core.helpers.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/api/circuits.core.loader.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/api/circuits.core.loader.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/api/circuits.core.manager.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/api/circuits.core.manager.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/api/circuits.core.pollers.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/api/circuits.core.pollers.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/api/circuits.core.timers.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/api/circuits.core.timers.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/api/circuits.core.utils.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/api/circuits.core.utils.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/api/circuits.core.values.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/api/circuits.core.values.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/api/circuits.core.workers.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/api/circuits.core.workers.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/api/circuits.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/api/circuits.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/api/circuits.io.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/api/circuits.io.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/api/circuits.io.events.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/api/circuits.io.events.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/api/circuits.io.file.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/api/circuits.io.file.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/api/circuits.io.notify.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/api/circuits.io.notify.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/api/circuits.io.process.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/api/circuits.io.process.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/api/circuits.io.serial.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/api/circuits.io.serial.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/api/circuits.net.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/api/circuits.net.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/api/circuits.net.events.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/api/circuits.net.events.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/api/circuits.net.sockets.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/api/circuits.net.sockets.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/api/circuits.node.client.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/api/circuits.node.client.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/api/circuits.node.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/api/circuits.node.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/api/circuits.node.events.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/api/circuits.node.events.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/api/circuits.node.node.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/api/circuits.node.node.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/api/circuits.node.server.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/api/circuits.node.server.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/api/circuits.node.utils.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/api/circuits.node.utils.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/api/circuits.protocols.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/api/circuits.protocols.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/api/circuits.protocols.http.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/api/circuits.protocols.http.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/api/circuits.protocols.irc.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/api/circuits.protocols.irc.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/api/circuits.protocols.line.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/api/circuits.protocols.line.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/api/circuits.protocols.websocket.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/api/circuits.protocols.websocket.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/api/circuits.six.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/api/circuits.six.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/api/circuits.tools.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/api/circuits.tools.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/api/circuits.version.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/api/circuits.version.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/api/circuits.web.client.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/api/circuits.web.client.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/api/circuits.web.constants.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/api/circuits.web.constants.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/api/circuits.web.controllers.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/api/circuits.web.controllers.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/api/circuits.web.dispatchers.dispatcher.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/api/circuits.web.dispatchers.dispatcher.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/api/circuits.web.dispatchers.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/api/circuits.web.dispatchers.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/api/circuits.web.dispatchers.jsonrpc.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/api/circuits.web.dispatchers.jsonrpc.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/api/circuits.web.dispatchers.static.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/api/circuits.web.dispatchers.static.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/api/circuits.web.dispatchers.virtualhosts.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/api/circuits.web.dispatchers.virtualhosts.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/api/circuits.web.dispatchers.xmlrpc.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/api/circuits.web.dispatchers.xmlrpc.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/api/circuits.web.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/api/circuits.web.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/api/circuits.web.errors.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/api/circuits.web.errors.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/api/circuits.web.events.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/api/circuits.web.events.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/api/circuits.web.exceptions.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/api/circuits.web.exceptions.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/api/circuits.web.headers.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/api/circuits.web.headers.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/api/circuits.web.http.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/api/circuits.web.http.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/api/circuits.web.loggers.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/api/circuits.web.loggers.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/api/circuits.web.main.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/api/circuits.web.main.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/api/circuits.web.parsers.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/api/circuits.web.parsers.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/api/circuits.web.parsers.http.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/api/circuits.web.parsers.http.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/api/circuits.web.parsers.multipart.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/api/circuits.web.parsers.multipart.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/api/circuits.web.parsers.querystring.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/api/circuits.web.parsers.querystring.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/api/circuits.web.processors.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/api/circuits.web.processors.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/api/circuits.web.servers.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/api/circuits.web.servers.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/api/circuits.web.sessions.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/api/circuits.web.sessions.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/api/circuits.web.tools.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/api/circuits.web.tools.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/api/circuits.web.url.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/api/circuits.web.url.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/api/circuits.web.utils.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/api/circuits.web.utils.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/api/circuits.web.websockets.client.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/api/circuits.web.websockets.client.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/api/circuits.web.websockets.dispatcher.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/api/circuits.web.websockets.dispatcher.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/api/circuits.web.websockets.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/api/circuits.web.websockets.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/api/circuits.web.wrappers.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/api/circuits.web.wrappers.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/api/circuits.web.wsgi.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/api/circuits.web.wsgi.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/api/index.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/api/index.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/changes.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/changes.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/contributors.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/contributors.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/dev/contributing.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/dev/contributing.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/dev/index.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/dev/index.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/dev/introduction.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/dev/introduction.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/dev/processes.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/dev/processes.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/dev/standards.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/dev/standards.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/environment.pickle and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/environment.pickle differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/examples/index.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/examples/index.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/faq.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/faq.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/glossary.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/glossary.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/index.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/index.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/man/components.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/man/components.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/man/debugger.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/man/debugger.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/man/events.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/man/events.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/man/handlers.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/man/handlers.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/man/index.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/man/index.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/man/manager.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/man/manager.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/man/misc/tools.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/man/misc/tools.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/man/values.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/man/values.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/readme.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/readme.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/roadmap.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/roadmap.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/start/downloading.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/start/downloading.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/start/index.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/start/index.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/start/installing.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/start/installing.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/start/quick.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/start/quick.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/start/requirements.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/start/requirements.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/todo.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/todo.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/tutorials/index.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/tutorials/index.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/tutorials/telnet/index.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/tutorials/telnet/index.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/tutorials/woof/index.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/tutorials/woof/index.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/web/features.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/web/features.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/web/gettingstarted.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/web/gettingstarted.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/web/howtos.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/web/howtos.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/web/index.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/web/index.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/web/introduction.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/web/introduction.doctree differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/docs/build/doctrees/web/miscellaneous.doctree and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/docs/build/doctrees/web/miscellaneous.doctree differ diff -Nru circuits-3.1.0+ds1/docs/check_docs.py circuits-3.2.2/docs/check_docs.py --- circuits-3.1.0+ds1/docs/check_docs.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/docs/check_docs.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,6 +1,6 @@ #!/usr/bin/env python -from subprocess import Popen, PIPE, STDOUT +from subprocess import PIPE, STDOUT, Popen def test_linkcheck(tmpdir): diff -Nru circuits-3.1.0+ds1/docs/requirements.txt circuits-3.2.2/docs/requirements.txt --- circuits-3.1.0+ds1/docs/requirements.txt 2014-10-31 22:49:44.000000000 +0000 +++ circuits-3.2.2/docs/requirements.txt 2021-10-19 16:23:49.000000000 +0000 @@ -1,6 +1,2 @@ Sphinx -#releases --e git+https://github.com/bitprophet/releases.git#egg=releases -Sphinx-PyPI-upload -sphinxcontrib-programoutput -sphinxcontrib-googleanalytics +releases diff -Nru circuits-3.1.0+ds1/docs/source/conf.py circuits-3.2.2/docs/source/conf.py --- circuits-3.1.0+ds1/docs/source/conf.py 2014-10-31 22:49:44.000000000 +0000 +++ circuits-3.2.2/docs/source/conf.py 2021-10-19 16:23:49.000000000 +0000 @@ -13,36 +13,24 @@ import sys from os import path -from imp import new_module + +from pkg_resources import parse_version + +from circuits import __version__ # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use path.abspath to make it absolute, like shown here. sys.path.insert(0, path.abspath('../..')) -version_module = new_module("version") -exec( - compile( - open( - path.abspath(path.join( - path.dirname(__file__), - "../../circuits/version.py" - )), - "r" - ).read(), - "../../circuits/version.py", "exec" - ), - version_module.__dict__ -) -# -- General configuration ----------------------------------------------------- + +# -- General configuration ----------------------------------------------- # Add any Sphinx extension module names here, as strings. They can be extensions # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. extensions = [] -bitbucket_project_url = 'https://bitbucket.org/circuits/circuits' - # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] @@ -50,14 +38,14 @@ source_suffix = '.rst' # The encoding of source files. -#source_encoding = 'utf-8' +# source_encoding = 'utf-8' # The master toctree document. master_doc = 'index' # General information about the project. project = u'circuits' -copyright = u'2004-2013, James Mills' +copyright = u'2004-2016, James Mills' url = "http://circuitsframework.com/" # The version info for the project you're documenting, acts as replacement for @@ -65,13 +53,13 @@ # built documents. # # The short X.Y version. -version = ".".join(map(str, version_module.version_info[:2])) +version = parse_version(__version__).base_version # The full version, including alpha/beta/rc tags. -release = version_module.version +release = __version__ # Devel or Release mode for the documentation (if devel, include TODOs, # can also be used in conditionals: .. ifconfig :: devel) -devel = version_module.version_info[-1] == "dev" +devel = "dev" in __version__ # -- Autodoc @@ -99,7 +87,7 @@ # -- track statistics with google analytics -#extensions.append("sphinxcontrib.googleanalytics") +# extensions.append("sphinxcontrib.googleanalytics") #googleanalytics_id = "UA-38618352-3" @@ -109,8 +97,8 @@ # 'releases' (changelog) settings releases_debug = True -releases_issue_uri = "https://bitbucket.org/circuits/circuits/issue/%s" -releases_release_uri = "https://bitbucket.org/circuits/circuits/src/tip/?at=%s" +releases_issue_uri = "https://github.com/circuits/circuits/issues/%s" +releases_release_uri = "https://github.com/circuits/circuits/tree/%s" releases_document_name = "changes" # The language for content autogenerated by Sphinx. Refer to documentation @@ -151,7 +139,7 @@ #modindex_common_prefix = [] -# -- Options for HTML output --------------------------------------------------- +# -- Options for HTML output --------------------------------------------- # The theme to use for HTML and HTML Help pages. Major themes that come with # Sphinx are currently 'default' and 'sphinxdoc'. @@ -227,7 +215,7 @@ htmlhelp_basename = 'circuitsdoc' -# -- Options for LaTeX output -------------------------------------------------- +# -- Options for LaTeX output -------------------------------------------- # The paper size ('letter' or 'a4'). #latex_paper_size = 'letter' diff -Nru circuits-3.1.0+ds1/docs/source/contributors.rst circuits-3.2.2/docs/source/contributors.rst --- circuits-3.1.0+ds1/docs/source/contributors.rst 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/docs/source/contributors.rst 2021-10-19 16:23:49.000000000 +0000 @@ -15,6 +15,8 @@ - Alex Mayfield - Toni Alatalo - Michael Lipp +- Matthieu Chevrier +- Yoann Ono Dit Biot Anyone not listed here (*apologies as this list is taken directly from Mercurial's churn command and output*). We appreciate any and all diff -Nru circuits-3.1.0+ds1/docs/source/dev/contributing.rst circuits-3.2.2/docs/source/dev/contributing.rst --- circuits-3.1.0+ds1/docs/source/dev/contributing.rst 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/docs/source/dev/contributing.rst 2021-10-19 16:23:49.000000000 +0000 @@ -1,3 +1,7 @@ +.. _Fork circuits: https://github.com/circuits/circuits/issues/new#fork-destination-box +.. _Create an Issue: https://github.com/circuits/circuits/issues/new +.. _Pull Request: https://github.com/circuits/circuits/compare/ + Contributing to circuits ======================== @@ -25,8 +29,7 @@ a bug to us is by writing a unit test (//similar to the ones in our tests//) so that we can verify the bug, fix it and commit the fix along with the test. -To submit a bug report, please use: - http://bitbucket.org/circuits/circuits/issues +To submit a bug report, please `Create an Issue`_ Writing new tests @@ -34,8 +37,8 @@ We're not perfect, and we're still writing more tests to ensure quality code. -If you'd like to help, please `Fork circuits `_, write more tests that cover more of our code base and -submit a `Pull Request `_. Many Thanks! +If you'd like to help, please `Fork circuits`_, write more tests that cover more +of our code base and submit a `Pull Request`_. Many Thanks! Adding New Features @@ -50,4 +53,4 @@ or -- `Submit a **New** Issue `_ +- `Create an Issue`_ diff -Nru circuits-3.1.0+ds1/docs/source/dev/environment.rst circuits-3.2.2/docs/source/dev/environment.rst --- circuits-3.1.0+ds1/docs/source/dev/environment.rst 1970-01-01 00:00:00.000000000 +0000 +++ circuits-3.2.2/docs/source/dev/environment.rst 2021-10-19 16:23:49.000000000 +0000 @@ -0,0 +1,72 @@ +.. _virtualenvwrapper: https://pypi.python.org/pypi/virtualenvwrapper +.. _virtualenv: https://pypi.python.org/pypi/virtualenv +.. _pip: https://pypi.python.org/pypi/pip +.. _Fabric: http://www.fabfile.org/ +.. _Python: https://www.python.org/ +.. _Git: https://git-scm.com/ + + +Setting up a circuits Development Environment +============================================= + +This is the recommended way to setup a development enviornment +for developing with or on circuits. + +.. note:: This document *assumes* you already have a working `Python`_ + environment with a minimum `Python`_ version of 2.7 as well + as `pip`_ already installed. + + +Prequisites +----------- + +It is highly recommended that you install and use `virtualenv`_ for all your +`Python`_ development and production deployments (*not just circuits*). + +It is also convenient to install and use the accompanying shell scripts +and tools `virtualenvwrapper`_ which adds a nice set of workflows +and functions useful for both development and deployments. + +.. code-block:: bash + + $ pip install -U virtualenvwrapper + $ source $(which virtualenvwrapper.sh) + +.. note:: You should put ``source $(which virtualenvwrapper.sh)`` in either + your ``$HOME/.bashrc`` or ``$HOME/.profile`` depending on how you + login and interact with your terminals. + +In addition to the above recommendations you must also have a `Git`_ client +installed and ready to use as well as your Editor/IDE of choice ready to use. + + +Getting Started +--------------- + +1. `Fork circuits `_ + (*if you haven't done so already*) +2. Clone your forked repository using `Git`_ +3. Create a new virtual environment using `virtualenvwrapper`_ +4. Install the `Development Requirements `_ +5. Install circuits in "develop" mode + +And you're done! + +Example: + +.. code-block:: bash + + $ git clone git@github.com:prologic/circuits.git + $ cd circuits + $ mkvirtualenv circuits + $ pip install -r requirements-dev.txt + $ python setup.py develop + +Alternatively if you already have `Fabric`_ installed: + +.. code-block:: bash + + $ git clone git@github.com:prologic/circuits.git + $ cd circuits + $ mkvirtualenv circuits + $ fab develop diff -Nru circuits-3.1.0+ds1/docs/source/dev/index.rst circuits-3.2.2/docs/source/dev/index.rst --- circuits-3.1.0+ds1/docs/source/dev/index.rst 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/docs/source/dev/index.rst 2021-10-19 16:23:49.000000000 +0000 @@ -14,5 +14,6 @@ introduction contributing + environment processes standards diff -Nru circuits-3.1.0+ds1/docs/source/dev/introduction.rst circuits-3.2.2/docs/source/dev/introduction.rst --- circuits-3.1.0+ds1/docs/source/dev/introduction.rst 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/docs/source/dev/introduction.rst 2021-10-19 16:23:49.000000000 +0000 @@ -1,5 +1,5 @@ .. _Developer Mailing List: http://groups.google.com/group/circuits-dev -.. _Issue Tracker: https://bitbucket.org/circuits/circuits/issues +.. _Issue Tracker: https://github.com/circuits/circuits/issues .. _FreeNode IRC Network: http://freenode.net .. _IRC Channel: http://webchat.freenode.net/?randomnick=1&channels=circuits&uio=d4 @@ -28,7 +28,7 @@ We use the following coding standard: -- `pep8 `_ +- `PEP-008 `_ We also lint our codebase with the following tools: @@ -50,15 +50,14 @@ We use the following tools to develop circuits and share code: - **Code Sharing:** - `Mercurial `_ + `Git `_ - **Code Hosting and Bug Reporting:** - `BitBucket `_ - `GitHub `_ (*Mirror Only*) + `GitHub `_ - **Issue Tracker:** - `Issue Tracker `_ + `Issue Tracker `_ - **Documentation Hosting:** `Read the Docs `_ - **Package Hosting:** `Python Package Index (PyPi) `_ - **Continuous Integration:** - `Drone `_ + `Github Actions `_ diff -Nru circuits-3.1.0+ds1/docs/source/dev/processes.rst circuits-3.2.2/docs/source/dev/processes.rst --- circuits-3.1.0+ds1/docs/source/dev/processes.rst 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/docs/source/dev/processes.rst 2021-10-19 16:23:49.000000000 +0000 @@ -1,4 +1,4 @@ -.. _Issue Tracker: https://bitbucket.org/circuits/circuits/issues +.. _Issue Tracker: https://github.com/circuits/circuits/issues Development Processes @@ -14,9 +14,10 @@ -------------------------------------- -We employ the use of the `SCRUM Agile Process `_ and use our `Issue Tracker`_ to track -features, bugs, chores and releases. If you wish to contribute -to circuits, please familiarize yourself with SCRUM and `BitBucket `'s Issue Tracker. +We employ the use of the `SCRUM Agile Process `_ +and use our `Issue Tracker`_ to track features, bugs, chores and releases. +If you wish to contribute to circuits, please familiarize yourself with SCRUM +and `GitHub `_'s Issue Tracker. Bug Reports @@ -24,20 +25,20 @@ - New Bug Reports are submitted via: - http://bitbucket.org/circuits/circuits/issues + https://github.com/circuits/circuits/issues - Confirmation and Discussion of all New Bug Reports. - Once confirmed, a new Bug is raised in our `Issue Tracker`_ - An appropriate milestone will be set (*depending on current milestone's schedule and resources*) - A unit test developed that demonstrates the bug's failure. - A fix developed that passes the unit test and breaks no others. -- A `New Pull Request `_ created with the fix. +- A `New Pull Request `_ created with the fix. This must contains: - A new or modified unit test. - A patch that fixes the bug ensuring all unit tests pass. - - The `Change Log `_ updated. + - The `Change Log `_ updated. - Appropriate documentation updated. -- The `Pull Request `_ is reviewed and approved by at least two other developers. +- The `Pull Request `_ is reviewed and approved by at least two other developers. Feature Requests @@ -45,27 +46,27 @@ - New Feature Requests are submitted via: - http://bitbucket.org/circuits/circuits/issues + https://github.com/circuits/circuits/issues - Confirmation and Discussion of all New Feature Requests. - Once confirmed, a new Feature is raised in our `Issue Tracker`_ - An appropriate milestone will be set (*depending on current milestone's schedule and resources*) - A unit test developed that demonstrates the new feature. - The new feature developed that passes the unit test and breaks no others. -- A `New Pull Request `_ created with the fix. +- A `New Pull Request `_ created with the fix. This must contains: - A new or modified unit test. - A patch that implements the new feature ensuring all unit tests pass. - - The `Change Log `_ updated. + - The `Change Log `_ updated. - Appropriate documentation updated. -- The `Pull Request `_ is reviewed and approved by at least two other developers. +- The `Pull Request `_ is reviewed and approved by at least two other developers. Writing new Code ---------------- -- Submit a `New Issue `_ +- Submit a `New Issue `_ - Write your code. - Use `flake8 `_ to ensure code quality. - Run the tests:: @@ -74,8 +75,8 @@ - Ensure any new or modified code does not break existing unit tests. - Update any relevant doc strings or documentation. -- Update the `Change Log `_ updated. -- Submit a `New Pull Request `_. +- Update the `Change Log `_ updated. +- Submit a `New Pull Request `_. Running the Tests @@ -88,7 +89,7 @@ - `pytest-cov `_ - `pytest `_ -All of these can be installed via ``easy_install`` or ``pip``. +All of these can be installed via ``pip``. Please also ensure that you you have all supported versions of Python that circuits supports installed in your local environment. diff -Nru circuits-3.1.0+ds1/docs/source/examples/echoserver.py circuits-3.2.2/docs/source/examples/echoserver.py --- circuits-3.1.0+ds1/docs/source/examples/echoserver.py 2014-09-29 08:08:23.000000000 +0000 +++ circuits-3.2.2/docs/source/examples/echoserver.py 2021-10-19 16:23:49.000000000 +0000 @@ -6,7 +6,7 @@ utilizing the builtin Socket Components that the circuits library ships with. """ -from circuits import handler, Debugger +from circuits import Debugger, handler from circuits.net.sockets import TCPServer diff -Nru circuits-3.1.0+ds1/docs/source/examples/hello.py circuits-3.2.2/docs/source/examples/hello.py --- circuits-3.1.0+ds1/docs/source/examples/hello.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/docs/source/examples/hello.py 2021-10-19 16:23:49.000000000 +0000 @@ -6,6 +6,7 @@ class hello(Event): + """hello Event""" diff -Nru circuits-3.1.0+ds1/docs/source/examples/helloweb.py circuits-3.2.2/docs/source/examples/helloweb.py --- circuits-3.1.0+ds1/docs/source/examples/helloweb.py 2014-09-29 08:08:34.000000000 +0000 +++ circuits-3.2.2/docs/source/examples/helloweb.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,6 +1,6 @@ #!/usr/bin/env python -from circuits.web import Server, Controller +from circuits.web import Controller, Server class Root(Controller): diff -Nru circuits-3.1.0+ds1/docs/source/examples/index.rst circuits-3.2.2/docs/source/examples/index.rst --- circuits-3.1.0+ds1/docs/source/examples/index.rst 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/docs/source/examples/index.rst 2021-10-19 16:23:49.000000000 +0000 @@ -36,4 +36,4 @@ -More `examples `_... +More `examples `_... diff -Nru circuits-3.1.0+ds1/docs/source/faq.rst circuits-3.2.2/docs/source/faq.rst --- circuits-3.1.0+ds1/docs/source/faq.rst 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/docs/source/faq.rst 2021-10-19 16:23:49.000000000 +0000 @@ -42,7 +42,7 @@ ... What platforms does circuits support? circuits currently supports Linux, FreeBSD, OSX and Windows and is currently continually tested against Linux and Windows against Python - versions 2.6, 2.7, 3.1 and 3.2 + versions 2.7, 3.4, 3.5 and 3.6 ... Can circuits be used for concurrent or distributed programming? Yes. We also have plans to build more distributed components into circuits diff -Nru circuits-3.1.0+ds1/docs/source/man/components.rst circuits-3.2.2/docs/source/man/components.rst --- circuits-3.1.0+ds1/docs/source/man/components.rst 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/docs/source/man/components.rst 2021-10-19 16:23:49.000000000 +0000 @@ -35,6 +35,9 @@ - :meth:`~BaseComponent.register` - :meth:`~BaseComponent.unregister` +The hierarchy of components facilitates addition and removal of complex components at runtime. + +All registered components in the hierarchy receive all applicable events regardless of lineage. Component Registration ---------------------- @@ -153,5 +156,5 @@ set([]) >>> -The `telnet Example `_ +The `telnet Example `_ does this for example. diff -Nru circuits-3.1.0+ds1/docs/source/man/debugger.rst circuits-3.2.2/docs/source/man/debugger.rst --- circuits-3.1.0+ds1/docs/source/man/debugger.rst 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/docs/source/man/debugger.rst 2021-10-19 16:23:49.000000000 +0000 @@ -36,7 +36,7 @@ """Your Application""" - app = Appp() + app = App() Debugger().register(app) app.run() @@ -79,15 +79,15 @@ , )> )> >>> app.fire(foo(1, 2)) - + >>> Logged Exceptions:: >>> app.fire(foo()) - + >>> , TypeError('foo() takes exactly 3 arguments (1 given)',), [' File "/home/prologic/work/circuits/circuits/core/manager.py", line 561, in _dispatcher\n value = handler(*eargs, **ekwargs)\n'] handler=>, fevent=)> - ERROR () {}: foo() takes exactly 3 arguments (1 given) + ERROR () {}: foo() takes exactly 3 arguments (1 given) File "/home/prologic/work/circuits/circuits/core/manager.py", line 561, in _dispatcher value = handler(*eargs, **ekwargs) diff -Nru circuits-3.1.0+ds1/docs/source/man/examples/handler_annotation.py circuits-3.2.2/docs/source/man/examples/handler_annotation.py --- circuits-3.1.0+ds1/docs/source/man/examples/handler_annotation.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/docs/source/man/examples/handler_annotation.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,6 +1,6 @@ #!/usr/bin/env python -from circuits import handler, BaseComponent, Debugger +from circuits import BaseComponent, Debugger, handler class MyComponent(BaseComponent): diff -Nru circuits-3.1.0+ds1/docs/source/man/examples/handler_returns.py circuits-3.2.2/docs/source/man/examples/handler_returns.py --- circuits-3.1.0+ds1/docs/source/man/examples/handler_returns.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/docs/source/man/examples/handler_returns.py 2021-10-19 16:23:49.000000000 +0000 @@ -4,6 +4,7 @@ class Identify(Event): + """Identify Event""" success = True @@ -36,10 +37,12 @@ class Bob(Dog): + """Bob""" class Fred(Dog): + """Fred""" Pound().run() diff -Nru circuits-3.1.0+ds1/docs/source/man/misc/tools.rst circuits-3.2.2/docs/source/man/misc/tools.rst --- circuits-3.1.0+ds1/docs/source/man/misc/tools.rst 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/docs/source/man/misc/tools.rst 2021-10-19 16:23:49.000000000 +0000 @@ -37,11 +37,11 @@ Event Handlers: 3 unregister; 1 - + foo; 1 - + prepare_unregister_complete; 1 - .prepare_unregister_complete] (App._on_prepare_unregister_complete)> + ][prepare_unregister_complete] (App._on_prepare_unregister_complete)> Displaying a Visual Representation of your Application @@ -92,7 +92,7 @@ the top-level component in your application of the value you pass to the ``name=`` keyword argument of ``~circuits.tools.graph``. -Example output of `telnet Example `_: +Example output of `telnet Example `_: .. image:: ../examples/Telnet.png diff -Nru circuits-3.1.0+ds1/docs/source/man/values.rst circuits-3.2.2/docs/source/man/values.rst --- circuits-3.1.0+ds1/docs/source/man/values.rst 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/docs/source/man/values.rst 2021-10-19 16:23:49.000000000 +0000 @@ -90,10 +90,10 @@ >>> app.tick() >>> app.tick() - ] ( )> + ] ( )> >>> app.tick() >>> x - + >>> x.value 'Hello World!' >>> diff -Nru circuits-3.1.0+ds1/docs/source/roadmap.rst circuits-3.2.2/docs/source/roadmap.rst --- circuits-3.1.0+ds1/docs/source/roadmap.rst 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/docs/source/roadmap.rst 2021-10-19 16:23:49.000000000 +0000 @@ -1,23 +1,6 @@ Road Map ======== +We managed our Roadmap on our [Github Project](https://github.com/circuits/circuits) -Here's a list of upcoming releases of circuits in order of "next release -first". - -Each bullet point states a high level goal we're trying to achieve for -the release whilst the "Issues List" (*linked to our Issue Tracker*) -lists specific issues we've tagged with the respective milestone. - -.. note:: At this stage we don't have any good estimates for our milestones - but we hope we can improve this with future releases and start - adding estimates here. - - -circuits 3.1 ------------- - -- Improved `circuits.web `_ - - -.. seealso:: `circuits 3.1 milestone `_ +.. see:: [Milestones](https://github.com/circuits/circuits/milestones) diff -Nru circuits-3.1.0+ds1/docs/source/start/downloading.rst circuits-3.2.2/docs/source/start/downloading.rst --- circuits-3.1.0+ds1/docs/source/start/downloading.rst 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/docs/source/start/downloading.rst 2021-10-19 16:23:49.000000000 +0000 @@ -6,21 +6,20 @@ --------------------- The latest stable releases can be downloaded from the -`Downloads `_ page +`Releases `_ page (*specifically the Tags tab*). Latest Development Source Code ------------------------------ -We use `Mercurial `_ for source control -and code sharing. +We use `Git `_ for source control and code sharing. The latest development branch can be cloned using the following command: .. code-block:: sh - $ hg clone https://bitbucket.org/circuits/circuits/ + $ git clone https://github.com/circuits/circuits.git -For further instructions on how to use Mercurial, please refer to the -`Mercurial Book `_. +For further instructions on how to use Git, please refer to the +`Git Website `_. diff -Nru circuits-3.1.0+ds1/docs/source/start/requirements.rst circuits-3.2.2/docs/source/start/requirements.rst --- circuits-3.1.0+ds1/docs/source/start/requirements.rst 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/docs/source/start/requirements.rst 2021-10-19 16:23:49.000000000 +0000 @@ -6,11 +6,11 @@ - circuits has no **required** dependencies beyond the `Python Standard Library`_. -- Python: >= 2.6 or pypy >= 2.0 +- Python: >= 2.7 or pypy >= 2.0 :Supported Platforms: Linux, FreeBSD, Mac OS X, Windows -:Supported Python Versions: 2.6, 2.7, 3.2, 3.3 +:Supported Python Versions: 2.7, 3.4, 3.5, 3.6 :Supported pypy Versions: 2.0 diff -Nru circuits-3.1.0+ds1/docs/source/_themes/om/layout.html circuits-3.2.2/docs/source/_themes/om/layout.html --- circuits-3.1.0+ds1/docs/source/_themes/om/layout.html 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/docs/source/_themes/om/layout.html 2021-10-19 16:23:49.000000000 +0000 @@ -18,39 +18,6 @@ {% block extrahead %} {{ super() }} - - {% endblock %} {% block document %} diff -Nru circuits-3.1.0+ds1/docs/source/tutorials/telnet/index.rst circuits-3.2.2/docs/source/tutorials/telnet/index.rst --- circuits-3.1.0+ds1/docs/source/tutorials/telnet/index.rst 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/docs/source/tutorials/telnet/index.rst 2021-10-19 16:23:49.000000000 +0000 @@ -9,7 +9,7 @@ -------- Welcome to our 2nd circuits tutorial. This tutorial is going to walk you -through the `telnet Example `_ +through the `telnet Example `_ showing you how to various parts of the circuits component library for building a simple TCP client that also accepts user input. @@ -166,7 +166,7 @@ ------- To try this example out, download a copy of the -`echoserver Example `_ +`echoserver Example `_ and copy and paste the full source code of the ``Telnet`` example above into a file called ``telnet.py``. @@ -180,7 +180,7 @@ Have fun! -For more examples see `examples `_. +For more examples see `examples `_. .. seealso:: - :doc:`../../faq` diff -Nru circuits-3.1.0+ds1/docs/source/tutorials/telnet/telnet.py circuits-3.2.2/docs/source/tutorials/telnet/telnet.py --- circuits-3.1.0+ds1/docs/source/tutorials/telnet/telnet.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/docs/source/tutorials/telnet/telnet.py 2021-10-19 16:23:49.000000000 +0000 @@ -2,11 +2,10 @@ import sys - +from circuits import Component, handler from circuits.io import File -from circuits import handler, Component -from circuits.net.sockets import TCPClient from circuits.net.events import connect, write +from circuits.net.sockets import TCPClient class Telnet(Component): diff -Nru circuits-3.1.0+ds1/docs/source/tutorials/woof/002.py circuits-3.2.2/docs/source/tutorials/woof/002.py --- circuits-3.1.0+ds1/docs/source/tutorials/woof/002.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/docs/source/tutorials/woof/002.py 2021-10-19 16:23:49.000000000 +0000 @@ -4,6 +4,7 @@ class MyComponent(Component): + """My Component""" MyComponent().run() diff -Nru circuits-3.1.0+ds1/docs/source/tutorials/woof/006.py circuits-3.2.2/docs/source/tutorials/woof/006.py --- circuits-3.1.0+ds1/docs/source/tutorials/woof/006.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/docs/source/tutorials/woof/006.py 2021-10-19 16:23:49.000000000 +0000 @@ -4,6 +4,7 @@ class woof(Event): + """woof Event""" @@ -26,10 +27,12 @@ class Bob(Dog): + """Bob""" class Fred(Dog): + """Fred""" Pound().run() diff -Nru circuits-3.1.0+ds1/docs/source/tutorials/woof/007.py circuits-3.2.2/docs/source/tutorials/woof/007.py --- circuits-3.1.0+ds1/docs/source/tutorials/woof/007.py 2014-09-20 22:14:32.000000000 +0000 +++ circuits-3.2.2/docs/source/tutorials/woof/007.py 2021-10-19 16:23:49.000000000 +0000 @@ -4,6 +4,7 @@ class woof(Event): + """woof Event""" @@ -26,12 +27,14 @@ class Bob(Dog): + """Bob""" channel = "bob" class Fred(Dog): + """Fred""" channel = "fred" diff -Nru circuits-3.1.0+ds1/docs/source/tutorials/woof/008.py circuits-3.2.2/docs/source/tutorials/woof/008.py --- circuits-3.1.0+ds1/docs/source/tutorials/woof/008.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/docs/source/tutorials/woof/008.py 2021-10-19 16:23:49.000000000 +0000 @@ -4,6 +4,7 @@ class bark(Event): + """bark Event""" @@ -26,12 +27,14 @@ class Bob(Dog): + """Bob""" channel = "bob" class Fred(Dog): + """Fred""" channel = "fred" diff -Nru circuits-3.1.0+ds1/docs/source/tutorials/woof/009.py circuits-3.2.2/docs/source/tutorials/woof/009.py --- circuits-3.1.0+ds1/docs/source/tutorials/woof/009.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/docs/source/tutorials/woof/009.py 2021-10-19 16:23:49.000000000 +0000 @@ -4,6 +4,7 @@ class bark(Event): + """bark Event""" @@ -26,12 +27,14 @@ class Bob(Dog): + """Bob""" channel = "bob" class Fred(Dog): + """Fred""" channel = "fred" diff -Nru circuits-3.1.0+ds1/docs/source/web/howtos.rst circuits-3.2.2/docs/source/web/howtos.rst --- circuits-3.1.0+ds1/docs/source/web/howtos.rst 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/docs/source/web/howtos.rst 2021-10-19 16:23:49.000000000 +0000 @@ -128,7 +128,7 @@ from circuits.net.events import write from circuits import Component, Debugger - from circuits.web.dispatchers import WebSockets + from circuits.web.dispatchers import WebSocketsDispatcher from circuits.web import Controller, Logger, Server, Static @@ -152,10 +152,10 @@ Echo().register(app) Root().register(app) Logger().register(app) - WebSockets("/websocket").register(app) + WebSocketsDispatcher("/websocket").register(app) app.run() -See the `circuits.web examples `_. +See the `circuits.web examples `_. How do I: Build a Simple Form diff -Nru circuits-3.1.0+ds1/examples/99bottles.py circuits-3.2.2/examples/99bottles.py --- circuits-3.1.0+ds1/examples/99bottles.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/examples/99bottles.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,23 +1,19 @@ #!/usr/bin/env python - - """An implementation of the Python Concurrency Problem of 99 Bottles of Beer See: http://wiki.python.org/moin/Concurrency/99Bottles """ - - from __future__ import print_function import sys - -from circuits.io import File from circuits import Component +from circuits.io import File from circuits.protocols import Line class Tail(Component): + """A complex component which combines the ``File`` and ``LP`` (Line Protoco) components together to implement similar functionality to the UNIX ``tail`` command. @@ -33,6 +29,7 @@ class Grep(Component): + """A simple component that simply listens for ``line`` events from the ``Tail`` component and performs a regular expression match against each line. If the line matches it is printed to standard output. diff -Nru circuits-3.1.0+ds1/examples/async_worker_webpage_download.py circuits-3.2.2/examples/async_worker_webpage_download.py --- circuits-3.1.0+ds1/examples/async_worker_webpage_download.py 1970-01-01 00:00:00.000000000 +0000 +++ circuits-3.2.2/examples/async_worker_webpage_download.py 2021-10-19 16:23:49.000000000 +0000 @@ -0,0 +1,44 @@ +from time import sleep + +import requests + +from circuits import Component, Debugger, Event, Timer, Worker, task + + +def download_web_page(url): + print('Downloading {}'.format(url)) + response = requests.get(url) + sleep(2) # This website is really slow. + # Only returning portion of web page. + # You would probably process web page for data before sending back + return response.text[:200] + + +class App(Component): + + def init(self, *args, **kwargs): + self.foo_count = 0 + Worker(process=False).register(self) + + def foo(self): + self.foo_count += 1 + print("Foo!") + if self.foo_count > 10: + self.stop() + + def started(self, component): + # x = yield self.call(task(factorial, 10)) + Timer(1, Event.create("foo"), persist=True).register(self) + self.fire(task(download_web_page, 'http://www.slickdeals.net')) # async + self.fire(task(download_web_page, 'http://www.google.com')) # async + self.fire(task(download_web_page, 'http://www.yahoo.com')) # async + + def task_success(self, function_called, function_result): + func, url_called = function_called + print('url {} gave {}'.format(url_called, function_result)) + + +if __name__ == '__main__': + app = App() + Debugger().register(app) + app.run() diff -Nru circuits-3.1.0+ds1/examples/cat.py circuits-3.2.2/examples/cat.py --- circuits-3.1.0+ds1/examples/cat.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/examples/cat.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,17 +1,12 @@ #!/usr/bin/env python - - """Clone of the standard UNIX "cat" command. This example shows how you can utilize some of the buitlin I/O components in circuits to write a very simple clone of the standard UNIX "cat" command. """ - - import sys - -from circuits.io import stdout, File, write +from circuits.io import File, stdout, write class Cat(File): diff -Nru circuits-3.1.0+ds1/examples/cert.pem circuits-3.2.2/examples/cert.pem --- circuits-3.1.0+ds1/examples/cert.pem 1970-01-01 00:00:00.000000000 +0000 +++ circuits-3.2.2/examples/cert.pem 2021-10-19 16:23:49.000000000 +0000 @@ -0,0 +1,37 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICWwIBAAKBgQC9B7hV67bzhLA//STrZUIi0iHD4WFtftOhvj+xiHRNnYw0+r+4 +WdQv1YiL+ab03pn/J9R1SQuOGwYDVPQvYX+qEFVRUFP9yvXIQl7PG40HQzfs8lJz +hnmI+64HJT//oJ9e7PiyDHLfFH1FuCqSy9RlvzOd4hmydX9J3VxFFzrpJQIDAQAB +AoGAHhGxT/Gb+6a6xqMFEXDdEV7twhQDBIDtN0hlJ192aLZMDE1q2+9mImnMO7/t +v/v88Sqr0DBbZzKDRVppMXRH80ZtnmMu3/3kUCtA3WAbKxyFpIiXGv/NAUHZe5Gz +rua+z3lUvmt6CmwMm2ReB70Q61zxr9q4HjrjYI82dtJ4M40CQQDnGujxdBdbPmiR +oc8mcShfmPNP7igQrUkf/DpB0GWnLWdA97mmXLw4jHXpHy9gm3wGc+9uOi0Ex8Ml +1t9xAGFjAkEA0WSGwG45d5dmYV8Oa/9UsY5/F6hAlYAAI1TxRsKcl2YTqaQastac +glV1GSUrgGw/8UBvdKKS2REF7cpAkiQV1wJAPtQhCiuOgf7YfOcpowDWgg7Z7xwH +Bmml3K08xVG7oRSF4rK2ZRUHErSVBbi1r6T1tedk62mjfY41bp8ZBeadkwJAD7AG +YHhhmdIf+3+Rpwm0ILFaWD1kyU6TtBHzGagO71DYfEctMOTfSOx6H24nejGiAMMh +Fo3vjo+18ADNIaXOdQJAYdm+dUdyVaW2IDUi7ew0shyKTC4OaEZtXIwwINvrqUsX +//6z8mw/S5rXGlfKadiz4uwzcXlSvg727O1efpibvA== +-----END RSA PRIVATE KEY----- +-----BEGIN CERTIFICATE----- +MIIDjTCCAvagAwIBAgIJAN0msyL5El/jMA0GCSqGSIb3DQEBBQUAMIGMMQswCQYD +VQQGEwJBVTETMBEGA1UECBMKUXVlZW5zbGFuZDERMA8GA1UEBxMIQnJpc2JhbmUx +FTATBgNVBAoTDFNob3J0Q2lyY3VpdDEUMBIGA1UEAxMLSmFtZXMgTWlsbHMxKDAm +BgkqhkiG9w0BCQEWGWFkbWluQHNob3J0Y2lyY3VpdC5uZXQuYXUwHhcNMTAwMTEz +MDczOTAwWhcNMTEwMTEzMDczOTAwWjCBjDELMAkGA1UEBhMCQVUxEzARBgNVBAgT +ClF1ZWVuc2xhbmQxETAPBgNVBAcTCEJyaXNiYW5lMRUwEwYDVQQKEwxTaG9ydENp +cmN1aXQxFDASBgNVBAMTC0phbWVzIE1pbGxzMSgwJgYJKoZIhvcNAQkBFhlhZG1p +bkBzaG9ydGNpcmN1aXQubmV0LmF1MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB +gQC9B7hV67bzhLA//STrZUIi0iHD4WFtftOhvj+xiHRNnYw0+r+4WdQv1YiL+ab0 +3pn/J9R1SQuOGwYDVPQvYX+qEFVRUFP9yvXIQl7PG40HQzfs8lJzhnmI+64HJT// +oJ9e7PiyDHLfFH1FuCqSy9RlvzOd4hmydX9J3VxFFzrpJQIDAQABo4H0MIHxMB0G +A1UdDgQWBBSq+tU5ZDymUuMcgZ83gxk1PTN89zCBwQYDVR0jBIG5MIG2gBSq+tU5 +ZDymUuMcgZ83gxk1PTN896GBkqSBjzCBjDELMAkGA1UEBhMCQVUxEzARBgNVBAgT +ClF1ZWVuc2xhbmQxETAPBgNVBAcTCEJyaXNiYW5lMRUwEwYDVQQKEwxTaG9ydENp +cmN1aXQxFDASBgNVBAMTC0phbWVzIE1pbGxzMSgwJgYJKoZIhvcNAQkBFhlhZG1p +bkBzaG9ydGNpcmN1aXQubmV0LmF1ggkA3SazIvkSX+MwDAYDVR0TBAUwAwEB/zAN +BgkqhkiG9w0BAQUFAAOBgQAokSGDpbFV2osC8nM8K12vheeDBVDHGxOaENXGVIm8 +SWPXsaIUsm6JQx0wm/eouWRPbNJkOBwBrNCls1oMmdxdxG8mBh+kAMWUkdVeuT2H +lCo9BRJnhUr4L6poJ7ORzL2oUilGZNwONpHGY0cWzFG8/tOoRJsfKZm23bwXbIxv +Hw== +-----END CERTIFICATE----- diff -Nru circuits-3.1.0+ds1/examples/chatserver.py circuits-3.2.2/examples/chatserver.py --- circuits-3.1.0+ds1/examples/chatserver.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/examples/chatserver.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,21 +1,15 @@ #!/usr/bin/env python - - """Chat Server Example This example demonstrates how to create a very simple telnet-style chat server that supports many connecting clients. """ - - from optparse import OptionParser - -from circuits.net.events import write from circuits import Component, Debugger +from circuits.net.events import write from circuits.net.sockets import TCPServer - __version__ = "0.0.1" USAGE = "%prog [options]" @@ -50,7 +44,7 @@ """Initialize our ``ChatServer`` Component. This uses the convenience ``init`` method which is called after the - component is proeprly constructed and initialized and passed the + component is properly constructed and initialized and passed the same args and kwargs that were passed during construction. """ @@ -109,7 +103,7 @@ del self.clients[sock] def read(self, sock, data): - """Read Event -- Triggered for when client conenctions have data""" + """Read Event -- Triggered for when client connections have data""" data = data.strip().decode("utf-8") diff -Nru circuits-3.1.0+ds1/examples/circ.py circuits-3.2.2/examples/circ.py --- circuits-3.1.0+ds1/examples/circ.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/examples/circ.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,6 +1,4 @@ #!/usr/bin/env python - - """Circuits IRC Client A circuits based IRC Client demonstrating integration with urwid - a curses @@ -13,31 +11,23 @@ ./circ.py --help """ - - import os import sys -from select import select -from inspect import getargspec -from socket import gethostname from optparse import OptionParser from re import compile as compile_regex +from select import select +from socket import gethostname +from urwid import AttrWrap, Edit, Frame, ListBox, Pile, SimpleListWalker, Text +from urwid.raw_display import Screen -from circuits import handler, Component -from circuits import __version__ as systemVersion +from circuits import Component, __version__ as systemVersion, handler from circuits.net.sockets import TCPClient, connect - from circuits.protocols.irc import ( - request, Message, - IRC, RPL_ENDOFMOTD, - ERR_NICKNAMEINUSE, ERR_NOMOTD, - QUIT, PART, PRIVMSG, USER, NICK, JOIN + ERR_NICKNAMEINUSE, ERR_NOMOTD, IRC, JOIN, NICK, PART, PRIVMSG, QUIT, + RPL_ENDOFMOTD, USER, Message, request, ) - -from urwid.raw_display import Screen -from urwid import AttrWrap, Edit, Frame, ListBox, Pile, SimpleListWalker, Text - +from circuits.tools import getargspec USAGE = "%prog [options] host [port]" VERSION = "%prog v" + systemVersion @@ -49,7 +39,7 @@ } CMD_REGEX = compile_regex( - "\/(?P[a-z]+) ?" + r"\/(?P[a-z]+) ?" "(?P.*)(?iu)" ) @@ -328,5 +318,6 @@ client.run() + if __name__ == "__main__": main() diff -Nru circuits-3.1.0+ds1/examples/dirwatch.py circuits-3.2.2/examples/dirwatch.py --- circuits-3.1.0+ds1/examples/dirwatch.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/examples/dirwatch.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,5 +1,4 @@ #!/usr/bin/env python - """Directory Watch Example This example demonstrates the inotify I/O Component ``Notify`` which can @@ -7,10 +6,8 @@ takes a path to watch as the first Command Line Argument and prints to stdour every file system event it sees. """ - import sys - from circuits import Component from circuits.io import Notify diff -Nru circuits-3.1.0+ds1/examples/dnsclient.py circuits-3.2.2/examples/dnsclient.py --- circuits-3.1.0+ds1/examples/dnsclient.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/examples/dnsclient.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,6 +1,4 @@ #!/usr/bin/env python - - """DNS Client Example A simple little DNS Client example using @@ -9,7 +7,7 @@ deconstruction (*a really nice library btw with great integration into circuits*). -Specify the server, port and query as argumetns +Specify the server, port, and query as arguments to perform a lookup against a server using UDP. To run this example:: @@ -17,27 +15,24 @@ pip install dnslib ./dnsclient.py 8.8.8.8 53 google.com """ - - from __future__ import print_function - import sys - from dnslib import DNSQuestion, DNSRecord - +from circuits import Component, Debugger, Event from circuits.net.events import write from circuits.net.sockets import UDPClient -from circuits import Event, Component, Debugger class reply(Event): + """reply Event""" class DNS(Component): + """DNS Protocol Handling""" def read(self, peer, data): @@ -45,6 +40,7 @@ class Dummy(Component): + """A Dummy DNS Handler This just parses the reply packet and @@ -69,10 +65,11 @@ class DNSClient(Component): + """DNS Client This ties everything together in a nice - configurable way with protocol, transport + configurable way with protocol, transport, and dummy handler as well as optional debugger. """ diff -Nru circuits-3.1.0+ds1/examples/dnsserver.py circuits-3.2.2/examples/dnsserver.py --- circuits-3.1.0+ds1/examples/dnsserver.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/examples/dnsserver.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,6 +1,4 @@ #!/usr/bin/env python - - """DNS Server Example A simple little DNS Server example using @@ -21,28 +19,24 @@ dig @localhost -p 1053 test.com """ - - from __future__ import print_function - import sys +from dnslib import QTYPE, RR, A, DNSHeader, DNSRecord -from dnslib import A, RR -from dnslib import DNSHeader, DNSRecord, QTYPE - - +from circuits import Component, Debugger, Event from circuits.net.events import write from circuits.net.sockets import UDPServer -from circuits import Event, Component, Debugger class query(Event): + """query Event""" class DNS(Component): + """DNS Protocol Handling""" def read(self, peer, data): @@ -50,6 +44,7 @@ class Dummy(Component): + """A Dummy DNS Handler This just returns an A record response @@ -78,6 +73,7 @@ class DNSServer(Component): + """DNS Server This ties everything together in a nice diff -Nru circuits-3.1.0+ds1/examples/echoserial.py circuits-3.2.2/examples/echoserial.py --- circuits-3.1.0+ds1/examples/echoserial.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/examples/echoserial.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,19 +1,15 @@ #!/usr/bin/env python - - """Simple Serial Example This example shows how to use the ``circuits.io.Serial`` Component to access serial data. This example simply echos back what it receives on the serial port. -.. warning:: THis example is currently untested. +.. warning:: This example is currently untested. """ - - +from circuits import Component, Debugger, handler from circuits.io import Serial from circuits.io.events import write -from circuits import handler, Component, Debugger class EchoSerial(Component): diff -Nru circuits-3.1.0+ds1/examples/echoserver.py circuits-3.2.2/examples/echoserver.py --- circuits-3.1.0+ds1/examples/echoserver.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/examples/echoserver.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,14 +1,10 @@ #!/usr/bin/env python - - """Simple TCP Echo Server This example shows how you can create a simple TCP Server (an Echo Service) utilizing the builtin Socket Components that the circuits library ships with. """ - - -from circuits import handler, Debugger +from circuits import Debugger, handler from circuits.net.sockets import TCPServer @@ -32,6 +28,6 @@ # Start and "run" the system. # Bind to port 0.0.0.0:8000 -app = EchoServer(("0.0.0.0", 8000)) +app = EchoServer(("0.0.0.0", 8000), secure=True, certfile="cert.pem") Debugger().register(app) app.run() diff -Nru circuits-3.1.0+ds1/examples/echoserverunix.py circuits-3.2.2/examples/echoserverunix.py --- circuits-3.1.0+ds1/examples/echoserverunix.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/examples/echoserverunix.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,14 +1,10 @@ #!/usr/bin/env python - - """Simple UNIX Echo Server This example shows how you can create a simple UNIX Server (an Echo Service) utilizing the builtin Socket Components that the circuits library ships with. """ - - -from circuits import handler, Debugger +from circuits import Debugger, handler from circuits.net.sockets import UNIXServer diff -Nru circuits-3.1.0+ds1/examples/factorial_multiple.py circuits-3.2.2/examples/factorial_multiple.py --- circuits-3.1.0+ds1/examples/factorial_multiple.py 1970-01-01 00:00:00.000000000 +0000 +++ circuits-3.2.2/examples/factorial_multiple.py 2021-10-19 16:23:49.000000000 +0000 @@ -0,0 +1,47 @@ +#!/usr/bin/env python +from __future__ import print_function + +from time import sleep + +from circuits import Component, Debugger, Event, Timer, Worker, task + + +def factorial(n): + x = 1 + for i in range(1, (n + 1)): + x = x * (i + 1) + sleep(1) # deliberate! + return x + + +class App(Component): + + def init(self, *args, **kwargs): + Worker(process=True).register(self) + + def foo(self): + print("Foo!") + + def started(self, component): + self.fire(task(factorial, 3)) # async + self.fire(task(factorial, 5)) # async + self.fire(task(factorial, 7)) # async + self.fire(task(factorial, 10)) # async + self.fire(task(factorial, 11)) # async + self.fire(task(factorial, 11)) # async + self.fire(task(factorial, 12)) # async + self.fire(task(factorial, 14)) # async + Timer(1, Event.create("foo"), persist=True).register(self) + + def task_success(self, function_called, factorial_result): + func, argument = function_called + print("factorial({0}) = {1:d}".format(str(argument), factorial_result)) + # Stop after the last and longest running task + if argument == 14: + self.stop() + + +if __name__ == '__main__': + app = App() + Debugger().register(app) + app.run() diff -Nru circuits-3.1.0+ds1/examples/factorial.py circuits-3.2.2/examples/factorial.py --- circuits-3.1.0+ds1/examples/factorial.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/examples/factorial.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,13 +1,9 @@ #!/usr/bin/env python - - from __future__ import print_function from time import sleep - -from circuits import task, Worker -from circuits import Component, Debugger, Event, Timer +from circuits import Component, Debugger, Event, Timer, Worker, task def factorial(n): diff -Nru circuits-3.1.0+ds1/examples/filter.py circuits-3.2.2/examples/filter.py --- circuits-3.1.0+ds1/examples/filter.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/examples/filter.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,6 +1,4 @@ #!/usr/bin/env python - - """Simple Event Filtering This example shows how you can filter events by using the ``Event.stop()`` @@ -13,15 +11,13 @@ $ ./filter.py Hello World! """ - - from __future__ import print_function - from circuits import Component, Event class hello(Event): + """hello Event""" diff -Nru circuits-3.1.0+ds1/examples/hello_bridge.py circuits-3.2.2/examples/hello_bridge.py --- circuits-3.1.0+ds1/examples/hello_bridge.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/examples/hello_bridge.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,39 +1,43 @@ -#!/usr/bin/python -i - +#!/usr/bin/env python """Bridge Example -To use this example run it interactively through the Python interactive -shell using the -i option as per the shebang line above. +This example is quite similar to the Hello example +but displays a hello form both the parent and child +processing demonstrating how IPC works using the Bridge. +""" +from __future__ import print_function + +from os import getpid -i.e: python -i hello_bridge.py +from circuits import Component, Event, ipc -At the python prompt: - >>> x = m.fire(Hello()) - . - . - . - >>> x - -""" # noqa +class hello(Event): + """hello Event""" -from os import getpid +class Child(Component): + def hello(self): + return "Hello from child with pid {0}".format(getpid()) -from circuits import Component, Debugger, Event, Manager +class App(Component): -class hello(Event): - """hello Event""" + def init(self): + Child().start(process=True, link=self) + def ready(self, *args): + x = yield self.call(hello()) + yield print(x) -class App(Component): + y = yield self.call(ipc(hello())) + yield print(y) + + raise SystemExit(0) def hello(self): - return "Hello World! ({0:d})".format(getpid()) + return "Hello from parent with pid {0}".format(getpid()) -m = Manager() + Debugger() -m.start() -App().start(process=True, link=m) +App().run() diff -Nru circuits-3.1.0+ds1/examples/hello_multi_bridge.py circuits-3.2.2/examples/hello_multi_bridge.py --- circuits-3.1.0+ds1/examples/hello_multi_bridge.py 1970-01-01 00:00:00.000000000 +0000 +++ circuits-3.2.2/examples/hello_multi_bridge.py 2021-10-19 16:23:49.000000000 +0000 @@ -0,0 +1,56 @@ +#!/usr/bin/env python +"""Multi Bridge Example + +Identical to the Hello Bridge Example but with a 2nd child. +""" +from __future__ import print_function + +from os import getpid + +from circuits import Component, Event, ipc + + +class go(Event): + """go Event""" + + +class hello(Event): + """hello Event""" + + +class Child(Component): + + def hello(self): + return "Hello from child with pid {0}".format(getpid()) + + +class App(Component): + + def init(self): + self.counter = 0 + self.child1 = Child().start(process=True, link=self) + self.child2 = Child().start(process=True, link=self) + + def ready(self, *args): + self.counter += 1 + if self.counter < 2: + return + self.fire(go()) + + def go(self): + x = yield self.call(hello()) + yield print(x) + + y = yield self.call(ipc(hello()), self.child1[1].channel) + yield print(y) + + z = yield self.call(ipc(hello()), self.child2[1].channel) + yield print(z) + + raise SystemExit(0) + + def hello(self): + return "Hello from parent with pid {0}".format(getpid()) + + +App().run() diff -Nru circuits-3.1.0+ds1/examples/hello.py circuits-3.2.2/examples/hello.py --- circuits-3.1.0+ds1/examples/hello.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/examples/hello.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,11 +1,8 @@ #!/usr/bin/env python - - """circuits Hello World""" from __future__ import print_function - from circuits import Component, Event @@ -13,6 +10,10 @@ """hello Event""" +class terminate(Event): + """terminate Event""" + + class App(Component): def hello(self): @@ -20,7 +21,7 @@ print("Hello World!") - def started(self, component): + def started(self, *args): """Started Event Handler This is fired internally when your application starts up @@ -29,7 +30,9 @@ """ self.fire(hello()) # Fire hello Event + self.fire(terminate()) + def terminate(self): raise SystemExit(0) # Terminate the Application diff -Nru circuits-3.1.0+ds1/examples/index.rst circuits-3.2.2/examples/index.rst --- circuits-3.1.0+ds1/examples/index.rst 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/examples/index.rst 2021-10-19 16:23:49.000000000 +0000 @@ -106,4 +106,4 @@ app.run() -More `examples `_... +More `examples `_... diff -Nru circuits-3.1.0+ds1/examples/ircbot.py circuits-3.2.2/examples/ircbot.py --- circuits-3.1.0+ds1/examples/ircbot.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/examples/ircbot.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,5 +1,4 @@ #!/usr/bin/env python - """IRC Bot Example This example shows how to use several components in circuits as well @@ -7,17 +6,14 @@ to the FreeNode IRC Network and joins the #circuits channel. It will also echo anything privately messages to it in response. """ - - import sys - -from circuits import Component +from circuits import Component, Debugger from circuits.net.sockets import TCPClient, connect -from circuits.protocols.irc import IRC, PRIVMSG, USER, NICK, JOIN - -from circuits.protocols.irc import ERR_NICKNAMEINUSE -from circuits.protocols.irc import RPL_ENDOFMOTD, ERR_NOMOTD +from circuits.protocols.irc import ( + ERR_NICKNAMEINUSE, ERR_NOMOTD, IRC, JOIN, NICK, PRIVMSG, RPL_ENDOFMOTD, + USER, +) class Bot(Component): @@ -89,7 +85,6 @@ # Configure and run the system bot = Bot(*sys.argv[1:]) -from circuits import Debugger Debugger().register(bot) # To register a 2nd ``Bot`` instance. Simply use a separate channel. diff -Nru circuits-3.1.0+ds1/examples/ircclient.py circuits-3.2.2/examples/ircclient.py --- circuits-3.1.0+ds1/examples/ircclient.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/examples/ircclient.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,7 +1,5 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- - - """Example IRC Client A basic IRC client with a very basic console interface. @@ -11,25 +9,17 @@ ./ircclient.py --help """ - - from __future__ import print_function import os -from socket import gethostname from optparse import OptionParser +from socket import gethostname - -from circuits import handler, Component -from circuits import __version__ as systemVersion - +from circuits import Component, Debugger, __version__ as systemVersion, handler from circuits.io import stdin - from circuits.net.events import connect from circuits.net.sockets import TCPClient - -from circuits.protocols.irc import IRC, PRIVMSG, USER, NICK, JOIN - +from circuits.protocols.irc import IRC, JOIN, NICK, PRIVMSG, USER USAGE = "%prog [options] host [port]" VERSION = "%prog v" + systemVersion @@ -45,6 +35,12 @@ ) parser.add_option( + "-d", "--debug", + action="store_true", default=False, dest="debug", + help="Enable debug verbose logging", + ) + + parser.add_option( "-c", "--channel", action="store", default="#circuits", dest="channel", help="Channel to join" @@ -77,6 +73,10 @@ TCPClient(channel=self.channel).register(self) IRC(channel=self.channel).register(self) + # Enable Debugging? + if opts.debug: + Debugger().register(self) + def ready(self, component): """ready Event @@ -102,6 +102,17 @@ self.fire(NICK(nick)) self.fire(USER(nick, nick, self.hostname, name)) + def disconnected(self): + """disconnected Event + + This event is triggered by the underlying ``TCPClient`` Component + when the connection has been disconnected. + """ + + print("Disconnecetd from %s:%d" % (self.host, self.port)) + + raise SystemExit(0) + def numeric(self, source, numeric, *args): """numeric Event diff -Nru circuits-3.1.0+ds1/examples/ircd.py circuits-3.2.2/examples/ircd.py --- circuits-3.1.0+ds1/examples/ircd.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/examples/ircd.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,6 +1,4 @@ #!/usr/bin/env python - - """Example IRC Server .. note:: This is an example only and is feature incomplete. @@ -9,34 +7,26 @@ USER NICK JOIN PART NICK WHO QUIT """ - - import logging -from logging import getLogger - -from time import time -from sys import stderr +from argparse import ArgumentDefaultsHelpFormatter, ArgumentParser +from collections import defaultdict from itertools import chain +from logging import getLogger from operator import attrgetter -from collections import defaultdict -from argparse import ArgumentDefaultsHelpFormatter, ArgumentParser - - -from circuits import handler, Component, Debugger +from sys import stderr +from time import time -from circuits.net.sockets import TCPServer +from circuits import Component, Debugger, handler from circuits.net.events import close, write - -from circuits.protocols.irc import joinprefix, reply, response, IRC, Message - +from circuits.net.sockets import TCPServer +from circuits.protocols.irc import IRC, Message, joinprefix, reply, response from circuits.protocols.irc.replies import ( - ERR_NOMOTD, ERR_NOSUCHNICK, ERR_NOSUCHCHANNEL, ERR_UNKNOWNCOMMAND, - RPL_WELCOME, RPL_YOURHOST, RPL_WHOREPLY, RPL_ENDOFWHO, RPL_NOTOPIC, - RPL_NAMEREPLY, RPL_ENDOFNAMES, - ERR_NICKNAMEINUSE, + ERR_NICKNAMEINUSE, ERR_NOMOTD, ERR_NOSUCHCHANNEL, ERR_NOSUCHNICK, + ERR_UNKNOWNCOMMAND, RPL_CHANNELMODEIS, RPL_ENDOFNAMES, RPL_ENDOFWHO, + RPL_LIST, RPL_LISTEND, RPL_LISTSTART, RPL_NAMEREPLY, RPL_NOTOPIC, + RPL_TOPIC, RPL_WELCOME, RPL_WHOREPLY, RPL_YOURHOST, ) - __version__ = "0.0.1" @@ -73,6 +63,8 @@ def __init__(self, name): self.name = name + self.topic = None + self.mode = '+n' self.users = [] @@ -85,6 +77,7 @@ self.port = port self.nick = None + self.mode = '' self.away = False self.channels = [] self.signon = None @@ -190,7 +183,7 @@ user, host = user.userinfo.user, user.userinfo.host yield self.call( - response.create("quit", sock, (nick, user, host), "Leavling") + response.create("quit", sock, (nick, user, host), "Leaving") ) del self.users[sock] @@ -273,9 +266,12 @@ Message("JOIN", name, prefix=user.prefix) ) - self.fire(reply(sock, RPL_NOTOPIC(name))) - self.fire(reply(sock, RPL_NAMEREPLY(channel))) - self.fire(reply(sock, RPL_ENDOFNAMES())) + if channel.topic: + self.fire(reply(sock, RPL_TOPIC(channel.topic))) + else: + self.fire(reply(sock, RPL_NOTOPIC(channel.name))) + self.fire(reply(sock, RPL_NAMEREPLY(channel.name, [u.prefix for u in channel.users]))) + self.fire(reply(sock, RPL_ENDOFNAMES(channel.name))) def part(self, sock, source, name, reason="Leaving"): user = self.users[sock] @@ -352,6 +348,22 @@ self.fire(write(target, bytes(message))) + def mode(self, sock, source, mask, mode=None, params=None): + if mask.startswith('#'): + if mask not in self.channels: + return self.fire(reply(sock, ERR_NOSUCHCHANNEL(mask))) + channel = self.channels[mask] + if not params: + self.fire(reply(sock, RPL_CHANNELMODEIS(channel.name, channel.mode))) + elif mask not in self.users: + return self.fire(reply(sock, ERR_NOSUCHNICK(mask))) + + def list(self, sock, source): + self.fire(reply(sock, RPL_LISTSTART())) + for channel in self.channels.values(): + self.fire(reply(sock, RPL_LIST(channel, str(len(channel.users)), channel.topic or ''))) + self.fire(reply(sock, RPL_LISTEND())) + @property def commands(self): exclude = {"ready", "connect", "disconnect", "read", "write"} diff -Nru circuits-3.1.0+ds1/examples/node/hello_node.py circuits-3.2.2/examples/node/hello_node.py --- circuits-3.1.0+ds1/examples/node/hello_node.py 2014-09-24 09:54:43.000000000 +0000 +++ circuits-3.2.2/examples/node/hello_node.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,6 +1,4 @@ #!/usr/bin/python -i - - """Node Example To use this example run it interactively through the Python interactive @@ -14,27 +12,25 @@ >>> >>> x - + >>> y = app.fire(remote(hello(), "test")) . . . >>> y - , 'app2' channel=None)> + , 'app2' channel=None)> """ # noqa - - from __future__ import print_function import sys from os import getpid - from circuits import Component, Event from circuits.node import Node, remote # noqa class hello(Event): + """hello Event""" diff -Nru circuits-3.1.0+ds1/examples/node/increment/client_auto_binding.py circuits-3.2.2/examples/node/increment/client_auto_binding.py --- circuits-3.1.0+ds1/examples/node/increment/client_auto_binding.py 1970-01-01 00:00:00.000000000 +0000 +++ circuits-3.2.2/examples/node/increment/client_auto_binding.py 2021-10-19 16:23:49.000000000 +0000 @@ -0,0 +1,76 @@ +#!/usr/bin/env python +from optparse import OptionParser + +from circuits import Component, Debugger, Event +from circuits.node import Node + +__version__ = "0.0.1" + +USAGE = "%prog [options]" +VERSION = "%prog v" + __version__ + + +class increment(Event): + + def __init__(self, value): + Event.__init__(self, value) + + +def parse_options(): + parser = OptionParser(usage=USAGE, version=VERSION) + + parser.add_option( + "-i", "--ip", + action="store", type="string", + default="127.0.0.1:8000", dest="bind", + help="Bind to address:[port]" + ) + + parser.add_option( + "-d", "--debug", + action="store_true", + default=False, dest="debug", + help="Enable debug mode" + ) + + opts, args = parser.parse_args() + + return opts, args + + +class NodeClient(Component): + + def init(self, args, opts): + if opts.debug: + Debugger().register(self) + + if ":" in opts.bind: + address, port = opts.bind.split(":") + port = int(port) + else: + address, port = opts.bind, 8000 + + auto_remote_event = { + 'increment': '*' + } + + node = Node().register(self) + node.add( + 'peer_name', address, port, auto_remote_event=auto_remote_event) + + def connected_to(self, *args, **kwargs): + i = 0 + while True: + print(i) + i = (yield self.call(increment(i))).value + + +def main(): + opts, args = parse_options() + + # Configure and "run" the System. + NodeClient(args, opts).run() + + +if __name__ == "__main__": + main() diff -Nru circuits-3.1.0+ds1/examples/node/increment/client.py circuits-3.2.2/examples/node/increment/client.py --- circuits-3.1.0+ds1/examples/node/increment/client.py 2014-09-24 09:54:43.000000000 +0000 +++ circuits-3.2.2/examples/node/increment/client.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,10 +1,8 @@ #!/usr/bin/env python - from optparse import OptionParser +from circuits import Component, Debugger, Event from circuits.node import Node, remote -from circuits import Component, Debugger, handler, Event - __version__ = "0.0.1" @@ -13,6 +11,7 @@ class increment(Event): + def __init__(self, value): Event.__init__(self, value) @@ -54,7 +53,7 @@ node = Node().register(self) node.add('peer_name', address, port) - def ready(self, client): + def connected_to(self, *args, **kwargs): i = 0 while True: print(i) diff -Nru circuits-3.1.0+ds1/examples/node/increment/server.py circuits-3.2.2/examples/node/increment/server.py --- circuits-3.1.0+ds1/examples/node/increment/server.py 2014-09-24 09:54:43.000000000 +0000 +++ circuits-3.2.2/examples/node/increment/server.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,10 +1,8 @@ #!/usr/bin/env python - from optparse import OptionParser -from circuits.node import Node from circuits import Component, Debugger, handler - +from circuits.node import Node __version__ = "0.0.1" @@ -46,9 +44,7 @@ else: address, port = opts.bind, 8000 - bind = (address, port) - - Node(bind).register(self) + Node(port=port, server_ip=address).register(self) def connect(self, sock, host, port): print('Peer connected: %s:%d' % (host, port)) diff -Nru circuits-3.1.0+ds1/examples/node/nodeserver.py circuits-3.2.2/examples/node/nodeserver.py --- circuits-3.1.0+ds1/examples/node/nodeserver.py 2014-09-24 09:54:43.000000000 +0000 +++ circuits-3.2.2/examples/node/nodeserver.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,23 +1,17 @@ #!/usr/bin/env python - - """Node Server Example This example demonstrates how to create a very simple node server that supports bi-diractional messaging between server and connected clients forming a cluster of nodes. """ - - from __future__ import print_function -from os import getpid from optparse import OptionParser +from os import getpid - -from circuits.node import Node from circuits import Component, Debugger - +from circuits.node import Node __version__ = "0.0.1" @@ -71,9 +65,7 @@ else: address, port = opts.bind, 8000 - bind = (address, port) - - Node(bind).register(self) + Node(port=port, server_ip=address).register(self) def connect(self, sock, host, port): """Connect Event -- Triggered for new connecting clients""" diff -Nru circuits-3.1.0+ds1/examples/node/send_all_client/client.py circuits-3.2.2/examples/node/send_all_client/client.py --- circuits-3.1.0+ds1/examples/node/send_all_client/client.py 1970-01-01 00:00:00.000000000 +0000 +++ circuits-3.2.2/examples/node/send_all_client/client.py 2021-10-19 16:23:49.000000000 +0000 @@ -0,0 +1,62 @@ +#!/usr/bin/env python +from optparse import OptionParser + +from circuits import Component, Debugger +from circuits.node import Node + +__version__ = "0.0.1" + +USAGE = "%prog [options]" +VERSION = "%prog v" + __version__ + + +def parse_options(): + parser = OptionParser(usage=USAGE, version=VERSION) + + parser.add_option( + "-i", "--ip", + action="store", type="string", + default="127.0.0.1:8000", dest="bind", + help="Bind to address:[port]" + ) + + parser.add_option( + "-d", "--debug", + action="store_true", + default=False, dest="debug", + help="Enable debug mode" + ) + + opts, args = parser.parse_args() + + return opts, args + + +class NodeClient(Component): + + def init(self, args, opts): + if opts.debug: + Debugger().register(self) + + if ":" in opts.bind: + address, port = opts.bind.split(":") + port = int(port) + else: + address, port = opts.bind, 8000 + + node = Node().register(self) + node.add('peer_name', address, port) + + def send_all_event(self, infos): + print('receive: %s' % infos) + + +def main(): + opts, args = parse_options() + + # Configure and "run" the System. + NodeClient(args, opts).run() + + +if __name__ == "__main__": + main() diff -Nru circuits-3.1.0+ds1/examples/node/send_all_client/server.py circuits-3.2.2/examples/node/send_all_client/server.py --- circuits-3.1.0+ds1/examples/node/send_all_client/server.py 1970-01-01 00:00:00.000000000 +0000 +++ circuits-3.2.2/examples/node/send_all_client/server.py 2021-10-19 16:23:49.000000000 +0000 @@ -0,0 +1,80 @@ +#!/usr/bin/env python +from datetime import datetime +from optparse import OptionParser + +from circuits import Component, Debugger, Event, Timer +from circuits.node import Node + +__version__ = "0.0.1" + +USAGE = "%prog [options]" +VERSION = "%prog v" + __version__ + + +def parse_options(): + parser = OptionParser(usage=USAGE, version=VERSION) + + parser.add_option( + "-b", "--bind", + action="store", type="string", + default="0.0.0.0:8000", dest="bind", + help="Bind to address:[port]" + ) + + parser.add_option( + "-d", "--debug", + action="store_true", + default=False, dest="debug", + help="Enable debug mode" + ) + + opts, args = parser.parse_args() + + return opts, args + + +class send_all_event(Event): + + def __init__(self, infos): + super(send_all_event, self).__init__(infos) + + +class NodeServer(Component): + + def init(self, args, opts): + if opts.debug: + Debugger().register(self) + + if ":" in opts.bind: + address, port = opts.bind.split(":") + port = int(port) + else: + address, port = opts.bind, 8000 + + self.node = Node(port=port, server_ip=address).register(self) + + def connect(self, sock, host, port): + print('Peer connected: %s:%d' % (host, port)) + + def disconnect(self, sock): + print('Peer disconnected: %s' % sock) + + def ready(self, server, bind): + print('Server ready: %s:%d' % bind) + Timer(3, Event.create('send_all'), persist=True).register(self) + + def send_all(self): + event = send_all_event(str(datetime.now())) + print('send: %s' % event) + self.node.server.send_all(event) + + +def main(): + opts, args = parse_options() + + # Configure and "run" the System. + NodeServer(args, opts).run() + + +if __name__ == "__main__": + main() diff -Nru circuits-3.1.0+ds1/examples/pingpong.py circuits-3.2.2/examples/pingpong.py --- circuits-3.1.0+ds1/examples/pingpong.py 1970-01-01 00:00:00.000000000 +0000 +++ circuits-3.2.2/examples/pingpong.py 2021-10-19 16:23:49.000000000 +0000 @@ -0,0 +1,75 @@ +#!/usr/bin/env python +"""Bridge Example + +A Bridge example that demonstrates bidirectional parent/child +communications and displays the no. of events per second and latency. +""" +from __future__ import print_function + +import sys +from signal import SIGINT, SIGTERM +from time import time +from traceback import format_exc + +from circuits import Component, Event, handler, ipc + + +def log(msg, *args, **kwargs): + sys.stderr.write("{0:s}{1:s}".format(msg.format(*args), kwargs.get("n", "\n"))) + sys.stderr.flush() + + +def error(e): + log("ERROR: {0:s}", e) + log(format_exc()) + + +def status(msg, *args): + log("\r\x1b[K{0:s}", msg.format(*args), n="") + + +class ping(Event): + """ping Event""" + + +class pong(Event): + """pong Event""" + + +class Child(Component): + + def ping(self, ts): + self.fire(ipc(pong(ts, time()))) + + +class App(Component): + + def init(self): + self.events = 0 + self.stime = time() + + Child().start(process=True, link=self) + + def ready(self, *args): + self.fire(ipc(ping(time()))) + + def pong(self, ts1, ts2): + latency = (ts2 - ts1) * 1000.0 + status( + "{0:d} event/s @ {1:0.2f}ms latency".format( + int(self.events / (time() - self.stime)), + latency + ) + ) + self.fire(ipc(ping(time()))) + + def signal(self, signo, stack): + if signo in [SIGINT, SIGTERM]: + raise SystemExit(0) + + @handler() + def on_event(self, *args, **kwargs): + self.events += 1 + + +App().run() diff -Nru circuits-3.1.0+ds1/examples/ping.py circuits-3.2.2/examples/ping.py --- circuits-3.1.0+ds1/examples/ping.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/examples/ping.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,6 +1,4 @@ #!/usr/bin/env python - - """Clone of the standard UNIX "ping" command. This example shows how you can utilize some of the buitlin I/O components @@ -9,13 +7,10 @@ using the ``circuits.io.Process`` Component for Asyncchronous I/O communications with the process. """ - - import sys - from circuits import Component, Debugger -from circuits.io import stdout, Process, write +from circuits.io import Process, stdout, write class Ping(Component): diff -Nru circuits-3.1.0+ds1/examples/portforward.py circuits-3.2.2/examples/portforward.py --- circuits-3.1.0+ds1/examples/portforward.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/examples/portforward.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,5 +1,4 @@ #!/usr/bin/env python - """A Port Forwarding Example This example demonstrates slightly more complex features and behaviors @@ -12,14 +11,12 @@ This example also has support for daemonizing the process into the background. """ - - -from uuid import uuid4 as uuid from optparse import OptionParser +from uuid import uuid4 as uuid +from circuits import Component, Debugger, handler from circuits.app import Daemon -from circuits import handler, Component, Debugger -from circuits.net.events import close, Connect, write +from circuits.net.events import close, connect, write from circuits.net.sockets import TCPClient, TCPServer __version__ = "0.2" @@ -187,5 +184,6 @@ system.run() + if __name__ == "__main__": main() diff -Nru circuits-3.1.0+ds1/examples/primitives/call.py circuits-3.2.2/examples/primitives/call.py --- circuits-3.1.0+ds1/examples/primitives/call.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/examples/primitives/call.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,17 +1,19 @@ #!/usr/bin/env python - from circuits import Component, Event class hello(Event): + """hello Event""" class foo(Event): + """foo Event""" class bar(Event): + """bar Event""" @@ -33,4 +35,5 @@ print("{0:d}".format(x.value)) self.stop() + App().run() diff -Nru circuits-3.1.0+ds1/examples/primitives/fire.py circuits-3.2.2/examples/primitives/fire.py --- circuits-3.1.0+ds1/examples/primitives/fire.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/examples/primitives/fire.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,17 +1,19 @@ #!/usr/bin/env python - from circuits import Component, Event class hello(Event): + """hello Event""" class foo(Event): + """foo Event""" class bar(Event): + """bar Event""" @@ -32,4 +34,5 @@ self.fire(hello()) self.stop() + App().run() diff -Nru circuits-3.1.0+ds1/examples/primitives/wait.py circuits-3.2.2/examples/primitives/wait.py --- circuits-3.1.0+ds1/examples/primitives/wait.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/examples/primitives/wait.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,17 +1,19 @@ #!/usr/bin/env python - from circuits import Component, Event class hello(Event): + """hello Event""" class foo(Event): + """foo Event""" class bar(Event): + """bar Event""" @@ -38,4 +40,5 @@ print("{0:d}".format(x.value)) self.stop() + App().run() diff -Nru circuits-3.1.0+ds1/examples/proxy.py circuits-3.2.2/examples/proxy.py --- circuits-3.1.0+ds1/examples/proxy.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/examples/proxy.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,8 +1,7 @@ #!/usr/bin/env python - from uuid import uuid4 as uuid -from circuits import Component +from circuits import Component, Debugger from circuits.net.events import close, connect, write from circuits.net.sockets import TCPClient, TCPServer @@ -63,7 +62,6 @@ app = Proxy(("0.0.0.0", 3333), "127.0.0.1", 22) -from circuits import Debugger Debugger().register(app) app.run() diff -Nru circuits-3.1.0+ds1/examples/signals.py circuits-3.2.2/examples/signals.py --- circuits-3.1.0+ds1/examples/signals.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/examples/signals.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,20 +1,16 @@ #!/usr/bin/env python - - """circuits Signal Handling A modified version of the circuits Hello World example to demonstrate how to customize signal handling and cause a delayed system terminate. """ - - from __future__ import print_function - from circuits import Component, Debugger, Event, Timer class hello(Event): + """hello Event""" diff -Nru circuits-3.1.0+ds1/examples/stompclient.py circuits-3.2.2/examples/stompclient.py --- circuits-3.1.0+ds1/examples/stompclient.py 1970-01-01 00:00:00.000000000 +0000 +++ circuits-3.2.2/examples/stompclient.py 2021-10-19 16:23:49.000000000 +0000 @@ -0,0 +1,101 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +"""Example usage for StompClient component + +Requires a STOMP server to connect to. + +""" + +import logging +import ssl + +from circuits import Component, Event, Timer +from circuits.protocols.stomp.client import ACK_AUTO, StompClient +from circuits.protocols.stomp.events import connect, send, subscribe + +LOG = logging.getLogger(__name__) + + +class QueueHandler(Component): + + def __init__(self, queue, host=None, *args, **kwargs): + super(QueueHandler, self).__init__(*args, **kwargs) + self.queue = queue + self.host = host + + def registered(self, event, component, parent): + if component.parent is self: + self.fire(Event.create("reconnect")) + + def connected(self): + """Client has connected to the STOMP server""" + LOG.info("STOMP connected.") + # Let's subscribe to the message destination + self.fire(subscribe(self.queue, ack=ACK_AUTO)) + + def subscribe_success(self, event, *args, **kwargs): + """ Subscribed to message destination """ + # Let's fire off some messages + self.fire(send(headers=None, + body="Hello World", + destination=self.queue)) + self.fire(send(headers=None, + body="Hello Again World", + destination=self.queue)) + + def heartbeat_timeout(self): + """Heartbeat timed out from the STOMP server""" + LOG.error("STOMP heartbeat timeout!") + # Set a timer to automatically reconnect + Timer(10, Event.create("Reconnect")).register(self) + + def on_stomp_error(self, headers, message, error): + """STOMP produced an error.""" + LOG.error('STOMP listener: Error:\n%s', message or error) + + def message(self, event, headers, message): + """STOMP produced a message.""" + LOG.info("Message Received: %s", message) + + def disconnected(self, event, *args, **kwargs): + # Wait a while then try to reconnect + LOG.info("We got disconnected, reconnect") + Timer(10, Event.create("reconnect")).register(self) + + def reconnect(self): + """Try (re)connect to the STOMP server""" + LOG.info("STOMP attempting to connect") + self.fire(connect(host=self.host)) + + +def main(): + logging.basicConfig() + logging.getLogger().setLevel(logging.INFO) + # Configure and run + context = ssl.create_default_context() + context.check_hostname = True + context.verify_mode = ssl.CERT_REQUIRED + + # You can create an STOMP server to test for free at https://www.cloudamqp.com/ + uri = "orangutan.rmq.cloudamqp.com" + port = 61614 + login = "xxxyyy" + passcode = "somepassword" + host = "xxxyyy" + queue = "test1" + + s = StompClient(uri, port, + username=login, + password=passcode, + heartbeats=(10000, 10000), + ssl_context=context) + + qr = QueueHandler(queue, host=host) + s.register(qr) + + qr.run() + + +if __name__ == "__main__": + main() diff -Nru circuits-3.1.0+ds1/examples/tail.py circuits-3.2.2/examples/tail.py --- circuits-3.1.0+ds1/examples/tail.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/examples/tail.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,14 +1,13 @@ #!/usr/bin/env python - """Clone of the standard UNIX "tail" command. This example shows how you can utilize some of the buitlin I/O components in circuits to write a very simple clone of the standard UNIX "tail" command. """ - import sys + from circuits import Component, Debugger -from circuits.io import stdout, File, Write +from circuits.io import File, Write, stdout class Tail(Component): @@ -38,5 +37,6 @@ self.fire(Write(data), self.stdout) + # Setup and run the system. (Tail(sys.argv[1]) + Debugger()).run() diff -Nru circuits-3.1.0+ds1/examples/telnet.py circuits-3.2.2/examples/telnet.py --- circuits-3.1.0+ds1/examples/telnet.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/examples/telnet.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,7 +1,5 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- - - """Telnet Example A basic telnet-like clone that connects to remote hosts @@ -19,21 +17,17 @@ * Event * net.sockets.TCPClient """ - - from __future__ import print_function import os from optparse import OptionParser - import circuits +from circuits import Component, handler from circuits.io import stdin -from circuits.tools import graph -from circuits import handler, Component from circuits.net.events import connect, write -from circuits.net.sockets import TCPClient, UNIXClient, UDPClient - +from circuits.net.sockets import TCPClient, UDPClient, UNIXClient +from circuits.tools import graph USAGE = "%prog [options] host [port]" VERSION = "%prog v" + circuits.__version__ @@ -43,6 +37,12 @@ parser = OptionParser(usage=USAGE, version=VERSION) parser.add_option( + "-s", "--secure", + action="store_true", default=False, dest="secure", + help="Enable secure mode" + ) + + parser.add_option( "-u", "--udp", action="store_true", default=False, dest="udp", help="Use UDP transport", @@ -98,7 +98,7 @@ print("Trying %s ..." % host) if not opts["udp"]: - self.fire(connect(*dest)) + self.fire(connect(*dest, secure=opts["secure"])) else: self.fire(write((host, port), b"\x00")) diff -Nru circuits-3.1.0+ds1/examples/testing/pytest/conftest.py circuits-3.2.2/examples/testing/pytest/conftest.py --- circuits-3.1.0+ds1/examples/testing/pytest/conftest.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/examples/testing/pytest/conftest.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,18 +1,14 @@ -# Module: conftest -# Date: 6th December 2010 -# Author: James Mills, prologic at shortcircuit dot net dot au - """py.test config""" -import pytest - import sys import threading -from time import sleep from collections import deque +from time import sleep + +import pytest +from circuits import BaseComponent, Debugger, Manager, handler from circuits.core.manager import TIMEOUT -from circuits import handler, BaseComponent, Debugger, Manager class Watcher(BaseComponent): @@ -108,9 +104,9 @@ return watcher -def pytest_namespace(): - return dict(( - ("WaitEvent", WaitEvent), - ("PLATFORM", sys.platform), - ("PYVER", sys.version_info[:3]), - )) +for key, value in dict(( + ("WaitEvent", WaitEvent), + ("PLATFORM", sys.platform), + ("PYVER", sys.version_info[:3]), +)).items(): + setattr(pytest, key, value) diff -Nru circuits-3.1.0+ds1/examples/testing/pytest/hello.py circuits-3.2.2/examples/testing/pytest/hello.py --- circuits-3.1.0+ds1/examples/testing/pytest/hello.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/examples/testing/pytest/hello.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,11 +1,11 @@ #!/usr/bin/env python - """circuits Hello World""" from circuits import Component, Event class hello(Event): + """hello Event""" diff -Nru circuits-3.1.0+ds1/examples/testing/pytest/test_hello.py circuits-3.2.2/examples/testing/pytest/test_hello.py --- circuits-3.1.0+ds1/examples/testing/pytest/test_hello.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/examples/testing/pytest/test_hello.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,8 +1,6 @@ #!/usr/bin/env python - import pytest - -from hello import Hello, App +from hello import App, hello @pytest.fixture @@ -19,7 +17,7 @@ def test(app, watcher): - x = app.fire(Hello()) + x = app.fire(hello()) assert watcher.wait("hello") assert x.value == "Hello World!" diff -Nru circuits-3.1.0+ds1/examples/timers.py circuits-3.2.2/examples/timers.py --- circuits-3.1.0+ds1/examples/timers.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/examples/timers.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,11 +1,9 @@ #!/usr/bin/env python - """Simple Timers A trivial simple example of using circuits and timers. """ - -from circuits import Event, Component, Timer +from circuits import Component, Event, Timer class App(Component): diff -Nru circuits-3.1.0+ds1/examples/web/acldemo.py circuits-3.2.2/examples/web/acldemo.py --- circuits-3.1.0+ds1/examples/web/acldemo.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/examples/web/acldemo.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,8 +1,7 @@ #!/usr/bin/env python - -from circuits import handler, Component +from circuits import Component, handler +from circuits.web import Controller, Server from circuits.web.errors import Forbidden -from circuits.web import Server, Controller class ACL(Component): @@ -19,7 +18,7 @@ match the allowed set. """ - if not request.remote.ip in self.allowed: + if request.remote.ip not in self.allowed: event.stop() return Forbidden(request, response) @@ -29,6 +28,7 @@ def index(self): return "Hello World!" + app = Server(("0.0.0.0", 8000)) ACL().register(app) Root().register(app) diff -Nru circuits-3.1.0+ds1/examples/web/authdemo.py circuits-3.2.2/examples/web/authdemo.py --- circuits-3.1.0+ds1/examples/web/authdemo.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/examples/web/authdemo.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,12 +1,9 @@ #!/usr/bin/env python - - from hashlib import md5 - -from circuits import handler, Component -from circuits.web import Server, Controller -from circuits.web.tools import check_auth, basic_auth +from circuits import Component, handler +from circuits.web import Controller, Server +from circuits.web.tools import basic_auth, check_auth class Auth(Component): @@ -33,6 +30,7 @@ def index(self): return "Hello World!" + app = Server(("0.0.0.0", 8000)) Auth().register(app) Root().register(app) diff -Nru circuits-3.1.0+ds1/examples/web/basecontrollers.py circuits-3.2.2/examples/web/basecontrollers.py --- circuits-3.1.0+ds1/examples/web/basecontrollers.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/examples/web/basecontrollers.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,7 +1,6 @@ #!/usr/bin/env python - from circuits.web import Server -from circuits.web.controllers import expose, BaseController +from circuits.web.controllers import BaseController, expose class Root(BaseController): @@ -17,6 +16,7 @@ return "Hello World!" + app = Server(("0.0.0.0", 8000)) Root().register(app) app.run() diff -Nru circuits-3.1.0+ds1/examples/web/baseservers.py circuits-3.2.2/examples/web/baseservers.py --- circuits-3.1.0+ds1/examples/web/baseservers.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/examples/web/baseservers.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,5 +1,4 @@ #!/usr/bin/env python - from circuits import Component from circuits.web import BaseServer @@ -17,6 +16,7 @@ return "Hello World!" + app = BaseServer(("0.0.0.0", 8000)) Root().register(app) app.run() diff -Nru circuits-3.1.0+ds1/examples/web/controllers.py circuits-3.2.2/examples/web/controllers.py --- circuits-3.1.0+ds1/examples/web/controllers.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/examples/web/controllers.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,6 +1,6 @@ #!/usr/bin/env python - -from circuits.web import Server, Controller, Static +from circuits import Debugger +from circuits.web import Controller, Server, Static class Root(Controller): @@ -15,8 +15,8 @@ return "Hello World!" + app = Server(("0.0.0.0", 9000)) -from circuits import Debugger Debugger().register(app) Static().register(app) Root().register(app) diff -Nru circuits-3.1.0+ds1/examples/web/crud.py circuits-3.2.2/examples/web/crud.py --- circuits-3.1.0+ds1/examples/web/crud.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/examples/web/crud.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,6 +1,5 @@ #!/usr/bin/env python - -from circuits.web import Server, Controller, Logger +from circuits.web import Controller, Logger, Server class Root(Controller): diff -Nru circuits-3.1.0+ds1/examples/web/fileupload.py circuits-3.2.2/examples/web/fileupload.py --- circuits-3.1.0+ds1/examples/web/fileupload.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/examples/web/fileupload.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,12 +1,9 @@ #!/usr/bin/env python - """File Upload A simple example showing how to access an uploaded file. """ - - -from circuits.web import Server, Controller +from circuits.web import Controller, Server UPLOAD_FORM = """ diff -Nru circuits-3.1.0+ds1/examples/web/filtering.py circuits-3.2.2/examples/web/filtering.py --- circuits-3.1.0+ds1/examples/web/filtering.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/examples/web/filtering.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,20 +1,18 @@ #!/usr/bin/env python - """Filtering A simple example showing how to intercept and potentially filter requests. This example demonstrates how you could intercept the response before it goes out changing the response's content into ALL UPPER CASE! """ - -from circuits import handler, Component -from circuits.web import Server, Controller +from circuits import Component, handler +from circuits.web import Controller, Server class Upper(Component): channel = "web" # By default all web related events - # go to the "web" channel. + # go to the "web" channel. @handler("response", priority=1.0) def _on_response(self, response): @@ -42,6 +40,7 @@ return "Hello World!" + app = Server(("0.0.0.0", 8000)) Upper().register(app) Root().register(app) diff -Nru circuits-3.1.0+ds1/examples/web/forms.py circuits-3.2.2/examples/web/forms.py --- circuits-3.1.0+ds1/examples/web/forms.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/examples/web/forms.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,11 +1,9 @@ #!/usr/bin/env python - """Forms A simple example showing how to deal with data forms. """ - -from circuits.web import Server, Controller +from circuits.web import Controller, Server FORM = """ diff -Nru circuits-3.1.0+ds1/examples/web/httpauth.py circuits-3.2.2/examples/web/httpauth.py --- circuits-3.1.0+ds1/examples/web/httpauth.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/examples/web/httpauth.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,7 +1,6 @@ #!/usr/bin/env python - -from circuits.web import Server, Controller -from circuits.web.tools import check_auth, basic_auth +from circuits.web import Controller, Server +from circuits.web.tools import basic_auth, check_auth class Root(Controller): @@ -16,6 +15,7 @@ return basic_auth(self.request, self.response, realm, users, encrypt) + app = Server(("0.0.0.0", 8000)) Root().register(app) app.run() diff -Nru circuits-3.1.0+ds1/examples/web/jsoncontroller.py circuits-3.2.2/examples/web/jsoncontroller.py --- circuits-3.1.0+ds1/examples/web/jsoncontroller.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/examples/web/jsoncontroller.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,6 +1,5 @@ #!/usr/bin/env python - -from circuits.web import Server, JSONController +from circuits.web import JSONController, Server class Root(JSONController): @@ -8,6 +7,7 @@ def index(self): return {"success": True, "message": "Hello World!"} + app = Server(("0.0.0.0", 8000)) Root().register(app) app.run() diff -Nru circuits-3.1.0+ds1/examples/web/jsonrpc.py circuits-3.2.2/examples/web/jsonrpc.py --- circuits-3.1.0+ds1/examples/web/jsonrpc.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/examples/web/jsonrpc.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,7 +1,6 @@ #!/usr/bin/env python - from circuits import Component -from circuits.web import Server, Logger, JSONRPC +from circuits.web import JSONRPC, Logger, Server class Test(Component): @@ -9,6 +8,7 @@ def foo(self, a, b, c): return a, b, c + app = Server(("0.0.0.0", 8000)) Logger().register(app) JSONRPC().register(app) diff -Nru circuits-3.1.0+ds1/examples/web/jsonserializer.py circuits-3.2.2/examples/web/jsonserializer.py --- circuits-3.1.0+ds1/examples/web/jsonserializer.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/examples/web/jsonserializer.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,16 +1,16 @@ #!/usr/bin/env python - from json import dumps -from circuits import handler, Component -from circuits.web import Server, Controller, Logger +from circuits import Component, handler +from circuits.web import Controller, Logger, Server class JSONSerializer(Component): channel = "web" - @handler("response", priority=1.0) # 1 higher than the default response handler + # 1 higher than the default response handler + @handler("response", priority=1.0) def serialize_response_body(self, response): response.headers["Content-Type"] = "application/json" response.body = dumps(response.body) @@ -21,6 +21,7 @@ def index(self): return {"message": "Hello World!"} + app = Server(("0.0.0.0", 9000)) JSONSerializer().register(app) Logger().register(app) diff -Nru circuits-3.1.0+ds1/examples/web/jsontool.py circuits-3.2.2/examples/web/jsontool.py --- circuits-3.1.0+ds1/examples/web/jsontool.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/examples/web/jsontool.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,8 +1,7 @@ #!/usr/bin/env python - from json import dumps -from circuits.web import Server, Controller +from circuits.web import Controller, Server def json(f): @@ -17,6 +16,7 @@ def getrange(self, limit=4): return list(range(int(limit))) + app = Server(("0.0.0.0", 8000)) Root().register(app) app.run() diff -Nru circuits-3.1.0+ds1/examples/web/makotemplates.py circuits-3.2.2/examples/web/makotemplates.py --- circuits-3.1.0+ds1/examples/web/makotemplates.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/examples/web/makotemplates.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,11 +1,10 @@ #!/usr/bin/env python - import os import mako from mako.lookup import TemplateLookup -from circuits.web import Server, Controller, Static +from circuits.web import Controller, Server, Static DEFAULTS = {} @@ -21,7 +20,7 @@ d.update(DEFAULTS) tpl = templates.get_template(name) return tpl.render(**d) - except: + except Exception: return mako.exceptions.html_error_template().render() @@ -36,6 +35,7 @@ msg = "Thank you %s %s" % (firstName, lastName) return render(self.tpl, message=msg) + app = Server(("0.0.0.0", 8000)) Static().register(app) Root().register(app) diff -Nru circuits-3.1.0+ds1/examples/web/sessions.py circuits-3.2.2/examples/web/sessions.py --- circuits-3.1.0+ds1/examples/web/sessions.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/examples/web/sessions.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,6 +1,5 @@ #!/usr/bin/env python - -from circuits.web import Server, Controller, Sessions +from circuits.web import Controller, Server, Sessions class Root(Controller): @@ -11,6 +10,7 @@ self.session["name"] = name return "Hello %s!" % name + app = Server(("0.0.0.0", 8000)) Sessions().register(app) Root().register(app) diff -Nru circuits-3.1.0+ds1/examples/web/shadowauth.py circuits-3.2.2/examples/web/shadowauth.py --- circuits-3.1.0+ds1/examples/web/shadowauth.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/examples/web/shadowauth.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,19 +1,17 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- - """Shadow Auth Demo An example of a Circuits Component that requires users authenticate against /etc/passwd or /etc/shadow before letting them into the web site. """ - -from os import path from crypt import crypt -from socket import gethostname +from os import path from re import compile as compile_regex +from socket import gethostname -from circuits import handler, Component -from circuits.web import _httpauth, Server, Controller +from circuits import Component, handler +from circuits.web import Controller, Server, _httpauth from circuits.web.errors import HTTPError, Unauthorized @@ -63,6 +61,7 @@ def index(self): return "Hello, {0:s}".format(self.request.login) + app = Server(("0.0.0.0", 8000)) PasswdAuth().register(app) Root().register(app) diff -Nru circuits-3.1.0+ds1/examples/web/singleclickandrun.py circuits-3.2.2/examples/web/singleclickandrun.py --- circuits-3.1.0+ds1/examples/web/singleclickandrun.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/examples/web/singleclickandrun.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,8 +1,8 @@ #!/usr/bin/env python - import webbrowser -from circuits.web import Server, Controller +from circuits.web import Controller, Server + HTML = """\ @@ -27,6 +27,7 @@ def exit(self): raise SystemExit(0) + app = Server(("0.0.0.0", 8000)) Root().register(app) app.start() diff -Nru circuits-3.1.0+ds1/examples/web/ssl-forward-cert.py circuits-3.2.2/examples/web/ssl-forward-cert.py --- circuits-3.1.0+ds1/examples/web/ssl-forward-cert.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/examples/web/ssl-forward-cert.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,9 +1,8 @@ #!/usr/bin/env python - # stdlib import ssl -from circuits.web import Server, Controller +from circuits.web import Controller, Server class Root(Controller): diff -Nru circuits-3.1.0+ds1/examples/web/sslserver.py circuits-3.2.2/examples/web/sslserver.py --- circuits-3.1.0+ds1/examples/web/sslserver.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/examples/web/sslserver.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,6 +1,6 @@ #!/usr/bin/env python - -from circuits.web import Server, Controller +from circuits import Debugger +from circuits.web import Controller, Server class Root(Controller): @@ -10,5 +10,6 @@ app = Server(("0.0.0.0", 8443), secure=True, certfile="cert.pem") +Debugger().register(app) Root().register(app) app.run() diff -Nru circuits-3.1.0+ds1/examples/web/terminal/terminal.py circuits-3.2.2/examples/web/terminal/terminal.py --- circuits-3.1.0+ds1/examples/web/terminal/terminal.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/examples/web/terminal/terminal.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,27 +1,27 @@ #!/usr/bin/env python - - import os import signal from StringIO import StringIO -from subprocess import Popen, PIPE +from subprocess import PIPE, Popen +from circuits import Component, Debugger, Event, handler from circuits.io import File -from circuits.tools import inspect from circuits.net.events import write +from circuits.tools import inspect +from circuits.web import Controller, Logger, Server, Sessions, Static from circuits.web.events import stream -from circuits import handler, Event, Component -from circuits.web import Server, Controller, Logger, Static, Sessions BUFFERING = 1 STREAMING = 2 class kill(Event): + """kill Event""" class input(Event): + """input Event""" @@ -127,8 +127,6 @@ return self.response -from circuits import Debugger - app = Server(("0.0.0.0", 8000)) Debugger().register(app) Static("/js", docroot="static/js").register(app) diff -Nru circuits-3.1.0+ds1/examples/web/virtualhosts.py circuits-3.2.2/examples/web/virtualhosts.py --- circuits-3.1.0+ds1/examples/web/virtualhosts.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/examples/web/virtualhosts.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,6 +1,5 @@ #!/usr/bin/env python - -from circuits.web import Server, Controller +from circuits.web import Controller, Server from circuits.web.dispatchers import VirtualHosts @@ -25,11 +24,13 @@ def index(self): return "I am bar." + domains = { "foo.localdomain:8000": "foo", "bar.localdomain:8000": "bar", } + app = Server(("0.0.0.0", 8000)) VirtualHosts(domains).register(app) Root().register(app) diff -Nru circuits-3.1.0+ds1/examples/web/websockets.py circuits-3.2.2/examples/web/websockets.py --- circuits-3.1.0+ds1/examples/web/websockets.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/examples/web/websockets.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,9 +1,8 @@ #!/usr/bin/env python - -from circuits.net.events import write from circuits import Component, Debugger -from circuits.web.dispatchers import WebSocketsDispatcher +from circuits.net.events import write from circuits.web import Controller, Logger, Server, Static +from circuits.web.dispatchers import WebSocketsDispatcher class Echo(Component): @@ -19,6 +18,7 @@ def index(self): return "Hello World!" + app = Server(("0.0.0.0", 8000)) Debugger().register(app) Static().register(app) diff -Nru circuits-3.1.0+ds1/examples/web/wiki/defaultpages/FrontPage circuits-3.2.2/examples/web/wiki/defaultpages/FrontPage --- circuits-3.1.0+ds1/examples/web/wiki/defaultpages/FrontPage 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/examples/web/wiki/defaultpages/FrontPage 2021-10-19 16:23:49.000000000 +0000 @@ -21,7 +21,7 @@ THe entire source code to this wiki can be found on the [[http://circuitsframework.com/|circuits]] project home page -here: http://bitbucket.org/circuits/circuits/src/tip/examples/web/wiki/ +here: https://github.com/circuits/circuits/tree/master/examples/web/wiki/ Try the [[SandBox]] :) diff -Nru circuits-3.1.0+ds1/examples/web/wiki/Dockerfile circuits-3.2.2/examples/web/wiki/Dockerfile --- circuits-3.1.0+ds1/examples/web/wiki/Dockerfile 1970-01-01 00:00:00.000000000 +0000 +++ circuits-3.2.2/examples/web/wiki/Dockerfile 2021-10-19 16:23:49.000000000 +0000 @@ -0,0 +1,6 @@ +FROM crux/python:onbuild + +EXPOSE 9000 + +ENTRYPOINT ["./wiki.py"] +CMD [] diff -Nru circuits-3.1.0+ds1/examples/web/wiki/.gitignore circuits-3.2.2/examples/web/wiki/.gitignore --- circuits-3.1.0+ds1/examples/web/wiki/.gitignore 1970-01-01 00:00:00.000000000 +0000 +++ circuits-3.2.2/examples/web/wiki/.gitignore 2021-10-19 16:23:49.000000000 +0000 @@ -0,0 +1 @@ +wiki.db diff -Nru circuits-3.1.0+ds1/examples/web/wiki/macros/html.py circuits-3.2.2/examples/web/wiki/macros/html.py --- circuits-3.1.0+ds1/examples/web/wiki/macros/html.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/examples/web/wiki/macros/html.py 2021-10-19 16:23:49.000000000 +0000 @@ -2,12 +2,11 @@ Macros for generating snippets of HTML. """ - import genshi import pygments -import pygments.util -import pygments.lexers import pygments.formatters +import pygments.lexers +import pygments.util from genshi import builder from genshi.filters import HTMLSanitizer diff -Nru circuits-3.1.0+ds1/examples/web/wiki/macros/include.py circuits-3.2.2/examples/web/wiki/macros/include.py --- circuits-3.1.0+ds1/examples/web/wiki/macros/include.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/examples/web/wiki/macros/include.py 2021-10-19 16:23:49.000000000 +0000 @@ -2,7 +2,6 @@ Macros for inclusion of other wiki pages """ - from genshi import builder @@ -51,5 +50,5 @@ environ["page.name"] = pagename return builder.tag.pre(environ["parser"].render( - page, environ=environ).decode("utf-8") + page, environ=environ).decode("utf-8") ) diff -Nru circuits-3.1.0+ds1/examples/web/wiki/macros/__init__.py circuits-3.2.2/examples/web/wiki/macros/__init__.py --- circuits-3.1.0+ds1/examples/web/wiki/macros/__init__.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/examples/web/wiki/macros/__init__.py 2021-10-19 16:23:49.000000000 +0000 @@ -2,7 +2,6 @@ Macro support and dispatcher """ - import os from inspect import getmembers, getmodule, isfunction @@ -26,7 +25,7 @@ args, kwargs = parse_args(arg_string) try: return environ["macros"][name](macro, environ, *args, **kwargs) - except Exception, e: + except Exception as e: return "ERROR: Error while executing macro %r (%s)" % (name, e) else: return "Macro not found!" @@ -34,7 +33,9 @@ def loadMacros(): path = os.path.abspath(os.path.dirname(__file__)) - p = lambda x: os.path.splitext(x)[1] == ".py" + + def p(x): + os.path.splitext(x)[1] == ".py" modules = [x for x in os.listdir(path) if p(x) and not x == "__init__.py"] macros = {} @@ -45,7 +46,8 @@ moduleName = "%s.%s" % (__package__, name) m = __import__(moduleName, globals(), locals(), __package__) - p = lambda x: isfunction(x) and getmodule(x) is m + def p(x): + isfunction(x) and getmodule(x) is m for name, function in getmembers(m, p): name = name.replace("_", "-") try: diff -Nru circuits-3.1.0+ds1/examples/web/wiki/macros/utils.py circuits-3.2.2/examples/web/wiki/macros/utils.py --- circuits-3.1.0+ds1/examples/web/wiki/macros/utils.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/examples/web/wiki/macros/utils.py 2021-10-19 16:23:49.000000000 +0000 @@ -2,7 +2,6 @@ Utility macros """ - from inspect import getdoc diff -Nru circuits-3.1.0+ds1/examples/web/wiki/requirements.txt circuits-3.2.2/examples/web/wiki/requirements.txt --- circuits-3.1.0+ds1/examples/web/wiki/requirements.txt 1970-01-01 00:00:00.000000000 +0000 +++ circuits-3.2.2/examples/web/wiki/requirements.txt 2021-10-19 16:23:49.000000000 +0000 @@ -0,0 +1,3 @@ +circuits +pygments +creoleparser diff -Nru circuits-3.1.0+ds1/examples/web/wiki/setup.py circuits-3.2.2/examples/web/wiki/setup.py --- circuits-3.1.0+ds1/examples/web/wiki/setup.py 1970-01-01 00:00:00.000000000 +0000 +++ circuits-3.2.2/examples/web/wiki/setup.py 2021-10-19 16:23:49.000000000 +0000 @@ -0,0 +1,21 @@ +#!/usr/bin/env python +from setuptools import setup + + +def parse_requirements(filename): + with open(filename, "r") as f: + for line in f: + if line and line[0] != "#": + yield line.strip() + + +setup( + name="wiki", + version="dev", + description="circuits wiki demo", + scripts=( + "wiki.py", + ), + install_requires=list(parse_requirements("requirements.txt")), + zip_safe=True +) diff -Nru circuits-3.1.0+ds1/examples/web/wiki/wiki.py circuits-3.2.2/examples/web/wiki/wiki.py --- circuits-3.1.0+ds1/examples/web/wiki/wiki.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/examples/web/wiki/wiki.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,14 +1,12 @@ #!/usr/bin/env python - import os import sqlite3 -from creoleparser import create_dialect, creole11_base, Parser +import macros +from creoleparser import Parser, create_dialect, creole11_base import circuits -from circuits.web import Server, Controller, Logger, Static - -import macros +from circuits.web import Controller, Logger, Server, Static text2html = Parser( create_dialect(creole11_base, macro_func=macros.dispatcher), @@ -83,6 +81,7 @@ self.db.save(name, form.get("text", "")) return self.redirect(name) + app = Server(("0.0.0.0", 9000)) Static(docroot="static").register(app) Root().register(app) Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/examples/web/wiki.zip and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/examples/web/wiki.zip differ diff -Nru circuits-3.1.0+ds1/examples/web/wsgiapp.py circuits-3.2.2/examples/web/wsgiapp.py --- circuits-3.1.0+ds1/examples/web/wsgiapp.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/examples/web/wsgiapp.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,5 +1,4 @@ #!/usr/bin/env python - from circuits.web import Controller from circuits.web.wsgi import Application @@ -9,5 +8,6 @@ def index(self): return "Hello World!" + application = Application() Root().register(application) diff -Nru circuits-3.1.0+ds1/examples/web/wsgi.py circuits-3.2.2/examples/web/wsgi.py --- circuits-3.1.0+ds1/examples/web/wsgi.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/examples/web/wsgi.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,7 +1,6 @@ #!/usr/bin/env python - -from circuits.web.wsgi import Gateway from circuits.web import Controller, Server +from circuits.web.wsgi import Gateway def foo(environ, start_response): @@ -10,6 +9,7 @@ class Root(Controller): + """App Rot""" def index(self): diff -Nru circuits-3.1.0+ds1/examples/web/xmlrpc_demo.py circuits-3.2.2/examples/web/xmlrpc_demo.py --- circuits-3.1.0+ds1/examples/web/xmlrpc_demo.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/examples/web/xmlrpc_demo.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,7 +1,6 @@ #!/usr/bin/env python - from circuits import Component -from circuits.web import Server, Logger, XMLRPC +from circuits.web import XMLRPC, Logger, Server class Test(Component): @@ -9,6 +8,7 @@ def foo(self, a, b, c): return a, b, c + app = Server(("0.0.0.0", 8000)) Logger().register(app) XMLRPC().register(app) diff -Nru circuits-3.1.0+ds1/examples/wget.py circuits-3.2.2/examples/wget.py --- circuits-3.1.0+ds1/examples/wget.py 2014-09-24 09:45:15.000000000 +0000 +++ circuits-3.2.2/examples/wget.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,19 +1,14 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- - - """wget Example A basic wget-like clone that asynchronously connections a remote web server requesting a given resource. """ - - from __future__ import print_function import sys - from circuits import Component from circuits.web.client import Client, request diff -Nru circuits-3.1.0+ds1/fabfile/docker.py circuits-3.2.2/fabfile/docker.py --- circuits-3.1.0+ds1/fabfile/docker.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/fabfile/docker.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,17 +1,10 @@ -# Module: docker -# Date: 24th May 2014 -# Author: James Mills, j dot mills at griffith dot edu dot au - - """Docker Tasks""" from fabric.api import local, task - from .utils import msg, requires, tobool - TAG = "prologic/circuits" diff -Nru circuits-3.1.0+ds1/fabfile/docs.py circuits-3.2.2/fabfile/docs.py --- circuits-3.1.0+ds1/fabfile/docs.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/fabfile/docs.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,14 +1,9 @@ -# Module: docs -# Date: 03rd April 2013 -# Author: James Mills, j dot mills at griffith dot edu dot au - """Documentation Tasks""" from fabric.api import lcd, local, task from .utils import pip, requires - PACKAGE = "circuits" @@ -18,7 +13,8 @@ if PACKAGE is not None: pip(requirements="docs/requirements.txt") - local("sphinx-apidoc -f -e -T -o docs/source/api {0:s}".format(PACKAGE)) + local( + "sphinx-apidoc -f -e -T -o docs/source/api {0:s}".format(PACKAGE)) @task() diff -Nru circuits-3.1.0+ds1/fabfile/help.py circuits-3.2.2/fabfile/help.py --- circuits-3.1.0+ds1/fabfile/help.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/fabfile/help.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,17 +1,12 @@ -# Module: help -# Date: 28th November 2013 -# Author: James Mills, j dot mills at griffith dot edu dot au - """Help Tasks""" from __future__ import print_function - from fabric import state from fabric.api import task -from fabric.tasks import Task from fabric.task_utils import crawl +from fabric.tasks import Task @task(default=True) @@ -41,7 +36,7 @@ print() print(doc) else: - print("No help available for {0;s}".format(name)) + print("No help available for {0:s}".format(name)) else: print("No such task {0:s}".format(name)) print("For a list of tasks type: fab -l") diff -Nru circuits-3.1.0+ds1/fabfile/__init__.py circuits-3.2.2/fabfile/__init__.py --- circuits-3.1.0+ds1/fabfile/__init__.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/fabfile/__init__.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,8 +1,3 @@ -# Package: fabfile -# Date: 18th June 2013 -# Author: James Mills, j dot mills at griffith dot edu dot au - - """Development Task""" @@ -10,17 +5,14 @@ from os import getcwd - +import docker # noqa +import docs # noqa +import help # noqa from fabric.api import ( - abort, cd, execute, hide, hosts, - local, prefix, prompt, run, settings, task + abort, cd, execute, hide, hosts, local, prefix, prompt, run, settings, + task, ) - -import help # noqa -import docs # noqa -import docker # noqa - from .utils import msg, pip, requires, tobool @@ -83,10 +75,6 @@ with msg("Creating env"): run("mkvirtualenv test") - with msg("Bootstrapping"): - with prefix("workon test"): - run("./bootstrap.sh") - with msg("Building"): with prefix("workon test"): run("fab develop") @@ -107,32 +95,9 @@ print("Release version: {0:s}".format(version)) if prompt("Is this ok?", default="Y", validate=r"^[YyNn]?$") in "yY": - run("hg tag {0:s}".format(version)) - run("python setup.py egg_info sdist bdist_egg register upload") + run("git tag {0:s}".format(version)) + run("python setup.py egg_info sdist bdist_egg bdist_wheel register upload") run("python setup.py build_sphinx upload_sphinx") with msg("Destroying env"): run("rmvirtualenv test") - - -@task() -def sync(*args): - """Synchronouse Local Repository with Remote(s)""" - - status = local("hg status", capture=True) - if status: - abort( - ( - "Repository is not in a clean state! " - "Please commit, revert or shelve!" - ) - ) - - with settings(warn_only=True): - local("hg pull --update") - local("hg pull --update github") - local("hg pull --update upstream") - local("hg bookmark -r tip master") - local("hg push") - local("hg push github") - local("hg push upstream") diff -Nru circuits-3.1.0+ds1/fabfile/utils.py circuits-3.2.2/fabfile/utils.py --- circuits-3.1.0+ds1/fabfile/utils.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/fabfile/utils.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,15 +1,9 @@ -# Module: utils -# Date: 03rd April 2013 -# Author: James Mills, j dot mills at griffith dot edu dot au - - """Utilities""" +from contextlib import contextmanager from functools import wraps from imp import find_module -from contextlib import contextmanager - from fabric.api import abort, hide, local, puts, quiet, settings, warn diff -Nru circuits-3.1.0+ds1/.github/ISSUE_TEMPLATE.md circuits-3.2.2/.github/ISSUE_TEMPLATE.md --- circuits-3.1.0+ds1/.github/ISSUE_TEMPLATE.md 1970-01-01 00:00:00.000000000 +0000 +++ circuits-3.2.2/.github/ISSUE_TEMPLATE.md 2021-10-19 16:23:49.000000000 +0000 @@ -0,0 +1,19 @@ +### Expected Behaviour + +Please clearly describe the problem you are having and expected behaviour +you believe you should be expecting. + +### Steps to reproduce + +Please ideally provide a minimal viable reproducible example in code of the +problem that we can clearly run and observe the broken behaviour or missing +feature. If not please describe in as much clear detail how we can reproduce +the problem ourselves. + +### Environment and Platform + +- OS: Linux, Windows or BSD / OS X +- Python: 2.7, 3.5, PyPy +- circuits: 3.2? Something older? + +---- diff -Nru circuits-3.1.0+ds1/.github/PULL_REQUEST_TEMPLATE circuits-3.2.2/.github/PULL_REQUEST_TEMPLATE --- circuits-3.1.0+ds1/.github/PULL_REQUEST_TEMPLATE 1970-01-01 00:00:00.000000000 +0000 +++ circuits-3.2.2/.github/PULL_REQUEST_TEMPLATE 2021-10-19 16:23:49.000000000 +0000 @@ -0,0 +1,4 @@ +Please describe what this pull request implements, improves or fixes. +Please be clear and concise but terse. We can read the code :) + +Fixes # diff -Nru circuits-3.1.0+ds1/.github/workflows/python-app.yml circuits-3.2.2/.github/workflows/python-app.yml --- circuits-3.1.0+ds1/.github/workflows/python-app.yml 1970-01-01 00:00:00.000000000 +0000 +++ circuits-3.2.2/.github/workflows/python-app.yml 2021-10-19 16:23:49.000000000 +0000 @@ -0,0 +1,64 @@ +# This workflow will install Python dependencies, run tests and lint with a single version of Python +# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions + +name: circuits + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + build: + + runs-on: ubuntu-latest # ubuntu-18.04 # ubuntu-latest doesn't work with 3.4 + + strategy: + fail-fast: false + matrix: + python-version: + - '2.7' + # - '3.4' FIXME: does not work :-( + - '3.5' + - '3.6' + - '3.7' + - '3.8' + - '3.9' + - '3.10-dev' + # - 'pypy2' # FIXME: flaky + # - 'pypy3' # FIXME: flaky + + steps: + - uses: actions/checkout@v2 + - name: Set up Python + uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python-version }} + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install -U isort flake8 pytest + pip install setuptools-scm==5.0.2 # || pip install setuptools-scm==3.5.0 # Python 2.7, 3.4, 3.5 support + if [ -f requirements.txt ]; then pip install -r requirements.txt; fi + - name: Lint with flake8 + run: | + # stop the build if there are Python syntax errors or undefined names + flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics + # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide + flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics + #with: + # python-version: '3.6' + - name: Lint with isort + run: | + isort . --check --diff || true + continue-on-error: true + #with: + # python-version: '3.6' + - name: Install test requirements + run: | + pip install -Ur requirements-test.txt + pip install -Ue . + - name: Test with pytest + run: | + tox -e py -- --tb=native -vvv -l --cov --no-cov-on-fail --cov-report= diff -Nru circuits-3.1.0+ds1/.gitignore circuits-3.2.2/.gitignore --- circuits-3.1.0+ds1/.gitignore 1970-01-01 00:00:00.000000000 +0000 +++ circuits-3.2.2/.gitignore 2021-10-19 16:23:49.000000000 +0000 @@ -0,0 +1,19 @@ +*~ +tmp +.git +.tox +.env +dist +.eggs +*.pyc +*.pyo +*.bak +*.xml +*.sw? +build +.cache +coverage +.coverage* +docs/build +*.egg-info +*/version.py diff -Nru circuits-3.1.0+ds1/LICENSE circuits-3.2.2/LICENSE --- circuits-3.1.0+ds1/LICENSE 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/LICENSE 2021-10-19 16:23:49.000000000 +0000 @@ -1,4 +1,4 @@ -Copyright (C) 2004-2013 James Mills +Copyright (C) 2004-2016 James Mills Circuits is covered by the MIT license:: diff -Nru circuits-3.1.0+ds1/Makefile circuits-3.2.2/Makefile --- circuits-3.1.0+ds1/Makefile 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/Makefile 1970-01-01 00:00:00.000000000 +0000 @@ -1,36 +0,0 @@ -.PHONY: help clean docs graph packages tests - -help: - @echo "Please use \`make ' where is one of" - @echo " clean to cleanup build and temporary files" - @echo " docs to build the documentation" - @echo " graph to generate dependency graph" - @echo " packages to build python source and egg packages" - @echo " tests to run the test suite" - -clean: - @rm -rf build dist circuits.egg-info - @rm -rf .coverage coverage - @rm -rf docs/build - @find . -name '__pycache__' -exec rm -rf {} + - @find . -name '*.pyc' -delete - @find . -name '*.pyo' -delete - @find . -name '*~' -delete - @rm -f *.xml - -docs: - @make -C docs html - -graph: - @sfood circuits -i -I tests -d -u 2> /dev/null | sfood-graph | dot -Tps | ps2pdf - > circuits.pdf - -release: - @python2.6 setup.py clean bdist_egg upload - @python2.7 setup.py clean bdist_egg upload - @python3.2 setup.py clean bdist_egg upload - @python3.3 setup.py clean bdist_egg upload - @python setup.py clean build_sphinx upload_sphinx - @python setup.py clean sdist --formats=bztar,gztar,zip upload - -tests: - @python -m tests.main diff -Nru circuits-3.1.0+ds1/man/circuits.bench.1 circuits-3.2.2/man/circuits.bench.1 --- circuits-3.1.0+ds1/man/circuits.bench.1 1970-01-01 00:00:00.000000000 +0000 +++ circuits-3.2.2/man/circuits.bench.1 2021-10-19 16:23:49.000000000 +0000 @@ -0,0 +1,58 @@ +.TH circuits.bench 1 "Jun 2011" "circuits 2.0.2" "User Commands" +.SH NAME +circuits.bench \- simple benchmaking of the circuits library +.SH SYNOPSIS +.B circuits.bench +[\fIoptions\fR] +.SH DESCRIPTION +circuits.bench does some simple benchmaking of the circuits library. +.SH OPTIONS +.TP +\fB-b\fR \fIaddress:[port]\fR +Bind to address:[port] (UDP) to test remote events. Default address is 0.0.0.0. +.TP +\fB-c\fR \fIinteger\fR +Set concurrency level to \fIinteger\fR. Default is 1. +.TP +\fB-d\fR +Enable debug mode. +.TP +\fB-e\fR \fInumber\fR +Stop after specified \fInumber\fR of events. Default is 0. +.TP +\fB-f\fR \fInumber\fR +\fInumber\fR of dummy events to fill queue with. Default is 0. +.TP +\fB-l\fR +Listen on 0.0.0.0:8000 (UDP) to test remote events. +.TP +\fB-m\fR \fImode\fR +Set operation mode. \fImode\fR can be \fIlatency\fR, \fIspeed\fR or \fIsync\fR. +Default \fImode\fR is \fIspeed\fR. +.TP +\fB-o\fR \fIformat\fR +Specify output format. +For example \fIformat\fR can be:"cicuits.bench: events:%s, speed:%s, time:%s" +.TP +\fB-p\fR +Enable execution profiling support. +.TP +\fB-q\fR +Suppress output. +.TP +\fB-s\fR +Enable psyco (circuits on speed!) if it is available. +.TP +\fB-t\fR \fIseconds\fR +Stop after specified elapsed \fIseconds\fR. +.TP +\fB-w\fR +Wait for remote nodes to connect. +.TP +\fB--version\fR +Output version information and exit. +.SH AUTHOR +James Mills +.PP +This manual page was written by Daniele Tricoli , for the +Debian project (but may be used by others). diff -Nru circuits-3.1.0+ds1/man/circuits.web.1 circuits-3.2.2/man/circuits.web.1 --- circuits-3.1.0+ds1/man/circuits.web.1 1970-01-01 00:00:00.000000000 +0000 +++ circuits-3.2.2/man/circuits.web.1 2021-10-19 16:23:49.000000000 +0000 @@ -0,0 +1,44 @@ +.TH circuits.web 1 "Jun 2011" "circuits 2.0.2" "User Commands" +.SH NAME +circuits.web \- Web Server and testing tool +.SH SYNOPSIS +.B circuits.web +[\fIoptions\fR] [\fIdocroot\fR] +.SH DESCRIPTION +circuits.web is a component based, event-driven light weight and high +performance HTTP/WSGI framework. circuits.web applications are stand-alone +applications with a high performance, multi-process web server with great +concurrent scalability with full support for WSGI and deployment with other web +servers. +.SH OPTIONS +.TP +\fB-b\fR \fIaddress:[port]\fR +Bind to address:[port]. Default address is 0.0.0.0:8000. +.TP +\fB-d\fR +Enable debug mode. +.TP +\fB-j\fR +Use python JIT (psyco) if it is available. +.TP +\fB-m\fR \fInumber\fR +Specify \fInumber\fR of processes to start (multiprocessing). +.TP +\fB-p\fR +Enable execution profiling support. +.TP +\fB-s\fR \fIserver\fR +Specify server to use. +.TP +\fB-t\fR \fItype\fR +Specify type of poller to use. \fItype\fR can be \fIepoll\fR, \fIpoll\fR or +\fIselect\fR. +Default \fItype\fR is \fIselect\fR. +.TP +\fB-v\fR +Enable WSGI validation mode. +.SH AUTHOR +James Mills +.PP +This manual page was written by Daniele Tricoli , for the +Debian project (but may be used by others). diff -Nru circuits-3.1.0+ds1/MANIFEST.in circuits-3.2.2/MANIFEST.in --- circuits-3.1.0+ds1/MANIFEST.in 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/MANIFEST.in 2021-10-19 16:23:49.000000000 +0000 @@ -1,4 +1,12 @@ -recursive-include docs * +recursive-include man * recursive-include tests * -recursive-include examples * -include LICENSE Makefile *.rst *.txt *.ini + +include LICENSE README.rst CHANGES.rst + +prune docs +prune fabfile +prune examples +prune setup.cfg + +global-exclude __pycache__ +global-exclude *.py[co] diff -Nru circuits-3.1.0+ds1/PKG-INFO circuits-3.2.2/PKG-INFO --- circuits-3.1.0+ds1/PKG-INFO 2014-10-31 23:13:40.000000000 +0000 +++ circuits-3.2.2/PKG-INFO 1970-01-01 00:00:00.000000000 +0000 @@ -1,297 +0,0 @@ -Metadata-Version: 1.1 -Name: circuits -Version: 3.1.0 -Summary: Asynchronous Component based Event Application Framework -Home-page: http://circuitsframework.com/ -Author: James Mills -Author-email: prologic@shortcircuit.net.au -License: MIT -Download-URL: http://bitbucket.org/circuits/circuits/downloads/ -Description: .. _Python Programming Language: http://www.python.org/ - .. _#circuits IRC Channel: http://webchat.freenode.net/?randomnick=1&channels=circuits&uio=d4 - .. _FreeNode IRC Network: http://freenode.net - .. _Python Standard Library: http://docs.python.org/library/ - .. _MIT License: http://www.opensource.org/licenses/mit-license.php - .. _Create an Issue: https://bitbucket.org/circuits/circuits/issue/new - .. _Mailing List: http://groups.google.com/group/circuits-users - .. _Project Website: http://circuitsframework.com/ - .. _PyPi Page: http://pypi.python.org/pypi/circuits - .. _Read the Docs: http://circuits.readthedocs.org/en/latest/ - .. _View the ChangeLog: http://circuits.readthedocs.org/en/latest/changes.html - .. _Downloads Page: https://bitbucket.org/circuits/circuits/downloads - - - circuits is a **Lightweight** **Event** driven and **Asynchronous** - **Application Framework** for the `Python Programming Language`_ - with a strong **Component** Architecture. - - circuits also includes a lightweight, high performance and scalable - HTTP/WSGI compliant web server as well as various I/O and Networking - components. - - - Visit the `Project Website`_ - - `Read the Docs`_ - - Download it from the `Downloads Page`_ - - `View the ChangeLog`_ - - .. image:: https://pypip.in/v/circuits/badge.png?text=version - :target: https://pypi.python.org/pypi/circuits - :alt: Latest Version - - .. image:: https://pypip.in/py_versions/circuits/badge.svg - :target: https://pypi.python.org/pypi/circuits - :alt: Supported Python Versions - - .. image:: https://pypip.in/implementation/circuits/badge.svg - :target: https://pypi.python.org/pypi/circuits - :alt: Supported Python implementations - - .. image:: https://pypip.in/status/circuits/badge.svg - :target: https://pypi.python.org/pypi/circuits - :alt: Development Status - - .. image:: https://pypip.in/d/circuits/badge.png - :target: https://pypi.python.org/pypi/circuits - :alt: Number of Downloads - - .. image:: https://pypip.in/format/circuits/badge.svg - :target: https://pypi.python.org/pypi/circuits - :alt: Format - - .. image:: https://pypip.in/license/circuits/badge.svg - :target: https://pypi.python.org/pypi/circuits - :alt: License - - .. image:: https://requires.io/bitbucket/circuits/circuits/requirements.png?branch=default - :target: https://requires.io/bitbucket/circuits/circuits/requirements?branch=default - :alt: Requirements Status - - - Examples - -------- - - - Hello - ..... - - - .. code:: python - - #!/usr/bin/env python - - """circuits Hello World""" - - from circuits import Component, Event - - - class hello(Event): - """hello Event""" - - - class App(Component): - - def hello(self): - """Hello Event Handler""" - - print("Hello World!") - - def started(self, component): - """Started Event Handler - - This is fired internally when your application starts up and can be used to - trigger events that only occur once during startup. - """ - - self.fire(hello()) # Fire hello Event - - raise SystemExit(0) # Terminate the Application - - App().run() - - - Echo Server - ........... - - - .. code:: python - - #!/usr/bin/env python - - """Simple TCP Echo Server - - This example shows how you can create a simple TCP Server (an Echo Service) - utilizing the builtin Socket Components that the circuits library ships with. - """ - - from circuits import handler, Debugger - from circuits.net.sockets import TCPServer - - - class EchoServer(TCPServer): - - @handler("read") - def on_read(self, sock, data): - """Read Event Handler - - This is fired by the underlying Socket Component when there has been - new data read from the connected client. - - ..note :: By simply returning, client/server socket components listen - to ValueChagned events (feedback) to determine if a handler - returned some data and fires a subsequent Write event with - the value returned. - """ - - return data - - # Start and "run" the system. - # Bind to port 0.0.0.0:9000 - app = EchoServer(9000) - Debugger().register(app) - app.run() - - - Hello Web - ......... - - - .. code:: python - - #!/usr/bin/env python - - from circuits.web import Server, Controller - - - class Root(Controller): - - def index(self): - """Index Request Handler - - Controller(s) expose implicitly methods as request handlers. - Request Handlers can still be customized by using the ``@expose`` - decorator. For example exposing as a different path. - """ - - return "Hello World!" - - app = Server(("0.0.0.0", 9000)) - Root().register(app) - app.run() - - - More `examples `_... - - - - Features - -------- - - - event driven - - concurrency support - - component architecture - - asynchronous I/O components - - no required external dependencies - - full featured web framework (circuits.web) - - coroutine based synchronization primitives - - - Requirements - ------------ - - - circuits has no dependencies beyond the `Python Standard Library`_. - - - Supported Platforms - ------------------- - - - Linux, FreeBSD, Mac OS X, Windows - - Python 2.6, 2.7, 3.2, 3.3, 3.4 - - pypy 2.0, 2.1, 2.2 - - - Installation - ------------ - - The simplest and recommended way to install circuits is with pip. - You may install the latest stable release from PyPI with pip:: - - > pip install circuits - - If you do not have pip, you may use easy_install:: - - > easy_install circuits - - Alternatively, you may download the source package from the - `PyPi Page`_ or the `Downloads Page`_ extract it and install using:: - - > python setup.py install - - - .. note:: - You can install the `development version - `_ - via ``pip install circuits==dev``. - - - License - ------- - - circuits is licensed under the `MIT License`_. - - - Feedback - -------- - - We welcome any questions or feedback about bugs and suggestions on how to - improve circuits. Let us know what you think about circuits. `@pythoncircuits `_. - - Do you have suggestions for improvement? Then please `Create an Issue`_ - with details of what you would like to see. I'll take a look at it and - work with you to either incorporate the idea or find a better solution. - - - Community - --------- - - There is also a small community of circuits enthusiasts that you may - find on the `#circuits IRC Channel`_ on the `FreeNode IRC Network`_ - and the `Mailing List`_. - -Keywords: event framework distributed concurrent component asynchronous -Platform: POSIX -Classifier: Development Status :: 5 - Production/Stable -Classifier: Environment :: Console -Classifier: Environment :: No Input/Output (Daemon) -Classifier: Environment :: Other Environment -Classifier: Environment :: Plugins -Classifier: Environment :: Web Environment -Classifier: Intended Audience :: Developers -Classifier: Intended Audience :: Information Technology -Classifier: Intended Audience :: Science/Research -Classifier: Intended Audience :: System Administrators -Classifier: Intended Audience :: Telecommunications Industry -Classifier: License :: OSI Approved :: MIT License -Classifier: Natural Language :: English -Classifier: Operating System :: POSIX :: BSD -Classifier: Operating System :: POSIX :: Linux -Classifier: Operating System :: MacOS :: MacOS X -Classifier: Operating System :: Microsoft :: Windows -Classifier: Programming Language :: Python :: 2.6 -Classifier: Programming Language :: Python :: 2.7 -Classifier: Programming Language :: Python :: 3.1 -Classifier: Programming Language :: Python :: 3.2 -Classifier: Programming Language :: Python :: 3.3 -Classifier: Programming Language :: Python :: Implementation :: CPython -Classifier: Programming Language :: Python :: Implementation :: PyPy -Classifier: Topic :: Adaptive Technologies -Classifier: Topic :: Communications :: Chat :: Internet Relay Chat -Classifier: Topic :: Communications :: Email :: Mail Transport Agents -Classifier: Topic :: Database -Classifier: Topic :: Internet :: WWW/HTTP :: HTTP Servers -Classifier: Topic :: Internet :: WWW/HTTP :: WSGI :: Application -Classifier: Topic :: Internet :: WWW/HTTP :: WSGI :: Middleware -Classifier: Topic :: Internet :: WWW/HTTP :: WSGI :: Server -Classifier: Topic :: Software Development :: Libraries :: Application Frameworks -Classifier: Topic :: Software Development :: Libraries :: Python Modules -Classifier: Topic :: System :: Clustering -Classifier: Topic :: System :: Distributed Computing diff -Nru circuits-3.1.0+ds1/README.md circuits-3.2.2/README.md --- circuits-3.1.0+ds1/README.md 1970-01-01 00:00:00.000000000 +0000 +++ circuits-3.2.2/README.md 2021-10-19 16:23:49.000000000 +0000 @@ -0,0 +1,94 @@ +[![Build Status](https://github.com/circuits/circuits/actions/workflows/python-app.yml/badge.svg)](https://github.com/circuits/circuits/actions/workflows/python-app.yml) + +[![codecov](https://codecov.io/gh/circuits/circuits/branch/master/graph/badge.svg)](https://codecov.io/gh/circuits/circuits) + +[![Stories Ready](https://badge.waffle.io/circuits/circuits.png?label=ready&title=Ready)](https://waffle.io/circuits/circuits) + +circuits is a **Lightweight** **Event** driven and **Asynchronous** **Application Framework** for the [Python Programming Language](http://www.python.org/) with a strong **Component** Architecture. + +circuits also includes a lightweight, high performance and scalable HTTP/WSGI compliant web server as well as various I/O and Networking components. + +- [Website](http://circuitsframework.com/) +- [Downloads](https://github.com/circuits/circuits/releases) +- [Documentation](http://circuits.readthedocs.org/en/latest/) + +Got questions? + +- [Ask a Question](http://stackoverflow.com/questions/ask) (Tag it: `circuits-framework`) + +Examples +======== + +Features +======== + +- event driven +- concurrency support +- component architecture +- asynchronous I/O components +- no required external dependencies +- full featured web framework (circuits.web) +- coroutine based synchronization primitives + +Requirements +============ + +- circuits has no dependencies beyond the [Python Standard Library](http://docs.python.org/library/). + +Supported Platforms +=================== + +- Linux, FreeBSD, Mac OS X, Windows +- Python 2.7, 3.4, 3.5, 3.6 +- pypy (the newer the better) + +Installation +============ + +The simplest and recommended way to install circuits is with pip. You may install the latest stable release from PyPI with pip: + + $ pip install circuits + +If you do not have pip, you may use easy\_install: + + $ easy_install circuits + +Alternatively, you may download the source package from the [PyPi](http://pypi.python.org/pypi/circuits) or the [Downloads](https://github.com/circuits/circuits/releases) extract it and install using: + + $ python setup.py install + +> **note** +> +> You can install the [development version](https://github.com/circuits/circuits/archive/master.zip#egg=circuits-dev) +> via `pip install circuits==dev`. +> +License +======= + +circuits is licensed under the [MIT License](http://www.opensource.org/licenses/mit-license.php). + +Feedback +======== + +We welcome any questions or feedback about bugs and suggestions on how to improve circuits. + +Let us know what you think about circuits. [@pythoncircuits](http://twitter.com/pythoncircuits). + +Do you have suggestions for improvement? Then please [Create an Issue](https://github.com/circuits/circuits/issues/new) with details of what you would like to see. I'll take a look at it and work with you to either incorporate the idea or find a better solution. + +Community +========= + +There are also several places you can reach out to the circuits community: + +- [Mailing List](http://groups.google.com/group/circuits-users) +- [Google+ Group](https://plus.google.com/communities/107775112577294599973) +- [\#circuits IRC Channel](http://webchat.freenode.net/?randomnick=1&channels=circuits&uio=d4) on the [FreeNode IRC Network](http://freenode.net) +- [Ask a Question](http://stackoverflow.com/questions/ask) on [Stackoverflow](http://stackoverflow.com/) (Tag it: `circuits-framework`) + +------------------------------------------------------------------------ + +Disclaimer +========== + +Whilst I (James Mills) continue to contribute and maintain the circuits project I do not represent the interests or business of my employer Facebook Inc. The contributions I make are of my own free time and have no bearing or relevance to Facebook Inc. diff -Nru circuits-3.1.0+ds1/README.rst circuits-3.2.2/README.rst --- circuits-3.1.0+ds1/README.rst 2014-10-31 23:12:32.000000000 +0000 +++ circuits-3.2.2/README.rst 2021-10-19 16:23:49.000000000 +0000 @@ -3,14 +3,27 @@ .. _FreeNode IRC Network: http://freenode.net .. _Python Standard Library: http://docs.python.org/library/ .. _MIT License: http://www.opensource.org/licenses/mit-license.php -.. _Create an Issue: https://bitbucket.org/circuits/circuits/issue/new +.. _Create an Issue: https://github.com/circuits/circuits/issues/new .. _Mailing List: http://groups.google.com/group/circuits-users -.. _Project Website: http://circuitsframework.com/ -.. _PyPi Page: http://pypi.python.org/pypi/circuits -.. _Read the Docs: http://circuits.readthedocs.org/en/latest/ -.. _View the ChangeLog: http://circuits.readthedocs.org/en/latest/changes.html -.. _Downloads Page: https://bitbucket.org/circuits/circuits/downloads - +.. _Website: http://circuitsframework.com/ +.. _PyPi: http://pypi.python.org/pypi/circuits +.. _Documentation: http://circuits.readthedocs.org/en/latest/ +.. _Downloads: https://github.com/circuits/circuits/releases +.. _Ask a Question: http://stackoverflow.com/questions/ask +.. _Stackoverflow: http://stackoverflow.com/ +.. _Google+ Group: https://plus.google.com/communities/107775112577294599973 + +.. image:: https://github.com/circuits/circuits/actions/workflows/python-app.yml/badge.svg + :target: https://github.com/circuits/circuits/actions/workflows/python-app.yml + :alt: Build Status + +.. image:: https://codecov.io/gh/circuits/circuits/branch/master/graph/badge.svg + :target: https://codecov.io/gh/circuits/circuits + :alt: Coverage + +.. image:: https://badge.waffle.io/circuits/circuits.png?label=ready&title=Ready + :target: https://waffle.io/circuits/circuits + :alt: Stories Ready circuits is a **Lightweight** **Event** driven and **Asynchronous** **Application Framework** for the `Python Programming Language`_ @@ -20,48 +33,18 @@ HTTP/WSGI compliant web server as well as various I/O and Networking components. -- Visit the `Project Website`_ -- `Read the Docs`_ -- Download it from the `Downloads Page`_ -- `View the ChangeLog`_ - -.. image:: https://pypip.in/v/circuits/badge.png?text=version - :target: https://pypi.python.org/pypi/circuits - :alt: Latest Version - -.. image:: https://pypip.in/py_versions/circuits/badge.svg - :target: https://pypi.python.org/pypi/circuits - :alt: Supported Python Versions - -.. image:: https://pypip.in/implementation/circuits/badge.svg - :target: https://pypi.python.org/pypi/circuits - :alt: Supported Python implementations - -.. image:: https://pypip.in/status/circuits/badge.svg - :target: https://pypi.python.org/pypi/circuits - :alt: Development Status - -.. image:: https://pypip.in/d/circuits/badge.png - :target: https://pypi.python.org/pypi/circuits - :alt: Number of Downloads - -.. image:: https://pypip.in/format/circuits/badge.svg - :target: https://pypi.python.org/pypi/circuits - :alt: Format - -.. image:: https://pypip.in/license/circuits/badge.svg - :target: https://pypi.python.org/pypi/circuits - :alt: License - -.. image:: https://requires.io/bitbucket/circuits/circuits/requirements.png?branch=default - :target: https://requires.io/bitbucket/circuits/circuits/requirements?branch=default - :alt: Requirements Status +- `Website`_ +- `Downloads`_ +- `Documentation`_ + +Got questions? + +- `Ask a Question`_ (Tag it: ``circuits-framework``) Examples -------- - .. include:: examples/index.rst @@ -87,8 +70,8 @@ ------------------- - Linux, FreeBSD, Mac OS X, Windows -- Python 2.6, 2.7, 3.2, 3.3, 3.4 -- pypy 2.0, 2.1, 2.2 +- Python 2.7, 3.4, 3.5, 3.6 +- pypy (the newer the better) Installation @@ -97,21 +80,21 @@ The simplest and recommended way to install circuits is with pip. You may install the latest stable release from PyPI with pip:: - > pip install circuits + $ pip install circuits If you do not have pip, you may use easy_install:: - > easy_install circuits + $ easy_install circuits Alternatively, you may download the source package from the -`PyPi Page`_ or the `Downloads Page`_ extract it and install using:: +`PyPi`_ or the `Downloads`_ extract it and install using:: - > python setup.py install + $ python setup.py install .. note:: You can install the `development version - `_ + `_ via ``pip install circuits==dev``. @@ -125,7 +108,9 @@ -------- We welcome any questions or feedback about bugs and suggestions on how to -improve circuits. Let us know what you think about circuits. `@pythoncircuits `_. +improve circuits. + +Let us know what you think about circuits. `@pythoncircuits `_. Do you have suggestions for improvement? Then please `Create an Issue`_ with details of what you would like to see. I'll take a look at it and @@ -135,6 +120,19 @@ Community --------- -There is also a small community of circuits enthusiasts that you may -find on the `#circuits IRC Channel`_ on the `FreeNode IRC Network`_ -and the `Mailing List`_. +There are also several places you can reach out to the circuits community: + +- `Mailing List`_ +- `Google+ Group`_ +- `#circuits IRC Channel`_ on the `FreeNode IRC Network`_ +- `Ask a Question`_ on `Stackoverflow`_ (Tag it: ``circuits-framework``) + +---- + +Disclaimer +---------- + +Whilst I (James Mills) continue to contribute and maintain the circuits project +I do not represent the interests or business of my employer Facebook Inc. The +contributions I make are of my own free time and have no bearing or relevance +to Facebook Inc. diff -Nru circuits-3.1.0+ds1/requirements-dev.txt circuits-3.2.2/requirements-dev.txt --- circuits-3.1.0+ds1/requirements-dev.txt 2014-09-20 22:14:32.000000000 +0000 +++ circuits-3.2.2/requirements-dev.txt 2021-10-19 16:23:49.000000000 +0000 @@ -1,17 +1,20 @@ # Convenient Development Tasks -Fabric==1.8.3 +Fabric # Debugging -pudb==2014.1 +pudb + +# Packaging +wheel # Running Tests -tox==1.7.1 -pytest==2.5.2 -pytest-cov==1.6 +tox +pytest +uhttplib +codecov +pytest-cov # Generating Documentation -Sphinx==1.2.2 -Sphinx-PyPI-upload==0.2.1 -sphinxcontrib-bitbucket==1.0 -sphinxcontrib-googleanalytics==0.1 -sphinxcontrib-programoutput==0.8 +Sphinx +releases +Sphinx-PyPI-upload diff -Nru circuits-3.1.0+ds1/requirements-test.txt circuits-3.2.2/requirements-test.txt --- circuits-3.1.0+ds1/requirements-test.txt 1970-01-01 00:00:00.000000000 +0000 +++ circuits-3.2.2/requirements-test.txt 2021-10-19 16:23:49.000000000 +0000 @@ -0,0 +1,7 @@ +codecov +pytest +pytest-cov +pytest-timeout +flake8 +isort +tox diff -Nru circuits-3.1.0+ds1/requirements.txt circuits-3.2.2/requirements.txt --- circuits-3.1.0+ds1/requirements.txt 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/requirements.txt 2021-10-19 16:23:49.000000000 +0000 @@ -1 +0,0 @@ -. diff -Nru circuits-3.1.0+ds1/setup.cfg circuits-3.2.2/setup.cfg --- circuits-3.1.0+ds1/setup.cfg 2014-10-31 23:13:40.000000000 +0000 +++ circuits-3.2.2/setup.cfg 2021-10-19 16:23:49.000000000 +0000 @@ -1,12 +1,24 @@ [build_sphinx] source-dir = docs/source -build-dir = docs/build +build-dir = docs/build [upload_sphinx] -upload-dir = docs/build/html +upload-dir = docs/build/html -[egg_info] -tag_build = -tag_date = 0 -tag_svn_revision = 0 +[bdist_wheel] +universal=1 +[flake8] +exclude = build,.git,.tox,docs,circuits/six.py,circuits/web/parsers/multipart.py +max-line-length = 119 + +[isort] +combine_as_imports = true +default_section = THIRDPARTY +known_standard_library = crypt +include_trailing_comma = true +known_first_party = circuits +line_length = 79 +multi_line_output = 5 +dont_skip = __init__.py +skip = .tox,docs,circuits/web/parsers/multipart.py diff -Nru circuits-3.1.0+ds1/setup.py circuits-3.2.2/setup.py --- circuits-3.1.0+ds1/setup.py 2014-10-04 02:41:47.000000000 +0000 +++ circuits-3.2.2/setup.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,42 +1,22 @@ #!/usr/bin/env python - from glob import glob -from os import getcwd, path -from imp import new_module - -from setuptools import setup, find_packages +from setuptools import find_packages, setup -version = new_module("version") - -exec( - compile( - open( - path.join( - path.dirname( - globals().get( - "__file__", - path.join(getcwd(), "circuits") - ) - ), - "circuits/version.py" - ), - "r" - ).read(), - "circuits/version.py", "exec" - ), - version.__dict__ -) +def read_file(filename): + try: + return open(filename, "r").read() + except IOError: + return "" setup( name="circuits", - version=version.version, description="Asynchronous Component based Event Application Framework", long_description=open("README.rst").read().replace( ".. include:: examples/index.rst", - open("examples/index.rst", "r").read() + read_file("examples/index.rst") ), author="James Mills", author_email="prologic@shortcircuit.net.au", @@ -60,11 +40,13 @@ "Operating System :: POSIX :: Linux", "Operating System :: MacOS :: MacOS X", "Operating System :: Microsoft :: Windows", - "Programming Language :: Python :: 2.6", "Programming Language :: Python :: 2.7", - "Programming Language :: Python :: 3.1", - "Programming Language :: Python :: 3.2", - "Programming Language :: Python :: 3.3", + "Programming Language :: Python :: 3.4", + "Programming Language :: Python :: 3.5", + "Programming Language :: Python :: 3.6", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy", "Topic :: Adaptive Technologies", @@ -82,14 +64,30 @@ license="MIT", keywords="event framework distributed concurrent component asynchronous", platforms="POSIX", - packages=find_packages("."), + packages=find_packages( + exclude=[ + "*.tests", + "*.tests.*", + "tests.*", + "tests", + "*.fabfile", + "*.fabfile.*", + "fabfile.*", + "fabfile", + ] + ), scripts=glob("bin/*"), - install_requires=[], entry_points={ "console_scripts": [ "circuits.web=circuits.web.main:main", ] }, - test_suite="tests.main.main", - zip_safe=True + zip_safe=True, + use_scm_version={ + "write_to": "circuits/version.py", + }, + setup_requires=[ + "setuptools_scm" + ], + extras_require={"stomp": ["stompest>=2.3.0", "pysocks>=1.6.7"]}, ) diff -Nru circuits-3.1.0+ds1/tests/app/app.py circuits-3.2.2/tests/app/app.py --- circuits-3.1.0+ds1/tests/app/app.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/app/app.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,9 +1,9 @@ #!/usr/bin/env python - - -from sys import argv +import sys from os.path import abspath +from circuits import Component +from circuits.app import Daemon try: from coverage import coverage @@ -12,14 +12,13 @@ HAS_COVERAGE = False -from circuits import Component -from circuits.app import Daemon - - class App(Component): - def init(self, pidfile, **kwargs): - Daemon(pidfile, **kwargs).register(self) + def init(self, pidfile): + self.pidfile = pidfile + + def started(self, *args): + Daemon(self.pidfile).register(self) def prepare_unregister(self, *args): return @@ -30,11 +29,14 @@ _coverage = coverage(data_suffix=True) _coverage.start() - pidfile = abspath(argv[1]) + args = iter(sys.argv) + next(args) # executable + + pidfile = next(args) # pidfile - app = App(pidfile) + pidfile = abspath(pidfile) - app.run() + App(pidfile).run() if HAS_COVERAGE: _coverage.stop() Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/app/app.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/app/app.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/app/__init__.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/app/__init__.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/app/__pycache__/app.cpython-32.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/app/__pycache__/app.cpython-32.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/app/__pycache__/app.cpython-33.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/app/__pycache__/app.cpython-33.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/app/__pycache__/app.cpython-34.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/app/__pycache__/app.cpython-34.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/app/__pycache__/__init__.cpython-32.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/app/__pycache__/__init__.cpython-32.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/app/__pycache__/__init__.cpython-33.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/app/__pycache__/__init__.cpython-33.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/app/__pycache__/__init__.cpython-34.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/app/__pycache__/__init__.cpython-34.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/app/__pycache__/test_daemon.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/app/__pycache__/test_daemon.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/app/__pycache__/test_daemon.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/app/__pycache__/test_daemon.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/app/__pycache__/test_daemon.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/app/__pycache__/test_daemon.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/app/__pycache__/test_daemon.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/app/__pycache__/test_daemon.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/app/__pycache__/test_daemon.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/app/__pycache__/test_daemon.cpython-34-PYTEST.pyc differ diff -Nru circuits-3.1.0+ds1/tests/app/test_daemon.py circuits-3.2.2/tests/app/test_daemon.py --- circuits-3.1.0+ds1/tests/app/test_daemon.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/app/test_daemon.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,21 +1,17 @@ #!/usr/bin/env python - - -import pytest -if pytest.PLATFORM == "win32": - pytest.skip("Unsupported Platform") - - import sys -from os import kill -from time import sleep from errno import ESRCH +from os import kill from signal import SIGTERM from subprocess import Popen +from time import sleep +import pytest from . import app +pytestmark = pytest.mark.skipif(pytest.PLATFORM == 'win32', reason='Unsupported Platform') + def is_running(pid): try: diff -Nru circuits-3.1.0+ds1/tests/conftest.py circuits-3.2.2/tests/conftest.py --- circuits-3.1.0+ds1/tests/conftest.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/conftest.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,19 +1,18 @@ -# Module: conftest -# Date: 6th December 2010 -# Author: James Mills, prologic at shortcircuit dot net dot au - """py.test config""" -import pytest - import sys import threading -import collections -from time import sleep from collections import deque +from time import sleep +try: + from collections import Callable +except ImportError: + from collections.abc import Callable +import pytest + +from circuits import BaseComponent, Debugger, Manager, handler from circuits.core.manager import TIMEOUT -from circuits import handler, BaseComponent, Debugger, Manager class Watcher(BaseComponent): @@ -30,25 +29,25 @@ def clear(self): self.events.clear() - def wait(self, name, channel=None, timeout=6.0): - try: - for i in range(int(timeout / TIMEOUT)): - if channel is None: - with self._lock: - for event in self.events: - if event.name == name: - return True - else: - with self._lock: - for event in self.events: - if event.name == name and \ - channel in event.channels: - return True + def wait(self, name, channel=None, timeout=30.0): + for i in range(int(timeout / TIMEOUT)): + with self._lock: + for event in self.events: + if event.name == name and event.waitingHandlers == 0: + if (channel is None) or (channel in event.channels): + return True + sleep(TIMEOUT) + else: + return False - sleep(TIMEOUT) - finally: - pass - #self.events.clear() + def count(self, name, channel=None, n=1, timeout=30.0): + n = 0 + with self._lock: + for event in self.events: + if event.name == name and event.waitingHandlers == 0: + if (channel is None) or (channel in event.channels): + n += 1 + return n class Flag(object): @@ -72,7 +71,7 @@ class WaitEvent(object): - def __init__(self, manager, name, channel=None, timeout=6.0): + def __init__(self, manager, name, channel=None, timeout=30.0): if channel is None: channel = getattr(manager, "channel", None) @@ -98,10 +97,10 @@ self.manager.removeHandler(self.handler) -def wait_for(obj, attr, value=True, timeout=3.0): +def wait_for(obj, attr, value=True, timeout=30.0): from circuits.core.manager import TIMEOUT for i in range(int(timeout / TIMEOUT)): - if isinstance(value, collections.Callable): + if isinstance(value, Callable): if value(obj, attr): return True elif getattr(obj, attr) == value: @@ -109,7 +108,21 @@ sleep(TIMEOUT) -@pytest.fixture(scope="session") +class SimpleManager(Manager): + + def tick(self, timeout=-1): + self._running = False + return super(SimpleManager, self).tick(timeout) + + +@pytest.fixture +def simple_manager(request): + manager = SimpleManager() + Debugger(events=request.config.option.verbose).register(manager) + return manager + + +@pytest.fixture def manager(request): manager = Manager() @@ -122,12 +135,7 @@ manager.start() assert waiter.wait() - if request.config.option.verbose: - verbose = True - else: - verbose = False - - Debugger(events=verbose).register(manager) + Debugger(events=request.config.option.verbose).register(manager) return manager @@ -146,12 +154,12 @@ return watcher -def pytest_namespace(): - return dict(( - ("WaitEvent", WaitEvent), - ("wait_for", wait_for), - ("call_event", call_event), - ("PLATFORM", sys.platform), - ("PYVER", sys.version_info[:3]), - ("call_event_from_name", call_event_from_name), - )) +for key, value in dict(( + ("WaitEvent", WaitEvent), + ("wait_for", wait_for), + ("call_event", call_event), + ("PLATFORM", sys.platform), + ("PYVER", sys.version_info[:3]), + ("call_event_from_name", call_event_from_name), +)).items(): + setattr(pytest, key, value) Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/conftest.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/conftest.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/app.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/app.pyc differ diff -Nru circuits-3.1.0+ds1/tests/core/exitcodeapp.py circuits-3.2.2/tests/core/exitcodeapp.py --- circuits-3.1.0+ds1/tests/core/exitcodeapp.py 1970-01-01 00:00:00.000000000 +0000 +++ circuits-3.2.2/tests/core/exitcodeapp.py 2021-10-19 16:23:49.000000000 +0000 @@ -0,0 +1,23 @@ +#!/usr/bin/env python +import sys + +from circuits import Component + + +class App(Component): + + def started(self, *args): + try: + code = int(sys.argv[1]) + except ValueError: + code = sys.argv[1] + + raise SystemExit(code) + + +def main(): + App().run() + + +if __name__ == "__main__": + main() Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__init__.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__init__.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/app.cpython-32.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/app.cpython-32.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/app.cpython-33.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/app.cpython-33.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/app.cpython-34.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/app.cpython-34.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/__init__.cpython-32.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/__init__.cpython-32.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/__init__.cpython-33.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/__init__.cpython-33.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/__init__.cpython-34.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/__init__.cpython-34.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/signalapp.cpython-32.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/signalapp.cpython-32.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/signalapp.cpython-33.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/signalapp.cpython-33.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/signalapp.cpython-34.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/signalapp.cpython-34.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_bridge.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_bridge.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_bridge.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_bridge.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_bridge.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_bridge.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_bridge.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_bridge.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_bridge.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_bridge.cpython-34-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_call_wait.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_call_wait.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_call_wait.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_call_wait.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_call_wait.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_call_wait.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_call_wait.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_call_wait.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_call_wait.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_call_wait.cpython-34-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_call_wait_order.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_call_wait_order.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_call_wait_order.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_call_wait_order.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_call_wait_order.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_call_wait_order.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_call_wait_order.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_call_wait_order.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_call_wait_order.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_call_wait_order.cpython-34-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_call_wait_timeout.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_call_wait_timeout.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_call_wait_timeout.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_call_wait_timeout.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_call_wait_timeout.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_call_wait_timeout.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_call_wait_timeout.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_call_wait_timeout.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_call_wait_timeout.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_call_wait_timeout.cpython-34-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_channel_selection.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_channel_selection.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_channel_selection.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_channel_selection.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_channel_selection.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_channel_selection.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_channel_selection.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_channel_selection.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_channel_selection.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_channel_selection.cpython-34-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_complete.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_complete.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_complete.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_complete.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_complete.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_complete.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_complete.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_complete.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_complete.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_complete.cpython-34-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_component_repr.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_component_repr.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_component_repr.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_component_repr.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_component_repr.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_component_repr.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_component_repr.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_component_repr.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_component_repr.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_component_repr.cpython-34-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_component_setup.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_component_setup.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_component_setup.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_component_setup.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_component_setup.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_component_setup.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_component_setup.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_component_setup.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_component_setup.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_component_setup.cpython-34-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_component_targeting.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_component_targeting.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_component_targeting.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_component_targeting.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_component_targeting.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_component_targeting.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_component_targeting.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_component_targeting.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_component_targeting.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_component_targeting.cpython-34-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_core.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_core.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_core.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_core.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_core.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_core.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_core.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_core.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_core.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_core.cpython-34-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_debugger.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_debugger.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_debugger.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_debugger.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_debugger.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_debugger.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_debugger.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_debugger.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_debugger.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_debugger.cpython-34-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_dynamic_handlers.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_dynamic_handlers.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_dynamic_handlers.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_dynamic_handlers.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_dynamic_handlers.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_dynamic_handlers.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_dynamic_handlers.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_dynamic_handlers.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_dynamic_handlers.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_dynamic_handlers.cpython-34-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_errors.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_errors.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_errors.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_errors.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_errors.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_errors.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_errors.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_errors.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_errors.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_errors.cpython-34-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_event.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_event.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_event.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_event.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_event.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_event.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_event.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_event.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_event.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_event.cpython-34-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_event_priority.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_event_priority.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_event_priority.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_event_priority.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_event_priority.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_event_priority.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_event_priority.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_event_priority.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_event_priority.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_event_priority.cpython-34-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_feedback.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_feedback.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_feedback.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_feedback.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_feedback.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_feedback.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_feedback.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_feedback.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_feedback.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_feedback.cpython-34-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_filters.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_filters.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_filters.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_filters.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_filters.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_filters.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_filters.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_filters.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_filters.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_filters.cpython-34-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_generate_events.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_generate_events.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_generate_events.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_generate_events.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_generate_events.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_generate_events.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_generate_events.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_generate_events.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_generate_events.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_generate_events.cpython-34-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_generator_value.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_generator_value.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_generator_value.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_generator_value.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_generator_value.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_generator_value.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_generator_value.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_generator_value.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_generator_value.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_generator_value.cpython-34-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_globals.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_globals.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_globals.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_globals.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_globals.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_globals.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_globals.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_globals.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_globals.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_globals.cpython-34-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_imports.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_imports.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_imports.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_imports.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_imports.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_imports.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_imports.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_imports.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_imports.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_imports.cpython-34-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_inheritence.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_inheritence.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_inheritence.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_inheritence.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_inheritence.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_inheritence.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_inheritence.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_inheritence.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_inheritence.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_inheritence.cpython-34-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_interface_query.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_interface_query.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_interface_query.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_interface_query.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_interface_query.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_interface_query.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_interface_query.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_interface_query.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_interface_query.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_interface_query.cpython-34-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_loader.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_loader.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_loader.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_loader.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_loader.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_loader.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_loader.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_loader.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_loader.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_loader.cpython-34-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_manager_repr.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_manager_repr.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_manager_repr.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_manager_repr.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_manager_repr.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_manager_repr.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_manager_repr.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_manager_repr.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_manager_repr.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_manager_repr.cpython-34-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_new_filter.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_new_filter.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_new_filter.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_new_filter.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_new_filter.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_new_filter.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_new_filter.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_new_filter.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_new_filter.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_new_filter.cpython-34-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_priority.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_priority.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_priority.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_priority.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_priority.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_priority.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_priority.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_priority.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_priority.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_priority.cpython-34-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_signals.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_signals.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_signals.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_signals.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_signals.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_signals.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_signals.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_signals.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_signals.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_signals.cpython-34-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_timers.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_timers.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_timers.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_timers.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_timers.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_timers.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_timers.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_timers.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_timers.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_timers.cpython-34-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_utils.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_utils.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_utils.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_utils.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_utils.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_utils.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_utils.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_utils.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_utils.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_utils.cpython-34-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_value.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_value.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_value.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_value.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_value.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_value.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_value.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_value.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_value.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_value.cpython-34-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_worker_process.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_worker_process.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_worker_process.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_worker_process.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_worker_process.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_worker_process.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_worker_process.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_worker_process.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_worker_process.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_worker_process.cpython-34-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_worker_thread.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_worker_thread.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_worker_thread.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_worker_thread.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_worker_thread.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_worker_thread.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_worker_thread.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_worker_thread.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/__pycache__/test_worker_thread.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/__pycache__/test_worker_thread.cpython-34-PYTEST.pyc differ diff -Nru circuits-3.1.0+ds1/tests/core/signalapp.py circuits-3.2.2/tests/core/signalapp.py --- circuits-3.1.0+ds1/tests/core/signalapp.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/core/signalapp.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,9 +1,9 @@ #!/usr/bin/env python - - import os import sys +from circuits import Component +from circuits.app import Daemon try: from coverage import coverage @@ -12,10 +12,6 @@ HAS_COVERAGE = False -from circuits import Component -from circuits.app import Daemon - - class App(Component): def init(self, pidfile, signalfile): @@ -44,5 +40,6 @@ _coverage.stop() _coverage.save() + if __name__ == "__main__": main() Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/core/signalapp.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/core/signalapp.pyc differ diff -Nru circuits-3.1.0+ds1/tests/core/test_bridge.py circuits-3.2.2/tests/core/test_bridge.py --- circuits-3.1.0+ds1/tests/core/test_bridge.py 2014-10-01 12:38:20.000000000 +0000 +++ circuits-3.2.2/tests/core/test_bridge.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,16 +1,13 @@ #!/usr/bin/python -i - +from os import getpid import pytest -if pytest.PLATFORM == "win32": - pytest.skip("Unsupported Platform") - -pytest.importorskip("multiprocessing") +from circuits import Component, Event, ipc -from os import getpid +pytestmark = pytest.mark.skipif(pytest.PLATFORM == 'win32', reason='Unsupported Platform') -from circuits import Component, Event +pytest.importorskip("multiprocessing") class hello(Event): @@ -26,9 +23,9 @@ def test(manager, watcher): app = App() process, bridge = app.start(process=True, link=manager) - assert watcher.wait("ready", timeout=30) + assert watcher.wait("ready") - x = manager.fire(hello()) + x = manager.fire(ipc(hello())) assert pytest.wait_for(x, "result") diff -Nru circuits-3.1.0+ds1/tests/core/test_call_wait_instance.py circuits-3.2.2/tests/core/test_call_wait_instance.py --- circuits-3.1.0+ds1/tests/core/test_call_wait_instance.py 1970-01-01 00:00:00.000000000 +0000 +++ circuits-3.2.2/tests/core/test_call_wait_instance.py 2021-10-19 16:23:49.000000000 +0000 @@ -0,0 +1,50 @@ +#!/usr/bin/env python +import pytest + +from circuits import Component, Event, handler + + +class wait(Event): + """wait Event""" + + success = True + + +class hello(Event): + """hello Event""" + + success = True + + +class App(Component): + + @handler("wait") + def _on_wait(self): + e = hello() + x = self.fire(e) + yield self.wait(e) + yield x.value + + def hello(self): + return "Hello World!" + + +@pytest.fixture +def app(request, manager, watcher): + app = App().register(manager) + assert watcher.wait("registered") + + def finalizer(): + app.unregister() + + request.addfinalizer(finalizer) + + return app + + +def test_wait_instance(manager, watcher, app): + x = manager.fire(wait()) + assert watcher.wait("wait_success") + + value = x.value + assert value == "Hello World!" diff -Nru circuits-3.1.0+ds1/tests/core/test_call_wait_order.py circuits-3.2.2/tests/core/test_call_wait_order.py --- circuits-3.1.0+ds1/tests/core/test_call_wait_order.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/core/test_call_wait_order.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,17 +1,14 @@ #!/usr/bin/env python - -import pytest - - -from time import sleep, time from random import random, seed +from time import sleep, time +import pytest -from circuits.core import task, Worker -from circuits.core import handler, Component, Event +from circuits.core import Component, Event, Worker, handler, task class hello(Event): + """hello Event""" success = True @@ -32,7 +29,7 @@ yield (yield self.call(e1)) -@pytest.fixture(scope="module") +@pytest.fixture def app(request, manager, watcher): seed(time()) diff -Nru circuits-3.1.0+ds1/tests/core/test_call_wait.py circuits-3.2.2/tests/core/test_call_wait.py --- circuits-3.1.0+ds1/tests/core/test_call_wait.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/core/test_call_wait.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,8 +1,7 @@ #!/usr/bin/env python - import pytest -from circuits import handler, Component, Event +from circuits import Component, Event, handler class wait(Event): @@ -56,7 +55,6 @@ class App(Component): - @handler("wait") def _on_wait(self): x = self.fire(hello()) @@ -100,7 +98,7 @@ yield x.value + y.value -@pytest.fixture(scope="module") +@pytest.fixture def app(request, manager, watcher): app = App().register(manager) assert watcher.wait("registered") @@ -159,3 +157,16 @@ value = x.value assert value == 3 + + +@pytest.mark.xfail(reason='Issue #226') +@pytest.mark.timeout(1) +def test_wait_too_late(manager, watcher, app): + event = foo() + manager.fire(event) + assert watcher.wait("foo_success") + manager.tick() + + x = manager.wait(event, timeout=.1) + value = next(x) + assert value == list(range(1, 10)) diff -Nru circuits-3.1.0+ds1/tests/core/test_call_wait_timeout.py circuits-3.2.2/tests/core/test_call_wait_timeout.py --- circuits-3.1.0+ds1/tests/core/test_call_wait_timeout.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/core/test_call_wait_timeout.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,26 +1,29 @@ #!/usr/bin/env python - import pytest -from circuits.core import handler, Component, Event, TimeoutError +from circuits.core import Component, Event, TimeoutError, handler class wait(Event): + """wait Event""" success = True class call(Event): + """call Event""" success = True class hello(Event): + """hello Event""" success = True class App(Component): + @handler('wait') def _on_wait(self, timeout=-1): result = self.fire(hello()) @@ -46,7 +49,7 @@ yield result -@pytest.fixture(scope="module") +@pytest.fixture def app(request, manager, watcher): app = App().register(manager) assert watcher.wait("registered") diff -Nru circuits-3.1.0+ds1/tests/core/test_channel_selection.py circuits-3.2.2/tests/core/test_channel_selection.py --- circuits-3.1.0+ds1/tests/core/test_channel_selection.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/core/test_channel_selection.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,15 +1,16 @@ #!/usr/bin/python -i - -from circuits import Event, Component, Manager +from circuits import Component, Event, Manager class foo(Event): + """foo Event""" channels = ("a",) class bar(Event): + """bar Event""" @@ -43,7 +44,7 @@ def test(): m = Manager() + A() + B() + C() - while m: + while len(m): m.flush() # Rely on Event.channels diff -Nru circuits-3.1.0+ds1/tests/core/test_complete.py circuits-3.2.2/tests/core/test_complete.py --- circuits-3.1.0+ds1/tests/core/test_complete.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/core/test_complete.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,6 +1,5 @@ #!/usr/bin/python - -from circuits import Event, Component +from circuits import Component, Event class simple_event(Event): @@ -8,6 +7,7 @@ class test(Event): + """test Event""" success = True @@ -70,12 +70,13 @@ """ self._state_when_complete = self._state + app = App() Nested1().register(app) Nested2().register(app) Nested3().register(app) -while app: +while len(app): app.flush() @@ -84,7 +85,7 @@ Test if complete works for an event without further effects """ app.fire(simple_event()) - while app: + while len(app): app.flush() assert app._simple_event_completed @@ -92,7 +93,7 @@ def test_complete_nested(): app.fire(test()) - while app: + while len(app): app.flush() assert app._state_when_success == "Old state" diff -Nru circuits-3.1.0+ds1/tests/core/test_component_repr.py circuits-3.2.2/tests/core/test_component_repr.py --- circuits-3.1.0+ds1/tests/core/test_component_repr.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/core/test_component_repr.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,21 +1,16 @@ -# Module: test_component_repr -# Date: 23rd February 2010 -# Author: James Mills, prologic at shortcircuit dot net dot au - """Component Repr Tests Test Component's representation string. """ - import os +from circuits import Component, Event + try: from threading import current_thread except ImportError: from threading import currentThread as current_thread # NOQA -from circuits import Event, Component - class App(Component): diff -Nru circuits-3.1.0+ds1/tests/core/test_component_setup.py circuits-3.2.2/tests/core/test_component_setup.py --- circuits-3.1.0+ds1/tests/core/test_component_setup.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/core/test_component_setup.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,16 +1,13 @@ -# Module: test_component_setup -# Date: 23rd February 2010 -# Author: James Mills, prologic at shortcircuit dot net dot au +from circuits import Component, Manager from circuits.core.handlers import handler + """Component Setup Tests Tests that event handlers of a Component are automatically registered as event handlers. """ -from circuits import Component, Manager - class App(Component): @@ -51,7 +48,7 @@ assert app.test in app._handlers.get("test", set()) app.unregister() - while m: + while len(m): m.flush() assert not m._handlers @@ -74,7 +71,7 @@ assert b.parent == a a.unregister() - while m: + while len(m): m.flush() assert b.informed diff -Nru circuits-3.1.0+ds1/tests/core/test_component_targeting.py circuits-3.2.2/tests/core/test_component_targeting.py --- circuits-3.1.0+ds1/tests/core/test_component_targeting.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/core/test_component_targeting.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,12 +1,11 @@ #!/usr/bin/env python - - import pytest from circuits import Component, Event class hello(Event): + """hello Event""" success = True @@ -20,7 +19,7 @@ return "Hello World!" -@pytest.fixture(scope="module") +@pytest.fixture def app(request, manager, watcher): app = App().register(manager) assert watcher.wait("registered") diff -Nru circuits-3.1.0+ds1/tests/core/test_core.py circuits-3.2.2/tests/core/test_core.py --- circuits-3.1.0+ds1/tests/core/test_core.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/core/test_core.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,9 +1,9 @@ #!/usr/bin/python -i - -from circuits import Event, Component, Manager +from circuits import Component, Event, Manager class test(Event): + """test Event""" @@ -23,7 +23,7 @@ app = App() app.register(m) -while app: +while len(app): app.flush() @@ -35,4 +35,4 @@ def test_contains(): assert App in m - assert not m in app + assert m not in app diff -Nru circuits-3.1.0+ds1/tests/core/test_coroutine.py circuits-3.2.2/tests/core/test_coroutine.py --- circuits-3.1.0+ds1/tests/core/test_coroutine.py 1970-01-01 00:00:00.000000000 +0000 +++ circuits-3.2.2/tests/core/test_coroutine.py 2021-10-19 16:23:49.000000000 +0000 @@ -0,0 +1,73 @@ +#!/usr/bin/env python +from __future__ import print_function + +import pytest + +from circuits import Component, Event + +pytestmark = pytest.mark.skip("XXX: This test fails intermittently") + + +class test(Event): + + """test Event""" + + +class coroutine1(Event): + + """coroutine Event""" + + complete = True + + +class coroutine2(Event): + + """coroutine Event""" + + complete = True + + +class App(Component): + + returned = False + + def test(self, event): + event.stop() + return "Hello World!" + + def coroutine1(self): + print("coroutine1") + yield self.call(test()) + print("returned") + self.returned = True + + def coroutine2(self): + print("coroutine2") + self.fire(test()) + yield self.wait("test") + print("returned") + self.returned = True + + +@pytest.fixture +def app(request, manager, watcher): + app = App().register(manager) + assert watcher.wait("registered") + + def finalizer(): + app.unregister() + + request.addfinalizer(finalizer) + + return app + + +def test_coroutine(manager, watcher, app): + manager.fire(coroutine1()) + assert watcher.wait("coroutine1_complete") + assert app.returned, "coroutine1" + + app.returned = False + manager.fire(coroutine2()) + assert watcher.wait("coroutine2_complete") + assert app.returned, "coroutine2" diff -Nru circuits-3.1.0+ds1/tests/core/test_debugger.py circuits-3.2.2/tests/core/test_debugger.py --- circuits-3.1.0+ds1/tests/core/test_debugger.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/core/test_debugger.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,21 +1,17 @@ -# Module: debugger -# Date: 5th November 2008 -# Author: James Mills, prologic at shortcircuit dot net dot au - """Debugger Tests""" import sys import pytest +from circuits import Debugger +from circuits.core import Component, Event + try: from StringIO import StringIO except ImportError: from io import StringIO # NOQA -from circuits import Debugger -from circuits.core import Event, Component - class test(Event): """test Event""" @@ -45,7 +41,7 @@ stderr = StringIO() debugger = Debugger(file=stderr) debugger.register(app) - while app: + while len(app): app.flush() stderr.seek(0) stderr.truncate() @@ -81,7 +77,7 @@ app = App() debugger = Debugger(file=stderr) debugger.register(app) - while app: + while len(app): app.flush() stderr.seek(0) stderr.truncate() @@ -121,7 +117,7 @@ app = App() debugger = Debugger(file=logfile) debugger.register(app) - while app: + while len(app): app.flush() stderr.seek(0) stderr.truncate() @@ -156,7 +152,7 @@ stderr = StringIO() debugger = Debugger(file=stderr) debugger.register(app) - while app: + while len(app): app.flush() stderr.seek(0) stderr.truncate() @@ -208,7 +204,7 @@ stderr = StringIO() debugger = Debugger(file=stderr) debugger.register(app) - while app: + while len(app): app.flush() stderr.seek(0) stderr.truncate() @@ -243,7 +239,7 @@ stderr = StringIO() debugger = Debugger(file=stderr) debugger.register(app) - while app: + while len(app): app.flush() stderr.seek(0) stderr.truncate() @@ -277,7 +273,7 @@ logger = Logger() debugger = Debugger(logger=logger) debugger.register(app) - while app: + while len(app): app.flush() e = Event() @@ -292,12 +288,12 @@ logger = Logger() debugger = Debugger(logger=logger) debugger.register(app) - while app: + while len(app): app.flush() e = test(raiseException=True) app.fire(e) - while app: + while len(app): app.flush() - assert logger.error_msg.startswith("ERROR (") + assert logger.error_msg.startswith("ERROR (") diff -Nru circuits-3.1.0+ds1/tests/core/test_dynamic_handlers.py circuits-3.2.2/tests/core/test_dynamic_handlers.py --- circuits-3.1.0+ds1/tests/core/test_dynamic_handlers.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/core/test_dynamic_handlers.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,11 +1,11 @@ #!/usr/bin/env python - import pytest -from circuits import handler, Event, Manager +from circuits import Event, Manager, handler class foo(Event): + """foo Event""" diff -Nru circuits-3.1.0+ds1/tests/core/test_errors.py circuits-3.2.2/tests/core/test_errors.py --- circuits-3.1.0+ds1/tests/core/test_errors.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/core/test_errors.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,11 +1,11 @@ #!/usr/bin/env python - import pytest -from circuits import Event, Component +from circuits import Component, Event class test(Event): + """test Event""" diff -Nru circuits-3.1.0+ds1/tests/core/test_event_priority.py circuits-3.2.2/tests/core/test_event_priority.py --- circuits-3.1.0+ds1/tests/core/test_event_priority.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/core/test_event_priority.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,13 +1,14 @@ #!/usr/bin/env python - from circuits import Component, Event class foo(Event): + """foo Event""" class done(Event): + """done Event""" diff -Nru circuits-3.1.0+ds1/tests/core/test_event.py circuits-3.2.2/tests/core/test_event.py --- circuits-3.1.0+ds1/tests/core/test_event.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/core/test_event.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,15 +1,12 @@ -# Module: test_event -# Date: 12th April 2010 -# Author: James Mills, prologic at shortcircuit dot net dot au - """Event Tests""" import py -from circuits import Event, Component +from circuits import Component, Event class test(Event): + """test Event""" @@ -21,7 +18,7 @@ def test_repr(): app = App() - while app: + while len(app): app.flush() e = test() @@ -37,7 +34,7 @@ def test_create(): app = App() - while app: + while len(app): app.flush() e = Event.create("test") @@ -53,7 +50,7 @@ def test_getitem(): app = App() - while app: + while len(app): app.flush() e = test(1, 2, 3, foo="bar") @@ -69,7 +66,7 @@ def test_setitem(): app = App() - while app: + while len(app): app.flush() e = test(1, 2, 3, foo="bar") diff -Nru circuits-3.1.0+ds1/tests/core/test_exit_code.py circuits-3.2.2/tests/core/test_exit_code.py --- circuits-3.1.0+ds1/tests/core/test_exit_code.py 1970-01-01 00:00:00.000000000 +0000 +++ circuits-3.2.2/tests/core/test_exit_code.py 2021-10-19 16:23:49.000000000 +0000 @@ -0,0 +1,24 @@ +#!/usr/bin/env python +import sys +from subprocess import PIPE, Popen + +from . import exitcodeapp + + +def test_ints(tmpdir): + for expected_status in range(4): + args = [sys.executable, exitcodeapp.__file__, + "{0:d}".format(expected_status)] + p = Popen(args, env={"PYTHONPATH": ":".join(sys.path)}) + status = p.wait() + + assert status == expected_status + + +def test_string(tmpdir): + args = [sys.executable, exitcodeapp.__file__, "foobar"] + p = Popen(args, env={"PYTHONPATH": ":".join(sys.path)}, stderr=PIPE) + status = p.wait() + + assert status == 1 + assert p.stderr.read() == b"foobar\n" diff -Nru circuits-3.1.0+ds1/tests/core/test_feedback.py circuits-3.2.2/tests/core/test_feedback.py --- circuits-3.1.0+ds1/tests/core/test_feedback.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/core/test_feedback.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,15 +1,12 @@ -# Module: test_feedback -# Date: 11th February 2010 -# Author: James Mills, prologic at shortcircuit dot net dot au - """Feedback Channels Tests""" import py -from circuits import handler, Event, Component +from circuits import Component, Event, handler class test(Event): + """test Event""" success = True @@ -55,20 +52,20 @@ def test_success(): app = App() - while app: + while len(app): app.flush() e = test() value = app.fire(e) - while app: + while len(app): app.flush() # The Event s = value.value assert s == "Hello World!" - while app: + while len(app): app.flush() assert app.e == e @@ -79,19 +76,19 @@ def test_failure(): app = App() - while app: + while len(app): app.flush() e = test(error=True) x = app.fire(e) - while app: + while len(app): app.flush() # The Event py.test.raises(Exception, lambda x: reraise(x[1]), x.value) - while app: + while len(app): app.flush() assert app.e == e diff -Nru circuits-3.1.0+ds1/tests/core/test_filters.py circuits-3.2.2/tests/core/test_filters.py --- circuits-3.1.0+ds1/tests/core/test_filters.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/core/test_filters.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,9 +1,9 @@ #!/usr/bin/env python - -from circuits import handler, Event, BaseComponent +from circuits import BaseComponent, Event, handler class test(Event): + """test Event""" @@ -22,7 +22,7 @@ def test_main(): app = App() - while app: + while len(app): app.flush() x = app.fire(test()) app.flush() diff -Nru circuits-3.1.0+ds1/tests/core/test_generate_events.py circuits-3.2.2/tests/core/test_generate_events.py --- circuits-3.1.0+ds1/tests/core/test_generate_events.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/core/test_generate_events.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,5 +1,4 @@ #!/usr/bin/env python - import pytest from circuits import Component, Event @@ -36,7 +35,7 @@ self._ready = True -@pytest.fixture(scope="module") +@pytest.fixture def app(request, manager, watcher): app = App().register(manager) diff -Nru circuits-3.1.0+ds1/tests/core/test_generator_value.py circuits-3.2.2/tests/core/test_generator_value.py --- circuits-3.1.0+ds1/tests/core/test_generator_value.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/core/test_generator_value.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,13 +1,14 @@ #!/usr/bin/env python - -from circuits import Event, Component +from circuits import Component, Event class test(Event): + """test Event""" class hello(Event): + """hello Event""" @@ -26,7 +27,7 @@ def test_return_generator(): app = App() - while app: + while len(app): app.flush() v = app.fire(test()) @@ -39,7 +40,7 @@ def test_yield(): app = App() - while app: + while len(app): app.flush() v = app.fire(hello()) diff -Nru circuits-3.1.0+ds1/tests/core/test_globals.py circuits-3.2.2/tests/core/test_globals.py --- circuits-3.1.0+ds1/tests/core/test_globals.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/core/test_globals.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,13 +1,14 @@ #!/usr/bin/env python - -from circuits import handler, Event, Component +from circuits import Component, Event, handler class foo(Event): + """foo Event""" class test(Event): + """test Event""" @@ -32,11 +33,11 @@ def test_main(): app = A() + B() - while app: + while len(app): app.flush() x = app.fire(test(), "a") - while app: + while len(app): app.flush() assert x.value[0] == "Bar" @@ -46,12 +47,12 @@ def test_event(): app = A() + B() - while app: + while len(app): app.flush() e = test() x = app.fire(e) - while app: + while len(app): app.flush() assert x.value[0] == "Bar" @@ -61,12 +62,12 @@ def test_channel(): app = A() + B() - while app: + while len(app): app.flush() e = foo() x = app.fire(e, "b") - while app: + while len(app): app.flush() assert x.value == "Bar" diff -Nru circuits-3.1.0+ds1/tests/core/test_imports.py circuits-3.2.2/tests/core/test_imports.py --- circuits-3.1.0+ds1/tests/core/test_imports.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/core/test_imports.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,5 +1,4 @@ #!/usr/bin/env python - from circuits.core.components import BaseComponent diff -Nru circuits-3.1.0+ds1/tests/core/test_inheritence.py circuits-3.2.2/tests/core/test_inheritence.py --- circuits-3.1.0+ds1/tests/core/test_inheritence.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/core/test_inheritence.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,11 +1,11 @@ #!/usr/bin/env python - import pytest -from circuits import handler, Event, Component +from circuits import Component, Event, handler class test(Event): + """test Event""" diff -Nru circuits-3.1.0+ds1/tests/core/test_interface_query.py circuits-3.2.2/tests/core/test_interface_query.py --- circuits-3.1.0+ds1/tests/core/test_interface_query.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/core/test_interface_query.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,12 +1,9 @@ #!/usr/bin/env python - """Test Interface Query Test the capabilities of querying a Component class or instance for it's interface. That is it's event handlers it responds to. """ - - from circuits import Component diff -Nru circuits-3.1.0+ds1/tests/core/test_loader.py circuits-3.2.2/tests/core/test_loader.py --- circuits-3.1.0+ds1/tests/core/test_loader.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/core/test_loader.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,16 +1,13 @@ #!/usr/bin/env python - - -import pytest - - from os.path import dirname +import pytest from circuits import Event, Loader, Manager class test(Event): + """test Event""" diff -Nru circuits-3.1.0+ds1/tests/core/test_manager_repr.py circuits-3.2.2/tests/core/test_manager_repr.py --- circuits-3.1.0+ds1/tests/core/test_manager_repr.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/core/test_manager_repr.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,15 +1,10 @@ -# Module: test_manager_repr -# Date: 23rd February 2010 -# Author: James Mills, prologic at shortcircuit dot net dot au - """Manager Repr Tests Test Manager's representation string. """ - import os -from time import sleep from threading import current_thread +from time import sleep import pytest diff -Nru circuits-3.1.0+ds1/tests/core/test_memory_leaks.py circuits-3.2.2/tests/core/test_memory_leaks.py --- circuits-3.1.0+ds1/tests/core/test_memory_leaks.py 1970-01-01 00:00:00.000000000 +0000 +++ circuits-3.2.2/tests/core/test_memory_leaks.py 2021-10-19 16:23:49.000000000 +0000 @@ -0,0 +1,46 @@ +#!/usr/bin/env python +import pytest + +from circuits import Component, Event, handler + + +class call(Event): + + """call Event""" + success = True + + +class hello(Event): + + """hello Event""" + success = True + + +class App(Component): + @handler("call") + def _on_call(self): + x = yield self.call(hello()) + yield x.value + + def hello(self): + return "Hello World!" + + +@pytest.fixture +def app(request, manager, watcher): + app = App().register(manager) + assert watcher.wait("registered") + + def finalizer(): + app.unregister() + + request.addfinalizer(finalizer) + + return app + + +def test_done_handlers_dont_leak(manager, watcher, app): + manager.fire(call()) + manager.fire(call()) + assert watcher.wait("call_success") + assert "hello_done" not in app._handlers diff -Nru circuits-3.1.0+ds1/tests/core/test_new_filter.py circuits-3.2.2/tests/core/test_new_filter.py --- circuits-3.1.0+ds1/tests/core/test_new_filter.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/core/test_new_filter.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,11 +1,11 @@ #!/usr/bin/env python - import pytest from circuits import Component, Event class hello(Event): + """hello Event""" success = True diff -Nru circuits-3.1.0+ds1/tests/core/test_priority.py circuits-3.2.2/tests/core/test_priority.py --- circuits-3.1.0+ds1/tests/core/test_priority.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/core/test_priority.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,9 +1,9 @@ #!/usr/bin/python -i - -from circuits import handler, Event, Component, Manager +from circuits import Component, Event, Manager, handler class test(Event): + """test Event""" @@ -21,17 +21,18 @@ def test_2(self): return 2 + m = Manager() app = App() app.register(m) -while m: +while len(m): m.flush() def test_main(): v = m.fire(test()) - while m: + while len(m): m.flush() x = list(v) assert x == [3, 2, 0] diff -Nru circuits-3.1.0+ds1/tests/core/test_signals.py circuits-3.2.2/tests/core/test_signals.py --- circuits-3.1.0+ds1/tests/core/test_signals.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/core/test_signals.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,17 +1,13 @@ #!/usr/bin/env python - - -import pytest - - import os import sys -from time import sleep from errno import ESRCH -from signal import SIGTERM from os import kill, remove +from signal import SIGTERM from subprocess import Popen +from time import sleep +import pytest from . import signalapp @@ -59,11 +55,10 @@ kill(pid, SIGTERM) wait(pid) - f = open(signalfile, "r") - signal = f.read().strip() - f.close() + with open(signalfile, "r") as fd: + signal = fd.read().strip() - assert signal == str(SIGTERM) + assert int(signal) == int(SIGTERM) remove(pidfile) remove(signalfile) diff -Nru circuits-3.1.0+ds1/tests/core/test_timers.py circuits-3.2.2/tests/core/test_timers.py --- circuits-3.1.0+ds1/tests/core/test_timers.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/core/test_timers.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,87 +1,87 @@ -# Module: test_timers -# Date: 10th February 2010 -# Author: James Mills, prologic at shortcircuit dot net dot au -import time - """Timers Tests""" -import pytest from datetime import datetime, timedelta +from itertools import starmap +from operator import sub +from time import time + +import pytest + +from circuits import Component, Event, Timer, sleep +from circuits.six.moves import map, zip -from circuits import Event, Component, Timer +@pytest.fixture +def app(request, manager, watcher): + app = App().register(manager) + assert watcher.wait("registered") -def pytest_funcarg__app(request): - return request.cached_setup( - setup=lambda: setupapp(request), - teardown=lambda app: teardownapp(app), - scope="module" - ) + def finalizer(): + app.unregister() + assert watcher.wait("unregistered") + request.addfinalizer(finalizer) -def setupapp(request): - app = App() - app.start() return app -def teardownapp(app): - app.stop() +class single(Event): + """single Event""" -class test(Event): - """test Event""" + complete = True + + +class persistent(Event): + + """persistent Event""" + + complete = True class App(Component): - def __init__(self): - super(App, self).__init__() + def init(self): self.flag = False self.count = 0 self.timestamps = [] - def reset(self): - self.timestamps = [] - self.flag = False - self.count = 0 - - def test(self): - self.timestamps.append(time.time()) + def single(self): + self.timestamps.append(time()) self.count += 1 self.flag = True + def persistent(self, interval): + timer = Timer(interval, single(), persist=True) + timer.register(self) + + yield sleep(interval * 10) + + timer.unregister() + + +def test_single(app, watcher): + Timer(0.1, single()).register(app) + assert watcher.wait("single_complete") + assert app.flag + + +def test_persistent(app, watcher): + exponent = -1 + interval = 10.0 ** exponent + app.fire(persistent(interval)) + assert watcher.wait("persistent_complete") -def test_timer(app): - timer = Timer(0.1, test(), "timer") - timer.register(app) - assert pytest.wait_for(app, "flag") - app.reset() - - -def test_persistentTimer(app): - app.timestamps.append(time.time()) - timer = Timer(0.2, test(), "timer", persist=True) - timer.register(app) - - wait_res = pytest.wait_for(app, "count", 2) - assert app.count >= 2 - assert wait_res - delta = app.timestamps[1] - app.timestamps[0] - # Should be 0.1, but varies depending on timer precision and load - assert delta >= 0.08 and delta < 0.5 - delta = app.timestamps[2] - app.timestamps[1] - assert delta >= 0.08 and delta < 0.5 - app.reset() + xs = list(map(abs, starmap(sub, zip(app.timestamps, app.timestamps[1:])))) + avg = sum(xs) / len(xs) - timer.unregister() + assert round(avg, abs(exponent)) == interval -def test_datetime(app): +def test_datetime(app, watcher): now = datetime.now() d = now + timedelta(seconds=0.1) - timer = Timer(d, test(), "timer") - timer.register(app) - assert pytest.wait_for(app, "flag") - app.reset() + Timer(d, single()).register(app) + assert watcher.wait("single_complete") + assert app.flag diff -Nru circuits-3.1.0+ds1/tests/core/test_utils.py circuits-3.2.2/tests/core/test_utils.py --- circuits-3.1.0+ds1/tests/core/test_utils.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/core/test_utils.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,11 +1,11 @@ #!/usr/bin/env python - import sys from types import ModuleType from circuits import Component from circuits.core.utils import findchannel, findroot, findtype + FOO = """\ def foo(): return "Hello World!" @@ -18,6 +18,7 @@ class Base(Component): + """Base""" @@ -72,7 +73,7 @@ b.register(a) a.register(app) - while app: + while len(app): app.flush() root = findroot(b) @@ -84,7 +85,7 @@ app = App() (A() + B()).register(app) - while app: + while len(app): app.flush() a = findchannel(app, "a") @@ -96,7 +97,7 @@ app = App() (A() + B()).register(app) - while app: + while len(app): app.flush() a = findtype(app, A) diff -Nru circuits-3.1.0+ds1/tests/core/test_value.py circuits-3.2.2/tests/core/test_value.py --- circuits-3.1.0+ds1/tests/core/test_value.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/core/test_value.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,25 +1,28 @@ #!/usr/bin/python -i - +from types import TracebackType import pytest - -from circuits import handler, Event, Component +from circuits import Component, Event, handler class hello(Event): - "Hhllo Event" + + "Hello Event" class test(Event): + "test Event" class foo(Event): + "foo Event" class values(Event): + "values Event" complete = True @@ -58,70 +61,63 @@ @pytest.fixture -def app(request, manager, watcher): - app = App().register(manager) - watcher.wait("registered") +def app(request, simple_manager): + return App().register(simple_manager) - def finalizer(): - app.unregister() - watcher.wait("unregistered") - request.addfinalizer(finalizer) - - return app - - -def test_value(app, watcher): +def test_value(app, simple_manager): x = app.fire(hello()) - watcher.wait("hello") + simple_manager.run() assert "Hello World!" in x assert x.value == "Hello World!" -def test_nested_value(app, watcher): +def test_nested_value(app, simple_manager): x = app.fire(test()) - watcher.wait("test") + simple_manager.run() assert x.value == "Hello World!" assert str(x) == "Hello World!" -def test_value_notify(app, watcher): - x = app.fire(hello()) - x.notify = True +def test_value_notify(app, simple_manager): + ev = hello() + ev.notify = True + x = app.fire(ev) - watcher.wait("hello_value_changed") + simple_manager.run() assert "Hello World!" in x assert x.value == "Hello World!" assert app.value is x -def test_nested_value_notify(app, watcher): - x = app.fire(test()) - x.notify = True +def test_nested_value_notify(app, simple_manager): + ev = test() + ev.notify = True + x = app.fire(ev) - watcher.wait("hello_value_changed") + simple_manager.run() assert x.value == "Hello World!" assert str(x) == "Hello World!" assert app.value is x -def test_error_value(app, watcher): +def test_error_value(app, simple_manager): x = app.fire(foo()) - watcher.wait("foo") + simple_manager.run() etype, evalue, etraceback = x assert etype is Exception assert str(evalue) == "ERROR" - assert isinstance(etraceback, list) + assert isinstance(etraceback, TracebackType) -def test_multiple_values(app, watcher): +def test_multiple_values(app, simple_manager): v = app.fire(values()) - watcher.wait("values_complete") + simple_manager.run() assert isinstance(v.value, list) diff -Nru circuits-3.1.0+ds1/tests/core/test_worker_process.py circuits-3.2.2/tests/core/test_worker_process.py --- circuits-3.1.0+ds1/tests/core/test_worker_process.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/core/test_worker_process.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,17 +1,13 @@ -# Module: test_workers -# Date: 7th October 2008 -# Author: James Mills, prologic at shortcircuit dot net dot au - """Workers Tests""" -import pytest - from os import getpid -from circuits import task, Worker +import pytest + +from circuits import Worker, task -@pytest.fixture(scope="module") +@pytest.fixture def worker(request, manager): worker = Worker().register(manager) diff -Nru circuits-3.1.0+ds1/tests/core/test_worker_thread.py circuits-3.2.2/tests/core/test_worker_thread.py --- circuits-3.1.0+ds1/tests/core/test_worker_thread.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/core/test_worker_thread.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,31 +1,24 @@ -# Module: test_workers -# Date: 7th October 2008 -# Author: James Mills, prologic at shortcircuit dot net dot au - """Workers Tests""" + import pytest -from circuits import task, Worker +from circuits import Worker, task + +task.complete = True -@pytest.fixture(scope="module") -def worker(request): - worker = Worker() +@pytest.fixture +def worker(request, manager, watcher): + worker = Worker().register(manager) + assert watcher.wait("registered") def finalizer(): - worker.stop() + worker.unregister() + assert watcher.wait("unregistered") request.addfinalizer(finalizer) - if request.config.option.verbose: - from circuits import Debugger - Debugger().register(worker) - - waiter = pytest.WaitEvent(worker, "started") - worker.start() - assert waiter.wait() - return worker @@ -42,19 +35,17 @@ return a + b -def test(worker): - x = worker.fire(task(f)) - - assert pytest.wait_for(x, "result") +def test(manager, watcher, worker): + x = manager.fire(task(f)) + assert watcher.wait("task_complete") assert x.result assert x.value == 1000000 -def test_args(worker): - x = worker.fire(task(add, 1, 2)) - - assert pytest.wait_for(x, "result") +def test_args(manager, watcher, worker): + x = manager.fire(task(add, 1, 2)) + assert watcher.wait("task_complete") assert x.result assert x.value == 3 diff -Nru circuits-3.1.0+ds1/tests/__init__.py circuits-3.2.2/tests/__init__.py --- circuits-3.1.0+ds1/tests/__init__.py 2013-07-27 13:03:18.000000000 +0000 +++ circuits-3.2.2/tests/__init__.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,5 +1 @@ -# Package: tests -# Date: 10 February 2010 -# Author: James Mills, prologic at shortcircuit dot net dot au - """circuits tests""" Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/__init__.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/__init__.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/io/__init__.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/io/__init__.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/io/__pycache__/__init__.cpython-32.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/io/__pycache__/__init__.cpython-32.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/io/__pycache__/__init__.cpython-33.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/io/__pycache__/__init__.cpython-33.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/io/__pycache__/__init__.cpython-34.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/io/__pycache__/__init__.cpython-34.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/io/__pycache__/test_file.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/io/__pycache__/test_file.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/io/__pycache__/test_file.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/io/__pycache__/test_file.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/io/__pycache__/test_file.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/io/__pycache__/test_file.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/io/__pycache__/test_file.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/io/__pycache__/test_file.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/io/__pycache__/test_file.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/io/__pycache__/test_file.cpython-34-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/io/__pycache__/test_notify.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/io/__pycache__/test_notify.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/io/__pycache__/test_notify.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/io/__pycache__/test_notify.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/io/__pycache__/test_notify.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/io/__pycache__/test_notify.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/io/__pycache__/test_notify.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/io/__pycache__/test_notify.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/io/__pycache__/test_notify.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/io/__pycache__/test_notify.cpython-34-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/io/__pycache__/test_process.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/io/__pycache__/test_process.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/io/__pycache__/test_process.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/io/__pycache__/test_process.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/io/__pycache__/test_process.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/io/__pycache__/test_process.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/io/__pycache__/test_process.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/io/__pycache__/test_process.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/io/__pycache__/test_process.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/io/__pycache__/test_process.cpython-34-PYTEST.pyc differ diff -Nru circuits-3.1.0+ds1/tests/io/test_file.py circuits-3.2.2/tests/io/test_file.py --- circuits-3.1.0+ds1/tests/io/test_file.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/io/test_file.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,13 +1,13 @@ #!/usr/bin/env python +from io import BytesIO import pytest -if pytest.PLATFORM == "win32": - pytest.skip("Unsupported Platform") -from io import BytesIO -from circuits.io import File from circuits import Component -from circuits.io.events import write, close +from circuits.io import File +from circuits.io.events import close, write + +pytestmark = pytest.mark.skipif(pytest.PLATFORM == 'win32', reason='Unsupported Platform') class FileApp(Component): diff -Nru circuits-3.1.0+ds1/tests/io/test_notify.py circuits-3.2.2/tests/io/test_notify.py --- circuits-3.1.0+ds1/tests/io/test_notify.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/io/test_notify.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,41 +1,156 @@ #!/usr/bin/env python - +import os import pytest -pytest.importorskip("pyinotify") -from circuits.io.notify import Notify from circuits import Component, handler +try: + from circuits.io.notify import Notify +except ImportError: + pytest.importorskip("pyinotify") + class App(Component): def init(self, *args, **kwargs): - self.created = False + self.created_status = False @handler('created', channel='notify') def created(self, *args, **kwargs): - self.created = True + self.created_status = True + +class Creator: -def test_notify(manager, watcher, tmpdir): + def __init__(self, app, watcher, tmpdir, timeout=0.5): + self.app = app + self.watcher = watcher + self.tmpdir = tmpdir + self.timeout = timeout + + def create(self, *targets, **kwargs): + assert_created = kwargs.get('assert_created', True) + target = os.path.join(*targets) + self.tmpdir.ensure(target, dir=kwargs.get('dir', False)) + self.watcher.wait("created", timeout=self.timeout) + assert self.app.created_status == assert_created + # Reset for next call + self.watcher.clear() + self.app.created_status = False + + +@pytest.fixture() +def app(manager, watcher): app = App().register(manager) - notify = Notify().register(app) + yield app + # Unregister application on test end + app.unregister() + watcher.wait("unregistered") + +@pytest.fixture() +def notify(app, watcher): + notify = Notify().register(app) watcher.wait("registered") + return notify + + +@pytest.fixture() +def creator(app, watcher, tmpdir): + return Creator(app, watcher, tmpdir) + +# TESTS + + +def test_notify_file(notify, tmpdir, creator): + + # Add a path to the watch notify.add_path(str(tmpdir)) - tmpdir.ensure("helloworld.txt") - watcher.wait("created") - assert app.created - app.created = False + # Test creation and detection of a file + creator.create("helloworld.txt") + # Remove the path from the watch notify.remove_path(str(tmpdir)) - tmpdir.ensure("helloworld2.txt") - watcher.wait("created") - assert not app.created + # Test creation and NON detection of a file + creator.create("helloworld2.txt", assert_created=False) - app.unregister() - watcher.wait("unregistered") + +def test_notify_dir(notify, tmpdir, creator): + + # Add a path to the watch + notify.add_path(str(tmpdir)) + + # Test creation and detection of a file + creator.create("hellodir", dir=True) + + # Remove the path from the watch + notify.remove_path(str(tmpdir)) + + # Test creation and NON detection of a file + creator.create("hellodir2", dir=True, assert_created=False) + + +def test_notify_subdir_recursive(notify, tmpdir, creator): + + # Add a subdir + subdir = "sub" + tmpdir.ensure(subdir, dir=True) + + # Add a path to the watch + notify.add_path(str(tmpdir), recursive=True) + + # Test creation and detection of a file in subdir + creator.create(subdir, "helloworld.txt", assert_created=True) + + +@pytest.mark.xfail(reason="pyinotify issue #133") +def test_notify_subdir_recursive_remove_path(notify, tmpdir, creator): + # This is logically the second part of the above test, + # but pyinotify fails on rm_watch(...., rec=True) + + # Add a subdir + subdir = "sub" + tmpdir.ensure(subdir, dir=True) + + # Add a path to the watch + notify.add_path(str(tmpdir), recursive=True) + + # Remove the path from the watch + notify.remove_path(str(tmpdir), recursive=True) + + # Test creation and NON detection of a file in subdir + creator.create(subdir, "helloworld2.txt", assert_created=False) + + +def test_notify_subdir_recursive_auto_add(notify, tmpdir, creator): + + # Add a path to the watch + notify.add_path(str(tmpdir), recursive=True) + + # Create/detect subdirectory + subdir = "sub" + creator.create(subdir, dir=True, assert_created=True) + + # Create/detect file in subdirectory + creator.create(subdir, "helloworld.txt", assert_created=True) + + # Skip notify.remove_path() because pyinotify is broken + + +def test_notify_subdir_recursive_no_auto_add(notify, tmpdir, creator): + + # Add a path to the watch + notify.add_path(str(tmpdir), recursive=True, auto_add=False) + + # Create/detect subdirectory + subdir = "sub" + creator.create(subdir, dir=True, assert_created=True) + + # Create, not detect file in subdirectory + creator.create(subdir, "helloworld.txt", assert_created=False) + + # Skip notify.remove_path() because pyinotify is broken diff -Nru circuits-3.1.0+ds1/tests/io/test_process.py circuits-3.2.2/tests/io/test_process.py --- circuits-3.1.0+ds1/tests/io/test_process.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/io/test_process.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,11 +1,11 @@ #!/usr/bin/env python - import pytest -if pytest.PLATFORM == "win32": - pytest.skip("Unsupported Platform") from circuits.io import Process, write +if pytest.PLATFORM == "win32": + pytest.skip("Unsupported Platform") + def test(manager, watcher): p = Process(["echo", "Hello World!"]).register(manager) @@ -14,7 +14,7 @@ p.start() assert watcher.wait("started", p.channel) - assert watcher.wait("stopped", p.channel) + assert watcher.wait("terminated", p.channel) s = p.stdout.getvalue() assert s == b"Hello World!\n" @@ -23,7 +23,8 @@ def test2(manager, watcher, tmpdir): foo = tmpdir.ensure("foo.txt") - p = Process(["cat - > {0:s}".format(str(foo))], shell=True).register(manager) + p = Process( + ["cat - > {0:s}".format(str(foo))], shell=True).register(manager) assert watcher.wait("registered") p.start() @@ -38,3 +39,30 @@ with foo.open("r") as f: assert f.read() == "Hello World!" + + +def test_two_procs(manager, watcher): + p1 = Process(["echo", "1"]).register(manager) + p2 = Process("echo 2 ; sleep 1", shell=True).register(manager) + + p1.start() + p2.start() + + assert watcher.wait("terminated", p1.channel) + assert p1._terminated + assert not p2._terminated + assert not p2._stdout_closed + assert not p2._stderr_closed + + watcher.clear() # Get rid of first terminated() + + s1 = p1.stdout.getvalue() + assert s1 == b"1\n" + + assert watcher.wait("terminated", p2.channel) + assert p2._terminated + assert p2._stdout_closed + assert p2._stderr_closed + + s2 = p2.stdout.getvalue() + assert s2 == b"2\n" diff -Nru circuits-3.1.0+ds1/tests/main.py circuits-3.2.2/tests/main.py --- circuits-3.1.0+ds1/tests/main.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/main.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,29 +0,0 @@ -#!/usr/bin/env python - -import sys -from types import ModuleType -from os.path import abspath, dirname -from subprocess import Popen, STDOUT - - -def importable(module): - try: - m = __import__(module, globals(), locals()) - return type(m) is ModuleType - except ImportError: - return False - - -def main(): - cmd = ["py.test", "-r", "fsxX", "--ignore=tmp"] - - if importable("pytest_cov"): - cmd.append("--cov=circuits") - cmd.append("--cov-report=html") - - cmd.append(dirname(abspath(__file__))) - - raise SystemExit(Popen(cmd, stdout=sys.stdout, stderr=STDOUT).wait()) - -if __name__ == "__main__": - main() Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/main.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/main.pyc differ diff -Nru circuits-3.1.0+ds1/tests/net/cert.pem circuits-3.2.2/tests/net/cert.pem --- circuits-3.1.0+ds1/tests/net/cert.pem 1970-01-01 00:00:00.000000000 +0000 +++ circuits-3.2.2/tests/net/cert.pem 2021-10-19 16:23:49.000000000 +0000 @@ -0,0 +1,49 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEAw56dcICp8bf9GHCIoKKXjnGwRTHh3Ibm6FxuE+b0Pm/zX48d +pWEyhw/cGpiTL860Bmpu8K/zEELRPNBU0HMbSqXYX0kODStgXzrsJDy4rPUuzeGN +8fDLH/8/2gIaIqnLoVhkOoF2d4cnTH96j/Q7z2QeCftHLzVovPqmucpxgHPZYZ8M +XYlP4MvN0PAskaON+AQxayNUEVGUDEj9w1w7kwR0D70l3AJL+yHHeJpqF4TRsXGF +/mi8IGBAaWRXerK2qt6X09IbmCyS+5GTOt9BRuhfRgfkXDLnrJKa1ymSVl3E3y7Y +ViXz/QT8UssjYW61E0E9Q0SZh5DkOSnr9a1J9QIDAQABAoIBAAHZwkuKLBFpWC+f +AOvkHeLvGGfPLP/VFuIj3ba6fJ0KmhbRV8p0vPGiKMbnopzVK8bTwvDr+TSyLSCS +J/tA24U9RGrCWiutuV+tQwakvGqGd0bjV2Bukr1ewM/jLTQevxprp6cWCnTfBnQm +0JYEDXzMyav2gJnlu3PuOx2O2LwKWEqERFWEj2pvitD1LGgw1rN0qjssXtlhuBtr +xfxECyhtfa1fyD9Dx9lKK14vJMLq6027DLsFf5qOFmTr8399SnuPwxvldzNzJaVB +9nLQHVNR59e292UsaPAPhKOpH2bZTDy3MJrfzJHe5p59JcU9vSJsOkluaQXP2ivq +H2d9hwECgYEA7IYcTv9Tf5joxUDhWcjjaKND3Bpsc3f1Qo9jQuFBlZoW441gZQpr +d1W9DUQ86tLRHNs6M4lJAGzs2fLweGgjNesn0+Q+sUDFnpW1sra89ucK81Xp8Ikn +v7eKhp8an6daMGzX1dvQGRSEePPiNLvym0Y46XF6P4pN6ArigM5kceUCgYEA07o/ +f4V6y72U5AVToKwop6/aEAOqeyCO51BaafAhfiOaHV1smZLRAMwy6E3BB4BKvNOX +wEKnu63MMgUsrcFORpcl+O2v3ZOK1oByS4z8PwvzPQYUaQf5xKqFUAQhgLvwI049 +sLJSyA0OWYGwq5h5d+BKGVP64vs/sE2Jw6yuNtECgYBjTU73T7VDvfQEVOAH7RKk +7N7huupLdFKxVjgLbT02zRHNCZ8t7Lj/yixsNHkK8eW/or8Fwh63IgQy4Q9azgXy +bj8zdAFqM9KEaUB2vsgJNSlgznJAfaUFlc6ABK6N1xpDeH8Jl5b/4KBZk7MmBr6t +uEbOo8j6gluBD4jXIVAEjQKBgHy8U0B7kPaLQDZ99ODJzEHOVjftEPjtG4OnUTzs +Xa8Epnz6V0q6tis0IiG9/STALkfEmLiKDGuDXrNxXPsY0VbBIXvf/CYcEEWC8tMT +wmAaWDjxZgDi1AFLPLMBXAONtVH3fFynEiINnxCYWU8eyyEWoFD/quUihEkHxUvk +ZdahAoGBANz6W+VbTAK5iNq81CBSIvCROi7OXObdyVlbb0W5ehB7hWCAelmt0KCt +D/ZlSr4IC6ztq7XsgCitP7GROA+yi/7Pi6dWO2hkJbe/iCDgvvaGTNWbZQLccFBJ +XIAPPkyssmKgYVGtJfBHLxj7FWB7TMwXmLOuALcyCPJe/HDcFySQ +-----END RSA PRIVATE KEY----- +-----BEGIN CERTIFICATE----- +MIIDoTCCAokCFC9S/3ETWtegvP0F5DrxSUoPaRTgMA0GCSqGSIb3DQEBCwUAMIGM +MQswCQYDVQQGEwJBVTETMBEGA1UECAwKUXVlZW5zbGFuZDERMA8GA1UEBwwIQnJp +c2JhbmUxFTATBgNVBAoMDFNob3J0Q2lyY3VpdDEUMBIGA1UEAwwLSmFtZXMgTWls +bHMxKDAmBgkqhkiG9w0BCQEWGWFkbWluQHNob3J0Y2lyY3VpdC5uZXQuYXUwHhcN +MjAxMjE0MjMzMTM2WhcNMzAxMjEyMjMzMTM2WjCBjDELMAkGA1UEBhMCQVUxEzAR +BgNVBAgMClF1ZWVuc2xhbmQxETAPBgNVBAcMCEJyaXNiYW5lMRUwEwYDVQQKDAxT +aG9ydENpcmN1aXQxFDASBgNVBAMMC0phbWVzIE1pbGxzMSgwJgYJKoZIhvcNAQkB +FhlhZG1pbkBzaG9ydGNpcmN1aXQubmV0LmF1MIIBIjANBgkqhkiG9w0BAQEFAAOC +AQ8AMIIBCgKCAQEAw56dcICp8bf9GHCIoKKXjnGwRTHh3Ibm6FxuE+b0Pm/zX48d +pWEyhw/cGpiTL860Bmpu8K/zEELRPNBU0HMbSqXYX0kODStgXzrsJDy4rPUuzeGN +8fDLH/8/2gIaIqnLoVhkOoF2d4cnTH96j/Q7z2QeCftHLzVovPqmucpxgHPZYZ8M +XYlP4MvN0PAskaON+AQxayNUEVGUDEj9w1w7kwR0D70l3AJL+yHHeJpqF4TRsXGF +/mi8IGBAaWRXerK2qt6X09IbmCyS+5GTOt9BRuhfRgfkXDLnrJKa1ymSVl3E3y7Y +ViXz/QT8UssjYW61E0E9Q0SZh5DkOSnr9a1J9QIDAQABMA0GCSqGSIb3DQEBCwUA +A4IBAQAUr7fRHFMy8MSQbYj4PQdu4mIA+beIrEN8+wnMgdONv4o30aetilC55ffN +c94TlezlpzX6aHrRJ0jiEOW2PbjVgayMG2um7QICLjqwyrK+18NCwEQxDthX/wXv +KFTMHrDo5FSLRLxe2m3wNT38EaVM0NHMwai71ehEnLCYJo9shw/PphXkXONIltuS +lGOEu/mvI7PA/2fJUS8U+3Fdr2K0i22c7JfNvr8gu2mkydsNMxDnKnLVq6s8QIz5 +lzezCkqIpNfJT8E2KlIsAFQXE6awrAcc7Fcc9/PbwrNOB7x7DVwz7GGb5vSTvrMg +dXTYnVO0WJFrlipOjt3DnazbRRtN +-----END CERTIFICATE----- Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/net/client.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/net/client.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/net/__init__.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/net/__init__.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/net/__pycache__/client.cpython-32.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/net/__pycache__/client.cpython-32.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/net/__pycache__/client.cpython-33.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/net/__pycache__/client.cpython-33.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/net/__pycache__/client.cpython-34.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/net/__pycache__/client.cpython-34.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/net/__pycache__/__init__.cpython-32.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/net/__pycache__/__init__.cpython-32.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/net/__pycache__/__init__.cpython-33.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/net/__pycache__/__init__.cpython-33.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/net/__pycache__/__init__.cpython-34.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/net/__pycache__/__init__.cpython-34.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/net/__pycache__/server.cpython-32.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/net/__pycache__/server.cpython-32.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/net/__pycache__/server.cpython-33.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/net/__pycache__/server.cpython-33.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/net/__pycache__/server.cpython-34.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/net/__pycache__/server.cpython-34.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/net/__pycache__/test_client.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/net/__pycache__/test_client.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/net/__pycache__/test_client.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/net/__pycache__/test_client.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/net/__pycache__/test_client.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/net/__pycache__/test_client.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/net/__pycache__/test_client.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/net/__pycache__/test_client.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/net/__pycache__/test_client.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/net/__pycache__/test_client.cpython-34-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/net/__pycache__/test_pipe.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/net/__pycache__/test_pipe.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/net/__pycache__/test_pipe.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/net/__pycache__/test_pipe.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/net/__pycache__/test_pipe.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/net/__pycache__/test_pipe.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/net/__pycache__/test_pipe.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/net/__pycache__/test_pipe.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/net/__pycache__/test_pipe.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/net/__pycache__/test_pipe.cpython-34-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/net/__pycache__/test_poller_reuse.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/net/__pycache__/test_poller_reuse.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/net/__pycache__/test_poller_reuse.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/net/__pycache__/test_poller_reuse.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/net/__pycache__/test_poller_reuse.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/net/__pycache__/test_poller_reuse.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/net/__pycache__/test_poller_reuse.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/net/__pycache__/test_poller_reuse.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/net/__pycache__/test_poller_reuse.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/net/__pycache__/test_poller_reuse.cpython-34-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/net/__pycache__/test_tcp.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/net/__pycache__/test_tcp.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/net/__pycache__/test_tcp.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/net/__pycache__/test_tcp.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/net/__pycache__/test_tcp.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/net/__pycache__/test_tcp.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/net/__pycache__/test_tcp.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/net/__pycache__/test_tcp.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/net/__pycache__/test_tcp.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/net/__pycache__/test_tcp.cpython-34-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/net/__pycache__/test_udp.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/net/__pycache__/test_udp.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/net/__pycache__/test_udp.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/net/__pycache__/test_udp.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/net/__pycache__/test_udp.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/net/__pycache__/test_udp.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/net/__pycache__/test_udp.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/net/__pycache__/test_udp.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/net/__pycache__/test_udp.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/net/__pycache__/test_udp.cpython-34-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/net/__pycache__/test_unix.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/net/__pycache__/test_unix.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/net/__pycache__/test_unix.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/net/__pycache__/test_unix.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/net/__pycache__/test_unix.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/net/__pycache__/test_unix.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/net/__pycache__/test_unix.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/net/__pycache__/test_unix.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/net/__pycache__/test_unix.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/net/__pycache__/test_unix.cpython-34-PYTEST.pyc differ diff -Nru circuits-3.1.0+ds1/tests/net/server.py circuits-3.2.2/tests/net/server.py --- circuits-3.1.0+ds1/tests/net/server.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/net/server.py 2021-10-19 16:23:49.000000000 +0000 @@ -6,9 +6,7 @@ channel = "server" - def __init__(self): - super(Server, self).__init__() - + def init(self): self.data = "" self.host = None self.port = None Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/net/server.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/net/server.pyc differ diff -Nru circuits-3.1.0+ds1/tests/net/test_client.py circuits-3.2.2/tests/net/test_client.py --- circuits-3.1.0+ds1/tests/net/test_client.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/net/test_client.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,5 +1,4 @@ #!/usr/bin/env python - from socket import gaierror diff -Nru circuits-3.1.0+ds1/tests/net/test_pipe.py circuits-3.2.2/tests/net/test_pipe.py --- circuits-3.1.0+ds1/tests/net/test_pipe.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/net/test_pipe.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,19 +1,18 @@ #!/usr/bin/env python - import pytest -if pytest.PLATFORM == "win32": - pytest.skip("Unsupported Platform") from circuits import Manager -from circuits.net.sockets import Pipe from circuits.core.pollers import Select from circuits.net.events import close, write +from circuits.net.sockets import Pipe from .client import Client +pytestmark = pytest.mark.skipif(pytest.PLATFORM == 'win32', reason='Unsupported Platform') + def pytest_generate_tests(metafunc): - metafunc.addcall(funcargs={"Poller": Select}) + metafunc.parametrize("Poller", [Select]) def test_pipe(Poller): diff -Nru circuits-3.1.0+ds1/tests/net/test_poller_reuse.py circuits-3.2.2/tests/net/test_poller_reuse.py --- circuits-3.1.0+ds1/tests/net/test_poller_reuse.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/net/test_poller_reuse.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,9 +1,8 @@ #!/usr/bin/env python - from circuits import Manager -from circuits.core.utils import findtype from circuits.core.pollers import BasePoller, Poller -from circuits.net.sockets import TCPServer, TCPClient +from circuits.core.utils import findtype +from circuits.net.sockets import TCPClient, TCPServer def test(): diff -Nru circuits-3.1.0+ds1/tests/net/test_server.py circuits-3.2.2/tests/net/test_server.py --- circuits-3.1.0+ds1/tests/net/test_server.py 1970-01-01 00:00:00.000000000 +0000 +++ circuits-3.2.2/tests/net/test_server.py 2021-10-19 16:23:49.000000000 +0000 @@ -0,0 +1,29 @@ +from circuits.net.sockets import BUFSIZE +from circuits.web.servers import BaseServer + + +class MockClass(BaseServer): + pass + + +def test_dynamic_bufsize_in_baseserver(): + bufsize = 10000 + try: + # Assert when we set BUFSIZE ourselves + mock = MockClass(bind="0.0.0.0:1234", bufsize=bufsize) + # that it will be set to our given value + assert bufsize == mock.server._bufsize + finally: + mock.server.unregister() + mock.stop() + + +def test_constant_bufsize_in_baseserver(): + try: + # Assert when we dont set BUFSIZE ourself + mock = MockClass(bind="0.0.0.0:1235") + # that it will be set to the constant default value + assert mock.server._bufsize == BUFSIZE + finally: + mock.server.unregister() + mock.stop() diff -Nru circuits-3.1.0+ds1/tests/net/test_socket_options.py circuits-3.2.2/tests/net/test_socket_options.py --- circuits-3.1.0+ds1/tests/net/test_socket_options.py 1970-01-01 00:00:00.000000000 +0000 +++ circuits-3.2.2/tests/net/test_socket_options.py 2021-10-19 16:23:49.000000000 +0000 @@ -0,0 +1,13 @@ +import pytest + +from circuits.net.sockets import TCPServer + +try: + from socket import SOL_SOCKET, SO_REUSEPORT +except ImportError: + pytestmark = pytest.mark.skip(reason='Missing SO_REUSEPORT') + + +def test_socket_options_server(): + s = TCPServer(('0.0.0.0', 8090), socket_options=[(SOL_SOCKET, SO_REUSEPORT, 1)]) + assert s._sock.getsockopt(SOL_SOCKET, SO_REUSEPORT) == 1 diff -Nru circuits-3.1.0+ds1/tests/net/test_tcp.py circuits-3.2.2/tests/net/test_tcp.py --- circuits-3.1.0+ds1/tests/net/test_tcp.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/net/test_tcp.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,20 +1,76 @@ #!/usr/bin/env python +import os.path +import select +from socket import ( + AF_INET, AF_INET6, EAI_NODATA, EAI_NONAME, SOCK_STREAM, + error as SocketError, has_ipv6, socket, +) +from ssl import wrap_socket as sslsocket import pytest +from tests.conftest import WaitEvent -import select -from socket import error as SocketError -from socket import EAI_NODATA, EAI_NONAME -from socket import socket, AF_INET, AF_INET6, SOCK_STREAM, has_ipv6 - -from circuits import Manager +from circuits import Debugger, Manager +from circuits.core.pollers import EPoll, KQueue, Poll, Select from circuits.net.events import close, connect, write -from circuits.core.pollers import Select, Poll, EPoll, KQueue -from circuits.net.sockets import TCPServer, TCP6Server, TCPClient, TCP6Client +from circuits.net.sockets import TCP6Client, TCP6Server, TCPClient, TCPServer from .client import Client from .server import Server +CERT_FILE = os.path.join(os.path.dirname(__file__), "cert.pem") + + +class TestClient(object): + + def __init__(self, ipv6=False): + self._sockname = None + + self.sock = socket( + AF_INET6 if ipv6 + else AF_INET, + SOCK_STREAM + ) + + self.ssock = sslsocket(self.sock) + + @property + def sockname(self): + return self._sockname + + def connect(self, host, port): + self.ssock.connect_ex((host, port)) + self._sockname = self.ssock.getsockname() + + def send(self, data): + self.ssock.send(data) + + def recv(self, buflen=4069): + return self.ssock.recv(buflen) + + def disconnect(self): + try: + self.ssock.shutdown(2) + except SocketError: + pass + + try: + self.ssock.close() + except SocketError: + pass + + +@pytest.fixture +def client(request, ipv6): + client = TestClient(ipv6=ipv6) + + def finalizer(): + client.disconnect() + + request.addfinalizer(finalizer) + + return client + def wait_host(server): def checker(obj, attr): @@ -22,23 +78,24 @@ assert pytest.wait_for(server, ("host", "port"), checker) -def _pytest_generate_tests(metafunc, ipv6): - metafunc.addcall(funcargs={"Poller": Select, "ipv6": ipv6}) +def pytest_generate_tests(metafunc): + ipv6 = [False] + if has_ipv6: + ipv6.append(True) - if hasattr(select, "poll"): - metafunc.addcall(funcargs={"Poller": Poll, "ipv6": ipv6}) + for ipv6 in ipv6: + poller = [(Select, ipv6)] - if hasattr(select, "epoll"): - metafunc.addcall(funcargs={"Poller": EPoll, "ipv6": ipv6}) + if hasattr(select, "poll"): + poller.append((Poll, ipv6)) - if hasattr(select, "kqueue"): - metafunc.addcall(funcargs={"Poller": KQueue, "ipv6": ipv6}) + if hasattr(select, "epoll"): + poller.append((EPoll, ipv6)) + if hasattr(select, "kqueue"): + poller.append((KQueue, ipv6)) -def pytest_generate_tests(metafunc): - _pytest_generate_tests(metafunc, ipv6=False) - if has_ipv6: - _pytest_generate_tests(metafunc, ipv6=True) + metafunc.parametrize('Poller,ipv6', poller) def test_tcp_basic(Poller, ipv6): @@ -82,10 +139,43 @@ m.stop() +def test_tcps_basic(manager, watcher, client, Poller, ipv6): + poller = Poller().register(manager) + + if ipv6: + tcp_server = TCP6Server(("::1", 0), secure=True, certfile=CERT_FILE) + else: + tcp_server = TCPServer(0, secure=True, certfile=CERT_FILE) + + server = Server() + tcp_server + + server.register(manager) + + try: + watcher.wait("ready", "server") + + client.connect(server.host, server.port) + assert watcher.wait("connect", "server") + assert client.recv() == b"Ready" + + client.send(b"foo") + assert watcher.wait("read", "server") + assert client.recv() == b"foo" + + client.disconnect() + assert watcher.wait("disconnect", "server") + + server.fire(close()) + assert watcher.wait("closed", "server") + finally: + poller.unregister() + server.unregister() + + def test_tcp_reconnect(Poller, ipv6): - ### XXX: Apparently this doesn't work on Windows either? - ### XXX: UPDATE: Apparently Broken on Windows + Python 3.2 - ### TODO: Need to look into this. Find out why... + # XXX: Apparently this doesn't work on Windows either? + # XXX: UPDATE: Apparently Broken on Windows + Python 3.2 + # TODO: Need to look into this. Find out why... if pytest.PLATFORM == "win32" and pytest.PYVER[:2] >= (3, 2): pytest.skip("Broken on Windows on Python 3.2") @@ -144,22 +234,18 @@ def test_tcp_connect_closed_port(Poller, ipv6): - ### FIXME: This test is wrong. - ### We need to figure out the sequence of events on Windows - ### for this scenario. I think if you attempt to connect to - ### a shutdown listening socket (tcp server) you should get - ### an error event as response. if pytest.PLATFORM == "win32": pytest.skip("Broken on Windows") - m = Manager() + Poller() + m = Manager() + Poller() + Debugger() + if ipv6: tcp_server = TCP6Server(("::1", 0)) - tcp_client = TCP6Client() + tcp_client = TCP6Client(connect_timeout=1) else: tcp_server = TCPServer(0) - tcp_client = TCPClient() + tcp_client = TCPClient(connect_timeout=1) server = Server() + tcp_server client = Client() + tcp_client @@ -178,16 +264,11 @@ # 1st connect client.fire(connect(host, port)) - assert pytest.wait_for(client, "connected") - assert isinstance(client.error, SocketError) - - client.fire(write(b"foo")) - assert pytest.wait_for(client, "disconnected") - - client.disconnected = False - client.fire(write(b"foo")) - assert pytest.wait_for(client, "disconnected", timeout=1.0) is None + waiter = WaitEvent(m, "unreachable", channel='client') + assert waiter.wait() finally: + server.unregister() + client.unregister() m.stop() @@ -226,7 +307,7 @@ assert pytest.wait_for(server, "connected") assert pytest.wait_for(client, "data", b"Ready") - #assert server.client[1] == bind_port + # assert server.client[1] == bind_port client.fire(write(b"foo")) assert pytest.wait_for(server, "data", b"foo") @@ -241,27 +322,27 @@ m.stop() -def test_tcp_lookup_failure(Poller, ipv6): - m = Manager() + Poller() +def test_tcp_lookup_failure(manager, watcher, Poller, ipv6): + poller = Poller().register(manager) if ipv6: tcp_client = TCP6Client() else: tcp_client = TCPClient() - client = Client() + tcp_client - client.register(m) - - m.start() + client = Client() + tcp_client + client.register(manager) try: - assert pytest.wait_for(client, "ready") + assert watcher.wait("ready", "client") + + client.fire(connect("foo.bar.baz", 1234)) + assert watcher.wait("error", "client") - client.fire(connect("foo", 1234)) - assert pytest.wait_for(client, "error", lambda obj, attr: isinstance(getattr(obj, attr), SocketError)) if pytest.PLATFORM == "win32": assert client.error.errno == 11004 else: assert client.error.errno in (EAI_NODATA, EAI_NONAME,) finally: - m.stop() + poller.unregister() + client.unregister() diff -Nru circuits-3.1.0+ds1/tests/net/test_udp.py circuits-3.2.2/tests/net/test_udp.py --- circuits-3.1.0+ds1/tests/net/test_udp.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/net/test_udp.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,14 +1,13 @@ #!/usr/bin/env python +import select +import socket import pytest -import socket -import select - from circuits import Manager +from circuits.core.pollers import EPoll, KQueue, Poll, Select from circuits.net.events import close, write -from circuits.core.pollers import Select, Poll, EPoll, KQueue -from circuits.net.sockets import UDPServer, UDPClient, UDP6Server, UDP6Client +from circuits.net.sockets import UDP6Client, UDP6Server, UDPClient, UDPServer from .client import Client from .server import Server @@ -20,23 +19,24 @@ assert pytest.wait_for(server, ("host", "port"), checker) -def _pytest_generate_tests(metafunc, ipv6): - metafunc.addcall(funcargs={"Poller": Select, "ipv6": ipv6}) +def pytest_generate_tests(metafunc): + ipv6 = [False] + if socket.has_ipv6: + ipv6.append(True) - if hasattr(select, "poll"): - metafunc.addcall(funcargs={"Poller": Poll, "ipv6": ipv6}) + for ipv6 in ipv6: + poller = [(Select, ipv6)] - if hasattr(select, "epoll"): - metafunc.addcall(funcargs={"Poller": EPoll, "ipv6": ipv6}) + if hasattr(select, "poll"): + poller.append((Poll, ipv6)) - if hasattr(select, "kqueue"): - metafunc.addcall(funcargs={"Poller": KQueue, "ipv6": ipv6}) + if hasattr(select, "epoll"): + poller.append((EPoll, ipv6)) + if hasattr(select, "kqueue"): + poller.append((KQueue, ipv6)) -def pytest_generate_tests(metafunc): - _pytest_generate_tests(metafunc, ipv6=False) - if socket.has_ipv6: - _pytest_generate_tests(metafunc, ipv6=True) + metafunc.parametrize('Poller,ipv6', poller) def test_basic(Poller, ipv6): diff -Nru circuits-3.1.0+ds1/tests/net/test_unix.py circuits-3.2.2/tests/net/test_unix.py --- circuits-3.1.0+ds1/tests/net/test_unix.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/net/test_unix.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,43 +1,49 @@ #!/usr/bin/env python - -import pytest - import os -import sys import select +import sys +import tempfile -if sys.platform in ("win32", "cygwin"): - pytest.skip("Test Not Applicable on Windows") +import pytest +from pytest import fixture from circuits import Manager -from circuits.net.sockets import close, connect, write -from circuits.net.sockets import UNIXServer, UNIXClient -from circuits.core.pollers import Select, Poll, EPoll, KQueue +from circuits.core.pollers import EPoll, KQueue, Poll, Select +from circuits.net.sockets import UNIXClient, UNIXServer, close, connect, write from .client import Client from .server import Server +if sys.platform in ("win32", "cygwin"): + pytest.skip("Test Not Applicable on Windows") + + +@fixture +def tmpfile(request): + tmpdir = tempfile.mkdtemp() + filename = os.path.join(tmpdir, "test.sock") + + return filename + def pytest_generate_tests(metafunc): - metafunc.addcall(funcargs={"Poller": Select}) + poller = [Select] if hasattr(select, "poll"): - metafunc.addcall(funcargs={"Poller": Poll}) + poller.append(Poll) if hasattr(select, "epoll"): - metafunc.addcall(funcargs={"Poller": EPoll}) + poller.append(EPoll) if hasattr(select, "kqueue"): - metafunc.addcall(funcargs={"Poller": KQueue}) + poller.append(KQueue) + metafunc.parametrize('Poller', poller) -def test_unix(tmpdir, Poller): +def test_unix(tmpfile, Poller): m = Manager() + Poller() - sockpath = tmpdir.ensure("test.sock") - filename = str(sockpath) - - server = Server() + UNIXServer(filename) + server = Server() + UNIXServer(tmpfile) client = Client() + UNIXClient() server.register(m) @@ -49,7 +55,7 @@ assert pytest.wait_for(server, "ready") assert pytest.wait_for(client, "ready") - client.fire(connect(filename)) + client.fire(connect(tmpfile)) assert pytest.wait_for(client, "connected") assert pytest.wait_for(server, "connected") assert pytest.wait_for(client, "data", b"Ready") @@ -65,4 +71,3 @@ assert pytest.wait_for(server, "closed") finally: m.stop() - os.remove(filename) Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/node/__pycache__/test_node.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/node/__pycache__/test_node.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/node/__pycache__/test_node.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/node/__pycache__/test_node.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/node/__pycache__/test_node.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/node/__pycache__/test_node.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/node/__pycache__/test_node.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/node/__pycache__/test_node.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/node/__pycache__/test_node.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/node/__pycache__/test_node.cpython-34-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/node/__pycache__/test_utils.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/node/__pycache__/test_utils.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/node/__pycache__/test_utils.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/node/__pycache__/test_utils.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/node/__pycache__/test_utils.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/node/__pycache__/test_utils.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/node/__pycache__/test_utils.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/node/__pycache__/test_utils.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/node/__pycache__/test_utils.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/node/__pycache__/test_utils.cpython-34-PYTEST.pyc differ diff -Nru circuits-3.1.0+ds1/tests/node/test_node.py circuits-3.2.2/tests/node/test_node.py --- circuits-3.1.0+ds1/tests/node/test_node.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/node/test_node.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,17 +1,13 @@ #!/usr/bin/env python - - -from pytest import fixture, skip, PLATFORM - - -if PLATFORM == "win32": - skip("Broken on Windows") - +from pytest import PLATFORM, fixture, skip from circuits import Component, Event from circuits.net.events import close -from circuits.node import Node, remote from circuits.net.sockets import UDPServer +from circuits.node import Node, remote + +if PLATFORM == 'win32': + skip('Broken on Windows') class App(Component): @@ -21,7 +17,7 @@ disconnected = False def foo(self): - return "Hello World!" + return 'Hello World!' def ready(self, *args): self.ready = True @@ -36,15 +32,15 @@ @fixture() def bind(request, manager, watcher): server = UDPServer(0).register(manager) - assert watcher.wait("ready") + assert watcher.wait('ready') host, port = server.host, server.port server.fire(close()) - assert watcher.wait("closed") + assert watcher.wait('closed') server.unregister() - assert watcher.wait("unregistered") + assert watcher.wait('unregistered') return host, port @@ -53,13 +49,13 @@ def app(request, manager, watcher, bind): app = App().register(manager) node = Node().register(app) - watcher.wait("ready") + watcher.wait('ready') - child = (App() + Node(bind)) + child = (App() + Node(port=bind[1], server_ip=bind[0])) child.start(process=True) - node.add("child", *bind) - watcher.wait("connected") + node.add('child', *bind) + watcher.wait('connected') def finalizer(): child.stop() @@ -70,13 +66,12 @@ def test_return_value(app, watcher): - e = Event.create("foo") - e.notify = True - - r = remote(e, "child") - r.notify = True + event = Event.create('foo') + event.notify = True - value = app.fire(r) - assert watcher.wait("remote_value_changed") + remote_event = remote(event, 'child') + remote_event.notify = True - assert value.value == "Hello World!" + value = app.fire(remote_event) + assert watcher.wait('remote_value_changed') + assert value.value == 'Hello World!' diff -Nru circuits-3.1.0+ds1/tests/node/test_protocol.py circuits-3.2.2/tests/node/test_protocol.py --- circuits-3.1.0+ds1/tests/node/test_protocol.py 1970-01-01 00:00:00.000000000 +0000 +++ circuits-3.2.2/tests/node/test_protocol.py 2021-10-19 16:23:49.000000000 +0000 @@ -0,0 +1,218 @@ +#!/usr/bin/env python +import pytest + +from circuits import Component, Event +from circuits.core import Value +from circuits.node.protocol import Protocol +from circuits.node.utils import dump_event, dump_value + +pytestmark = pytest.mark.skipif(pytest.PLATFORM == 'win32', reason='Broken on Windows') + + +class return_value(Event): + success = True + + +class firewall_block(Event): + pass + + +class AppClient(Component): + write_data = b'' + + def return_value(self): + return 'Hello server!' + + def write(self, data): + self.write_data = data + + +class AppFirewall(Component): + write_data = b'' + + def fw_receive(self, event, sock): + return self.__event_is_allow(event) + + def fw_send(self, event, sock): + return self.__event_is_allow(event) + + def write(self, data): + self.write_data = data + + def __event_is_allow(self, event): + allow = 'return_value' == event.name \ + and 'prohibits_channel' not in event.channels + + if not allow: + self.fire(firewall_block()) + + return allow + + +class AppServer(Component): + write_data = b'' + write_sock = None + + def return_value(self): + return 'Hello client!' + + def write(self, sock, data): + self.write_sock = sock + self.write_data = data + + +@pytest.fixture() +def app_client(request, manager, watcher): + app = AppClient() + app.register(manager) + watcher.wait('registered') + + app.protocol = Protocol().register(app) + watcher.wait('registered') + + def finalizer(): + app.unregister() + + request.addfinalizer(finalizer) + + return app + + +@pytest.fixture() +def app_firewall(request, manager, watcher): + app = AppFirewall() + app.register(manager) + watcher.wait('registered') + + app.protocol = Protocol( + sock='sock obj', + receive_event_firewall=app.fw_receive, + send_event_firewall=app.fw_send, + ).register(app) + watcher.wait('registered') + + def finalizer(): + app.unregister() + + request.addfinalizer(finalizer) + + return app + + +@pytest.fixture() +def app_server(request, manager, watcher): + app = AppServer() + app.register(manager) + watcher.wait('registered') + + app.protocol = Protocol(sock='sock obj', server=True).register(app) + watcher.wait('registered') + + def finalizer(): + app.unregister() + + request.addfinalizer(finalizer) + + return app + + +def test_add_buffer(app_client, watcher): + packet = str.encode(dump_event(return_value(), 1)) + app_client.protocol.add_buffer(packet) + assert watcher.wait('return_value_success') + assert watcher.wait('write') + + value = Value() + value.value = 'Hello server!' + value.errors = False + value.node_call_id = 1 + assert app_client.write_data == str.encode(dump_value(value) + '~~~') + + +def test_add_buffer_server(app_server, watcher): + packet = str.encode(dump_event(return_value(), 1)) + app_server.protocol.add_buffer(packet) + assert watcher.wait('return_value_success') + assert watcher.wait('write') + + value = Value() + value.value = 'Hello client!' + value.errors = False + value.node_call_id = 1 + assert app_server.write_data == str.encode(dump_value(value) + '~~~') + assert app_server.write_sock == 'sock obj' + + +def test_firewall_receive(app_firewall, watcher): + # good event + packet = str.encode(dump_event(return_value(), 1)) + app_firewall.protocol.add_buffer(packet) + assert watcher.wait('return_value') + + # bad name + packet = str.encode(dump_event(Event.create('unallow_event'), 1)) + app_firewall.protocol.add_buffer(packet) + assert watcher.wait('firewall_block') + + # bad channel + event = return_value() + event.channels = ('prohibits_channel',) + packet = str.encode(dump_event(event, 1)) + app_firewall.protocol.add_buffer(packet) + assert watcher.wait('firewall_block') + + +def test_firewall_send(app_firewall, watcher): + # good event + event = return_value() + generator = app_firewall.protocol.send(event) + next(generator) # exec + assert watcher.wait('write') + assert app_firewall.write_data == str.encode(dump_event(event, 0) + '~~~') + + # bad name + generator = app_firewall.protocol.send(Event.create('unallow_event')) + next(generator) # exec + assert watcher.wait('firewall_block') + + # bad channel + event = return_value() + event.channels = ('prohibits_channel',) + generator = app_firewall.protocol.send(event) + next(generator) # exec + assert watcher.wait('firewall_block') + + +def test_send(app_client, watcher): + event = return_value() + generator = app_client.protocol.send(event) + next(generator) # exec + + assert watcher.wait('write') + assert app_client.write_data == str.encode(dump_event(event, 0) + '~~~') + + value = Value() + value.value = 'Hello server!' + value.errors = False + value.node_call_id = 0 + app_client.protocol.add_buffer(str.encode(dump_value(value) + '~~~')) + + assert next(generator).getValue() == value.value + + +def test_send_server(app_server, watcher): + event = return_value() + generator = app_server.protocol.send(event) + next(generator) # exec + + assert watcher.wait('write') + assert app_server.write_data == str.encode(dump_event(event, 0) + '~~~') + assert app_server.write_sock == 'sock obj' + + value = Value() + value.value = 'Hello client!' + value.errors = False + value.node_call_id = 0 + app_server.protocol.add_buffer(str.encode(dump_value(value) + '~~~')) + + assert next(generator).getValue() == value.value diff -Nru circuits-3.1.0+ds1/tests/node/test_server.py circuits-3.2.2/tests/node/test_server.py --- circuits-3.1.0+ds1/tests/node/test_server.py 1970-01-01 00:00:00.000000000 +0000 +++ circuits-3.2.2/tests/node/test_server.py 2021-10-19 16:23:49.000000000 +0000 @@ -0,0 +1,150 @@ +#!/usr/bin/env python +from __future__ import print_function + +from time import sleep + +import pytest + +from circuits import Component, Event +from circuits.net.events import close +from circuits.net.sockets import UDPServer +from circuits.node import Node + +pytestmark = pytest.mark.skipif(pytest.PLATFORM == 'win32', reason='Broken on Windows') + + +class return_value(Event): + success = True + + +class App(Component): + + def return_value(self, event): + print('Hello client!', event.channels) + + +@pytest.fixture() +def bind(manager, watcher): + server = UDPServer(0).register(manager) + assert watcher.wait('ready', channel='server') + + host, port = server.host, server.port + + server.fire(close()) + assert watcher.wait('closed', channel='server') + + server.unregister() + assert watcher.wait('unregistered', channel='server') + + return host, port + + +@pytest.fixture() +def app(manager, watcher, bind): + server = Node(port=bind[1], server_ip=bind[0]) + server.register(manager) + server.bind = bind + assert watcher.wait('registered', channel='node') + + return server + + +def test_auto_reconnect(app, watcher, manager): + # add client + client = App().register(manager) + node = Node().register(client) + chan = node.add('client1', *app.bind, reconnect_delay=1, connect_timeout=1) + assert watcher.wait('connected', channel=chan) + watcher.clear() + + # close server + app.fire(close(), app.channel) + assert watcher.wait('closed', channel=app.channel) + watcher.clear() + + # client gets an unreachable + assert watcher.wait('connect', channel=chan) + assert watcher.wait('unreachable', channel=chan) + watcher.clear() + + # start a new server + node2 = Node(port=app.bind[1], server_ip=app.bind[0]) + node2.register(manager) + assert watcher.wait('ready', channel=node2.channel) + watcher.clear() + + assert watcher.wait('connected', channel=chan) + + client.unregister() + + +def test_server_send_all(app, watcher, manager): + client1 = App().register(manager) + node1 = Node().register(client1) + chan = node1.add('client1', *app.bind) + assert watcher.wait('connected', channel=chan) + + client2 = App().register(manager) + node2 = Node().register(client2) + chan = node2.add('client2', *app.bind) + assert watcher.wait('connected', channel=chan) + + event = return_value() + app.server.send_all(event) + assert watcher.wait('return_value') + + client1.unregister() + client2.unregister() + + +def test_server_send(app, watcher, manager): + client1 = App().register(manager) + node1 = Node().register(client1) + chan1 = node1.add('client1', *app.bind) + assert watcher.wait('connected', channel=chan1) + + client2 = App().register(manager) + node2 = Node().register(client2) + chan2 = node2.add('client2', *app.bind) + assert watcher.wait('connected', channel=chan2) + + event = return_value() + app.server.send(event, app.server.get_socks()[0], no_result=True) + assert watcher.wait('return_value') + + client1.unregister() + client2.unregister() + + +def test_server_send_multicast(app, watcher, manager): + client1 = App().register(manager) + node1 = Node().register(client1) + chan1 = node1.add('client1', *app.bind) + assert watcher.wait('connected', channel=chan1) + watcher.clear() + + client2 = App().register(manager) + node2 = Node().register(client2) + chan2 = node2.add('client2', *app.bind) + assert watcher.wait('connected', channel=chan2) + watcher.clear() + + client3 = App().register(manager) + node3 = Node().register(client3) + chan3 = node3.add('client3', *app.bind) + assert watcher.wait('connected', channel=chan3) + watcher.clear() + + event = return_value() + app.server.send_to(event, app.server.get_socks()) + assert watcher.wait('return_value') + + for _ in range(3): + if watcher.count("return_value") == 3: + break + sleep(1) + assert watcher.count("return_value") == 3 + + client1.unregister() + client2.unregister() + client3.unregister() diff -Nru circuits-3.1.0+ds1/tests/node/test_utils.py circuits-3.2.2/tests/node/test_utils.py --- circuits-3.1.0+ds1/tests/node/test_utils.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/node/test_utils.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,51 +1,50 @@ -# Module: test_utils -# Date: ... -# Author: ... - -"""test_utils +'''test_utils ... -""" +''' from circuits import Event +from circuits.core import Value +from circuits.node.utils import dump_event, dump_value, load_event, load_value class test(Event): - """test Event""" + '''test Event''' -def test_events(): - from circuits.node.utils import dump_event, load_event - e = test(1, 2, 3, foo="bar") - e.success = True - e.failure = False +def test_events(): + event = test(1, 2, 3, foo='bar') + event.success = True + event.failure = False + event.test_meta = 1 id = 1 - s = dump_event(e, id) - x, id = load_event(s) + s = dump_event(event, id) + event, id = load_event(s) - assert hasattr(x, "args") - assert hasattr(x, "kwargs") - assert hasattr(x, "success") - assert hasattr(x, "failure") - assert hasattr(x, "channels") - assert hasattr(x, "notify") + assert hasattr(event, 'args') + assert hasattr(event, 'kwargs') + assert hasattr(event, 'success') + assert hasattr(event, 'failure') + assert hasattr(event, 'channels') + assert hasattr(event, 'notify') + assert hasattr(event, 'test_meta') def test_values(): - from circuits.node.utils import dump_value, load_value - from circuits.core.values import Value + event = Event() + event.test_meta = 1 - v = Value() - v.value = 'foo' - v.errors = False - v.node_trn = 1 + value = Value(event=event) + value.value = 'foo' + value.errors = False + value.node_call_id = 1 - s = dump_value(v) - x, id, errors = load_value(s) + x, id, errors, meta = load_value(dump_value(value)) - assert v.value == x + assert value.value == x assert id == 1 assert not errors + assert meta['test_meta'] == event.test_meta Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/protocols/__init__.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/protocols/__init__.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/protocols/__pycache__/__init__.cpython-32.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/protocols/__pycache__/__init__.cpython-32.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/protocols/__pycache__/__init__.cpython-33.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/protocols/__pycache__/__init__.cpython-33.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/protocols/__pycache__/__init__.cpython-34.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/protocols/__pycache__/__init__.cpython-34.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/protocols/__pycache__/test_irc.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/protocols/__pycache__/test_irc.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/protocols/__pycache__/test_irc.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/protocols/__pycache__/test_irc.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/protocols/__pycache__/test_irc.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/protocols/__pycache__/test_irc.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/protocols/__pycache__/test_irc.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/protocols/__pycache__/test_irc.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/protocols/__pycache__/test_irc.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/protocols/__pycache__/test_irc.cpython-34-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/protocols/__pycache__/test_line.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/protocols/__pycache__/test_line.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/protocols/__pycache__/test_line.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/protocols/__pycache__/test_line.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/protocols/__pycache__/test_line.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/protocols/__pycache__/test_line.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/protocols/__pycache__/test_line.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/protocols/__pycache__/test_line.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/protocols/__pycache__/test_line.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/protocols/__pycache__/test_line.cpython-34-PYTEST.pyc differ diff -Nru circuits-3.1.0+ds1/tests/protocols/test_irc.py circuits-3.2.2/tests/protocols/test_irc.py --- circuits-3.1.0+ds1/tests/protocols/test_irc.py 2014-09-16 13:09:44.000000000 +0000 +++ circuits-3.2.2/tests/protocols/test_irc.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,25 +1,15 @@ #!/usr/bin/env python - - import pytest from pytest import fixture - -from circuits import handler, Event, Component - +from circuits import Component, Event, handler from circuits.net.events import read, write - -from circuits.protocols.irc import IRC -from circuits.protocols.irc import strip, joinprefix, parseprefix - from circuits.protocols.irc import ( - PASS, USER, NICK, PONG, QUIT, - JOIN, PART, PRIVMSG, NOTICE, AWAY, - KICK, TOPIC, MODE, INVITE, NAMES, WHOIS + AWAY, INVITE, IRC, JOIN, KICK, MODE, NAMES, NICK, NOTICE, PART, PASS, PONG, + PRIVMSG, QUIT, TOPIC, USER, WHOIS, irc_color_to_ansi, joinprefix, parsemsg, + parseprefix, strip, ) -from circuits.six import u - class App(Component): @@ -49,7 +39,7 @@ def app(request): app = App() - while app: + while len(app): app.flush() return app @@ -71,6 +61,20 @@ assert s == "test!foo@localhost" +def test_parsemsg(): + s = b":foo!bar@localhost NICK foobar" + source, command, args = parsemsg(s) + assert source == (u"foo", u"bar", u"localhost") + assert command == "NICK" + assert args == [u"foobar"] + + s = b"" + source, command, args = parsemsg(s) + assert source == (None, None, None) + assert command is None + assert args == [] + + def test_parseprefix(): s = "test!foo@localhost" nick, ident, host = parseprefix(s) @@ -124,15 +128,15 @@ ( b":localhost NOTICE * :*** Looking up your hostname...\r\n", Event.create( - "notice", (u("localhost"), None, None), u("*"), - u("*** Looking up your hostname..."), + "notice", (u"localhost", None, None), u"*", + u"*** Looking up your hostname...", ) ), ]) def test_responses(app, data, event): app.reset() app.fire(read(data)) - while app: + while len(app): app.flush() e = app.events[-1] @@ -140,3 +144,17 @@ assert event.name == e.name assert event.args == e.args assert event.kwargs == e.kwargs + + +@pytest.mark.parametrize('inp,out', [ + ('hi \x02bold\x02 \x1ditalic\x1d \x1funderline\x1f \x1estrikethrough\x1e', 'hi \x02bold\x02 \x1b[03mitalic\x1b[23m \x1b[04munderline\x1b[24m \x1b[09mstrikethrough\x1b[29m'), + ('\x0300white\x03 \x0301black\x03 \x0302blue\x03 \x0303green\x03 \x0304red\x03 ', '\x1b[37mwhite\x1b[39;49m \x1b[30mblack\x1b[39;49m \x1b[34mblue\x1b[39;49m \x1b[32mgreen\x1b[39;49m \x1b[31mred\x1b[39;49m '), + ('\x0305brown\x03 \x0306magenta\x03 \x0307orange\x03 \x0308yellow\x03 ', '\x1b[36mbrown\x1b[39;49m \x1b[35mmagenta\x1b[39;49m \x1b[33morange\x1b[39;49m \x1b[93myellow\x1b[39;49m '), + ('\x0309lightgreen\x03 \x0310cyan\x03 \x0311lightcyan\x03 \x0312lightblue\x03 ', '\x1b[92mlightgreen\x1b[39;49m \x1b[36mcyan\x1b[39;49m \x1b[96mlightcyan\x1b[39;49m \x1b[94mlightblue\x1b[39;49m '), + ('\x0313pink\x03 \x0314grey\x03 \x0315lightgrey\x03', '\x1b[95mpink\x1b[39;49m \x1b[90mgrey\x1b[39;49m \x1b[37mlightgrey\x1b[39;49m'), + ('\x0300white\x03 \x0301,01black\x03 \x0301,02blue\x03 \x0301,03green\x03 \x0301,04red\x03 ', '\x1b[37mwhite\x1b[39;49m \x1b[30;40mblack\x1b[39;49m \x1b[30;44mblue\x1b[39;49m \x1b[30;42mgreen\x1b[39;49m \x1b[30;41mred\x1b[39;49m '), + ('\x0f', '\x1b[m'), + ('\x0302blue', '\x1b[34mblue\x1b[m'), +]) +def test_ansi_color(inp, out): + assert irc_color_to_ansi(inp) == out diff -Nru circuits-3.1.0+ds1/tests/protocols/test_line.py circuits-3.2.2/tests/protocols/test_line.py --- circuits-3.1.0+ds1/tests/protocols/test_line.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/protocols/test_line.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,12 +1,12 @@ #!/usr/bin/env python - from collections import defaultdict +from circuits import Component, Event from circuits.protocols import Line -from circuits import Event, Component class read(Event): + """read Event""" @@ -32,12 +32,12 @@ app = App() Line().register(app) - while app: + while len(app): app.flush() app.fire(read(b"1\n2\r\n3\n4")) - while app: + while len(app): app.flush() assert app.lines[0] == b"1" @@ -53,13 +53,13 @@ updateBuffer=buffers.__setitem__ ).register(app) - while app: + while len(app): app.flush() app.fire(read(1, b"1\n2\r\n3\n4")) app.fire(read(2, b"1\n2\r\n3\n4")) - while app: + while len(app): app.flush() assert app.lines[0] == (1, b"1") Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/__pycache__/conftest.cpython-32.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/__pycache__/conftest.cpython-32.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/__pycache__/conftest.cpython-33.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/__pycache__/conftest.cpython-33.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/__pycache__/conftest.cpython-34.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/__pycache__/conftest.cpython-34.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/__pycache__/__init__.cpython-32.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/__pycache__/__init__.cpython-32.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/__pycache__/__init__.cpython-33.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/__pycache__/__init__.cpython-33.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/__pycache__/__init__.cpython-34.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/__pycache__/__init__.cpython-34.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/tools/__init__.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/tools/__init__.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/tools/__pycache__/__init__.cpython-32.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/tools/__pycache__/__init__.cpython-32.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/tools/__pycache__/__init__.cpython-33.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/tools/__pycache__/__init__.cpython-33.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/tools/__pycache__/__init__.cpython-34.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/tools/__pycache__/__init__.cpython-34.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/tools/__pycache__/test_tools.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/tools/__pycache__/test_tools.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/tools/__pycache__/test_tools.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/tools/__pycache__/test_tools.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/tools/__pycache__/test_tools.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/tools/__pycache__/test_tools.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/tools/__pycache__/test_tools.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/tools/__pycache__/test_tools.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/tools/__pycache__/test_tools.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/tools/__pycache__/test_tools.cpython-34-PYTEST.pyc differ diff -Nru circuits-3.1.0+ds1/tests/tools/test_tools.py circuits-3.2.2/tests/tools/test_tools.py --- circuits-3.1.0+ds1/tests/tools/test_tools.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/tools/test_tools.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,22 +1,17 @@ -# Module: test_tools -# Date: 13th March 2009 -# Author: James Mills, prologic at shortcircuit dot net dot au - """Tools Test Suite Test all functionality of the tools package. """ - import pytest +from circuits import Component, reprhandler +from circuits.tools import findroot, inspect, kill, tryimport + try: from threading import current_thread except ImportError: from threading import currentThread as current_thread # NOQA -from circuits import Component, reprhandler -from circuits.tools import kill, inspect, findroot, tryimport - class A(Component): @@ -86,7 +81,7 @@ assert not f.components assert kill(d) is None - while a: + while len(a): a.flush() assert a.parent == a @@ -95,9 +90,9 @@ assert not c.components assert b in a.components - assert not d in a.components - assert not e in d.components - assert not f in e.components + assert d not in a.components + assert e not in d.components + assert f not in e.components assert d.parent == d assert e.parent == e @@ -109,18 +104,15 @@ def test_inspect(): - if pytest.PYVER[:2] == (3, 3): - pytest.skip("Broken on Python 3.3") - a = A() s = inspect(a) assert "Components: 0" in s assert "Event Handlers: 2" in s assert "foo; 1" in s - assert "" in s + assert "" in s assert "prepare_unregister_complete; 1" in s - assert ".prepare_unregister_complete] (A._on_prepare_unregister_complete)>" in s + assert "][prepare_unregister_complete] (A._on_prepare_unregister_complete)>" in s def test_findroot(): @@ -144,10 +136,9 @@ def test_reprhandler(): a = A() s = reprhandler(a.foo) - assert s == "" + assert s == "" - f = lambda: None - pytest.raises(AttributeError, reprhandler, f) + pytest.raises(AttributeError, reprhandler, lambda: None) def test_tryimport(): diff -Nru circuits-3.1.0+ds1/tests/web/cert.pem circuits-3.2.2/tests/web/cert.pem --- circuits-3.1.0+ds1/tests/web/cert.pem 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/web/cert.pem 2021-10-19 16:23:49.000000000 +0000 @@ -1,37 +1,49 @@ -----BEGIN RSA PRIVATE KEY----- -MIICWwIBAAKBgQC9B7hV67bzhLA//STrZUIi0iHD4WFtftOhvj+xiHRNnYw0+r+4 -WdQv1YiL+ab03pn/J9R1SQuOGwYDVPQvYX+qEFVRUFP9yvXIQl7PG40HQzfs8lJz -hnmI+64HJT//oJ9e7PiyDHLfFH1FuCqSy9RlvzOd4hmydX9J3VxFFzrpJQIDAQAB -AoGAHhGxT/Gb+6a6xqMFEXDdEV7twhQDBIDtN0hlJ192aLZMDE1q2+9mImnMO7/t -v/v88Sqr0DBbZzKDRVppMXRH80ZtnmMu3/3kUCtA3WAbKxyFpIiXGv/NAUHZe5Gz -rua+z3lUvmt6CmwMm2ReB70Q61zxr9q4HjrjYI82dtJ4M40CQQDnGujxdBdbPmiR -oc8mcShfmPNP7igQrUkf/DpB0GWnLWdA97mmXLw4jHXpHy9gm3wGc+9uOi0Ex8Ml -1t9xAGFjAkEA0WSGwG45d5dmYV8Oa/9UsY5/F6hAlYAAI1TxRsKcl2YTqaQastac -glV1GSUrgGw/8UBvdKKS2REF7cpAkiQV1wJAPtQhCiuOgf7YfOcpowDWgg7Z7xwH -Bmml3K08xVG7oRSF4rK2ZRUHErSVBbi1r6T1tedk62mjfY41bp8ZBeadkwJAD7AG -YHhhmdIf+3+Rpwm0ILFaWD1kyU6TtBHzGagO71DYfEctMOTfSOx6H24nejGiAMMh -Fo3vjo+18ADNIaXOdQJAYdm+dUdyVaW2IDUi7ew0shyKTC4OaEZtXIwwINvrqUsX -//6z8mw/S5rXGlfKadiz4uwzcXlSvg727O1efpibvA== +MIIEowIBAAKCAQEAw56dcICp8bf9GHCIoKKXjnGwRTHh3Ibm6FxuE+b0Pm/zX48d +pWEyhw/cGpiTL860Bmpu8K/zEELRPNBU0HMbSqXYX0kODStgXzrsJDy4rPUuzeGN +8fDLH/8/2gIaIqnLoVhkOoF2d4cnTH96j/Q7z2QeCftHLzVovPqmucpxgHPZYZ8M +XYlP4MvN0PAskaON+AQxayNUEVGUDEj9w1w7kwR0D70l3AJL+yHHeJpqF4TRsXGF +/mi8IGBAaWRXerK2qt6X09IbmCyS+5GTOt9BRuhfRgfkXDLnrJKa1ymSVl3E3y7Y +ViXz/QT8UssjYW61E0E9Q0SZh5DkOSnr9a1J9QIDAQABAoIBAAHZwkuKLBFpWC+f +AOvkHeLvGGfPLP/VFuIj3ba6fJ0KmhbRV8p0vPGiKMbnopzVK8bTwvDr+TSyLSCS +J/tA24U9RGrCWiutuV+tQwakvGqGd0bjV2Bukr1ewM/jLTQevxprp6cWCnTfBnQm +0JYEDXzMyav2gJnlu3PuOx2O2LwKWEqERFWEj2pvitD1LGgw1rN0qjssXtlhuBtr +xfxECyhtfa1fyD9Dx9lKK14vJMLq6027DLsFf5qOFmTr8399SnuPwxvldzNzJaVB +9nLQHVNR59e292UsaPAPhKOpH2bZTDy3MJrfzJHe5p59JcU9vSJsOkluaQXP2ivq +H2d9hwECgYEA7IYcTv9Tf5joxUDhWcjjaKND3Bpsc3f1Qo9jQuFBlZoW441gZQpr +d1W9DUQ86tLRHNs6M4lJAGzs2fLweGgjNesn0+Q+sUDFnpW1sra89ucK81Xp8Ikn +v7eKhp8an6daMGzX1dvQGRSEePPiNLvym0Y46XF6P4pN6ArigM5kceUCgYEA07o/ +f4V6y72U5AVToKwop6/aEAOqeyCO51BaafAhfiOaHV1smZLRAMwy6E3BB4BKvNOX +wEKnu63MMgUsrcFORpcl+O2v3ZOK1oByS4z8PwvzPQYUaQf5xKqFUAQhgLvwI049 +sLJSyA0OWYGwq5h5d+BKGVP64vs/sE2Jw6yuNtECgYBjTU73T7VDvfQEVOAH7RKk +7N7huupLdFKxVjgLbT02zRHNCZ8t7Lj/yixsNHkK8eW/or8Fwh63IgQy4Q9azgXy +bj8zdAFqM9KEaUB2vsgJNSlgznJAfaUFlc6ABK6N1xpDeH8Jl5b/4KBZk7MmBr6t +uEbOo8j6gluBD4jXIVAEjQKBgHy8U0B7kPaLQDZ99ODJzEHOVjftEPjtG4OnUTzs +Xa8Epnz6V0q6tis0IiG9/STALkfEmLiKDGuDXrNxXPsY0VbBIXvf/CYcEEWC8tMT +wmAaWDjxZgDi1AFLPLMBXAONtVH3fFynEiINnxCYWU8eyyEWoFD/quUihEkHxUvk +ZdahAoGBANz6W+VbTAK5iNq81CBSIvCROi7OXObdyVlbb0W5ehB7hWCAelmt0KCt +D/ZlSr4IC6ztq7XsgCitP7GROA+yi/7Pi6dWO2hkJbe/iCDgvvaGTNWbZQLccFBJ +XIAPPkyssmKgYVGtJfBHLxj7FWB7TMwXmLOuALcyCPJe/HDcFySQ -----END RSA PRIVATE KEY----- -----BEGIN CERTIFICATE----- -MIIDjTCCAvagAwIBAgIJAN0msyL5El/jMA0GCSqGSIb3DQEBBQUAMIGMMQswCQYD -VQQGEwJBVTETMBEGA1UECBMKUXVlZW5zbGFuZDERMA8GA1UEBxMIQnJpc2JhbmUx -FTATBgNVBAoTDFNob3J0Q2lyY3VpdDEUMBIGA1UEAxMLSmFtZXMgTWlsbHMxKDAm -BgkqhkiG9w0BCQEWGWFkbWluQHNob3J0Y2lyY3VpdC5uZXQuYXUwHhcNMTAwMTEz -MDczOTAwWhcNMTEwMTEzMDczOTAwWjCBjDELMAkGA1UEBhMCQVUxEzARBgNVBAgT -ClF1ZWVuc2xhbmQxETAPBgNVBAcTCEJyaXNiYW5lMRUwEwYDVQQKEwxTaG9ydENp -cmN1aXQxFDASBgNVBAMTC0phbWVzIE1pbGxzMSgwJgYJKoZIhvcNAQkBFhlhZG1p -bkBzaG9ydGNpcmN1aXQubmV0LmF1MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB -gQC9B7hV67bzhLA//STrZUIi0iHD4WFtftOhvj+xiHRNnYw0+r+4WdQv1YiL+ab0 -3pn/J9R1SQuOGwYDVPQvYX+qEFVRUFP9yvXIQl7PG40HQzfs8lJzhnmI+64HJT// -oJ9e7PiyDHLfFH1FuCqSy9RlvzOd4hmydX9J3VxFFzrpJQIDAQABo4H0MIHxMB0G -A1UdDgQWBBSq+tU5ZDymUuMcgZ83gxk1PTN89zCBwQYDVR0jBIG5MIG2gBSq+tU5 -ZDymUuMcgZ83gxk1PTN896GBkqSBjzCBjDELMAkGA1UEBhMCQVUxEzARBgNVBAgT -ClF1ZWVuc2xhbmQxETAPBgNVBAcTCEJyaXNiYW5lMRUwEwYDVQQKEwxTaG9ydENp -cmN1aXQxFDASBgNVBAMTC0phbWVzIE1pbGxzMSgwJgYJKoZIhvcNAQkBFhlhZG1p -bkBzaG9ydGNpcmN1aXQubmV0LmF1ggkA3SazIvkSX+MwDAYDVR0TBAUwAwEB/zAN -BgkqhkiG9w0BAQUFAAOBgQAokSGDpbFV2osC8nM8K12vheeDBVDHGxOaENXGVIm8 -SWPXsaIUsm6JQx0wm/eouWRPbNJkOBwBrNCls1oMmdxdxG8mBh+kAMWUkdVeuT2H -lCo9BRJnhUr4L6poJ7ORzL2oUilGZNwONpHGY0cWzFG8/tOoRJsfKZm23bwXbIxv -Hw== +MIIDoTCCAokCFC9S/3ETWtegvP0F5DrxSUoPaRTgMA0GCSqGSIb3DQEBCwUAMIGM +MQswCQYDVQQGEwJBVTETMBEGA1UECAwKUXVlZW5zbGFuZDERMA8GA1UEBwwIQnJp +c2JhbmUxFTATBgNVBAoMDFNob3J0Q2lyY3VpdDEUMBIGA1UEAwwLSmFtZXMgTWls +bHMxKDAmBgkqhkiG9w0BCQEWGWFkbWluQHNob3J0Y2lyY3VpdC5uZXQuYXUwHhcN +MjAxMjE0MjMzMTM2WhcNMzAxMjEyMjMzMTM2WjCBjDELMAkGA1UEBhMCQVUxEzAR +BgNVBAgMClF1ZWVuc2xhbmQxETAPBgNVBAcMCEJyaXNiYW5lMRUwEwYDVQQKDAxT +aG9ydENpcmN1aXQxFDASBgNVBAMMC0phbWVzIE1pbGxzMSgwJgYJKoZIhvcNAQkB +FhlhZG1pbkBzaG9ydGNpcmN1aXQubmV0LmF1MIIBIjANBgkqhkiG9w0BAQEFAAOC +AQ8AMIIBCgKCAQEAw56dcICp8bf9GHCIoKKXjnGwRTHh3Ibm6FxuE+b0Pm/zX48d +pWEyhw/cGpiTL860Bmpu8K/zEELRPNBU0HMbSqXYX0kODStgXzrsJDy4rPUuzeGN +8fDLH/8/2gIaIqnLoVhkOoF2d4cnTH96j/Q7z2QeCftHLzVovPqmucpxgHPZYZ8M +XYlP4MvN0PAskaON+AQxayNUEVGUDEj9w1w7kwR0D70l3AJL+yHHeJpqF4TRsXGF +/mi8IGBAaWRXerK2qt6X09IbmCyS+5GTOt9BRuhfRgfkXDLnrJKa1ymSVl3E3y7Y +ViXz/QT8UssjYW61E0E9Q0SZh5DkOSnr9a1J9QIDAQABMA0GCSqGSIb3DQEBCwUA +A4IBAQAUr7fRHFMy8MSQbYj4PQdu4mIA+beIrEN8+wnMgdONv4o30aetilC55ffN +c94TlezlpzX6aHrRJ0jiEOW2PbjVgayMG2um7QICLjqwyrK+18NCwEQxDthX/wXv +KFTMHrDo5FSLRLxe2m3wNT38EaVM0NHMwai71ehEnLCYJo9shw/PphXkXONIltuS +lGOEu/mvI7PA/2fJUS8U+3Fdr2K0i22c7JfNvr8gu2mkydsNMxDnKnLVq6s8QIz5 +lzezCkqIpNfJT8E2KlIsAFQXE6awrAcc7Fcc9/PbwrNOB7x7DVwz7GGb5vSTvrMg +dXTYnVO0WJFrlipOjt3DnazbRRtN -----END CERTIFICATE----- diff -Nru circuits-3.1.0+ds1/tests/web/conftest.py circuits-3.2.2/tests/web/conftest.py --- circuits-3.1.0+ds1/tests/web/conftest.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/web/conftest.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,19 +1,13 @@ -# Module: conftest -# Date: 10 February 2010 -# Author: James Mills, prologic at shortcircuit dot net dot au - """py.test config""" - import os import pytest +from circuits import Component, Debugger, handler from circuits.net.sockets import close from circuits.web import Server, Static -from circuits import handler, Component, Debugger from circuits.web.client import Client, request - DOCROOT = os.path.join(os.path.dirname(__file__), "static") @@ -45,45 +39,33 @@ self.closed = True -@pytest.fixture(scope="module") -def webapp(request): - webapp = WebApp() +@pytest.fixture +def webapp(request, manager, watcher): + webapp = WebApp().register(manager) + assert watcher.wait("ready") if hasattr(request.module, "application"): from circuits.web.wsgi import Gateway application = getattr(request.module, "application") Gateway({"/": application}).register(webapp) + assert watcher.wait("registered") Root = getattr(request.module, "Root", None) if Root is not None: Root().register(webapp) + assert watcher.wait("registered") if request.config.option.verbose: Debugger().register(webapp) - - waiter = pytest.WaitEvent(webapp, "ready") - webapp.start() - assert waiter.wait() + assert watcher.wait("registered") def finalizer(): - webapp.fire(close(), webapp.server) - webapp.stop() - - request.addfinalizer(finalizer) + webapp.fire(close()) + assert watcher.wait("closed") - return webapp - - -@pytest.fixture(scope="module") -def webclient(request, webapp): - webclient = WebClient() - waiter = pytest.WaitEvent(webclient, "ready", channel=webclient.channel) - webclient.register(webapp) - assert waiter.wait() - - def finalizer(): - webclient.unregister() + webapp.unregister() + assert watcher.wait("unregistered") request.addfinalizer(finalizer) - return webclient + return webapp Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/conftest.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/conftest.pyc differ diff -Nru circuits-3.1.0+ds1/tests/web/helpers.py circuits-3.2.2/tests/web/helpers.py --- circuits-3.1.0+ds1/tests/web/helpers.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/web/helpers.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,24 +1,11 @@ -try: - from urllib.error import HTTPError, URLError - from urllib.parse import quote, urlencode, urljoin - from urllib.request import HTTPBasicAuthHandler, HTTPCookieProcessor - from urllib.request import urlopen, build_opener, install_opener - from urllib.request import HTTPDigestAuthHandler, Request -except ImportError: - from urlparse import urljoin - from urllib import quote, urlencode - from urllib2 import HTTPError, URLError, HTTPDigestAuthHandler - from urllib2 import HTTPBasicAuthHandler, HTTPCookieProcessor - from urllib2 import urlopen, build_opener, install_opener, Request - -try: - from http.cookiejar import CookieJar -except ImportError: - from cookielib import CookieJar - -try: - from urllib.parse import urlparse -except ImportError: - from urlparse import urlparse +from circuits.six.moves.http_cookiejar import CookieJar # noqa +from circuits.six.moves.urllib_error import HTTPError, URLError # noqa +from circuits.six.moves.urllib_parse import ( # noqa + quote, urlencode, urljoin, urlparse, +) +from circuits.six.moves.urllib_request import ( # noqa + HTTPBasicAuthHandler, HTTPCookieProcessor, HTTPDigestAuthHandler, Request, + build_opener, install_opener, urlopen, +) # pylama:skip=1 Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/helpers.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/helpers.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__init__.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__init__.pyc differ diff -Nru circuits-3.1.0+ds1/tests/web/jsonrpclib.py circuits-3.2.2/tests/web/jsonrpclib.py --- circuits-3.1.0+ds1/tests/web/jsonrpclib.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/web/jsonrpclib.py 2021-10-19 16:23:49.000000000 +0000 @@ -29,10 +29,9 @@ # ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE # OF THIS SOFTWARE. # -------------------------------------------------------------------- - -import sys -import json import base64 +import json +import sys PY3 = sys.version_info[0] == 3 @@ -68,7 +67,9 @@ # Base class for all kinds of client-side errors. class Error(Exception): + """Base class for client errors.""" + def __str__(self): return repr(self) @@ -84,6 +85,7 @@ class ProtocolError(Error): + """Indicates an HTTP protocol error.""" def __init__(self, url, errcode, errmsg, headers, response): @@ -130,7 +132,7 @@ self.data = self.data + data def close(self): - #try to convert string to json + # try to convert string to json return json.loads(self.data.decode(self.encoding)) @@ -172,6 +174,7 @@ class Transport: + """Handles an HTTP transaction to an JSON-RPC server.""" # client identifier (may be overridden) @@ -367,6 +370,7 @@ class SafeTransport(Transport): + """Handles an HTTPS transaction to an JSON-RPC server.""" # FIXME: mostly untested @@ -435,7 +439,7 @@ __str__ = __repr__ def __getattr__(self, name): - #dispatch + # dispatch return _Method(self.__request, name) # note: to call a remote object with an non-standard name, use Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/jsonrpclib.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/jsonrpclib.pyc differ diff -Nru circuits-3.1.0+ds1/tests/web/multipartform.py circuits-3.2.2/tests/web/multipartform.py --- circuits-3.1.0+ds1/tests/web/multipartform.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/web/multipartform.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,7 +1,6 @@ - import itertools -from mimetypes import guess_type from email.generator import _make_boundary +from mimetypes import guess_type class MultiPartForm(dict): Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/multipartform.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/multipartform.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/conftest.cpython-32.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/conftest.cpython-32.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/conftest.cpython-33.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/conftest.cpython-33.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/conftest.cpython-34.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/conftest.cpython-34.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/helpers.cpython-32.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/helpers.cpython-32.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/helpers.cpython-33.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/helpers.cpython-33.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/helpers.cpython-34.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/helpers.cpython-34.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/__init__.cpython-32.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/__init__.cpython-32.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/__init__.cpython-33.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/__init__.cpython-33.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/__init__.cpython-34.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/__init__.cpython-34.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/jsonrpclib.cpython-32.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/jsonrpclib.cpython-32.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/jsonrpclib.cpython-33.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/jsonrpclib.cpython-33.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/jsonrpclib.cpython-34.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/jsonrpclib.cpython-34.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/multipartform.cpython-32.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/multipartform.cpython-32.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/multipartform.cpython-33.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/multipartform.cpython-33.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/multipartform.cpython-34.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/multipartform.cpython-34.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_bad_requests.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_bad_requests.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_bad_requests.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_bad_requests.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_bad_requests.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_bad_requests.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_bad_requests.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_bad_requests.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_bad_requests.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_bad_requests.cpython-34-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_basicauth.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_basicauth.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_basicauth.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_basicauth.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_basicauth.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_basicauth.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_basicauth.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_basicauth.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_basicauth.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_basicauth.cpython-34-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_call_wait.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_call_wait.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_call_wait.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_call_wait.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_call_wait.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_call_wait.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_call_wait.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_call_wait.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_call_wait.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_call_wait.cpython-34-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_client.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_client.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_client.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_client.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_client.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_client.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_client.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_client.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_client.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_client.cpython-34-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_conn.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_conn.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_conn.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_conn.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_conn.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_conn.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_conn.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_conn.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_conn.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_conn.cpython-34-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_cookies.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_cookies.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_cookies.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_cookies.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_cookies.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_cookies.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_cookies.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_cookies.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_cookies.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_cookies.cpython-34-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_core.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_core.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_core.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_core.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_core.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_core.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_core.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_core.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_core.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_core.cpython-34-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_digestauth.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_digestauth.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_digestauth.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_digestauth.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_digestauth.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_digestauth.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_digestauth.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_digestauth.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_digestauth.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_digestauth.cpython-34-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_dispatcher2.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_dispatcher2.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_dispatcher2.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_dispatcher2.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_dispatcher2.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_dispatcher2.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_dispatcher2.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_dispatcher2.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_dispatcher2.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_dispatcher2.cpython-34-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_dispatcher3.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_dispatcher3.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_dispatcher3.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_dispatcher3.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_dispatcher3.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_dispatcher3.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_dispatcher3.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_dispatcher3.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_dispatcher3.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_dispatcher3.cpython-34-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_dispatcher.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_dispatcher.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_dispatcher.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_dispatcher.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_dispatcher.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_dispatcher.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_dispatcher.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_dispatcher.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_dispatcher.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_dispatcher.cpython-34-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_disps.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_disps.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_disps.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_disps.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_disps.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_disps.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_disps.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_disps.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_disps.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_disps.cpython-34-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_exceptions.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_exceptions.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_exceptions.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_exceptions.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_exceptions.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_exceptions.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_exceptions.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_exceptions.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_exceptions.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_exceptions.cpython-34-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_expires.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_expires.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_expires.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_expires.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_expires.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_expires.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_expires.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_expires.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_expires.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_expires.cpython-34-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_expose.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_expose.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_expose.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_expose.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_expose.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_expose.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_expose.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_expose.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_expose.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_expose.cpython-34-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_generator.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_generator.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_generator.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_generator.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_generator.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_generator.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_generator.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_generator.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_generator.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_generator.cpython-34-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_gzip.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_gzip.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_gzip.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_gzip.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_gzip.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_gzip.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_gzip.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_gzip.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_gzip.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_gzip.cpython-34-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_headers.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_headers.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_headers.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_headers.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_headers.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_headers.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_headers.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_headers.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_headers.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_headers.cpython-34-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_http.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_http.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_http.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_http.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_http.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_http.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_http.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_http.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_http.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_http.cpython-34-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_json.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_json.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_json.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_json.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_json.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_json.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_json.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_json.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_json.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_json.cpython-34-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_jsonrpc.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_jsonrpc.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_jsonrpc.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_jsonrpc.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_jsonrpc.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_jsonrpc.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_jsonrpc.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_jsonrpc.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_jsonrpc.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_jsonrpc.cpython-34-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_large_post.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_large_post.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_large_post.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_large_post.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_large_post.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_large_post.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_large_post.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_large_post.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_large_post.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_large_post.cpython-34-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_logger.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_logger.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_logger.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_logger.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_logger.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_logger.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_logger.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_logger.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_logger.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_logger.cpython-34-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_methods.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_methods.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_methods.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_methods.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_methods.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_methods.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_methods.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_methods.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_methods.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_methods.cpython-34-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_multipartformdata.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_multipartformdata.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_multipartformdata.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_multipartformdata.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_multipartformdata.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_multipartformdata.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_multipartformdata.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_multipartformdata.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_multipartformdata.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_multipartformdata.cpython-34-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_null_response.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_null_response.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_null_response.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_null_response.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_null_response.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_null_response.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_null_response.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_null_response.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_null_response.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_null_response.cpython-34-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_request_failure.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_request_failure.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_request_failure.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_request_failure.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_request_failure.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_request_failure.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_request_failure.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_request_failure.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_request_failure.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_request_failure.cpython-34-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_security.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_security.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_security.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_security.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_security.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_security.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_security.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_security.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_security.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_security.cpython-34-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_serve_download.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_serve_download.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_serve_download.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_serve_download.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_serve_download.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_serve_download.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_serve_download.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_serve_download.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_serve_download.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_serve_download.cpython-34-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_serve_file.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_serve_file.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_serve_file.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_serve_file.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_serve_file.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_serve_file.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_serve_file.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_serve_file.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_serve_file.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_serve_file.cpython-34-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_servers.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_servers.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_servers.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_servers.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_servers.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_servers.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_servers.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_servers.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_servers.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_servers.cpython-34-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_sessions.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_sessions.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_sessions.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_sessions.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_sessions.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_sessions.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_sessions.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_sessions.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_sessions.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_sessions.cpython-34-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_static.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_static.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_static.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_static.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_static.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_static.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_static.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_static.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_static.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_static.cpython-34-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_unicode.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_unicode.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_unicode.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_unicode.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_unicode.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_unicode.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_unicode.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_unicode.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_unicode.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_unicode.cpython-34-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_utils.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_utils.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_utils.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_utils.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_utils.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_utils.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_utils.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_utils.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_utils.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_utils.cpython-34-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_value.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_value.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_value.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_value.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_value.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_value.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_value.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_value.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_value.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_value.cpython-34-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_vpath_args.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_vpath_args.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_vpath_args.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_vpath_args.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_vpath_args.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_vpath_args.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_vpath_args.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_vpath_args.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_vpath_args.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_vpath_args.cpython-34-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_websockets.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_websockets.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_websockets.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_websockets.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_websockets.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_websockets.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_websockets.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_websockets.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_websockets.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_websockets.cpython-34-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_wsgi_application.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_wsgi_application.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_wsgi_application.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_wsgi_application.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_wsgi_application.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_wsgi_application.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_wsgi_application.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_wsgi_application.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_wsgi_application.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_wsgi_application.cpython-34-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_wsgi_application_generator.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_wsgi_application_generator.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_wsgi_application_generator.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_wsgi_application_generator.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_wsgi_application_generator.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_wsgi_application_generator.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_wsgi_application_generator.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_wsgi_application_generator.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_wsgi_application_generator.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_wsgi_application_generator.cpython-34-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_wsgi_application_yield.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_wsgi_application_yield.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_wsgi_application_yield.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_wsgi_application_yield.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_wsgi_application_yield.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_wsgi_application_yield.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_wsgi_application_yield.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_wsgi_application_yield.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_wsgi_application_yield.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_wsgi_application_yield.cpython-34-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_wsgi_gateway.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_wsgi_gateway.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_wsgi_gateway.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_wsgi_gateway.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_wsgi_gateway.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_wsgi_gateway.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_wsgi_gateway.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_wsgi_gateway.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_wsgi_gateway.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_wsgi_gateway.cpython-34-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_wsgi_gateway_errors.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_wsgi_gateway_errors.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_wsgi_gateway_errors.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_wsgi_gateway_errors.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_wsgi_gateway_errors.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_wsgi_gateway_errors.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_wsgi_gateway_errors.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_wsgi_gateway_errors.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_wsgi_gateway_errors.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_wsgi_gateway_errors.cpython-34-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_wsgi_gateway_generator.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_wsgi_gateway_generator.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_wsgi_gateway_generator.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_wsgi_gateway_generator.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_wsgi_gateway_generator.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_wsgi_gateway_generator.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_wsgi_gateway_generator.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_wsgi_gateway_generator.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_wsgi_gateway_generator.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_wsgi_gateway_generator.cpython-34-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_wsgi_gateway_multiple_apps.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_wsgi_gateway_multiple_apps.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_wsgi_gateway_multiple_apps.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_wsgi_gateway_multiple_apps.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_wsgi_gateway_multiple_apps.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_wsgi_gateway_multiple_apps.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_wsgi_gateway_multiple_apps.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_wsgi_gateway_multiple_apps.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_wsgi_gateway_multiple_apps.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_wsgi_gateway_multiple_apps.cpython-34-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_wsgi_gateway_null_response.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_wsgi_gateway_null_response.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_wsgi_gateway_null_response.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_wsgi_gateway_null_response.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_wsgi_gateway_null_response.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_wsgi_gateway_null_response.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_wsgi_gateway_null_response.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_wsgi_gateway_null_response.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_wsgi_gateway_null_response.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_wsgi_gateway_null_response.cpython-34-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_wsgi_gateway_write.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_wsgi_gateway_write.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_wsgi_gateway_write.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_wsgi_gateway_write.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_wsgi_gateway_write.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_wsgi_gateway_write.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_wsgi_gateway_write.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_wsgi_gateway_write.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_wsgi_gateway_write.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_wsgi_gateway_write.cpython-34-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_wsgi_gateway_yield.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_wsgi_gateway_yield.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_wsgi_gateway_yield.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_wsgi_gateway_yield.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_wsgi_gateway_yield.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_wsgi_gateway_yield.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_wsgi_gateway_yield.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_wsgi_gateway_yield.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_wsgi_gateway_yield.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_wsgi_gateway_yield.cpython-34-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_xmlrpc.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_xmlrpc.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_xmlrpc.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_xmlrpc.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_xmlrpc.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_xmlrpc.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_xmlrpc.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_xmlrpc.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_xmlrpc.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_xmlrpc.cpython-34-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_yield.cpython-26-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_yield.cpython-26-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_yield.cpython-27-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_yield.cpython-27-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_yield.cpython-32-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_yield.cpython-32-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_yield.cpython-33-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_yield.cpython-33-PYTEST.pyc differ Binary files /tmp/tmpiol8g5wb/w4yU4LDiEB/circuits-3.1.0+ds1/tests/web/__pycache__/test_yield.cpython-34-PYTEST.pyc and /tmp/tmpiol8g5wb/fO4rWx1bED/circuits-3.2.2/tests/web/__pycache__/test_yield.cpython-34-PYTEST.pyc differ diff -Nru circuits-3.1.0+ds1/tests/web/test_bad_requests.py circuits-3.2.2/tests/web/test_bad_requests.py --- circuits-3.1.0+ds1/tests/web/test_bad_requests.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/web/test_bad_requests.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,12 +1,10 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- - try: from httplib import HTTPConnection except ImportError: from http.client import HTTPConnection # NOQA -from circuits.six import b from circuits.web import Controller @@ -22,7 +20,7 @@ connection.putrequest("GET", "/", "HTTP/1.1") connection.putheader("Connection", "close") - connection._output(b("X-Foo")) # Bad Header + connection._output(b"X-Foo") # Bad Header connection.endheaders() response = connection.getresponse() diff -Nru circuits-3.1.0+ds1/tests/web/test_basicauth.py circuits-3.2.2/tests/web/test_basicauth.py --- circuits-3.1.0+ds1/tests/web/test_basicauth.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/web/test_basicauth.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,8 +1,9 @@ from circuits.web import Controller -from circuits.web.tools import check_auth, basic_auth +from circuits.web.tools import basic_auth, check_auth -from .helpers import HTTPError, HTTPBasicAuthHandler -from .helpers import urlopen, build_opener, install_opener +from .helpers import ( + HTTPBasicAuthHandler, HTTPError, build_opener, install_opener, urlopen, +) class Root(Controller): diff -Nru circuits-3.1.0+ds1/tests/web/test_call_wait.py circuits-3.2.2/tests/web/test_call_wait.py --- circuits-3.1.0+ds1/tests/web/test_call_wait.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/web/test_call_wait.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,12 +1,12 @@ #!/usr/bin/env python - -from circuits.web import Controller from circuits import Component, Event +from circuits.web import Controller from .helpers import urlopen class foo(Event): + """foo Event""" diff -Nru circuits-3.1.0+ds1/tests/web/test_client.py circuits-3.2.2/tests/web/test_client.py --- circuits-3.1.0+ds1/tests/web/test_client.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/web/test_client.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,7 +1,5 @@ #!/usr/bin/env python - from circuits.web import Controller - from circuits.web.client import Client, request diff -Nru circuits-3.1.0+ds1/tests/web/test_conn.py circuits-3.2.2/tests/web/test_conn.py --- circuits-3.1.0+ds1/tests/web/test_conn.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/web/test_conn.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,5 +1,4 @@ #!/usr/bin/env python - try: from httplib import HTTPConnection except ImportError: @@ -9,6 +8,7 @@ class Root(Controller): + def index(self): return "Hello World!" diff -Nru circuits-3.1.0+ds1/tests/web/test_cookies.py circuits-3.2.2/tests/web/test_cookies.py --- circuits-3.1.0+ds1/tests/web/test_cookies.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/web/test_cookies.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,12 +1,11 @@ #!/usr/bin/env python - from circuits.web import Controller -from .helpers import build_opener, HTTPCookieProcessor -from .helpers import CookieJar +from .helpers import CookieJar, HTTPCookieProcessor, build_opener class Root(Controller): + def index(self): visited = self.cookie.get("visited") if visited and visited.value: diff -Nru circuits-3.1.0+ds1/tests/web/test_core.py circuits-3.2.2/tests/web/test_core.py --- circuits-3.1.0+ds1/tests/web/test_core.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/web/test_core.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,13 +1,9 @@ #!/usr/bin/env python - import pytest - -from circuits.six import b, u from circuits.web import Controller - -from .helpers import urlencode, urlopen, HTTPError +from .helpers import HTTPError, urlencode, urlopen class Root(Controller): @@ -62,16 +58,16 @@ @pytest.mark.parametrize("data,expected", [ - ((["1"], {}), b("a=1\nb=None")), - ((["1", "2"], {}), b("a=1\nb=2")), - ((["1"], {"b": "2"}), b("a=1\nb=2")), + ((["1"], {}), b"a=1\nb=None"), + ((["1", "2"], {}), b"a=1\nb=2"), + ((["1"], {"b": "2"}), b"a=1\nb=2"), ]) def test_default_args(webapp, data, expected): args, kwargs = data - url = u("{0:s}/test_default_args/{1:s}".format( + url = u"{0:s}/test_default_args/{1:s}".format( webapp.server.http.base, - u("/").join(args) - )) + u"/".join(args) + ) data = urlencode(kwargs).encode("utf-8") f = urlopen(url, data) assert f.read() == expected diff -Nru circuits-3.1.0+ds1/tests/web/test_digestauth.py circuits-3.2.2/tests/web/test_digestauth.py --- circuits-3.1.0+ds1/tests/web/test_digestauth.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/web/test_digestauth.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,14 +1,14 @@ #!/usr/bin/env python - import pytest -if pytest.PYVER[:2] == (3, 3): - pytest.skip("Broken on Python 3.3") from circuits.web import Controller from circuits.web.tools import check_auth, digest_auth -from .helpers import HTTPError, HTTPDigestAuthHandler -from .helpers import urlopen, build_opener, install_opener +from .helpers import ( + HTTPDigestAuthHandler, HTTPError, build_opener, install_opener, urlopen, +) + +pytestmark = pytest.mark.skipif(pytest.PYVER[:2] == (3, 3), reason='Broken on Python 3.3') class Root(Controller): diff -Nru circuits-3.1.0+ds1/tests/web/test_dispatcher2.py circuits-3.2.2/tests/web/test_dispatcher2.py --- circuits-3.1.0+ds1/tests/web/test_dispatcher2.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/web/test_dispatcher2.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,12 +1,12 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- - -from circuits.web import expose, Controller +from circuits.web import Controller, expose from .helpers import urlopen class Root(Controller): + def __init__(self, *args, **kwargs): super(Root, self).__init__(*args, **kwargs) self += Hello() diff -Nru circuits-3.1.0+ds1/tests/web/test_dispatcher3.py circuits-3.2.2/tests/web/test_dispatcher3.py --- circuits-3.1.0+ds1/tests/web/test_dispatcher3.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/web/test_dispatcher3.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,16 +1,14 @@ #!/usr/bin/env python - import pytest +from circuits.web import Controller + try: from httplib import HTTPConnection except ImportError: from http.client import HTTPConnection # NOQA -from circuits.web import Controller - - class Root(Controller): def GET(self): diff -Nru circuits-3.1.0+ds1/tests/web/test_dispatcher.py circuits-3.2.2/tests/web/test_dispatcher.py --- circuits-3.1.0+ds1/tests/web/test_dispatcher.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/web/test_dispatcher.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,10 +1,10 @@ #!/usr/bin/env python - from circuits.web import Controller from circuits.web.client import Client, request class Root(Controller): + def __init__(self, *args, **kwargs): super(Root, self).__init__(*args, **kwargs) self += Leaf() @@ -57,14 +57,16 @@ def test_leaf(webapp): - status, content = make_request(webapp, "%s/world/country/region" % webapp.server.http.base) + status, content = make_request( + webapp, "%s/world/country/region" % webapp.server.http.base) assert status == 200 assert content == b"Hello cities!" def test_city(webapp): - status, content = make_request(webapp, "%s/world/country/region/city" % webapp.server.http.base) + status, content = make_request( + webapp, "%s/world/country/region/city" % webapp.server.http.base) assert status == 200 assert content == b"Hello City!" diff -Nru circuits-3.1.0+ds1/tests/web/test_disps.py circuits-3.2.2/tests/web/test_disps.py --- circuits-3.1.0+ds1/tests/web/test_disps.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/web/test_disps.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,21 +1,15 @@ #!/usr/bin/env python - -from circuits.core.manager import Manager -from circuits.core.handlers import handler from circuits.core.components import BaseComponent - +from circuits.core.handlers import handler from circuits.web import BaseServer, Controller from circuits.web.dispatchers.dispatcher import Dispatcher -from .helpers import urlopen, urljoin +from .helpers import urljoin, urlopen class PrefixingDispatcher(BaseComponent): """Forward to another Dispatcher based on the channel.""" - def __init__(self, channel): - super(PrefixingDispatcher, self).__init__(channel=channel) - @handler("request", priority=1.0) def _on_request(self, event, request, response): path = request.path.strip("/") @@ -48,24 +42,20 @@ return "Hello from site 2!" -def test_disps(): - - manager = Manager() - - server1 = BaseServer(0, channel="site1") - server1.register(manager) - PrefixingDispatcher(channel="site1").register(server1) - Dispatcher(channel="site1").register(server1) +def test_disps(manager, watcher): + server1 = BaseServer(0, channel="site1").register(manager) + PrefixingDispatcher(channel="site1").register(manager) + Dispatcher(channel="site1").register(manager) Root1().register(manager) + assert watcher.wait("ready", channel=server1.channel) - server2 = BaseServer(("localhost", 0), channel="site2") - server2.register(manager) - PrefixingDispatcher(channel="site2").register(server2) - Dispatcher(channel="site2").register(server2) + server2 = BaseServer(("localhost", 0), channel="site2").register(manager) + PrefixingDispatcher(channel="site2").register(manager) + Dispatcher(channel="site2").register(manager) Root2().register(manager) + assert watcher.wait("ready", channel=server2.channel) DummyRoot().register(manager) - manager.start() f = urlopen(server1.http.base, timeout=3) s = f.read() diff -Nru circuits-3.1.0+ds1/tests/web/test_exceptions.py circuits-3.2.2/tests/web/test_exceptions.py --- circuits-3.1.0+ds1/tests/web/test_exceptions.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/web/test_exceptions.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,9 +1,10 @@ #!/usr/bin/env python +import json from circuits.web import Controller from circuits.web.exceptions import Forbidden, NotFound, Redirect -from .helpers import urlopen, HTTPError +from .helpers import HTTPError, urlopen class Root(Controller): @@ -21,7 +22,15 @@ raise NotFound() def test_contenttype(self): + raise Exception() + + def test_contenttype_json(self): + self.response.headers["Content-Type"] = "application/json" + raise Exception() + + def test_contenttype_json_no_debug(self): self.response.headers["Content-Type"] = "application/json" + self.request.print_debug = False raise Exception() @@ -53,10 +62,39 @@ def test_contenttype(webapp): try: - f = urlopen("%s/test_contenttype" % webapp.server.http.base) + urlopen("%s/test_contenttype" % webapp.server.http.base) except HTTPError as e: assert e.code == 500 assert e.msg == "Internal Server Error" - assert e.headers.get("Content-Type") == "text/html" + assert "text/html" in e.headers.get("Content-Type") + else: + assert False + + +def test_contenttype_json(webapp): + try: + urlopen("%s/test_contenttype_json" % webapp.server.http.base) + except HTTPError as e: + assert "json" in e.headers.get("Content-Type") + result = json.loads(e.read().decode("utf-8")) + assert result["code"] == 500 + assert result["name"] == "Internal Server Error" + assert result["description"] == "" + assert "raise Exception" in result["traceback"] + else: + assert False + + +def test_contenttype_json_no_debug(webapp): + try: + urlopen("%s/test_contenttype_json_no_debug" % + webapp.server.http.base) + except HTTPError as e: + assert "json" in e.headers.get("Content-Type") + result = json.loads(e.read().decode("utf-8")) + assert result["code"] == 500 + assert result["name"] == "Internal Server Error" + assert result["description"] == "" + assert "traceback" not in result else: assert False diff -Nru circuits-3.1.0+ds1/tests/web/test_expires.py circuits-3.2.2/tests/web/test_expires.py --- circuits-3.1.0+ds1/tests/web/test_expires.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/web/test_expires.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,8 +1,7 @@ #!/usr/bin/env python - from datetime import datetime -from time import mktime from email.utils import parsedate +from time import mktime from circuits.web import Controller @@ -39,7 +38,7 @@ cacheControl = f.headers["Cache-Control"] now = datetime.utcnow() - lastyear = now.replace(year=now.year-1) + lastyear = now.replace(year=now.year - 1) diff = (mktime(parsedate(expires)) - mktime(lastyear.utctimetuple())) assert diff < 1.0 diff -Nru circuits-3.1.0+ds1/tests/web/test_expose.py circuits-3.2.2/tests/web/test_expose.py --- circuits-3.1.0+ds1/tests/web/test_expose.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/web/test_expose.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,4 +1,4 @@ -from circuits.web import expose, Controller +from circuits.web import Controller, expose from .helpers import urlopen diff -Nru circuits-3.1.0+ds1/tests/web/test_generator.py circuits-3.2.2/tests/web/test_generator.py --- circuits-3.1.0+ds1/tests/web/test_generator.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/web/test_generator.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,5 +1,4 @@ #!/usr/bin/env python - from circuits.web import Controller from .helpers import urlopen diff -Nru circuits-3.1.0+ds1/tests/web/test_gzip.py circuits-3.2.2/tests/web/test_gzip.py --- circuits-3.1.0+ds1/tests/web/test_gzip.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/web/test_gzip.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,20 +1,15 @@ #!/usr/bin/env python - - -from pytest import fixture - - -from os import path from io import BytesIO +from os import path +from pytest import fixture +from circuits import Component, handler from circuits.web import Controller from circuits.web.tools import gzip -from circuits import handler, Component - from .conftest import DOCROOT -from .helpers import build_opener, Request +from .helpers import Request, build_opener class Gzip(Component): @@ -32,7 +27,7 @@ return "Hello World!" -@fixture(scope="module") +@fixture def gziptool(request, webapp): gziptool = Gzip().register(webapp) diff -Nru circuits-3.1.0+ds1/tests/web/test_headers.py circuits-3.2.2/tests/web/test_headers.py --- circuits-3.1.0+ds1/tests/web/test_headers.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/web/test_headers.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,5 +1,4 @@ #!/usr/bin/env python - from circuits.web import Controller from .helpers import urlopen diff -Nru circuits-3.1.0+ds1/tests/web/test_http.py circuits-3.2.2/tests/web/test_http.py --- circuits-3.1.0+ds1/tests/web/test_http.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/web/test_http.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,15 +1,15 @@ #!/usr/bin/env python - import pytest from circuits import Component +from circuits.net.events import connect, write +from circuits.net.sockets import TCPClient from circuits.web import Controller from circuits.web.client import parse_url -from circuits.net.sockets import TCPClient -from circuits.net.events import connect, write class Client(Component): + def __init__(self, *args, **kwargs): super(Client, self).__init__(*args, **kwargs) self._buffer = [] @@ -41,10 +41,50 @@ assert pytest.wait_for(transport, "connected") client.fire(write(b"GET / HTTP/1.1\r\n")) + client.fire(write(b"Host: localhost\r\n\r\n")) client.fire(write(b"Content-Type: text/plain\r\n\r\n")) assert pytest.wait_for(client, "done") client.stop() + ss = client.buffer().decode('utf-8') + s = ss.split('\r\n')[0] + assert s == "HTTP/1.1 200 OK", ss + + +def test_http_1_0(webapp): + transport = TCPClient() + client = Client() + client += transport + client.start() + + host, port, resource, secure = parse_url(webapp.server.http.base) + client.fire(connect(host, port)) + assert pytest.wait_for(transport, "connected") + + client.fire(write(b"GET / HTTP/1.0\r\n\r\n")) + assert pytest.wait_for(client, "done") + + client.stop() + + s = client.buffer().decode('utf-8').split('\r\n')[0] + assert s == "HTTP/1.0 200 OK" + + +def test_http_1_1_no_host_headers(webapp): + transport = TCPClient() + client = Client() + client += transport + client.start() + + host, port, resource, secure = parse_url(webapp.server.http.base) + client.fire(connect(host, port)) + assert pytest.wait_for(transport, "connected") + + client.fire(write(b"GET / HTTP/1.1\r\n\r\n")) + assert pytest.wait_for(client, "done") + + client.stop() + s = client.buffer().decode('utf-8').split('\r\n')[0] - assert s == "HTTP/1.1 200 OK" + assert s == "HTTP/1.1 400 Bad Request" diff -Nru circuits-3.1.0+ds1/tests/web/test_json.py circuits-3.2.2/tests/web/test_json.py --- circuits-3.1.0+ds1/tests/web/test_json.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/web/test_json.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,11 +1,9 @@ #!/usr/bin/env python - from json import loads from circuits.web import JSONController, Sessions -from .helpers import urlopen, build_opener, HTTPCookieProcessor -from .helpers import CookieJar +from .helpers import CookieJar, HTTPCookieProcessor, build_opener, urlopen class Root(JSONController): @@ -15,7 +13,8 @@ def test_sessions(self, name=None): if name: - self.session["name"] = name + with self.session as data: + data["name"] = name else: name = self.session.get("name", "World!") diff -Nru circuits-3.1.0+ds1/tests/web/test_jsonrpc.py circuits-3.2.2/tests/web/test_jsonrpc.py --- circuits-3.1.0+ds1/tests/web/test_jsonrpc.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/web/test_jsonrpc.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,10 +1,9 @@ #!/usr/bin/env python - from circuits import Component -from circuits.web import Controller, JSONRPC +from circuits.web import JSONRPC, Controller -from .jsonrpclib import ServerProxy from .helpers import urlopen +from .jsonrpclib import ServerProxy class App(Component): diff -Nru circuits-3.1.0+ds1/tests/web/test_large_post.py circuits-3.2.2/tests/web/test_large_post.py --- circuits-3.1.0+ds1/tests/web/test_large_post.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/web/test_large_post.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,5 +1,4 @@ #!/usr/bin/env python - from circuits.web import Controller from .helpers import urlencode, urlopen diff -Nru circuits-3.1.0+ds1/tests/web/test_logger.py circuits-3.2.2/tests/web/test_logger.py --- circuits-3.1.0+ds1/tests/web/test_logger.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/web/test_logger.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,18 +1,17 @@ #!/usr/bin/env python - +import re import sys - -try: - from StringIO import StringIO -except ImportError: - from io import StringIO # NOQA - from socket import gaierror, gethostbyname, gethostname from circuits.web import Controller, Logger from .helpers import urlopen +try: + from StringIO import StringIO +except ImportError: + from io import StringIO # NOQA + class DummyLogger(object): @@ -61,7 +60,11 @@ keys = list(d.keys()) for k in keys: - assert d[k] in s + if d[k] and d[k].startswith("127."): + # loopback network: 127.0.0.0/8 + assert re.search(r"127(\.[0-9]{1,3}){3}", s) + else: + assert d[k] in s logfile.close() logger.unregister() @@ -96,7 +99,11 @@ keys = list(d.keys()) for k in keys: - assert d[k] in s + if d[k] and d[k].startswith("127."): + # loopback network: 127.0.0.0/8 + assert re.search(r"127(\.[0-9]{1,3}){3}", s) + else: + assert d[k] in s logger.unregister() @@ -133,7 +140,11 @@ keys = list(d.keys()) for k in keys: - assert d[k] in s + if d[k] and d[k].startswith("127."): + # loopback network: 127.0.0.0/8 + assert re.search(r"127(\.[0-9]{1,3}){3}", s) + else: + assert d[k] in s logfile.close() logger.unregister() diff -Nru circuits-3.1.0+ds1/tests/web/test_methods.py circuits-3.2.2/tests/web/test_methods.py --- circuits-3.1.0+ds1/tests/web/test_methods.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/web/test_methods.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,5 +1,4 @@ #!/usr/bin/env python - try: from httplib import HTTPConnection except ImportError: diff -Nru circuits-3.1.0+ds1/tests/web/test_multipartformdata.py circuits-3.2.2/tests/web/test_multipartformdata.py --- circuits-3.1.0+ds1/tests/web/test_multipartformdata.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/web/test_multipartformdata.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,14 +1,13 @@ #!/usr/bin/env python +from io import BytesIO +from os import path import pytest -from os import path -from io import BytesIO - from circuits.web import Controller +from .helpers import Request, urlopen from .multipartform import MultiPartForm -from .helpers import urlopen, Request @pytest.fixture() diff -Nru circuits-3.1.0+ds1/tests/web/test_null_response.py circuits-3.2.2/tests/web/test_null_response.py --- circuits-3.1.0+ds1/tests/web/test_null_response.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/web/test_null_response.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,6 +1,6 @@ from circuits.web import Controller -from .helpers import urlopen, HTTPError +from .helpers import HTTPError, urlopen class Root(Controller): diff -Nru circuits-3.1.0+ds1/tests/web/test_request_failure.py circuits-3.2.2/tests/web/test_request_failure.py --- circuits-3.1.0+ds1/tests/web/test_request_failure.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/web/test_request_failure.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,8 +1,8 @@ #!/usr/bin/env python - -from .helpers import urlopen, HTTPError -from circuits.core.handlers import handler from circuits.core.components import BaseComponent +from circuits.core.handlers import handler + +from .helpers import HTTPError, urlopen class Root(BaseComponent): diff -Nru circuits-3.1.0+ds1/tests/web/test_security.py circuits-3.2.2/tests/web/test_security.py --- circuits-3.1.0+ds1/tests/web/test_security.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/web/test_security.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,14 +1,13 @@ #!/usr/bin/env python - from circuits.web import Controller +from .helpers import HTTPError, urlopen + try: from httplib import HTTPConnection except ImportError: from http.client import HTTPConnection # NOQA -from .helpers import urlopen, HTTPError - class Root(Controller): diff -Nru circuits-3.1.0+ds1/tests/web/test_serve_download.py circuits-3.2.2/tests/web/test_serve_download.py --- circuits-3.1.0+ds1/tests/web/test_serve_download.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/web/test_serve_download.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,9 +1,7 @@ #!/usr/bin/env python - import os from tempfile import mkstemp -from circuits import handler from circuits.web import Controller from .helpers import urlopen @@ -11,14 +9,14 @@ class Root(Controller): - @handler("started", priority=1.0, channel="*") - def _on_started(self, component): + def __init__(self, *args, **kwargs): + super(Root, self).__init__(*args, **kwargs) + fd, self.filename = mkstemp() os.write(fd, b"Hello World!") os.close(fd) - @handler("stopped", channel="(") - def _on_stopped(self, component): + def __del__(self): os.remove(self.filename) def index(self): diff -Nru circuits-3.1.0+ds1/tests/web/test_serve_file.py circuits-3.2.2/tests/web/test_serve_file.py --- circuits-3.1.0+ds1/tests/web/test_serve_file.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/web/test_serve_file.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,9 +1,7 @@ #!/usr/bin/env python - import os from tempfile import mkstemp -from circuits import handler from circuits.web import Controller from .helpers import urlopen @@ -11,14 +9,14 @@ class Root(Controller): - @handler("started", priority=1.0, channel="*") - def _on_started(self, component): + def __init__(self, *args, **kwargs): + super(Root, self).__init__(self, *args, **kwargs) + fd, self.filename = mkstemp() os.write(fd, b"Hello World!") os.close(fd) - @handler("stopped", channel="(") - def _on_stopped(self, component): + def __del__(self): os.remove(self.filename) def index(self): diff -Nru circuits-3.1.0+ds1/tests/web/test_servers.py circuits-3.2.2/tests/web/test_servers.py --- circuits-3.1.0+ds1/tests/web/test_servers.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/web/test_servers.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,19 +1,36 @@ #!/usr/bin/env python - -import pytest - +import os +import ssl +import sys +import tempfile from os import path from socket import gaierror -from circuits.web import Controller -from circuits import handler, Component -from circuits.web import BaseServer, Server +import pytest +from pytest import fixture + +from circuits import Component +from circuits.web import BaseServer, Controller, Server -from .helpers import urlopen, URLError +from .helpers import URLError, urlopen CERTFILE = path.join(path.dirname(__file__), "cert.pem") +# self signed cert +if pytest.PYVER >= (2, 7, 9): + SSL_CONTEXT = ssl.SSLContext(ssl.PROTOCOL_SSLv23) + SSL_CONTEXT.verify_mode = ssl.CERT_NONE + + +@fixture +def tmpfile(request): + tmpdir = tempfile.mkdtemp() + filename = os.path.join(tmpdir, "test.sock") + + return filename + + class BaseRoot(Component): channel = "web" @@ -30,8 +47,9 @@ class MakeQuiet(Component): - @handler("ready", channel="*", priority=1.0) - def _on_ready(self, event, *args): + channel = "web" + + def ready(self, event, *args): event.stop() @@ -46,7 +64,7 @@ try: f = urlopen(server.http.base) except URLError as e: - if type(e[0]) is gaierror: + if isinstance(e.reason, gaierror): f = urlopen("http://127.0.0.1:9000") else: raise @@ -68,7 +86,7 @@ try: f = urlopen(server.http.base) except URLError as e: - if type(e[0]) is gaierror: + if isinstance(e.reason, gaierror): f = urlopen("http://127.0.0.1:9000") else: raise @@ -80,6 +98,10 @@ watcher.wait("unregistered") +@pytest.mark.skipif((2,) < sys.version_info < (3, 4, 3), + reason="Context not implemented under python 3.4.3") +@pytest.mark.skipif(sys.version_info < (2, 7, 9), + reason="Context not implemented under python 2.7.9") def test_secure_server(manager, watcher): pytest.importorskip("ssl") @@ -90,9 +112,9 @@ Root().register(server) try: - f = urlopen(server.http.base) + f = urlopen(server.http.base, context=SSL_CONTEXT) except URLError as e: - if type(e[0]) is gaierror: + if isinstance(e.reason, gaierror): f = urlopen("http://127.0.0.1:9000") else: raise @@ -104,25 +126,38 @@ watcher.wait("unregistered") -def test_unixserver(manager, watcher, tmpdir): +def test_unixserver(manager, watcher, tmpfile): if pytest.PLATFORM == "win32": pytest.skip("Unsupported Platform") - sockpath = tmpdir.ensure("test.sock") - socket = str(sockpath) - - server = Server(socket).register(manager) + server = Server(tmpfile).register(manager) MakeQuiet().register(server) - watcher.wait("ready") + assert watcher.wait("ready") Root().register(server) assert path.basename(server.host) == "test.sock" + try: + from uhttplib import UnixHTTPConnection + + client = UnixHTTPConnection(server.http.base) + client.request("GET", "/") + response = client.getresponse() + s = response.read() + + assert s == b"Hello World!" + except ImportError: + pass + server.unregister() watcher.wait("unregistered") +@pytest.mark.skipif((2, 7, 9) < sys.version_info < (3, 4, 3), + reason="Context not implemented under python 3.4.3") +@pytest.mark.skipif(sys.version_info < (2, 7, 9), + reason="Context not implemented under python 2.7.9") def test_multi_servers(manager, watcher): pytest.importorskip("ssl") @@ -142,7 +177,7 @@ s = f.read() assert s == b"Hello World!" - f = urlopen(secure_server.http.base) + f = urlopen(secure_server.http.base, context=SSL_CONTEXT) s = f.read() assert s == b"Hello World!" diff -Nru circuits-3.1.0+ds1/tests/web/test_sessions.py circuits-3.2.2/tests/web/test_sessions.py --- circuits-3.1.0+ds1/tests/web/test_sessions.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/web/test_sessions.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,9 +1,7 @@ #!/usr/bin/env python - from circuits.web import Controller, Sessions -from .helpers import build_opener, HTTPCookieProcessor -from .helpers import CookieJar +from .helpers import CookieJar, HTTPCookieProcessor, build_opener class Root(Controller): @@ -11,12 +9,17 @@ def index(self, vpath=None): if vpath: name = vpath - self.session["name"] = name + with self.session as data: + data["name"] = name else: name = self.session.get("name", "World!") return "Hello %s" % name + def logout(self): + self.session.expire() + return "OK" + def test(webapp): Sessions().register(webapp) @@ -35,3 +38,30 @@ f = opener.open(webapp.server.http.base) s = f.read() assert s == b"Hello test" + + +def test_expire(webapp): + Sessions().register(webapp) + + cj = CookieJar() + opener = build_opener(HTTPCookieProcessor(cj)) + + f = opener.open(webapp.server.http.base) + s = f.read() + assert s == b"Hello World!" + + f = opener.open(webapp.server.http.base + "/test") + s = f.read() + assert s == b"Hello test" + + f = opener.open(webapp.server.http.base) + s = f.read() + assert s == b"Hello test" + + f = opener.open(webapp.server.http.base + "/logout") + s = f.read() + assert s == b"OK" + + f = opener.open(webapp.server.http.base) + s = f.read() + assert s == b"Hello World!" diff -Nru circuits-3.1.0+ds1/tests/web/test_static.py circuits-3.2.2/tests/web/test_static.py --- circuits-3.1.0+ds1/tests/web/test_static.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/web/test_static.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,20 +1,17 @@ #!/usr/bin/env python - from os import path +from circuits.web import Controller + +from .conftest import DOCROOT +from .helpers import HTTPError, quote, urlopen + try: from httplib import HTTPConnection except ImportError: from http.client import HTTPConnection # NOQA -from circuits.web import Controller - - -from .conftest import DOCROOT -from .helpers import quote, urlopen, HTTPError - - class Root(Controller): def index(self): @@ -67,8 +64,9 @@ assert b"helloworld.txt" in s -def test_file_quoating(webapp): - url = "{0:s}{1:s}".format(webapp.server.http.base, quote("/static/#foobar.txt")) +def test_file_quooting(webapp): + url = "{0:s}{1:s}".format( + webapp.server.http.base, quote("/static/#foobar.txt")) f = urlopen(url) s = f.read().strip() assert s == b"Hello World!" @@ -77,7 +75,8 @@ def test_range(webapp): connection = HTTPConnection(webapp.server.host, webapp.server.port) - connection.request("GET", "%s/static/largefile.txt" % webapp.server.http.base, headers={"Range": "bytes=0-100"}) + connection.request("GET", "%s/static/largefile.txt" % + webapp.server.http.base, headers={"Range": "bytes=0-100"}) response = connection.getresponse() assert response.status == 206 s = response.read() @@ -87,30 +86,33 @@ def test_ranges(webapp): connection = HTTPConnection(webapp.server.host, webapp.server.port) - connection.request("GET", "%s/static/largefile.txt" % webapp.server.http.base, headers={"Range": "bytes=0-50,51-100"}) + connection.request("GET", "%s/static/largefile.txt" % + webapp.server.http.base, headers={"Range": "bytes=0-50,51-100"}) response = connection.getresponse() assert response.status == 206 # XXX Complete this test. # ``response.read()`` is a multipart/bytes-range # See: Issue #59 - #s = response.read() - #assert s == open(path.join(DOCROOT, "largefile.txt"), "rb").read(101) + # s = response.read() + # assert s == open(path.join(DOCROOT, "largefile.txt"), "rb").read(101) def test_unsatisfiable_range1(webapp): connection = HTTPConnection(webapp.server.host, webapp.server.port) - connection.request("GET", "%s/static/largefile.txt" % webapp.server.http.base, headers={"Range": "bytes=0-100,100-10000,0-1"}) + connection.request("GET", "%s/static/largefile.txt" % + webapp.server.http.base, headers={"Range": "bytes=0-100,100-10000,0-1"}) response = connection.getresponse() assert response.status == 416 # TODO: Implement this test and condition # e.g: For a 10 byte file; Range: bytes=0-1,2-3,4-5,6-7,8-9 -#def test_unsatisfiable_range2(webapp): +# def test_unsatisfiable_range2(webapp): # connection = HTTPConnection(webapp.server.host, webapp.server.port) # -# connection.request("GET", "%s/static/largefile.txt" % webapp.server.http.base, headers={"Range": "bytes=0-100,100-10000,0-1"}) +# connection.request("GET", "%s/static/largefile.txt" % (webapp.server.http.base, +# headers={"Range": "bytes=0-100,100-10000,0-1"})) # response = connection.getresponse() # assert response.status == 416 diff -Nru circuits-3.1.0+ds1/tests/web/test_unicode.py circuits-3.2.2/tests/web/test_unicode.py --- circuits-3.1.0+ds1/tests/web/test_unicode.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/web/test_unicode.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,12 +1,13 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- +import pytest + try: from httplib import HTTPConnection except ImportError: - from http.client import HTTPConnection # NOQA + from http.client import HTTPConnection # noqa -from circuits.six import b from circuits.web import Controller from circuits.web.client import Client, request @@ -31,24 +32,30 @@ self.response.headers["A"] = "ä" return "ä" + def argument(self, arg): + return arg + def test_index(webapp): f = urlopen(webapp.server.http.base) s = f.read() - assert s == b("Hello World!") + assert s == b"Hello World!" -def test_request_body(webapp): +@pytest.mark.parametrize('body', [ + u"ä".encode('utf-8'), + u"ä".encode('iso8859-1') +]) +def test_request_body(webapp, body): connection = HTTPConnection(webapp.server.host, webapp.server.port) connection.connect() - body = b("ä") connection.request("GET", "/request_body", body) response = connection.getresponse() assert response.status == 200 assert response.reason == "OK" s = response.read() - assert s == b("ä") + assert s == body connection.close() @@ -62,7 +69,7 @@ assert response.status == 200 assert response.reason == "OK" s = response.read() - assert s == b("ä") + assert s == u"ä".encode('utf-8') connection.close() @@ -71,14 +78,14 @@ connection = HTTPConnection(webapp.server.host, webapp.server.port) connection.connect() - body = b("") + body = b"" headers = {"A": "ä"} connection.request("GET", "/request_headers", body, headers) response = connection.getresponse() assert response.status == 200 assert response.reason == "OK" s = response.read() - assert s == b("ä") + assert s == u"ä".encode('utf-8') connection.close() @@ -102,4 +109,19 @@ s = client.response.read() a = client.response.headers.get('A') assert a == "ä" - assert s == b("ä") + assert s == u"ä".encode('utf-8') + + +def test_argument(webapp): + connection = HTTPConnection(webapp.server.host, webapp.server.port) + connection.connect() + + data = 'arg=%E2%86%92' + connection.request("POST", "/argument", data, {"Content-type": "application/x-www-form-urlencoded"}) + response = connection.getresponse() + assert response.status == 200 + assert response.reason == "OK" + s = response.read() + assert s.decode('utf-8') == u'\u2192' + + connection.close() diff -Nru circuits-3.1.0+ds1/tests/web/test_utils.py circuits-3.2.2/tests/web/test_utils.py --- circuits-3.1.0+ds1/tests/web/test_utils.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/web/test_utils.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,14 +1,13 @@ #!/usr/bin/env python - from io import BytesIO + +from circuits.web.utils import compress, get_ranges + try: from gzip import decompress except ImportError: import zlib - decompress = zlib.decompressobj(16+zlib.MAX_WBITS).decompress # NOQA - -from circuits.web.utils import compress -from circuits.web.utils import get_ranges + decompress = zlib.decompressobj(16 + zlib.MAX_WBITS).decompress # NOQA def test_ranges(): diff -Nru circuits-3.1.0+ds1/tests/web/test_value.py circuits-3.2.2/tests/web/test_value.py --- circuits-3.1.0+ds1/tests/web/test_value.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/web/test_value.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,12 +1,12 @@ #!/usr/bin/env python - +from circuits import Component, Event from circuits.web import Controller -from circuits import Event, Component from .helpers import urlopen class hello(Event): + """hello Event""" diff -Nru circuits-3.1.0+ds1/tests/web/test_vpath_args.py circuits-3.2.2/tests/web/test_vpath_args.py --- circuits-3.1.0+ds1/tests/web/test_vpath_args.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/web/test_vpath_args.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,6 +1,5 @@ #!/usr/bin/env python - -from circuits.web import expose, Controller +from circuits.web import Controller, expose from .helpers import urlopen diff -Nru circuits-3.1.0+ds1/tests/web/test_websockets.py circuits-3.2.2/tests/web/test_websockets.py --- circuits-3.1.0+ds1/tests/web/test_websockets.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/web/test_websockets.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,16 +1,13 @@ #!/usr/bin/env python - - from __future__ import print_function +import pytest from circuits import Component -from circuits.web.servers import Server +from circuits.net.sockets import BUFSIZE, close, write from circuits.web.controllers import Controller -from circuits.net.sockets import close, write from circuits.web.websockets import WebSocketClient, WebSocketsDispatcher - from .helpers import urlopen @@ -50,13 +47,10 @@ self.response = data -def test(manager, watcher, webapp): - server = Server(0).register(manager) - watcher.wait("ready") - - echo = Echo().register(server) - Root().register(server) - watcher.wait("registered", channel="wsserver") +@pytest.mark.parametrize('chunksize', [BUFSIZE, BUFSIZE + 1, BUFSIZE * 2]) +def test(manager, watcher, webapp, chunksize): + echo = Echo().register(webapp) + assert watcher.wait("registered", channel="wsserver") f = urlopen(webapp.server.http.base) s = f.read() @@ -64,26 +58,41 @@ watcher.clear() - WebSocketsDispatcher("/websocket").register(server) - watcher.wait("registered", channel="web") + WebSocketsDispatcher("/websocket").register(webapp) + assert watcher.wait("registered", channel="web") - uri = "ws://{0:s}:{1:d}/websocket".format(server.host, server.port) + uri = "ws://{0:s}:{1:d}/websocket".format( + webapp.server.host, webapp.server.port) WebSocketClient(uri).register(manager) client = Client().register(manager) - watcher.wait("registered", channel="wsclient") - watcher.wait("connected", channel="wsclient") + assert watcher.wait("registered", channel="wsclient") + assert watcher.wait("connected", channel="wsclient") + assert watcher.wait("connect", channel="wsserver") assert len(echo.clients) == 1 - watcher.wait("read", channel="ws") + assert watcher.wait("read", channel="ws") assert client.response.startswith("Welcome") watcher.clear() client.fire(write("Hello!"), "ws") - watcher.wait("read", channel="ws") + assert watcher.wait("read", channel="ws") assert client.response == "Received: Hello!" + watcher.clear() + + client.fire(write("World!"), "ws") + assert watcher.wait("read", channel="ws") + assert client.response == "Received: World!" + + watcher.clear() + + data = "A" * (chunksize + 1) + client.fire(write(data), "ws") + assert watcher.wait("read", channel="ws") + assert client.response == "Received: %s" % (data,) + f = urlopen(webapp.server.http.base) s = f.read() assert s == b"Hello World!" @@ -91,12 +100,8 @@ assert len(echo.clients) == 1 client.fire(close(), "ws") - watcher.wait("disconnect", channel="wsserver") + assert watcher.wait("disconnect", channel="wsserver") assert len(echo.clients) == 0 client.unregister() - watcher.wait("unregistered") - watcher.clear() - - server.unregister() - watcher.wait("unregistered") + assert watcher.wait("unregistered") diff -Nru circuits-3.1.0+ds1/tests/web/test_wsgi_application_generator.py circuits-3.2.2/tests/web/test_wsgi_application_generator.py --- circuits-3.1.0+ds1/tests/web/test_wsgi_application_generator.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/web/test_wsgi_application_generator.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,5 +1,4 @@ #!/usr/bin/env python - from circuits.web import Controller from circuits.web.wsgi import Application @@ -14,6 +13,7 @@ yield "World!" return response() + application = Application() + Root() diff -Nru circuits-3.1.0+ds1/tests/web/test_wsgi_application.py circuits-3.2.2/tests/web/test_wsgi_application.py --- circuits-3.1.0+ds1/tests/web/test_wsgi_application.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/web/test_wsgi_application.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,9 +1,8 @@ #!/usr/bin/env python - from circuits.web import Controller from circuits.web.wsgi import Application -from .helpers import urlencode, urlopen, HTTPError +from .helpers import HTTPError, urlencode, urlopen class Root(Controller): @@ -24,6 +23,7 @@ def test_notfound(self): return self.notfound() + application = Application() + Root() diff -Nru circuits-3.1.0+ds1/tests/web/test_wsgi_application_yield.py circuits-3.2.2/tests/web/test_wsgi_application_yield.py --- circuits-3.1.0+ds1/tests/web/test_wsgi_application_yield.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/web/test_wsgi_application_yield.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,5 +1,4 @@ #!/usr/bin/env python - from circuits.web import Controller from circuits.web.wsgi import Application @@ -12,6 +11,7 @@ yield "Hello " yield "World!" + application = Application() + Root() diff -Nru circuits-3.1.0+ds1/tests/web/test_wsgi_gateway_errors.py circuits-3.2.2/tests/web/test_wsgi_gateway_errors.py --- circuits-3.1.0+ds1/tests/web/test_wsgi_gateway_errors.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/web/test_wsgi_gateway_errors.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,4 +1,4 @@ -from .helpers import urlopen, HTTPError +from .helpers import HTTPError, urlopen def application(environ, start_response): diff -Nru circuits-3.1.0+ds1/tests/web/test_wsgi_gateway_generator.py circuits-3.2.2/tests/web/test_wsgi_gateway_generator.py --- circuits-3.1.0+ds1/tests/web/test_wsgi_gateway_generator.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/web/test_wsgi_gateway_generator.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,5 +1,4 @@ #!/usr/bin/env python - from .helpers import urlopen diff -Nru circuits-3.1.0+ds1/tests/web/test_wsgi_gateway_multiple_apps.py circuits-3.2.2/tests/web/test_wsgi_gateway_multiple_apps.py --- circuits-3.1.0+ds1/tests/web/test_wsgi_gateway_multiple_apps.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/web/test_wsgi_gateway_multiple_apps.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,8 +1,5 @@ #!/usr/bin/env python - import pytest -if pytest.PYVER[:2] == (3, 3): - pytest.skip("Broken on Python 3.3") from circuits.web import Server from circuits.web.wsgi import Gateway diff -Nru circuits-3.1.0+ds1/tests/web/test_wsgi_gateway_null_response.py circuits-3.2.2/tests/web/test_wsgi_gateway_null_response.py --- circuits-3.1.0+ds1/tests/web/test_wsgi_gateway_null_response.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/web/test_wsgi_gateway_null_response.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,9 +1,8 @@ #!/usr/bin/env python +from circuits.web import Controller from .helpers import urlopen -from circuits.web import Controller - class Root(Controller): diff -Nru circuits-3.1.0+ds1/tests/web/test_wsgi_gateway.py circuits-3.2.2/tests/web/test_wsgi_gateway.py --- circuits-3.1.0+ds1/tests/web/test_wsgi_gateway.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/web/test_wsgi_gateway.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,5 +1,4 @@ #!/usr/bin/env python - from .helpers import urlopen diff -Nru circuits-3.1.0+ds1/tests/web/test_wsgi_gateway_write.py circuits-3.2.2/tests/web/test_wsgi_gateway_write.py --- circuits-3.1.0+ds1/tests/web/test_wsgi_gateway_write.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/web/test_wsgi_gateway_write.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,5 +1,4 @@ #!/usr/bin/env python - from .helpers import urlopen diff -Nru circuits-3.1.0+ds1/tests/web/test_wsgi_gateway_yield.py circuits-3.2.2/tests/web/test_wsgi_gateway_yield.py --- circuits-3.1.0+ds1/tests/web/test_wsgi_gateway_yield.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/web/test_wsgi_gateway_yield.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,5 +1,4 @@ #!/usr/bin/env python - from .helpers import urlopen diff -Nru circuits-3.1.0+ds1/tests/web/test_xmlrpc.py circuits-3.2.2/tests/web/test_xmlrpc.py --- circuits-3.1.0+ds1/tests/web/test_xmlrpc.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/web/test_xmlrpc.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,12 +1,11 @@ #!/usr/bin/env python - try: from xmlrpc.client import ServerProxy except ImportError: from xmlrpclib import ServerProxy # NOQA from circuits import Component -from circuits.web import Controller, XMLRPC +from circuits.web import XMLRPC, Controller from .helpers import urlopen diff -Nru circuits-3.1.0+ds1/tests/web/test_yield.py circuits-3.2.2/tests/web/test_yield.py --- circuits-3.1.0+ds1/tests/web/test_yield.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/web/test_yield.py 2021-10-19 16:23:49.000000000 +0000 @@ -1,5 +1,4 @@ #!/usr/bin/env python - from circuits.web import Controller from .helpers import urlopen diff -Nru circuits-3.1.0+ds1/tests/web/websocket.py circuits-3.2.2/tests/web/websocket.py --- circuits-3.1.0+ds1/tests/web/websocket.py 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tests/web/websocket.py 2021-10-19 16:23:49.000000000 +0000 @@ -18,17 +18,14 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA """ - - -import socket +import logging import random +import socket import struct from hashlib import md5 -import logging from .helpers import urlparse - logger = logging.getLogger() @@ -39,6 +36,7 @@ class ConnectionClosedException(WebSocketException): pass + default_timeout = None traceEnabled = False @@ -117,6 +115,7 @@ websock.connect(url, **options) return websock + _MAX_INTEGER = (1 << 32) - 1 _AVAILABLE_KEY_CHARS = list(range(0x21, 0x2f + 1)).extend( list(range(0x3a, 0x7e + 1)) @@ -139,7 +138,7 @@ pos = random.randint(0, len(key_n)) key_n = key_n[0:pos] + chr(c) + key_n[pos:] for i in range(spaces_n): - pos = random.randint(1, len(key_n)-1) + pos = random.randint(1, len(key_n) - 1) key_n = key_n[0:pos] + " " + key_n[pos:] return number_n, key_n @@ -148,6 +147,7 @@ def _create_key3(): return "".join([chr(random.randint(0, _MAX_ASCII_BYTE)) for i in range(8)]) + HEADERS_TO_CHECK = { "upgrade": "websocket", "connection": "upgrade", @@ -177,6 +177,7 @@ class WebSocket(object): + """ Low level WebSocket interface. This class is based on @@ -194,6 +195,7 @@ 'Hello, Server' >>> ws.close() """ + def __init__(self): """ Initalize WebSocket object. @@ -293,7 +295,7 @@ return result def _validate_header(self, headers): - #TODO: check other headers + # TODO: check other headers for key, value in HEADERS_TO_CHECK.items(): v = headers.get(key, None) if value != v: @@ -412,11 +414,11 @@ result = self._recv(2) if result != "\xff\x00": logger.error("bad closing Handshake") - except: + except Exception: pass self.sock.settimeout(timeout) self.sock.shutdown(socket.SHUT_RDWR) - except: + except Exception: pass self._closeInternal() @@ -452,10 +454,12 @@ class WebSocketApp(object): + """ Higher level of APIs are provided. The interface is like JavaScript WebSocket object. """ + def __init__(self, url, on_open=None, on_message=None, on_error=None, on_close=None): @@ -527,7 +531,7 @@ if __name__ == "__main__": enableTrace(True) - #ws = create_connection("ws://localhost:8080/echo") + # ws = create_connection("ws://localhost:8080/echo") ws = create_connection("ws://localhost:5000/chat") print("Sending 'Hello, World'...") ws.send("Hello, World") diff -Nru circuits-3.1.0+ds1/tox.ini circuits-3.2.2/tox.ini --- circuits-3.1.0+ds1/tox.ini 2014-09-04 10:32:30.000000000 +0000 +++ circuits-3.2.2/tox.ini 2021-10-19 16:23:49.000000000 +0000 @@ -1,17 +1,18 @@ -# Tox (http://tox.testrun.org/) is a tool for running tests -# in multiple virtualenvs. This configuration file will run the -# test suite on all supported python versions. To use it, "pip install tox" -# and then run "tox" from this directory. - [tox] -envlist = py26,py27,py32,py33,py34,pypy -skip_missing_interpreters = True +envlist=docs,py27,py34,py35,py36,pypy +skip_missing_interpreters=True + +[pytest] +addopts=-r fsxX --durations=10 --ignore=tmp [testenv] -commands=py.test --cov=circuits --cov-report=html --junitxml=circuits-{envname}.xml tests -deps = - pytest-cov +commands=py.test {posargs} +extras= stomp +deps= pytest + pytest-cov + pytest-timeout +passenv=TEST_STOMP_* [testenv:docs] basepython=python @@ -19,4 +20,5 @@ deps= sphinx pytest -commands=py.test --tb=line -v --junitxml=circuits-docs-{envname}.xml check_docs.py + releases +commands=py.test --tb=native -v --junitxml=circuits-docs-{envname}.xml check_docs.py