Asynchronous ORM

I. Async Method Syntax Styles

A quick summary of syntax styles mentioned so far:

A. Trailing _async suffix:

await objects.filter(...).order_by(...).first_async()

Pros (of async): Explicit. Method overriding (ex: for save_async) feels a bit more natural.
Cons (of separate method): Encourages documenting the sync/async method pair separately, which would bloat the docs.

Pros (of trailing form): The await (at the beginning) and the async (at the end) conceptually are in a symmetic formation, which is easy to see and remember: “If you start with ‘await’ then you need to end with ‘async’.”

B1. Trailing a namespace: (new)

await objects.filter(...).order_by(...).first.a()

Pros (of a): Succinct.

B2. Leading a namespace:

await objects.filter(...).order_by(...).a.first()

Pros (of leading form): Meshes better with at least one syntax for async field access (i.e. await model.a.field). However I could see other field access syntaxes.

II. Async Field Access Syntax Styles

A. Trailing _async suffix: (new)

await choice.question_async

B1. Trailing a namespace: (new) - :no_entry_sign: Not implementable

await choice.question.a

B2. Leading a namespace:

await choice.a.question

C. Leading a lookup method: (new)

await choice.a('question')
# or
await choice.a['question']

:-1: I don’t like the extra quotes and parens which are combersome to type for a common operation.

III. Thoughts

  • I’m leaning toward the trailing forms.
  • I’m feeling a bit better about using _async as a general suffix.
    • The biggest caveat I see is possibly doubling the number of functions in the documentation. But then again, Sphinx has enough control that you can just document foo and foo_async as two method names with the same description. (The documentation for the typing module’s fields {IO, TextIO, BytesIO} shows that this pattern is possible.)
    • And of course I’m also a bit worried that _async is a lot of extra letters to type.

Comments?