Skip to content

2.8.0 - Refactoring, bug fixes, new loop_run function and more!

Compare
Choose a tag to compare
@Someguy123 Someguy123 released this 17 Dec 20:51
· 36 commits to master since this release

Tl;Dr; important changes

  • Added asyncx functions: loop_run, is_async_context, _awaitable_blacklisted
  • Added asyncx decorator awaitable_class, and mixin class AwaitableMixin (mixin version of awaitable_class decorator)
  • Removed class helpers.extras.git.Git and replaced it with an alias to AsyncGit as @awaitable_class rendered the
    wrapper class obsolete
  • Refactored some types from common module into types
  • Refactored tests and added some new tests for some of the added functions/classes
  • Various refactoring and general cleanup

New Features / Additions

  • asyncx.loop_run is similar to asyncx.run_sync, but more flexible, and doesn't use the deprecated asyncio.coroutine
    function. It can be passed either a coroutine directly for execution, or if a function/method is passed,
    (doesn't have to be async) then it can attempt to extract the coroutine by calling each layer until a coroutine
    or non-callable is found.

    While there's no plan to remove asynx.run_sync in the near future, it's strongly recommended to switch usages of run_sync
    to loop_run because it's better at handling different forms of awaitable objects:

    • Unlike run_sync, loop_run can handle both async function references AND coroutines

    • Unlike run_sync, loop_run can unwrap coroutines / async function references that are wrapped in a normal
      non-async function (e.g. @awaitable wrapper functions)

    • Unlike run_sync, loop_run can accept the optional _loop keyword argument, allowing you to specify a custom asyncio
      event loop if you desire.

    • Unlike run_sync, loop_run will cleanly execute non-async functions if they're encountered, and simply return
      non-callable objects that were passed to it, instead of failing.

  • New function / class decorator asyncx.awaitable_class - wraps a class and overrides __getattribute__ to enable all async
    methods to be called from non-async code. Similar to asyncx.awaitable, but affects all async methods in a class, and
    doesn't require non-async wrapper functions to be written.

    • If a non-async method or standard attribute is requested, then those are returned as normal without modification.

    • If an async method is called on the class, then it checks to see if there's a current AsyncIO context - if there is, it
      simply returns the coroutine for await'ing

    • If there isn't an async context, it will use loop_run to call the method synchronously using the
      current event loop, and return the method's result synchronously.

  • New class asyncx.AwaitableMixin - a mixin class which works the same as asyncx.awaitable_class, but as a mixin class
    add to your class's inheritance, instead of a decorator.

  • Created the file CHANGELOG.md - note that it doesn't contain a full changelog yet, it only goes back as far as version 2.5

Changes / Updates

  • The wrapper class helpers.extras.git.Git has been removed, as AsyncGit now uses the much simpler @awaitable_class
    decorator to enable synchronous usage of all async methods, instead of a sub-class with individually @awaitable wrapped
    methods.

    To avoid breaking any existing code which relied on extras.git.Git, Git is now an alias for AsyncGit. No changes
    needed to be made to the Git tests in tests/test_extras.py, so this change isn't believed to cause code breakage.

  • A large portion of the decorator asyncx.awaitable has been refactored into the smaller functions: _awaitable_blacklisted
    and is_async_context.

  • During the refactoring of asyncx.awaitable, a bug was discovered in the blacklist scanning for sub-modules - this is now
    fixed (note: blacklist scanning is refactored into _awaitable_blacklisted)

  • asyncx.py now has an __all__ module attribute, allowing __init__ to simply import * instead of having to list each
    class/function etc.

  • cache.asyncx.__init__

    • Added a PyDoc comment at the start of the file, explaining the AsyncIO adapters and how to use them.

    • Added the attributes HAS_ASYNC_REDIS, HAS_ASYNC_MEMORY, and HAS_ASYNC_MEMCACHED to allow for easy availability
      checking of async cache adapters.

    • Lowered the ImportError log level for AsyncRedisCache and AsyncMemcachedCache from log.exception down to log.debug

  • Refactored various generic / template types (e.g. T, K, CL) from helpers.common into helpers.types

Testing

  • Refactored tests/test_general.py into a folder tests/general/

  • Refactored AsyncIO related tests from tests/test_general.py into tests/asyncx/test_async_common.py

  • Added several new AsyncIO tests to tests/asyncx/test_async_common.py, mainly aimed at the new asyncx.awaitable_class,
    and asyncx.AwaitableMixin