async-object let you write classes with async def __init__
Project description
async-object
async-object
let you write classes with async def __init__
Installation
From PyPI repository
pip install --user async-object
From source
git clone https://github.com/francis-clairicia/async-object.git
cd async-object
pip install --user .
Usage
It is simple, with async-object
you can do this:
from async_object import AsyncObject
class MyObject(AsyncObject):
async def __init__(self) -> None:
await super().__init__()
# Do some async stuff
if __name__ == "__main__":
import asyncio
async def main() -> None:
instance = await MyObject()
assert isinstance(instance, MyObject)
asyncio.run(main())
This example uses asyncio
, but it is compatible with all runner libraries, since this package only uses the language syntax.
Description
async-object
provides a base class AsyncObject
using AsyncObjectMeta
metaclass.
AsyncObjectMeta
overrides the default type
constructor in order to return a coroutine, which must be await
-ed to get the instance.
async def main() -> None:
coroutine = MyObject()
print(coroutine)
instance = await coroutine
print(instance)
Replace the main
in the Usage example by this one and run it. You should see something like this in your console:
<coroutine object AsyncObjectMeta.__call__ at 0x7ff1f28eb300>
<__main__.MyObject object at 0x7ff1f21a4fd0>
Arguments
Obviously, arguments can be given to __init__
and __new__
.
The inheritance logic with "normal" constructors is the same here:
from typing_extensions import Self
class MyObjectOnlyNew(AsyncObject):
def __new__(cls, *args: Any, **kwargs: Any) -> Self:
self = super().__new__(cls)
print(args)
print(kwargs)
return self
class MyObjectOnlyInit(AsyncObject):
async def __init__(self, *args: Any, **kwargs: Any) -> None:
# await super().__init__() # Optional if the base class is only AsyncObject (but useful in multiple inheritance context)
print(args)
print(kwargs)
class MyObjectBothNewAndInit(AsyncObject):
def __new__(cls, *args: Any, **kwargs: Any) -> Self:
self = super().__new__(cls)
print(args)
print(kwargs)
return self
async def __init__(self, *args: Any, **kwargs: Any) -> None:
# await super().__init__()
print(args)
print(kwargs)
Inheritance
Talking about inheritance, there are a few rules to follow:
AsyncObject
or a subclass must appear at least once in the base classes declaration.- Non-
AsyncObject
classes can be used as base classes if they do not override__init__
(in order not to break the MRO). - To avoid confusion with awaitable objects, overriding
__await__
is forbidden.
Abstract base classes
There is a metaclass AsyncABCMeta
deriving from AsyncObjectMeta
and abc.ABCMeta
which allows you to declare abstract base classes
import abc
from async_object import AsyncObject, AsyncABCMeta
class MyAbstractObject(AsyncObject, metaclass=AsyncABCMeta):
@abc.abstractmethod
def method(self) -> None:
raise NotImplementedError
@abc.abstractmethod
async def async_method(self) -> None:
raise NotImplementedError
class MyObject(MyAbstractObject):
async def __init__(self) -> None:
pass
def method(self) -> None:
pass
async def async_method(self) -> None:
pass
N.B.: There is a shorthand AsyncABC
like abc.ABC
.
import abc
from async_object import AsyncABC
class MyAbstractObject(AsyncABC):
@abc.abstractmethod
def method(self) -> None:
raise NotImplementedError
@abc.abstractmethod
async def async_method(self) -> None:
raise NotImplementedError
Static type checking: mypy integration
mypy
does not like having async def
for __init__
, and will not understand await AsyncObject()
.
async-object
embeds a plugin which helps mypy
to understand asynchronous constructors.
Installation
Firstly, install the needed dependencies:
pip install async-object[mypy]
To register this plugin in your mypy.ini
, pyproject.toml
, or whatever, you must add async_object.contrib.mypy.plugin
to the plugins list.
In mypy.ini
:
[mypy]
plugins = async_object.contrib.mypy.plugin
In pyproject.toml
:
[tool.mypy]
plugins = ["async_object.contrib.mypy.plugin"]
For more information, see the mypy documentation.
What is permitted then ?
__init__
method returning a coroutine is accepted
The error The return type of "__init__" must be None
is discarded.
class MyObject(AsyncObject):
async def __init__(self, param: int) -> None:
await super().__init__()
The class instanciation introspection is fixed
async def main() -> None:
coroutine = MyObject()
reveal_type(coroutine) # Revealed type is "typing.Coroutine[Any, Any, __main__.MyObject]"
instance = await coroutine
reveal_type(instance) # Revealed type is "__main__.MyObject"
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
File details
Details for the file async_object-2.0.0.tar.gz
.
File metadata
- Download URL: async_object-2.0.0.tar.gz
- Upload date:
- Size: 32.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/4.0.2 CPython/3.9.18
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 0168dc4489ea3bf6620837d9af1382d36524b435d0ebdea2affcdbc802b5f9f3 |
|
MD5 | 0cc1ef9b8ac5be5e64e13f449e941534 |
|
BLAKE2b-256 | 5ee1bf32038dce05cfcf528c5222c227403318a948c6a458dbf0a9ae67f2220e |
File details
Details for the file async_object-2.0.0-py3-none-any.whl
.
File metadata
- Download URL: async_object-2.0.0-py3-none-any.whl
- Upload date:
- Size: 8.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/4.0.2 CPython/3.9.18
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | fa527d7af21b274972ee171347370099ae2f3a8353a6f3bbaa4958919ac364c2 |
|
MD5 | 2fbb90cd561149f8b2d405fc2b733017 |
|
BLAKE2b-256 | 767ec72fe3e97116b6f6bbbbf517f9777efc62ee113f08d11b2ea3790768a7ad |