File: async.md

package info (click to toggle)
python-jsonpath 2.0.2-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,028 kB
  • sloc: python: 9,473; makefile: 6
file content (61 lines) | stat: -rw-r--r-- 2,388 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# Async API

Largely motivated by its integration with [Python Liquid](https://jg-rp.github.io/liquid/jsonpath/introduction), Python JSONPath offers an asynchronous API that allows for items in a target data structure to be "fetched" lazily.

[`findall_async()`](api.md#jsonpath.JSONPathEnvironment.findall_async) and [`finditer_async()`](api.md#jsonpath.JSONPathEnvironment.finditer_async) are [asyncio](https://docs.python.org/3/library/asyncio.html) equivalents to [`findall()`](api.md#jsonpath.JSONPathEnvironment.findall) and [`finditer()`](api.md#jsonpath.JSONPathEnvironment.finditer). By default, any class implementing the [mapping](https://docs.python.org/3/library/collections.abc.html#collections.abc.Mapping) or [sequence](https://docs.python.org/3/library/collections.abc.html#collections.abc.Sequence) interfaces, and a `__getitem_async__()` method, will have `__getitem_async__()` awaited instead of calling `__getitem__()` when resolving mapping keys or sequence indices.

## Example

In this example, showing a lazy-loading collections of `Player` objects, only the "A" team's players are fetched from the database, and only when they are first accessed.

```python
from collections import abc
from dataclasses import dataclass
from typing import Dict
from typing import Iterator
from typing import List

import jsonpath


@dataclass
class Player:
    name: str
    pid: int
    rank: int


class LazyPlayers(abc.Mapping[str, Player]):
    def __init__(self, names: List[str]):
        self.names = names
        self.cached_players: Dict[str, Player] = {}

    def __len__(self) -> int:
        return len(self.names)

    def __iter__(self) -> Iterator[str]:
        return iter(self.names)

    def __getitem__(self, k: str) -> Player:
        if self.cached_players is None:
            # Blocking IO here
            self.cached_players = get_stuff_from_database()
        return self.cached_players[k]

    async def __getitem_async__(self, k: str) -> Player:
        if self.cached_players is None:
            # Do async IO here.
            self.cached_players = await get_stuff_from_database_async()
        return self.cached_players[k]


data = {
    "teams": {
        "A Team": LazyPlayers(["Sue", "Bob"]),
        "B Team": LazyPlayers(["Sally", "Frank"]),
    }
}

best_a_team_players = jsonpath.findall_async("$.teams['A Team'][?rank >= 8]", data)

```