Skip to content

Latest commit

 

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 

README.md

CrossSync

CrossSync provides a simple way to share logic between async and sync code. It is made up of a small library that provides:

  1. a set of shims that provide a shared sync/async API surface
  2. annotations that are used to guide generation of a sync version from an async class

Using CrossSync, the async code is treated as the source of truth, and sync code is generated from it.

Usage

CrossSync Shims

Many Asyncio components have direct, 1:1 threaded counterparts for use in non-asyncio code. CrossSync provides a compatibility layer that works with both

CrossSync Asyncio Version Sync Version
CrossSync.Queue asyncio.Queue queue.Queue
CrossSync.Condition asyncio.Condition threading.Condition
CrossSync.Future asyncio.Future Concurrent.futures.Future
CrossSync.Task asyncio.Task Concurrent.futures.Future
CrossSync.Event asyncio.Event threading.Event
CrossSync.Semaphore asyncio.Semaphore threading.Semaphore
CrossSync.Awaitable typing.Awaitable typing.Union (no-op type)
CrossSync.Iterable typing.AsyncIterable typing.Iterable
CrossSync.Iterator typing.AsyncIterator typing.Iterator
CrossSync.Generator typing.AsyncGenerator typing.Generator
CrossSync.Retry google.api_core.retry.AsyncRetry google.api_core.retry.Retry
CrossSync.StopIteration StopAsyncIteration StopIteration
CrossSync.Mock unittest.mock.AsyncMock unittest.mock.Mock

Custom aliases can be added using CrossSync.add_mapping(class, name)

Additionally, CrossSync provides method implementations that work equivalently in async and sync code:

  • CrossSync.sleep()
  • CrossSync.gather_partials()
  • CrossSync.wait()
  • CrossSync.condition_wait()
  • CrossSync.event_wait()
  • CrossSync.create_task()
  • CrossSync.retry_target()
  • CrossSync.retry_target_stream()

Annotations

CrossSync provides a set of annotations to mark up async classes, to guide the generation of sync code.

  • @CrossSync.convert_sync
    • marks classes for conversion. Unmarked classes will be copied as-is
    • if add_mapping is included, the async and sync classes can be accessed using a shared CrossSync.X alias
  • @CrossSync.convert
    • marks async functions for conversion. Unmarked methods will be copied as-is
  • @CrossSync.drop
    • marks functions or classes that should not be included in sync output
  • @CrossSync.pytest
    • marks test functions. Test functions automatically have all async keywords stripped (i.e., rm_aio is unneeded)
  • CrossSync.add_mapping
    • manually registers a new CrossSync.X alias, for custom types
  • CrossSync.rm_aio
    • Marks regions of the code that include asyncio keywords that should be stripped during generation

Code Generation

Generation can be initiated using nox -s generate_sync from the root of the project. This will find all classes with the __CROSS_SYNC_OUTPUT__ = "path/to/output" annotation, and generate a sync version of classes marked with @CrossSync.convert_sync at the output path.

There is a unit test at tests/unit/data/test_sync_up_to_date.py that verifies that the generated code is up to date

Architecture

CrossSync is made up of two parts:

  • the runtime shims and annotations live in /google/cloud/aio/_cross_sync
  • the code generation logic lives in /.cross_sync/ in the repo root