Skip to content

Commit 708ee19

Browse files
committed
Option attente stabilité
1 parent 81365e4 commit 708ee19

File tree

3 files changed

+82
-11
lines changed

3 files changed

+82
-11
lines changed

constellationPy/client.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
from .const import LIEN_SIGNALEMENT_ERREURS
1414
from .serveur import obtenir_contexte
15-
from .utils import à_chameau, à_kebab, fais_rien_asynchrone, une_fois, tableau_exporté_à_pandas
15+
from .utils import à_chameau, à_kebab, fais_rien_asynchrone, une_fois, tableau_exporté_à_pandas, attendre_stabilité
1616

1717

1818
# Idée de https://stackoverflow.com/questions/48282841/in-trio-how-can-i-have-a-background-task-that-lives-as-long-as-my-object-does
@@ -278,11 +278,12 @@ async def obt_données_tableau(
278278
id_tableau: str,
279279
langues: Optional[str | list[str]] = None,
280280
formatDonnées="constellation",
281+
patience: int | float=1
281282
):
282283
async def f_suivi(f):
283284
return await soimême.tableaux.suivre_données_exportation(id_tableau=id_tableau, f=f, langues=langues)
284285

285-
données = await une_fois(f_suivi, soimême.pouponnière)
286+
données = await une_fois(f_suivi, soimême.pouponnière, attendre_stabilité(patience))
286287

287288
if formatDonnées.lower() == "pandas":
288289
return tableau_exporté_à_pandas(données)
@@ -294,6 +295,7 @@ async def f_suivi(f):
294295
async def obt_données_tableau_nuée(
295296
soimême, id_nuée: str, clef_tableau: str, n_résultats_désirés: int,
296297
langues: Optional[str | list[str]] = None, formatDonnées="constellation",
298+
patience: int | float=1
297299
):
298300
async def f_suivi(f):
299301
return await soimême.nuées.suivre_données_exportation_tableau(
@@ -302,7 +304,7 @@ async def f_suivi(f):
302304
n_résultats_désirés=n_résultats_désirés, f=f
303305
)
304306

305-
données = await une_fois(f_suivi, soimême.pouponnière)
307+
données = await une_fois(f_suivi, soimême.pouponnière, attendre_stabilité(patience))
306308

307309
if formatDonnées.lower() == "pandas":
308310
return tableau_exporté_à_pandas(données)

constellationPy/utils.py

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
from __future__ import annotations
22

33
import inspect
4-
from typing import Any, TypedDict, Callable, Coroutine
4+
import json
5+
from typing import Any, TypedDict, Callable, Coroutine, Awaitable, Optional
56
from typing import TYPE_CHECKING
67

78
import pandas as pd
@@ -34,11 +35,15 @@ async def fais_rien_asynchrone() -> None:
3435

3536
async def une_fois_sans_oublier(
3637
f_suivre: Callable[[Callable[[Any, str], None]], Coroutine],
37-
pouponnière: trio.Nursery
38+
pouponnière: trio.Nursery,
39+
fCond: Optional[Callable[[Any], Awaitable[bool]]] = None,
3840
) -> Any:
3941
canal_envoie, canal_réception = trio.open_memory_channel(0)
4042

4143
async def f_réception(résultat):
44+
if fCond and not await fCond(résultat):
45+
return
46+
4247
async with canal_envoie:
4348
try:
4449
await canal_envoie.send(résultat)
@@ -60,7 +65,8 @@ async def f_réception(résultat):
6065

6166
async def une_fois(
6267
f_suivi: Callable[[Callable[[Any], None]], Coroutine[None, None]],
63-
pouponnière: trio.Nursery
68+
pouponnière: trio.Nursery,
69+
fCond: Optional[Callable[[Any], Awaitable[bool]]] = None,
6470
) -> Any:
6571
async def f_async(f, task_status=trio.TASK_STATUS_IGNORED):
6672
with trio.CancelScope() as _context:
@@ -72,19 +78,35 @@ async def annuler():
7278

7379
task_status.started(annuler)
7480

75-
return await une_fois_sans_oublier(f_async, pouponnière)
81+
return await une_fois_sans_oublier(f_async, pouponnière, fCond)
82+
83+
def attendre_stabilité(n: int | float) -> Callable[[Any], Awaitable[bool]]:
84+
85+
précédente = {}
86+
async def stable(val: Any):
87+
chaîne_val = json.dumps(val)
88+
if "val" in précédente and chaîne_val == précédente["val"]:
89+
return False
7690

91+
précédente["val"] = chaîne_val
92+
await trio.sleep(n)
93+
return précédente["val"] == chaîne_val
94+
95+
return stable
7796

7897
type_élément = TypedDict("type_élément", {"empreinte": str, "données": dict[str, Any]})
7998
type_tableau = list[type_élément]
80-
type_tableau_exporté = TypedDict("type_tableau_exporté", {"données": list[dict[str, Any]], "fichiersSFIP": set, "nomTableau": str})
99+
type_tableau_exporté = TypedDict("type_tableau_exporté",
100+
{"données": list[dict[str, Any]], "fichiersSFIP": set, "nomTableau": str})
101+
81102

82103
def tableau_exporté_à_pandas(tableau: type_tableau_exporté):
83104
données = tableau["données"]
84105

85106
données_pandas = pd.DataFrame(données)
86107
return données_pandas
87108

109+
88110
def tableau_à_pandas(tableau: type_tableau, index_empreinte=False) -> pd.DataFrame:
89111
index = [x["empreinte"] for x in tableau] if index_empreinte else None
90112
données = [x["données"] for x in tableau]

tests/test_utils.py

Lines changed: 50 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import trio
66

77
from constellationPy.utils import à_chameau, à_kebab, une_fois_sans_oublier, tableau_à_pandas, pandas_à_constellation, \
8-
une_fois
8+
une_fois, attendre_stabilité
99

1010

1111
class TestUtils(TestCase):
@@ -17,7 +17,7 @@ def test_à_kebab(soimême):
1717
kebab = à_kebab("suivreDonnéesTableau")
1818
soimême.assertEqual(kebab, "suivre_données_tableau")
1919

20-
async def test_une_fois(soimême):
20+
async def test_une_fois_sans_oublier(soimême):
2121
async with trio.open_nursery() as pouponnière:
2222
async def f_async(f, task_status=trio.TASK_STATUS_IGNORED):
2323
with trio.CancelScope() as _context:
@@ -28,7 +28,21 @@ async def f_async(f, task_status=trio.TASK_STATUS_IGNORED):
2828
x = await une_fois_sans_oublier(f_async, pouponnière)
2929
soimême.assertEqual(x, 1)
3030

31-
async def test_une_fois_avec_oublier(soimême):
31+
async def test_une_fois_sans_oublier_avec_condition(soimême):
32+
async with trio.open_nursery() as pouponnière:
33+
async def f_async(f, task_status=trio.TASK_STATUS_IGNORED):
34+
with trio.CancelScope() as _context:
35+
task_status.started(_context.cancel)
36+
await f(1)
37+
await f(2)
38+
39+
async def condition(val):
40+
return val > 1
41+
42+
x = await une_fois_sans_oublier(f_async, pouponnière, condition)
43+
soimême.assertEqual(x, 2)
44+
45+
async def test_une_fois(soimême):
3246
oubl = {"ié": False}
3347
async with trio.open_nursery() as pouponnière:
3448
async def f_suivi(f):
@@ -43,6 +57,39 @@ async def f_oublier():
4357
soimême.assertEqual(x, 123)
4458
soimême.assertTrue(oubl["ié"])
4559

60+
async def test_une_fois_avec_condition(soimême):
61+
oubl = {"ié": False}
62+
async with trio.open_nursery() as pouponnière:
63+
async def f_suivi(f):
64+
async def f_oublier():
65+
oubl["ié"] = True
66+
67+
pouponnière.start_soon(f, 123)
68+
pouponnière.start_soon(f, 456)
69+
return f_oublier
70+
71+
async def condition(val):
72+
return val > 150
73+
74+
x = await une_fois(f_suivi, pouponnière=pouponnière, fCond=condition)
75+
76+
soimême.assertEqual(x, 456)
77+
soimême.assertTrue(oubl["ié"])
78+
79+
async def test_attendre_stabilité(soimême):
80+
vals = {}
81+
attendre_stable = attendre_stabilité(0.1)
82+
async def f(x: str):
83+
vals[x] = await attendre_stable(x)
84+
85+
async with trio.open_nursery() as pouponnière:
86+
pouponnière.start_soon(f, "a")
87+
await trio.sleep(0.05)
88+
pouponnière.start_soon(f, "b")
89+
90+
soimême.assertFalse(vals["a"])
91+
soimême.assertTrue(vals["b"])
92+
4693
def test_tableau_à_pandas(soimême):
4794
tableau = [{"empreinte": "abc", "données": {"a": 1, "b": 2}}, {"empreinte": "def", "données": {"a": 3}}]
4895
données_pandas = tableau_à_pandas(tableau)

0 commit comments

Comments
 (0)