Source code for asyncqlio.meta
"""
Useful metamagic classes, such as async ABCs.
"""
import inspect
import typing
from abc import ABCMeta
[docs]def make_proxy(name: str):
"""
Makes a proxy object for magic methods.
"""
def proxy(self, *args, **kwargs):
item = self.__getattr__(name)
return item(*args, **kwargs)
return proxy
[docs]def proxy_to_getattr(*magic_methods: str):
"""
Proxies a method to to ``__getattr__`` when it would not be normally proxied.
This is used for magic methods that are slot loaded (``__setattr__`` etc.)
:param magic_methods: The magic methods to proxy to getattr.
"""
def _modify_type(obb):
for item in magic_methods:
setattr(obb, item, make_proxy(item))
return obb
return _modify_type
[docs]class TypeProperty(object):
"""
A property on a type.
"""
def __init__(self, fget):
"""
:param fget: The function to call on getting the property.
"""
self.fget = fget
self.name = None
def __set_name__(self, owner, name):
self.name = name
def __get__(self, instance, owner):
# we always the type, never the instance
if owner is None:
owner = type(instance)
return self.fget.__get__(instance, owner)()
[docs]def typeproperty(func: typing.Callable[[], typing.Any]) -> TypeProperty:
"""
Marks a function as a type property.
"""
if not isinstance(func, (classmethod, staticmethod)):
func = classmethod(func)
return TypeProperty(func)
# Copied from https://github.com/dabeaz/curio/blob/master/curio/meta.py
# Copyright (C) David Beazley (Dabeaz LLC)
# This code is licenced under the MIT licence.
# This code has been minutely edited in formatting and docstrings.
super().__init__(name, bases, methods)
class AsyncABC(metaclass=AsyncABCMeta):
pass
[docs]class AsyncInstanceType(AsyncABCMeta):
"""
Metaclass that allows for asynchronous instance initialization and the
__init__() method to be defined as a coroutine.
.. code-block:: python3
class Spam(metaclass=AsyncInstanceType):
async def __init__(self, x, y):
self.x = x
self.y = y
async def main():
s = await Spam(2, 3)
...
"""
@staticmethod
def __new__(meta, clsname, bases, attributes):
if '__init__' in attributes and not inspect.iscoroutinefunction(attributes['__init__']):
raise TypeError('__init__ must be a coroutine')
return super().__new__(meta, clsname, bases, attributes)
async def __call__(cls, *args, **kwargs):
self = cls.__new__(cls, *args, **kwargs)
await self.__init__(*args, **kwargs)
return self
class AsyncObject(metaclass=AsyncInstanceType):
pass
...
# END COPIED CODE