Skip to content

Commit 08d0f9d

Browse files
committed
tests(QueryList): Add doctests (ported from libvcs implementation)
1 parent d117417 commit 08d0f9d

File tree

1 file changed

+177
-13
lines changed

1 file changed

+177
-13
lines changed

src/libtmux/_internal/query_list.py

Lines changed: 177 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,55 @@ def keygetter(
4040
obj: "Mapping[str, t.Any]",
4141
path: str,
4242
) -> t.Union[None, t.Any, str, t.List[str], "Mapping[str, str]"]:
43-
"""obj, "foods__breakfast", obj['foods']['breakfast'].
43+
"""Fetch values in objects and keys, supported nested data.
4444
45-
>>> keygetter({ "foods": { "breakfast": "cereal" } }, "foods__breakfast")
46-
'cereal'
47-
>>> keygetter({ "foods": { "breakfast": "cereal" } }, "foods")
45+
**With dictionaries**:
46+
47+
>>> keygetter({ "food": { "breakfast": "cereal" } }, "food")
4848
{'breakfast': 'cereal'}
4949
50+
>>> keygetter({ "food": { "breakfast": "cereal" } }, "food__breakfast")
51+
'cereal'
52+
53+
**With objects**:
54+
55+
>>> from typing import Optional
56+
>>> from dataclasses import dataclass, field
57+
58+
>>> @dataclass()
59+
... class Food:
60+
... fruit: list[str] = field(default_factory=list)
61+
... breakfast: Optional[str] = None
62+
63+
64+
>>> @dataclass()
65+
... class Restaurant:
66+
... place: str
67+
... city: str
68+
... state: str
69+
... food: Food = field(default_factory=Food)
70+
71+
72+
>>> restaurant = Restaurant(
73+
... place="Largo",
74+
... city="Tampa",
75+
... state="Florida",
76+
... food=Food(
77+
... fruit=["banana", "orange"], breakfast="cereal"
78+
... )
79+
... )
80+
81+
>>> restaurant
82+
Restaurant(place='Largo',
83+
city='Tampa',
84+
state='Florida',
85+
food=Food(fruit=['banana', 'orange'], breakfast='cereal'))
86+
87+
>>> keygetter(restaurant, "food")
88+
Food(fruit=['banana', 'orange'], breakfast='cereal')
89+
90+
>>> keygetter(restaurant, "food__breakfast")
91+
'cereal'
5092
"""
5193
try:
5294
sub_fields = path.split("__")
@@ -74,10 +116,24 @@ def parse_lookup(
74116
75117
If comparator not used or value not found, return None.
76118
77-
mykey__endswith("mykey") -> "mykey" else None
78-
79119
>>> parse_lookup({ "food": "red apple" }, "food__istartswith", "__istartswith")
80120
'red apple'
121+
122+
It can also look up objects:
123+
124+
>>> from dataclasses import dataclass
125+
126+
>>> @dataclass()
127+
... class Inventory:
128+
... food: str
129+
130+
>>> item = Inventory(food="red apple")
131+
132+
>>> item
133+
Inventory(food='red apple')
134+
135+
>>> parse_lookup(item, "food__istartswith", "__istartswith")
136+
'red apple'
81137
"""
82138
try:
83139
if isinstance(path, str) and isinstance(lookup, str) and path.endswith(lookup):
@@ -264,6 +320,8 @@ class QueryList(t.Generic[T], t.List[T]):
264320
265321
*Experimental, unstable*.
266322
323+
**With dictionaries**:
324+
267325
>>> query = QueryList(
268326
... [
269327
... {
@@ -280,6 +338,7 @@ class QueryList(t.Generic[T], t.List[T]):
280338
... },
281339
... ]
282340
... )
341+
283342
>>> query.filter(place="Chicago suburbs")[0]['city']
284343
'Elmhurst'
285344
>>> query.filter(place__icontains="chicago")[0]['city']
@@ -290,8 +349,119 @@ class QueryList(t.Generic[T], t.List[T]):
290349
'Elmhurst'
291350
>>> query.filter(foods__fruit__in="orange")[0]['city']
292351
'Tampa'
293-
>>> query.get(foods__fruit__in="orange")['city']
352+
353+
>>> query.filter(foods__fruit__in="apple")
354+
[{'place': 'Chicago suburbs',
355+
'city': 'Elmhurst',
356+
'state': 'Illinois',
357+
'foods':
358+
{'fruit': ['apple', 'cantelope'], 'breakfast': 'waffles'}}]
359+
360+
>>> query.filter(foods__fruit__in="non_existent")
361+
[]
362+
363+
**With objects**:
364+
365+
>>> from typing import Any, Dict
366+
>>> from dataclasses import dataclass, field
367+
368+
>>> @dataclass()
369+
... class Restaurant:
370+
... place: str
371+
... city: str
372+
... state: str
373+
... foods: Dict[str, Any]
374+
375+
>>> restaurant = Restaurant(
376+
... place="Largo",
377+
... city="Tampa",
378+
... state="Florida",
379+
... foods={
380+
... "fruit": ["banana", "orange"], "breakfast": "cereal"
381+
... }
382+
... )
383+
384+
>>> restaurant
385+
Restaurant(place='Largo',
386+
city='Tampa',
387+
state='Florida',
388+
foods={'fruit': ['banana', 'orange'], 'breakfast': 'cereal'})
389+
390+
>>> query = QueryList([restaurant])
391+
392+
>>> query.filter(foods__fruit__in="banana")
393+
[Restaurant(place='Largo',
394+
city='Tampa',
395+
state='Florida',
396+
foods={'fruit': ['banana', 'orange'], 'breakfast': 'cereal'})]
397+
398+
>>> query.filter(foods__fruit__in="banana")[0].city
399+
'Tampa'
400+
401+
>>> query.get(foods__fruit__in="banana").city
402+
'Tampa'
403+
404+
**With objects (nested)**:
405+
406+
>>> from typing import List, Optional
407+
>>> from dataclasses import dataclass, field
408+
409+
>>> @dataclass()
410+
... class Food:
411+
... fruit: List[str] = field(default_factory=list)
412+
... breakfast: Optional[str] = None
413+
414+
415+
>>> @dataclass()
416+
... class Restaurant:
417+
... place: str
418+
... city: str
419+
... state: str
420+
... food: Food = field(default_factory=Food)
421+
422+
423+
>>> query = QueryList([
424+
... Restaurant(
425+
... place="Largo",
426+
... city="Tampa",
427+
... state="Florida",
428+
... food=Food(
429+
... fruit=["banana", "orange"], breakfast="cereal"
430+
... )
431+
... ),
432+
... Restaurant(
433+
... place="Chicago suburbs",
434+
... city="Elmhurst",
435+
... state="Illinois",
436+
... food=Food(
437+
... fruit=["apple", "cantelope"], breakfast="waffles"
438+
... )
439+
... )
440+
... ])
441+
442+
>>> query.filter(food__fruit__in="banana")
443+
[Restaurant(place='Largo',
444+
city='Tampa',
445+
state='Florida',
446+
food=Food(fruit=['banana', 'orange'], breakfast='cereal'))]
447+
448+
>>> query.filter(food__fruit__in="banana")[0].city
449+
'Tampa'
450+
451+
>>> query.get(food__fruit__in="banana").city
294452
'Tampa'
453+
454+
>>> query.filter(food__breakfast="waffles")
455+
[Restaurant(place='Chicago suburbs',
456+
city='Elmhurst',
457+
state='Illinois',
458+
food=Food(fruit=['apple', 'cantelope'], breakfast='waffles'))]
459+
460+
>>> query.filter(food__breakfast="waffles")[0].city
461+
'Elmhurst'
462+
463+
>>> query.filter(food__breakfast="non_existent")
464+
[]
295465
"""
296466

297467
data: "Sequence[T]"
@@ -308,12 +478,6 @@ def items(self) -> t.List[t.Tuple[str, T]]:
308478
def __eq__(
309479
self,
310480
other: object,
311-
# other: t.Union[
312-
# "QueryList[T]",
313-
# t.List[Mapping[str, str]],
314-
# t.List[Mapping[str, int]],
315-
# t.List[Mapping[str, t.Union[str, Mapping[str, t.Union[List[str], str]]]]],
316-
# ],
317481
) -> bool:
318482
data = other
319483

0 commit comments

Comments
 (0)