Module graia.broadcast.utilles

Expand source code
import inspect
import itertools
from functools import lru_cache
from typing import (
    Any,
    Callable,
    Generator,
    Generic,
    Iterable,
    List,
    Tuple,
    TypeVar,
    Union,
)

from iterwrapper import IterWrapper

from .entities.dispatcher import BaseDispatcher


async def run_always_await(any_callable):
    if inspect.iscoroutine(any_callable):
        return await any_callable
    else:
        return any_callable


async def run_always_await_safely(callable, *args, **kwargs):
    if iscoroutinefunction(callable):
        return await callable(*args, **kwargs)
    return callable(*args, **kwargs)


def printer(value):
    print(value)
    return value


def group_dict(iw: IterWrapper, key: Callable[[Any], Any]):
    temp = {}
    for i in iw:
        k = key(i)
        temp.setdefault(k, [])
        temp[k].append(i)
    return temp


cache_size = 4096

origin_isinstance = isinstance

cached_isinstance = lru_cache(1024)(isinstance)
cached_getattr = lru_cache(cache_size)(getattr)


@lru_cache(cache_size)
def argument_signature(callable_target):
    return [
        (
            name,
            param.annotation if param.annotation != inspect._empty else None,
            param.default if param.default != inspect._empty else None,
        )
        for name, param in dict(inspect.signature(callable_target).parameters).items()
    ]


@lru_cache(cache_size)
def is_asyncgener(o):
    return inspect.isasyncgenfunction(o)


@lru_cache(cache_size)
def iscoroutinefunction(o):
    return inspect.iscoroutinefunction(o)


@lru_cache(cache_size)
def isasyncgen(o):
    return inspect.isasyncgen(o)


def flat_yield_from(l):
    for i in l:
        if type(i) == list:
            yield from i


@lru_cache(None)
def dispatcher_mixin_handler(dispatcher: BaseDispatcher) -> List[BaseDispatcher]:
    unbound_mixin = getattr(dispatcher, "mixin", [])
    result = [dispatcher]

    for i in unbound_mixin:
        if issubclass(i, BaseDispatcher):
            result.extend(dispatcher_mixin_handler(i))
        else:
            result.append(i)
    return result


class as_sliceable:
    def __init__(self, iterable) -> None:
        self.iterable = iterable

    def __getitem__(self, item: Union[slice, int]) -> Any:
        if isinstance(item, slice):
            return itertools.islice(self.iterable, item.start, item.stop, item.step)
        else:
            return list(itertools.islice(self.iterable, item, item + 1, None))[0]

    def __iter__(self):
        return self.iterable


T = TypeVar("T")

"""
class NestableIterable(Iterable[T]):
    index_stack: list
    iterable: Iterable[T]

    def __init__(self, iterable: Iterable[T]) -> None:
        self.iterable = iterable
        self.index_stack = [0]

    def __iter__(self):
        index = self.index_stack[-1]
        self.index_stack.append(self.index_stack[-1])

        start_offset = index + int(bool(index))
        try:
            for self.index_stack[-1], content in enumerate(
                itertools.islice(self.iterable, start_offset, None, None),
                start=start_offset,
            ):
                yield content
        finally:
            self.index_stack.pop()

    def with_new(self, target):
        self.iterable = target
        return self
"""

I = TypeVar("I")


class NestableIterable(Generic[I, T]):
    iterable: Iterable[T]
    indexes: List[I]

    generator_with_index_factory: Callable[
        [Iterable[T], I], Generator[None, None, Tuple[I, T]]
    ]
    index_increase_func: Callable[[I, Iterable[T]], I]
    is_index_origin: Callable[[I], bool]

    @staticmethod
    def default_generator_factory(iterable: Iterable[T], start: I):
        return enumerate(iterable[start:], start=start)

    def __init__(
        self,
        iterable: Iterable[T],
        generator_with_index_factory: Callable[
            [Iterable[T], I], Generator[None, None, Tuple[I, T]]
        ] = None,
        index_increase_func: Callable[[I, Iterable[T]], I] = lambda x, _: x + 1,
        initial_index_value_factory: Callable[[], I] = lambda: 0,
        is_index_origin: Callable[[I], bool] = lambda x: x == 0,
    ) -> None:
        self.iterable = iterable
        self.indexes = [initial_index_value_factory()]

        self.generator_with_index_factory = (
            generator_with_index_factory or self.default_generator_factory
        )
        self.index_increase_func = index_increase_func
        self.is_index_origin = is_index_origin

    def __iter__(self):
        current_index = self.indexes[-1]
        self.indexes.append(current_index)

        if self.is_index_origin(current_index):
            start_offset = current_index
        else:
            start_offset = self.index_increase_func(current_index, self.iterable)
        # 0 = 0
        # <except 0> = index + 1
        try:
            for self.indexes[-1], content in self.generator_with_index_factory(
                self.iterable,
                start=start_offset,
            ):
                yield content
        finally:
            self.indexes.pop()

Global variables

var T

class NestableIterable(Iterable[T]): index_stack: list iterable: Iterable[T]

def __init__(self, iterable: Iterable[T]) -> None:
    self.iterable = iterable
    self.index_stack = [0]

def __iter__(self):
    index = self.index_stack[-1]
    self.index_stack.append(self.index_stack[-1])

    start_offset = index + int(bool(index))
    try:
        for self.index_stack[-1], content in enumerate(
            itertools.islice(self.iterable, start_offset, None, None),
            start=start_offset,
        ):
            yield content
    finally:
        self.index_stack.pop()

def with_new(self, target):
    self.iterable = target
    return self

Functions

def argument_signature(callable_target)
Expand source code
@lru_cache(cache_size)
def argument_signature(callable_target):
    return [
        (
            name,
            param.annotation if param.annotation != inspect._empty else None,
            param.default if param.default != inspect._empty else None,
        )
        for name, param in dict(inspect.signature(callable_target).parameters).items()
    ]
def dispatcher_mixin_handler(dispatcher: BaseDispatcher) ‑> List[BaseDispatcher]
Expand source code
@lru_cache(None)
def dispatcher_mixin_handler(dispatcher: BaseDispatcher) -> List[BaseDispatcher]:
    unbound_mixin = getattr(dispatcher, "mixin", [])
    result = [dispatcher]

    for i in unbound_mixin:
        if issubclass(i, BaseDispatcher):
            result.extend(dispatcher_mixin_handler(i))
        else:
            result.append(i)
    return result
def flat_yield_from(l)
Expand source code
def flat_yield_from(l):
    for i in l:
        if type(i) == list:
            yield from i
def group_dict(iw: iterwrapper.wrapper.IterWrapper, key: Callable[[Any], Any])
Expand source code
def group_dict(iw: IterWrapper, key: Callable[[Any], Any]):
    temp = {}
    for i in iw:
        k = key(i)
        temp.setdefault(k, [])
        temp[k].append(i)
    return temp
def is_asyncgener(o)
Expand source code
@lru_cache(cache_size)
def is_asyncgener(o):
    return inspect.isasyncgenfunction(o)
def isasyncgen(o)
Expand source code
@lru_cache(cache_size)
def isasyncgen(o):
    return inspect.isasyncgen(o)
def iscoroutinefunction(o)
Expand source code
@lru_cache(cache_size)
def iscoroutinefunction(o):
    return inspect.iscoroutinefunction(o)
def printer(value)
Expand source code
def printer(value):
    print(value)
    return value
async def run_always_await(any_callable)
Expand source code
async def run_always_await(any_callable):
    if inspect.iscoroutine(any_callable):
        return await any_callable
    else:
        return any_callable
async def run_always_await_safely(callable, *args, **kwargs)
Expand source code
async def run_always_await_safely(callable, *args, **kwargs):
    if iscoroutinefunction(callable):
        return await callable(*args, **kwargs)
    return callable(*args, **kwargs)

Classes

class NestableIterable (iterable: Iterable[~T], generator_with_index_factory: Callable[[Iterable[~T], ~I], Generator[NoneType, NoneType, Tuple[~I, ~T]]] = None, index_increase_func: Callable[[~I, Iterable[~T]], ~I] = <function NestableIterable.<lambda>>, initial_index_value_factory: Callable[[], ~I] = <function NestableIterable.<lambda>>, is_index_origin: Callable[[~I], bool] = <function NestableIterable.<lambda>>)

Abstract base class for generic types.

A generic type is typically declared by inheriting from this class parameterized with one or more type variables. For example, a generic mapping type might be defined as::

class Mapping(Generic[KT, VT]): def getitem(self, key: KT) -> VT: … # Etc.

This class can then be used as follows::

def lookup_name(mapping: Mapping[KT, VT], key: KT, default: VT) -> VT: try: return mapping[key] except KeyError: return default

Expand source code
class NestableIterable(Iterable[T]):
    index_stack: list
    iterable: Iterable[T]

    def __init__(self, iterable: Iterable[T]) -> None:
        self.iterable = iterable
        self.index_stack = [0]

    def __iter__(self):
        index = self.index_stack[-1]
        self.index_stack.append(self.index_stack[-1])

        start_offset = index + int(bool(index))
        try:
            for self.index_stack[-1], content in enumerate(
                itertools.islice(self.iterable, start_offset, None, None),
                start=start_offset,
            ):
                yield content
        finally:
            self.index_stack.pop()

    def with_new(self, target):
        self.iterable = target
        return self

Ancestors

  • typing.Generic

Class variables

var generator_with_index_factory : Callable[[Iterable[~T], ~I], Generator[NoneType, NoneType, Tuple[~I, ~T]]]
var index_increase_func : Callable[[~I, Iterable[~T]], ~I]
var indexes : List[~I]
var is_index_origin : Callable[[~I], bool]
var iterable : Iterable[~T]

Static methods

def default_generator_factory(iterable: Iterable[~T], start: ~I)
Expand source code
@staticmethod
def default_generator_factory(iterable: Iterable[T], start: I):
    return enumerate(iterable[start:], start=start)
class as_sliceable (iterable)
Expand source code
class as_sliceable:
    def __init__(self, iterable) -> None:
        self.iterable = iterable

    def __getitem__(self, item: Union[slice, int]) -> Any:
        if isinstance(item, slice):
            return itertools.islice(self.iterable, item.start, item.stop, item.step)
        else:
            return list(itertools.islice(self.iterable, item, item + 1, None))[0]

    def __iter__(self):
        return self.iterable