diff --git a/compiler/docs/compiler.py b/compiler/docs/compiler.py index 91bbad38..cce4f769 100644 --- a/compiler/docs/compiler.py +++ b/compiler/docs/compiler.py @@ -339,7 +339,7 @@ def pyrogram_api(): f2.write(title + "\n" + "=" * len(title) + "\n\n") f2.write(".. automethod:: pyrogram.Client.{}()".format(method)) - functions = ["idle"] + functions = ["idle", "compose"] for func in functions: with open(root + "/{}.rst".format(func), "w") as f2: diff --git a/compiler/docs/template/methods.rst b/compiler/docs/template/methods.rst index 794e657e..1620350d 100644 --- a/compiler/docs/template/methods.rst +++ b/compiler/docs/template/methods.rst @@ -1,8 +1,9 @@ Available Methods ================= -This page is about Pyrogram methods. All the methods listed here are bound to a :class:`~pyrogram.Client` instance. -Some other utility functions can instead be found in the main package directly. +This page is about Pyrogram methods. All the methods listed here are bound to a :class:`~pyrogram.Client` instance, +except for :meth:`~pyrogram.idle()` and :meth:`~pyrogram.compose()`, which are special functions that can be found in +the main package directly. .. code-block:: python @@ -40,11 +41,13 @@ Utilities :nosignatures: idle + compose .. toctree:: :hidden: idle + compose .. currentmodule:: pyrogram.Client diff --git a/pyrogram/__init__.py b/pyrogram/__init__.py index bcef9c1d..1b8202ce 100644 --- a/pyrogram/__init__.py +++ b/pyrogram/__init__.py @@ -37,6 +37,6 @@ class ContinuePropagation(StopAsyncIteration): from . import raw, types, filters, handlers, emoji, enums from .client import Client -from .sync import idle +from .sync import idle, compose crypto_executor = ThreadPoolExecutor(1, thread_name_prefix="CryptoWorker") diff --git a/pyrogram/methods/utilities/compose.py b/pyrogram/methods/utilities/compose.py new file mode 100644 index 00000000..c8bdf769 --- /dev/null +++ b/pyrogram/methods/utilities/compose.py @@ -0,0 +1,62 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-present Dan +# +# This file is part of Pyrogram. +# +# Pyrogram is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pyrogram is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Pyrogram. If not, see . + +from typing import List + +import pyrogram +from .idle import idle + + +async def compose(clients: List["pyrogram.Client"]): + """Run multiple clients at once. + + This method can be used to run multiple clients at once and can be found directly in the ``pyrogram`` package. + + If you want to run a single client, you can use Client's bound method :meth:`~pyrogram.Client.run`. + + Parameters: + clients (List of :obj:`~pyrogram.Client`): + A list of client objects to run. + + Example: + .. code-block:: python + + import asyncio + from pyrogram import Client, compose + + + async def main(): + app1 = Client("account1") + app2 = Client("account2") + app3 = Client("account3") + + ... + + await compose([app1, app2, app3]) + + + asyncio.run(main()) + + """ + for c in clients: + await c.start() + + await idle() + + for c in clients: + await c.stop() diff --git a/pyrogram/methods/utilities/run.py b/pyrogram/methods/utilities/run.py index e3890355..ec1bece3 100644 --- a/pyrogram/methods/utilities/run.py +++ b/pyrogram/methods/utilities/run.py @@ -38,6 +38,8 @@ class Run: operation. This is almost the same as :py:obj:`asyncio.run` except for the fact that Pyrogram's ``run`` uses the current event loop instead of a new one. + If you want to run multiple clients at once, see :meth:`pyrogram.compose`. + Parameters: coroutine (``Coroutine``, *optional*): Pass a coroutine to run it until it completes. diff --git a/pyrogram/sync.py b/pyrogram/sync.py index 41c23e3b..94c82a3d 100644 --- a/pyrogram/sync.py +++ b/pyrogram/sync.py @@ -23,7 +23,7 @@ import threading from pyrogram import types from pyrogram.methods import Methods -from pyrogram.methods.utilities import idle as idle_module +from pyrogram.methods.utilities import idle as idle_module, compose as compose_module def async_to_sync(obj, name): @@ -105,6 +105,9 @@ for class_name in dir(types): if inspect.isclass(cls): wrap(cls) -# Special case for idle, because it's not inside Methods +# Special case for idle and compose, because they are not inside Methods async_to_sync(idle_module, "idle") idle = getattr(idle_module, "idle") + +async_to_sync(compose_module, "compose") +compose = getattr(compose_module, "compose")