From 2cea05f127499f42179b3699866b8e1444761b9f Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Wed, 17 Jun 2020 10:25:14 -0500 Subject: [PATCH] unbundle pysignals --- ouimeaux/discovery.py | 2 +- ouimeaux/pysignals/LICENSE.txt | 68 ----- ouimeaux/pysignals/__init__.py | 9 - ouimeaux/pysignals/dispatcher.py | 385 ------------------------ ouimeaux/pysignals/inspect.py | 131 -------- ouimeaux/pysignals/license.python.txt | 254 ---------------- ouimeaux/pysignals/weakref_backports.py | 68 ----- ouimeaux/signals.py | 2 +- requirements.txt | 1 + 9 files changed, 3 insertions(+), 917 deletions(-) delete mode 100644 ouimeaux/pysignals/LICENSE.txt delete mode 100644 ouimeaux/pysignals/__init__.py delete mode 100644 ouimeaux/pysignals/dispatcher.py delete mode 100644 ouimeaux/pysignals/inspect.py delete mode 100644 ouimeaux/pysignals/license.python.txt delete mode 100644 ouimeaux/pysignals/weakref_backports.py diff --git a/ouimeaux/discovery.py b/ouimeaux/discovery.py index 21bb2e7..a0c65a1 100644 --- a/ouimeaux/discovery.py +++ b/ouimeaux/discovery.py @@ -5,7 +5,7 @@ from gevent.server import DatagramServer from ouimeaux.utils import get_ip_address -from ouimeaux.pysignals import receiver +from pysignals import receiver from ouimeaux.signals import discovered diff --git a/ouimeaux/pysignals/LICENSE.txt b/ouimeaux/pysignals/LICENSE.txt deleted file mode 100644 index 77121f5..0000000 --- a/ouimeaux/pysignals/LICENSE.txt +++ /dev/null @@ -1,68 +0,0 @@ -pysignals was originally forked from django.dispatch. - -Copyright (c) Django Software Foundation and individual contributors. -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - 3. Neither the name of Django nor the names of its contributors may be used - to endorse or promote products derived from this software without - specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - - -django.dispatch was originally forked from PyDispatcher. - -PyDispatcher License: - - Copyright (c) 2001-2003, Patrick K. O'Brien and Contributors - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials - provided with the distribution. - - The name of Patrick K. O'Brien, or the name of any Contributor, - may not be used to endorse or promote products derived from this - software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - OF THE POSSIBILITY OF SUCH DAMAGE. - diff --git a/ouimeaux/pysignals/__init__.py b/ouimeaux/pysignals/__init__.py deleted file mode 100644 index 18b284c..0000000 --- a/ouimeaux/pysignals/__init__.py +++ /dev/null @@ -1,9 +0,0 @@ -"""Multi-consumer multi-producer dispatching mechanism - -Originally based on pydispatch (BSD) http://pypi.python.org/pypi/PyDispatcher/2.0.1 -See license.txt for original license. - -Heavily modified for Django's purposes. -""" - -from .dispatcher import Signal, StateChange, receiver # NOQA diff --git a/ouimeaux/pysignals/dispatcher.py b/ouimeaux/pysignals/dispatcher.py deleted file mode 100644 index 4baf101..0000000 --- a/ouimeaux/pysignals/dispatcher.py +++ /dev/null @@ -1,385 +0,0 @@ -from __future__ import absolute_import - -import sys -import threading -import weakref - -import logging - -from future.builtins import range -import six -from .inspect import func_accepts_kwargs - -if six.PY2: - from .weakref_backports import WeakMethod -else: - from weakref import WeakMethod - - -pysignals_debug = False - - -def set_debug( val ): - pysignals_debug = val - - -def _make_id(target): - if hasattr(target, '__func__'): - return (id(target.__self__), id(target.__func__)) - return id(target) -NONE_ID = _make_id(None) - -# A marker for caching -NO_RECEIVERS = object() - - -class Signal(object): - """ - Base class for all signals - - Internal attributes: - - receivers - { receiverkey (id) : weakref(receiver) } - """ - def __init__(self, providing_args=None, use_caching=False): - """ - Create a new signal. - - providing_args - A list of the arguments this signal can pass along in a send() call. - """ - self.receivers = [] - if providing_args is None: - providing_args = [] - self.providing_args = set(providing_args) - self.lock = threading.Lock() - self.use_caching = use_caching - # For convenience we create empty caches even if they are not used. - # A note about caching: if use_caching is defined, then for each - # distinct sender we cache the receivers that sender has in - # 'sender_receivers_cache'. The cache is cleaned when .connect() or - # .disconnect() is called and populated on send(). - self.sender_receivers_cache = weakref.WeakKeyDictionary() if use_caching else {} - self._dead_receivers = False - - def connect(self, receiver, sender=None, weak=True, dispatch_uid=None): - """ - Connect receiver to sender for signal. - - Arguments: - - receiver - A function or an instance method which is to receive signals. - Receivers must be hashable objects. - - If weak is True, then receiver must be weak referenceable. - - Receivers must be able to accept keyword arguments. - - If a receiver is connected with a dispatch_uid argument, it - will not be added if another receiver was already connected - with that dispatch_uid. - - sender - The sender to which the receiver should respond. Must either be - of type Signal, or None to receive events from any sender. - - weak - Whether to use weak references to the receiver. By default, the - module will attempt to use weak references to the receiver - objects. If this parameter is false, then strong references will - be used. - - dispatch_uid - An identifier used to uniquely identify a particular instance of - a receiver. This will usually be a string, though it may be - anything hashable. - """ - #from django.conf import settings - - # If DEBUG is on, check that we got a good receiver - if pysignals_debug: - import inspect - assert callable(receiver), "Signal receivers must be callable." - - # Check for **kwargs - if not func_accepts_kwargs(receiver): - raise ValueError("Signal receivers must accept keyword arguments (**kwargs).") - - if dispatch_uid: - lookup_key = (dispatch_uid, _make_id(sender)) - else: - lookup_key = (_make_id(receiver), _make_id(sender)) - - if weak: - ref = weakref.ref - receiver_object = receiver - # Check for bound methods - if hasattr(receiver, '__self__') and hasattr(receiver, '__func__'): - ref = WeakMethod - receiver_object = receiver.__self__ - if six.PY3: - receiver = ref(receiver) - weakref.finalize(receiver_object, self._remove_receiver) - else: - receiver = ref(receiver, self._remove_receiver) - - with self.lock: - self._clear_dead_receivers() - for r_key, _ in self.receivers: - if r_key == lookup_key: - break - else: - self.receivers.append((lookup_key, receiver)) - self.sender_receivers_cache.clear() - - def disconnect(self, receiver=None, sender=None, weak=None, dispatch_uid=None): - """ - Disconnect receiver from sender for signal. - - If weak references are used, disconnect need not be called. The receiver - will be remove from dispatch automatically. - - Arguments: - - receiver - The registered receiver to disconnect. May be none if - dispatch_uid is specified. - - sender - The registered sender to disconnect - - dispatch_uid - the unique identifier of the receiver to disconnect - """ - if weak is not None: - logging.WARNING("Passing `weak` to disconnect has no effect.") - if dispatch_uid: - lookup_key = (dispatch_uid, _make_id(sender)) - else: - lookup_key = (_make_id(receiver), _make_id(sender)) - - disconnected = False - with self.lock: - self._clear_dead_receivers() - for index in range(len(self.receivers)): - (r_key, _) = self.receivers[index] - if r_key == lookup_key: - disconnected = True - del self.receivers[index] - break - self.sender_receivers_cache.clear() - return disconnected - - def has_listeners(self, sender=None): - return bool(self._live_receivers(sender)) - - def send(self, sender, **named): - """ - Send signal from sender to all connected receivers. - - If any receiver raises an error, the error propagates back through send, - terminating the dispatch loop. So it's possible that all receivers - won't be called if an error is raised. - - Arguments: - - sender - The sender of the signal. Either a specific object or None. - - named - Named arguments which will be passed to receivers. - - Returns a list of tuple pairs [(receiver, response), ... ]. - """ - responses = [] - if not self.receivers or self.sender_receivers_cache.get(sender) is NO_RECEIVERS: - return responses - - for receiver in self._live_receivers(sender): - response = receiver(signal=self, sender=sender, **named) - responses.append((receiver, response)) - return responses - - def send_robust(self, sender, **named): - """ - Send signal from sender to all connected receivers catching errors. - - Arguments: - - sender - The sender of the signal. Can be any python object (normally one - registered with a connect if you actually want something to - occur). - - named - Named arguments which will be passed to receivers. These - arguments must be a subset of the argument names defined in - providing_args. - - Return a list of tuple pairs [(receiver, response), ... ]. May raise - DispatcherKeyError. - - If any receiver raises an error (specifically any subclass of - Exception), the error instance is returned as the result for that - receiver. The traceback is always attached to the error at - ``__traceback__``. - """ - responses = [] - if not self.receivers or self.sender_receivers_cache.get(sender) is NO_RECEIVERS: - return responses - - # Call each receiver with whatever arguments it can accept. - # Return a list of tuple pairs [(receiver, response), ... ]. - for receiver in self._live_receivers(sender): - try: - response = receiver(signal=self, sender=sender, **named) - except Exception as err: - if not hasattr(err, '__traceback__'): - err.__traceback__ = sys.exc_info()[2] - responses.append((receiver, err)) - else: - responses.append((receiver, response)) - return responses - - def _clear_dead_receivers(self): - # Note: caller is assumed to hold self.lock. - if self._dead_receivers: - self._dead_receivers = False - new_receivers = [] - for r in self.receivers: - if isinstance(r[1], weakref.ReferenceType) and r[1]() is None: - continue - new_receivers.append(r) - self.receivers = new_receivers - - def _live_receivers(self, sender): - """ - Filter sequence of receivers to get resolved, live receivers. - - This checks for weak references and resolves them, then returning only - live receivers. - """ - receivers = None - if self.use_caching and not self._dead_receivers: - receivers = self.sender_receivers_cache.get(sender) - # We could end up here with NO_RECEIVERS even if we do check this case in - # .send() prior to calling _live_receivers() due to concurrent .send() call. - if receivers is NO_RECEIVERS: - return [] - if receivers is None: - with self.lock: - self._clear_dead_receivers() - senderkey = _make_id(sender) - receivers = [] - for (receiverkey, r_senderkey), receiver in self.receivers: - if r_senderkey == NONE_ID or r_senderkey == senderkey: - receivers.append(receiver) - if self.use_caching: - if not receivers: - self.sender_receivers_cache[sender] = NO_RECEIVERS - else: - # Note, we must cache the weakref versions. - self.sender_receivers_cache[sender] = receivers - non_weak_receivers = [] - for receiver in receivers: - if isinstance(receiver, weakref.ReferenceType): - # Dereference the weak reference. - receiver = receiver() - if receiver is not None: - non_weak_receivers.append(receiver) - else: - non_weak_receivers.append(receiver) - return non_weak_receivers - - def _remove_receiver(self, receiver=None): - # Mark that the self.receivers list has dead weakrefs. If so, we will - # clean those up in connect, disconnect and _live_receivers while - # holding self.lock. Note that doing the cleanup here isn't a good - # idea, _remove_receiver() will be called as side effect of garbage - # collection, and so the call can happen while we are already holding - # self.lock. - self._dead_receivers = True - - def receive(self, **kwargs): - """ - A decorator for connecting receivers to this signal. Used by passing in the - keyword arguments to connect:: - - @post_save.receive(sender=MyModel) - def signal_receiver(sender, **kwargs): - ... - - """ - def _decorator(func): - self.connect(func, **kwargs) - return func - return _decorator - - -class StateChange( Signal ): - - def __init__(self, providing_args=None): - super(StateChange, self).__init__(providing_args) - self.sender_status = {} - - def send(self, sender, **named): - """ - Send signal from sender to all connected receivers *only if* the signal's - contents has changed. - - If any receiver raises an error, the error propagates back through send, - terminating the dispatch loop, so it is quite possible to not have all - receivers called if a raises an error. - - Arguments: - - sender - The sender of the signal Either a specific object or None. - - named - Named arguments which will be passed to receivers. - - Returns a list of tuple pairs [(receiver, response), ... ]. - """ - responses = [] - if not self.receivers: - return responses - - sender_id = _make_id(sender) - if sender_id not in self.sender_status: - self.sender_status[sender_id] = {} - - if self.sender_status[sender_id] == named: - return responses - - self.sender_status[sender_id] = named - - for receiver in self._live_receivers(sender_id): - response = receiver(signal=self, sender=sender, **named) - responses.append((receiver, response)) - return responses - - -def receiver(signal, **kwargs): - """ - A decorator for connecting receivers to signals. Used by passing in the - signal (or list of signals) and keyword arguments to connect:: - - @receiver(post_save, sender=MyModel) - def signal_receiver(sender, **kwargs): - ... - - @receiver([post_save, post_delete], sender=MyModel) - def signals_receiver(sender, **kwargs): - ... - """ - def _decorator(func): - if isinstance(signal, (list, tuple)): - for s in signal: - s.connect(func, **kwargs) - else: - signal.connect(func, **kwargs) - return func - return _decorator diff --git a/ouimeaux/pysignals/inspect.py b/ouimeaux/pysignals/inspect.py deleted file mode 100644 index 0171931..0000000 --- a/ouimeaux/pysignals/inspect.py +++ /dev/null @@ -1,131 +0,0 @@ -from __future__ import absolute_import - -import inspect - -import six - - -def getargspec(func): - if six.PY2: - return inspect.getargspec(func) - - sig = inspect.signature(func) - args = [ - p.name for p in sig.parameters.values() - if p.kind == inspect.Parameter.POSITIONAL_OR_KEYWORD - ] - varargs = [ - p.name for p in sig.parameters.values() - if p.kind == inspect.Parameter.VAR_POSITIONAL - ] - varargs = varargs[0] if varargs else None - varkw = [ - p.name for p in sig.parameters.values() - if p.kind == inspect.Parameter.VAR_KEYWORD - ] - varkw = varkw[0] if varkw else None - defaults = [ - p.default for p in sig.parameters.values() - if p.kind == inspect.Parameter.POSITIONAL_OR_KEYWORD and p.default is not p.empty - ] or None - return args, varargs, varkw, defaults - - -def get_func_args(func): - if six.PY2: - argspec = inspect.getargspec(func) - return argspec.args[1:] # ignore 'self' - - sig = inspect.signature(func) - return [ - arg_name for arg_name, param in sig.parameters.items() - if param.kind == inspect.Parameter.POSITIONAL_OR_KEYWORD - ] - - -def get_func_full_args(func): - """ - Return a list of (argument name, default value) tuples. If the argument - does not have a default value, omit it in the tuple. Arguments such as - *args and **kwargs are also included. - """ - if six.PY2: - argspec = inspect.getargspec(func) - args = argspec.args[1:] # ignore 'self' - defaults = argspec.defaults or [] - # Split args into two lists depending on whether they have default value - no_default = args[:len(args) - len(defaults)] - with_default = args[len(args) - len(defaults):] - # Join the two lists and combine it with default values - args = [(arg,) for arg in no_default] + zip(with_default, defaults) - # Add possible *args and **kwargs and prepend them with '*' or '**' - varargs = [('*' + argspec.varargs,)] if argspec.varargs else [] - kwargs = [('**' + argspec.keywords,)] if argspec.keywords else [] - return args + varargs + kwargs - - sig = inspect.signature(func) - args = [] - for arg_name, param in sig.parameters.items(): - name = arg_name - # Ignore 'self' - if name == 'self': - continue - if param.kind == inspect.Parameter.VAR_POSITIONAL: - name = '*' + name - elif param.kind == inspect.Parameter.VAR_KEYWORD: - name = '**' + name - if param.default != inspect.Parameter.empty: - args.append((name, param.default)) - else: - args.append((name,)) - return args - - -def func_accepts_kwargs(func): - if six.PY2: - # Not all callables are inspectable with getargspec, so we'll - # try a couple different ways but in the end fall back on assuming - # it is -- we don't want to prevent registration of valid but weird - # callables. - try: - argspec = inspect.getargspec(func) - except TypeError: - try: - argspec = inspect.getargspec(func.__call__) - except (TypeError, AttributeError): - argspec = None - return not argspec or argspec[2] is not None - - return any( - p for p in inspect.signature(func).parameters.values() - if p.kind == p.VAR_KEYWORD - ) - - -def func_accepts_var_args(func): - """ - Return True if function 'func' accepts positional arguments *args. - """ - if six.PY2: - return inspect.getargspec(func)[1] is not None - - return any( - p for p in inspect.signature(func).parameters.values() - if p.kind == p.VAR_POSITIONAL - ) - - -def func_has_no_args(func): - args = inspect.getargspec(func)[0] if six.PY2 else [ - p for p in inspect.signature(func).parameters.values() - if p.kind == p.POSITIONAL_OR_KEYWORD - ] - return len(args) == 1 - - -def func_supports_parameter(func, parameter): - if six.PY3: - return parameter in inspect.signature(func).parameters - else: - args, varargs, varkw, defaults = inspect.getargspec(func) - return parameter in args diff --git a/ouimeaux/pysignals/license.python.txt b/ouimeaux/pysignals/license.python.txt deleted file mode 100644 index f9ca2c9..0000000 --- a/ouimeaux/pysignals/license.python.txt +++ /dev/null @@ -1,254 +0,0 @@ -A. HISTORY OF THE SOFTWARE -========================== - -Python was created in the early 1990s by Guido van Rossum at Stichting -Mathematisch Centrum (CWI, see http://www.cwi.nl) in the Netherlands -as a successor of a language called ABC. Guido remains Python's -principal author, although it includes many contributions from others. - -In 1995, Guido continued his work on Python at the Corporation for -National Research Initiatives (CNRI, see http://www.cnri.reston.va.us) -in Reston, Virginia where he released several versions of the -software. - -In May 2000, Guido and the Python core development team moved to -BeOpen.com to form the BeOpen PythonLabs team. In October of the same -year, the PythonLabs team moved to Digital Creations (now Zope -Corporation, see http://www.zope.com). In 2001, the Python Software -Foundation (PSF, see http://www.python.org/psf/) was formed, a -non-profit organization created specifically to own Python-related -Intellectual Property. Zope Corporation is a sponsoring member of -the PSF. - -All Python releases are Open Source (see http://www.opensource.org for -the Open Source Definition). Historically, most, but not all, Python -releases have also been GPL-compatible; the table below summarizes -the various releases. - - Release Derived Year Owner GPL- - from compatible? (1) - - 0.9.0 thru 1.2 1991-1995 CWI yes - 1.3 thru 1.5.2 1.2 1995-1999 CNRI yes - 1.6 1.5.2 2000 CNRI no - 2.0 1.6 2000 BeOpen.com no - 1.6.1 1.6 2001 CNRI yes (2) - 2.1 2.0+1.6.1 2001 PSF no - 2.0.1 2.0+1.6.1 2001 PSF yes - 2.1.1 2.1+2.0.1 2001 PSF yes - 2.1.2 2.1.1 2002 PSF yes - 2.1.3 2.1.2 2002 PSF yes - 2.2 and above 2.1.1 2001-now PSF yes - -Footnotes: - -(1) GPL-compatible doesn't mean that we're distributing Python under - the GPL. All Python licenses, unlike the GPL, let you distribute - a modified version without making your changes open source. The - GPL-compatible licenses make it possible to combine Python with - other software that is released under the GPL; the others don't. - -(2) According to Richard Stallman, 1.6.1 is not GPL-compatible, - because its license has a choice of law clause. According to - CNRI, however, Stallman's lawyer has told CNRI's lawyer that 1.6.1 - is "not incompatible" with the GPL. - -Thanks to the many outside volunteers who have worked under Guido's -direction to make these releases possible. - - -B. TERMS AND CONDITIONS FOR ACCESSING OR OTHERWISE USING PYTHON -=============================================================== - -PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2 --------------------------------------------- - -1. This LICENSE AGREEMENT is between the Python Software Foundation -("PSF"), and the Individual or Organization ("Licensee") accessing and -otherwise using this software ("Python") in source or binary form and -its associated documentation. - -2. Subject to the terms and conditions of this License Agreement, PSF hereby -grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce, -analyze, test, perform and/or display publicly, prepare derivative works, -distribute, and otherwise use Python alone or in any derivative version, -provided, however, that PSF's License Agreement and PSF's notice of copyright, -i.e., "Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, -2011, 2012, 2013, 2014 Python Software Foundation; All Rights Reserved" are retained -in Python alone or in any derivative version prepared by Licensee. - -3. In the event Licensee prepares a derivative work that is based on -or incorporates Python or any part thereof, and wants to make -the derivative work available to others as provided herein, then -Licensee hereby agrees to include in any such work a brief summary of -the changes made to Python. - -4. PSF is making Python available to Licensee on an "AS IS" -basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR -IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND -DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS -FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT -INFRINGE ANY THIRD PARTY RIGHTS. - -5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON -FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS -A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON, -OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. - -6. This License Agreement will automatically terminate upon a material -breach of its terms and conditions. - -7. Nothing in this License Agreement shall be deemed to create any -relationship of agency, partnership, or joint venture between PSF and -Licensee. This License Agreement does not grant permission to use PSF -trademarks or trade name in a trademark sense to endorse or promote -products or services of Licensee, or any third party. - -8. By copying, installing or otherwise using Python, Licensee -agrees to be bound by the terms and conditions of this License -Agreement. - - -BEOPEN.COM LICENSE AGREEMENT FOR PYTHON 2.0 -------------------------------------------- - -BEOPEN PYTHON OPEN SOURCE LICENSE AGREEMENT VERSION 1 - -1. This LICENSE AGREEMENT is between BeOpen.com ("BeOpen"), having an -office at 160 Saratoga Avenue, Santa Clara, CA 95051, and the -Individual or Organization ("Licensee") accessing and otherwise using -this software in source or binary form and its associated -documentation ("the Software"). - -2. Subject to the terms and conditions of this BeOpen Python License -Agreement, BeOpen hereby grants Licensee a non-exclusive, -royalty-free, world-wide license to reproduce, analyze, test, perform -and/or display publicly, prepare derivative works, distribute, and -otherwise use the Software alone or in any derivative version, -provided, however, that the BeOpen Python License is retained in the -Software, alone or in any derivative version prepared by Licensee. - -3. BeOpen is making the Software available to Licensee on an "AS IS" -basis. BEOPEN MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR -IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, BEOPEN MAKES NO AND -DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS -FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE WILL NOT -INFRINGE ANY THIRD PARTY RIGHTS. - -4. BEOPEN SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF THE -SOFTWARE FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS -AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THE SOFTWARE, OR ANY -DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. - -5. This License Agreement will automatically terminate upon a material -breach of its terms and conditions. - -6. This License Agreement shall be governed by and interpreted in all -respects by the law of the State of California, excluding conflict of -law provisions. Nothing in this License Agreement shall be deemed to -create any relationship of agency, partnership, or joint venture -between BeOpen and Licensee. This License Agreement does not grant -permission to use BeOpen trademarks or trade names in a trademark -sense to endorse or promote products or services of Licensee, or any -third party. As an exception, the "BeOpen Python" logos available at -http://www.pythonlabs.com/logos.html may be used according to the -permissions granted on that web page. - -7. By copying, installing or otherwise using the software, Licensee -agrees to be bound by the terms and conditions of this License -Agreement. - - -CNRI LICENSE AGREEMENT FOR PYTHON 1.6.1 ---------------------------------------- - -1. This LICENSE AGREEMENT is between the Corporation for National -Research Initiatives, having an office at 1895 Preston White Drive, -Reston, VA 20191 ("CNRI"), and the Individual or Organization -("Licensee") accessing and otherwise using Python 1.6.1 software in -source or binary form and its associated documentation. - -2. Subject to the terms and conditions of this License Agreement, CNRI -hereby grants Licensee a nonexclusive, royalty-free, world-wide -license to reproduce, analyze, test, perform and/or display publicly, -prepare derivative works, distribute, and otherwise use Python 1.6.1 -alone or in any derivative version, provided, however, that CNRI's -License Agreement and CNRI's notice of copyright, i.e., "Copyright (c) -1995-2001 Corporation for National Research Initiatives; All Rights -Reserved" are retained in Python 1.6.1 alone or in any derivative -version prepared by Licensee. Alternately, in lieu of CNRI's License -Agreement, Licensee may substitute the following text (omitting the -quotes): "Python 1.6.1 is made available subject to the terms and -conditions in CNRI's License Agreement. This Agreement together with -Python 1.6.1 may be located on the Internet using the following -unique, persistent identifier (known as a handle): 1895.22/1013. This -Agreement may also be obtained from a proxy server on the Internet -using the following URL: http://hdl.handle.net/1895.22/1013". - -3. In the event Licensee prepares a derivative work that is based on -or incorporates Python 1.6.1 or any part thereof, and wants to make -the derivative work available to others as provided herein, then -Licensee hereby agrees to include in any such work a brief summary of -the changes made to Python 1.6.1. - -4. CNRI is making Python 1.6.1 available to Licensee on an "AS IS" -basis. CNRI MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR -IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, CNRI MAKES NO AND -DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS -FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON 1.6.1 WILL NOT -INFRINGE ANY THIRD PARTY RIGHTS. - -5. CNRI SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON -1.6.1 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS -A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 1.6.1, -OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. - -6. This License Agreement will automatically terminate upon a material -breach of its terms and conditions. - -7. This License Agreement shall be governed by the federal -intellectual property law of the United States, including without -limitation the federal copyright law, and, to the extent such -U.S. federal law does not apply, by the law of the Commonwealth of -Virginia, excluding Virginia's conflict of law provisions. -Notwithstanding the foregoing, with regard to derivative works based -on Python 1.6.1 that incorporate non-separable material that was -previously distributed under the GNU General Public License (GPL), the -law of the Commonwealth of Virginia shall govern this License -Agreement only as to issues arising under or with respect to -Paragraphs 4, 5, and 7 of this License Agreement. Nothing in this -License Agreement shall be deemed to create any relationship of -agency, partnership, or joint venture between CNRI and Licensee. This -License Agreement does not grant permission to use CNRI trademarks or -trade name in a trademark sense to endorse or promote products or -services of Licensee, or any third party. - -8. By clicking on the "ACCEPT" button where indicated, or by copying, -installing or otherwise using Python 1.6.1, Licensee agrees to be -bound by the terms and conditions of this License Agreement. - - ACCEPT - - -CWI LICENSE AGREEMENT FOR PYTHON 0.9.0 THROUGH 1.2 --------------------------------------------------- - -Copyright (c) 1991 - 1995, Stichting Mathematisch Centrum Amsterdam, -The Netherlands. All rights reserved. - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -provided that the above copyright notice appear in all copies and that -both that copyright notice and this permission notice appear in -supporting documentation, and that the name of Stichting Mathematisch -Centrum or CWI not be used in advertising or publicity pertaining to -distribution of the software without specific, written prior -permission. - -STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO -THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE -FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/ouimeaux/pysignals/weakref_backports.py b/ouimeaux/pysignals/weakref_backports.py deleted file mode 100644 index edc8693..0000000 --- a/ouimeaux/pysignals/weakref_backports.py +++ /dev/null @@ -1,68 +0,0 @@ -""" -weakref_backports is a partial backport of the weakref module for python -versions below 3.4. - -Copyright (C) 2013 Python Software Foundation, see license.python.txt for -details. - -The following changes were made to the original sources during backporting: - - * Added `self` to `super` calls. - * Removed `from None` when raising exceptions. - -""" -from weakref import ref - - -class WeakMethod(ref): - """ - A custom `weakref.ref` subclass which simulates a weak reference to - a bound method, working around the lifetime problem of bound methods. - """ - - __slots__ = "_func_ref", "_meth_type", "_alive", "__weakref__" - - def __new__(cls, meth, callback=None): - try: - obj = meth.__self__ - func = meth.__func__ - except AttributeError: - raise TypeError("argument should be a bound method, not {}" - .format(type(meth))) - def _cb(arg): - # The self-weakref trick is needed to avoid creating a reference - # cycle. - self = self_wr() - if self._alive: - self._alive = False - if callback is not None: - callback(self) - self = ref.__new__(cls, obj, _cb) - self._func_ref = ref(func, _cb) - self._meth_type = type(meth) - self._alive = True - self_wr = ref(self) - return self - - def __call__(self): - obj = super(WeakMethod, self).__call__() - func = self._func_ref() - if obj is None or func is None: - return None - return self._meth_type(func, obj) - - def __eq__(self, other): - if isinstance(other, WeakMethod): - if not self._alive or not other._alive: - return self is other - return ref.__eq__(self, other) and self._func_ref == other._func_ref - return False - - def __ne__(self, other): - if isinstance(other, WeakMethod): - if not self._alive or not other._alive: - return self is not other - return ref.__ne__(self, other) or self._func_ref != other._func_ref - return True - - __hash__ = ref.__hash__ diff --git a/ouimeaux/signals.py b/ouimeaux/signals.py index b421aab..9b61c25 100644 --- a/ouimeaux/signals.py +++ b/ouimeaux/signals.py @@ -1,4 +1,4 @@ -from ouimeaux.pysignals import Signal, StateChange, receiver +from pysignals import Signal, StateChange, receiver # Work around a bug in pysignals when in the interactive interpreter import sys diff --git a/requirements.txt b/requirements.txt index efba2a3..e146907 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,3 +3,4 @@ requests >= 2.3.0 pyyaml six future +pysignals