You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							90 lines
						
					
					
						
							2.2 KiB
						
					
					
				
			
		
		
	
	
							90 lines
						
					
					
						
							2.2 KiB
						
					
					
				import abc
 | 
						|
import functools
 | 
						|
import weakref
 | 
						|
 | 
						|
from . import exc as async_exc
 | 
						|
 | 
						|
 | 
						|
class ReversibleProxy:
 | 
						|
    # weakref.ref(async proxy object) -> weakref.ref(sync proxied object)
 | 
						|
    _proxy_objects = {}
 | 
						|
    __slots__ = ("__weakref__",)
 | 
						|
 | 
						|
    def _assign_proxied(self, target):
 | 
						|
        if target is not None:
 | 
						|
            target_ref = weakref.ref(target, ReversibleProxy._target_gced)
 | 
						|
            proxy_ref = weakref.ref(
 | 
						|
                self,
 | 
						|
                functools.partial(ReversibleProxy._target_gced, target_ref),
 | 
						|
            )
 | 
						|
            ReversibleProxy._proxy_objects[target_ref] = proxy_ref
 | 
						|
 | 
						|
        return target
 | 
						|
 | 
						|
    @classmethod
 | 
						|
    def _target_gced(cls, ref, proxy_ref=None):
 | 
						|
        cls._proxy_objects.pop(ref, None)
 | 
						|
 | 
						|
    @classmethod
 | 
						|
    def _regenerate_proxy_for_target(cls, target):
 | 
						|
        raise NotImplementedError()
 | 
						|
 | 
						|
    @classmethod
 | 
						|
    def _retrieve_proxy_for_target(cls, target, regenerate=True):
 | 
						|
        try:
 | 
						|
            proxy_ref = cls._proxy_objects[weakref.ref(target)]
 | 
						|
        except KeyError:
 | 
						|
            pass
 | 
						|
        else:
 | 
						|
            proxy = proxy_ref()
 | 
						|
            if proxy is not None:
 | 
						|
                return proxy
 | 
						|
 | 
						|
        if regenerate:
 | 
						|
            return cls._regenerate_proxy_for_target(target)
 | 
						|
        else:
 | 
						|
            return None
 | 
						|
 | 
						|
 | 
						|
class StartableContext(abc.ABC):
 | 
						|
    __slots__ = ()
 | 
						|
 | 
						|
    @abc.abstractmethod
 | 
						|
    async def start(self, is_ctxmanager=False):
 | 
						|
        pass
 | 
						|
 | 
						|
    def __await__(self):
 | 
						|
        return self.start().__await__()
 | 
						|
 | 
						|
    async def __aenter__(self):
 | 
						|
        return await self.start(is_ctxmanager=True)
 | 
						|
 | 
						|
    @abc.abstractmethod
 | 
						|
    async def __aexit__(self, type_, value, traceback):
 | 
						|
        pass
 | 
						|
 | 
						|
    def _raise_for_not_started(self):
 | 
						|
        raise async_exc.AsyncContextNotStarted(
 | 
						|
            "%s context has not been started and object has not been awaited."
 | 
						|
            % (self.__class__.__name__)
 | 
						|
        )
 | 
						|
 | 
						|
 | 
						|
class ProxyComparable(ReversibleProxy):
 | 
						|
    __slots__ = ()
 | 
						|
 | 
						|
    def __hash__(self):
 | 
						|
        return id(self)
 | 
						|
 | 
						|
    def __eq__(self, other):
 | 
						|
        return (
 | 
						|
            isinstance(other, self.__class__)
 | 
						|
            and self._proxied == other._proxied
 | 
						|
        )
 | 
						|
 | 
						|
    def __ne__(self, other):
 | 
						|
        return (
 | 
						|
            not isinstance(other, self.__class__)
 | 
						|
            or self._proxied != other._proxied
 | 
						|
        )
 |