Updates
This commit is contained in:
42
ETB-API/venv/lib/python3.12/site-packages/vine/__init__.py
Normal file
42
ETB-API/venv/lib/python3.12/site-packages/vine/__init__.py
Normal file
@@ -0,0 +1,42 @@
|
||||
"""Python promises."""
|
||||
import re
|
||||
from collections import namedtuple
|
||||
|
||||
from .abstract import Thenable
|
||||
from .funtools import (
|
||||
ensure_promise,
|
||||
maybe_promise,
|
||||
ppartial,
|
||||
preplace,
|
||||
starpromise,
|
||||
transform,
|
||||
wrap,
|
||||
)
|
||||
from .promises import promise
|
||||
from .synchronization import barrier
|
||||
|
||||
__version__ = '5.1.0'
|
||||
__author__ = 'Ask Solem'
|
||||
__contact__ = 'auvipy@gmail.com'
|
||||
__homepage__ = 'https://github.com/celery/vine'
|
||||
__docformat__ = 'restructuredtext'
|
||||
|
||||
# -eof meta-
|
||||
|
||||
version_info_t = namedtuple('version_info_t', (
|
||||
'major', 'minor', 'micro', 'releaselevel', 'serial',
|
||||
))
|
||||
# bump version can only search for {current_version}
|
||||
# so we have to parse the version here.
|
||||
_temp = re.match(
|
||||
r'(\d+)\.(\d+).(\d+)(.+)?', __version__).groups()
|
||||
VERSION = version_info = version_info_t(
|
||||
int(_temp[0]), int(_temp[1]), int(_temp[2]), _temp[3] or '', '')
|
||||
del (_temp)
|
||||
del (re)
|
||||
|
||||
__all__ = [
|
||||
'Thenable', 'promise', 'barrier',
|
||||
'maybe_promise', 'ensure_promise',
|
||||
'ppartial', 'preplace', 'starpromise', 'transform', 'wrap',
|
||||
]
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
68
ETB-API/venv/lib/python3.12/site-packages/vine/abstract.py
Normal file
68
ETB-API/venv/lib/python3.12/site-packages/vine/abstract.py
Normal file
@@ -0,0 +1,68 @@
|
||||
"""Abstract classes."""
|
||||
import abc
|
||||
from collections.abc import Callable
|
||||
|
||||
__all__ = ['Thenable']
|
||||
|
||||
|
||||
class Thenable(Callable, metaclass=abc.ABCMeta): # pragma: no cover
|
||||
"""Object that supports ``.then()``."""
|
||||
|
||||
__slots__ = ()
|
||||
|
||||
@abc.abstractmethod
|
||||
def then(self, on_success, on_error=None):
|
||||
raise NotImplementedError()
|
||||
|
||||
@abc.abstractmethod
|
||||
def throw(self, exc=None, tb=None, propagate=True):
|
||||
raise NotImplementedError()
|
||||
|
||||
@abc.abstractmethod
|
||||
def cancel(self):
|
||||
raise NotImplementedError()
|
||||
|
||||
@classmethod
|
||||
def __subclasshook__(cls, C):
|
||||
if cls is Thenable:
|
||||
if any('then' in B.__dict__ for B in C.__mro__):
|
||||
return True
|
||||
return NotImplemented
|
||||
|
||||
@classmethod
|
||||
def register(cls, other):
|
||||
# overide to return other so `register` can be used as a decorator
|
||||
type(cls).register(cls, other)
|
||||
return other
|
||||
|
||||
|
||||
@Thenable.register
|
||||
class ThenableProxy:
|
||||
"""Proxy to object that supports ``.then()``."""
|
||||
|
||||
def _set_promise_target(self, p):
|
||||
self._p = p
|
||||
|
||||
def then(self, on_success, on_error=None):
|
||||
return self._p.then(on_success, on_error)
|
||||
|
||||
def cancel(self):
|
||||
return self._p.cancel()
|
||||
|
||||
def throw1(self, exc=None):
|
||||
return self._p.throw1(exc)
|
||||
|
||||
def throw(self, exc=None, tb=None, propagate=True):
|
||||
return self._p.throw(exc, tb=tb, propagate=propagate)
|
||||
|
||||
@property
|
||||
def cancelled(self):
|
||||
return self._p.cancelled
|
||||
|
||||
@property
|
||||
def ready(self):
|
||||
return self._p.ready
|
||||
|
||||
@property
|
||||
def failed(self):
|
||||
return self._p.failed
|
||||
113
ETB-API/venv/lib/python3.12/site-packages/vine/funtools.py
Normal file
113
ETB-API/venv/lib/python3.12/site-packages/vine/funtools.py
Normal file
@@ -0,0 +1,113 @@
|
||||
"""Functional utilities."""
|
||||
from .abstract import Thenable
|
||||
from .promises import promise
|
||||
|
||||
__all__ = [
|
||||
'maybe_promise', 'ensure_promise',
|
||||
'ppartial', 'preplace', 'ready_promise',
|
||||
'starpromise', 'transform', 'wrap',
|
||||
]
|
||||
|
||||
|
||||
def maybe_promise(p):
|
||||
"""Return None if p is undefined, otherwise make sure it's a promise."""
|
||||
if p:
|
||||
if not isinstance(p, Thenable):
|
||||
return promise(p)
|
||||
return p
|
||||
|
||||
|
||||
def ensure_promise(p):
|
||||
"""Ensure p is a promise.
|
||||
|
||||
If p is not a promise, a new promise is created with p' as callback.
|
||||
"""
|
||||
if p is None:
|
||||
return promise()
|
||||
return maybe_promise(p)
|
||||
|
||||
|
||||
def ppartial(p, *args, **kwargs):
|
||||
"""Create/modify promise with partial arguments."""
|
||||
p = ensure_promise(p)
|
||||
if args:
|
||||
p.args = args + p.args
|
||||
if kwargs:
|
||||
p.kwargs.update(kwargs)
|
||||
return p
|
||||
|
||||
|
||||
def preplace(p, *args, **kwargs):
|
||||
"""Replace promise arguments.
|
||||
|
||||
This will force the promise to disregard any arguments
|
||||
the promise is fulfilled with, and to be called with the
|
||||
provided arguments instead.
|
||||
"""
|
||||
def _replacer(*_, **__):
|
||||
return p(*args, **kwargs)
|
||||
return promise(_replacer)
|
||||
|
||||
|
||||
def ready_promise(callback=None, *args):
|
||||
"""Create promise that is already fulfilled."""
|
||||
p = ensure_promise(callback)
|
||||
p(*args)
|
||||
return p
|
||||
|
||||
|
||||
def starpromise(fun, *args, **kwargs):
|
||||
"""Create promise, using star arguments."""
|
||||
return promise(fun, args, kwargs)
|
||||
|
||||
|
||||
def transform(filter_, callback, *filter_args, **filter_kwargs):
|
||||
"""Filter final argument to a promise.
|
||||
|
||||
E.g. to coerce callback argument to :class:`int`::
|
||||
|
||||
transform(int, callback)
|
||||
|
||||
or a more complex example extracting something from a dict
|
||||
and coercing the value to :class:`float`:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
def filter_key_value(key, filter_, mapping):
|
||||
return filter_(mapping[key])
|
||||
|
||||
def get_page_expires(self, url, callback=None):
|
||||
return self.request(
|
||||
'GET', url,
|
||||
callback=transform(get_key, callback, 'PageExpireValue', int),
|
||||
)
|
||||
|
||||
"""
|
||||
callback = ensure_promise(callback)
|
||||
P = promise(_transback, (filter_, callback, filter_args, filter_kwargs))
|
||||
P.then(promise(), callback.throw)
|
||||
return P
|
||||
|
||||
|
||||
def _transback(filter_, callback, args, kwargs, ret):
|
||||
try:
|
||||
ret = filter_(*args + (ret,), **kwargs)
|
||||
except Exception:
|
||||
callback.throw()
|
||||
else:
|
||||
return callback(ret)
|
||||
|
||||
|
||||
def wrap(p):
|
||||
"""Wrap promise.
|
||||
|
||||
This wraps the promise such that if the promise is called with a promise as
|
||||
argument, we attach ourselves to that promise instead.
|
||||
"""
|
||||
def on_call(*args, **kwargs):
|
||||
if len(args) == 1 and isinstance(args[0], promise):
|
||||
return args[0].then(p)
|
||||
else:
|
||||
return p(*args, **kwargs)
|
||||
|
||||
return on_call
|
||||
241
ETB-API/venv/lib/python3.12/site-packages/vine/promises.py
Normal file
241
ETB-API/venv/lib/python3.12/site-packages/vine/promises.py
Normal file
@@ -0,0 +1,241 @@
|
||||
"""Promise implementation."""
|
||||
import inspect
|
||||
import sys
|
||||
from collections import deque
|
||||
from weakref import WeakMethod, ref
|
||||
|
||||
from .abstract import Thenable
|
||||
from .utils import reraise
|
||||
|
||||
__all__ = ['promise']
|
||||
|
||||
|
||||
@Thenable.register
|
||||
class promise:
|
||||
"""Promise of future evaluation.
|
||||
|
||||
This is a special implementation of promises in that it can
|
||||
be used both for "promise of a value" and lazy evaluation.
|
||||
The biggest upside for this is that everything in a promise can also be
|
||||
a promise, e.g. filters, callbacks and errbacks can all be promises.
|
||||
|
||||
Usage examples:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
>>> p = promise()
|
||||
>>> p.then(promise(print, ('OK',))) # noqa
|
||||
>>> p.on_error = promise(print, ('ERROR',)) # noqa
|
||||
>>> p(20)
|
||||
OK, 20
|
||||
>>> p.then(promise(print, ('hello',))) # noqa
|
||||
hello, 20
|
||||
|
||||
|
||||
>>> p.throw(KeyError('foo'))
|
||||
ERROR, KeyError('foo')
|
||||
|
||||
|
||||
>>> p2 = promise()
|
||||
>>> p2.then(print) # noqa
|
||||
>>> p2.cancel()
|
||||
>>> p(30)
|
||||
|
||||
Example:
|
||||
.. code-block:: python
|
||||
|
||||
from vine import promise, wrap
|
||||
|
||||
class Protocol:
|
||||
|
||||
def __init__(self):
|
||||
self.buffer = []
|
||||
|
||||
def receive_message(self):
|
||||
return self.read_header().then(
|
||||
self.read_body).then(
|
||||
wrap(self.prepare_body))
|
||||
|
||||
def read(self, size, callback=None):
|
||||
callback = callback or promise()
|
||||
tell_eventloop_to_read(size, callback)
|
||||
return callback
|
||||
|
||||
def read_header(self, callback=None):
|
||||
return self.read(4, callback)
|
||||
|
||||
def read_body(self, header, callback=None):
|
||||
body_size, = unpack('>L', header)
|
||||
return self.read(body_size, callback)
|
||||
|
||||
def prepare_body(self, value):
|
||||
self.buffer.append(value)
|
||||
"""
|
||||
|
||||
if not hasattr(sys, 'pypy_version_info'): # pragma: no cover
|
||||
__slots__ = (
|
||||
'fun', 'args', 'kwargs', 'ready', 'failed',
|
||||
'value', 'ignore_result', 'reason', '_svpending', '_lvpending',
|
||||
'on_error', 'cancelled', 'weak', '__weakref__',
|
||||
# adding '__dict__' to get dynamic assignment if needed
|
||||
"__dict__",
|
||||
)
|
||||
|
||||
def __init__(self, fun=None, args=None, kwargs=None,
|
||||
callback=None, on_error=None, weak=False,
|
||||
ignore_result=False):
|
||||
self.weak = weak
|
||||
self.ignore_result = ignore_result
|
||||
self.fun = self._get_fun_or_weakref(fun=fun, weak=weak)
|
||||
self.args = args or ()
|
||||
self.kwargs = kwargs or {}
|
||||
self.ready = False
|
||||
self.failed = False
|
||||
self.value = None
|
||||
self.reason = None
|
||||
# Optimization
|
||||
# Most promises will only have one callback, so we optimize for this
|
||||
# case by using a list only when there are multiple callbacks.
|
||||
# s(calar) pending / l(ist) pending
|
||||
self._svpending = None
|
||||
self._lvpending = None
|
||||
self.on_error = on_error
|
||||
self.cancelled = False
|
||||
|
||||
if callback is not None:
|
||||
self.then(callback)
|
||||
|
||||
if self.fun:
|
||||
assert self.fun and callable(fun)
|
||||
|
||||
@staticmethod
|
||||
def _get_fun_or_weakref(fun, weak):
|
||||
"""Return the callable or a weak reference.
|
||||
|
||||
Handles both bound and unbound methods.
|
||||
"""
|
||||
if not weak:
|
||||
return fun
|
||||
|
||||
if inspect.ismethod(fun):
|
||||
return WeakMethod(fun)
|
||||
else:
|
||||
return ref(fun)
|
||||
|
||||
def __repr__(self):
|
||||
return ('<{0} --> {1!r}>' if self.fun else '<{0}>').format(
|
||||
f'{type(self).__name__}@0x{id(self):x}', self.fun,
|
||||
)
|
||||
|
||||
def cancel(self):
|
||||
self.cancelled = True
|
||||
try:
|
||||
if self._svpending is not None:
|
||||
self._svpending.cancel()
|
||||
if self._lvpending is not None:
|
||||
for pending in self._lvpending:
|
||||
pending.cancel()
|
||||
if isinstance(self.on_error, Thenable):
|
||||
self.on_error.cancel()
|
||||
finally:
|
||||
self._svpending = self._lvpending = self.on_error = None
|
||||
|
||||
def __call__(self, *args, **kwargs):
|
||||
retval = None
|
||||
if self.cancelled:
|
||||
return
|
||||
final_args = self.args + args if args else self.args
|
||||
final_kwargs = dict(self.kwargs, **kwargs) if kwargs else self.kwargs
|
||||
# self.fun may be a weakref
|
||||
fun = self._fun_is_alive(self.fun)
|
||||
if fun is not None:
|
||||
try:
|
||||
if self.ignore_result:
|
||||
fun(*final_args, **final_kwargs)
|
||||
ca = ()
|
||||
ck = {}
|
||||
else:
|
||||
retval = fun(*final_args, **final_kwargs)
|
||||
self.value = (ca, ck) = (retval,), {}
|
||||
except Exception:
|
||||
return self.throw()
|
||||
else:
|
||||
self.value = (ca, ck) = final_args, final_kwargs
|
||||
self.ready = True
|
||||
svpending = self._svpending
|
||||
if svpending is not None:
|
||||
try:
|
||||
svpending(*ca, **ck)
|
||||
finally:
|
||||
self._svpending = None
|
||||
else:
|
||||
lvpending = self._lvpending
|
||||
try:
|
||||
while lvpending:
|
||||
p = lvpending.popleft()
|
||||
p(*ca, **ck)
|
||||
finally:
|
||||
self._lvpending = None
|
||||
return retval
|
||||
|
||||
def _fun_is_alive(self, fun):
|
||||
return fun() if self.weak else self.fun
|
||||
|
||||
def then(self, callback, on_error=None):
|
||||
if not isinstance(callback, Thenable):
|
||||
callback = promise(callback, on_error=on_error)
|
||||
if self.cancelled:
|
||||
callback.cancel()
|
||||
return callback
|
||||
if self.failed:
|
||||
callback.throw(self.reason)
|
||||
elif self.ready:
|
||||
args, kwargs = self.value
|
||||
callback(*args, **kwargs)
|
||||
if self._lvpending is None:
|
||||
svpending = self._svpending
|
||||
if svpending is not None:
|
||||
self._svpending, self._lvpending = None, deque([svpending])
|
||||
else:
|
||||
self._svpending = callback
|
||||
return callback
|
||||
self._lvpending.append(callback)
|
||||
return callback
|
||||
|
||||
def throw1(self, exc=None):
|
||||
if not self.cancelled:
|
||||
exc = exc if exc is not None else sys.exc_info()[1]
|
||||
self.failed, self.reason = True, exc
|
||||
if self.on_error:
|
||||
self.on_error(*self.args + (exc,), **self.kwargs)
|
||||
|
||||
def throw(self, exc=None, tb=None, propagate=True):
|
||||
if not self.cancelled:
|
||||
current_exc = sys.exc_info()[1]
|
||||
exc = exc if exc is not None else current_exc
|
||||
try:
|
||||
self.throw1(exc)
|
||||
svpending = self._svpending
|
||||
if svpending is not None:
|
||||
try:
|
||||
svpending.throw1(exc)
|
||||
finally:
|
||||
self._svpending = None
|
||||
else:
|
||||
lvpending = self._lvpending
|
||||
try:
|
||||
while lvpending:
|
||||
lvpending.popleft().throw1(exc)
|
||||
finally:
|
||||
self._lvpending = None
|
||||
finally:
|
||||
if self.on_error is None and propagate:
|
||||
if tb is None and (exc is None or exc is current_exc):
|
||||
raise
|
||||
reraise(type(exc), exc, tb)
|
||||
|
||||
@property
|
||||
def listeners(self):
|
||||
if self._lvpending:
|
||||
return self._lvpending
|
||||
return [self._svpending]
|
||||
@@ -0,0 +1,104 @@
|
||||
"""Synchronization primitives."""
|
||||
from .abstract import Thenable
|
||||
from .promises import promise
|
||||
|
||||
__all__ = ['barrier']
|
||||
|
||||
|
||||
class barrier:
|
||||
"""Barrier.
|
||||
|
||||
Synchronization primitive to call a callback after a list
|
||||
of promises have been fulfilled.
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# Request supports the .then() method.
|
||||
p1 = http.Request('http://a')
|
||||
p2 = http.Request('http://b')
|
||||
p3 = http.Request('http://c')
|
||||
requests = [p1, p2, p3]
|
||||
|
||||
def all_done():
|
||||
pass # all requests complete
|
||||
|
||||
b = barrier(requests).then(all_done)
|
||||
|
||||
# oops, we forgot we want another request
|
||||
b.add(http.Request('http://d'))
|
||||
|
||||
Note that you cannot add new promises to a barrier after
|
||||
the barrier is fulfilled.
|
||||
"""
|
||||
|
||||
def __init__(self, promises=None, args=None, kwargs=None,
|
||||
callback=None, size=None):
|
||||
self.p = promise()
|
||||
self.args = args or ()
|
||||
self.kwargs = kwargs or {}
|
||||
self._value = 0
|
||||
self.size = size or 0
|
||||
if not self.size and promises:
|
||||
# iter(l) calls len(l) so generator wrappers
|
||||
# can only return NotImplemented in the case the
|
||||
# generator is not fully consumed yet.
|
||||
plen = promises.__len__()
|
||||
if plen is not NotImplemented:
|
||||
self.size = plen
|
||||
self.ready = self.failed = False
|
||||
self.reason = None
|
||||
self.cancelled = False
|
||||
self.finalized = False
|
||||
|
||||
[self.add_noincr(p) for p in promises or []]
|
||||
self.finalized = bool(promises or self.size)
|
||||
if callback:
|
||||
self.then(callback)
|
||||
|
||||
__slots__ = ( # noqa
|
||||
'p', 'args', 'kwargs', '_value', 'size',
|
||||
'ready', 'reason', 'cancelled', 'finalized',
|
||||
'__weakref__',
|
||||
# adding '__dict__' to get dynamic assignment
|
||||
"__dict__",
|
||||
)
|
||||
|
||||
def __call__(self, *args, **kwargs):
|
||||
if not self.ready and not self.cancelled:
|
||||
self._value += 1
|
||||
if self.finalized and self._value >= self.size:
|
||||
self.ready = True
|
||||
self.p(*self.args, **self.kwargs)
|
||||
|
||||
def finalize(self):
|
||||
if not self.finalized and self._value >= self.size:
|
||||
self.p(*self.args, **self.kwargs)
|
||||
self.finalized = True
|
||||
|
||||
def cancel(self):
|
||||
self.cancelled = True
|
||||
self.p.cancel()
|
||||
|
||||
def add_noincr(self, p):
|
||||
if not self.cancelled:
|
||||
if self.ready:
|
||||
raise ValueError('Cannot add promise to full barrier')
|
||||
p.then(self)
|
||||
|
||||
def add(self, p):
|
||||
if not self.cancelled:
|
||||
self.add_noincr(p)
|
||||
self.size += 1
|
||||
|
||||
def then(self, callback, errback=None):
|
||||
self.p.then(callback, errback)
|
||||
|
||||
def throw(self, *args, **kwargs):
|
||||
if not self.cancelled:
|
||||
self.p.throw(*args, **kwargs)
|
||||
throw1 = throw
|
||||
|
||||
|
||||
Thenable.register(barrier)
|
||||
27
ETB-API/venv/lib/python3.12/site-packages/vine/utils.py
Normal file
27
ETB-API/venv/lib/python3.12/site-packages/vine/utils.py
Normal file
@@ -0,0 +1,27 @@
|
||||
"""Python compatibility utilities."""
|
||||
from functools import WRAPPER_ASSIGNMENTS, WRAPPER_UPDATES, partial
|
||||
from functools import update_wrapper as _update_wrapper
|
||||
|
||||
__all__ = ['update_wrapper', 'wraps']
|
||||
|
||||
|
||||
def update_wrapper(wrapper, wrapped, *args, **kwargs):
|
||||
"""Update wrapper, also setting .__wrapped__."""
|
||||
wrapper = _update_wrapper(wrapper, wrapped, *args, **kwargs)
|
||||
wrapper.__wrapped__ = wrapped
|
||||
return wrapper
|
||||
|
||||
|
||||
def wraps(wrapped,
|
||||
assigned=WRAPPER_ASSIGNMENTS,
|
||||
updated=WRAPPER_UPDATES):
|
||||
"""Backport of Python 3.5 wraps that adds .__wrapped__."""
|
||||
return partial(update_wrapper, wrapped=wrapped,
|
||||
assigned=assigned, updated=updated)
|
||||
|
||||
|
||||
def reraise(tp, value, tb=None):
|
||||
"""Reraise exception."""
|
||||
if value.__traceback__ is not tb:
|
||||
raise value.with_traceback(tb)
|
||||
raise value
|
||||
Reference in New Issue
Block a user