Metadata-Version: 2.1
Name: aevent
Version: 0.1.1
Summary: Call synchronous Python from async code, without blocking
Home-page: UNKNOWN
Author: Matthias Urlichs
Author-email: matthias@urlichs.de
License: MIT
Project-URL: Source code, https://github.com/M-o-a-T/aevent
Project-URL: Issue tracker, https://github.com/M-o-a-T/aevent/issues
Description: ====================================
        ``aevent``: an asyncronizing library
        ====================================
        
        ``aevent`` lets you call boring synchronous Python from async code.
        Without blocking or splatting ``async`` and ``await`` onto it.
        Ideally, this works without modifying the synchronous code.
        
        Put another way,
        ``aevent`` is to ``gevent`` what ``anyio`` is to ``greenlet``.
        
        That is, it replaces standard Python functions with calls to `anyio`_
        instead of ``gevent``.
        
        Some limitations apply.
        
        Usage
        =====
        
        **Before any other imports**, insert this code block into your main code::
        
           import aevent
           aevent.setup('trio')  # or asyncio, if you must
           
        This will annoy various code checkers, but that can't be helped.
        
        **Start your main loop** using ``aevent.run``, or call ``await aevent.per_task()``
        in the task(s) that need to use patched code.
        
        The ``aevent.native`` and ``aevent.patched`` context managers can be used to
        temporarily disable or re-enable ``aevent``'s patches.
        
        
        Support functions
        -----------------
        
        ``aevent`` monkey-patches ``anyio``'s ``TaskGroup.spawn`` in two ways.
        
        * the child task is instrumented to support `greenback`.
        
        * ``spawn`` returns a cancel scope. You can use it to cancel the new task.
        
        Call ``aevent.per_task`` in your child task if you start tasks some other way.
        
        
        Threading
        ---------
        
        Threads are translated to tasks. In order for that to work, you must start
        your program with `aevent.run`, or run the sync code in question within an
        `aevent.runner` async context manager. Runners may be nested.
        
        
        Supported modules
        =================
        
        * time
        
          * sleep
        
        * threading
        * queue
        * atexit
        * socket
        * select
        
          * poll
        
        Not yet supported
        -----------------
        
        * select
        
          * anything else
        
        * dns
        * os
        
          * read
        
          * write
        
        * ssl
        * subprocess
        * signal
        
        
        Subclassing patched classes
        ---------------------------
        
        Directly subclassing one of the classes patched by ``aevent`` does not
        work and requires special consideration. Consider this code::
        
           class my_thread(threading.Thread):
              def run(self):
                  ...
        
        For use with ``aevent`` you can choose the original ``Thread``
        implementation::
        
            orig_Thread = getattr(threading.Thread, "_aevent_orig", threading.Thread)
            class my_thread(orig_Thread):
              ...
        
        or the ``aevent``-ified version::
        
            new_Thread = threading.Thread._aevent_new # fails when aevent is not loaded
            class my_thread(new_Thread):
              ...
        
        or you might want to create two separate implementations, and switch based
        on the aevent context::
        
            class _orig_my_thread(threading.Thread._aevent_orig):
               ...
            class _new_my_thread(threading.Thread._aevent_new):
               ...
            my_thread = aevent.patch__new_my_thread, name="my_thread", orig=_orig_my_thread)
        
        If you generate local subclasses on the fly, you can simplify this to::
        
            def some_code():
                class my_thread(threading.Thread._aevent_select()):
                    def run(self):
                        ...
                job = my_tread()
                my_thread.start()
        
        
        Other affected modules
        ----------------------
        
        You need to import any module which requires non-patched code before
        importing ``aevent``.
        
        Modules which are known to be affected:
        
        * multiprocessing
        
        
        Internals
        =========
        
        ``aevent``'s monkey patching is done mainly on the module/class level.
        ``gevent`` prefers to patch individual methods. This may cause some
        reduced compatibility compared to ``gevent``.
        
        ``aevent`` works by prepending its local ``_monkey`` directory to the import path.
        These modules try to afford the same public interface as the ones they're
        replacing while calling the corresponding ``anyio`` functions through
        `greenback_`.
        
        Context switching back to async-flavored code is done by way of `greenback`_.
        
        ``aevent`` runs on Python 3.7 ff.
        
        Testing
        -------
        
        The test suite runs with `trio`_ as backend. Due to ``aevent``'s monkeypatching,
        switching backends around is not supported. However, you can set the
        environment variable ``AEVENT_BACKEND`` to `asyncio`_ to run the test
        suite with that.
        
        The test suite pulls in a copy of `pyroute2`_ (no changes, other than fixing
        bugs unrelated to ``aevent``) and tests against its test suite, thereby
        (mostly) ensuring that this particular package works with ``aevent``.
        
        .. _asyncio: https://docs.python.org/3/library/asyncio.html
        .. _trio: https://github.com/python-trio/trio
        .. _anyio: https://github.com/agronholm/anyio
        .. _greenback: https://github.com/oremanj/greenback
        .. _pyroute2: https://github.com/svinota/pyroute2
        
Platform: UNKNOWN
Classifier: Development Status :: 1 - Planning
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.7
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Requires-Python: >=3.7.0
Provides-Extra: doc
Provides-Extra: test
Provides-Extra: trio
