From 54c72bcaa0aa1ce9683d8154e2263a3aca477f5e Mon Sep 17 00:00:00 2001 From: Roland Salardon Date: Tue, 4 Aug 2026 02:30:20 +0200 Subject: [PATCH 01/11] chore: session summary [skip ci] Signed-off-by: Roland Salardon --- SESSION.md | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 SESSION.md diff --git a/SESSION.md b/SESSION.md new file mode 100644 index 00000000..91a39e02 --- /dev/null +++ b/SESSION.md @@ -0,0 +1,25 @@ +## PROJET Gw2Analytics — Résumé de session (2026-08-04) + +### Objectif +Parité totale du parser avec Elite Insights (EI) v3.26.0.0 sur les logs WvW (0 diff). + +### État du travail +- **En cours :** investigation du surcomptage regen sur "Non Squad Player 50" (`20260125-001308`, instanceID 3089, account "Non Squad Player 50", agent 38309). +- Constat probe : notre tracker compte regen actif jusqu'à rel≈50320 (55.845 %) alors que EI l'arrête à rel=40940 (44.757 %). Dernier événement regen à rel=21118. +- **Cause probable identifiée** : les événements `remove_manual` (7 présents sur cet agent) ne sont PAS pris en charge dans `BuffStateTracker.process()` — seuls `apply`, `remove_single`, `remove_all` sont gérés. Les `remove_manual` sont donc ignorés et les stacks ne sont pas retirés → surcomptage. +- EI states : `[[0,0],[2905,1],[40940,0]]`. Règle d'uptime EI : uptime calculé sur événements/états, pas sur présence cumulée simple. + +### Next Move +1. Ajouter la gestion de `kind == "remove_manual"` (et vérifier `remove_all`) dans `buff_state.py` — traiter comme un remove de la stack correspondante (par durée/stack_id), façon EI. +2. Ré-échantillonner : `uv run python scripts/ei-parity/ei_diff.py 20260125-001308 --show "buffUptimes"` et comparer inst 3089. +3. Vérifier que les "Non Squad Player" 50/58 passent de 52.2/51.895 → 44.757/43.852. + +### Fichiers clés +- `libs/gw2_analytics/src/gw2_analytics/buff_state.py` — ligne ~337 (`remove_single`), ~372 (`remove_all`), ~295 (`apply`) ; **manque `remove_manual`**. +- `libs/gw2_analytics/src/gw2_analytics/ei_compare.py` +- `scripts/ei-parity/ei_diff.py`, `.tooling/ei-out/_detailed_wvw_kill.json` +- Probes `/tmp/probe_ev.py`, `/tmp/probe_tr.py` + +### Probes +- `/tmp/probe_ev.py ` : dumps événements regen ciblant un agent. +- `/tmp/probe_tr.py ` : trace le tracker stack par événement (before/after expirations). \ No newline at end of file From 6f20eed17124f3d49812030e7efe503c18ad4f83 Mon Sep 17 00:00:00 2001 From: Roland Salardon Date: Tue, 4 Aug 2026 09:00:27 +0200 Subject: [PATCH 02/11] chore: autopush WIP [skip ci] Signed-off-by: Roland Salardon --- _dump_tmp.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 _dump_tmp.py diff --git a/_dump_tmp.py b/_dump_tmp.py new file mode 100644 index 00000000..85695539 --- /dev/null +++ b/_dump_tmp.py @@ -0,0 +1,18 @@ +import json, sys +from gw2_evtc_parser import read_zevtc_archive, PythonEvtcParser + +stem = sys.argv[1]; inst = int(sys.argv[2]) +raw = read_zevtc_archive(f"zevtc files/{stem}.zevtc") +p = PythonEvtcParser() +fight = next(p.parse(raw)) +events = list(p.parse_events(raw)) +origin = min(e.time_ms for e in events) +d = json.load(open(f".tooling/ei-out/{stem}_detailed_wvw_kill.json")) +aid = [a for a in fight.agents if a.instance_id == inst][0].id + +evs = sorted([e for e in events + if getattr(e,"skill_id",None)==718 and getattr(e,"target_agent_id",None)==aid + and type(e).__name__=="BoonApplyEvent"], key=lambda e:e.time_ms) +print(f"=== inst {inst} {len(evs)} regen events ===") +for e in evs: + print(f"{e.time_ms-origin:6d} {e.kind:13s} src={e.source_agent_id:5d} dur={e.duration_ms} stk={e.stack_id}") \ No newline at end of file From b05b0e7eb04b380a8178e07ca85b00b6696a6152 Mon Sep 17 00:00:00 2001 From: Roland Salardon Date: Tue, 4 Aug 2026 09:30:29 +0200 Subject: [PATCH 03/11] chore: autopush WIP [skip ci] Signed-off-by: Roland Salardon --- _dbg_tmp.py | 60 ++++++++++++++++++++++++++++++++++++ _port_tmp.py | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++++ _v2_tmp.py | 80 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 227 insertions(+) create mode 100644 _dbg_tmp.py create mode 100644 _port_tmp.py create mode 100644 _v2_tmp.py diff --git a/_dbg_tmp.py b/_dbg_tmp.py new file mode 100644 index 00000000..96e91d94 --- /dev/null +++ b/_dbg_tmp.py @@ -0,0 +1,60 @@ +import json +from gw2_evtc_parser import read_zevtc_archive, PythonEvtcParser + +stem="20260125-001308"; inst=3089 +raw = read_zevtc_archive(f"zevtc files/{stem}.zevtc") +p = PythonEvtcParser() +fight = next(p.parse(raw)) +events = list(p.parse_events(raw)) +origin = min(e.time_ms for e in events) +aid = [a for a in fight.agents if a.instance_id == inst][0].id +evs = sorted([e for e in events + if getattr(e,"skill_id",None)==718 and getattr(e,"target_agent_id",None)==aid + and type(e).__name__=="BoonApplyEvent"], key=lambda e:e.time_ms) +mapped=[] +for e in evs: + mapped.append((e.time_ms-origin, e.kind, e.source_agent_id, e.duration_ms, e.stack_id)) +print("events:") +for m in mapped: print(" ", m) + +class SI: + __slots__=("start","dur","src","sid") + def __init__(s,start,dur,src,sid): s.start=start;s.dur=dur;s.src=src;s.sid=sid + def shift(s,ss,ds): + s.start+=ss; s.dur-=ds + +def sim(heal): + q=[]; waste=[]; gen=[]; prev=mapped[0][0] + def sort_q(): q.sort(key=lambda x:-heal.get(x.src,0)) + def upd(tp): + if not q or tp<=0: return + a=q[0]; diff=tp; lo=0 + if a.dur1 else {srcs[0]:1000} + bar,pg,pw=simulate(mapped,dur,heal) + print(f" heal={heal} bar={round(bar/dur*100,3)} (EI {exp}) gen={pg} pw={pw}") + for pl in d['players']: + if pl.get('instanceID')==inst: + for bu in pl.get('buffUptimes',[]): + if bu.get('id')==718: + print(" EI uptime:",round(bu['buffData'][0]['uptime'],3)) + print(" EI wasted:",bu['buffData'][0]['wasted']) + print(" EI states:",bu['states']) +main() \ No newline at end of file diff --git a/_v2_tmp.py b/_v2_tmp.py new file mode 100644 index 00000000..3b876742 --- /dev/null +++ b/_v2_tmp.py @@ -0,0 +1,80 @@ +import json, itertools +from gw2_evtc_parser import read_zevtc_archive, PythonEvtcParser + +def read_events(stem, inst): + raw = read_zevtc_archive(f"zevtc files/{stem}.zevtc") + p = PythonEvtcParser() + fight = next(p.parse(raw)) + events = list(p.parse_events(raw)) + origin = min(e.time_ms for e in events) + aid = [a for a in fight.agents if a.instance_id == inst][0].id + evs = sorted([e for e in events if getattr(e,"skill_id",None)==718 and getattr(e,"target_agent_id",None)==aid and type(e).__name__=="BoonApplyEvent"], key=lambda e:e.time_ms) + return origin, evs + +class SI: + __slots__=("start","dur","src","sid","ext") + def __init__(s,start,dur,src,sid): s.start=start;s.dur=dur;s.src=src;s.sid=sid;s.ext=[] + @property + def total(s): return s.dur+sum(v for _,v in s.ext) + def shift(s,ss,ds): + s.start+=ss; s.dur-=ds + if s.dur==0 and s.ext: s.src,s.dur=s.ext[0]; s.ext.pop(0) + def extend(s,v,src): s.ext.append((src,v)) + +def simulate(mapped, duration, heal): + q=[]; waste=[]; gen=[]; no_sort=False; prev=mapped[0][0] + def sort_q(): + if no_sort: return + q.sort(key=lambda x:-heal.get(x.src,0)) + def activate(it): + nonlocal no_sort + no_sort=True + q.remove(it) + if q and q[0].total<50: q[0]=it + else: q.insert(0,it) + def upd(tp): + if not q or tp<=0: return + a=q[0]; diff=tp; lo=0 + if a.dur Date: Tue, 4 Aug 2026 09:40:30 +0200 Subject: [PATCH 04/11] chore: autopush WIP [skip ci] Signed-off-by: Roland Salardon --- _v3_tmp.py | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 _v3_tmp.py diff --git a/_v3_tmp.py b/_v3_tmp.py new file mode 100644 index 00000000..6d42aca5 --- /dev/null +++ b/_v3_tmp.py @@ -0,0 +1,82 @@ +import json +from collections import defaultdict +from gw2_evtc_parser import read_zevtc_archive, PythonEvtcParser +from gw2_evtc_parser.parser import _compute_post_skills_offset, _EVENT_STRUCT_EVENTS_2025 as S + +stem="20260125-001308" +raw = read_zevtc_archive(f"zevtc files/{stem}.zevtc") +off = _compute_post_skills_offset(raw, is_evtc_2025=True) +p = PythonEvtcParser() +fight = next(p.parse(raw)) +aid = {a.instance_id:a.id for a in fight.agents} +events = list(p.parse_events(raw)) +origin = min(e.time_ms for e in events) + +def get_inst(inst): + taid = next(a for a in fight.agents if a.instance_id==inst).id + out=[] + for c in range(off,len(raw)-64+1,64): + t=S.unpack_from(raw,c) + if t[6]==718 and t[2]==taid: + out.append((t[0]-origin, t[3], t[1], t[19], bool(t[17]), t[15])) + return sorted(out) + +class SI: + __slots__=("start","dur","src","sid","ext") + def __init__(s,start,dur,src,sid): s.start=start;s.dur=dur;s.src=src;s.sid=sid;s.ext=[] + @property + def total(s): return s.dur+sum(v for _,v in s.ext) + def shift(s,ss,ds): + s.start+=ss; s.dur-=ds + if s.dur==0 and s.ext: s.src,s.dur=s.ext[0]; s.ext.pop(0) + +def simulate(mapped, duration, heal): + q=[]; waste=[]; gen=[]; no_sort=False; prev=mapped[0][0] + def sort_q(): + if not no_sort: q.sort(key=lambda x:-heal.get(x.src,0)) + def activate(it): + nonlocal no_sort + no_sort=True + q.remove(it) + if q and q[0].total<50: q[0]=it + else: q.insert(0,it) + def upd(tp): + if not q or tp<=0: return + a=q[0]; diff=tp; lo=0 + if a.dur Date: Tue, 4 Aug 2026 09:50:32 +0200 Subject: [PATCH 05/11] chore: autopush WIP [skip ci] Signed-off-by: Roland Salardon --- libs/gw2_core/src/gw2_core/models.py | 11 +++++++++++ libs/gw2_evtc_parser/src/gw2_evtc_parser/parser.py | 1 + 2 files changed, 12 insertions(+) diff --git a/libs/gw2_core/src/gw2_core/models.py b/libs/gw2_core/src/gw2_core/models.py index 690fb870..9ff39e20 100644 --- a/libs/gw2_core/src/gw2_core/models.py +++ b/libs/gw2_core/src/gw2_core/models.py @@ -528,6 +528,17 @@ class because the wire shape (time_ms + source/target agent id + ) stacks: int = Field(..., ge=0, description="Magnitude of the state change.") stack_id: int = Field(default=0, ge=0, le=0xFFFFFFFF) + added_active: bool = Field( + default=False, + description=( + "arcdps 2025+ ``is_shields`` byte of the raw buff-apply record: " + "1 marks the apply as the currently-active stack. Elite Insights " + "uses this to activate the newly added stack (move to front + " + "``noSort``), which is required for Regeneration parity. Only the " + "arcdps 2025+ wire carries this byte; legacy records default to " + "False." + ), + ) kind: Literal["apply", "remove_single", "remove_all", "remove_manual"] = Field( default="apply", description=( diff --git a/libs/gw2_evtc_parser/src/gw2_evtc_parser/parser.py b/libs/gw2_evtc_parser/src/gw2_evtc_parser/parser.py index be4c80b9..a3149d49 100644 --- a/libs/gw2_evtc_parser/src/gw2_evtc_parser/parser.py +++ b/libs/gw2_evtc_parser/src/gw2_evtc_parser/parser.py @@ -1165,6 +1165,7 @@ def parse_events(source: BinaryIO | bytes) -> Iterator[Event]: # noqa: PLR0912, stacks=1, stack_id=pad, kind="apply", + added_active=bool(is_shields), ) continue # v0.17.0: a self-inflicted condition tick (src == dst, From 7da1adef8748b90cb4b2a6e7980f7a797c82d072 Mon Sep 17 00:00:00 2001 From: Roland Salardon Date: Tue, 4 Aug 2026 09:53:51 +0200 Subject: [PATCH 06/11] chore: autopush WIP [skip ci] Signed-off-by: Roland Salardon --- .../src/gw2_analytics/buff_state.py | 74 +++++++++++++------ 1 file changed, 53 insertions(+), 21 deletions(-) diff --git a/libs/gw2_analytics/src/gw2_analytics/buff_state.py b/libs/gw2_analytics/src/gw2_analytics/buff_state.py index 5f5d3882..933cb628 100644 --- a/libs/gw2_analytics/src/gw2_analytics/buff_state.py +++ b/libs/gw2_analytics/src/gw2_analytics/buff_state.py @@ -312,28 +312,60 @@ def process( # noqa: PLR0912, PLR0915 target_tracker.stack_ids = [stack_id for _, stack_id, _ in pairs] target_tracker.healing_scores = [healing for _, _, healing in pairs] else: - target_tracker.expirations.append(event.duration_ms or None) - target_tracker.stack_ids.append(event.stack_id) - target_tracker.healing_scores.append( - self._healing_by_agent.get(event.source_agent_id, 0) - ) - if buff_name == "regeneration" and not target_tracker.no_sort: - pairs = sorted( - zip( - target_tracker.expirations, - target_tracker.stack_ids, - target_tracker.healing_scores, - strict=True, - ), - key=lambda pair: pair[2], - reverse=True, + if buff_name == "regeneration": + # EI BuffSimulatorDuration + HealingLogic: capacity-5 + # queue, replace the lowest-heal stack on overflow + # (wasting its remaining duration), re-sort by healing + # until the first added_active apply pins no_sort, then + # activate: move the new stack to the front (or replace + # the active stack outright when it has <50 ms left). + new_duration = event.duration_ms or None + new_healing = self._healing_by_agent.get(event.source_agent_id, 0) + if len(target_tracker.expirations) >= _capacity_for(buff_name): + target_tracker.expirations[-1] = new_duration + target_tracker.stack_ids[-1] = event.stack_id + target_tracker.healing_scores[-1] = new_healing + else: + target_tracker.expirations.append(new_duration) + target_tracker.stack_ids.append(event.stack_id) + target_tracker.healing_scores.append(new_healing) + if not target_tracker.no_sort: + pairs = sorted( + zip( + target_tracker.expirations, + target_tracker.stack_ids, + target_tracker.healing_scores, + strict=True, + ), + key=lambda pair: pair[2], + reverse=True, + ) + target_tracker.expirations = [expiry for expiry, _, _ in pairs] + target_tracker.stack_ids = [stack_id for _, stack_id, _ in pairs] + target_tracker.healing_scores = [healing for _, _, healing in pairs] + if event.added_active: + target_tracker.no_sort = True + new_index = target_tracker.stack_ids.index(event.stack_id) + expiry = target_tracker.expirations.pop(new_index) + stack_id = target_tracker.stack_ids.pop(new_index) + healing = target_tracker.healing_scores.pop(new_index) + if target_tracker.expirations and (target_tracker.expirations[0] or 0) < 50: + target_tracker.expirations[0] = expiry + target_tracker.stack_ids[0] = stack_id + target_tracker.healing_scores[0] = healing + else: + target_tracker.expirations.insert(0, expiry) + target_tracker.stack_ids.insert(0, stack_id) + target_tracker.healing_scores.insert(0, healing) + else: + target_tracker.expirations.append(event.duration_ms or None) + target_tracker.stack_ids.append(event.stack_id) + target_tracker.healing_scores.append( + self._healing_by_agent.get(event.source_agent_id, 0) ) - target_tracker.expirations = [expiry for expiry, _, _ in pairs] - target_tracker.stack_ids = [stack_id for _, stack_id, _ in pairs] - target_tracker.healing_scores = [healing for _, _, healing in pairs] - del target_tracker.expirations[_capacity_for(buff_name) :] - del target_tracker.stack_ids[_capacity_for(buff_name) :] - del target_tracker.healing_scores[_capacity_for(buff_name) :] + del target_tracker.expirations[_capacity_for(buff_name) :] + del target_tracker.stack_ids[_capacity_for(buff_name) :] + del target_tracker.healing_scores[_capacity_for(buff_name) :] elif event.kind == "remove_single": if _max_stacks_for(buff_name) == 1 and target_tracker.expirations: stack_index = next( From 7097d3b157fbf5f73d304cab703a0226eff76487 Mon Sep 17 00:00:00 2001 From: Roland Salardon Date: Tue, 4 Aug 2026 09:57:48 +0200 Subject: [PATCH 07/11] chore: remove temp probe scripts [skip ci] Signed-off-by: Roland Salardon --- _dump_tmp.py | 18 ----------- _port_tmp.py | 87 ---------------------------------------------------- _v2_tmp.py | 80 ----------------------------------------------- _v3_tmp.py | 82 ------------------------------------------------- 4 files changed, 267 deletions(-) delete mode 100644 _dump_tmp.py delete mode 100644 _port_tmp.py delete mode 100644 _v2_tmp.py delete mode 100644 _v3_tmp.py diff --git a/_dump_tmp.py b/_dump_tmp.py deleted file mode 100644 index 85695539..00000000 --- a/_dump_tmp.py +++ /dev/null @@ -1,18 +0,0 @@ -import json, sys -from gw2_evtc_parser import read_zevtc_archive, PythonEvtcParser - -stem = sys.argv[1]; inst = int(sys.argv[2]) -raw = read_zevtc_archive(f"zevtc files/{stem}.zevtc") -p = PythonEvtcParser() -fight = next(p.parse(raw)) -events = list(p.parse_events(raw)) -origin = min(e.time_ms for e in events) -d = json.load(open(f".tooling/ei-out/{stem}_detailed_wvw_kill.json")) -aid = [a for a in fight.agents if a.instance_id == inst][0].id - -evs = sorted([e for e in events - if getattr(e,"skill_id",None)==718 and getattr(e,"target_agent_id",None)==aid - and type(e).__name__=="BoonApplyEvent"], key=lambda e:e.time_ms) -print(f"=== inst {inst} {len(evs)} regen events ===") -for e in evs: - print(f"{e.time_ms-origin:6d} {e.kind:13s} src={e.source_agent_id:5d} dur={e.duration_ms} stk={e.stack_id}") \ No newline at end of file diff --git a/_port_tmp.py b/_port_tmp.py deleted file mode 100644 index 72a406ec..00000000 --- a/_port_tmp.py +++ /dev/null @@ -1,87 +0,0 @@ -import json, itertools -from gw2_evtc_parser import read_zevtc_archive, PythonEvtcParser - -def read_events(stem, inst): - raw = read_zevtc_archive(f"zevtc files/{stem}.zevtc") - p = PythonEvtcParser() - fight = next(p.parse(raw)) - events = list(p.parse_events(raw)) - origin = min(e.time_ms for e in events) - aid = [a for a in fight.agents if a.instance_id == inst][0].id - evs = sorted([e for e in events - if getattr(e,"skill_id",None)==718 and getattr(e,"target_agent_id",None)==aid - and type(e).__name__=="BoonApplyEvent"], key=lambda e:e.time_ms) - return origin, aid, evs - -class SI: - __slots__=("start","dur","src","sid","ext") - def __init__(s,start,dur,src,sid): s.start=start;s.dur=dur;s.src=src;s.sid=sid;s.ext=[] - @property - def total(s): return s.dur+sum(v for _,v in s.ext) - def shift(s,ss,ds): - s.start+=ss; s.dur-=ds - if s.dur==0 and s.ext: - s.src,s.dur=s.ext[0]; s.ext.pop(0) - -def simulate(mapped, duration, heal): - q=[]; waste=[]; gen=[]; no_sort=False; prev=mapped[0][0] - def sort_q(): - if no_sort: return - q.sort(key=lambda x:-heal.get(x.src,0)) - def activate(it): - nonlocal no_sort - no_sort=True - q.remove(it) - if q and q[0].total<50: q[0]=it - else: q.insert(0,it) - def upd(tp): - if not q or tp<=0: return - a=q[0]; diff=tp; lo=0 - if a.dur1 else {srcs[0]:1000} - bar,pg,pw=simulate(mapped,dur,heal) - print(f" heal={heal} bar={round(bar/dur*100,3)} (EI {exp}) gen={pg} pw={pw}") - for pl in d['players']: - if pl.get('instanceID')==inst: - for bu in pl.get('buffUptimes',[]): - if bu.get('id')==718: - print(" EI uptime:",round(bu['buffData'][0]['uptime'],3)) - print(" EI wasted:",bu['buffData'][0]['wasted']) - print(" EI states:",bu['states']) -main() \ No newline at end of file diff --git a/_v2_tmp.py b/_v2_tmp.py deleted file mode 100644 index 3b876742..00000000 --- a/_v2_tmp.py +++ /dev/null @@ -1,80 +0,0 @@ -import json, itertools -from gw2_evtc_parser import read_zevtc_archive, PythonEvtcParser - -def read_events(stem, inst): - raw = read_zevtc_archive(f"zevtc files/{stem}.zevtc") - p = PythonEvtcParser() - fight = next(p.parse(raw)) - events = list(p.parse_events(raw)) - origin = min(e.time_ms for e in events) - aid = [a for a in fight.agents if a.instance_id == inst][0].id - evs = sorted([e for e in events if getattr(e,"skill_id",None)==718 and getattr(e,"target_agent_id",None)==aid and type(e).__name__=="BoonApplyEvent"], key=lambda e:e.time_ms) - return origin, evs - -class SI: - __slots__=("start","dur","src","sid","ext") - def __init__(s,start,dur,src,sid): s.start=start;s.dur=dur;s.src=src;s.sid=sid;s.ext=[] - @property - def total(s): return s.dur+sum(v for _,v in s.ext) - def shift(s,ss,ds): - s.start+=ss; s.dur-=ds - if s.dur==0 and s.ext: s.src,s.dur=s.ext[0]; s.ext.pop(0) - def extend(s,v,src): s.ext.append((src,v)) - -def simulate(mapped, duration, heal): - q=[]; waste=[]; gen=[]; no_sort=False; prev=mapped[0][0] - def sort_q(): - if no_sort: return - q.sort(key=lambda x:-heal.get(x.src,0)) - def activate(it): - nonlocal no_sort - no_sort=True - q.remove(it) - if q and q[0].total<50: q[0]=it - else: q.insert(0,it) - def upd(tp): - if not q or tp<=0: return - a=q[0]; diff=tp; lo=0 - if a.dur Date: Tue, 4 Aug 2026 10:20:03 +0200 Subject: [PATCH 08/11] chore: remove leftover probe script _dbg_tmp.py [skip ci] Signed-off-by: Roland Salardon --- _dbg_tmp.py | 60 ----------------------------------------------------- 1 file changed, 60 deletions(-) delete mode 100644 _dbg_tmp.py diff --git a/_dbg_tmp.py b/_dbg_tmp.py deleted file mode 100644 index 96e91d94..00000000 --- a/_dbg_tmp.py +++ /dev/null @@ -1,60 +0,0 @@ -import json -from gw2_evtc_parser import read_zevtc_archive, PythonEvtcParser - -stem="20260125-001308"; inst=3089 -raw = read_zevtc_archive(f"zevtc files/{stem}.zevtc") -p = PythonEvtcParser() -fight = next(p.parse(raw)) -events = list(p.parse_events(raw)) -origin = min(e.time_ms for e in events) -aid = [a for a in fight.agents if a.instance_id == inst][0].id -evs = sorted([e for e in events - if getattr(e,"skill_id",None)==718 and getattr(e,"target_agent_id",None)==aid - and type(e).__name__=="BoonApplyEvent"], key=lambda e:e.time_ms) -mapped=[] -for e in evs: - mapped.append((e.time_ms-origin, e.kind, e.source_agent_id, e.duration_ms, e.stack_id)) -print("events:") -for m in mapped: print(" ", m) - -class SI: - __slots__=("start","dur","src","sid") - def __init__(s,start,dur,src,sid): s.start=start;s.dur=dur;s.src=src;s.sid=sid - def shift(s,ss,ds): - s.start+=ss; s.dur-=ds - -def sim(heal): - q=[]; waste=[]; gen=[]; prev=mapped[0][0] - def sort_q(): q.sort(key=lambda x:-heal.get(x.src,0)) - def upd(tp): - if not q or tp<=0: return - a=q[0]; diff=tp; lo=0 - if a.dur Date: Tue, 4 Aug 2026 10:27:34 +0200 Subject: [PATCH 09/11] fix(analytics): satisfy PLR5501 elif in regen apply branch [skip ci] Signed-off-by: Roland Salardon --- .../src/gw2_analytics/buff_state.py | 103 +++++++++--------- 1 file changed, 51 insertions(+), 52 deletions(-) diff --git a/libs/gw2_analytics/src/gw2_analytics/buff_state.py b/libs/gw2_analytics/src/gw2_analytics/buff_state.py index 933cb628..8b27c76a 100644 --- a/libs/gw2_analytics/src/gw2_analytics/buff_state.py +++ b/libs/gw2_analytics/src/gw2_analytics/buff_state.py @@ -311,61 +311,60 @@ def process( # noqa: PLR0912, PLR0915 target_tracker.expirations = [expiry for expiry, _, _ in pairs] target_tracker.stack_ids = [stack_id for _, stack_id, _ in pairs] target_tracker.healing_scores = [healing for _, _, healing in pairs] - else: - if buff_name == "regeneration": - # EI BuffSimulatorDuration + HealingLogic: capacity-5 - # queue, replace the lowest-heal stack on overflow - # (wasting its remaining duration), re-sort by healing - # until the first added_active apply pins no_sort, then - # activate: move the new stack to the front (or replace - # the active stack outright when it has <50 ms left). - new_duration = event.duration_ms or None - new_healing = self._healing_by_agent.get(event.source_agent_id, 0) - if len(target_tracker.expirations) >= _capacity_for(buff_name): - target_tracker.expirations[-1] = new_duration - target_tracker.stack_ids[-1] = event.stack_id - target_tracker.healing_scores[-1] = new_healing - else: - target_tracker.expirations.append(new_duration) - target_tracker.stack_ids.append(event.stack_id) - target_tracker.healing_scores.append(new_healing) - if not target_tracker.no_sort: - pairs = sorted( - zip( - target_tracker.expirations, - target_tracker.stack_ids, - target_tracker.healing_scores, - strict=True, - ), - key=lambda pair: pair[2], - reverse=True, - ) - target_tracker.expirations = [expiry for expiry, _, _ in pairs] - target_tracker.stack_ids = [stack_id for _, stack_id, _ in pairs] - target_tracker.healing_scores = [healing for _, _, healing in pairs] - if event.added_active: - target_tracker.no_sort = True - new_index = target_tracker.stack_ids.index(event.stack_id) - expiry = target_tracker.expirations.pop(new_index) - stack_id = target_tracker.stack_ids.pop(new_index) - healing = target_tracker.healing_scores.pop(new_index) - if target_tracker.expirations and (target_tracker.expirations[0] or 0) < 50: - target_tracker.expirations[0] = expiry - target_tracker.stack_ids[0] = stack_id - target_tracker.healing_scores[0] = healing - else: - target_tracker.expirations.insert(0, expiry) - target_tracker.stack_ids.insert(0, stack_id) - target_tracker.healing_scores.insert(0, healing) + elif buff_name == "regeneration": + # EI BuffSimulatorDuration + HealingLogic: capacity-5 + # queue, replace the lowest-heal stack on overflow + # (wasting its remaining duration), re-sort by healing + # until the first added_active apply pins no_sort, then + # activate: move the new stack to the front (or replace + # the active stack outright when it has <50 ms left). + new_duration = event.duration_ms or None + new_healing = self._healing_by_agent.get(event.source_agent_id, 0) + if len(target_tracker.expirations) >= _capacity_for(buff_name): + target_tracker.expirations[-1] = new_duration + target_tracker.stack_ids[-1] = event.stack_id + target_tracker.healing_scores[-1] = new_healing else: - target_tracker.expirations.append(event.duration_ms or None) + target_tracker.expirations.append(new_duration) target_tracker.stack_ids.append(event.stack_id) - target_tracker.healing_scores.append( - self._healing_by_agent.get(event.source_agent_id, 0) + target_tracker.healing_scores.append(new_healing) + if not target_tracker.no_sort: + pairs = sorted( + zip( + target_tracker.expirations, + target_tracker.stack_ids, + target_tracker.healing_scores, + strict=True, + ), + key=lambda pair: pair[2], + reverse=True, ) - del target_tracker.expirations[_capacity_for(buff_name) :] - del target_tracker.stack_ids[_capacity_for(buff_name) :] - del target_tracker.healing_scores[_capacity_for(buff_name) :] + target_tracker.expirations = [expiry for expiry, _, _ in pairs] + target_tracker.stack_ids = [stack_id for _, stack_id, _ in pairs] + target_tracker.healing_scores = [healing for _, _, healing in pairs] + if event.added_active: + target_tracker.no_sort = True + new_index = target_tracker.stack_ids.index(event.stack_id) + expiry = target_tracker.expirations.pop(new_index) + stack_id = target_tracker.stack_ids.pop(new_index) + healing = target_tracker.healing_scores.pop(new_index) + if target_tracker.expirations and (target_tracker.expirations[0] or 0) < 50: + target_tracker.expirations[0] = expiry + target_tracker.stack_ids[0] = stack_id + target_tracker.healing_scores[0] = healing + else: + target_tracker.expirations.insert(0, expiry) + target_tracker.stack_ids.insert(0, stack_id) + target_tracker.healing_scores.insert(0, healing) + else: + target_tracker.expirations.append(event.duration_ms or None) + target_tracker.stack_ids.append(event.stack_id) + target_tracker.healing_scores.append( + self._healing_by_agent.get(event.source_agent_id, 0) + ) + del target_tracker.expirations[_capacity_for(buff_name) :] + del target_tracker.stack_ids[_capacity_for(buff_name) :] + del target_tracker.healing_scores[_capacity_for(buff_name) :] elif event.kind == "remove_single": if _max_stacks_for(buff_name) == 1 and target_tracker.expirations: stack_index = next( From 7e78402c807e31d10a66ed8c5c255708ddb5a58d Mon Sep 17 00:00:00 2001 From: Roland Salardon Date: Tue, 4 Aug 2026 10:34:59 +0200 Subject: [PATCH 10/11] fix(ci): bump cryptography >=50 to clear CVE-2026-69247/8/9 [skip ci] Signed-off-by: Roland Salardon --- pyproject.toml | 2 +- uv.lock | 89 ++++++++++++++++++++++++-------------------------- 2 files changed, 44 insertions(+), 47 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 71b17f56..65da84cc 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -73,7 +73,7 @@ dev = [ "alembic>=1.13,<2", "minio>=7.2,<8", "python-multipart>=0.0.20,<1", - "cryptography>=43.0.1,<49", # v0.10.26 CI: pip-audit → crypt>=48 + "cryptography>=50,<51", # v0.10.26 CI: pip-audit → crypt>=48; v0.15.x: CVE-2026-69247/8/9 → >=50 "arq>=0.25,<1", "redis>=5.0,<8", diff --git a/uv.lock b/uv.lock index 318f0a0f..fb81dd58 100644 --- a/uv.lock +++ b/uv.lock @@ -527,55 +527,52 @@ wheels = [ [[package]] name = "cryptography" -version = "48.0.1" +version = "50.0.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "cffi", marker = "platform_python_implementation != 'PyPy'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/12/45/870e7f4bef50e5f53b9f51d4428aee5290eedf58ba443f16b1ebb7ab8e66/cryptography-48.0.1.tar.gz", hash = "sha256:266f4ee051abb2f725b74ef8072b521ce1feacf685a3364fa6a6b45548db791a", size = 832989, upload-time = "2026-06-09T22:32:31.8Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/1b/bc/ee4137cbbe105652c0ee4252792b78fc8e7afa4b8e61d9d5dc05a7f45731/cryptography-48.0.1-cp311-abi3-macosx_10_9_universal2.whl", hash = "sha256:3e4a1a3232eef2e6c732827d5722db29a0cc8b27af2a4d865b094cf954be9ca1", size = 8008324, upload-time = "2026-06-09T22:31:00.702Z" }, - { url = "https://files.pythonhosted.org/packages/d5/85/6379d42181bfc713094f081360fc5784d6c816b599d45e7f082502d173ce/cryptography-48.0.1-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:32143b24adb918f078134e1e230f1eb8cc04886b92c28b5f0041aaf3e5699225", size = 4696243, upload-time = "2026-06-09T22:32:33.446Z" }, - { url = "https://files.pythonhosted.org/packages/9c/87/c85d147b53323c7eb4d850920c8901377323c2a0ff8d79c262d4fee89aa2/cryptography-48.0.1-cp311-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:f0d27a5696721ef7a672b8c810f6aded391058e0b9486e63e6d93baf765da691", size = 4713235, upload-time = "2026-06-09T22:31:40.141Z" }, - { url = "https://files.pythonhosted.org/packages/79/58/67cbf8cf1ee7c54b439ca07bbecf8362c07afc11a3724fea70f745784add/cryptography-48.0.1-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:eb86ce1af36fe65041b6db9a8bb064ee621a7e5fded0f80d475ec243477cd242", size = 4702323, upload-time = "2026-06-09T22:31:42.191Z" }, - { url = "https://files.pythonhosted.org/packages/89/c6/24266ac10c47f6cd2a865f4446062b466da1d1f10b27189eac00e61bf0c9/cryptography-48.0.1-cp311-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:b024e784ad6c077ee0147b35ea9cbfc1e34e1fd4c1dcca214c2794d73a12df08", size = 5300085, upload-time = "2026-06-09T22:31:58.703Z" }, - { url = "https://files.pythonhosted.org/packages/d2/bb/cc4b78784f97efc8c5874c2a9743708d172be6663024b34a0467885ae0c8/cryptography-48.0.1-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:3752f2dbc8f07a30aad2932c986cea495b03bb554887828225da104f732852b6", size = 4746137, upload-time = "2026-06-09T22:31:31.01Z" }, - { url = "https://files.pythonhosted.org/packages/1f/52/0c44de3f5267f8fbe8e835138017522a333436166e406f0db9b9e6e3033f/cryptography-48.0.1-cp311-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:bd81490cd5801d755cf97bb68ac191f14b708470b1c7cf4580f669b9c9264cd8", size = 4333867, upload-time = "2026-06-09T22:32:28.096Z" }, - { url = "https://files.pythonhosted.org/packages/9a/2e/772d7adbfa931537bc401640b7cac9976bff689bda187833e5d63b428e49/cryptography-48.0.1-cp311-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:66fd0771e7b9c6dcd44cf1120690d2338d16d72795cf40cae2786a39eba65429", size = 4701805, upload-time = "2026-06-09T22:31:38.284Z" }, - { url = "https://files.pythonhosted.org/packages/f8/a3/b06844f303873493c963caf581c04df31c7035e0c1b0f02c4814d319ec80/cryptography-48.0.1-cp311-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:3fd2ca57062b241c856670b073487d2e86c4637937ca5601e48f97bf8e11fc8f", size = 5258461, upload-time = "2026-06-09T22:31:04.187Z" }, - { url = "https://files.pythonhosted.org/packages/9f/13/8b765e2e12b07c74941caadb9d1c8fdc006c4dfbf2b8f2d610519758954d/cryptography-48.0.1-cp311-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:0ee6ea481db1ab889cba043ec1eda17bb9c1ea79db6722f779c3667f9f70322f", size = 4745488, upload-time = "2026-06-09T22:32:30.07Z" }, - { url = "https://files.pythonhosted.org/packages/2e/aa/48972bce55049b32a94f4907eda4d75fa385aad8a39506cc2fc72196ecf0/cryptography-48.0.1-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:f2ceef93cb096aa3c4cc4b5c94ca6131f9196d28c64d6111533402a9b2054d41", size = 4830256, upload-time = "2026-06-09T22:31:43.868Z" }, - { url = "https://files.pythonhosted.org/packages/47/a2/e5079a032fb85cf6005046ca92bbd78b0c82dad2b5751ab8c311659da06f/cryptography-48.0.1-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:9bd3f92d76217892b15df84ca256c2c113d386fdda7a7d8691aeeced976507c6", size = 4979117, upload-time = "2026-06-09T22:31:05.845Z" }, - { url = "https://files.pythonhosted.org/packages/b7/a0/8f50cae9c74e718ed769d63ed5c74bd0ea830c9550a74629cebd1b9c7bc7/cryptography-48.0.1-cp311-abi3-win32.whl", hash = "sha256:b9a32b876490d66c8bcc9963ef220199569748434ab01a9d6aaeabf88e7f5158", size = 3304154, upload-time = "2026-06-09T22:32:16.845Z" }, - { url = "https://files.pythonhosted.org/packages/c5/69/0572c77dbace6fef72f33755bd52ea399c71367250d366237f8691826b9e/cryptography-48.0.1-cp311-abi3-win_amd64.whl", hash = "sha256:39489bfca54c7a1f6b297efcd8bc608ab92d16c4ca631b0cad4da46724588b24", size = 3817138, upload-time = "2026-06-09T22:32:00.388Z" }, - { url = "https://files.pythonhosted.org/packages/42/06/3e768b4c3bc78201583fa35a0e18f640dd782ff41afba88f8545481a8874/cryptography-48.0.1-cp314-cp314t-macosx_10_9_universal2.whl", hash = "sha256:f817adc181390bd54f2f700107a7419040fb7c1bdf2fc26f36551a06a68c3345", size = 7989830, upload-time = "2026-06-09T22:31:07.8Z" }, - { url = "https://files.pythonhosted.org/packages/8a/13/6476736484b94041110c8340a3eb63962fea4975baea8cb4a512adb44d4d/cryptography-48.0.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d5d30989c6917b478b5817902e85fddaea2261efa8648383d965381ccb9e1ac4", size = 4689201, upload-time = "2026-06-09T22:31:09.745Z" }, - { url = "https://files.pythonhosted.org/packages/79/62/65a87f34d2a431546e2509b85d55e8c90df86d668f6731da64d538512ac2/cryptography-48.0.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:df637c05205ea7c1d7fbcbe54bbfea648a52951155f997af13d895d0ecc96991", size = 4702822, upload-time = "2026-06-09T22:32:24.409Z" }, - { url = "https://files.pythonhosted.org/packages/7f/59/810b5204b0a9b10f4b6bc06bd551a8b609803cd931806bc3b71884b225e5/cryptography-48.0.1-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:869c3b8a53bfe27147832df48b32adadf558249d50e76cb3769d40e986b13265", size = 4694875, upload-time = "2026-06-09T22:32:08.737Z" }, - { url = "https://files.pythonhosted.org/packages/24/dc/d8ca05ffea724eec6d232ea6f18e74c269eb6bdfdcc9bfba689790d1325f/cryptography-48.0.1-cp314-cp314t-manylinux_2_28_ppc64le.whl", hash = "sha256:e361afba8918070d376df76f408a4f67fec0ee9cff81a99e48fe9a233ef59e17", size = 5290385, upload-time = "2026-06-09T22:31:15.212Z" }, - { url = "https://files.pythonhosted.org/packages/03/8c/3be6cb4da181f5bb6c19cf560c2359d60644a6b5fc5b57854e528f47b296/cryptography-48.0.1-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:d069066deead00ac7f090be101be875a06855908f7ec004c27b8fefb4acfb411", size = 4737082, upload-time = "2026-06-09T22:32:22.66Z" }, - { url = "https://files.pythonhosted.org/packages/aa/f6/d5f60a5a1434dbfd949e227fd0065d194c7e6b6ac526b17f5c06152b8231/cryptography-48.0.1-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:09f73a725d582cef64b91281a322cd798d14a33b2b6f2b7ad9531dc336d84c02", size = 4325328, upload-time = "2026-06-09T22:32:10.777Z" }, - { url = "https://files.pythonhosted.org/packages/17/b7/ba75dd947a14b6ad907b01ae8f6b5b348cdd1b48142f0063dee9e20c1d9d/cryptography-48.0.1-cp314-cp314t-manylinux_2_34_aarch64.whl", hash = "sha256:15254441469dd6bf027039453288e2072124f8b6603563f5d759e1c9b69273fa", size = 4694530, upload-time = "2026-06-09T22:31:53.105Z" }, - { url = "https://files.pythonhosted.org/packages/62/29/50d6b9e8aff12d8b67afaeb3569335e32dc83a5723e3bbded24fdac9f809/cryptography-48.0.1-cp314-cp314t-manylinux_2_34_ppc64le.whl", hash = "sha256:8ace4507d1e6533c125f4fac754f8bb8b6a74c08e92179dabd7e16571a3efbf3", size = 5245046, upload-time = "2026-06-09T22:31:25.774Z" }, - { url = "https://files.pythonhosted.org/packages/9f/04/618f4115cfc0add0838c82507aa18a346089428da8653ad38b3ff36f5cb3/cryptography-48.0.1-cp314-cp314t-manylinux_2_34_x86_64.whl", hash = "sha256:b4e391975f038e66432328639620a4aff2d307513b004f1ca06d6225bced815c", size = 4736660, upload-time = "2026-06-09T22:32:12.676Z" }, - { url = "https://files.pythonhosted.org/packages/24/9c/06e062462a0de28a3b3911322eded4c16deb9f441b1b7575d3dc59488ab5/cryptography-48.0.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:42fcd8e26fe555d9b3577a135f5091fefa0aa4e99129c23fb56787a1bd4ada72", size = 4822229, upload-time = "2026-06-09T22:31:17.062Z" }, - { url = "https://files.pythonhosted.org/packages/f4/be/0561971eaaee4b8a0e7d5113c536921063ab91aaf23278ac374eaf881e11/cryptography-48.0.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:c1400da5e32a43253392277eac7490a60e497d810a63dd5608d71bbd7af507c9", size = 4966364, upload-time = "2026-06-09T22:31:32.842Z" }, - { url = "https://files.pythonhosted.org/packages/a4/27/728c77876f12b000820b69ae490f3c4083775e79e07827e9e60be07ad209/cryptography-48.0.1-cp314-cp314t-win32.whl", hash = "sha256:0df56b056bc17c1b7d6821dfa65216e62bd232d8ab05eb3db44e71d235651471", size = 3278498, upload-time = "2026-06-09T22:31:29.154Z" }, - { url = "https://files.pythonhosted.org/packages/06/e3/79a612c6d7b1e6ee0edd43633d53035bec2cfb78c82b76f7864f39e36f34/cryptography-48.0.1-cp314-cp314t-win_amd64.whl", hash = "sha256:9de21387aa95e2a895823d0745b430bed4f33503ba9ab5e0b5311f33e37d66d2", size = 3798790, upload-time = "2026-06-09T22:31:56.697Z" }, - { url = "https://files.pythonhosted.org/packages/ca/6c/00fa2a95997164c8b2072ce327c23d4ab20809ccc323ea5fab91e53a4bba/cryptography-48.0.1-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:4fdc69f8e4316bcf0c8c8ec1f26f285d12e8142d88d96c876a59a03be3f6ae67", size = 7987408, upload-time = "2026-06-09T22:32:20.777Z" }, - { url = "https://files.pythonhosted.org/packages/b0/d9/45f309a7e4e5f3f8f121d6d3be9e94024a7726ec598d6e08ae04edb2f04d/cryptography-48.0.1-cp39-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:48fe40804d4caa2288f24e70ca8c64c42dd826da0ad7e4f1b41b2128d679e6c8", size = 4690196, upload-time = "2026-06-09T22:31:54.74Z" }, - { url = "https://files.pythonhosted.org/packages/5f/9f/a1bc8bcc798811b8527eb374bbccf30a3f3e806829d967118222bf1125eb/cryptography-48.0.1-cp39-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:86be3b1b0b6bf09482fb50a979c508d2950ed95f5621ec77f4e385962006b83a", size = 4696782, upload-time = "2026-06-09T22:31:45.615Z" }, - { url = "https://files.pythonhosted.org/packages/66/c2/81a4fb4e4373c500bb526bc337ac5719dd31dd15b970b84a238168c6aa08/cryptography-48.0.1-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:4ab0a343c807bbcd90c971cd1ecf072937cd01847a9e002bef88fb47ac6be577", size = 4696618, upload-time = "2026-06-09T22:31:11.564Z" }, - { url = "https://files.pythonhosted.org/packages/e5/0b/aa68b221dde92d09cb29a024ede17550ee21e77a404e59fc093c82bb51e1/cryptography-48.0.1-cp39-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:9621de99d2da096006b629979efd8ae7eb2d8b822488d0c89ee4000c306c59b1", size = 5289970, upload-time = "2026-06-09T22:31:20.368Z" }, - { url = "https://files.pythonhosted.org/packages/78/13/fba657f958d2af66ea959a4ba01212632089249d34af1ae48054136344d7/cryptography-48.0.1-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:88c852a0ae366e262e5a1744b685e6a433dc8788dd2a277e418bf4904203609d", size = 4731873, upload-time = "2026-06-09T22:31:22.253Z" }, - { url = "https://files.pythonhosted.org/packages/4c/4c/9a964756d24a26b3e34dfcb16f961b89838786e6700b635b0d1e3adff4b6/cryptography-48.0.1-cp39-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:43c5835e2cb98c8733d86f57d6fc879b613f5c3478607281c3e36daffc6dd8a6", size = 4330804, upload-time = "2026-06-09T22:31:36.56Z" }, - { url = "https://files.pythonhosted.org/packages/4b/0f/a10f3a6eb12950a10e3a874070283aa2dd5875b2bfd15fad8a3e17b3f13e/cryptography-48.0.1-cp39-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:fe0180af5bf9236518a087e35bf2d9a347d5f5f51e63c579d683ddff424e3d46", size = 4696217, upload-time = "2026-06-09T22:31:13.351Z" }, - { url = "https://files.pythonhosted.org/packages/f3/6f/5cd12f951165ea73ef85266775d97e4c763b2474ccfd816dd69d3a18d6f8/cryptography-48.0.1-cp39-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:b7a2d1a937a738a881737cec135a38bb61470589b17515b9f73f571d0ae10401", size = 5245252, upload-time = "2026-06-09T22:32:02.193Z" }, - { url = "https://files.pythonhosted.org/packages/68/ab/8aaa12e4516ec4464033ab79b6f3b592bd5a92102467c4ace8a0d970203f/cryptography-48.0.1-cp39-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:b74ca3b8e5ecdd833bf6a002ca41b4793bb27fb8f1c06ffaf2643c9e9140e31b", size = 4731388, upload-time = "2026-06-09T22:32:04.019Z" }, - { url = "https://files.pythonhosted.org/packages/1b/24/50027ea4dca85ec1f40688f3c24fb32ccacd520583c9592c3cc95628e6fb/cryptography-48.0.1-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:2c37f2461406063b417837f5f3daab668652acd82423efcd7f0a9f04be972de1", size = 4824186, upload-time = "2026-06-09T22:32:18.707Z" }, - { url = "https://files.pythonhosted.org/packages/52/41/04cb5eb17085ade6f50cc611fb657df6a0f5885350de8764ece89c050197/cryptography-48.0.1-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:86fe77abb1bd87afb251d4d02ada7ecf53a32cee9b67d976abb2e45a13297475", size = 4964539, upload-time = "2026-06-09T22:31:18.793Z" }, - { url = "https://files.pythonhosted.org/packages/36/bf/ed70785c496e89d7e73b7cda2d21f2447fd6d4e821714b8d04ff217fed92/cryptography-48.0.1-cp39-abi3-win32.whl", hash = "sha256:6b2c0c3e6ccf3ade7750f836ef3ee36eea250cc467d45c256895573ac08cc6f1", size = 3282307, upload-time = "2026-06-09T22:30:53.162Z" }, - { url = "https://files.pythonhosted.org/packages/b3/ff/371ea7d252656ee1eb6d83eeeef3d1d0c6baf1d6497687d081ea03814670/cryptography-48.0.1-cp39-abi3-win_amd64.whl", hash = "sha256:9a49ca6c81417f6a5edb50375a60cccdd70fa0a91a5211829dbea74eba94d2ac", size = 3793408, upload-time = "2026-06-09T22:32:15.191Z" }, +sdist = { url = "https://files.pythonhosted.org/packages/de/41/6cbdcf9142d00fe82836fbb51e503e58088575cf7a0fe1dbff6695bf0840/cryptography-50.0.0.tar.gz", hash = "sha256:eeac2acb5a20ed25e0ad6d1df9891a520b78b404266b6d11778f25d5d691a6c9", size = 880201, upload-time = "2026-07-31T14:25:10.11Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c5/5c/59086b4aac5e879d38ddbcf74e4be7ade89cebc3eb199a55da998c3bb46a/cryptography-50.0.0-cp311-abi3-macosx_11_0_arm64.whl", hash = "sha256:031e2d5dd4bb9caa3ca9c82e5a197fd8ae680232cee62603d1a813f3f07e3d03", size = 4001252, upload-time = "2026-07-31T14:23:33.331Z" }, + { url = "https://files.pythonhosted.org/packages/57/ef/8f2df13c7216bcad3e1c74e07f6e193d93e998e114f524a53877c9af27ad/cryptography-50.0.0-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:fd9192b7b70c573d7f214eb1ae35e00d359f6f5e4b27c7e21e30de1fc6204645", size = 4719554, upload-time = "2026-07-31T14:23:35.611Z" }, + { url = "https://files.pythonhosted.org/packages/d9/41/029086c34d91052fc3b88bcc8056f709a7c915c7a23b235a54eb800b1c97/cryptography-50.0.0-cp311-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:06a32a980526a6ab9a4b9bf8f7385800791e2bb960903cb6b530e4817509a3b7", size = 4702130, upload-time = "2026-07-31T14:23:37.635Z" }, + { url = "https://files.pythonhosted.org/packages/7d/ff/b6ce0954962e7f7b969f850a883744197bb3910bdfd7b6da162eab7d9f68/cryptography-50.0.0-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:a1b30560f2acc95aa8b2e06e716a13dbfc97314747b80d9707e307f77b40d6b3", size = 4725244, upload-time = "2026-07-31T14:23:39.471Z" }, + { url = "https://files.pythonhosted.org/packages/06/1e/63a1027cb7fec360a182208e1b7767d5aa1fe57be3d6aa856e69a321edc0/cryptography-50.0.0-cp311-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:8d89f3976b10b4ce31118de72329025f70d2c6ead14a8217c5514dd2c6d5a78f", size = 5342265, upload-time = "2026-07-31T14:23:41.286Z" }, + { url = "https://files.pythonhosted.org/packages/6b/72/a1116d683a6d7ece94590013882515de087edf9ef0e6292aae615a44df73/cryptography-50.0.0-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:b42a28c1844fd9de8f3f7d540e36b66f3a9c83fceac7170ebc7a6a19edd9dcae", size = 4734609, upload-time = "2026-07-31T14:23:43.139Z" }, + { url = "https://files.pythonhosted.org/packages/15/37/36a9c479bbe49acea2636c7fd3360d20f7b7e079c300352011c44850b181/cryptography-50.0.0-cp311-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:900131fafd8aead39ac7dd3a7e833be754c17a95cfd91221636949fe4eb0aa8a", size = 4356517, upload-time = "2026-07-31T14:23:44.939Z" }, + { url = "https://files.pythonhosted.org/packages/32/98/8a151d64367204cbc63ec65d37502f1d9c53cf4bfc6ec3c532614dbec60d/cryptography-50.0.0-cp311-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:07949c449a1abcf60d1ee6e88956d89404c7df3c8258f46589e912988e551987", size = 4724529, upload-time = "2026-07-31T14:23:46.93Z" }, + { url = "https://files.pythonhosted.org/packages/22/f6/ec13b470172126464a86bf54d2294a46d29837fc51ba3e45d4047946fb5e/cryptography-50.0.0-cp311-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:f89831ef99dd7dd169ab06d63a831adb9e20a87aac6d380266bbda5823349169", size = 5299852, upload-time = "2026-07-31T14:23:48.851Z" }, + { url = "https://files.pythonhosted.org/packages/da/3a/f05e32c99d440c9bb891ea0e36c9091891e36be5a9a87ab2ee6ea20729f6/cryptography-50.0.0-cp311-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:82148ec5bddac30b51a5b3c1945075f896fa022cb93f8e4a01e9f6ee95292c5f", size = 4734462, upload-time = "2026-07-31T14:23:50.861Z" }, + { url = "https://files.pythonhosted.org/packages/ca/dc/bd72b26be8953f80625f63151efd38eee71c76ca6cf591c08ff34615a79e/cryptography-50.0.0-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:1489e263a8048bb8b6a8bac662eb2d402ea5d2b7b4699b72f385f1e2772db105", size = 4852708, upload-time = "2026-07-31T14:23:52.715Z" }, + { url = "https://files.pythonhosted.org/packages/27/20/c930314a2ab476d15dec966ec87e2e9637bb02b06106b12c0396c57bb603/cryptography-50.0.0-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:7cec5b856506da6defb290f30c9ee687d5f5e8cb0bd3f6459dde43b0b4fa40ef", size = 5004179, upload-time = "2026-07-31T14:23:54.887Z" }, + { url = "https://files.pythonhosted.org/packages/32/2e/c9db68a0c4bfa28e310707527c0ee3a2bd254104d2e02e68f368e197aa4c/cryptography-50.0.0-cp311-abi3-win_amd64.whl", hash = "sha256:bd1c592e4d5974f0d08d4888e432157adba757c66da0246918e43677fafa2d30", size = 3840395, upload-time = "2026-07-31T14:23:56.677Z" }, + { url = "https://files.pythonhosted.org/packages/c3/fb/951032a3bf22a5697c83183fb6294a4843772947a70e616c57b3ff5f522e/cryptography-50.0.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:49e7d93abdbd2990caced757e5fade25302f719c3c8fb6e6fff2dde98999fc41", size = 3989258, upload-time = "2026-07-31T14:23:58.881Z" }, + { url = "https://files.pythonhosted.org/packages/d4/67/91eb047e69c5e845f2f14b8a2e4a1aab0f283cb885531e9e22c8adb176bc/cryptography-50.0.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:19736989797678c6af1e55cd49055cdbcb55d8f6b5583ac5335f933aba9101dc", size = 4700648, upload-time = "2026-07-31T14:24:00.702Z" }, + { url = "https://files.pythonhosted.org/packages/30/82/85f0f7425c856b9f96459411eb12e74ef72df9caf6f8f15bf23a33ff131f/cryptography-50.0.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:80b63928fa35083b33966ce1efb70e5b9607181e49dcd1c22c8c005e319f667f", size = 4682442, upload-time = "2026-07-31T14:24:02.538Z" }, + { url = "https://files.pythonhosted.org/packages/1a/28/b555a365adff1cca2fbe7b9e487d68a40de6bc67ff2cb587473eb43de0e7/cryptography-50.0.0-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:d58c3db7cd6eed54e6c06744db55456b65ebd7492ddeae9c1e93cfca7aa857d3", size = 4707596, upload-time = "2026-07-31T14:24:04.394Z" }, + { url = "https://files.pythonhosted.org/packages/72/d8/f52538140cc719df62a01cf87d1c7142318d235817109d6f4054d7c352d6/cryptography-50.0.0-cp314-cp314t-manylinux_2_28_ppc64le.whl", hash = "sha256:df2a58a472f332225671c35b0a830208b86d004f82baa8530fa3782c85646533", size = 5314552, upload-time = "2026-07-31T14:24:06.31Z" }, + { url = "https://files.pythonhosted.org/packages/38/14/6120e5bd7c5aa022ad15424ba4d5c5269d0d9448ed4d55e492ea91e3c1c4/cryptography-50.0.0-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:11b74db56cdbe3cdee6e3f6982ecb70334fa10dce99ed58bf7894aaaa3b2a037", size = 4717113, upload-time = "2026-07-31T14:24:08.349Z" }, + { url = "https://files.pythonhosted.org/packages/fa/71/190bf38c3ee2e0f8efc9860ae100c9df4169742eef274b91e7aa1cb133b9/cryptography-50.0.0-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:f59e38625469987d7ef6d495323c55e7db6c212eaf6112267e0d3b565a2e9c9f", size = 4338580, upload-time = "2026-07-31T14:24:10.227Z" }, + { url = "https://files.pythonhosted.org/packages/3a/63/504ccfbbe61fd8aa983f7f146399cdf034c72c2fc55f5b2dfdcdcdb20c99/cryptography-50.0.0-cp314-cp314t-manylinux_2_34_aarch64.whl", hash = "sha256:ecfed7367f965a0328cfbdd70da860f15441f002f613185668c6e6ebf5a0ac11", size = 4707038, upload-time = "2026-07-31T14:24:12.169Z" }, + { url = "https://files.pythonhosted.org/packages/01/77/2cf79bbfc4d12ca106437a6e170d6aaa01a373e93093118aaaef0e801bd4/cryptography-50.0.0-cp314-cp314t-manylinux_2_34_ppc64le.whl", hash = "sha256:9aa87839c383bdbab6ef865787a1fb877af8dd03464c4400322726feaaadfc6d", size = 5273110, upload-time = "2026-07-31T14:24:14.38Z" }, + { url = "https://files.pythonhosted.org/packages/e5/45/8aae2972c520145377ea3559a605a899bebe227bf070b33cdb445929a9b9/cryptography-50.0.0-cp314-cp314t-manylinux_2_34_x86_64.whl", hash = "sha256:6ba6a53445bd3cfa809ef3ef5f1589aa6ba08784a1d962bf47d0940e871dab1c", size = 4716439, upload-time = "2026-07-31T14:24:16.415Z" }, + { url = "https://files.pythonhosted.org/packages/7b/20/4fe50b619a48c2525cc46e2dbc1ac490708d704be5d467bdaac6dc955682/cryptography-50.0.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:3f5735ffe4996d28b809371756219f5354864902a3b9e7c0b9ee87041209fc9c", size = 4837383, upload-time = "2026-07-31T14:24:18.553Z" }, + { url = "https://files.pythonhosted.org/packages/92/91/3a31366e183343d3703f8995c095f5734676bd6938118047e50fcf279eb4/cryptography-50.0.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:1b4a266766514614f8aa60416e71f2fc6e575d36e7bdc90f644fadb2f4b75b95", size = 4985772, upload-time = "2026-07-31T14:24:20.385Z" }, + { url = "https://files.pythonhosted.org/packages/74/9a/02ffe35b2853d121689871eb5dce862092562b3a1ed5cc98f1aaed441506/cryptography-50.0.0-cp314-cp314t-win_amd64.whl", hash = "sha256:12b9c6996425c76ea6c457ace4f3073e715b8c545add07cd1a8f3a4f90691269", size = 3816291, upload-time = "2026-07-31T14:24:22.125Z" }, + { url = "https://files.pythonhosted.org/packages/03/37/73d005be173aff344af30e9fd2a576575cb2391a7101d9cd3842e1fa8cce/cryptography-50.0.0-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:ccdc4a71a4dabae05de219404f9f4abc38e3b58422177ff93d0da05967dafa07", size = 4036009, upload-time = "2026-07-31T14:24:24.122Z" }, + { url = "https://files.pythonhosted.org/packages/ff/c6/7a6202a534e32103a285b7834a120869557fe198d51d7cfe59754c8bda9c/cryptography-50.0.0-cp39-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:910e1d2668e7de9648f2bcee30e180db2a6b15c30f887d7c4c93ddf96e3992e3", size = 4745252, upload-time = "2026-07-31T14:24:26.118Z" }, + { url = "https://files.pythonhosted.org/packages/85/4f/0fa8c2f4428198f15d9ff8d63400e27afbf94ce833f6108da1eb3753f945/cryptography-50.0.0-cp39-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:a91296cb61e8df6f86d0c19cc4068228da256bf59bf86049fbd821084565327f", size = 4728939, upload-time = "2026-07-31T14:24:27.994Z" }, + { url = "https://files.pythonhosted.org/packages/d1/63/54dd723490ba2dc09b299682c10b38db38f159728bcaae8c591b8af2f22d/cryptography-50.0.0-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:e722f16708d854fe924790e051061f6704a472c3bac347b6fd88033ea8dd0dc5", size = 4748483, upload-time = "2026-07-31T14:24:30.254Z" }, + { url = "https://files.pythonhosted.org/packages/1d/dd/7c77d26285cc7f6991efce64a0f5b4f9383bfa5dd8c5033003eaf7db4cdb/cryptography-50.0.0-cp39-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:d764dcf130c428ef66786f866dd750f53182bc608813489915e9fc106bb0c82f", size = 5367599, upload-time = "2026-07-31T14:24:32.457Z" }, + { url = "https://files.pythonhosted.org/packages/46/c9/f60aed34c013f317f92817b6c171c2d22a78270fa41109bd4b08af26b194/cryptography-50.0.0-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:105110f43a471dbd0060b9c9516cb8a6a79233631a04cc2ba16f28323ac6e025", size = 4762647, upload-time = "2026-07-31T14:24:34.599Z" }, + { url = "https://files.pythonhosted.org/packages/be/f3/f9a0173b139372c3a48ed98154b45cc6b9de17c789d5ab552e621c293609/cryptography-50.0.0-cp39-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:828743d939e9629bc267b8e2d08d8bb67cd4319c771a33d4b18b22dd8fb7440a", size = 4385197, upload-time = "2026-07-31T14:24:36.647Z" }, + { url = "https://files.pythonhosted.org/packages/d8/36/83bb81f6e569bc38e1e4a7bc80f29b46bb9601920bc455fc8e888f5d5742/cryptography-50.0.0-cp39-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:2a8183b489dc1f7f80f135780fadc1108f14b31b8a40411c7a5b17425f65f28b", size = 4748095, upload-time = "2026-07-31T14:24:39.493Z" }, + { url = "https://files.pythonhosted.org/packages/6b/16/d3008eff98c764979865834c3d386d4fd041b5f52e7f34fc29ac1a5eb515/cryptography-50.0.0-cp39-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:6e7d61120573a7f2cd94cc095f9e81f6967c61ccdf194285aa143ecec8e0b708", size = 5325948, upload-time = "2026-07-31T14:24:41.556Z" }, + { url = "https://files.pythonhosted.org/packages/9c/f8/d97f9603efda3888187bfdb893f26c41be4735c10631d05d284ee6b047c4/cryptography-50.0.0-cp39-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:37fdb0d0111f1e2ff07139dfb79f1b49531f8e213c46f1163dd7642979b58c47", size = 4762400, upload-time = "2026-07-31T14:24:43.636Z" }, + { url = "https://files.pythonhosted.org/packages/64/a2/4615c8f7d81a00b1d6e6afe19f694e1543582349fb5f4076f6cb5dc36485/cryptography-50.0.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:c87f62a3d3b9888ed0fdde100ec06aa61ca9cd44bad9057d1dff9a516b5f5bb9", size = 4878208, upload-time = "2026-07-31T14:24:45.522Z" }, + { url = "https://files.pythonhosted.org/packages/d2/1a/efcfb02f91407149a0dacffffab791f7e19bf6385f63b3666dc8b5e5c9c8/cryptography-50.0.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:65c2c3add92b45fd0709db8594536aea39c2a67af0e27ffcf049c498501140b7", size = 5037050, upload-time = "2026-07-31T14:24:47.697Z" }, + { url = "https://files.pythonhosted.org/packages/57/30/4a22984d4f1bdfb8c054f07a92bc176b97a3134cc1d6c4b3bffb1f3688b4/cryptography-50.0.0-cp39-abi3-win_amd64.whl", hash = "sha256:d24fead1d4d076e1bfb006dcec392074a3cd8d7b4fc8a595aa64073b2b7a96ba", size = 3874135, upload-time = "2026-07-31T14:24:50.085Z" }, ] [[package]] @@ -1062,7 +1059,7 @@ dev = [ dev = [ { name = "alembic", specifier = ">=1.13,<2" }, { name = "arq", specifier = ">=0.25,<1" }, - { name = "cryptography", specifier = ">=43.0.1,<49" }, + { name = "cryptography", specifier = ">=50,<51" }, { name = "fastapi", specifier = ">=0.140.13,<1" }, { name = "fastapi-mcp", specifier = ">=0.4,<1" }, { name = "httpx", specifier = ">=0.27" }, From eeede7e32a5ce37f8ef36638d85e76d6c595161f Mon Sep 17 00:00:00 2001 From: Roland Salardon Date: Tue, 4 Aug 2026 13:12:49 +0200 Subject: [PATCH 11/11] chore(ci): trigger pull_request check runs Signed-off-by: Roland Salardon