summaryrefslogtreecommitdiffstats
path: root/contrib/python/blinker
diff options
context:
space:
mode:
authormaxim-yurchuk <[email protected]>2024-10-09 12:29:46 +0300
committermaxim-yurchuk <[email protected]>2024-10-09 13:14:22 +0300
commit9731d8a4bb7ee2cc8554eaf133bb85498a4c7d80 (patch)
treea8fb3181d5947c0d78cf402aa56e686130179049 /contrib/python/blinker
parenta44b779cd359f06c3ebbef4ec98c6b38609d9d85 (diff)
publishFullContrib: true for ydb
<HIDDEN_URL> commit_hash:c82a80ac4594723cebf2c7387dec9c60217f603e
Diffstat (limited to 'contrib/python/blinker')
-rw-r--r--contrib/python/blinker/py2/.dist-info/METADATA62
-rw-r--r--contrib/python/blinker/py2/.dist-info/top_level.txt1
-rw-r--r--contrib/python/blinker/py2/blinker/__init__.py22
-rw-r--r--contrib/python/blinker/py2/blinker/_saferef.py234
-rw-r--r--contrib/python/blinker/py2/blinker/_utilities.py153
-rw-r--r--contrib/python/blinker/py2/blinker/base.py452
-rw-r--r--contrib/python/blinker/py2/ya.make27
-rw-r--r--contrib/python/blinker/py3/.yandex_meta/yamaker.yaml2
8 files changed, 953 insertions, 0 deletions
diff --git a/contrib/python/blinker/py2/.dist-info/METADATA b/contrib/python/blinker/py2/.dist-info/METADATA
new file mode 100644
index 00000000000..8d2e569b9a2
--- /dev/null
+++ b/contrib/python/blinker/py2/.dist-info/METADATA
@@ -0,0 +1,62 @@
+Metadata-Version: 2.1
+Name: blinker
+Version: 1.5
+Summary: Fast, simple object-to-object and broadcast signaling
+Home-page: https://blinker.readthedocs.io
+Author: Jason Kirtland
+Author-email: [email protected]
+Maintainer: Pallets Ecosystem
+Maintainer-email: [email protected]
+License: MIT License
+Project-URL: Source, https://github.com/pallets-eco/blinker
+Keywords: signal emit events broadcast
+Classifier: Development Status :: 5 - Production/Stable
+Classifier: Intended Audience :: Developers
+Classifier: License :: OSI Approved :: MIT License
+Classifier: Operating System :: OS Independent
+Classifier: Programming Language :: Python
+Classifier: Topic :: Software Development :: Libraries
+Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*
+Description-Content-Type: text/x-rst
+License-File: LICENSE.rst
+
+Blinker
+=======
+
+Blinker provides a fast dispatching system that allows any number of
+interested parties to subscribe to events, or "signals".
+
+Signal receivers can subscribe to specific senders or receive signals
+sent by any sender.
+
+.. code-block:: pycon
+
+ >>> from blinker import signal
+ >>> started = signal('round-started')
+ >>> def each(round):
+ ... print "Round %s!" % round
+ ...
+ >>> started.connect(each)
+
+ >>> def round_two(round):
+ ... print "This is round two."
+ ...
+ >>> started.connect(round_two, sender=2)
+
+ >>> for round in range(1, 4):
+ ... started.send(round)
+ ...
+ Round 1!
+ Round 2!
+ This is round two.
+ Round 3!
+
+
+Links
+-----
+
+- Documentation: https://blinker.readthedocs.io/
+- Changes: https://blinker.readthedocs.io/#changes
+- PyPI Releases: https://pypi.org/project/blinker/
+- Source Code: https://github.com/pallets-eco/blinker/
+- Issue Tracker: https://github.com/pallets-eco/blinker/issues/
diff --git a/contrib/python/blinker/py2/.dist-info/top_level.txt b/contrib/python/blinker/py2/.dist-info/top_level.txt
new file mode 100644
index 00000000000..1ff4ca55101
--- /dev/null
+++ b/contrib/python/blinker/py2/.dist-info/top_level.txt
@@ -0,0 +1 @@
+blinker
diff --git a/contrib/python/blinker/py2/blinker/__init__.py b/contrib/python/blinker/py2/blinker/__init__.py
new file mode 100644
index 00000000000..bed55ca9d83
--- /dev/null
+++ b/contrib/python/blinker/py2/blinker/__init__.py
@@ -0,0 +1,22 @@
+from blinker.base import (
+ ANY,
+ NamedSignal,
+ Namespace,
+ Signal,
+ WeakNamespace,
+ receiver_connected,
+ signal,
+)
+
+__all__ = [
+ 'ANY',
+ 'NamedSignal',
+ 'Namespace',
+ 'Signal',
+ 'WeakNamespace',
+ 'receiver_connected',
+ 'signal',
+ ]
+
+
+__version__ = '1.5'
diff --git a/contrib/python/blinker/py2/blinker/_saferef.py b/contrib/python/blinker/py2/blinker/_saferef.py
new file mode 100644
index 00000000000..081173df1d6
--- /dev/null
+++ b/contrib/python/blinker/py2/blinker/_saferef.py
@@ -0,0 +1,234 @@
+# extracted from Louie, http://pylouie.org/
+# updated for Python 3
+#
+# Copyright (c) 2006 Patrick K. O'Brien, Mike C. Fletcher,
+# Matthew R. Scott
+#
+# 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.
+#
+# * Neither the name of the <ORGANIZATION> 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.
+#
+"""Refactored 'safe reference from dispatcher.py"""
+
+import operator
+import sys
+import traceback
+import weakref
+
+
+try:
+ callable
+except NameError:
+ def callable(object):
+ return hasattr(object, '__call__')
+
+
+if sys.version_info < (3,):
+ get_self = operator.attrgetter('im_self')
+ get_func = operator.attrgetter('im_func')
+else:
+ get_self = operator.attrgetter('__self__')
+ get_func = operator.attrgetter('__func__')
+
+
+def safe_ref(target, on_delete=None):
+ """Return a *safe* weak reference to a callable target.
+
+ - ``target``: The object to be weakly referenced, if it's a bound
+ method reference, will create a BoundMethodWeakref, otherwise
+ creates a simple weakref.
+
+ - ``on_delete``: If provided, will have a hard reference stored to
+ the callable to be called after the safe reference goes out of
+ scope with the reference object, (either a weakref or a
+ BoundMethodWeakref) as argument.
+ """
+ try:
+ im_self = get_self(target)
+ except AttributeError:
+ if callable(on_delete):
+ return weakref.ref(target, on_delete)
+ else:
+ return weakref.ref(target)
+ else:
+ if im_self is not None:
+ # Turn a bound method into a BoundMethodWeakref instance.
+ # Keep track of these instances for lookup by disconnect().
+ assert hasattr(target, 'im_func') or hasattr(target, '__func__'), (
+ "safe_ref target %r has im_self, but no im_func, "
+ "don't know how to create reference" % target)
+ reference = BoundMethodWeakref(target=target, on_delete=on_delete)
+ return reference
+
+
+class BoundMethodWeakref(object):
+ """'Safe' and reusable weak references to instance methods.
+
+ BoundMethodWeakref objects provide a mechanism for referencing a
+ bound method without requiring that the method object itself
+ (which is normally a transient object) is kept alive. Instead,
+ the BoundMethodWeakref object keeps weak references to both the
+ object and the function which together define the instance method.
+
+ Attributes:
+
+ - ``key``: The identity key for the reference, calculated by the
+ class's calculate_key method applied to the target instance method.
+
+ - ``deletion_methods``: Sequence of callable objects taking single
+ argument, a reference to this object which will be called when
+ *either* the target object or target function is garbage
+ collected (i.e. when this object becomes invalid). These are
+ specified as the on_delete parameters of safe_ref calls.
+
+ - ``weak_self``: Weak reference to the target object.
+
+ - ``weak_func``: Weak reference to the target function.
+
+ Class Attributes:
+
+ - ``_all_instances``: Class attribute pointing to all live
+ BoundMethodWeakref objects indexed by the class's
+ calculate_key(target) method applied to the target objects.
+ This weak value dictionary is used to short-circuit creation so
+ that multiple references to the same (object, function) pair
+ produce the same BoundMethodWeakref instance.
+ """
+
+ _all_instances = weakref.WeakValueDictionary()
+
+ def __new__(cls, target, on_delete=None, *arguments, **named):
+ """Create new instance or return current instance.
+
+ Basically this method of construction allows us to
+ short-circuit creation of references to already- referenced
+ instance methods. The key corresponding to the target is
+ calculated, and if there is already an existing reference,
+ that is returned, with its deletion_methods attribute updated.
+ Otherwise the new instance is created and registered in the
+ table of already-referenced methods.
+ """
+ key = cls.calculate_key(target)
+ current = cls._all_instances.get(key)
+ if current is not None:
+ current.deletion_methods.append(on_delete)
+ return current
+ else:
+ base = super(BoundMethodWeakref, cls).__new__(cls)
+ cls._all_instances[key] = base
+ base.__init__(target, on_delete, *arguments, **named)
+ return base
+
+ def __init__(self, target, on_delete=None):
+ """Return a weak-reference-like instance for a bound method.
+
+ - ``target``: The instance-method target for the weak reference,
+ must have im_self and im_func attributes and be
+ reconstructable via the following, which is true of built-in
+ instance methods::
+
+ target.im_func.__get__( target.im_self )
+
+ - ``on_delete``: Optional callback which will be called when
+ this weak reference ceases to be valid (i.e. either the
+ object or the function is garbage collected). Should take a
+ single argument, which will be passed a pointer to this
+ object.
+ """
+ def remove(weak, self=self):
+ """Set self.isDead to True when method or instance is destroyed."""
+ methods = self.deletion_methods[:]
+ del self.deletion_methods[:]
+ try:
+ del self.__class__._all_instances[self.key]
+ except KeyError:
+ pass
+ for function in methods:
+ try:
+ if callable(function):
+ function(self)
+ except Exception:
+ try:
+ traceback.print_exc()
+ except AttributeError:
+ e = sys.exc_info()[1]
+ print ('Exception during saferef %s '
+ 'cleanup function %s: %s' % (self, function, e))
+ self.deletion_methods = [on_delete]
+ self.key = self.calculate_key(target)
+ im_self = get_self(target)
+ im_func = get_func(target)
+ self.weak_self = weakref.ref(im_self, remove)
+ self.weak_func = weakref.ref(im_func, remove)
+ self.self_name = str(im_self)
+ self.func_name = str(im_func.__name__)
+
+ def calculate_key(cls, target):
+ """Calculate the reference key for this reference.
+
+ Currently this is a two-tuple of the id()'s of the target
+ object and the target function respectively.
+ """
+ return (id(get_self(target)), id(get_func(target)))
+ calculate_key = classmethod(calculate_key)
+
+ def __str__(self):
+ """Give a friendly representation of the object."""
+ return "{}({}.{})".format(
+ self.__class__.__name__,
+ self.self_name,
+ self.func_name,
+ )
+
+ __repr__ = __str__
+
+ def __nonzero__(self):
+ """Whether we are still a valid reference."""
+ return self() is not None
+
+ def __cmp__(self, other):
+ """Compare with another reference."""
+ if not isinstance(other, self.__class__):
+ return cmp(self.__class__, type(other))
+ return cmp(self.key, other.key)
+
+ def __call__(self):
+ """Return a strong reference to the bound method.
+
+ If the target cannot be retrieved, then will return None,
+ otherwise returns a bound instance method for our object and
+ function.
+
+ Note: You may call this method any number of times, as it does
+ not invalidate the reference.
+ """
+ target = self.weak_self()
+ if target is not None:
+ function = self.weak_func()
+ if function is not None:
+ return function.__get__(target)
+ return None
diff --git a/contrib/python/blinker/py2/blinker/_utilities.py b/contrib/python/blinker/py2/blinker/_utilities.py
new file mode 100644
index 00000000000..133c57a0642
--- /dev/null
+++ b/contrib/python/blinker/py2/blinker/_utilities.py
@@ -0,0 +1,153 @@
+from weakref import ref
+
+from blinker._saferef import BoundMethodWeakref
+
+
+try:
+ callable
+except NameError:
+ def callable(object):
+ return hasattr(object, '__call__')
+
+
+try:
+ from collections import defaultdict
+except:
+ class defaultdict(dict):
+
+ def __init__(self, default_factory=None, *a, **kw):
+ if (default_factory is not None and
+ not hasattr(default_factory, '__call__')):
+ raise TypeError('first argument must be callable')
+ dict.__init__(self, *a, **kw)
+ self.default_factory = default_factory
+
+ def __getitem__(self, key):
+ try:
+ return dict.__getitem__(self, key)
+ except KeyError:
+ return self.__missing__(key)
+
+ def __missing__(self, key):
+ if self.default_factory is None:
+ raise KeyError(key)
+ self[key] = value = self.default_factory()
+ return value
+
+ def __reduce__(self):
+ if self.default_factory is None:
+ args = ()
+ else:
+ args = self.default_factory,
+ return type(self), args, None, None, self.items()
+
+ def copy(self):
+ return self.__copy__()
+
+ def __copy__(self):
+ return type(self)(self.default_factory, self)
+
+ def __deepcopy__(self, memo):
+ import copy
+ return type(self)(self.default_factory,
+ copy.deepcopy(self.items()))
+
+ def __repr__(self):
+ return 'defaultdict({}, {})'.format(self.default_factory,
+ dict.__repr__(self))
+
+
+class _symbol(object):
+
+ def __init__(self, name):
+ """Construct a new named symbol."""
+ self.__name__ = self.name = name
+
+ def __reduce__(self):
+ return symbol, (self.name,)
+
+ def __repr__(self):
+ return self.name
+_symbol.__name__ = 'symbol'
+
+
+class symbol(object):
+ """A constant symbol.
+
+ >>> symbol('foo') is symbol('foo')
+ True
+ >>> symbol('foo')
+ foo
+
+ A slight refinement of the MAGICCOOKIE=object() pattern. The primary
+ advantage of symbol() is its repr(). They are also singletons.
+
+ Repeated calls of symbol('name') will all return the same instance.
+
+ """
+ symbols = {}
+
+ def __new__(cls, name):
+ try:
+ return cls.symbols[name]
+ except KeyError:
+ return cls.symbols.setdefault(name, _symbol(name))
+
+
+try:
+ text = (str, unicode)
+except NameError:
+ text = str
+
+
+def hashable_identity(obj):
+ if hasattr(obj, '__func__'):
+ return (id(obj.__func__), id(obj.__self__))
+ elif hasattr(obj, 'im_func'):
+ return (id(obj.im_func), id(obj.im_self))
+ elif isinstance(obj, text):
+ return obj
+ else:
+ return id(obj)
+
+
+WeakTypes = (ref, BoundMethodWeakref)
+
+
+class annotatable_weakref(ref):
+ """A weakref.ref that supports custom instance attributes."""
+
+
+def reference(object, callback=None, **annotations):
+ """Return an annotated weak ref."""
+ if callable(object):
+ weak = callable_reference(object, callback)
+ else:
+ weak = annotatable_weakref(object, callback)
+ for key, value in annotations.items():
+ setattr(weak, key, value)
+ return weak
+
+
+def callable_reference(object, callback=None):
+ """Return an annotated weak ref, supporting bound instance methods."""
+ if hasattr(object, 'im_self') and object.im_self is not None:
+ return BoundMethodWeakref(target=object, on_delete=callback)
+ elif hasattr(object, '__self__') and object.__self__ is not None:
+ return BoundMethodWeakref(target=object, on_delete=callback)
+ return annotatable_weakref(object, callback)
+
+
+class lazy_property(object):
+ """A @property that is only evaluated once."""
+
+ def __init__(self, deferred):
+ self._deferred = deferred
+ self.__doc__ = deferred.__doc__
+
+ def __get__(self, obj, cls):
+ if obj is None:
+ return self
+ value = self._deferred(obj)
+ setattr(obj, self._deferred.__name__, value)
+ return value
diff --git a/contrib/python/blinker/py2/blinker/base.py b/contrib/python/blinker/py2/blinker/base.py
new file mode 100644
index 00000000000..8a3e4f95b97
--- /dev/null
+++ b/contrib/python/blinker/py2/blinker/base.py
@@ -0,0 +1,452 @@
+# -*- coding: utf-8; fill-column: 76 -*-
+"""Signals and events.
+
+A small implementation of signals, inspired by a snippet of Django signal
+API client code seen in a blog post. Signals are first-class objects and
+each manages its own receivers and message emission.
+
+The :func:`signal` function provides singleton behavior for named signals.
+
+"""
+from contextlib import contextmanager
+from warnings import warn
+from weakref import WeakValueDictionary
+
+from blinker._utilities import (
+ WeakTypes,
+ defaultdict,
+ hashable_identity,
+ lazy_property,
+ reference,
+ symbol,
+ )
+
+
+ANY = symbol('ANY')
+ANY.__doc__ = 'Token for "any sender".'
+ANY_ID = 0
+
+
+class Signal(object):
+ """A notification emitter."""
+
+ #: An :obj:`ANY` convenience synonym, allows ``Signal.ANY``
+ #: without an additional import.
+ ANY = ANY
+
+ @lazy_property
+ def receiver_connected(self):
+ """Emitted after each :meth:`connect`.
+
+ The signal sender is the signal instance, and the :meth:`connect`
+ arguments are passed through: *receiver*, *sender*, and *weak*.
+
+ .. versionadded:: 1.2
+
+ """
+ return Signal(doc="Emitted after a receiver connects.")
+
+ @lazy_property
+ def receiver_disconnected(self):
+ """Emitted after :meth:`disconnect`.
+
+ The sender is the signal instance, and the :meth:`disconnect` arguments
+ are passed through: *receiver* and *sender*.
+
+ Note, this signal is emitted **only** when :meth:`disconnect` is
+ called explicitly.
+
+ The disconnect signal can not be emitted by an automatic disconnect
+ (due to a weakly referenced receiver or sender going out of scope),
+ as the receiver and/or sender instances are no longer available for
+ use at the time this signal would be emitted.
+
+ An alternative approach is available by subscribing to
+ :attr:`receiver_connected` and setting up a custom weakref cleanup
+ callback on weak receivers and senders.
+
+ .. versionadded:: 1.2
+
+ """
+ return Signal(doc="Emitted after a receiver disconnects.")
+
+ def __init__(self, doc=None):
+ """
+ :param doc: optional. If provided, will be assigned to the signal's
+ __doc__ attribute.
+
+ """
+ if doc:
+ self.__doc__ = doc
+ #: A mapping of connected receivers.
+ #:
+ #: The values of this mapping are not meaningful outside of the
+ #: internal :class:`Signal` implementation, however the boolean value
+ #: of the mapping is useful as an extremely efficient check to see if
+ #: any receivers are connected to the signal.
+ self.receivers = {}
+ self._by_receiver = defaultdict(set)
+ self._by_sender = defaultdict(set)
+ self._weak_senders = {}
+
+ def connect(self, receiver, sender=ANY, weak=True):
+ """Connect *receiver* to signal events sent by *sender*.
+
+ :param receiver: A callable. Will be invoked by :meth:`send` with
+ `sender=` as a single positional argument and any ``kwargs`` that
+ were provided to a call to :meth:`send`.
+
+ :param sender: Any object or :obj:`ANY`, defaults to ``ANY``.
+ Restricts notifications delivered to *receiver* to only those
+ :meth:`send` emissions sent by *sender*. If ``ANY``, the receiver
+ will always be notified. A *receiver* may be connected to
+ multiple *sender* values on the same Signal through multiple calls
+ to :meth:`connect`.
+
+ :param weak: If true, the Signal will hold a weakref to *receiver*
+ and automatically disconnect when *receiver* goes out of scope or
+ is garbage collected. Defaults to True.
+
+ """
+ receiver_id = hashable_identity(receiver)
+ if weak:
+ receiver_ref = reference(receiver, self._cleanup_receiver)
+ receiver_ref.receiver_id = receiver_id
+ else:
+ receiver_ref = receiver
+ if sender is ANY:
+ sender_id = ANY_ID
+ else:
+ sender_id = hashable_identity(sender)
+
+ self.receivers.setdefault(receiver_id, receiver_ref)
+ self._by_sender[sender_id].add(receiver_id)
+ self._by_receiver[receiver_id].add(sender_id)
+ del receiver_ref
+
+ if sender is not ANY and sender_id not in self._weak_senders:
+ # wire together a cleanup for weakref-able senders
+ try:
+ sender_ref = reference(sender, self._cleanup_sender)
+ sender_ref.sender_id = sender_id
+ except TypeError:
+ pass
+ else:
+ self._weak_senders.setdefault(sender_id, sender_ref)
+ del sender_ref
+
+ # broadcast this connection. if receivers raise, disconnect.
+ if ('receiver_connected' in self.__dict__ and
+ self.receiver_connected.receivers):
+ try:
+ self.receiver_connected.send(self,
+ receiver=receiver,
+ sender=sender,
+ weak=weak)
+ except:
+ self.disconnect(receiver, sender)
+ raise
+ if receiver_connected.receivers and self is not receiver_connected:
+ try:
+ receiver_connected.send(self,
+ receiver_arg=receiver,
+ sender_arg=sender,
+ weak_arg=weak)
+ except:
+ self.disconnect(receiver, sender)
+ raise
+ return receiver
+
+ def connect_via(self, sender, weak=False):
+ """Connect the decorated function as a receiver for *sender*.
+
+ :param sender: Any object or :obj:`ANY`. The decorated function
+ will only receive :meth:`send` emissions sent by *sender*. If
+ ``ANY``, the receiver will always be notified. A function may be
+ decorated multiple times with differing *sender* values.
+
+ :param weak: If true, the Signal will hold a weakref to the
+ decorated function and automatically disconnect when *receiver*
+ goes out of scope or is garbage collected. Unlike
+ :meth:`connect`, this defaults to False.
+
+ The decorated function will be invoked by :meth:`send` with
+ `sender=` as a single positional argument and any ``kwargs`` that
+ were provided to the call to :meth:`send`.
+
+
+ .. versionadded:: 1.1
+
+ """
+ def decorator(fn):
+ self.connect(fn, sender, weak)
+ return fn
+ return decorator
+
+ @contextmanager
+ def connected_to(self, receiver, sender=ANY):
+ """Execute a block with the signal temporarily connected to *receiver*.
+
+ :param receiver: a receiver callable
+ :param sender: optional, a sender to filter on
+
+ This is a context manager for use in the ``with`` statement. It can
+ be useful in unit tests. *receiver* is connected to the signal for
+ the duration of the ``with`` block, and will be disconnected
+ automatically when exiting the block:
+
+ .. code-block:: python
+
+ with on_ready.connected_to(receiver):
+ # do stuff
+ on_ready.send(123)
+
+ .. versionadded:: 1.1
+
+ """
+ self.connect(receiver, sender=sender, weak=False)
+ try:
+ yield None
+ except:
+ self.disconnect(receiver)
+ raise
+ else:
+ self.disconnect(receiver)
+
+ def temporarily_connected_to(self, receiver, sender=ANY):
+ """An alias for :meth:`connected_to`.
+
+ :param receiver: a receiver callable
+ :param sender: optional, a sender to filter on
+
+ .. versionadded:: 0.9
+
+ .. versionchanged:: 1.1
+ Renamed to :meth:`connected_to`. ``temporarily_connected_to`` was
+ deprecated in 1.2 and will be removed in a subsequent version.
+
+ """
+ warn("temporarily_connected_to is deprecated; "
+ "use connected_to instead.",
+ DeprecationWarning)
+ return self.connected_to(receiver, sender)
+
+ def send(self, *sender, **kwargs):
+ """Emit this signal on behalf of *sender*, passing on ``kwargs``.
+
+ Returns a list of 2-tuples, pairing receivers with their return
+ value. The ordering of receiver notification is undefined.
+
+ :param sender: Any object or ``None``. If omitted, synonymous
+ with ``None``. Only accepts one positional argument.
+
+ :param kwargs: Data to be sent to receivers.
+ """
+ if not self.receivers:
+ # Ensure correct signature even on no-op sends, disable with -O
+ # for lowest possible cost.
+ if __debug__ and sender and len(sender) > 1:
+ raise TypeError('send() accepts only one positional '
+ 'argument, %s given' % len(sender))
+ return []
+
+ # Using '*sender' rather than 'sender=None' allows 'sender' to be
+ # used as a keyword argument- i.e. it's an invisible name in the
+ # function signature.
+ if len(sender) == 0:
+ sender = None
+ elif len(sender) > 1:
+ raise TypeError('send() accepts only one positional argument, '
+ '%s given' % len(sender))
+ else:
+ sender = sender[0]
+ return [(receiver, receiver(sender, **kwargs))
+ for receiver in self.receivers_for(sender)]
+
+ def has_receivers_for(self, sender):
+ """True if there is probably a receiver for *sender*.
+
+ Performs an optimistic check only. Does not guarantee that all
+ weakly referenced receivers are still alive. See
+ :meth:`receivers_for` for a stronger search.
+
+ """
+ if not self.receivers:
+ return False
+ if self._by_sender[ANY_ID]:
+ return True
+ if sender is ANY:
+ return False
+ return hashable_identity(sender) in self._by_sender
+
+ def receivers_for(self, sender):
+ """Iterate all live receivers listening for *sender*."""
+ # TODO: test receivers_for(ANY)
+ if self.receivers:
+ sender_id = hashable_identity(sender)
+ if sender_id in self._by_sender:
+ ids = (self._by_sender[ANY_ID] |
+ self._by_sender[sender_id])
+ else:
+ ids = self._by_sender[ANY_ID].copy()
+ for receiver_id in ids:
+ receiver = self.receivers.get(receiver_id)
+ if receiver is None:
+ continue
+ if isinstance(receiver, WeakTypes):
+ strong = receiver()
+ if strong is None:
+ self._disconnect(receiver_id, ANY_ID)
+ continue
+ receiver = strong
+ yield receiver
+
+ def disconnect(self, receiver, sender=ANY):
+ """Disconnect *receiver* from this signal's events.
+
+ :param receiver: a previously :meth:`connected<connect>` callable
+
+ :param sender: a specific sender to disconnect from, or :obj:`ANY`
+ to disconnect from all senders. Defaults to ``ANY``.
+
+ """
+ if sender is ANY:
+ sender_id = ANY_ID
+ else:
+ sender_id = hashable_identity(sender)
+ receiver_id = hashable_identity(receiver)
+ self._disconnect(receiver_id, sender_id)
+
+ if ('receiver_disconnected' in self.__dict__ and
+ self.receiver_disconnected.receivers):
+ self.receiver_disconnected.send(self,
+ receiver=receiver,
+ sender=sender)
+
+ def _disconnect(self, receiver_id, sender_id):
+ if sender_id == ANY_ID:
+ if self._by_receiver.pop(receiver_id, False):
+ for bucket in self._by_sender.values():
+ bucket.discard(receiver_id)
+ self.receivers.pop(receiver_id, None)
+ else:
+ self._by_sender[sender_id].discard(receiver_id)
+ self._by_receiver[receiver_id].discard(sender_id)
+
+ def _cleanup_receiver(self, receiver_ref):
+ """Disconnect a receiver from all senders."""
+ self._disconnect(receiver_ref.receiver_id, ANY_ID)
+
+ def _cleanup_sender(self, sender_ref):
+ """Disconnect all receivers from a sender."""
+ sender_id = sender_ref.sender_id
+ assert sender_id != ANY_ID
+ self._weak_senders.pop(sender_id, None)
+ for receiver_id in self._by_sender.pop(sender_id, ()):
+ self._by_receiver[receiver_id].discard(sender_id)
+
+ def _cleanup_bookkeeping(self):
+ """Prune unused sender/receiver bookkeeping. Not threadsafe.
+
+ Connecting & disconnecting leave behind a small amount of bookkeeping
+ for the receiver and sender values. Typical workloads using Blinker,
+ for example in most web apps, Flask, CLI scripts, etc., are not
+ adversely affected by this bookkeeping.
+
+ With a long-running Python process performing dynamic signal routing
+ with high volume- e.g. connecting to function closures, "senders" are
+ all unique object instances, and doing all of this over and over- you
+ may see memory usage will grow due to extraneous bookkeeping. (An empty
+ set() for each stale sender/receiver pair.)
+
+ This method will prune that bookkeeping away, with the caveat that such
+ pruning is not threadsafe. The risk is that cleanup of a fully
+ disconnected receiver/sender pair occurs while another thread is
+ connecting that same pair. If you are in the highly dynamic, unique
+ receiver/sender situation that has lead you to this method, that
+ failure mode is perhaps not a big deal for you.
+ """
+ for mapping in (self._by_sender, self._by_receiver):
+ for _id, bucket in list(mapping.items()):
+ if not bucket:
+ mapping.pop(_id, None)
+
+ def _clear_state(self):
+ """Throw away all signal state. Useful for unit tests."""
+ self._weak_senders.clear()
+ self.receivers.clear()
+ self._by_sender.clear()
+ self._by_receiver.clear()
+
+
+receiver_connected = Signal("""\
+Sent by a :class:`Signal` after a receiver connects.
+
+:argument: the Signal that was connected to
+:keyword receiver_arg: the connected receiver
+:keyword sender_arg: the sender to connect to
+:keyword weak_arg: true if the connection to receiver_arg is a weak reference
+
+.. deprecated:: 1.2
+
+As of 1.2, individual signals have their own private
+:attr:`~Signal.receiver_connected` and
+:attr:`~Signal.receiver_disconnected` signals with a slightly simplified
+call signature. This global signal is planned to be removed in 1.6.
+
+""")
+
+
+class NamedSignal(Signal):
+ """A named generic notification emitter."""
+
+ def __init__(self, name, doc=None):
+ Signal.__init__(self, doc)
+
+ #: The name of this signal.
+ self.name = name
+
+ def __repr__(self):
+ base = Signal.__repr__(self)
+ return "{}; {!r}>".format(base[:-1], self.name)
+
+
+class Namespace(dict):
+ """A mapping of signal names to signals."""
+
+ def signal(self, name, doc=None):
+ """Return the :class:`NamedSignal` *name*, creating it if required.
+
+ Repeated calls to this function will return the same signal object.
+
+ """
+ try:
+ return self[name]
+ except KeyError:
+ return self.setdefault(name, NamedSignal(name, doc))
+
+
+class WeakNamespace(WeakValueDictionary):
+ """A weak mapping of signal names to signals.
+
+ Automatically cleans up unused Signals when the last reference goes out
+ of scope. This namespace implementation exists for a measure of legacy
+ compatibility with Blinker <= 1.2, and may be dropped in the future.
+
+ .. versionadded:: 1.3
+
+ """
+
+ def signal(self, name, doc=None):
+ """Return the :class:`NamedSignal` *name*, creating it if required.
+
+ Repeated calls to this function will return the same signal object.
+
+ """
+ try:
+ return self[name]
+ except KeyError:
+ return self.setdefault(name, NamedSignal(name, doc))
+
+
+signal = Namespace().signal
diff --git a/contrib/python/blinker/py2/ya.make b/contrib/python/blinker/py2/ya.make
new file mode 100644
index 00000000000..65574d855e8
--- /dev/null
+++ b/contrib/python/blinker/py2/ya.make
@@ -0,0 +1,27 @@
+# Generated by devtools/yamaker (pypi).
+
+PY2_LIBRARY()
+
+SUBSCRIBER(web-chib g:python-contrib)
+
+VERSION(1.5)
+
+LICENSE(MIT)
+
+NO_LINT()
+
+PY_SRCS(
+ TOP_LEVEL
+ blinker/__init__.py
+ blinker/_saferef.py
+ blinker/_utilities.py
+ blinker/base.py
+)
+
+RESOURCE_FILES(
+ PREFIX contrib/python/blinker/py2/
+ .dist-info/METADATA
+ .dist-info/top_level.txt
+)
+
+END()
diff --git a/contrib/python/blinker/py3/.yandex_meta/yamaker.yaml b/contrib/python/blinker/py3/.yandex_meta/yamaker.yaml
new file mode 100644
index 00000000000..72d892005be
--- /dev/null
+++ b/contrib/python/blinker/py3/.yandex_meta/yamaker.yaml
@@ -0,0 +1,2 @@
+keep:
+ - blinker/_saferef.py # Пока сохраняем, как обновим mitmproxy, можно будет удалить