* [PATCH v2 03/18] bus/dpaa: fix error handling in qman_query
From: Hemant Agrawal @ 2026-06-19 6:09 UTC (permalink / raw)
To: stephen, david.marchand, dev; +Cc: stable
In-Reply-To: <20260619060916.485258-1-hemant.agrawal@nxp.com>
Optimize error handling in qman_query() to avoid redundant
checks and properly propagate error codes.
Fixes: 06268e2cb175 ("bus/dpaa: query queue frame count support")
Cc: stable@dpdk.org
Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com>
---
drivers/bus/dpaa/base/qbman/qman.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/bus/dpaa/base/qbman/qman.c b/drivers/bus/dpaa/base/qbman/qman.c
index 2da1b3e3f7..d289df2d33 100644
--- a/drivers/bus/dpaa/base/qbman/qman.c
+++ b/drivers/bus/dpaa/base/qbman/qman.c
@@ -1955,11 +1955,11 @@ int qman_query_fq(struct qman_fq *fq, struct qm_fqd *fqd)
cpu_relax();
DPAA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == QM_MCR_VERB_QUERYFQ);
res = mcr->result;
- if (res == QM_MCR_RESULT_OK)
- *fqd = mcr->queryfq.fqd;
- hw_fqd_to_cpu(fqd);
if (res != QM_MCR_RESULT_OK)
return -EIO;
+
+ *fqd = mcr->queryfq.fqd;
+ hw_fqd_to_cpu(fqd);
return 0;
}
--
2.43.0
^ permalink raw reply related
* [PATCH v2 02/18] bus/dpaa: fix fqid endianness
From: Hemant Agrawal @ 2026-06-19 6:09 UTC (permalink / raw)
To: stephen, david.marchand, dev; +Cc: stable
In-Reply-To: <20260619060916.485258-1-hemant.agrawal@nxp.com>
In qman_fq_flow_control(), the fqid field in the management
command was set using the host-endian fqid instead of the
pre-converted big-endian fqid_be. Fix it to use fqid_be
consistent with all other enqueue paths.
Fixes: c47ff048b99a ("bus/dpaa: add QMAN driver core routines")
Cc: stable@dpdk.org
Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com>
---
drivers/bus/dpaa/base/qbman/qman.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/bus/dpaa/base/qbman/qman.c b/drivers/bus/dpaa/base/qbman/qman.c
index 9a99eb9785..2da1b3e3f7 100644
--- a/drivers/bus/dpaa/base/qbman/qman.c
+++ b/drivers/bus/dpaa/base/qbman/qman.c
@@ -1921,7 +1921,7 @@ int qman_fq_flow_control(struct qman_fq *fq, int xon)
goto out;
}
mcc = qm_mc_start(&p->p);
- mcc->alterfq.fqid = fq->fqid;
+ mcc->alterfq.fqid = fq->fqid_be;
mcc->alterfq.count = 0;
myverb = xon ? QM_MCC_VERB_ALTER_FQXON : QM_MCC_VERB_ALTER_FQXOFF;
--
2.43.0
^ permalink raw reply related
* [PATCH v2 01/18] bus/dpaa: fix error handling of qman_create_fq
From: Hemant Agrawal @ 2026-06-19 6:08 UTC (permalink / raw)
To: stephen, david.marchand, dev; +Cc: stable
In-Reply-To: <20260619060916.485258-1-hemant.agrawal@nxp.com>
Fix the error handling path in qman_create_fq() to properly
return error codes instead of silently ignoring failures.
Fixes: c47ff048b99a ("bus/dpaa: add QMAN driver core routines")
Cc: stable@dpdk.org
Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com>
---
drivers/bus/dpaa/base/qbman/qman.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/bus/dpaa/base/qbman/qman.c b/drivers/bus/dpaa/base/qbman/qman.c
index 5534e1846c..9a99eb9785 100644
--- a/drivers/bus/dpaa/base/qbman/qman.c
+++ b/drivers/bus/dpaa/base/qbman/qman.c
@@ -1579,6 +1579,9 @@ int qman_create_fq(u32 fqid, u32 flags, struct qman_fq *fq)
err:
if (flags & QMAN_FQ_FLAG_DYNAMIC_FQID)
qman_release_fqid(fqid);
+#ifdef CONFIG_FSL_QMAN_FQ_LOOKUP
+ clear_fq_table_entry(fq->key);
+#endif
return -EIO;
}
--
2.43.0
^ permalink raw reply related
* [PATCH v2 00/18] net/dpaa: bug fixes for bus, net and fmlib drivers
From: Hemant Agrawal @ 2026-06-19 6:08 UTC (permalink / raw)
To: stephen, david.marchand, dev
In-Reply-To: <20260618141151.3990283-1-hemant.agrawal@nxp.com>
This series contains bug fixes for the DPAA PMD (bus/dpaa, net/dpaa,
net/dpaa/fmlib and dma/dpaa):
v2 changes:
- P05: Fix commit message API name (fm_pcd_kg_scheme_delete not FM_PCD_MatchTableSchemeDelete)
- P08: Guard DPAA_PUSH_QUEUES_NUMBER env-var override for LS1043A to prevent
inadvertent re-enabling of push mode (errata)
- P09: Document dpaa_finish() call removal in commit message
- P10: Fix wrong Fixes: tag (was log macro commit, now correct interrupt commit)
- P11: Split into two patches with correct per-driver Fixes: tags
- P13: Also fix rx_buf_diallocate -> rx_buf_deallocate typo
All patches are bug fixes tagged with Fixes: and Cc: stable@dpdk.org.
Gagandeep Singh (3):
bus/dpaa: fix device probe issue
net/dpaa: fix device remove
net/dpaa: fix invalid check on interrupt unregister
Hemant Agrawal (11):
bus/dpaa: fix error handling of qman_create_fq
bus/dpaa: fix fqid endianness
bus/dpaa: fix error handling in qman_query
net/dpaa: fix modify cgr to use index
bus/dpaa: fix fd leak for ccsr mmap
net/dpaa: fix xstat name for tx undersized counter
net/dpaa: fix xstat string typos in BMI stats table
net/dpaa: remove duplicate ptype entries
net/dpaa: fix wrong buffer in xstats get by id
net/dpaa: fix null l3_len check in checksum offload
net/dpaa: fix mbuf leak in SG fd creation
Jun Yang (1):
bus/dpaa: fix BMI RX stats register offset
Prashant Gupta (1):
net/dpaa/fmlib: add null check in scheme delete
Vanshika Shukla (2):
net/dpaa: fix port_handle leak in fm_prev_cleanup
dma/dpaa: fix out-of-bounds access in SG descriptor enqueue
drivers/bus/dpaa/base/qbman/bman_driver.c | 3 ++-
drivers/bus/dpaa/base/qbman/qman.c | 11 +++++----
drivers/bus/dpaa/base/qbman/qman_driver.c | 6 ++---
drivers/bus/dpaa/dpaa_bus.c | 17 +++++++------
drivers/bus/dpaa/include/fman.h | 6 ++---
drivers/dma/dpaa/dpaa_qdma.c | 7 +++++-
drivers/net/dpaa/dpaa_ethdev.c | 29 +++++++++++------------
drivers/net/dpaa/dpaa_flow.c | 4 ++++
drivers/net/dpaa/dpaa_rxtx.c | 3 +++
drivers/net/dpaa/fmlib/fm_lib.c | 3 +++
10 files changed, 53 insertions(+), 36 deletions(-)
--
2.43.0
^ permalink raw reply
* Re: [PATCH v3 00/20] net/sxe2: added Linkdata sxe2 ethernet driver
From: Stephen Hemminger @ 2026-06-19 2:16 UTC (permalink / raw)
To: liujie5; +Cc: dev
In-Reply-To: <20260618082723.571054-1-liujie5@linkdatatechnology.com>
On Thu, 18 Jun 2026 16:27:03 +0800
liujie5@linkdatatechnology.com wrote:
> From: Jie Liu <liujie5@linkdatatechnology.com>
>
> V3:
> Remove the `drv-sw-stats` devarg
>
> Jie Liu (20):
> net/sxe2: support AVX512 vectorized path for Rx and Tx
> net/sxe2: add AVX2 vector data path for Rx and Tx
> drivers: add supported packet types and link state
> net/sxe2: support L2 filtering and MAC config
> drivers: support RSS feature
> net/sxe2: support TM hierarchy and shaping
> net/sxe2: support IPsec inline protocol offload
> net/sxe2: support statistics and multi-process
> drivers: interrupt handling
> net/sxe2: add NEON vec Rx/Tx burst functions
> drivers: add support for VF representors
> net/sxe2: add support for custom UDP tunnel ports
> net/sxe2: support firmware version reading
> net/sxe2: implement get monitor address
> common/sxe2: add shared SFP module definitions
> net/sxe2: support SFP module info and EEPROM access
> net/sxe2: implement private dump info
> net/sxe2: add mbuf validation in Tx debug mode
> drivers: add parameters parsed using rte_kvargs
> net/sxe2: update sxe2 feature matrix docs
>
> doc/guides/nics/features/sxe2.ini | 56 +
> doc/guides/nics/sxe2.rst | 132 ++
> drivers/common/sxe2/sxe2_common.c | 156 ++
> drivers/common/sxe2/sxe2_common.h | 4 +
> drivers/common/sxe2/sxe2_flow_public.h | 633 +++++++
> drivers/common/sxe2/sxe2_ioctl_chnl.c | 178 +-
> drivers/common/sxe2/sxe2_ioctl_chnl_func.h | 18 +
> drivers/common/sxe2/sxe2_msg.h | 118 ++
> drivers/net/sxe2/meson.build | 54 +-
> drivers/net/sxe2/sxe2_cmd_chnl.c | 1587 +++++++++++++++-
> drivers/net/sxe2/sxe2_cmd_chnl.h | 139 ++
> drivers/net/sxe2/sxe2_drv_cmd.h | 523 +++++-
> drivers/net/sxe2/sxe2_dump.c | 302 +++
> drivers/net/sxe2/sxe2_dump.h | 12 +
> drivers/net/sxe2/sxe2_ethdev.c | 1515 ++++++++++++++-
> drivers/net/sxe2/sxe2_ethdev.h | 110 +-
> drivers/net/sxe2/sxe2_ethdev_repr.c | 609 ++++++
> drivers/net/sxe2/sxe2_ethdev_repr.h | 32 +
> drivers/net/sxe2/sxe2_filter.c | 895 +++++++++
> drivers/net/sxe2/sxe2_filter.h | 100 +
> drivers/net/sxe2/sxe2_flow.c | 1394 ++++++++++++++
> drivers/net/sxe2/sxe2_flow.h | 30 +
> drivers/net/sxe2/sxe2_flow_define.h | 144 ++
> drivers/net/sxe2/sxe2_flow_parse_action.c | 1182 ++++++++++++
> drivers/net/sxe2/sxe2_flow_parse_action.h | 23 +
> drivers/net/sxe2/sxe2_flow_parse_engine.c | 106 ++
> drivers/net/sxe2/sxe2_flow_parse_engine.h | 13 +
> drivers/net/sxe2/sxe2_flow_parse_pattern.c | 1935 +++++++++++++++++++
> drivers/net/sxe2/sxe2_flow_parse_pattern.h | 46 +
> drivers/net/sxe2/sxe2_ipsec.c | 1565 ++++++++++++++++
> drivers/net/sxe2/sxe2_ipsec.h | 254 +++
> drivers/net/sxe2/sxe2_irq.c | 1026 ++++++++++
> drivers/net/sxe2/sxe2_irq.h | 25 +
> drivers/net/sxe2/sxe2_mac.c | 530 ++++++
> drivers/net/sxe2/sxe2_mac.h | 84 +
> drivers/net/sxe2/sxe2_mp.c | 414 ++++
> drivers/net/sxe2/sxe2_mp.h | 67 +
> drivers/net/sxe2/sxe2_queue.c | 17 +-
> drivers/net/sxe2/sxe2_queue.h | 15 +-
> drivers/net/sxe2/sxe2_rss.c | 584 ++++++
> drivers/net/sxe2/sxe2_rss.h | 81 +
> drivers/net/sxe2/sxe2_rx.c | 93 +-
> drivers/net/sxe2/sxe2_rx.h | 2 +
> drivers/net/sxe2/sxe2_security.c | 335 ++++
> drivers/net/sxe2/sxe2_security.h | 77 +
> drivers/net/sxe2/sxe2_stats.c | 586 ++++++
> drivers/net/sxe2/sxe2_stats.h | 39 +
> drivers/net/sxe2/sxe2_switchdev.c | 332 ++++
> drivers/net/sxe2/sxe2_switchdev.h | 33 +
> drivers/net/sxe2/sxe2_tm.c | 1169 ++++++++++++
> drivers/net/sxe2/sxe2_tm.h | 78 +
> drivers/net/sxe2/sxe2_tx.c | 7 +
> drivers/net/sxe2/sxe2_txrx.c | 1969 +++++++++++++++++++-
> drivers/net/sxe2/sxe2_txrx.h | 8 +
> drivers/net/sxe2/sxe2_txrx_check_mbuf.c | 595 ++++++
> drivers/net/sxe2/sxe2_txrx_check_mbuf.h | 38 +
> drivers/net/sxe2/sxe2_txrx_poll.c | 281 ++-
> drivers/net/sxe2/sxe2_txrx_vec.c | 46 +-
> drivers/net/sxe2/sxe2_txrx_vec.h | 38 +-
> drivers/net/sxe2/sxe2_txrx_vec_avx2.c | 748 ++++++++
> drivers/net/sxe2/sxe2_txrx_vec_avx512.c | 868 +++++++++
> drivers/net/sxe2/sxe2_txrx_vec_common.h | 53 +-
> drivers/net/sxe2/sxe2_txrx_vec_neon.c | 691 +++++++
> drivers/net/sxe2/sxe2_txrx_vec_sse.c | 29 +-
> drivers/net/sxe2/sxe2_vsi.c | 146 ++
> drivers/net/sxe2/sxe2_vsi.h | 12 +-
> drivers/net/sxe2/sxe2vf_regs.h | 85 +
> 67 files changed, 24800 insertions(+), 266 deletions(-)
> create mode 100644 drivers/common/sxe2/sxe2_flow_public.h
> create mode 100644 drivers/common/sxe2/sxe2_msg.h
> create mode 100644 drivers/net/sxe2/sxe2_dump.c
> create mode 100644 drivers/net/sxe2/sxe2_dump.h
> create mode 100644 drivers/net/sxe2/sxe2_ethdev_repr.c
> create mode 100644 drivers/net/sxe2/sxe2_ethdev_repr.h
> create mode 100644 drivers/net/sxe2/sxe2_filter.c
> create mode 100644 drivers/net/sxe2/sxe2_filter.h
> create mode 100644 drivers/net/sxe2/sxe2_flow.c
> create mode 100644 drivers/net/sxe2/sxe2_flow.h
> create mode 100644 drivers/net/sxe2/sxe2_flow_define.h
> create mode 100644 drivers/net/sxe2/sxe2_flow_parse_action.c
> create mode 100644 drivers/net/sxe2/sxe2_flow_parse_action.h
> create mode 100644 drivers/net/sxe2/sxe2_flow_parse_engine.c
> create mode 100644 drivers/net/sxe2/sxe2_flow_parse_engine.h
> create mode 100644 drivers/net/sxe2/sxe2_flow_parse_pattern.c
> create mode 100644 drivers/net/sxe2/sxe2_flow_parse_pattern.h
> create mode 100644 drivers/net/sxe2/sxe2_ipsec.c
> create mode 100644 drivers/net/sxe2/sxe2_ipsec.h
> create mode 100644 drivers/net/sxe2/sxe2_irq.c
> create mode 100644 drivers/net/sxe2/sxe2_mac.c
> create mode 100644 drivers/net/sxe2/sxe2_mac.h
> create mode 100644 drivers/net/sxe2/sxe2_mp.c
> create mode 100644 drivers/net/sxe2/sxe2_mp.h
> create mode 100644 drivers/net/sxe2/sxe2_rss.c
> create mode 100644 drivers/net/sxe2/sxe2_rss.h
> create mode 100644 drivers/net/sxe2/sxe2_security.c
> create mode 100644 drivers/net/sxe2/sxe2_security.h
> create mode 100644 drivers/net/sxe2/sxe2_stats.c
> create mode 100644 drivers/net/sxe2/sxe2_stats.h
> create mode 100644 drivers/net/sxe2/sxe2_switchdev.c
> create mode 100644 drivers/net/sxe2/sxe2_switchdev.h
> create mode 100644 drivers/net/sxe2/sxe2_tm.c
> create mode 100644 drivers/net/sxe2/sxe2_tm.h
> create mode 100644 drivers/net/sxe2/sxe2_txrx_check_mbuf.c
> create mode 100644 drivers/net/sxe2/sxe2_txrx_check_mbuf.h
> create mode 100644 drivers/net/sxe2/sxe2_txrx_vec_avx2.c
> create mode 100644 drivers/net/sxe2/sxe2_txrx_vec_avx512.c
> create mode 100644 drivers/net/sxe2/sxe2_txrx_vec_neon.c
> create mode 100644 drivers/net/sxe2/sxe2vf_regs.h
>
I will do manual review on next series, but could you address these things
found by redoing AI review on this version.
[PATCH v3 00/20] net/sxe2: support AVX512 vectorized path
Good news first: the atomic-operations issue raised against v2 is properly
fixed. struct sxe2_rxq_sw_stats now uses plain uint64_t, the hot-path writer
uses ordinary += increments, and the if (sw_stats_en) gating is gone -
software stats are now always-on, which is what was asked for. Verified
against the assembled tree.
The rest of v3 has problems.
[PATCH v3 01/20] - and patches 02-09 - do not build
08/20 still has `if (adapter->devargs.sw_stats_en)` at sxe2_stats.c:212,
but 01/20 removed that field from struct sxe2_devargs. The series builds
at HEAD but commits 08 through 09 fail with "struct sxe2_devargs has no
member named 'sw_stats_en'". This is the same class of break as the
SXE2_DEV_TO_PCI issue in v1: the atomic-removal cleanup was applied to
the AVX512 patch (01/20) when it logically belongs to the stats patch
(08/20), and one straggler use was missed in the rebase.
The fix is twofold:
- Move the struct field removal and the cleanup of all its uses into
08/20 ("support statistics and multi-process"), where the field is
actually about.
- Delete the SXE2_DEVARG_SW_STATS / "drv-sw-stats" devarg entirely. After
the atomic removal it has no consumer in the assembled tree - it is
defined, registered with rte_kvargs and listed in
RTE_PMD_REGISTER_PARAM_STRING, but nothing reads it. Dead code.
Please run per-commit builds before posting the next revision. Both this
break and the v1 break would have been caught by `git rebase -x "ninja
-C build" <base>`, or by devtools/test-meson-builds.sh. Two consecutive
revisions with broken bisect bands in the same series is the wrong
trend.
[PATCH v3 19/20] commit message contains LLM citation placeholders
The body has "[citation:1][citation:3][citation:5]" markers, which are
unresolved LLM output. Same shape as the "Performance shows approximately
X% improvement in small packet forwarding scenarios" placeholder in
01/20. Please rewrite both commit messages by hand.
The 19/20 commit message also describes two unrelated changes (kvargs
parsing and memseg_walk callback infrastructure). These are separate
features and should be separate patches.
Patch scope drift
The v2 review noted that 03/20 carried scope unrelated to its subject.
In v3 this got worse:
- 03/20 grew by 777 lines and now creates sxe2_txrx.c (1793 lines) under
the subject "drivers: add supported packet types and link state". Tx/Rx
framework is not the same feature as a ptype callback.
- 01/20 grew by 227 lines and now touches 13 files including
sxe2_txrx_poll.c, sxe2_queue.h, sxe2_rx.c, sxe2_txrx_vec_sse.c,
sxe2_ethdev.c/h, and meson.build. The subject is "support AVX512 vector
path"; the atomic-removal cleanup, the struct rename of
high_performance_mode to no_sched_mode, and the SSE common-code changes
do not belong under that subject.
- 19/20 touches 15 files spanning kvargs, memseg walking, tm, flow, irq,
rx, and dump. Pick one feature per patch.
Each patch should do one thing the commit message describes. The split
makes review tractable and bisect meaningful.
Devargs design - mostly unresolved from off-list discussion
Of the seven devargs, only no-sched-mode and rx-low-latency have
defensible justification. The rest need to either be removed or have
their justifications documented in sxe2.rst:
- drv-sw-stats - orphaned dead code as noted above, remove.
- flow-duplicate-pattern - default value 1 ("allow duplicate rte_flow
rules") changes the standard rte_flow contract per boot flag. The
duplicate-rule behaviour should be one fixed policy compiled into the
driver, not a runtime knob; pick one and remove the devarg.
- function-flow-direct - no documented rationale anywhere. Either
explain what cross-PMD feature this represents and why no standard API
covers it, or remove.
- fnav-stat-type - selects which set of fnav (flow-director) counters
the driver exposes. These should be xstats names the user picks at
query time, not a boot-time selection.
- sched-layer-mode - TM hierarchy depth should be inferred from the
rte_tm topology the application builds, not configured by devarg.
Propose this as an rte_tm enhancement if the standard API really
cannot express it.
Minor
In sxe2_parse_no_sched_mode() the local variable is still named
high_performance_mode - the rename did not propagate from the struct
field to the parser. Cosmetic, but the name no longer matches what the
function parses.
The earlier suggestion to convert the 469-entry runtime-initialised
ptype table into a single static const uint32_t with designated
initialisers was not addressed. Lower priority but still worth doing.
The atomics fix and the kvargs work are real progress - this revision
is much closer to mergeable than v2 was. The two essential items for v4
are: fix the build break in commits 08-09 (and run per-commit builds),
and the devargs cleanup. Patch scope and the commit-message placeholders
are secondary but should also be addressed.
Stephen Hemminger <stephen@networkplumber.org>
^ permalink raw reply
* Re: [PATCH v2 1/6] bpf/x86: fix JIT encoding of BPF_JSET with immediate
From: Stephen Hemminger @ 2026-06-19 2:09 UTC (permalink / raw)
To: dev; +Cc: stable, Konstantin Ananyev, Marat Khalili, Ferruh Yigit
In-Reply-To: <20260618210026.430288-2-stephen@networkplumber.org>
On Thu, 18 Jun 2026 13:47:05 -0700
Stephen Hemminger <stephen@networkplumber.org> wrote:
> emit_tst_imm() emits TEST (0xF7 /0) but sized the immediate with
> imm_size(), which can return 1 byte. TEST has no imm8 form; it always
> takes imm32. A small mask like BPF_JSET | BPF_K #0x1 then produced a
> 4-byte instruction the CPU decodes as 7, swallowing the following Jcc
> and crashing.
>
> Always emit a 32-bit immediate for TEST.
>
> Bugzilla ID: 1959
> Fixes: cc752e43e079 ("bpf: add JIT compilation for x86_64 ISA")
> Cc: stable@dpdk.org
>
> Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
> ---
Turns out there are two more places with similar bugs (spotted with AI review).
^ permalink raw reply
* Re: [PATCH v1 0/5] prefix lcore role enum values
From: Stephen Hemminger @ 2026-06-19 2:03 UTC (permalink / raw)
To: Morten Brørup; +Cc: Huisong Li, thomas, andrew.rybchenko, dev, zhanjie9
In-Reply-To: <98CBD80474FA8B44BF855DF32C47DC35F65917@smartserver.smartshare.dk>
On Wed, 17 Jun 2026 13:48:37 +0200
Morten Brørup <mb@smartsharesystems.com> wrote:
> > From: Huisong Li [mailto:lihuisong@huawei.com]
> > Sent: Wednesday, 17 June 2026 12.28
> >
> > Add the RTE_LCORE_ prefix to the lcore role enum values in
> > rte_lcore_role_t
> > to follow DPDK naming conventions.
> >
> > - ROLE_RTE -> RTE_LCORE_ROLE_RTE
> > - ROLE_OFF -> RTE_LCORE_ROLE_OFF
> > - ROLE_SERVICE -> RTE_LCORE_ROLE_SERVICE
> > - ROLE_NON_EAL -> RTE_LCORE_ROLE_NON_EAL
> >
> > Old names are kept as macros aliasing to the new names to preserve
> > backward compatibility.
> >
>
> Series-Acked-by: Morten Brørup <mb@smartsharesystems.com>
>
The problem with this patch it causes build failures now with abi diff.
Example build log...
2 functions with some indirect sub-type change:
[C] 'function rte_lcore_role_t rte_eal_lcore_role(unsigned int)' at eal_common_lcore.c:74:1 has some indirect sub-type changes:
return type changed:
type size hasn't changed
4 enumerator deletions:
'rte_lcore_role_t::ROLE_RTE' value '0'
'rte_lcore_role_t::ROLE_OFF' value '1'
'rte_lcore_role_t::ROLE_SERVICE' value '2'
'rte_lcore_role_t::ROLE_NON_EAL' value '3'
4 enumerator insertions:
'rte_lcore_role_t::RTE_LCORE_ROLE_RTE' value '0'
'rte_lcore_role_t::RTE_LCORE_ROLE_OFF' value '1'
'rte_lcore_role_t::RTE_LCORE_ROLE_SERVICE' value '2'
'rte_lcore_role_t::RTE_LCORE_ROLE_NON_EAL' value '3'
[C] 'function int rte_lcore_has_role(unsigned int, rte_lcore_role_t)' at eal_common_lcore.c:85:1 has some indirect sub-type changes:
parameter 2 of type 'enum rte_lcore_role_t' has sub-type changes:
enum type 'enum rte_lcore_role_t' changed at rte_lcore.h:33:1, as reported earlier
Error: ABI issue reported for abidiff --suppr /home/runner/work/dpdk/dpdk/devtools/libabigail.abignore --no-added-syms --headers-dir1 reference/usr/local/include --headers-dir2 install/usr/local/include reference/usr/local/lib/librte_eal.so.26.1 install/usr/local/lib/librte_eal.so.26.2
^ permalink raw reply
* [PATCH v2 6/6] test/bpf: check that bpf_convert can be JIT'd
From: Stephen Hemminger @ 2026-06-18 20:47 UTC (permalink / raw)
To: dev; +Cc: Stephen Hemminger, Konstantin Ananyev, Marat Khalili
In-Reply-To: <20260618210026.430288-1-stephen@networkplumber.org>
Add followup in bpf conversion tests to make sure resulting
code was also run through JIT and that JIT produces
same results as non-JIT.
Reduce log output to make it easier to match which
expression might be causing issues.
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
app/test/test_bpf.c | 94 +++++++++++++++++++++++++++++++++++++--------
1 file changed, 79 insertions(+), 15 deletions(-)
diff --git a/app/test/test_bpf.c b/app/test/test_bpf.c
index 3a88434c3c..973dd7d659 100644
--- a/app/test/test_bpf.c
+++ b/app/test/test_bpf.c
@@ -8,6 +8,7 @@
#include <inttypes.h>
#include <unistd.h>
+#include <rte_byteorder.h>
#include <rte_memory.h>
#include <rte_debug.h>
#include <rte_hexdump.h>
@@ -32,6 +33,7 @@ test_bpf(void)
#include <rte_bpf.h>
#include <rte_ether.h>
#include <rte_ip.h>
+#include <rte_udp.h>
/* Tests of most simple BPF programs (no instructions, one instruction etc.) */
@@ -4529,6 +4531,7 @@ test_bpf_match(pcap_t *pcap, const char *str,
int ret = -1;
uint64_t rc;
+ printf("%s '%s'\n", __func__, str);
if (pcap_compile(pcap, &fcode, str, 1, PCAP_NETMASK_UNKNOWN)) {
printf("%s@%d: pcap_compile(\"%s\") failed: %s;\n",
__func__, __LINE__, str, pcap_geterr(pcap));
@@ -4550,6 +4553,24 @@ test_bpf_match(pcap_t *pcap, const char *str,
}
rc = rte_bpf_exec(bpf, mb);
+#if defined(RTE_ARCH_X86_64) || defined(RTE_ARCH_ARM64)
+ {
+ struct rte_bpf_jit jit;
+
+ rte_bpf_get_jit(bpf, &jit);
+ if (jit.func == NULL) {
+ printf("%s@%d: no JIT generated\n", __func__, __LINE__);
+ goto error;
+ }
+
+ fflush(stdout);
+ uint64_t rc_jit = jit.func(mb);
+ if (rc_jit != rc) {
+ printf("%s@%d: JIT return code does not match\n", __func__, __LINE__);
+ goto error;
+ }
+ }
+#endif
/* The return code from bpf capture filter is non-zero if matched */
ret = (rc == 0);
error:
@@ -4560,23 +4581,16 @@ test_bpf_match(pcap_t *pcap, const char *str,
return ret;
}
-/* Basic sanity test can we match a IP packet */
-static int
-test_bpf_filter_sanity(pcap_t *pcap)
+/* Setup mbuf for filter test */
+static void
+dummy_ip_prep(void *data, uint16_t plen)
{
- const uint32_t plen = 100;
- struct rte_mbuf mb, *m;
- uint8_t tbuf[RTE_MBUF_DEFAULT_BUF_SIZE];
struct {
struct rte_ether_hdr eth_hdr;
struct rte_ipv4_hdr ip_hdr;
- } *hdr;
+ struct rte_udp_hdr udp_hdr;
+ } *hdr = data;
- memset(&mb, 0, sizeof(mb));
- dummy_mbuf_prep(&mb, tbuf, sizeof(tbuf), plen);
- m = &mb;
-
- hdr = rte_pktmbuf_mtod(m, typeof(hdr));
hdr->eth_hdr = (struct rte_ether_hdr) {
.dst_addr.addr_bytes = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4),
@@ -4589,13 +4603,32 @@ test_bpf_filter_sanity(pcap_t *pcap)
.src_addr = rte_cpu_to_be_32(RTE_IPV4_LOOPBACK),
.dst_addr = rte_cpu_to_be_32(RTE_IPV4_BROADCAST),
};
+ hdr->udp_hdr = (struct rte_udp_hdr) {
+ .src_port = rte_rand_max(UINT16_MAX),
+ .dst_port = rte_cpu_to_be_16(9), /* discard port */
+ .dgram_len = rte_cpu_to_be_16(plen - sizeof(struct rte_ipv4_hdr)),
+ .dgram_cksum = 0,
+ };
+}
+
+
+/* Basic sanity test can we match a IP packet */
+static int
+test_bpf_filter_sanity(pcap_t *pcap)
+{
+ struct rte_mbuf mb = { 0 };
+ uint8_t tbuf[RTE_MBUF_DEFAULT_BUF_SIZE];
+ const uint32_t plen = 100;
+
+ dummy_mbuf_prep(&mb, tbuf, sizeof(tbuf), plen);
+ dummy_ip_prep(rte_pktmbuf_mtod(&mb, void *), plen);
- if (test_bpf_match(pcap, "ip", m) != 0) {
+ if (test_bpf_match(pcap, "ip", &mb) != 0) {
printf("%s@%d: filter \"ip\" doesn't match test data\n",
__func__, __LINE__);
return -1;
}
- if (test_bpf_match(pcap, "not ip", m) == 0) {
+ if (test_bpf_match(pcap, "not ip", &mb) == 0) {
printf("%s@%d: filter \"not ip\" does match test data\n",
__func__, __LINE__);
return -1;
@@ -4648,10 +4681,15 @@ static const char * const sample_filters[] = {
static int
test_bpf_filter(pcap_t *pcap, const char *s)
{
+ struct rte_mbuf mb = { 0 };
+ uint8_t tbuf[RTE_MBUF_DEFAULT_BUF_SIZE];
+ const uint32_t plen = 100;
struct bpf_program fcode;
struct rte_bpf_prm *prm = NULL;
struct rte_bpf *bpf = NULL;
+ int ret = -1;
+ printf("%s '%s'\n", __func__, s);
if (pcap_compile(pcap, &fcode, s, 1, PCAP_NETMASK_UNKNOWN)) {
printf("%s@%d: pcap_compile('%s') failed: %s;\n",
__func__, __LINE__, s, pcap_geterr(pcap));
@@ -4665,8 +4703,10 @@ test_bpf_filter(pcap_t *pcap, const char *s)
goto error;
}
+#ifdef DEBUG
printf("bpf convert for \"%s\" produced:\n", s);
rte_bpf_dump(stdout, prm->ins, prm->nb_ins);
+#endif
bpf = rte_bpf_load(prm);
if (bpf == NULL) {
@@ -4675,6 +4715,30 @@ test_bpf_filter(pcap_t *pcap, const char *s)
goto error;
}
+ dummy_mbuf_prep(&mb, tbuf, sizeof(tbuf), plen);
+ dummy_ip_prep(rte_pktmbuf_mtod(&mb, void *), plen);
+
+ uint64_t rc = rte_bpf_exec(bpf, &mb);
+#if defined(RTE_ARCH_X86_64) || defined(RTE_ARCH_ARM64)
+ {
+ struct rte_bpf_jit jit;
+
+ rte_bpf_get_jit(bpf, &jit);
+ if (jit.func == NULL) {
+ printf("%s@%d: no JIT generated\n", __func__, __LINE__);
+ goto error;
+ }
+
+ fflush(stdout);
+ uint64_t rc_jit = jit.func(&mb);
+ if (rc_jit != rc) {
+ printf("%s@%d: JIT return code does not match\n", __func__, __LINE__);
+ goto error;
+ }
+ }
+#endif
+ ret = 0;
+
error:
if (bpf)
rte_bpf_destroy(bpf);
@@ -4685,7 +4749,7 @@ test_bpf_filter(pcap_t *pcap, const char *s)
rte_free(prm);
pcap_freecode(&fcode);
- return (bpf == NULL) ? -1 : 0;
+ return ret;
}
static int
--
2.53.0
^ permalink raw reply related
* [PATCH v2 5/6] bpf/arm64: add BPF_ABS/BPF_IND packet load support
From: Stephen Hemminger @ 2026-06-18 20:47 UTC (permalink / raw)
To: dev
Cc: Stephen Hemminger, Wathsala Vithanage, Konstantin Ananyev,
Marat Khalili
In-Reply-To: <20260618210026.430288-1-stephen@networkplumber.org>
The arm64 JIT rejected BPF_LD | BPF_ABS and BPF_LD | BPF_IND with
"invalid opcode", so cBPF programs converted by rte_bpf_convert() could
not be JITed. Add these opcodes, mirroring the x86 JIT: a fast path for
data held in the first mbuf segment, and a __rte_pktmbuf_read() slow
path for everything else.
The forward branches over the call cannot use fixed distances:
emit_call() materializes the helper address with a variable number of
mov/movk instructions, so the block sizes are not known up front. Size
the three blocks (fast path, slow path, common tail) in a dry run, then
emit for real with the branches resolved from the measured offsets.
Programs using these opcodes use the call register layout, since the
slow path makes a function call.
Bugzilla ID: 1427
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
lib/bpf/bpf_jit_arm64.c | 149 +++++++++++++++++++++++++++++++++++++++-
1 file changed, 148 insertions(+), 1 deletion(-)
diff --git a/lib/bpf/bpf_jit_arm64.c b/lib/bpf/bpf_jit_arm64.c
index 67e42015de..3fc16fd984 100644
--- a/lib/bpf/bpf_jit_arm64.c
+++ b/lib/bpf/bpf_jit_arm64.c
@@ -1125,6 +1125,135 @@ emit_branch(struct a64_jit_ctx *ctx, uint8_t op, uint32_t i, int16_t off)
emit_b_cond(ctx, ebpf_to_a64_cond(op), jump_offset_get(ctx, i, off));
}
+/* LD_ABS/LD_IND code block offsets (in arm64 instructions) */
+enum {
+ LDMB_FAST_OFS, /* fast path */
+ LDMB_SLOW_OFS, /* slow path */
+ LDMB_FIN_OFS, /* common tail */
+ LDMB_OFS_NUM
+};
+
+/*
+ * Helper for emit_ld_mbuf(): fast path.
+ * Compute the packet offset; if it lies inside the first segment leave the
+ * data pointer in R0, otherwise branch to the slow path.
+ */
+static void
+emit_ldmb_fast_path(struct a64_jit_ctx *ctx, uint8_t src, uint8_t mode,
+ uint32_t sz, int32_t imm, const uint32_t ofs[LDMB_OFS_NUM])
+{
+ uint8_t r0 = ebpf_to_a64_reg(ctx, EBPF_REG_0);
+ uint8_t r6 = ebpf_to_a64_reg(ctx, EBPF_REG_6);
+ uint8_t tmp1 = ebpf_to_a64_reg(ctx, TMP_REG_1);
+ uint8_t tmp2 = ebpf_to_a64_reg(ctx, TMP_REG_2);
+ uint8_t tmp3 = ebpf_to_a64_reg(ctx, TMP_REG_3);
+
+ /* off = imm (+ src for BPF_IND) */
+ emit_mov_imm(ctx, 1, tmp1, imm);
+ if (mode == BPF_IND)
+ emit_add(ctx, 1, tmp1, src);
+
+ /* if ((int64_t)(mbuf->data_len - off) < sz) goto slow_path */
+ emit_mov_imm(ctx, 1, tmp2, offsetof(struct rte_mbuf, data_len));
+ emit_ldr(ctx, BPF_H, tmp2, r6, tmp2);
+ emit_sub(ctx, 1, tmp2, tmp1);
+ emit_mov_imm(ctx, 1, tmp3, sz);
+ emit_cmp(ctx, 1, tmp2, tmp3);
+ emit_b_cond(ctx, A64_LT, (int32_t)(ofs[LDMB_SLOW_OFS] - ctx->idx));
+
+ /* R0 = mbuf->buf_addr + mbuf->data_off + off */
+ emit_mov_imm(ctx, 1, tmp2, offsetof(struct rte_mbuf, data_off));
+ emit_ldr(ctx, BPF_H, tmp2, r6, tmp2);
+ emit_mov_imm(ctx, 1, r0, offsetof(struct rte_mbuf, buf_addr));
+ emit_ldr(ctx, EBPF_DW, r0, r6, r0);
+ emit_add(ctx, 1, r0, tmp2);
+ emit_add(ctx, 1, r0, tmp1);
+
+ emit_b(ctx, (int32_t)(ofs[LDMB_FIN_OFS] - ctx->idx));
+}
+
+/*
+ * Helper for emit_ld_mbuf(): slow path.
+ * R0 = __rte_pktmbuf_read(mbuf, off, sz, buf); return 0 if NULL.
+ * The scratch buffer is the space reserved by __rte_bpf_validate() at the
+ * bottom of the eBPF stack frame, i.e. (frame_pointer - stack_ofs).
+ */
+static void
+emit_ldmb_slow_path(struct a64_jit_ctx *ctx, uint32_t sz, uint32_t stack_ofs)
+{
+ uint8_t r0 = ebpf_to_a64_reg(ctx, EBPF_REG_0);
+ uint8_t r6 = ebpf_to_a64_reg(ctx, EBPF_REG_6);
+ uint8_t fp = ebpf_to_a64_reg(ctx, EBPF_FP);
+ uint8_t tmp1 = ebpf_to_a64_reg(ctx, TMP_REG_1);
+
+ /* arguments of __rte_pktmbuf_read(mbuf, off, len, buf) */
+ emit_mov_64(ctx, A64_R(1), tmp1); /* off (held in tmp1) */
+ emit_mov_64(ctx, A64_R(0), r6); /* mbuf */
+ emit_mov_imm(ctx, 0, A64_R(2), sz); /* len */
+ emit_sub_imm_64(ctx, A64_R(3), fp, stack_ofs); /* buf */
+
+ emit_call(ctx, tmp1, (void *)(uintptr_t)__rte_pktmbuf_read);
+ emit_return_zero_if_src_zero(ctx, 1, r0);
+}
+
+/*
+ * Helper for emit_ld_mbuf(): common tail.
+ * Load the value pointed to by R0 and convert from network byte order.
+ */
+static void
+emit_ldmb_fin(struct a64_jit_ctx *ctx, uint8_t opsz, uint32_t sz)
+{
+ uint8_t r0 = ebpf_to_a64_reg(ctx, EBPF_REG_0);
+
+ emit_ldr(ctx, opsz, r0, r0, A64_ZR);
+ if (opsz != BPF_B)
+ emit_be(ctx, r0, sz * 8);
+}
+
+/*
+ * emit code for BPF_ABS/BPF_IND load.
+ * generates the following construction:
+ * fast_path:
+ * off = src + imm
+ * if (mbuf->data_len - off < sz)
+ * goto slow_path;
+ * ptr = mbuf->buf_addr + mbuf->data_off + off;
+ * goto fin_part;
+ * slow_path:
+ * typeof(sz) buf; // scratch space reserved on the eBPF stack
+ * ptr = __rte_pktmbuf_read(mbuf, off, sz, &buf);
+ * if (ptr == NULL)
+ * return 0;
+ * fin_part:
+ * res = *(typeof(sz))ptr;
+ * res = ntoh(res);
+ */
+static void
+emit_ld_mbuf(struct a64_jit_ctx *ctx, uint8_t op, uint8_t src, int32_t imm,
+ uint32_t stack_ofs)
+{
+ uint8_t mode = BPF_MODE(op);
+ uint8_t opsz = BPF_SIZE(op);
+ uint32_t sz = bpf_size(opsz);
+ uint32_t ofs[LDMB_OFS_NUM];
+
+ /* seed offsets so the dry-run branches stay in range */
+ ofs[LDMB_FAST_OFS] = ofs[LDMB_SLOW_OFS] = ofs[LDMB_FIN_OFS] = ctx->idx;
+
+ /* dry run to record block offsets */
+ emit_ldmb_fast_path(ctx, src, mode, sz, imm, ofs);
+ ofs[LDMB_SLOW_OFS] = ctx->idx;
+ emit_ldmb_slow_path(ctx, sz, stack_ofs);
+ ofs[LDMB_FIN_OFS] = ctx->idx;
+ emit_ldmb_fin(ctx, opsz, sz);
+
+ /* rewind and emit for real with resolved offsets */
+ ctx->idx = ofs[LDMB_FAST_OFS];
+ emit_ldmb_fast_path(ctx, src, mode, sz, imm, ofs);
+ emit_ldmb_slow_path(ctx, sz, stack_ofs);
+ emit_ldmb_fin(ctx, opsz, sz);
+}
+
static void
check_program_has_call(struct a64_jit_ctx *ctx, struct rte_bpf *bpf)
{
@@ -1137,8 +1266,17 @@ check_program_has_call(struct a64_jit_ctx *ctx, struct rte_bpf *bpf)
op = ins->code;
switch (op) {
- /* Call imm */
+ /*
+ * BPF_ABS/BPF_IND can fall through to __rte_pktmbuf_read(),
+ * so they need the call-clobbered register layout as well.
+ */
case (BPF_JMP | EBPF_CALL):
+ case (BPF_LD | BPF_ABS | BPF_B):
+ case (BPF_LD | BPF_ABS | BPF_H):
+ case (BPF_LD | BPF_ABS | BPF_W):
+ case (BPF_LD | BPF_IND | BPF_B):
+ case (BPF_LD | BPF_IND | BPF_H):
+ case (BPF_LD | BPF_IND | BPF_W):
ctx->foundcall = 1;
return;
}
@@ -1340,6 +1478,15 @@ emit(struct a64_jit_ctx *ctx, struct rte_bpf *bpf)
emit_mov_imm(ctx, 1, dst, u64);
i++;
break;
+ /* R0 = ntoh(*(size *)(mbuf data + (src) + imm)) */
+ case (BPF_LD | BPF_ABS | BPF_B):
+ case (BPF_LD | BPF_ABS | BPF_H):
+ case (BPF_LD | BPF_ABS | BPF_W):
+ case (BPF_LD | BPF_IND | BPF_B):
+ case (BPF_LD | BPF_IND | BPF_H):
+ case (BPF_LD | BPF_IND | BPF_W):
+ emit_ld_mbuf(ctx, op, src, imm, bpf->stack_sz);
+ break;
/* *(size *)(dst + off) = src */
case (BPF_STX | BPF_MEM | BPF_B):
case (BPF_STX | BPF_MEM | BPF_H):
--
2.53.0
^ permalink raw reply related
* [PATCH v2 4/6] test/bpf: check that JIT was generated
From: Stephen Hemminger @ 2026-06-18 20:47 UTC (permalink / raw)
To: dev; +Cc: Stephen Hemminger, Marat Khalili, Konstantin Ananyev
In-Reply-To: <20260618210026.430288-1-stephen@networkplumber.org>
Avoid silently ignoring JIT failures. The test cases should
all succeed JIT compilation; if not it is a bug in the JIT
implementation and should be reported.
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
Acked-by: Marat Khalili <marat.khalili@huawei.com>
---
app/test/test_bpf.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/app/test/test_bpf.c b/app/test/test_bpf.c
index e70dea736f..3a88434c3c 100644
--- a/app/test/test_bpf.c
+++ b/app/test/test_bpf.c
@@ -3590,6 +3590,14 @@ run_test(const struct bpf_test *tst)
rv, strerror(rv));
}
}
+#if defined(RTE_ARCH_X86_64) || defined(RTE_ARCH_ARM64)
+ else {
+ /* a JIT backend exists for this arch, so it must compile */
+ printf("%s@%d: %s: no JIT code generated;\n",
+ __func__, __LINE__, tst->name);
+ ret = -1;
+ }
+#endif
rte_bpf_destroy(bpf);
return ret;
--
2.53.0
^ permalink raw reply related
* [PATCH v2 3/6] bpf/arm64: fix offset type to allow a negative jump
From: Stephen Hemminger @ 2026-06-18 20:47 UTC (permalink / raw)
To: dev
Cc: Christophe Fontaine, stable, Stephen Hemminger,
Wathsala Vithanage, Konstantin Ananyev, Marat Khalili,
Jerin Jacob
In-Reply-To: <20260618210026.430288-1-stephen@networkplumber.org>
From: Christophe Fontaine <cfontain@redhat.com>
The DPDK BPF JIT standalone test test_ld_mbuf1 fails on arm64.
It does:
r6 = r1 // mbuf
r0 = *(u8 *)pkt[0] // BPF_ABS
if ((r0 & 0xf0) == 0x40)
goto parse
r0 = 0
exit // epilogue E0
parse:
r0 = *(u8 *)pkt[r0 + 3] // BPF_IND
...
exit
emit_return_zero_if_src_zero() returns 0 by branching to a function
epilogue. The target maybe a previous epilogue so branch
might be backwards; therefore the offset needs to be negative.
The offset was stored in a uint16_t, so a negative value wrapped to a
large positive number; emit_b() then branched past the end of the
program and faulted at run time.
Fixes: 111e2a747a4f ("bpf/arm: add basic arithmetic operations")
Cc: stable@dpdk.org
Signed-off-by: Christophe Fontaine <cfontain@redhat.com>
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
lib/bpf/bpf_jit_arm64.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/lib/bpf/bpf_jit_arm64.c b/lib/bpf/bpf_jit_arm64.c
index a04ef33a9c..67e42015de 100644
--- a/lib/bpf/bpf_jit_arm64.c
+++ b/lib/bpf/bpf_jit_arm64.c
@@ -957,10 +957,12 @@ static void
emit_return_zero_if_src_zero(struct a64_jit_ctx *ctx, bool is64, uint8_t src)
{
uint8_t r0 = ebpf_to_a64_reg(ctx, EBPF_REG_0);
- uint16_t jump_to_epilogue;
+ int32_t jump_to_epilogue;
emit_cbnz(ctx, is64, src, 3);
emit_mov_imm(ctx, is64, r0, 0);
+
+ /* maybe backwards branch to earlier epilogue */
jump_to_epilogue = (ctx->program_start + ctx->program_sz) - ctx->idx;
emit_b(ctx, jump_to_epilogue);
}
--
2.53.0
^ permalink raw reply related
* [PATCH v2 2/6] test/bpf: add JSET test with small immediate
From: Stephen Hemminger @ 2026-06-18 20:47 UTC (permalink / raw)
To: dev; +Cc: Stephen Hemminger, Konstantin Ananyev, Marat Khalili
In-Reply-To: <20260618210026.430288-1-stephen@networkplumber.org>
The existing jump test only used a 32-bit JSET mask,
so the broken imm8 encoding of TEST in the x86 JIT was never exercised.
Add a case with a byte-sized mask;
run_test() runs it through the interpreter and the JIT.
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
app/test/test_bpf.c | 82 +++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 82 insertions(+)
diff --git a/app/test/test_bpf.c b/app/test/test_bpf.c
index dd24722450..e70dea736f 100644
--- a/app/test/test_bpf.c
+++ b/app/test/test_bpf.c
@@ -3158,7 +3158,89 @@ static const struct ebpf_insn test_ld_mbuf3_prog[] = {
};
/* all bpf test cases */
+/*
+ * JSET with a byte-sized mask: exercises the imm8 path of the TEST
+ * encoding in the x86 JIT (a 32-bit mask takes a different path).
+ */
+static const struct ebpf_insn test_jset1_prog[] = {
+ {
+ .code = (BPF_ALU | EBPF_MOV | BPF_K),
+ .dst_reg = EBPF_REG_0,
+ .imm = 0,
+ },
+ {
+ .code = (BPF_LDX | BPF_MEM | BPF_B),
+ .dst_reg = EBPF_REG_2,
+ .src_reg = EBPF_REG_1,
+ .off = offsetof(struct dummy_offset, u8),
+ },
+ /* bit 0 is set in the input: branch is taken */
+ {
+ .code = (BPF_JMP | BPF_JSET | BPF_K),
+ .dst_reg = EBPF_REG_2,
+ .imm = 0x1,
+ .off = 1,
+ },
+ {
+ .code = (BPF_JMP | BPF_JA),
+ .off = 1,
+ },
+ {
+ .code = (EBPF_ALU64 | BPF_OR | BPF_K),
+ .dst_reg = EBPF_REG_0,
+ .imm = 0x1,
+ },
+ /* bit 1 is clear in the input: branch is not taken */
+ {
+ .code = (BPF_JMP | BPF_JSET | BPF_K),
+ .dst_reg = EBPF_REG_2,
+ .imm = 0x2,
+ .off = 1,
+ },
+ {
+ .code = (BPF_JMP | BPF_JA),
+ .off = 1,
+ },
+ {
+ .code = (EBPF_ALU64 | BPF_OR | BPF_K),
+ .dst_reg = EBPF_REG_0,
+ .imm = 0x2,
+ },
+ {
+ .code = (BPF_JMP | EBPF_EXIT),
+ },
+};
+
+static void
+test_jset1_prepare(void *arg)
+{
+ struct dummy_offset *df = arg;
+
+ memset(df, 0, sizeof(*df));
+ df->u8 = 0x1; /* bit 0 set, bit 1 clear */
+}
+
+static int
+test_jset1_check(uint64_t rc, const void *arg)
+{
+ return cmp_res(__func__, 0x1, rc, arg, arg, 0);
+}
+
static const struct bpf_test tests[] = {
+ {
+ .name = "test_jset1",
+ .arg_sz = sizeof(struct dummy_offset),
+ .prm = {
+ .ins = test_jset1_prog,
+ .nb_ins = RTE_DIM(test_jset1_prog),
+ .prog_arg = {
+ .type = RTE_BPF_ARG_PTR,
+ .size = sizeof(struct dummy_offset),
+ },
+ },
+ .prepare = test_jset1_prepare,
+ .check_result = test_jset1_check,
+ },
{
.name = "test_store1",
.arg_sz = sizeof(struct dummy_offset),
--
2.53.0
^ permalink raw reply related
* [PATCH v2 1/6] bpf/x86: fix JIT encoding of BPF_JSET with immediate
From: Stephen Hemminger @ 2026-06-18 20:47 UTC (permalink / raw)
To: dev
Cc: Stephen Hemminger, stable, Konstantin Ananyev, Marat Khalili,
Ferruh Yigit
In-Reply-To: <20260618210026.430288-1-stephen@networkplumber.org>
emit_tst_imm() emits TEST (0xF7 /0) but sized the immediate with
imm_size(), which can return 1 byte. TEST has no imm8 form; it always
takes imm32. A small mask like BPF_JSET | BPF_K #0x1 then produced a
4-byte instruction the CPU decodes as 7, swallowing the following Jcc
and crashing.
Always emit a 32-bit immediate for TEST.
Bugzilla ID: 1959
Fixes: cc752e43e079 ("bpf: add JIT compilation for x86_64 ISA")
Cc: stable@dpdk.org
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
lib/bpf/bpf_jit_x86.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/bpf/bpf_jit_x86.c b/lib/bpf/bpf_jit_x86.c
index 88b1b5aeab..0ffe3783ff 100644
--- a/lib/bpf/bpf_jit_x86.c
+++ b/lib/bpf/bpf_jit_x86.c
@@ -921,7 +921,7 @@ emit_tst_imm(struct bpf_jit_state *st, uint32_t op, uint32_t dreg, uint32_t imm)
emit_rex(st, op, 0, dreg);
emit_bytes(st, &ops, sizeof(ops));
emit_modregrm(st, MOD_DIRECT, mods, dreg);
- emit_imm(st, imm, imm_size(imm));
+ emit_imm(st, imm, sizeof(int32_t));
}
static void
--
2.53.0
^ permalink raw reply related
* [PATCH v2 0/6] bpf: JIT related bug fixes
From: Stephen Hemminger @ 2026-06-18 20:47 UTC (permalink / raw)
To: dev; +Cc: Stephen Hemminger
In-Reply-To: <20260608203322.1116296-1-stephen@networkplumber.org>
While implementing JIT for packet capture ran into several issues:
1. x86 JIT had pre-existing bug which would crash
2. ARM64 BPF JIT was missing instructions for packet access.
Which had been discovered previously [1]
3. Tests related to JIT were not being run or missing coverage.
Fixed all of these. Patches are ordered so that most urgent fix
is first, follwed by the test that should have caught the problem.
The arm64 epilogue branch fix (patch 3) was originally posted by Christophe
Fontaine [1]; that series stalled, so it is carried here with his
authorship.
Changes since v1:
- add x86 BPF_JSET encoding fix and a regression test (patches 1-2),
found once the convert test ran generated code through the JIT
- carry Christophe's arm64 epilogue fix with his sign-off (patch 3)
- convert test now runs the converted filters through the JIT, not just
loads them (patch 6)
- kept Marat's ack (patch 4)
Since tests change enough, decided to drop his ack for that part.
[1] https://inbox.dpdk.org/dev/20260319114500.9757-2-cfontain@redhat.com/
Christophe Fontaine (1):
bpf/arm64: fix offset type to allow a negative jump
Stephen Hemminger (5):
bpf/x86: fix JIT encoding of BPF_JSET with immediate
test/bpf: add JSET test with small immediate
test/bpf: check that JIT was generated
bpf/arm64: add BPF_ABS/BPF_IND packet load support
test/bpf: check that bpf_convert can be JIT'd
app/test/test_bpf.c | 184 ++++++++++++++++++++++++++++++++++++----
lib/bpf/bpf_jit_arm64.c | 153 ++++++++++++++++++++++++++++++++-
lib/bpf/bpf_jit_x86.c | 2 +-
3 files changed, 321 insertions(+), 18 deletions(-)
--
2.53.0
^ permalink raw reply
* [PATCH v2] dts: update dts check format script and resolve errors
From: Koushik Bhargav Nimoji @ 2026-06-18 20:45 UTC (permalink / raw)
To: luca.vizzarro, patrickrobb1997
Cc: dev, abailey, ahassick, lylavoie, Koushik Bhargav Nimoji
In-Reply-To: <20260609144501.1441468-1-knimoji@iol.unh.edu>
This patch updates the tool versions used in the dts-check-format.sh
script; by doing so, formatting and type hinting errors that weren't
previously visible have now appeared. This patch also resolves those
new formatting and type hinting errors.
Signed-off-by: Koushik Bhargav Nimoji <knimoji@iol.unh.edu>
---
v2:
*Fixed type hinting issues stemming from ParamSpec
issues.
*Fixed tarball write type parameter for copying
directories from one node to another.
---
dts/api/packet.py | 15 +-
dts/api/testpmd/__init__.py | 12 +-
dts/api/testpmd/types.py | 6 +-
dts/framework/config/__init__.py | 24 +-
dts/framework/config/test_run.py | 12 +-
dts/framework/context.py | 8 +-
.../interactive_remote_session.py | 2 +-
.../remote_session/interactive_shell.py | 6 +-
.../remote_session/remote_session.py | 4 +-
dts/framework/remote_session/shell_pool.py | 2 +-
dts/framework/settings.py | 8 +-
dts/framework/testbed_model/cpu.py | 2 +-
.../testbed_model/traffic_generator/scapy.py | 6 +-
.../testbed_model/traffic_generator/trex.py | 6 +-
dts/framework/utils.py | 13 +-
dts/poetry.lock | 368 ++++++++++++++----
dts/pyproject.toml | 8 +-
dts/tests/TestSuite_cryptodev_throughput.py | 4 +-
dts/tests/TestSuite_port_control.py | 3 +-
.../TestSuite_single_core_forward_perf.py | 2 +-
20 files changed, 372 insertions(+), 139 deletions(-)
diff --git a/dts/api/packet.py b/dts/api/packet.py
index 094a1b7a9d..3dda18e781 100644
--- a/dts/api/packet.py
+++ b/dts/api/packet.py
@@ -87,9 +87,9 @@ def send_packets_and_capture(
CapturingTrafficGenerator,
)
- assert isinstance(
- get_ctx().func_tg, CapturingTrafficGenerator
- ), "Cannot capture with a non-capturing traffic generator"
+ assert isinstance(get_ctx().func_tg, CapturingTrafficGenerator), (
+ "Cannot capture with a non-capturing traffic generator"
+ )
tg: CapturingTrafficGenerator = cast(CapturingTrafficGenerator, get_ctx().func_tg)
# TODO: implement @requires for types of traffic generator
packets = adjust_addresses(packets)
@@ -308,8 +308,7 @@ def _verify_l2_frame(received_packet: Ether, contains_l3: bool) -> bool:
if contains_l3:
expected_src_mac = get_ctx().topology.sut_port_egress.mac_address
log_debug(
- f"Comparing received src mac '{received_packet.src}' "
- f"with expected '{expected_src_mac}'."
+ f"Comparing received src mac '{received_packet.src}' with expected '{expected_src_mac}'."
)
if received_packet.src != expected_src_mac:
return False
@@ -344,9 +343,9 @@ def assess_performance_by_packet(
PerformanceTrafficGenerator,
)
- assert isinstance(
- get_ctx().perf_tg, PerformanceTrafficGenerator
- ), "Cannot send performance traffic with non-performance traffic generator"
+ assert isinstance(get_ctx().perf_tg, PerformanceTrafficGenerator), (
+ "Cannot send performance traffic with non-performance traffic generator"
+ )
tg: PerformanceTrafficGenerator = cast(PerformanceTrafficGenerator, get_ctx().perf_tg)
# TODO: implement @requires for types of traffic generator
return tg.calculate_traffic_and_stats(packet, duration, send_mpps)
diff --git a/dts/api/testpmd/__init__.py b/dts/api/testpmd/__init__.py
index e9187440bb..f4767c6aeb 100644
--- a/dts/api/testpmd/__init__.py
+++ b/dts/api/testpmd/__init__.py
@@ -76,7 +76,9 @@ def _requires_stopped_ports(func: TestPmdMethod) -> TestPmdMethod:
"""
@functools.wraps(func)
- def _wrapper(self: "TestPmd", *args: P.args, **kwargs: P.kwargs) -> Any:
+ def _wrapper(
+ self: "TestPmd", *args: P.args, **kwargs: P.kwargs
+ ) -> Callable[Concatenate["TestPmd", P], Any]:
if self.ports_started:
self._logger.debug("Ports need to be stopped to continue.")
self.stop_all_ports()
@@ -100,7 +102,9 @@ def _requires_started_ports(func: TestPmdMethod) -> TestPmdMethod:
"""
@functools.wraps(func)
- def _wrapper(self: "TestPmd", *args: P.args, **kwargs: P.kwargs) -> Any:
+ def _wrapper(
+ self: "TestPmd", *args: P.args, **kwargs: P.kwargs
+ ) -> Callable[Concatenate["TestPmd", P], Any]:
if not self.ports_started:
self._logger.debug("Ports need to be started to continue.")
self.start_all_ports()
@@ -128,7 +132,9 @@ def _add_remove_mtu(mtu: int = 1500) -> Callable[[TestPmdMethod], TestPmdMethod]
def decorator(func: TestPmdMethod) -> TestPmdMethod:
@functools.wraps(func)
- def wrapper(self: "TestPmd", *args: P.args, **kwargs: P.kwargs) -> Any:
+ def wrapper(
+ self: "TestPmd", *args: P.args, **kwargs: P.kwargs
+ ) -> Callable[Concatenate["TestPmd", P], Any]:
original_mtu = self.ports[0].mtu
self.set_port_mtu_all(mtu=mtu, verify=False)
retval = func(self, *args, **kwargs)
diff --git a/dts/api/testpmd/types.py b/dts/api/testpmd/types.py
index 0d322aece2..af3263682e 100644
--- a/dts/api/testpmd/types.py
+++ b/dts/api/testpmd/types.py
@@ -279,7 +279,7 @@ def from_list_string(cls, names: str) -> Self:
Returns:
An instance of this flag.
"""
- flag = cls(0)
+ flag: RSSOffloadTypesFlag = cls(0)
for name in names.split():
flag |= cls.from_str(name)
return flag
@@ -960,7 +960,7 @@ def from_list_string(cls, names: str) -> Self:
Returns:
An instance of this flag.
"""
- flag = cls(0)
+ flag: PacketOffloadFlag = cls(0)
for name in names.split():
flag |= cls.from_str(name)
return flag
@@ -1168,7 +1168,7 @@ def from_list_string(cls, names: str) -> Self:
Returns:
An instance of this flag.
"""
- flag = cls(0)
+ flag: RtePTypes = cls(0)
for name in names.split():
flag |= cls.from_str(name)
return flag
diff --git a/dts/framework/config/__init__.py b/dts/framework/config/__init__.py
index d2f0138e4a..a8861894b7 100644
--- a/dts/framework/config/__init__.py
+++ b/dts/framework/config/__init__.py
@@ -85,9 +85,9 @@ def validate_port_links(self) -> Self:
sut_node_port_peer = existing_port_links.get(
(self.test_run.system_under_test_node, link.sut_port), None
)
- assert (
- sut_node_port_peer is not None
- ), f"Invalid SUT node port specified for link port_topology.{link_idx}."
+ assert sut_node_port_peer is not None, (
+ f"Invalid SUT node port specified for link port_topology.{link_idx}."
+ )
assert sut_node_port_peer is False or sut_node_port_peer == link.right, (
f"The SUT node port for link port_topology.{link_idx} is "
@@ -97,9 +97,9 @@ def validate_port_links(self) -> Self:
tg_node_port_peer = existing_port_links.get(
(self.test_run.traffic_generator_node, link.tg_port), None
)
- assert (
- tg_node_port_peer is not None
- ), f"Invalid TG node port specified for link port_topology.{link_idx}."
+ assert tg_node_port_peer is not None, (
+ f"Invalid TG node port specified for link port_topology.{link_idx}."
+ )
assert tg_node_port_peer is False or sut_node_port_peer == link.left, (
f"The TG node port for link port_topology.{link_idx} is "
@@ -117,16 +117,16 @@ def validate_test_run_against_nodes(self) -> Self:
sut_node_name = self.test_run.system_under_test_node
sut_node = next((n for n in self.nodes if n.name == sut_node_name), None)
- assert (
- sut_node is not None
- ), f"The system_under_test_node {sut_node_name} is not a valid node name."
+ assert sut_node is not None, (
+ f"The system_under_test_node {sut_node_name} is not a valid node name."
+ )
tg_node_name = self.test_run.traffic_generator_node
tg_node = next((n for n in self.nodes if n.name == tg_node_name), None)
- assert (
- tg_node is not None
- ), f"The traffic_generator_name {tg_node_name} is not a valid node name."
+ assert tg_node is not None, (
+ f"The traffic_generator_name {tg_node_name} is not a valid node name."
+ )
return self
diff --git a/dts/framework/config/test_run.py b/dts/framework/config/test_run.py
index 76e24d1785..3cd643981d 100644
--- a/dts/framework/config/test_run.py
+++ b/dts/framework/config/test_run.py
@@ -233,9 +233,9 @@ def test_suite_spec(self) -> "TestSuiteSpec":
from framework.test_suite import find_by_name
test_suite_spec = find_by_name(self.test_suite_name)
- assert (
- test_suite_spec is not None
- ), f"{self.test_suite_name} is not a valid test suite module name."
+ assert test_suite_spec is not None, (
+ f"{self.test_suite_name} is not a valid test suite module name."
+ )
return test_suite_spec
@cached_property
@@ -384,9 +384,9 @@ def convert_from_string(cls, data: Any) -> Any:
@model_validator(mode="after")
def verify_distinct_nodes(self) -> Self:
"""Verify that each side of the link has distinct nodes."""
- assert (
- self.left.node_type != self.right.node_type
- ), "Linking ports of the same node is unsupported."
+ assert self.left.node_type != self.right.node_type, (
+ "Linking ports of the same node is unsupported."
+ )
return self
diff --git a/dts/framework/context.py b/dts/framework/context.py
index 8f1021dc96..efe9af0645 100644
--- a/dts/framework/context.py
+++ b/dts/framework/context.py
@@ -60,9 +60,9 @@ def reset(self) -> None:
else _field.default
)
- assert (
- default is not MISSING
- ), "{LocalContext.__name__} must have defaults on all fields!"
+ assert default is not MISSING, (
+ "{LocalContext.__name__} must have defaults on all fields!"
+ )
setattr(self, _field.name, default)
@@ -108,7 +108,7 @@ def filter_cores(
) -> Callable[[type["TestProtocol"]], Callable]:
"""Decorates functions that require a temporary update to the lcore specifier."""
- def decorator(func: type["TestProtocol"]) -> Callable:
+ def decorator(func: type["TestProtocol"]) -> Callable[P, type["TestProtocol"]]:
@functools.wraps(func)
def wrapper(*args: P.args, **kwargs: P.kwargs) -> Any:
local_ctx = get_ctx().local
diff --git a/dts/framework/remote_session/interactive_remote_session.py b/dts/framework/remote_session/interactive_remote_session.py
index c8156b4345..fc42e862bc 100644
--- a/dts/framework/remote_session/interactive_remote_session.py
+++ b/dts/framework/remote_session/interactive_remote_session.py
@@ -109,7 +109,7 @@ def _connect(self) -> None:
self._logger.debug(traceback.format_exc())
self._logger.warning(e)
self._logger.info(
- f"Retrying interactive session connection: retry number {retry_attempt +1}"
+ f"Retrying interactive session connection: retry number {retry_attempt + 1}"
)
else:
break
diff --git a/dts/framework/remote_session/interactive_shell.py b/dts/framework/remote_session/interactive_shell.py
index a65cbce209..6bba58a4f6 100644
--- a/dts/framework/remote_session/interactive_shell.py
+++ b/dts/framework/remote_session/interactive_shell.py
@@ -50,7 +50,9 @@
def only_active(func: InteractiveShellMethod) -> InteractiveShellMethod:
"""This decorator will skip running the method if the SSH channel is not active."""
- def _wrapper(self: "InteractiveShell", *args: P.args, **kwargs: P.kwargs) -> R | None:
+ def _wrapper(
+ self: "InteractiveShell", *args: P.args, **kwargs: P.kwargs
+ ) -> Callable[P, "InteractiveShell"] | None:
if self._ssh_channel.active:
return func(self, *args, **kwargs)
return None
@@ -167,7 +169,7 @@ def start_application(self, prompt: str | None = None, add_to_shell_pool: bool =
break
except InteractiveSSHTimeoutError:
self._logger.info(
- f"Interactive shell failed to start (attempt {attempt+1} out of "
+ f"Interactive shell failed to start (attempt {attempt + 1} out of "
f"{self._init_attempts})"
)
else:
diff --git a/dts/framework/remote_session/remote_session.py b/dts/framework/remote_session/remote_session.py
index 158325bb7f..fb5f6fedf5 100644
--- a/dts/framework/remote_session/remote_session.py
+++ b/dts/framework/remote_session/remote_session.py
@@ -72,9 +72,7 @@ def __post_init__(self, init_stdout: str, init_stderr: str) -> None:
def __str__(self) -> str:
"""Format the command outputs."""
return (
- f"stdout: '{self.stdout}'\n"
- f"stderr: '{self.stderr}'\n"
- f"return_code: '{self.return_code}'"
+ f"stdout: '{self.stdout}'\nstderr: '{self.stderr}'\nreturn_code: '{self.return_code}'"
)
diff --git a/dts/framework/remote_session/shell_pool.py b/dts/framework/remote_session/shell_pool.py
index 241737eab3..710107c6cb 100644
--- a/dts/framework/remote_session/shell_pool.py
+++ b/dts/framework/remote_session/shell_pool.py
@@ -74,7 +74,7 @@ def unregister_shell(self, shell: "InteractiveShell") -> None:
def start_new_pool(self) -> None:
"""Start a new shell pool."""
- self._logger.debug(f"Starting new shell pool and advancing to level {self.pool_level+1}.")
+ self._logger.debug(f"Starting new shell pool and advancing to level {self.pool_level + 1}.")
self._pools.append(set())
def terminate_current_pool(self) -> None:
diff --git a/dts/framework/settings.py b/dts/framework/settings.py
index b08373b7ea..f329677804 100644
--- a/dts/framework/settings.py
+++ b/dts/framework/settings.py
@@ -249,9 +249,9 @@ def error(self, message) -> NoReturn:
if _is_from_env(action):
action_name = _get_action_name(action)
env_var_name = _get_env_var_name(action)
- assert (
- env_var_name is not None
- ), "Action was set from environment, but no environment variable name was found."
+ assert env_var_name is not None, (
+ "Action was set from environment, but no environment variable name was found."
+ )
env_var_value = os.environ.get(env_var_name)
message = message.replace(
@@ -260,7 +260,7 @@ def error(self, message) -> NoReturn:
)
print(f"{self.prog}: error: {message}\n", file=sys.stderr)
- self.exit(2, "For help and usage, " "run the command with the --help flag.\n")
+ self.exit(2, "For help and usage, run the command with the --help flag.\n")
class _EnvVarHelpFormatter(ArgumentDefaultsHelpFormatter):
diff --git a/dts/framework/testbed_model/cpu.py b/dts/framework/testbed_model/cpu.py
index 6e2ecca080..a9471709dd 100644
--- a/dts/framework/testbed_model/cpu.py
+++ b/dts/framework/testbed_model/cpu.py
@@ -105,7 +105,7 @@ def __init__(self, lcore_list: list[int] | list[str] | list[LogicalCore] | str)
# the input lcores may not be sorted
self._lcore_list.sort()
- self._lcore_str = f'{",".join(self._get_consecutive_lcores_range(self._lcore_list))}'
+ self._lcore_str = f"{','.join(self._get_consecutive_lcores_range(self._lcore_list))}"
@property
def lcore_list(self) -> list[int]:
diff --git a/dts/framework/testbed_model/traffic_generator/scapy.py b/dts/framework/testbed_model/traffic_generator/scapy.py
index c6e9006205..62853a34e4 100644
--- a/dts/framework/testbed_model/traffic_generator/scapy.py
+++ b/dts/framework/testbed_model/traffic_generator/scapy.py
@@ -314,9 +314,9 @@ def __init__(self, tg_node: Node, config: ScapyTrafficGeneratorConfig, **kwargs:
kwargs: Additional keyword arguments. Supported arguments correspond to the parameters
of :meth:`PythonShell.__init__` in this case.
"""
- assert (
- tg_node.config.os == OS.linux
- ), "Linux is the only supported OS for scapy traffic generation"
+ assert tg_node.config.os == OS.linux, (
+ "Linux is the only supported OS for scapy traffic generation"
+ )
super().__init__(tg_node=tg_node, config=config, **kwargs)
diff --git a/dts/framework/testbed_model/traffic_generator/trex.py b/dts/framework/testbed_model/traffic_generator/trex.py
index 2abfbfc5ab..d53791b0a6 100644
--- a/dts/framework/testbed_model/traffic_generator/trex.py
+++ b/dts/framework/testbed_model/traffic_generator/trex.py
@@ -95,9 +95,9 @@ def __init__(self, tg_node: Node, config: TrexTrafficGeneratorConfig) -> None:
tg_node: TG node the TRex instance is operating on.
config: Traffic generator config provided for TRex instance.
"""
- assert (
- tg_node.config.os == OS.linux
- ), "Linux is the only supported OS for trex traffic generation"
+ assert tg_node.config.os == OS.linux, (
+ "Linux is the only supported OS for trex traffic generation"
+ )
super().__init__(tg_node=tg_node, config=config)
self._tg_node_config = tg_node.config
diff --git a/dts/framework/utils.py b/dts/framework/utils.py
index 9917ffbfaa..5753c1b7fe 100644
--- a/dts/framework/utils.py
+++ b/dts/framework/utils.py
@@ -21,7 +21,7 @@
import tarfile
from enum import Enum, Flag
from pathlib import Path
-from typing import Any, Callable
+from typing import Any, Callable, Literal, TypeAlias, cast
from scapy.layers.inet import IP, TCP, UDP, Ether
from scapy.packet import Packet
@@ -39,6 +39,8 @@
rf"(?:(sut|tg)\.)?({REGEX_FOR_IDENTIFIER})" # right side
)
+Tar_modes: TypeAlias = Literal["w:gz", "w:bz2", "w:xz", "w:tar"]
+
def expand_range(range_str: str) -> list[int]:
"""Process `range_str` into a list of integers.
@@ -154,7 +156,11 @@ def extension(self) -> str:
For other compression formats, the extension will be in the format
'tar.{compression format}'.
"""
- return f"{self.value}" if self == self.none else f"{type(self).none.value}.{self.value}"
+ return (
+ f"{self.value}"
+ if self == self.none
+ else f"{TarCompressionFormat.none.value}.{self.value}"
+ )
def convert_to_list_of_string(value: Any | list[Any]) -> list[str]:
@@ -207,7 +213,8 @@ def filter_func(tarinfo: tarfile.TarInfo) -> tarfile.TarInfo | None:
return None
target_tarball_path = dir_path.with_suffix(f".{compress_format.extension}")
- with tarfile.open(target_tarball_path, f"w:{compress_format.value}") as tar:
+ tarball_mode = cast(Tar_modes, f"w:{compress_format.value}")
+ with tarfile.open(target_tarball_path, tarball_mode) as tar:
tar.add(dir_path, arcname=dir_path.name, filter=create_filter_function(exclude))
return target_tarball_path
diff --git a/dts/poetry.lock b/dts/poetry.lock
index 0ad5d32b85..eda7cc2fec 100644
--- a/dts/poetry.lock
+++ b/dts/poetry.lock
@@ -1,4 +1,4 @@
-# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand.
+# This file is automatically @generated by Poetry 2.3.2 and should not be changed by hand.
[[package]]
name = "aenum"
@@ -6,6 +6,7 @@ version = "3.1.15"
description = "Advanced Enumerations (compatible with Python's stdlib Enum), NamedTuples, and NamedConstants"
optional = false
python-versions = "*"
+groups = ["main"]
files = [
{file = "aenum-3.1.15-py2-none-any.whl", hash = "sha256:27b1710b9d084de6e2e695dab78fe9f269de924b51ae2850170ee7e1ca6288a5"},
{file = "aenum-3.1.15-py3-none-any.whl", hash = "sha256:e0dfaeea4c2bd362144b87377e2c61d91958c5ed0b4daf89cb6f45ae23af6288"},
@@ -18,17 +19,62 @@ version = "0.7.0"
description = "Reusable constraint types to use with typing.Annotated"
optional = false
python-versions = ">=3.8"
+groups = ["main"]
files = [
{file = "annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"},
{file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"},
]
+[[package]]
+name = "ast-serialize"
+version = "0.5.0"
+description = "Python bindings for mypy AST serialization"
+optional = false
+python-versions = ">=3.7"
+groups = ["dev"]
+files = [
+ {file = "ast_serialize-0.5.0-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:8f5c14f169eb0972c0c21bada5358b23d6047c76583b005234f865b11f1fa00a"},
+ {file = "ast_serialize-0.5.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7d1a2de9de5be04652f0ed60738356ef94f66db37924a9499fffe98dc491aa0b"},
+ {file = "ast_serialize-0.5.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:be5173fb66f9b49026d9d5a2ff0fc7c7009077107c0eb285b2d60fdf1fe10bd1"},
+ {file = "ast_serialize-0.5.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f8015cd071ac1339924ee2b8098c93e00e155f30a16f40ec9816fcf84f4753f6"},
+ {file = "ast_serialize-0.5.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5499e8797edff2a9186aa313ed382c6b422e798e9332d9953badcee6e69a88f2"},
+ {file = "ast_serialize-0.5.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6848f2a093fb5548751a9a09bff8fcd229e2bbeb0e3331f391b6ae6d26cd9903"},
+ {file = "ast_serialize-0.5.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:832d4c998e0b091fd60a6d6bceee535483c4d490de9ba85003af835225719261"},
+ {file = "ast_serialize-0.5.0-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:16db7c62ec0b8efe1d7afd283a388d8f74f2605d56032e5a37747d2de8dba027"},
+ {file = "ast_serialize-0.5.0-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:baf5eb061eb5bccade4128ad42da33787d72f6013809cd1b590376ece8b3c937"},
+ {file = "ast_serialize-0.5.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:104e4a35bd7c124173c41760ef9aaea17ddb3f86c65cb643671d59afbe3ee94c"},
+ {file = "ast_serialize-0.5.0-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:36be371028fc1675acb38a331bde160dbab7ff907fdf00b67eb6911aa106951b"},
+ {file = "ast_serialize-0.5.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:061ee58bdb52341c8201a6df41182a977736bae3b7ded87ca7176ca25a8a47ab"},
+ {file = "ast_serialize-0.5.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:b15219e9cdc9f53f6f4cb51c009203507228226148c05c5e8fe451c28b435eb3"},
+ {file = "ast_serialize-0.5.0-cp314-cp314t-win32.whl", hash = "sha256:842d1c004bb466c7df036f95fabef789570541922b10976b12f5592a69cf0b38"},
+ {file = "ast_serialize-0.5.0-cp314-cp314t-win_amd64.whl", hash = "sha256:b0c06d760909b095cc466356dfccd05a1c7233a6ca191c020dca2c6a6f16c24c"},
+ {file = "ast_serialize-0.5.0-cp314-cp314t-win_arm64.whl", hash = "sha256:787baedb0262cc49e8ce37cc15c00ae818e46a165a3b36f5e21ed174998104cb"},
+ {file = "ast_serialize-0.5.0-cp39-abi3-macosx_10_12_x86_64.whl", hash = "sha256:0668aa9459cfa8c9c49ddd2163ebcf43088ba045ef7492af6fe22e0098303101"},
+ {file = "ast_serialize-0.5.0-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:bf683d6363edf2b39eed6b6d4fe22d34b6203867a67e27134d9e2a2680c4bc4a"},
+ {file = "ast_serialize-0.5.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9cc22cf0c9be65e71cf88fda130af60d61eb4a79370ad4cfe7900d48a4aa2211"},
+ {file = "ast_serialize-0.5.0-cp39-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f66173891548c9f2726bf27957b41cabce12fa679dc6da505ddbde4d4b3b31cf"},
+ {file = "ast_serialize-0.5.0-cp39-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e42d729ef2be96a14efbad355093284739e3670ece3e534f82cc8832790911d9"},
+ {file = "ast_serialize-0.5.0-cp39-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b725026bafa801dbd7310eb13a75f0a2e370e7e51b2cb225f9d21fcfadf919ee"},
+ {file = "ast_serialize-0.5.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b54f60c1d78767a53b67eaa663f0dfac3afe606aa07f1301572f588b73d64809"},
+ {file = "ast_serialize-0.5.0-cp39-abi3-manylinux_2_31_riscv64.whl", hash = "sha256:27d51654fc240a1e87e742d353d98eb45b75f62f129086b3596ab53df2ac2a43"},
+ {file = "ast_serialize-0.5.0-cp39-abi3-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2782c36237c46dd1674542f2109740ea5ea485a169bf1431939ada0434e17934"},
+ {file = "ast_serialize-0.5.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:1943db345233cc7194a470f13afa9c59772c0b123dea0c9414c4d4ca54369759"},
+ {file = "ast_serialize-0.5.0-cp39-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:df1c00022cbbcb064bfaa505aa9c9295362443ce5dacb459d1331d3da353f887"},
+ {file = "ast_serialize-0.5.0-cp39-abi3-musllinux_1_2_i686.whl", hash = "sha256:cae65289fc456fde04af979a2be09302ef5d8ab92ef23e596d6746dc267ada27"},
+ {file = "ast_serialize-0.5.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:239a4c354e8d676e9d94631d1d4a64edc6b266f86ff3a5a80aedd344f342c01d"},
+ {file = "ast_serialize-0.5.0-cp39-abi3-win32.whl", hash = "sha256:143a4ef63285a075871908fda3672dc21864b83a8ec3ee12304aa3e4c5387b9a"},
+ {file = "ast_serialize-0.5.0-cp39-abi3-win_amd64.whl", hash = "sha256:cf25572c526add400f26a4750dc6ce0c3bb93fc1f75e7ae0cad4ce4f2cd5c590"},
+ {file = "ast_serialize-0.5.0-cp39-abi3-win_arm64.whl", hash = "sha256:92a31c9c20d25a076edaeec76b128a3535d74a24f340b9a8a7e96c9b86dc9642"},
+ {file = "ast_serialize-0.5.0.tar.gz", hash = "sha256:5880091bfe6f4f986f22866375c2e884843e7a0b6343ae41aeea659613d879b6"},
+]
+
[[package]]
name = "bcrypt"
version = "4.2.1"
description = "Modern password hashing for your software and your servers"
optional = false
python-versions = ">=3.7"
+groups = ["main"]
files = [
{file = "bcrypt-4.2.1-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:1340411a0894b7d3ef562fb233e4b6ed58add185228650942bdc885362f32c17"},
{file = "bcrypt-4.2.1-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b1ee315739bc8387aa36ff127afc99120ee452924e0df517a8f3e4c0187a0f5f"},
@@ -67,6 +113,7 @@ version = "1.17.1"
description = "Foreign Function Interface for Python calling C code."
optional = false
python-versions = ">=3.8"
+groups = ["main", "dev"]
files = [
{file = "cffi-1.17.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:df8b1c11f177bc2313ec4b2d46baec87a5f3e71fc8b45dab2ee7cae86d9aba14"},
{file = "cffi-1.17.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8f2cdc858323644ab277e9bb925ad72ae0e67f69e804f4898c070998d50b1a67"},
@@ -136,6 +183,7 @@ files = [
{file = "cffi-1.17.1-cp39-cp39-win_amd64.whl", hash = "sha256:d016c76bdd850f3c626af19b0542c9677ba156e4ee4fccfdd7848803533ef662"},
{file = "cffi-1.17.1.tar.gz", hash = "sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824"},
]
+markers = {dev = "platform_python_implementation != \"PyPy\""}
[package.dependencies]
pycparser = "*"
@@ -146,6 +194,7 @@ version = "44.0.0"
description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers."
optional = false
python-versions = "!=3.9.0,!=3.9.1,>=3.7"
+groups = ["main", "dev"]
files = [
{file = "cryptography-44.0.0-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:84111ad4ff3f6253820e6d3e58be2cc2a00adb29335d4cacb5ab4d4d34f2a123"},
{file = "cryptography-44.0.0-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b15492a11f9e1b62ba9d73c210e2416724633167de94607ec6069ef724fad092"},
@@ -180,10 +229,10 @@ files = [
cffi = {version = ">=1.12", markers = "platform_python_implementation != \"PyPy\""}
[package.extras]
-docs = ["sphinx (>=5.3.0)", "sphinx-rtd-theme (>=3.0.0)"]
+docs = ["sphinx (>=5.3.0)", "sphinx-rtd-theme (>=3.0.0) ; python_version >= \"3.8\""]
docstest = ["pyenchant (>=3)", "readme-renderer (>=30.0)", "sphinxcontrib-spelling (>=7.3.1)"]
-nox = ["nox (>=2024.4.15)", "nox[uv] (>=2024.3.2)"]
-pep8test = ["check-sdist", "click (>=8.0.1)", "mypy (>=1.4)", "ruff (>=0.3.6)"]
+nox = ["nox (>=2024.4.15)", "nox[uv] (>=2024.3.2) ; python_version >= \"3.8\""]
+pep8test = ["check-sdist ; python_version >= \"3.8\"", "click (>=8.0.1)", "mypy (>=1.4)", "ruff (>=0.3.6)"]
sdist = ["build (>=1.0.0)"]
ssh = ["bcrypt (>=3.1.5)"]
test = ["certifi (>=2024)", "cryptography-vectors (==44.0.0)", "pretend (>=0.7)", "pytest (>=7.4.0)", "pytest-benchmark (>=4.0)", "pytest-cov (>=2.10.1)", "pytest-xdist (>=3.5.0)"]
@@ -195,6 +244,7 @@ version = "5.1.1"
description = "Decorators for Humans"
optional = false
python-versions = ">=3.5"
+groups = ["main"]
files = [
{file = "decorator-5.1.1-py3-none-any.whl", hash = "sha256:b8c3f85900b9dc423225913c5aace94729fe1fa9763b38939a95226f02d37186"},
{file = "decorator-5.1.1.tar.gz", hash = "sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330"},
@@ -206,6 +256,7 @@ version = "1.2.18"
description = "Python @deprecated decorator to deprecate old python classes, functions or methods."
optional = false
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7"
+groups = ["main"]
files = [
{file = "Deprecated-1.2.18-py2.py3-none-any.whl", hash = "sha256:bd5011788200372a32418f888e326a09ff80d0214bd961147cfed01b5c018eec"},
{file = "deprecated-1.2.18.tar.gz", hash = "sha256:422b6f6d859da6f2ef57857761bfb392480502a64c3028ca9bbe86085d72115d"},
@@ -215,7 +266,7 @@ files = [
wrapt = ">=1.10,<2"
[package.extras]
-dev = ["PyTest", "PyTest-Cov", "bump2version (<1)", "setuptools", "tox"]
+dev = ["PyTest", "PyTest-Cov", "bump2version (<1)", "setuptools ; python_version >= \"3.12\"", "tox"]
[[package]]
name = "fabric"
@@ -223,6 +274,7 @@ version = "3.2.2"
description = "High level SSH command execution"
optional = false
python-versions = "*"
+groups = ["main"]
files = [
{file = "fabric-3.2.2-py3-none-any.whl", hash = "sha256:91c47c0be68b14936c88b34da8a1f55e5710fd28397dac5d4ff2e21558113a6f"},
{file = "fabric-3.2.2.tar.gz", hash = "sha256:8783ca42e3b0076f08b26901aac6b9d9b1f19c410074e7accfab902c184ff4a3"},
@@ -243,56 +295,177 @@ version = "2.2.0"
description = "Pythonic task execution"
optional = false
python-versions = ">=3.6"
+groups = ["main"]
files = [
{file = "invoke-2.2.0-py3-none-any.whl", hash = "sha256:6ea924cc53d4f78e3d98bc436b08069a03077e6f85ad1ddaa8a116d7dad15820"},
{file = "invoke-2.2.0.tar.gz", hash = "sha256:ee6cbb101af1a859c7fe84f2a264c059020b0cb7fe3535f9424300ab568f6bd5"},
]
+[[package]]
+name = "librt"
+version = "0.11.0"
+description = "Mypyc runtime library"
+optional = false
+python-versions = ">=3.9"
+groups = ["dev"]
+markers = "platform_python_implementation != \"PyPy\""
+files = [
+ {file = "librt-0.11.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6e94ebfcfa2d5e9926d6c3b9aa4617ffc42a845b4321fb84021b872358c82a0f"},
+ {file = "librt-0.11.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ae627397a2f351560440d872d6f7c8dbb4072e57868e7b2fc5b8b430fe489d45"},
+ {file = "librt-0.11.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:dc329359321b67d24efdf4bc69012b0597001649544db662c001db5a0184794c"},
+ {file = "librt-0.11.0-cp310-cp310-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:7e82e642ab0f7608ce2fe53d76ca2280a9ee33a1b06556142c7c6fe80a86fc33"},
+ {file = "librt-0.11.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:88145c15c67731d54283d135b03244028c750cc9edc334a96a4f5950ebdb2884"},
+ {file = "librt-0.11.0-cp310-cp310-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:9d36a51b3d93320b686588e27123f4995804dbf1bce81df78c02fc3c6eea9280"},
+ {file = "librt-0.11.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d00f3ac06a2a8b246327f11e186a53a100a4d5c7ed52346367e5ec751d51586c"},
+ {file = "librt-0.11.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:461bbceede621f1ffb8839755f8663e886087ee7af16294cab7fb4d782c62eeb"},
+ {file = "librt-0.11.0-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:0cad8a4d6a8ff03c9b76f9414caccd78e7cfbc8a2e12fa334d8e1d9932753783"},
+ {file = "librt-0.11.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f37aa505b3cf60701562eddb32df74b12a9e380c207fd8b06dd157a943ac7ea0"},
+ {file = "librt-0.11.0-cp310-cp310-win32.whl", hash = "sha256:94663a21534637f0e787ec2a2a756022df6e5b7b2335a5cdd7d8e33d68a2af89"},
+ {file = "librt-0.11.0-cp310-cp310-win_amd64.whl", hash = "sha256:dec7db73758c2b54953fd8b7fe348c45188fe26b39ee18446196edd08453a5d4"},
+ {file = "librt-0.11.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:93d95bd45b7d58343d8b90d904450a545144eec19a002511163426f8ab1fae29"},
+ {file = "librt-0.11.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4ee278c769a713638cdacd4c0436d72156e75df3ebc0166ab2b9dc43acc386c9"},
+ {file = "librt-0.11.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f230cb1cbc9faaa616f9a678f530ebcf186e414b6bcbd88b960e4ba1b92428d5"},
+ {file = "librt-0.11.0-cp311-cp311-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:5d63c855d86938d9de93e265c9bd8c705b51ec494de5738340ee93767a686e4b"},
+ {file = "librt-0.11.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:993f028be9e96a08d31df3479ac80d99be374d17f3b78e4796b3fd3c913d4e89"},
+ {file = "librt-0.11.0-cp311-cp311-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:258d73a0aa66a055e65b2e4d1b8cdb23b9d132c5bb915d9547d804fcaed116cc"},
+ {file = "librt-0.11.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0827efe7854718f04aaddf6496e96960a956e676fe1d0f04eb41511fd8ad06d5"},
+ {file = "librt-0.11.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:7753e57d6e12d019c0d8786f1c09c709f4c3fcc57c3887b24e36e6c06ec938b7"},
+ {file = "librt-0.11.0-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:11bd19822431cc21af9f27374e7ae2e58103c7d98bda823536a6c47f6bb2bb3d"},
+ {file = "librt-0.11.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:22bdf239b219d3993761a148ffa134b19e52e9989c84f845d5d7b71d70a17412"},
+ {file = "librt-0.11.0-cp311-cp311-win32.whl", hash = "sha256:46c60b61e308eb535fbd6fa622b1ee1bb2815691c1ad9c98bf7b84952ec3bc8d"},
+ {file = "librt-0.11.0-cp311-cp311-win_amd64.whl", hash = "sha256:902e546ff044f579ff1c953ff5fce97b636fe9e3943996b2177710c6ef076f73"},
+ {file = "librt-0.11.0-cp311-cp311-win_arm64.whl", hash = "sha256:65ac3bc20f78aa0ee5ae84baa68917f89fef4af63e941084dd019a0d0e749f0c"},
+ {file = "librt-0.11.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b87504f1690a23b9a2cca841191a04f83895d4fc2dd04df91d82b1a04ca2ad46"},
+ {file = "librt-0.11.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40071fc5fe0ce8daa6de616702314a01e1250711682b0523d6ab8d4525910cb3"},
+ {file = "librt-0.11.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:137e79445c896a0ea7b265f52d23954e05b64222ee1af69e2cb34219067cbb67"},
+ {file = "librt-0.11.0-cp312-cp312-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:cca6644054e78746d8d4ef238681f9c34ff8b584fe6b988ecebb8db3b15e622a"},
+ {file = "librt-0.11.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d5b0eea49f5562861ee8d757a32ef7d559c1d35be2aaaa1ec28941d74c9ffc8a"},
+ {file = "librt-0.11.0-cp312-cp312-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:0d1029d7e1ae1a7e647ed6fb5df8c4ce2dffefb7a9f5fd1376a4554d96dac09f"},
+ {file = "librt-0.11.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:bc3ce6b33c5828d9e80592011a5c584cb2ce86edbc4088405f70da47dc1d1b3b"},
+ {file = "librt-0.11.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:936c5995f3514a42111f20099397d8177c79b4d7e70961e396c6f5a0a3566766"},
+ {file = "librt-0.11.0-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:9bc0ca6ad9381cbe8e4aa6e5726e4c80c78115a6e9723c599ed1d73e092bc49d"},
+ {file = "librt-0.11.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:070aa8c26c0a74774317a72df8851facc7f0f012a5b406557ac56992d92e1ec8"},
+ {file = "librt-0.11.0-cp312-cp312-win32.whl", hash = "sha256:6bf14feb84b05ae945277395451998c89c54d0def4070eb5c08de544930b245a"},
+ {file = "librt-0.11.0-cp312-cp312-win_amd64.whl", hash = "sha256:75672f0bc524ede266287d532d7923dbce94c7514ad07627bac3d0c6d92cc4d9"},
+ {file = "librt-0.11.0-cp312-cp312-win_arm64.whl", hash = "sha256:2f10cf143e4a9bb0f4f5af568a00df94a2d69ef41c2579584454bb0fe5cc642c"},
+ {file = "librt-0.11.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:78dc31f7fdfe9c9d0eb0e8f42d139db230e826415bbcabd9f0e9faaaee909894"},
+ {file = "librt-0.11.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:fa475675db22290c3158e1d42326d0f5a65f04f44a0e68c3630a25b53560fb9c"},
+ {file = "librt-0.11.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:621db29691044bdeda22e789e482e1b0f3a985d90e3426c9c6d17606416205ea"},
+ {file = "librt-0.11.0-cp313-cp313-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:a9010e2ed5b3a9e158c5fd966b3ab7e834bb3d3aacc8f66c91dd4b57a3799230"},
+ {file = "librt-0.11.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7c39513d8b7477a2e1ed8c43fc21c524e8d5a0f8d4e8b7b074dbdbe7820a08e2"},
+ {file = "librt-0.11.0-cp313-cp313-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:7aef3cf1d5af86e770ab04bfd993dfc4ae8b8c17f66fb77dd4a7d50de7bbb1a3"},
+ {file = "librt-0.11.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:557183ddc36babe46b27dd60facbd5adb4492181a5be887587d57cda6e092f21"},
+ {file = "librt-0.11.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:83d3e1f72bd42f6c5c0b7daec530c3f829bd02db42c70b8ddf0c2d90a2459930"},
+ {file = "librt-0.11.0-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:4ce1f21fbe589bc1afd7872dece84fb0e1144f794a288e58a10d2c54a55c43be"},
+ {file = "librt-0.11.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:970b09f7044ea2b64c9da42fd3d335666518cfd1c6e8a182c95da73d0214b41e"},
+ {file = "librt-0.11.0-cp313-cp313-win32.whl", hash = "sha256:78fddc31cd4d3caa897ad5d31f856b1faadc9474021ad6cb182b9018793e254e"},
+ {file = "librt-0.11.0-cp313-cp313-win_amd64.whl", hash = "sha256:8ca8aa88751a775870b764e93bad5135385f563cb8dcee399abf034ea4d3cb47"},
+ {file = "librt-0.11.0-cp313-cp313-win_arm64.whl", hash = "sha256:96f044bb325fd9cf1a723015638c219e9143f0dfbc0ca54c565df2b7fc748b44"},
+ {file = "librt-0.11.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:4a017a95e5837dc15a8c5661d60e05daa96b90908b1aa6b7acdf443cd25c8ebd"},
+ {file = "librt-0.11.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:b1ecbd9819deccc39b7542bf4d2a740d8a620694d39989e58661d3763458f8d4"},
+ {file = "librt-0.11.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7da327dacd7be8f8ec36547373550744a3cc0e536d54665cd83f8bcd961200e8"},
+ {file = "librt-0.11.0-cp314-cp314-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:0dc56b1f8d06e60db362cc3fdae206681817f86ce4725d34511473487f12a34b"},
+ {file = "librt-0.11.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:05fb8fb2ab90e21c8d12ea240d744ad514da9baf381ebfa70d91d20d21713175"},
+ {file = "librt-0.11.0-cp314-cp314-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:cae74872be221df4374d10fec61f93ed1513b9546ea84f2c0bf73ab3e9bd0b03"},
+ {file = "librt-0.11.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:32bcc918c0148eb7e3d57385125bac7e5f9e4359d05f07448b09f6f778c2f31c"},
+ {file = "librt-0.11.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:f9743fc99135d5f78d2454435615f6dec0473ca507c26ce9d92b10b562a280d3"},
+ {file = "librt-0.11.0-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:5ba067f4aadae8fda802d91d2124c90c42195ff32d9161d3549e6d05cfe26f96"},
+ {file = "librt-0.11.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:de3bf945454d032f9e390b85c4072e0a0570bf825421c8be0e71209fa65e1abe"},
+ {file = "librt-0.11.0-cp314-cp314-win32.whl", hash = "sha256:d2277a05f6dcb9fd13db9566aac4fabd68c3ea1ea46ee5567d4eef8efa495a2f"},
+ {file = "librt-0.11.0-cp314-cp314-win_amd64.whl", hash = "sha256:ab73e8db5e3f564d812c1f5c3a175930a5f9bc96ccb5e3b22a34d7858b401cf7"},
+ {file = "librt-0.11.0-cp314-cp314-win_arm64.whl", hash = "sha256:aea3caa317752e3a466fa8af45d91ee0ea8c7fdd96e42b0a8dd9b76a7931eba1"},
+ {file = "librt-0.11.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:d1b36540d7aaf9b9101b3a6f376c8d8e9f7a9aec93ed05918f2c69d493ffef72"},
+ {file = "librt-0.11.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:efbb343ab2ce3540f4ecbe6315d677ed70f37cd9a72b1e58066c918ca83acbaa"},
+ {file = "librt-0.11.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:aa0dd688aab3f7914d3e6e5e3554978e0383312fb8e771d84be008a35b9ee548"},
+ {file = "librt-0.11.0-cp314-cp314t-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:f5fb36b8c6c63fdcbb1d526d94c0d1331610d43f4118cc1beb4efef4f3faacb2"},
+ {file = "librt-0.11.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4a9a237d13addb93715b6fee74023d5ee3469b53fce527626c0e088aa585805f"},
+ {file = "librt-0.11.0-cp314-cp314t-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:5ddd17bd87b2c56ddd60e546a7984a2e64c4e8eab92fb4cf3830a48ad5469d51"},
+ {file = "librt-0.11.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:bd43992b4473d42f12ff9e68326079f0696d9d4e6000e8f39a0238d482ba6ee2"},
+ {file = "librt-0.11.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:f8e3e8056dd674e279741485e2e512d6e9a751c7455809d0114e6ebf8d781085"},
+ {file = "librt-0.11.0-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:c1f708d8ae9c56cf38a903c44297243d2ec83fd82b396b977e0144a3e76217e3"},
+ {file = "librt-0.11.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:0add982e0e7b9fc14cf4b33789d5f13f66581889b88c2f58099f6ce8f92617bd"},
+ {file = "librt-0.11.0-cp314-cp314t-win32.whl", hash = "sha256:2b481d846ac894c4e8403c5fd0e87c5d11d6499e404b474602508a224ff531c8"},
+ {file = "librt-0.11.0-cp314-cp314t-win_amd64.whl", hash = "sha256:28edb433edde181112a908c78907af28f964eabc15f4dd16c9d66c834302677c"},
+ {file = "librt-0.11.0-cp314-cp314t-win_arm64.whl", hash = "sha256:dee008f20b542e3cd162ba338a7f9ec0f6d23d395f66fe8aeeec3c9d067ea253"},
+ {file = "librt-0.11.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6bd72d903911d995ab666dbd1871f8b1e80925a699af8063fbf50053329fb05f"},
+ {file = "librt-0.11.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0ef69ac715f3cd8e5cd252cb2aebfa72c015492aacc339d5d7bf8fef3c62c677"},
+ {file = "librt-0.11.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:624a40c4a4ad7773315c287276cd024509b2c66ff5904f504bfc08d2c70293ab"},
+ {file = "librt-0.11.0-cp39-cp39-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:41dc19fe150b69716c8ece4f76773a9e8813fe3e35e032a58b4d46423fb8d7c0"},
+ {file = "librt-0.11.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4e8bd98ea9c47ae90b319a087ab28dac493f1ffbc1ecd1f28fcdbf3b7e1108d1"},
+ {file = "librt-0.11.0-cp39-cp39-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:84308fc49423ce6475d1c5d1985cd69a8ca9f0325fc7d5f81bb690a3f3625d4e"},
+ {file = "librt-0.11.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:ff0fbaf5f44a21beeb0110f2ab64f45135a9536a834b79c0d1ef018f2786bbfa"},
+ {file = "librt-0.11.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:9c028a9442a18e266955d364ce42259136e79a7ba14d773e0d778d5f70cd56f1"},
+ {file = "librt-0.11.0-cp39-cp39-musllinux_1_2_riscv64.whl", hash = "sha256:9f1692105a02bcf853f355032a5fdc5494358ef83d8fd22d16de375c85cec3f5"},
+ {file = "librt-0.11.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:7a80a71e1fda83cc752a9141e87aae7fef279538597564d670e9ce513f286192"},
+ {file = "librt-0.11.0-cp39-cp39-win32.whl", hash = "sha256:140695816ddf3c86eb972981a26f35efd871c44b0c3aed44c8cd01749386617f"},
+ {file = "librt-0.11.0-cp39-cp39-win_amd64.whl", hash = "sha256:92f7ff819c197fc30473190a12c2856f325ac90aabfccbeb2072d28cc2e234e3"},
+ {file = "librt-0.11.0.tar.gz", hash = "sha256:075dc3ef4458a278e0195cbf6ac9d38808d9b906c5a6c7f7f79c3888276a3fb1"},
+]
+
[[package]]
name = "mypy"
-version = "1.13.0"
+version = "2.1.0"
description = "Optional static typing for Python"
optional = false
-python-versions = ">=3.8"
+python-versions = ">=3.10"
+groups = ["dev"]
files = [
- {file = "mypy-1.13.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6607e0f1dd1fb7f0aca14d936d13fd19eba5e17e1cd2a14f808fa5f8f6d8f60a"},
- {file = "mypy-1.13.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8a21be69bd26fa81b1f80a61ee7ab05b076c674d9b18fb56239d72e21d9f4c80"},
- {file = "mypy-1.13.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7b2353a44d2179846a096e25691d54d59904559f4232519d420d64da6828a3a7"},
- {file = "mypy-1.13.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:0730d1c6a2739d4511dc4253f8274cdd140c55c32dfb0a4cf8b7a43f40abfa6f"},
- {file = "mypy-1.13.0-cp310-cp310-win_amd64.whl", hash = "sha256:c5fc54dbb712ff5e5a0fca797e6e0aa25726c7e72c6a5850cfd2adbc1eb0a372"},
- {file = "mypy-1.13.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:581665e6f3a8a9078f28d5502f4c334c0c8d802ef55ea0e7276a6e409bc0d82d"},
- {file = "mypy-1.13.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3ddb5b9bf82e05cc9a627e84707b528e5c7caaa1c55c69e175abb15a761cec2d"},
- {file = "mypy-1.13.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:20c7ee0bc0d5a9595c46f38beb04201f2620065a93755704e141fcac9f59db2b"},
- {file = "mypy-1.13.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3790ded76f0b34bc9c8ba4def8f919dd6a46db0f5a6610fb994fe8efdd447f73"},
- {file = "mypy-1.13.0-cp311-cp311-win_amd64.whl", hash = "sha256:51f869f4b6b538229c1d1bcc1dd7d119817206e2bc54e8e374b3dfa202defcca"},
- {file = "mypy-1.13.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:5c7051a3461ae84dfb5dd15eff5094640c61c5f22257c8b766794e6dd85e72d5"},
- {file = "mypy-1.13.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:39bb21c69a5d6342f4ce526e4584bc5c197fd20a60d14a8624d8743fffb9472e"},
- {file = "mypy-1.13.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:164f28cb9d6367439031f4c81e84d3ccaa1e19232d9d05d37cb0bd880d3f93c2"},
- {file = "mypy-1.13.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a4c1bfcdbce96ff5d96fc9b08e3831acb30dc44ab02671eca5953eadad07d6d0"},
- {file = "mypy-1.13.0-cp312-cp312-win_amd64.whl", hash = "sha256:a0affb3a79a256b4183ba09811e3577c5163ed06685e4d4b46429a271ba174d2"},
- {file = "mypy-1.13.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:a7b44178c9760ce1a43f544e595d35ed61ac2c3de306599fa59b38a6048e1aa7"},
- {file = "mypy-1.13.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:5d5092efb8516d08440e36626f0153b5006d4088c1d663d88bf79625af3d1d62"},
- {file = "mypy-1.13.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:de2904956dac40ced10931ac967ae63c5089bd498542194b436eb097a9f77bc8"},
- {file = "mypy-1.13.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:7bfd8836970d33c2105562650656b6846149374dc8ed77d98424b40b09340ba7"},
- {file = "mypy-1.13.0-cp313-cp313-win_amd64.whl", hash = "sha256:9f73dba9ec77acb86457a8fc04b5239822df0c14a082564737833d2963677dbc"},
- {file = "mypy-1.13.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:100fac22ce82925f676a734af0db922ecfea991e1d7ec0ceb1e115ebe501301a"},
- {file = "mypy-1.13.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7bcb0bb7f42a978bb323a7c88f1081d1b5dee77ca86f4100735a6f541299d8fb"},
- {file = "mypy-1.13.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bde31fc887c213e223bbfc34328070996061b0833b0a4cfec53745ed61f3519b"},
- {file = "mypy-1.13.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:07de989f89786f62b937851295ed62e51774722e5444a27cecca993fc3f9cd74"},
- {file = "mypy-1.13.0-cp38-cp38-win_amd64.whl", hash = "sha256:4bde84334fbe19bad704b3f5b78c4abd35ff1026f8ba72b29de70dda0916beb6"},
- {file = "mypy-1.13.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:0246bcb1b5de7f08f2826451abd947bf656945209b140d16ed317f65a17dc7dc"},
- {file = "mypy-1.13.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:7f5b7deae912cf8b77e990b9280f170381fdfbddf61b4ef80927edd813163732"},
- {file = "mypy-1.13.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7029881ec6ffb8bc233a4fa364736789582c738217b133f1b55967115288a2bc"},
- {file = "mypy-1.13.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:3e38b980e5681f28f033f3be86b099a247b13c491f14bb8b1e1e134d23bb599d"},
- {file = "mypy-1.13.0-cp39-cp39-win_amd64.whl", hash = "sha256:a6789be98a2017c912ae6ccb77ea553bbaf13d27605d2ca20a76dfbced631b24"},
- {file = "mypy-1.13.0-py3-none-any.whl", hash = "sha256:9c250883f9fd81d212e0952c92dbfcc96fc237f4b7c92f56ac81fd48460b3e5a"},
- {file = "mypy-1.13.0.tar.gz", hash = "sha256:0291a61b6fbf3e6673e3405cfcc0e7650bebc7939659fdca2702958038bd835e"},
+ {file = "mypy-2.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:11a6beb180257a805961aea9ec591bbd0bd17f1e18d35b8456d57aee5bedfedc"},
+ {file = "mypy-2.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8ef78c1d306bbf9a8a12f526c44902c9c28dffd6c52c52bf6a72641ce18d3849"},
+ {file = "mypy-2.1.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c209a90853081ff01d01ee895cafe10f7db1474e0d95beaeef0f6c1db9119bbd"},
+ {file = "mypy-2.1.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:47cebf61abde7c088a4e27718a8b13a81655686b2e9c251f5c0915a802248166"},
+ {file = "mypy-2.1.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:d57a90ae5e872138a425ec328edbc9b235d1934c4377881a33ec05b341acc9a8"},
+ {file = "mypy-2.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:aea7f7a8a55b459c34275fc468ada6ca7c173a5e43a68f5dbe588a563d8a06b8"},
+ {file = "mypy-2.1.0-cp310-cp310-win_arm64.whl", hash = "sha256:c989640253f0d76843e9c6c1bbf4bd48c5e85ada61bde4beb37cb3eca035685e"},
+ {file = "mypy-2.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a683016b16fe2f572dc04c72be7ee0504ac1605a265d0200f5cea695fb788f41"},
+ {file = "mypy-2.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1a293c534adb55271fef24a26da04b855540a8c13cc07bc5917b9fd2c394f2ca"},
+ {file = "mypy-2.1.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7406f4d048e71e576f5356d317e5b0a9e666dfd966bd99f9d14ca06e1a341538"},
+ {file = "mypy-2.1.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e0210d626fc8b31ccc90233754c7bc90e1f43205e85d96387f7db1285b55c398"},
+ {file = "mypy-2.1.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:3712c20deed54e814eaaa825603bada8ea1c390670a397c95b98405347acc563"},
+ {file = "mypy-2.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:fcaa0e479066e31f7cceb6a3bea39cb22b2ff51a6b2f24f193d19179ba17c389"},
+ {file = "mypy-2.1.0-cp311-cp311-win_arm64.whl", hash = "sha256:0b1a5260c95aa443083f9ed3592662941951bca3d4ca224a5dc517c38b7cf666"},
+ {file = "mypy-2.1.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:244358bf1c0da7722230bce60683d52e8e9fd030554926f15b747a84efb5b3af"},
+ {file = "mypy-2.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4ec7c57657493c7a75534df2751c8ae2cda383c16ecc55d2106c54476b1b16f6"},
+ {file = "mypy-2.1.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d8161b6ff4392410023224f0969d17db93e1e154bc3e4ba62598e720723ae211"},
+ {file = "mypy-2.1.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bf03e12003084a67395184d3eb8cbd6a489dc3655b5664b28c210a9e2403ab0b"},
+ {file = "mypy-2.1.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:20509760fd791c51579d573153407d226385ec1f8bcce55d730b354f3336bc22"},
+ {file = "mypy-2.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:6753d0c1fdd6b1a23b9e4f283ce80b2153b724adcb2653b20b85a8a28ac6436b"},
+ {file = "mypy-2.1.0-cp312-cp312-win_arm64.whl", hash = "sha256:98ebb6589bb3b6d0c6f0c459d53ca55b8091fbc13d277c4041c885392e8195e8"},
+ {file = "mypy-2.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:35aac3bb114e03888f535d5eb51b8bafbb3266586b599da1940f9b1be3ec5bd5"},
+ {file = "mypy-2.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:8de55a8c861f2a49331f807be98d90caeceeef520bde13d43a160207f8af613e"},
+ {file = "mypy-2.1.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5fdf2941a07434af755837d9880f7d7d25f1dacb1af9dcd4b9b66f2220a3024e"},
+ {file = "mypy-2.1.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e195b817c13f02352a9c124301f9f30f078405444679b6753c1b96b6eed37285"},
+ {file = "mypy-2.1.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5431d42af987ebd92ba2f71d45c85ed41d8e6ca9f5fd209a69f68f707d2469e5"},
+ {file = "mypy-2.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:767fe8c66dc3e01e19e1737d4c38ebefead16125e1b8e58ad421903b376f5c65"},
+ {file = "mypy-2.1.0-cp313-cp313-win_arm64.whl", hash = "sha256:ecfe70d43775ab99562ab128ce49854a362044c9f894961f68f898c23cb7429d"},
+ {file = "mypy-2.1.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:7354c5a7f69d9345c3d6e69921d57088eea3ddeeb6b20d34c1b3855b02c36ec2"},
+ {file = "mypy-2.1.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:49890d4f76ac9e06ec117f9e09f3174da70a620a0c300953d8595c926e80947f"},
+ {file = "mypy-2.1.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:761be68e023ef5d94678772396a8af1220030f80837a3afd8d0aef3b419666f4"},
+ {file = "mypy-2.1.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c90345fc182dc363b891350457ec69c35140858538f38b4540845afcc32b1aef"},
+ {file = "mypy-2.1.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:b84802e7b5a6daf1f5e15bc9fcd7ddae77be13981ffab037f1c67bb84d67d135"},
+ {file = "mypy-2.1.0-cp314-cp314-win_amd64.whl", hash = "sha256:022c771234936ceac541ebaf836fe9e2abeb3f5e09aff21588fe543ff006fe21"},
+ {file = "mypy-2.1.0-cp314-cp314-win_arm64.whl", hash = "sha256:498207db725cec88829a6a5c2fc771205fd043719ef98bc49aba8fb9fc4e6d57"},
+ {file = "mypy-2.1.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:7d5e5cad0efeba72b93cd17490cc0d69c5ac9ca132994fe3fb0314808aeeb83e"},
+ {file = "mypy-2.1.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:ff715050c127d724fd260a2e666e7747fdd83511c0c47d449d98238970aef780"},
+ {file = "mypy-2.1.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:82208da9e09414d520e912d3e462d454854bed0810b71540bb016dcbca7308fd"},
+ {file = "mypy-2.1.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e79ebc1b904b84f0310dff7469655a9c36c7a68bddb37bdd42b67a332df61d08"},
+ {file = "mypy-2.1.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:e583edc957cfb0deb142079162ae826f58449b116c1d442f2d91c69d9fced081"},
+ {file = "mypy-2.1.0-cp314-cp314t-win_amd64.whl", hash = "sha256:b33b6cd332695bba180d55e717a79d3038e479a2c49cc5eb3d53603409b9a5d7"},
+ {file = "mypy-2.1.0-cp314-cp314t-win_arm64.whl", hash = "sha256:4f910fe825376a7b66ef7ca8c98e5a149e8cd64c19ae71d84047a74ee060d4e6"},
+ {file = "mypy-2.1.0-py3-none-any.whl", hash = "sha256:a663814603a5c563fb87a4f96fb473eeb30d1f5a4885afcf44f9db000a366289"},
+ {file = "mypy-2.1.0.tar.gz", hash = "sha256:81e76ad12c2d804512e9b13240d1588316531bfba07558286078bfbce9613633"},
]
[package.dependencies]
-mypy-extensions = ">=1.0.0"
+ast-serialize = ">=0.3.0,<1.0.0"
+librt = {version = ">=0.11.0", markers = "platform_python_implementation != \"PyPy\""}
+mypy_extensions = ">=1.0.0"
+pathspec = ">=1.0.0"
tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""}
-typing-extensions = ">=4.6.0"
+typing_extensions = [
+ {version = ">=4.6.0", markers = "python_version < \"3.15\""},
+ {version = ">=4.14.0", markers = "python_version >= \"3.15\""},
+]
[package.extras]
dmypy = ["psutil (>=4.0)"]
@@ -307,6 +480,7 @@ version = "1.0.0"
description = "Type system extensions for programs checked with the mypy type checker."
optional = false
python-versions = ">=3.5"
+groups = ["dev"]
files = [
{file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"},
{file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"},
@@ -318,6 +492,7 @@ version = "3.5.0"
description = "SSH2 protocol library"
optional = false
python-versions = ">=3.6"
+groups = ["main"]
files = [
{file = "paramiko-3.5.0-py3-none-any.whl", hash = "sha256:1fedf06b085359051cd7d0d270cebe19e755a8a921cc2ddbfa647fb0cd7d68f9"},
{file = "paramiko-3.5.0.tar.gz", hash = "sha256:ad11e540da4f55cedda52931f1a3f812a8238a7af7f62a60de538cd80bb28124"},
@@ -329,20 +504,39 @@ cryptography = ">=3.3"
pynacl = ">=1.5"
[package.extras]
-all = ["gssapi (>=1.4.1)", "invoke (>=2.0)", "pyasn1 (>=0.1.7)", "pywin32 (>=2.1.8)"]
-gssapi = ["gssapi (>=1.4.1)", "pyasn1 (>=0.1.7)", "pywin32 (>=2.1.8)"]
+all = ["gssapi (>=1.4.1) ; platform_system != \"Windows\"", "invoke (>=2.0)", "pyasn1 (>=0.1.7)", "pywin32 (>=2.1.8) ; platform_system == \"Windows\""]
+gssapi = ["gssapi (>=1.4.1) ; platform_system != \"Windows\"", "pyasn1 (>=0.1.7)", "pywin32 (>=2.1.8) ; platform_system == \"Windows\""]
invoke = ["invoke (>=2.0)"]
+[[package]]
+name = "pathspec"
+version = "1.1.1"
+description = "Utility library for gitignore style pattern matching of file paths."
+optional = false
+python-versions = ">=3.9"
+groups = ["dev"]
+files = [
+ {file = "pathspec-1.1.1-py3-none-any.whl", hash = "sha256:a00ce642f577bf7f473932318056212bc4f8bfdf53128c78bbd5af0b9b20b189"},
+ {file = "pathspec-1.1.1.tar.gz", hash = "sha256:17db5ecd524104a120e173814c90367a96a98d07c45b2e10c2f3919fff91bf5a"},
+]
+
+[package.extras]
+hyperscan = ["hyperscan (>=0.7)"]
+optional = ["typing-extensions (>=4)"]
+re2 = ["google-re2 (>=1.1)"]
+
[[package]]
name = "pycparser"
version = "2.22"
description = "C parser in Python"
optional = false
python-versions = ">=3.8"
+groups = ["main", "dev"]
files = [
{file = "pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc"},
{file = "pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6"},
]
+markers = {dev = "platform_python_implementation != \"PyPy\""}
[[package]]
name = "pydantic"
@@ -350,6 +544,7 @@ version = "2.10.3"
description = "Data validation using Python type hints"
optional = false
python-versions = ">=3.8"
+groups = ["main"]
files = [
{file = "pydantic-2.10.3-py3-none-any.whl", hash = "sha256:be04d85bbc7b65651c5f8e6b9976ed9c6f41782a55524cef079a34a0bb82144d"},
{file = "pydantic-2.10.3.tar.gz", hash = "sha256:cb5ac360ce894ceacd69c403187900a02c4b20b693a9dd1d643e1effab9eadf9"},
@@ -362,7 +557,7 @@ typing-extensions = ">=4.12.2"
[package.extras]
email = ["email-validator (>=2.0.0)"]
-timezone = ["tzdata"]
+timezone = ["tzdata ; python_version >= \"3.9\" and platform_system == \"Windows\""]
[[package]]
name = "pydantic-core"
@@ -370,6 +565,7 @@ version = "2.27.1"
description = "Core functionality for Pydantic validation and serialization"
optional = false
python-versions = ">=3.8"
+groups = ["main"]
files = [
{file = "pydantic_core-2.27.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:71a5e35c75c021aaf400ac048dacc855f000bdfed91614b4a726f7432f1f3d6a"},
{file = "pydantic_core-2.27.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f82d068a2d6ecfc6e054726080af69a6764a10015467d7d7b9f66d6ed5afa23b"},
@@ -482,6 +678,7 @@ version = "1.5.0"
description = "Python binding to the Networking and Cryptography (NaCl) library"
optional = false
python-versions = ">=3.6"
+groups = ["main"]
files = [
{file = "PyNaCl-1.5.0-cp36-abi3-macosx_10_10_universal2.whl", hash = "sha256:401002a4aaa07c9414132aaed7f6836ff98f59277a234704ff66878c2ee4a0d1"},
{file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:52cb72a79269189d4e0dc537556f4740f7f0a9ec41c1322598799b0bdad4ef92"},
@@ -508,6 +705,7 @@ version = "6.0.2"
description = "YAML parser and emitter for Python"
optional = false
python-versions = ">=3.8"
+groups = ["main"]
files = [
{file = "PyYAML-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086"},
{file = "PyYAML-6.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf"},
@@ -566,29 +764,30 @@ files = [
[[package]]
name = "ruff"
-version = "0.8.2"
+version = "0.15.16"
description = "An extremely fast Python linter and code formatter, written in Rust."
optional = false
python-versions = ">=3.7"
+groups = ["dev"]
files = [
- {file = "ruff-0.8.2-py3-none-linux_armv6l.whl", hash = "sha256:c49ab4da37e7c457105aadfd2725e24305ff9bc908487a9bf8d548c6dad8bb3d"},
- {file = "ruff-0.8.2-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:ec016beb69ac16be416c435828be702ee694c0d722505f9c1f35e1b9c0cc1bf5"},
- {file = "ruff-0.8.2-py3-none-macosx_11_0_arm64.whl", hash = "sha256:f05cdf8d050b30e2ba55c9b09330b51f9f97d36d4673213679b965d25a785f3c"},
- {file = "ruff-0.8.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:60f578c11feb1d3d257b2fb043ddb47501ab4816e7e221fbb0077f0d5d4e7b6f"},
- {file = "ruff-0.8.2-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:cbd5cf9b0ae8f30eebc7b360171bd50f59ab29d39f06a670b3e4501a36ba5897"},
- {file = "ruff-0.8.2-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b402ddee3d777683de60ff76da801fa7e5e8a71038f57ee53e903afbcefdaa58"},
- {file = "ruff-0.8.2-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:705832cd7d85605cb7858d8a13d75993c8f3ef1397b0831289109e953d833d29"},
- {file = "ruff-0.8.2-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:32096b41aaf7a5cc095fa45b4167b890e4c8d3fd217603f3634c92a541de7248"},
- {file = "ruff-0.8.2-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e769083da9439508833cfc7c23e351e1809e67f47c50248250ce1ac52c21fb93"},
- {file = "ruff-0.8.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5fe716592ae8a376c2673fdfc1f5c0c193a6d0411f90a496863c99cd9e2ae25d"},
- {file = "ruff-0.8.2-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:81c148825277e737493242b44c5388a300584d73d5774defa9245aaef55448b0"},
- {file = "ruff-0.8.2-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:d261d7850c8367704874847d95febc698a950bf061c9475d4a8b7689adc4f7fa"},
- {file = "ruff-0.8.2-py3-none-musllinux_1_2_i686.whl", hash = "sha256:1ca4e3a87496dc07d2427b7dd7ffa88a1e597c28dad65ae6433ecb9f2e4f022f"},
- {file = "ruff-0.8.2-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:729850feed82ef2440aa27946ab39c18cb4a8889c1128a6d589ffa028ddcfc22"},
- {file = "ruff-0.8.2-py3-none-win32.whl", hash = "sha256:ac42caaa0411d6a7d9594363294416e0e48fc1279e1b0e948391695db2b3d5b1"},
- {file = "ruff-0.8.2-py3-none-win_amd64.whl", hash = "sha256:2aae99ec70abf43372612a838d97bfe77d45146254568d94926e8ed5bbb409ea"},
- {file = "ruff-0.8.2-py3-none-win_arm64.whl", hash = "sha256:fb88e2a506b70cfbc2de6fae6681c4f944f7dd5f2fe87233a7233d888bad73e8"},
- {file = "ruff-0.8.2.tar.gz", hash = "sha256:b84f4f414dda8ac7f75075c1fa0b905ac0ff25361f42e6d5da681a465e0f78e5"},
+ {file = "ruff-0.15.16-py3-none-linux_armv6l.whl", hash = "sha256:6ac3c0b3969cc6cf6b158c4e2f8f682acb58e7d700d8a44b65ecdc72d66ab0b2"},
+ {file = "ruff-0.15.16-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:197c207ed75ffba54a0dec23db4aa939a27a3053073e085e0042433cbdc58e4a"},
+ {file = "ruff-0.15.16-py3-none-macosx_11_0_arm64.whl", hash = "sha256:3a39fec45ab316cc23e7558f23fea4a70403ddb5648ea9a4a3854a16973d0071"},
+ {file = "ruff-0.15.16-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ba93191d79003116b95128c9d306e045200fdbd0bccb782b110f3cd1d4abc5cf"},
+ {file = "ruff-0.15.16-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c6ee4b90520630120ef032aa5cc10db483852dff950e78b1d717e2993a61ac8d"},
+ {file = "ruff-0.15.16-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4e4215bc938bc3c8215c1472c1aa437e310fee20cd427335fec9d7e609563628"},
+ {file = "ruff-0.15.16-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7c8d26be963b090f10e29abc8b3e74a2a321f6fa34e02424e30b5af89350ecbb"},
+ {file = "ruff-0.15.16-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f198cf4123602a2280ed46c307bcbafe41758d6fee5b456b6b6058ca1514b3b4"},
+ {file = "ruff-0.15.16-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bb27515fa6240fb586ae82b901a59e67d24acff86f2190b433dc542fe0435aeb"},
+ {file = "ruff-0.15.16-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:a267c46ba1593fc26b8eecbea050b39d40c0b6bb7781ee11c90a02cd10032951"},
+ {file = "ruff-0.15.16-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:528c68f39a91498a8d50e91ff5985df3d105782bab49cc378e73ac26bff083e8"},
+ {file = "ruff-0.15.16-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:7ed55c58950df60589a9a7a5d2f8fa5f54ebd287163be805adfe6ee95a9de123"},
+ {file = "ruff-0.15.16-py3-none-musllinux_1_2_i686.whl", hash = "sha256:d482feaf51512b50f9790ceb417a56a61dd1e9d9bf967662b9ed27c01b34f53a"},
+ {file = "ruff-0.15.16-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:1e15bc8c94513dae2a40cc9ef07c94fdd4ecc9e29dabebeebe170f952322c9e3"},
+ {file = "ruff-0.15.16-py3-none-win32.whl", hash = "sha256:580378f7bd4aa25f72e74aa54948a9622f142b1e509521dd10902e886681cc1e"},
+ {file = "ruff-0.15.16-py3-none-win_amd64.whl", hash = "sha256:408256017284eddf98fff77b29aa4fb30f586042d535b2d9befc6512f400aaec"},
+ {file = "ruff-0.15.16-py3-none-win_arm64.whl", hash = "sha256:8cd61783afb39638a7133ef0d2dfb1e91277593962f81b5a8423eb0b888a6121"},
+ {file = "ruff-0.15.16.tar.gz", hash = "sha256:d05e78d38c78caf020b03789e25106c93017db5a0cb6e2819885018c61343b78"},
]
[[package]]
@@ -597,6 +796,7 @@ version = "2.6.1"
description = "Scapy: interactive packet manipulation tool"
optional = false
python-versions = "<4,>=3.7"
+groups = ["main"]
files = [
{file = "scapy-2.6.1-py3-none-any.whl", hash = "sha256:88a998572049b511a1f3e44f4aa7c62dd39c6ea2aa1bb58434f503956641789d"},
{file = "scapy-2.6.1.tar.gz", hash = "sha256:7600d7e2383c853e5c3a6e05d37e17643beebf2b3e10d7914dffcc3bc3c6e6c5"},
@@ -613,6 +813,7 @@ version = "0.10.2"
description = "Python Library for Tom's Obvious, Minimal Language"
optional = false
python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
+groups = ["dev"]
files = [
{file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"},
{file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"},
@@ -624,6 +825,8 @@ version = "2.2.1"
description = "A lil' TOML parser"
optional = false
python-versions = ">=3.8"
+groups = ["dev"]
+markers = "python_version == \"3.10\""
files = [
{file = "tomli-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249"},
{file = "tomli-2.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6"},
@@ -665,6 +868,7 @@ version = "2.0.0.10"
description = "Typing stubs for invoke"
optional = false
python-versions = ">=3.7"
+groups = ["dev"]
files = [
{file = "types-invoke-2.0.0.10.tar.gz", hash = "sha256:a54d7ecdc19e0c22cd2786ef2e64c2631715c78eba8a1bf40b511d0608f33a88"},
{file = "types_invoke-2.0.0.10-py3-none-any.whl", hash = "sha256:2404e4279601fa96e14ef68321fd10a660a828677aabdcaeef6a5189778084ef"},
@@ -672,13 +876,14 @@ files = [
[[package]]
name = "types-paramiko"
-version = "3.5.0.20240928"
+version = "4.0.0.20260518"
description = "Typing stubs for paramiko"
optional = false
-python-versions = ">=3.8"
+python-versions = ">=3.10"
+groups = ["dev"]
files = [
- {file = "types-paramiko-3.5.0.20240928.tar.gz", hash = "sha256:79dd9b2ee510b76a3b60d8ac1f3f348c45fcecf01347ca79e14db726bbfc442d"},
- {file = "types_paramiko-3.5.0.20240928-py3-none-any.whl", hash = "sha256:cda0aff4905fe8efe4b5448331a80e943d42a796bd4beb77a3eed3485bc96a85"},
+ {file = "types_paramiko-4.0.0.20260518-py3-none-any.whl", hash = "sha256:0ffaf1a6eb796833a49653cba4c7be13af51c8269d75234972d6239763dda270"},
+ {file = "types_paramiko-4.0.0.20260518.tar.gz", hash = "sha256:286f6830945cba63797eedf375ed87138d93198121253afe66c5d6dbcf91318d"},
]
[package.dependencies]
@@ -686,13 +891,14 @@ cryptography = ">=37.0.0"
[[package]]
name = "types-pyyaml"
-version = "6.0.12.20240917"
+version = "6.0.12.20260518"
description = "Typing stubs for PyYAML"
optional = false
-python-versions = ">=3.8"
+python-versions = ">=3.10"
+groups = ["dev"]
files = [
- {file = "types-PyYAML-6.0.12.20240917.tar.gz", hash = "sha256:d1405a86f9576682234ef83bcb4e6fff7c9305c8b1fbad5e0bcd4f7dbdc9c587"},
- {file = "types_PyYAML-6.0.12.20240917-py3-none-any.whl", hash = "sha256:392b267f1c0fe6022952462bf5d6523f31e37f6cea49b14cee7ad634b6301570"},
+ {file = "types_pyyaml-6.0.12.20260518-py3-none-any.whl", hash = "sha256:d2150f75a231c9fe9c7463bd29487d93e60bac90400287351384bc2284eba7cd"},
+ {file = "types_pyyaml-6.0.12.20260518.tar.gz", hash = "sha256:d917f83fb38462550338c1297faedd860b3ec83912b96b1e3d73255f7473e466"},
]
[[package]]
@@ -701,17 +907,33 @@ version = "4.12.2"
description = "Backported and Experimental Type Hints for Python 3.8+"
optional = false
python-versions = ">=3.8"
+groups = ["main", "dev"]
+markers = "python_version < \"3.15\""
files = [
{file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"},
{file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"},
]
+[[package]]
+name = "typing-extensions"
+version = "4.15.0"
+description = "Backported and Experimental Type Hints for Python 3.9+"
+optional = false
+python-versions = ">=3.9"
+groups = ["main", "dev"]
+markers = "python_version >= \"3.15\""
+files = [
+ {file = "typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548"},
+ {file = "typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466"},
+]
+
[[package]]
name = "wrapt"
version = "1.17.2"
description = "Module for decorators, wrappers and monkey patching."
optional = false
python-versions = ">=3.8"
+groups = ["main"]
files = [
{file = "wrapt-1.17.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:3d57c572081fed831ad2d26fd430d565b76aa277ed1d30ff4d40670b1c0dd984"},
{file = "wrapt-1.17.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b5e251054542ae57ac7f3fba5d10bfff615b6c2fb09abeb37d2f1463f841ae22"},
@@ -795,6 +1017,6 @@ files = [
]
[metadata]
-lock-version = "2.0"
+lock-version = "2.1"
python-versions = "^3.10"
-content-hash = "aa6dff54827602c89ee125019291965de50d7a471ca48add889ea23aa5fd9b2f"
+content-hash = "1ca3cdf5bf98c528845b5e22169322db8912fe437988635f4ebea088b2079463"
diff --git a/dts/pyproject.toml b/dts/pyproject.toml
index 8b061c3cee..b639af65b6 100644
--- a/dts/pyproject.toml
+++ b/dts/pyproject.toml
@@ -28,12 +28,12 @@ aenum = "^3.1.15"
pydantic = "^2.9.2"
[tool.poetry.group.dev.dependencies]
-mypy = "^1.13.0"
+mypy = "^2.1.0"
toml = "^0.10.2"
-ruff = "^0.8.1"
-types-paramiko = "^3.5.0.20240928"
+ruff = "^0.15.16"
+types-paramiko = "^4.0.0.20260518"
types-invoke = "^2.0.0.10"
-types-pyyaml = "^6.0.12.20240917"
+types-pyyaml = "^6.0.12.20260518"
[build-system]
requires = ["poetry-core>=1.0.0"]
diff --git a/dts/tests/TestSuite_cryptodev_throughput.py b/dts/tests/TestSuite_cryptodev_throughput.py
index af0a5680ab..2fc0d8779a 100644
--- a/dts/tests/TestSuite_cryptodev_throughput.py
+++ b/dts/tests/TestSuite_cryptodev_throughput.py
@@ -101,12 +101,12 @@ def _print_stats(self, test_vals: list[dict[str, int | float | str]]) -> None:
print(f"{'Throughput Results'.center(border_len)}\n{'=' * border_len}")
for k, v in test_vals[0].items():
print(f"|{k.title():<{element_len}}", end="")
- print(f"|\n{'='*border_len}")
+ print(f"|\n{'=' * border_len}")
for test_val in test_vals:
for k, v in test_val.items():
print(f"|{v:<{element_len}}", end="")
- print(f"|\n{'='*border_len}")
+ print(f"|\n{'=' * border_len}")
def _verify_throughput(
self,
diff --git a/dts/tests/TestSuite_port_control.py b/dts/tests/TestSuite_port_control.py
index 6be47838d0..b51fdc2959 100644
--- a/dts/tests/TestSuite_port_control.py
+++ b/dts/tests/TestSuite_port_control.py
@@ -44,8 +44,7 @@ def _send_packets_and_verify(self) -> None:
recv_pakts = [
p
for p in recv_pakts
- if
- (
+ if (
# Remove padding from the bytes.
hasattr(p, "load") and p.load.decode("utf-8").replace("\x00", "") == payload
)
diff --git a/dts/tests/TestSuite_single_core_forward_perf.py b/dts/tests/TestSuite_single_core_forward_perf.py
index 1e7ab7b036..acdf8ae2f6 100644
--- a/dts/tests/TestSuite_single_core_forward_perf.py
+++ b/dts/tests/TestSuite_single_core_forward_perf.py
@@ -144,7 +144,7 @@ def single_core_forward_perf(self) -> None:
for params in self.test_parameters:
verify(
params["pass"] is True,
- f"""Packets forwarded is less than {(1 -self.delta_tolerance)*100}%
+ f"""Packets forwarded is less than {(1 - self.delta_tolerance) * 100}%
of the expected baseline.
Measured MPPS = {params["measured_mpps"]}
Expected MPPS = {params["expected_mpps"]}""",
--
2.54.0
^ permalink raw reply related
* Re: [PATCH] examples/ptp_tap_relay_sw: forbid shadowed variables
From: Stephen Hemminger @ 2026-06-18 20:05 UTC (permalink / raw)
To: Thomas Monjalon; +Cc: dev, Rajesh Kumar
In-Reply-To: <20260618142526.191340-1-thomas@monjalon.net>
On Thu, 18 Jun 2026 16:25:26 +0200
Thomas Monjalon <thomas@monjalon.net> wrote:
> By removing the compilation flag no_shadow_cflag,
> it becomes forbidden to shadow a variable.
>
> Signed-off-by: Thomas Monjalon <thomas@monjalon.net>
> ---
Thanks, example did not exist when the first pass was done.
Acked-by: Stephen Hemminger <stephen@networkplumber.org>
^ permalink raw reply
* [DPDK/core Bug 1959] BPF JIT produces bad code
From: bugzilla @ 2026-06-18 19:52 UTC (permalink / raw)
To: dev
http://bugs.dpdk.org/show_bug.cgi?id=1959
Bug ID: 1959
Summary: BPF JIT produces bad code
Product: DPDK
Version: 22.03
Hardware: All
OS: All
Status: UNCONFIRMED
Severity: major
Priority: Normal
Component: core
Assignee: dev@dpdk.org
Reporter: stephen@networkplumber.org
Target Milestone: ---
While testing bpf convert code for capture; discovered that the following BPF
instructions are JIT'd in a way that causes a SEGV when executed.
bpf convert for "ether[0] & 1 = 0 and ip[16] >= 224" produced:
cBPF program (8 insns)
(000) ldb [0]
(001) jset #0x1 jt 7 jf 2
(002) ldh [12]
(003) jeq #0x800 jt 4 jf 7
(004) ldb [30]
(005) jge #0xe0 jt 6 jf 7
(006) ret #262144
(007) ret #0
eBPF program (14 insns)
L0: xor r0, r0
L1: xor r7, r7
L2: mov r6, r1
L3: ldb r0, [0]
L4: jset r0, #0x1, L12
L5: ldh r0, [12]
L6: jne r0, #0x800, L12
L7: ldb r0, [30]
L8: jge r0, #0xe0, L10
L9: ja L12
L10: mov32 r0, #0x40000
L11: exit
L12: mov32 r0, #0x0
L13: exit
JIT code at [0x7fb6dbebf000], len=340
00000000: 48 83 EC 18 48 89 5C 24 00 4C 89 6C 24 08 48 89 | H...H.\$.L.l$.H.
00000010: 6C 24 10 48 89 E5 48 83 EC 08 48 83 E4 F0 48 31 | l$.H..H...H...H1
00000020: C0 4D 31 ED 48 89 FB 48 31 F6 48 0F B7 53 28 48 | .M1.H..H1.H..S(H
00000030: 29 F2 48 83 FA 01 7C 11 48 0F B7 53 10 48 8B 43 | ).H...|.H..S.H.C
00000040: 00 48 01 D0 48 01 F0 EB 26 48 C7 C2 01 00 00 00 | .H..H...&H......
00000050: 48 89 E9 48 83 E9 08 48 89 DF 48 B8 30 7E C6 A5 | H..H...H..H.0~..
00000060: 01 56 00 00 FF D0 48 85 C0 0F 84 CA 00 00 00 48 | .V....H........H
00000070: 0F B6 40 00 48 F7 C0 01 0F 85 D2 00 00 00 48 C7 | ..@.H.........H.
00000080: C6 0C 00 00 00 48 0F B7 53 28 48 29 F2 48 83 FA | .....H..S(H).H..
00000090: 02 7C 11 48 0F B7 53 10 48 8B 43 00 48 01 D0 48 | .|.H..S.H.C.H..H
000000A0: 01 F0 EB 22 48 C7 C2 02 00 00 00 48 89 E9 48 83 | ..."H......H..H.
000000B0: E9 08 48 89 DF 48 B8 30 7E C6 A5 01 56 00 00 FF | ..H..H.0~...V...
000000C0: D0 48 85 C0 74 73 48 0F B7 40 00 66 C1 C8 08 0F | .H..tsH..@.f....
000000D0: B7 C0 48 81 F8 00 08 00 00 75 75 48 C7 C6 1E 00 | ..H......uuH....
000000E0: 00 00 48 0F B7 53 28 48 29 F2 48 83 FA 01 7C 11 | ..H..S(H).H...|.
000000F0: 48 0F B7 53 10 48 8B 43 00 48 01 D0 48 01 F0 EB | H..S.H.C.H..H...
00000100: 22 48 C7 C2 01 00 00 00 48 89 E9 48 83 E9 08 48 | "H......H..H...H
00000110: 89 DF 48 B8 30 7E C6 A5 01 56 00 00 FF D0 48 85 | ..H.0~...V....H.
00000120: C0 74 16 48 0F B6 40 00 48 81 F8 E0 00 00 00 73 | .t.H..@.H......s
00000130: 02 EB 1D C7 C0 00 00 04 00 48 89 EC 48 8B 5C 24 | .........H..H.\$
00000140: 00 4C 8B 6C 24 08 48 8B 6C 24 10 48 83 C4 18 C3 | .L.l$.H.l$.H....
00000150: 31 C0 EB E5 | 1...
Segmentation fault DPDK_TEST=bpf_convert_autotest ./build/app/dpdk-test
--
You are receiving this mail because:
You are the assignee for the bug.
^ permalink raw reply
* Re: [PATCH] examples: Fix vm_power_manager scratch area to /run/dpdk/powermonitor
From: Sudheendra S @ 2026-06-18 19:24 UTC (permalink / raw)
To: Bruce Richardson
Cc: Stephen Hemminger, dev@dpdk.org, Anatoly Burakov,
Sivaprasad Tummala
In-Reply-To: <ahm4Qr5gLBf6sxof@bricha3-mobl1.ger.corp.intel.com>
[-- Attachment #1: Type: text/plain, Size: 4160 bytes --]
*Note: Changed subject line from /run/dpdk/powermanager ->
/run/dpdk/powermonitor*
Hi All,
Apologies for the delay.
So, I am following the above thread and below are what I understand are the
changes that are needed :
1. I see that rte_eal_get_runtime_dir() is RTE_EXPORTED_SYMBOL. I will
verify that channel_manager has access to this symbol.
2. Upon successful creation of /run/dpdk, I can mkdir
CHANNEL_MGR_SOCKET_PATH (/var/run/dpdk/powermonitor) and opendir() that for
subsequent processing.
3. Fixup the documentation to reflect correct powermonitor path
Please let me know if I am missing anything or if I misinterpreting any
part of the email exchange.
Thanks for all your help and support.
-Sudheendra G Sampath
On Fri, May 29, 2026 at 9:01 AM Bruce Richardson <bruce.richardson@intel.com>
wrote:
> On Fri, May 29, 2026 at 08:23:24AM -0700, Stephen Hemminger wrote:
> > On Fri, 29 May 2026 09:01:34 +0100
> > Bruce Richardson <bruce.richardson@intel.com> wrote:
> >
> > > On Thu, May 28, 2026 at 07:04:48PM +0000, Sudheendra Sampath wrote:
> > > > This patch for bug 1832 will do the following:
> > > > 1. If /run/dpdk is not present, it will create it first with and
> > > > then create powermanager directory underneath it.
> > > > 2. If /run/dpdk is present, it will verify it is actually a
> directory
> > > > before creating subdirectory, powermanager.
> > > >
> > > I would suggest using $XDG_RUNTIME_DIR for the directory path, rather
> than
> > > hardcoding it by default. If XDG_RUNTIME_DIR is not set, then maybe
> > > consider using /run/dpdk. However, rather than /run/dpdk, I'd suggest
> using
> > > the normal runtime dir path on most distros as the default:
> > > /run/user/<uid>.
> > >
> > > /Bruce
> >
> > The login in EAL is a little more detailed.
> > The choice is from systemd conventions which follows filesystem
> hierarchy.
> >
> >
> > int eal_create_runtime_dir(void)
> > {
> > const char *directory;
> > char run_dir[PATH_MAX];
> > char tmp[PATH_MAX];
> > int ret;
> >
> > /* from RuntimeDirectory= see systemd.exec */
> > directory = getenv("RUNTIME_DIRECTORY");
> > if (directory == NULL) {
> > /*
> > * Used standard convention defined in
> > * XDG Base Directory Specification and
> > * Filesystem Hierarchy Standard.
> > */
> > if (getuid() == 0)
> > directory = "/var/run";
> > else
> > directory = getenv("XDG_RUNTIME_DIR") ? : "/tmp";
> > }
> >
> > /* create DPDK subdirectory under runtime dir */
> > ret = snprintf(tmp, sizeof(tmp), "%s/dpdk", directory);
> > if (ret < 0 || ret == sizeof(tmp)) {
> > EAL_LOG(ERR, "Error creating DPDK runtime path name");
> > return -1;
> > }
> >
> > /* create prefix-specific subdirectory under DPDK runtime dir */
> > ret = snprintf(run_dir, sizeof(run_dir), "%s/%s",
> > tmp, eal_get_hugefile_prefix());
> > if (ret < 0 || ret == sizeof(run_dir)) {
> > EAL_LOG(ERR, "Error creating prefix-specific runtime path
> name");
> > return -1;
> > }
> >
> > /* create the path if it doesn't exist. no "mkdir -p" here, so do
> it
> > * step by step.
> > */
> > ret = mkdir(tmp, 0700);
> > if (ret < 0 && errno != EEXIST) {
> > EAL_LOG(ERR, "Error creating '%s': %s",
> > tmp, strerror(errno));
> > return -1;
> > }
> >
> > ret = mkdir(run_dir, 0700);
> > if (ret < 0 && errno != EEXIST) {
> > EAL_LOG(ERR, "Error creating '%s': %s",
> > run_dir, strerror(errno));
> > return -1;
> > }
>
> Yes. Can the power manager call the rte_eal_get_runtime_dir() API and use
> that as a basis for its working directory? Save duplicating all this logic.
>
> /Bruce
>
[-- Attachment #2: Type: text/html, Size: 5594 bytes --]
^ permalink raw reply
* Re: [PATCH v2 2/2] dts: add build arguments to test run configuration
From: Koushik Bhargav Nimoji @ 2026-06-18 18:59 UTC (permalink / raw)
To: luca.vizzarro, patrickrobb1997; +Cc: dev, abailey, ahassick, lylavoie
In-Reply-To: <20260609143647.1434076-2-knimoji@iol.unh.edu>
[-- Attachment #1: Type: text/plain, Size: 6479 bytes --]
Recheck-request: github-robot: build
On Tue, Jun 9, 2026 at 10:36 AM Koushik Bhargav Nimoji <knimoji@iol.unh.edu>
wrote:
> This patch adds the ability to specify build arguments when building DPDK
> through DTS. Doing so allows users to build DPDK with the desired build
> arguments, which allows for a more configurable DTS run.
>
> Signed-off-by: Koushik Bhargav Nimoji <knimoji@iol.unh.edu>
> ---
> dts/configurations/test_run.example.yaml | 13 +++++++++++++
> dts/framework/config/test_run.py | 2 ++
> dts/framework/remote_session/dpdk.py | 12 ++++++++----
> dts/framework/utils.py | 21 ++++++++++++++++++++-
> 4 files changed, 43 insertions(+), 5 deletions(-)
>
> diff --git a/dts/configurations/test_run.example.yaml
> b/dts/configurations/test_run.example.yaml
> index ee641f5dce..0bd5151801 100644
> --- a/dts/configurations/test_run.example.yaml
> +++ b/dts/configurations/test_run.example.yaml
> @@ -16,6 +16,8 @@
> # `precompiled_build_dir` or `build_options` can be defined, but
> not both.
> # `compiler_wrapper`:
> # Optional, adds a compiler wrapper if present.
> +# `build_args`:
> +# The additional build arguments to be used when building DPDK.
> # `func_traffic_generator` & `perf_traffic_generator`:
> # Define `func_traffic_generator` when `func` set to true.
> # Define `perf_traffic_generator` when `perf` set to true.
> @@ -40,6 +42,17 @@ dpdk:
> # the combination of the following two makes CC="ccache gcc"
> compiler: gcc
> compiler_wrapper: ccache # see `Optional Fields`
> + # arguments to be used when building DPDK
> + # build_args:
> + # c_args:
> + # - O3
> + # - g
> + # b_coverage:
> + # - "true"
> + # buildtype:
> + # - release
> + # flags:
> + # - strip
> func_traffic_generator:
> type: SCAPY
> # perf_traffic_generator:
> diff --git a/dts/framework/config/test_run.py
> b/dts/framework/config/test_run.py
> index 76e24d1785..eab12041fc 100644
> --- a/dts/framework/config/test_run.py
> +++ b/dts/framework/config/test_run.py
> @@ -191,6 +191,8 @@ class DPDKBuildOptionsConfiguration(FrozenModel):
> #: This string will be put in front of the compiler when executing
> the build. Useful for adding
> #: wrapper commands, such as ``ccache``.
> compiler_wrapper: str = ""
> + #: The build arguments to build dpdk with
> + build_args: dict[str, list[str]] = {}
>
>
> class DPDKUncompiledBuildConfiguration(BaseDPDKBuildConfiguration):
> diff --git a/dts/framework/remote_session/dpdk.py
> b/dts/framework/remote_session/dpdk.py
> index 865f97f6ca..4dc0ceeaaf 100644
> --- a/dts/framework/remote_session/dpdk.py
> +++ b/dts/framework/remote_session/dpdk.py
> @@ -100,8 +100,8 @@ def setup(self) -> None:
> match self.config:
> case
> DPDKPrecompiledBuildConfiguration(precompiled_build_dir=build_dir):
> self._set_remote_dpdk_build_dir(build_dir)
> - case
> DPDKUncompiledBuildConfiguration(build_options=build_options):
> - self._configure_dpdk_build(build_options)
> + case DPDKUncompiledBuildConfiguration():
> + self._configure_dpdk_build(self.config.build_options)
> self._build_dpdk()
>
> def teardown(self) -> None:
> @@ -277,16 +277,20 @@ def _build_dpdk(self) -> None:
> `remote_dpdk_tree_path` has already been set on the SUT node.
> """
> ctx = get_ctx()
> + build_options = getattr(self.config, "build_options")
> # If the SUT is an ice driver device, make sure to build with 16B
> descriptors.
> if (
> ctx.topology.sut_port_ingress
> and ctx.topology.sut_port_ingress.config.os_driver == "ice"
> ):
> meson_args = MesonArgs(
> - default_library="static", libdir="lib",
> c_args="-DRTE_NET_INTEL_USE_16BYTE_DESC"
> + build_options.build_args,
> + default_library="static",
> + libdir="lib",
> + c_args="-DRTE_NET_INTEL_USE_16BYTE_DESC",
> )
> else:
> - meson_args = MesonArgs(default_library="static", libdir="lib")
> + meson_args = MesonArgs(build_options.build_args,
> default_library="static", libdir="lib")
>
> if SETTINGS.code_coverage:
> meson_args._add_arg("-Db_coverage=true")
> diff --git a/dts/framework/utils.py b/dts/framework/utils.py
> index 38da88cd9c..e0ed35066c 100644
> --- a/dts/framework/utils.py
> +++ b/dts/framework/utils.py
> @@ -99,10 +99,16 @@ class MesonArgs:
>
> _default_library: str
>
> - def __init__(self, default_library: str | None = None, **dpdk_args:
> str | bool):
> + def __init__(
> + self,
> + dpdk_build_args: dict[str, list[str]],
> + default_library: str | None = None,
> + **dpdk_args: str | bool,
> + ):
> """Initialize the meson arguments.
>
> Args:
> + dpdk_build_args: The DPDK build arguments specified in the
> test run configuration file.
> default_library: The default library type, Meson supports
> ``shared``, ``static`` and
> ``both``. Defaults to :data:`None`, in which case the
> argument won't be used.
> dpdk_args: The arguments found in ``meson_options.txt`` in
> root DPDK directory.
> @@ -121,6 +127,19 @@ def __init__(self, default_library: str | None =
> None, **dpdk_args: str | bool):
> )
> )
>
> + arguments = []
> + for option, value in dpdk_build_args.items():
> + if option == "c_args":
> + values = " ".join(f"-{val}" for val in value)
> + arguments.append(f'-D{option}="{values}"')
> + elif option == "flags":
> + values = " ".join(f"--{val}" for val in value)
> + arguments.append(values)
> + else:
> + arguments.append(f" -D{option}={value[0]}")
> +
> + self._dpdk_args = " ".join(arguments)
> +
> def __str__(self) -> str:
> """The actual args."""
> return " ".join(f"{self._default_library}
> {self._dpdk_args}".split())
> --
> 2.54.0
>
>
[-- Attachment #2: Type: text/html, Size: 8042 bytes --]
^ permalink raw reply
* Re: [PATCH v1] dts: update dts check format script and resolve errors
From: Koushik Bhargav Nimoji @ 2026-06-18 18:59 UTC (permalink / raw)
To: luca.vizzarro, patrickrobb1997; +Cc: abailey, ahassick, lylavoie, dev
In-Reply-To: <20260609144501.1441468-1-knimoji@iol.unh.edu>
[-- Attachment #1: Type: text/plain, Size: 80962 bytes --]
Recheck-request: github-robot: build
On Tue, Jun 9, 2026 at 10:45 AM Koushik Bhargav Nimoji <knimoji@iol.unh.edu>
wrote:
> This patch updates the tool versions used in the dts-check-format.sh
> script;by doing so, formatting and type hinting errors that weren't
> previously visible have now appeared. This patch also resolves those
> new formatting and type hinting errors.
>
> Signed-off-by: Koushik Bhargav Nimoji <knimoji@iol.unh.edu>
> ---
> dts/api/packet.py | 15 +-
> dts/api/testpmd/__init__.py | 12 +-
> dts/api/testpmd/types.py | 6 +-
> dts/framework/config/__init__.py | 24 +-
> dts/framework/config/test_run.py | 12 +-
> dts/framework/context.py | 8 +-
> .../interactive_remote_session.py | 2 +-
> .../remote_session/interactive_shell.py | 6 +-
> .../remote_session/remote_session.py | 4 +-
> dts/framework/remote_session/shell_pool.py | 2 +-
> dts/framework/settings.py | 8 +-
> dts/framework/testbed_model/cpu.py | 2 +-
> .../testbed_model/traffic_generator/scapy.py | 6 +-
> .../testbed_model/traffic_generator/trex.py | 6 +-
> dts/framework/utils.py | 9 +-
> dts/poetry.lock | 368 ++++++++++++++----
> dts/pyproject.toml | 8 +-
> dts/tests/TestSuite_cryptodev_throughput.py | 4 +-
> dts/tests/TestSuite_port_control.py | 3 +-
> .../TestSuite_single_core_forward_perf.py | 2 +-
> 20 files changed, 369 insertions(+), 138 deletions(-)
>
> diff --git a/dts/api/packet.py b/dts/api/packet.py
> index 094a1b7a9d..3dda18e781 100644
> --- a/dts/api/packet.py
> +++ b/dts/api/packet.py
> @@ -87,9 +87,9 @@ def send_packets_and_capture(
> CapturingTrafficGenerator,
> )
>
> - assert isinstance(
> - get_ctx().func_tg, CapturingTrafficGenerator
> - ), "Cannot capture with a non-capturing traffic generator"
> + assert isinstance(get_ctx().func_tg, CapturingTrafficGenerator), (
> + "Cannot capture with a non-capturing traffic generator"
> + )
> tg: CapturingTrafficGenerator = cast(CapturingTrafficGenerator,
> get_ctx().func_tg)
> # TODO: implement @requires for types of traffic generator
> packets = adjust_addresses(packets)
> @@ -308,8 +308,7 @@ def _verify_l2_frame(received_packet: Ether,
> contains_l3: bool) -> bool:
> if contains_l3:
> expected_src_mac = get_ctx().topology.sut_port_egress.mac_address
> log_debug(
> - f"Comparing received src mac '{received_packet.src}' "
> - f"with expected '{expected_src_mac}'."
> + f"Comparing received src mac '{received_packet.src}' with
> expected '{expected_src_mac}'."
> )
> if received_packet.src != expected_src_mac:
> return False
> @@ -344,9 +343,9 @@ def assess_performance_by_packet(
> PerformanceTrafficGenerator,
> )
>
> - assert isinstance(
> - get_ctx().perf_tg, PerformanceTrafficGenerator
> - ), "Cannot send performance traffic with non-performance traffic
> generator"
> + assert isinstance(get_ctx().perf_tg, PerformanceTrafficGenerator), (
> + "Cannot send performance traffic with non-performance traffic
> generator"
> + )
> tg: PerformanceTrafficGenerator = cast(PerformanceTrafficGenerator,
> get_ctx().perf_tg)
> # TODO: implement @requires for types of traffic generator
> return tg.calculate_traffic_and_stats(packet, duration, send_mpps)
> diff --git a/dts/api/testpmd/__init__.py b/dts/api/testpmd/__init__.py
> index e9187440bb..1bde66d876 100644
> --- a/dts/api/testpmd/__init__.py
> +++ b/dts/api/testpmd/__init__.py
> @@ -76,7 +76,9 @@ def _requires_stopped_ports(func: TestPmdMethod) ->
> TestPmdMethod:
> """
>
> @functools.wraps(func)
> - def _wrapper(self: "TestPmd", *args: P.args, **kwargs: P.kwargs) ->
> Any:
> + def _wrapper(
> + self: "TestPmd", *args: P.args, **kwargs: P.kwargs
> + ) -> Callable[P, "TestPmd"] | Any:
> if self.ports_started:
> self._logger.debug("Ports need to be stopped to continue.")
> self.stop_all_ports()
> @@ -100,7 +102,9 @@ def _requires_started_ports(func: TestPmdMethod) ->
> TestPmdMethod:
> """
>
> @functools.wraps(func)
> - def _wrapper(self: "TestPmd", *args: P.args, **kwargs: P.kwargs) ->
> Any:
> + def _wrapper(
> + self: "TestPmd", *args: P.args, **kwargs: P.kwargs
> + ) -> Callable[P, "TestPmd"] | Any:
> if not self.ports_started:
> self._logger.debug("Ports need to be started to continue.")
> self.start_all_ports()
> @@ -128,7 +132,9 @@ def _add_remove_mtu(mtu: int = 1500) ->
> Callable[[TestPmdMethod], TestPmdMethod]
>
> def decorator(func: TestPmdMethod) -> TestPmdMethod:
> @functools.wraps(func)
> - def wrapper(self: "TestPmd", *args: P.args, **kwargs: P.kwargs)
> -> Any:
> + def wrapper(
> + self: "TestPmd", *args: P.args, **kwargs: P.kwargs
> + ) -> Callable[P, TestPmd] | Any:
> original_mtu = self.ports[0].mtu
> self.set_port_mtu_all(mtu=mtu, verify=False)
> retval = func(self, *args, **kwargs)
> diff --git a/dts/api/testpmd/types.py b/dts/api/testpmd/types.py
> index 0d322aece2..af3263682e 100644
> --- a/dts/api/testpmd/types.py
> +++ b/dts/api/testpmd/types.py
> @@ -279,7 +279,7 @@ def from_list_string(cls, names: str) -> Self:
> Returns:
> An instance of this flag.
> """
> - flag = cls(0)
> + flag: RSSOffloadTypesFlag = cls(0)
> for name in names.split():
> flag |= cls.from_str(name)
> return flag
> @@ -960,7 +960,7 @@ def from_list_string(cls, names: str) -> Self:
> Returns:
> An instance of this flag.
> """
> - flag = cls(0)
> + flag: PacketOffloadFlag = cls(0)
> for name in names.split():
> flag |= cls.from_str(name)
> return flag
> @@ -1168,7 +1168,7 @@ def from_list_string(cls, names: str) -> Self:
> Returns:
> An instance of this flag.
> """
> - flag = cls(0)
> + flag: RtePTypes = cls(0)
> for name in names.split():
> flag |= cls.from_str(name)
> return flag
> diff --git a/dts/framework/config/__init__.py
> b/dts/framework/config/__init__.py
> index d2f0138e4a..a8861894b7 100644
> --- a/dts/framework/config/__init__.py
> +++ b/dts/framework/config/__init__.py
> @@ -85,9 +85,9 @@ def validate_port_links(self) -> Self:
> sut_node_port_peer = existing_port_links.get(
> (self.test_run.system_under_test_node, link.sut_port),
> None
> )
> - assert (
> - sut_node_port_peer is not None
> - ), f"Invalid SUT node port specified for link
> port_topology.{link_idx}."
> + assert sut_node_port_peer is not None, (
> + f"Invalid SUT node port specified for link
> port_topology.{link_idx}."
> + )
>
> assert sut_node_port_peer is False or sut_node_port_peer ==
> link.right, (
> f"The SUT node port for link port_topology.{link_idx} is "
> @@ -97,9 +97,9 @@ def validate_port_links(self) -> Self:
> tg_node_port_peer = existing_port_links.get(
> (self.test_run.traffic_generator_node, link.tg_port), None
> )
> - assert (
> - tg_node_port_peer is not None
> - ), f"Invalid TG node port specified for link
> port_topology.{link_idx}."
> + assert tg_node_port_peer is not None, (
> + f"Invalid TG node port specified for link
> port_topology.{link_idx}."
> + )
>
> assert tg_node_port_peer is False or sut_node_port_peer ==
> link.left, (
> f"The TG node port for link port_topology.{link_idx} is "
> @@ -117,16 +117,16 @@ def validate_test_run_against_nodes(self) -> Self:
> sut_node_name = self.test_run.system_under_test_node
> sut_node = next((n for n in self.nodes if n.name ==
> sut_node_name), None)
>
> - assert (
> - sut_node is not None
> - ), f"The system_under_test_node {sut_node_name} is not a valid
> node name."
> + assert sut_node is not None, (
> + f"The system_under_test_node {sut_node_name} is not a valid
> node name."
> + )
>
> tg_node_name = self.test_run.traffic_generator_node
> tg_node = next((n for n in self.nodes if n.name ==
> tg_node_name), None)
>
> - assert (
> - tg_node is not None
> - ), f"The traffic_generator_name {tg_node_name} is not a valid
> node name."
> + assert tg_node is not None, (
> + f"The traffic_generator_name {tg_node_name} is not a valid
> node name."
> + )
>
> return self
>
> diff --git a/dts/framework/config/test_run.py
> b/dts/framework/config/test_run.py
> index 76e24d1785..3cd643981d 100644
> --- a/dts/framework/config/test_run.py
> +++ b/dts/framework/config/test_run.py
> @@ -233,9 +233,9 @@ def test_suite_spec(self) -> "TestSuiteSpec":
> from framework.test_suite import find_by_name
>
> test_suite_spec = find_by_name(self.test_suite_name)
> - assert (
> - test_suite_spec is not None
> - ), f"{self.test_suite_name} is not a valid test suite module
> name."
> + assert test_suite_spec is not None, (
> + f"{self.test_suite_name} is not a valid test suite module
> name."
> + )
> return test_suite_spec
>
> @cached_property
> @@ -384,9 +384,9 @@ def convert_from_string(cls, data: Any) -> Any:
> @model_validator(mode="after")
> def verify_distinct_nodes(self) -> Self:
> """Verify that each side of the link has distinct nodes."""
> - assert (
> - self.left.node_type != self.right.node_type
> - ), "Linking ports of the same node is unsupported."
> + assert self.left.node_type != self.right.node_type, (
> + "Linking ports of the same node is unsupported."
> + )
> return self
>
>
> diff --git a/dts/framework/context.py b/dts/framework/context.py
> index 8f1021dc96..efe9af0645 100644
> --- a/dts/framework/context.py
> +++ b/dts/framework/context.py
> @@ -60,9 +60,9 @@ def reset(self) -> None:
> else _field.default
> )
>
> - assert (
> - default is not MISSING
> - ), "{LocalContext.__name__} must have defaults on all fields!"
> + assert default is not MISSING, (
> + "{LocalContext.__name__} must have defaults on all
> fields!"
> + )
>
> setattr(self, _field.name, default)
>
> @@ -108,7 +108,7 @@ def filter_cores(
> ) -> Callable[[type["TestProtocol"]], Callable]:
> """Decorates functions that require a temporary update to the lcore
> specifier."""
>
> - def decorator(func: type["TestProtocol"]) -> Callable:
> + def decorator(func: type["TestProtocol"]) -> Callable[P,
> type["TestProtocol"]]:
> @functools.wraps(func)
> def wrapper(*args: P.args, **kwargs: P.kwargs) -> Any:
> local_ctx = get_ctx().local
> diff --git a/dts/framework/remote_session/interactive_remote_session.py
> b/dts/framework/remote_session/interactive_remote_session.py
> index c8156b4345..fc42e862bc 100644
> --- a/dts/framework/remote_session/interactive_remote_session.py
> +++ b/dts/framework/remote_session/interactive_remote_session.py
> @@ -109,7 +109,7 @@ def _connect(self) -> None:
> self._logger.debug(traceback.format_exc())
> self._logger.warning(e)
> self._logger.info(
> - f"Retrying interactive session connection: retry
> number {retry_attempt +1}"
> + f"Retrying interactive session connection: retry
> number {retry_attempt + 1}"
> )
> else:
> break
> diff --git a/dts/framework/remote_session/interactive_shell.py
> b/dts/framework/remote_session/interactive_shell.py
> index a65cbce209..6bba58a4f6 100644
> --- a/dts/framework/remote_session/interactive_shell.py
> +++ b/dts/framework/remote_session/interactive_shell.py
> @@ -50,7 +50,9 @@
> def only_active(func: InteractiveShellMethod) -> InteractiveShellMethod:
> """This decorator will skip running the method if the SSH channel is
> not active."""
>
> - def _wrapper(self: "InteractiveShell", *args: P.args, **kwargs:
> P.kwargs) -> R | None:
> + def _wrapper(
> + self: "InteractiveShell", *args: P.args, **kwargs: P.kwargs
> + ) -> Callable[P, "InteractiveShell"] | None:
> if self._ssh_channel.active:
> return func(self, *args, **kwargs)
> return None
> @@ -167,7 +169,7 @@ def start_application(self, prompt: str | None = None,
> add_to_shell_pool: bool =
> break
> except InteractiveSSHTimeoutError:
> self._logger.info(
> - f"Interactive shell failed to start (attempt
> {attempt+1} out of "
> + f"Interactive shell failed to start (attempt {attempt
> + 1} out of "
> f"{self._init_attempts})"
> )
> else:
> diff --git a/dts/framework/remote_session/remote_session.py
> b/dts/framework/remote_session/remote_session.py
> index 158325bb7f..fb5f6fedf5 100644
> --- a/dts/framework/remote_session/remote_session.py
> +++ b/dts/framework/remote_session/remote_session.py
> @@ -72,9 +72,7 @@ def __post_init__(self, init_stdout: str, init_stderr:
> str) -> None:
> def __str__(self) -> str:
> """Format the command outputs."""
> return (
> - f"stdout: '{self.stdout}'\n"
> - f"stderr: '{self.stderr}'\n"
> - f"return_code: '{self.return_code}'"
> + f"stdout: '{self.stdout}'\nstderr:
> '{self.stderr}'\nreturn_code: '{self.return_code}'"
> )
>
>
> diff --git a/dts/framework/remote_session/shell_pool.py
> b/dts/framework/remote_session/shell_pool.py
> index 241737eab3..710107c6cb 100644
> --- a/dts/framework/remote_session/shell_pool.py
> +++ b/dts/framework/remote_session/shell_pool.py
> @@ -74,7 +74,7 @@ def unregister_shell(self, shell: "InteractiveShell") ->
> None:
>
> def start_new_pool(self) -> None:
> """Start a new shell pool."""
> - self._logger.debug(f"Starting new shell pool and advancing to
> level {self.pool_level+1}.")
> + self._logger.debug(f"Starting new shell pool and advancing to
> level {self.pool_level + 1}.")
> self._pools.append(set())
>
> def terminate_current_pool(self) -> None:
> diff --git a/dts/framework/settings.py b/dts/framework/settings.py
> index b08373b7ea..f329677804 100644
> --- a/dts/framework/settings.py
> +++ b/dts/framework/settings.py
> @@ -249,9 +249,9 @@ def error(self, message) -> NoReturn:
> if _is_from_env(action):
> action_name = _get_action_name(action)
> env_var_name = _get_env_var_name(action)
> - assert (
> - env_var_name is not None
> - ), "Action was set from environment, but no environment
> variable name was found."
> + assert env_var_name is not None, (
> + "Action was set from environment, but no environment
> variable name was found."
> + )
> env_var_value = os.environ.get(env_var_name)
>
> message = message.replace(
> @@ -260,7 +260,7 @@ def error(self, message) -> NoReturn:
> )
>
> print(f"{self.prog}: error: {message}\n", file=sys.stderr)
> - self.exit(2, "For help and usage, " "run the command with the
> --help flag.\n")
> + self.exit(2, "For help and usage, run the command with the --help
> flag.\n")
>
>
> class _EnvVarHelpFormatter(ArgumentDefaultsHelpFormatter):
> diff --git a/dts/framework/testbed_model/cpu.py
> b/dts/framework/testbed_model/cpu.py
> index 6e2ecca080..a9471709dd 100644
> --- a/dts/framework/testbed_model/cpu.py
> +++ b/dts/framework/testbed_model/cpu.py
> @@ -105,7 +105,7 @@ def __init__(self, lcore_list: list[int] | list[str] |
> list[LogicalCore] | str)
>
> # the input lcores may not be sorted
> self._lcore_list.sort()
> - self._lcore_str =
> f'{",".join(self._get_consecutive_lcores_range(self._lcore_list))}'
> + self._lcore_str =
> f"{','.join(self._get_consecutive_lcores_range(self._lcore_list))}"
>
> @property
> def lcore_list(self) -> list[int]:
> diff --git a/dts/framework/testbed_model/traffic_generator/scapy.py
> b/dts/framework/testbed_model/traffic_generator/scapy.py
> index c6e9006205..62853a34e4 100644
> --- a/dts/framework/testbed_model/traffic_generator/scapy.py
> +++ b/dts/framework/testbed_model/traffic_generator/scapy.py
> @@ -314,9 +314,9 @@ def __init__(self, tg_node: Node, config:
> ScapyTrafficGeneratorConfig, **kwargs:
> kwargs: Additional keyword arguments. Supported arguments
> correspond to the parameters
> of :meth:`PythonShell.__init__` in this case.
> """
> - assert (
> - tg_node.config.os == OS.linux
> - ), "Linux is the only supported OS for scapy traffic generation"
> + assert tg_node.config.os == OS.linux, (
> + "Linux is the only supported OS for scapy traffic generation"
> + )
>
> super().__init__(tg_node=tg_node, config=config, **kwargs)
>
> diff --git a/dts/framework/testbed_model/traffic_generator/trex.py
> b/dts/framework/testbed_model/traffic_generator/trex.py
> index 22cd20dea9..0314dfc881 100644
> --- a/dts/framework/testbed_model/traffic_generator/trex.py
> +++ b/dts/framework/testbed_model/traffic_generator/trex.py
> @@ -94,9 +94,9 @@ def __init__(self, tg_node: Node, config:
> TrexTrafficGeneratorConfig) -> None:
> tg_node: TG node the TRex instance is operating on.
> config: Traffic generator config provided for TRex instance.
> """
> - assert (
> - tg_node.config.os == OS.linux
> - ), "Linux is the only supported OS for trex traffic generation"
> + assert tg_node.config.os == OS.linux, (
> + "Linux is the only supported OS for trex traffic generation"
> + )
>
> super().__init__(tg_node=tg_node, config=config)
> self._tg_node_config = tg_node.config
> diff --git a/dts/framework/utils.py b/dts/framework/utils.py
> index 9917ffbfaa..d16580ec85 100644
> --- a/dts/framework/utils.py
> +++ b/dts/framework/utils.py
> @@ -154,7 +154,11 @@ def extension(self) -> str:
> For other compression formats, the extension will be in the format
> 'tar.{compression format}'.
> """
> - return f"{self.value}" if self == self.none else
> f"{type(self).none.value}.{self.value}"
> + return (
> + f"{self.value}"
> + if self == self.none
> + else f"{TarCompressionFormat.none.value}.{self.value}"
> + )
>
>
> def convert_to_list_of_string(value: Any | list[Any]) -> list[str]:
> @@ -207,7 +211,8 @@ def filter_func(tarinfo: tarfile.TarInfo) ->
> tarfile.TarInfo | None:
> return None
>
> target_tarball_path =
> dir_path.with_suffix(f".{compress_format.extension}")
> - with tarfile.open(target_tarball_path, f"w:{compress_format.value}")
> as tar:
> + compression_format: Any = f"w:{compress_format.value}"
> + with tarfile.open(target_tarball_path, compression_format) as tar:
> tar.add(dir_path, arcname=dir_path.name,
> filter=create_filter_function(exclude))
>
> return target_tarball_path
> diff --git a/dts/poetry.lock b/dts/poetry.lock
> index 0ad5d32b85..eda7cc2fec 100644
> --- a/dts/poetry.lock
> +++ b/dts/poetry.lock
> @@ -1,4 +1,4 @@
> -# This file is automatically @generated by Poetry 1.8.3 and should not be
> changed by hand.
> +# This file is automatically @generated by Poetry 2.3.2 and should not be
> changed by hand.
>
> [[package]]
> name = "aenum"
> @@ -6,6 +6,7 @@ version = "3.1.15"
> description = "Advanced Enumerations (compatible with Python's stdlib
> Enum), NamedTuples, and NamedConstants"
> optional = false
> python-versions = "*"
> +groups = ["main"]
> files = [
> {file = "aenum-3.1.15-py2-none-any.whl", hash =
> "sha256:27b1710b9d084de6e2e695dab78fe9f269de924b51ae2850170ee7e1ca6288a5"},
> {file = "aenum-3.1.15-py3-none-any.whl", hash =
> "sha256:e0dfaeea4c2bd362144b87377e2c61d91958c5ed0b4daf89cb6f45ae23af6288"},
> @@ -18,17 +19,62 @@ version = "0.7.0"
> description = "Reusable constraint types to use with typing.Annotated"
> optional = false
> python-versions = ">=3.8"
> +groups = ["main"]
> files = [
> {file = "annotated_types-0.7.0-py3-none-any.whl", hash =
> "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"},
> {file = "annotated_types-0.7.0.tar.gz", hash =
> "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"},
> ]
>
> +[[package]]
> +name = "ast-serialize"
> +version = "0.5.0"
> +description = "Python bindings for mypy AST serialization"
> +optional = false
> +python-versions = ">=3.7"
> +groups = ["dev"]
> +files = [
> + {file = "ast_serialize-0.5.0-cp314-cp314t-macosx_10_12_x86_64.whl",
> hash =
> "sha256:8f5c14f169eb0972c0c21bada5358b23d6047c76583b005234f865b11f1fa00a"},
> + {file = "ast_serialize-0.5.0-cp314-cp314t-macosx_11_0_arm64.whl",
> hash =
> "sha256:7d1a2de9de5be04652f0ed60738356ef94f66db37924a9499fffe98dc491aa0b"},
> + {file =
> "ast_serialize-0.5.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",
> hash =
> "sha256:be5173fb66f9b49026d9d5a2ff0fc7c7009077107c0eb285b2d60fdf1fe10bd1"},
> + {file =
> "ast_serialize-0.5.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl",
> hash =
> "sha256:f8015cd071ac1339924ee2b8098c93e00e155f30a16f40ec9816fcf84f4753f6"},
> + {file =
> "ast_serialize-0.5.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl",
> hash =
> "sha256:5499e8797edff2a9186aa313ed382c6b422e798e9332d9953badcee6e69a88f2"},
> + {file =
> "ast_serialize-0.5.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl",
> hash =
> "sha256:6848f2a093fb5548751a9a09bff8fcd229e2bbeb0e3331f391b6ae6d26cd9903"},
> + {file =
> "ast_serialize-0.5.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
> hash =
> "sha256:832d4c998e0b091fd60a6d6bceee535483c4d490de9ba85003af835225719261"},
> + {file =
> "ast_serialize-0.5.0-cp314-cp314t-manylinux_2_31_riscv64.whl", hash =
> "sha256:16db7c62ec0b8efe1d7afd283a388d8f74f2605d56032e5a37747d2de8dba027"},
> + {file =
> "ast_serialize-0.5.0-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl",
> hash =
> "sha256:baf5eb061eb5bccade4128ad42da33787d72f6013809cd1b590376ece8b3c937"},
> + {file = "ast_serialize-0.5.0-cp314-cp314t-musllinux_1_2_aarch64.whl",
> hash =
> "sha256:104e4a35bd7c124173c41760ef9aaea17ddb3f86c65cb643671d59afbe3ee94c"},
> + {file = "ast_serialize-0.5.0-cp314-cp314t-musllinux_1_2_armv7l.whl",
> hash =
> "sha256:36be371028fc1675acb38a331bde160dbab7ff907fdf00b67eb6911aa106951b"},
> + {file = "ast_serialize-0.5.0-cp314-cp314t-musllinux_1_2_i686.whl",
> hash =
> "sha256:061ee58bdb52341c8201a6df41182a977736bae3b7ded87ca7176ca25a8a47ab"},
> + {file = "ast_serialize-0.5.0-cp314-cp314t-musllinux_1_2_x86_64.whl",
> hash =
> "sha256:b15219e9cdc9f53f6f4cb51c009203507228226148c05c5e8fe451c28b435eb3"},
> + {file = "ast_serialize-0.5.0-cp314-cp314t-win32.whl", hash =
> "sha256:842d1c004bb466c7df036f95fabef789570541922b10976b12f5592a69cf0b38"},
> + {file = "ast_serialize-0.5.0-cp314-cp314t-win_amd64.whl", hash =
> "sha256:b0c06d760909b095cc466356dfccd05a1c7233a6ca191c020dca2c6a6f16c24c"},
> + {file = "ast_serialize-0.5.0-cp314-cp314t-win_arm64.whl", hash =
> "sha256:787baedb0262cc49e8ce37cc15c00ae818e46a165a3b36f5e21ed174998104cb"},
> + {file = "ast_serialize-0.5.0-cp39-abi3-macosx_10_12_x86_64.whl", hash
> =
> "sha256:0668aa9459cfa8c9c49ddd2163ebcf43088ba045ef7492af6fe22e0098303101"},
> + {file = "ast_serialize-0.5.0-cp39-abi3-macosx_11_0_arm64.whl", hash =
> "sha256:bf683d6363edf2b39eed6b6d4fe22d34b6203867a67e27134d9e2a2680c4bc4a"},
> + {file =
> "ast_serialize-0.5.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",
> hash =
> "sha256:9cc22cf0c9be65e71cf88fda130af60d61eb4a79370ad4cfe7900d48a4aa2211"},
> + {file =
> "ast_serialize-0.5.0-cp39-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl",
> hash =
> "sha256:f66173891548c9f2726bf27957b41cabce12fa679dc6da505ddbde4d4b3b31cf"},
> + {file =
> "ast_serialize-0.5.0-cp39-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl",
> hash =
> "sha256:e42d729ef2be96a14efbad355093284739e3670ece3e534f82cc8832790911d9"},
> + {file =
> "ast_serialize-0.5.0-cp39-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl",
> hash =
> "sha256:b725026bafa801dbd7310eb13a75f0a2e370e7e51b2cb225f9d21fcfadf919ee"},
> + {file =
> "ast_serialize-0.5.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
> hash =
> "sha256:b54f60c1d78767a53b67eaa663f0dfac3afe606aa07f1301572f588b73d64809"},
> + {file = "ast_serialize-0.5.0-cp39-abi3-manylinux_2_31_riscv64.whl",
> hash =
> "sha256:27d51654fc240a1e87e742d353d98eb45b75f62f129086b3596ab53df2ac2a43"},
> + {file =
> "ast_serialize-0.5.0-cp39-abi3-manylinux_2_5_i686.manylinux1_i686.whl",
> hash =
> "sha256:2782c36237c46dd1674542f2109740ea5ea485a169bf1431939ada0434e17934"},
> + {file = "ast_serialize-0.5.0-cp39-abi3-musllinux_1_2_aarch64.whl",
> hash =
> "sha256:1943db345233cc7194a470f13afa9c59772c0b123dea0c9414c4d4ca54369759"},
> + {file = "ast_serialize-0.5.0-cp39-abi3-musllinux_1_2_armv7l.whl",
> hash =
> "sha256:df1c00022cbbcb064bfaa505aa9c9295362443ce5dacb459d1331d3da353f887"},
> + {file = "ast_serialize-0.5.0-cp39-abi3-musllinux_1_2_i686.whl", hash
> =
> "sha256:cae65289fc456fde04af979a2be09302ef5d8ab92ef23e596d6746dc267ada27"},
> + {file = "ast_serialize-0.5.0-cp39-abi3-musllinux_1_2_x86_64.whl",
> hash =
> "sha256:239a4c354e8d676e9d94631d1d4a64edc6b266f86ff3a5a80aedd344f342c01d"},
> + {file = "ast_serialize-0.5.0-cp39-abi3-win32.whl", hash =
> "sha256:143a4ef63285a075871908fda3672dc21864b83a8ec3ee12304aa3e4c5387b9a"},
> + {file = "ast_serialize-0.5.0-cp39-abi3-win_amd64.whl", hash =
> "sha256:cf25572c526add400f26a4750dc6ce0c3bb93fc1f75e7ae0cad4ce4f2cd5c590"},
> + {file = "ast_serialize-0.5.0-cp39-abi3-win_arm64.whl", hash =
> "sha256:92a31c9c20d25a076edaeec76b128a3535d74a24f340b9a8a7e96c9b86dc9642"},
> + {file = "ast_serialize-0.5.0.tar.gz", hash =
> "sha256:5880091bfe6f4f986f22866375c2e884843e7a0b6343ae41aeea659613d879b6"},
> +]
> +
> [[package]]
> name = "bcrypt"
> version = "4.2.1"
> description = "Modern password hashing for your software and your servers"
> optional = false
> python-versions = ">=3.7"
> +groups = ["main"]
> files = [
> {file = "bcrypt-4.2.1-cp37-abi3-macosx_10_12_universal2.whl", hash =
> "sha256:1340411a0894b7d3ef562fb233e4b6ed58add185228650942bdc885362f32c17"},
> {file =
> "bcrypt-4.2.1-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",
> hash =
> "sha256:b1ee315739bc8387aa36ff127afc99120ee452924e0df517a8f3e4c0187a0f5f"},
> @@ -67,6 +113,7 @@ version = "1.17.1"
> description = "Foreign Function Interface for Python calling C code."
> optional = false
> python-versions = ">=3.8"
> +groups = ["main", "dev"]
> files = [
> {file = "cffi-1.17.1-cp310-cp310-macosx_10_9_x86_64.whl", hash =
> "sha256:df8b1c11f177bc2313ec4b2d46baec87a5f3e71fc8b45dab2ee7cae86d9aba14"},
> {file = "cffi-1.17.1-cp310-cp310-macosx_11_0_arm64.whl", hash =
> "sha256:8f2cdc858323644ab277e9bb925ad72ae0e67f69e804f4898c070998d50b1a67"},
> @@ -136,6 +183,7 @@ files = [
> {file = "cffi-1.17.1-cp39-cp39-win_amd64.whl", hash =
> "sha256:d016c76bdd850f3c626af19b0542c9677ba156e4ee4fccfdd7848803533ef662"},
> {file = "cffi-1.17.1.tar.gz", hash =
> "sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824"},
> ]
> +markers = {dev = "platform_python_implementation != \"PyPy\""}
>
> [package.dependencies]
> pycparser = "*"
> @@ -146,6 +194,7 @@ version = "44.0.0"
> description = "cryptography is a package which provides cryptographic
> recipes and primitives to Python developers."
> optional = false
> python-versions = "!=3.9.0,!=3.9.1,>=3.7"
> +groups = ["main", "dev"]
> files = [
> {file = "cryptography-44.0.0-cp37-abi3-macosx_10_9_universal2.whl",
> hash =
> "sha256:84111ad4ff3f6253820e6d3e58be2cc2a00adb29335d4cacb5ab4d4d34f2a123"},
> {file =
> "cryptography-44.0.0-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",
> hash =
> "sha256:b15492a11f9e1b62ba9d73c210e2416724633167de94607ec6069ef724fad092"},
> @@ -180,10 +229,10 @@ files = [
> cffi = {version = ">=1.12", markers = "platform_python_implementation !=
> \"PyPy\""}
>
> [package.extras]
> -docs = ["sphinx (>=5.3.0)", "sphinx-rtd-theme (>=3.0.0)"]
> +docs = ["sphinx (>=5.3.0)", "sphinx-rtd-theme (>=3.0.0) ; python_version
> >= \"3.8\""]
> docstest = ["pyenchant (>=3)", "readme-renderer (>=30.0)",
> "sphinxcontrib-spelling (>=7.3.1)"]
> -nox = ["nox (>=2024.4.15)", "nox[uv] (>=2024.3.2)"]
> -pep8test = ["check-sdist", "click (>=8.0.1)", "mypy (>=1.4)", "ruff
> (>=0.3.6)"]
> +nox = ["nox (>=2024.4.15)", "nox[uv] (>=2024.3.2) ; python_version >=
> \"3.8\""]
> +pep8test = ["check-sdist ; python_version >= \"3.8\"", "click (>=8.0.1)",
> "mypy (>=1.4)", "ruff (>=0.3.6)"]
> sdist = ["build (>=1.0.0)"]
> ssh = ["bcrypt (>=3.1.5)"]
> test = ["certifi (>=2024)", "cryptography-vectors (==44.0.0)", "pretend
> (>=0.7)", "pytest (>=7.4.0)", "pytest-benchmark (>=4.0)", "pytest-cov
> (>=2.10.1)", "pytest-xdist (>=3.5.0)"]
> @@ -195,6 +244,7 @@ version = "5.1.1"
> description = "Decorators for Humans"
> optional = false
> python-versions = ">=3.5"
> +groups = ["main"]
> files = [
> {file = "decorator-5.1.1-py3-none-any.whl", hash =
> "sha256:b8c3f85900b9dc423225913c5aace94729fe1fa9763b38939a95226f02d37186"},
> {file = "decorator-5.1.1.tar.gz", hash =
> "sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330"},
> @@ -206,6 +256,7 @@ version = "1.2.18"
> description = "Python @deprecated decorator to deprecate old python
> classes, functions or methods."
> optional = false
> python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7"
> +groups = ["main"]
> files = [
> {file = "Deprecated-1.2.18-py2.py3-none-any.whl", hash =
> "sha256:bd5011788200372a32418f888e326a09ff80d0214bd961147cfed01b5c018eec"},
> {file = "deprecated-1.2.18.tar.gz", hash =
> "sha256:422b6f6d859da6f2ef57857761bfb392480502a64c3028ca9bbe86085d72115d"},
> @@ -215,7 +266,7 @@ files = [
> wrapt = ">=1.10,<2"
>
> [package.extras]
> -dev = ["PyTest", "PyTest-Cov", "bump2version (<1)", "setuptools", "tox"]
> +dev = ["PyTest", "PyTest-Cov", "bump2version (<1)", "setuptools ;
> python_version >= \"3.12\"", "tox"]
>
> [[package]]
> name = "fabric"
> @@ -223,6 +274,7 @@ version = "3.2.2"
> description = "High level SSH command execution"
> optional = false
> python-versions = "*"
> +groups = ["main"]
> files = [
> {file = "fabric-3.2.2-py3-none-any.whl", hash =
> "sha256:91c47c0be68b14936c88b34da8a1f55e5710fd28397dac5d4ff2e21558113a6f"},
> {file = "fabric-3.2.2.tar.gz", hash =
> "sha256:8783ca42e3b0076f08b26901aac6b9d9b1f19c410074e7accfab902c184ff4a3"},
> @@ -243,56 +295,177 @@ version = "2.2.0"
> description = "Pythonic task execution"
> optional = false
> python-versions = ">=3.6"
> +groups = ["main"]
> files = [
> {file = "invoke-2.2.0-py3-none-any.whl", hash =
> "sha256:6ea924cc53d4f78e3d98bc436b08069a03077e6f85ad1ddaa8a116d7dad15820"},
> {file = "invoke-2.2.0.tar.gz", hash =
> "sha256:ee6cbb101af1a859c7fe84f2a264c059020b0cb7fe3535f9424300ab568f6bd5"},
> ]
>
> +[[package]]
> +name = "librt"
> +version = "0.11.0"
> +description = "Mypyc runtime library"
> +optional = false
> +python-versions = ">=3.9"
> +groups = ["dev"]
> +markers = "platform_python_implementation != \"PyPy\""
> +files = [
> + {file = "librt-0.11.0-cp310-cp310-macosx_10_9_x86_64.whl", hash =
> "sha256:6e94ebfcfa2d5e9926d6c3b9aa4617ffc42a845b4321fb84021b872358c82a0f"},
> + {file = "librt-0.11.0-cp310-cp310-macosx_11_0_arm64.whl", hash =
> "sha256:ae627397a2f351560440d872d6f7c8dbb4072e57868e7b2fc5b8b430fe489d45"},
> + {file =
> "librt-0.11.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",
> hash =
> "sha256:dc329359321b67d24efdf4bc69012b0597001649544db662c001db5a0184794c"},
> + {file =
> "librt-0.11.0-cp310-cp310-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl",
> hash =
> "sha256:7e82e642ab0f7608ce2fe53d76ca2280a9ee33a1b06556142c7c6fe80a86fc33"},
> + {file =
> "librt-0.11.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl",
> hash =
> "sha256:88145c15c67731d54283d135b03244028c750cc9edc334a96a4f5950ebdb2884"},
> + {file =
> "librt-0.11.0-cp310-cp310-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl",
> hash =
> "sha256:9d36a51b3d93320b686588e27123f4995804dbf1bce81df78c02fc3c6eea9280"},
> + {file = "librt-0.11.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash =
> "sha256:d00f3ac06a2a8b246327f11e186a53a100a4d5c7ed52346367e5ec751d51586c"},
> + {file = "librt-0.11.0-cp310-cp310-musllinux_1_2_i686.whl", hash =
> "sha256:461bbceede621f1ffb8839755f8663e886087ee7af16294cab7fb4d782c62eeb"},
> + {file = "librt-0.11.0-cp310-cp310-musllinux_1_2_riscv64.whl", hash =
> "sha256:0cad8a4d6a8ff03c9b76f9414caccd78e7cfbc8a2e12fa334d8e1d9932753783"},
> + {file = "librt-0.11.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash =
> "sha256:f37aa505b3cf60701562eddb32df74b12a9e380c207fd8b06dd157a943ac7ea0"},
> + {file = "librt-0.11.0-cp310-cp310-win32.whl", hash =
> "sha256:94663a21534637f0e787ec2a2a756022df6e5b7b2335a5cdd7d8e33d68a2af89"},
> + {file = "librt-0.11.0-cp310-cp310-win_amd64.whl", hash =
> "sha256:dec7db73758c2b54953fd8b7fe348c45188fe26b39ee18446196edd08453a5d4"},
> + {file = "librt-0.11.0-cp311-cp311-macosx_10_9_x86_64.whl", hash =
> "sha256:93d95bd45b7d58343d8b90d904450a545144eec19a002511163426f8ab1fae29"},
> + {file = "librt-0.11.0-cp311-cp311-macosx_11_0_arm64.whl", hash =
> "sha256:4ee278c769a713638cdacd4c0436d72156e75df3ebc0166ab2b9dc43acc386c9"},
> + {file =
> "librt-0.11.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",
> hash =
> "sha256:f230cb1cbc9faaa616f9a678f530ebcf186e414b6bcbd88b960e4ba1b92428d5"},
> + {file =
> "librt-0.11.0-cp311-cp311-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl",
> hash =
> "sha256:5d63c855d86938d9de93e265c9bd8c705b51ec494de5738340ee93767a686e4b"},
> + {file =
> "librt-0.11.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl",
> hash =
> "sha256:993f028be9e96a08d31df3479ac80d99be374d17f3b78e4796b3fd3c913d4e89"},
> + {file =
> "librt-0.11.0-cp311-cp311-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl",
> hash =
> "sha256:258d73a0aa66a055e65b2e4d1b8cdb23b9d132c5bb915d9547d804fcaed116cc"},
> + {file = "librt-0.11.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash =
> "sha256:0827efe7854718f04aaddf6496e96960a956e676fe1d0f04eb41511fd8ad06d5"},
> + {file = "librt-0.11.0-cp311-cp311-musllinux_1_2_i686.whl", hash =
> "sha256:7753e57d6e12d019c0d8786f1c09c709f4c3fcc57c3887b24e36e6c06ec938b7"},
> + {file = "librt-0.11.0-cp311-cp311-musllinux_1_2_riscv64.whl", hash =
> "sha256:11bd19822431cc21af9f27374e7ae2e58103c7d98bda823536a6c47f6bb2bb3d"},
> + {file = "librt-0.11.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash =
> "sha256:22bdf239b219d3993761a148ffa134b19e52e9989c84f845d5d7b71d70a17412"},
> + {file = "librt-0.11.0-cp311-cp311-win32.whl", hash =
> "sha256:46c60b61e308eb535fbd6fa622b1ee1bb2815691c1ad9c98bf7b84952ec3bc8d"},
> + {file = "librt-0.11.0-cp311-cp311-win_amd64.whl", hash =
> "sha256:902e546ff044f579ff1c953ff5fce97b636fe9e3943996b2177710c6ef076f73"},
> + {file = "librt-0.11.0-cp311-cp311-win_arm64.whl", hash =
> "sha256:65ac3bc20f78aa0ee5ae84baa68917f89fef4af63e941084dd019a0d0e749f0c"},
> + {file = "librt-0.11.0-cp312-cp312-macosx_10_13_x86_64.whl", hash =
> "sha256:b87504f1690a23b9a2cca841191a04f83895d4fc2dd04df91d82b1a04ca2ad46"},
> + {file = "librt-0.11.0-cp312-cp312-macosx_11_0_arm64.whl", hash =
> "sha256:40071fc5fe0ce8daa6de616702314a01e1250711682b0523d6ab8d4525910cb3"},
> + {file =
> "librt-0.11.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",
> hash =
> "sha256:137e79445c896a0ea7b265f52d23954e05b64222ee1af69e2cb34219067cbb67"},
> + {file =
> "librt-0.11.0-cp312-cp312-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl",
> hash =
> "sha256:cca6644054e78746d8d4ef238681f9c34ff8b584fe6b988ecebb8db3b15e622a"},
> + {file =
> "librt-0.11.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl",
> hash =
> "sha256:d5b0eea49f5562861ee8d757a32ef7d559c1d35be2aaaa1ec28941d74c9ffc8a"},
> + {file =
> "librt-0.11.0-cp312-cp312-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl",
> hash =
> "sha256:0d1029d7e1ae1a7e647ed6fb5df8c4ce2dffefb7a9f5fd1376a4554d96dac09f"},
> + {file = "librt-0.11.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash =
> "sha256:bc3ce6b33c5828d9e80592011a5c584cb2ce86edbc4088405f70da47dc1d1b3b"},
> + {file = "librt-0.11.0-cp312-cp312-musllinux_1_2_i686.whl", hash =
> "sha256:936c5995f3514a42111f20099397d8177c79b4d7e70961e396c6f5a0a3566766"},
> + {file = "librt-0.11.0-cp312-cp312-musllinux_1_2_riscv64.whl", hash =
> "sha256:9bc0ca6ad9381cbe8e4aa6e5726e4c80c78115a6e9723c599ed1d73e092bc49d"},
> + {file = "librt-0.11.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash =
> "sha256:070aa8c26c0a74774317a72df8851facc7f0f012a5b406557ac56992d92e1ec8"},
> + {file = "librt-0.11.0-cp312-cp312-win32.whl", hash =
> "sha256:6bf14feb84b05ae945277395451998c89c54d0def4070eb5c08de544930b245a"},
> + {file = "librt-0.11.0-cp312-cp312-win_amd64.whl", hash =
> "sha256:75672f0bc524ede266287d532d7923dbce94c7514ad07627bac3d0c6d92cc4d9"},
> + {file = "librt-0.11.0-cp312-cp312-win_arm64.whl", hash =
> "sha256:2f10cf143e4a9bb0f4f5af568a00df94a2d69ef41c2579584454bb0fe5cc642c"},
> + {file = "librt-0.11.0-cp313-cp313-macosx_10_13_x86_64.whl", hash =
> "sha256:78dc31f7fdfe9c9d0eb0e8f42d139db230e826415bbcabd9f0e9faaaee909894"},
> + {file = "librt-0.11.0-cp313-cp313-macosx_11_0_arm64.whl", hash =
> "sha256:fa475675db22290c3158e1d42326d0f5a65f04f44a0e68c3630a25b53560fb9c"},
> + {file =
> "librt-0.11.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",
> hash =
> "sha256:621db29691044bdeda22e789e482e1b0f3a985d90e3426c9c6d17606416205ea"},
> + {file =
> "librt-0.11.0-cp313-cp313-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl",
> hash =
> "sha256:a9010e2ed5b3a9e158c5fd966b3ab7e834bb3d3aacc8f66c91dd4b57a3799230"},
> + {file =
> "librt-0.11.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl",
> hash =
> "sha256:7c39513d8b7477a2e1ed8c43fc21c524e8d5a0f8d4e8b7b074dbdbe7820a08e2"},
> + {file =
> "librt-0.11.0-cp313-cp313-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl",
> hash =
> "sha256:7aef3cf1d5af86e770ab04bfd993dfc4ae8b8c17f66fb77dd4a7d50de7bbb1a3"},
> + {file = "librt-0.11.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash =
> "sha256:557183ddc36babe46b27dd60facbd5adb4492181a5be887587d57cda6e092f21"},
> + {file = "librt-0.11.0-cp313-cp313-musllinux_1_2_i686.whl", hash =
> "sha256:83d3e1f72bd42f6c5c0b7daec530c3f829bd02db42c70b8ddf0c2d90a2459930"},
> + {file = "librt-0.11.0-cp313-cp313-musllinux_1_2_riscv64.whl", hash =
> "sha256:4ce1f21fbe589bc1afd7872dece84fb0e1144f794a288e58a10d2c54a55c43be"},
> + {file = "librt-0.11.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash =
> "sha256:970b09f7044ea2b64c9da42fd3d335666518cfd1c6e8a182c95da73d0214b41e"},
> + {file = "librt-0.11.0-cp313-cp313-win32.whl", hash =
> "sha256:78fddc31cd4d3caa897ad5d31f856b1faadc9474021ad6cb182b9018793e254e"},
> + {file = "librt-0.11.0-cp313-cp313-win_amd64.whl", hash =
> "sha256:8ca8aa88751a775870b764e93bad5135385f563cb8dcee399abf034ea4d3cb47"},
> + {file = "librt-0.11.0-cp313-cp313-win_arm64.whl", hash =
> "sha256:96f044bb325fd9cf1a723015638c219e9143f0dfbc0ca54c565df2b7fc748b44"},
> + {file = "librt-0.11.0-cp314-cp314-macosx_10_13_x86_64.whl", hash =
> "sha256:4a017a95e5837dc15a8c5661d60e05daa96b90908b1aa6b7acdf443cd25c8ebd"},
> + {file = "librt-0.11.0-cp314-cp314-macosx_11_0_arm64.whl", hash =
> "sha256:b1ecbd9819deccc39b7542bf4d2a740d8a620694d39989e58661d3763458f8d4"},
> + {file =
> "librt-0.11.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",
> hash =
> "sha256:7da327dacd7be8f8ec36547373550744a3cc0e536d54665cd83f8bcd961200e8"},
> + {file =
> "librt-0.11.0-cp314-cp314-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl",
> hash =
> "sha256:0dc56b1f8d06e60db362cc3fdae206681817f86ce4725d34511473487f12a34b"},
> + {file =
> "librt-0.11.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl",
> hash =
> "sha256:05fb8fb2ab90e21c8d12ea240d744ad514da9baf381ebfa70d91d20d21713175"},
> + {file =
> "librt-0.11.0-cp314-cp314-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl",
> hash =
> "sha256:cae74872be221df4374d10fec61f93ed1513b9546ea84f2c0bf73ab3e9bd0b03"},
> + {file = "librt-0.11.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash =
> "sha256:32bcc918c0148eb7e3d57385125bac7e5f9e4359d05f07448b09f6f778c2f31c"},
> + {file = "librt-0.11.0-cp314-cp314-musllinux_1_2_i686.whl", hash =
> "sha256:f9743fc99135d5f78d2454435615f6dec0473ca507c26ce9d92b10b562a280d3"},
> + {file = "librt-0.11.0-cp314-cp314-musllinux_1_2_riscv64.whl", hash =
> "sha256:5ba067f4aadae8fda802d91d2124c90c42195ff32d9161d3549e6d05cfe26f96"},
> + {file = "librt-0.11.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash =
> "sha256:de3bf945454d032f9e390b85c4072e0a0570bf825421c8be0e71209fa65e1abe"},
> + {file = "librt-0.11.0-cp314-cp314-win32.whl", hash =
> "sha256:d2277a05f6dcb9fd13db9566aac4fabd68c3ea1ea46ee5567d4eef8efa495a2f"},
> + {file = "librt-0.11.0-cp314-cp314-win_amd64.whl", hash =
> "sha256:ab73e8db5e3f564d812c1f5c3a175930a5f9bc96ccb5e3b22a34d7858b401cf7"},
> + {file = "librt-0.11.0-cp314-cp314-win_arm64.whl", hash =
> "sha256:aea3caa317752e3a466fa8af45d91ee0ea8c7fdd96e42b0a8dd9b76a7931eba1"},
> + {file = "librt-0.11.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash =
> "sha256:d1b36540d7aaf9b9101b3a6f376c8d8e9f7a9aec93ed05918f2c69d493ffef72"},
> + {file = "librt-0.11.0-cp314-cp314t-macosx_11_0_arm64.whl", hash =
> "sha256:efbb343ab2ce3540f4ecbe6315d677ed70f37cd9a72b1e58066c918ca83acbaa"},
> + {file =
> "librt-0.11.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",
> hash =
> "sha256:aa0dd688aab3f7914d3e6e5e3554978e0383312fb8e771d84be008a35b9ee548"},
> + {file =
> "librt-0.11.0-cp314-cp314t-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl",
> hash =
> "sha256:f5fb36b8c6c63fdcbb1d526d94c0d1331610d43f4118cc1beb4efef4f3faacb2"},
> + {file =
> "librt-0.11.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl",
> hash =
> "sha256:4a9a237d13addb93715b6fee74023d5ee3469b53fce527626c0e088aa585805f"},
> + {file =
> "librt-0.11.0-cp314-cp314t-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl",
> hash =
> "sha256:5ddd17bd87b2c56ddd60e546a7984a2e64c4e8eab92fb4cf3830a48ad5469d51"},
> + {file = "librt-0.11.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash =
> "sha256:bd43992b4473d42f12ff9e68326079f0696d9d4e6000e8f39a0238d482ba6ee2"},
> + {file = "librt-0.11.0-cp314-cp314t-musllinux_1_2_i686.whl", hash =
> "sha256:f8e3e8056dd674e279741485e2e512d6e9a751c7455809d0114e6ebf8d781085"},
> + {file = "librt-0.11.0-cp314-cp314t-musllinux_1_2_riscv64.whl", hash =
> "sha256:c1f708d8ae9c56cf38a903c44297243d2ec83fd82b396b977e0144a3e76217e3"},
> + {file = "librt-0.11.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash =
> "sha256:0add982e0e7b9fc14cf4b33789d5f13f66581889b88c2f58099f6ce8f92617bd"},
> + {file = "librt-0.11.0-cp314-cp314t-win32.whl", hash =
> "sha256:2b481d846ac894c4e8403c5fd0e87c5d11d6499e404b474602508a224ff531c8"},
> + {file = "librt-0.11.0-cp314-cp314t-win_amd64.whl", hash =
> "sha256:28edb433edde181112a908c78907af28f964eabc15f4dd16c9d66c834302677c"},
> + {file = "librt-0.11.0-cp314-cp314t-win_arm64.whl", hash =
> "sha256:dee008f20b542e3cd162ba338a7f9ec0f6d23d395f66fe8aeeec3c9d067ea253"},
> + {file = "librt-0.11.0-cp39-cp39-macosx_10_9_x86_64.whl", hash =
> "sha256:6bd72d903911d995ab666dbd1871f8b1e80925a699af8063fbf50053329fb05f"},
> + {file = "librt-0.11.0-cp39-cp39-macosx_11_0_arm64.whl", hash =
> "sha256:0ef69ac715f3cd8e5cd252cb2aebfa72c015492aacc339d5d7bf8fef3c62c677"},
> + {file =
> "librt-0.11.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",
> hash =
> "sha256:624a40c4a4ad7773315c287276cd024509b2c66ff5904f504bfc08d2c70293ab"},
> + {file =
> "librt-0.11.0-cp39-cp39-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl",
> hash =
> "sha256:41dc19fe150b69716c8ece4f76773a9e8813fe3e35e032a58b4d46423fb8d7c0"},
> + {file =
> "librt-0.11.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl",
> hash =
> "sha256:4e8bd98ea9c47ae90b319a087ab28dac493f1ffbc1ecd1f28fcdbf3b7e1108d1"},
> + {file =
> "librt-0.11.0-cp39-cp39-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl",
> hash =
> "sha256:84308fc49423ce6475d1c5d1985cd69a8ca9f0325fc7d5f81bb690a3f3625d4e"},
> + {file = "librt-0.11.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash =
> "sha256:ff0fbaf5f44a21beeb0110f2ab64f45135a9536a834b79c0d1ef018f2786bbfa"},
> + {file = "librt-0.11.0-cp39-cp39-musllinux_1_2_i686.whl", hash =
> "sha256:9c028a9442a18e266955d364ce42259136e79a7ba14d773e0d778d5f70cd56f1"},
> + {file = "librt-0.11.0-cp39-cp39-musllinux_1_2_riscv64.whl", hash =
> "sha256:9f1692105a02bcf853f355032a5fdc5494358ef83d8fd22d16de375c85cec3f5"},
> + {file = "librt-0.11.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash =
> "sha256:7a80a71e1fda83cc752a9141e87aae7fef279538597564d670e9ce513f286192"},
> + {file = "librt-0.11.0-cp39-cp39-win32.whl", hash =
> "sha256:140695816ddf3c86eb972981a26f35efd871c44b0c3aed44c8cd01749386617f"},
> + {file = "librt-0.11.0-cp39-cp39-win_amd64.whl", hash =
> "sha256:92f7ff819c197fc30473190a12c2856f325ac90aabfccbeb2072d28cc2e234e3"},
> + {file = "librt-0.11.0.tar.gz", hash =
> "sha256:075dc3ef4458a278e0195cbf6ac9d38808d9b906c5a6c7f7f79c3888276a3fb1"},
> +]
> +
> [[package]]
> name = "mypy"
> -version = "1.13.0"
> +version = "2.1.0"
> description = "Optional static typing for Python"
> optional = false
> -python-versions = ">=3.8"
> +python-versions = ">=3.10"
> +groups = ["dev"]
> files = [
> - {file = "mypy-1.13.0-cp310-cp310-macosx_10_9_x86_64.whl", hash =
> "sha256:6607e0f1dd1fb7f0aca14d936d13fd19eba5e17e1cd2a14f808fa5f8f6d8f60a"},
> - {file = "mypy-1.13.0-cp310-cp310-macosx_11_0_arm64.whl", hash =
> "sha256:8a21be69bd26fa81b1f80a61ee7ab05b076c674d9b18fb56239d72e21d9f4c80"},
> - {file =
> "mypy-1.13.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl",
> hash =
> "sha256:7b2353a44d2179846a096e25691d54d59904559f4232519d420d64da6828a3a7"},
> - {file = "mypy-1.13.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash =
> "sha256:0730d1c6a2739d4511dc4253f8274cdd140c55c32dfb0a4cf8b7a43f40abfa6f"},
> - {file = "mypy-1.13.0-cp310-cp310-win_amd64.whl", hash =
> "sha256:c5fc54dbb712ff5e5a0fca797e6e0aa25726c7e72c6a5850cfd2adbc1eb0a372"},
> - {file = "mypy-1.13.0-cp311-cp311-macosx_10_9_x86_64.whl", hash =
> "sha256:581665e6f3a8a9078f28d5502f4c334c0c8d802ef55ea0e7276a6e409bc0d82d"},
> - {file = "mypy-1.13.0-cp311-cp311-macosx_11_0_arm64.whl", hash =
> "sha256:3ddb5b9bf82e05cc9a627e84707b528e5c7caaa1c55c69e175abb15a761cec2d"},
> - {file =
> "mypy-1.13.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl",
> hash =
> "sha256:20c7ee0bc0d5a9595c46f38beb04201f2620065a93755704e141fcac9f59db2b"},
> - {file = "mypy-1.13.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash =
> "sha256:3790ded76f0b34bc9c8ba4def8f919dd6a46db0f5a6610fb994fe8efdd447f73"},
> - {file = "mypy-1.13.0-cp311-cp311-win_amd64.whl", hash =
> "sha256:51f869f4b6b538229c1d1bcc1dd7d119817206e2bc54e8e374b3dfa202defcca"},
> - {file = "mypy-1.13.0-cp312-cp312-macosx_10_13_x86_64.whl", hash =
> "sha256:5c7051a3461ae84dfb5dd15eff5094640c61c5f22257c8b766794e6dd85e72d5"},
> - {file = "mypy-1.13.0-cp312-cp312-macosx_11_0_arm64.whl", hash =
> "sha256:39bb21c69a5d6342f4ce526e4584bc5c197fd20a60d14a8624d8743fffb9472e"},
> - {file =
> "mypy-1.13.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl",
> hash =
> "sha256:164f28cb9d6367439031f4c81e84d3ccaa1e19232d9d05d37cb0bd880d3f93c2"},
> - {file = "mypy-1.13.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash =
> "sha256:a4c1bfcdbce96ff5d96fc9b08e3831acb30dc44ab02671eca5953eadad07d6d0"},
> - {file = "mypy-1.13.0-cp312-cp312-win_amd64.whl", hash =
> "sha256:a0affb3a79a256b4183ba09811e3577c5163ed06685e4d4b46429a271ba174d2"},
> - {file = "mypy-1.13.0-cp313-cp313-macosx_10_13_x86_64.whl", hash =
> "sha256:a7b44178c9760ce1a43f544e595d35ed61ac2c3de306599fa59b38a6048e1aa7"},
> - {file = "mypy-1.13.0-cp313-cp313-macosx_11_0_arm64.whl", hash =
> "sha256:5d5092efb8516d08440e36626f0153b5006d4088c1d663d88bf79625af3d1d62"},
> - {file =
> "mypy-1.13.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl",
> hash =
> "sha256:de2904956dac40ced10931ac967ae63c5089bd498542194b436eb097a9f77bc8"},
> - {file = "mypy-1.13.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash =
> "sha256:7bfd8836970d33c2105562650656b6846149374dc8ed77d98424b40b09340ba7"},
> - {file = "mypy-1.13.0-cp313-cp313-win_amd64.whl", hash =
> "sha256:9f73dba9ec77acb86457a8fc04b5239822df0c14a082564737833d2963677dbc"},
> - {file = "mypy-1.13.0-cp38-cp38-macosx_10_9_x86_64.whl", hash =
> "sha256:100fac22ce82925f676a734af0db922ecfea991e1d7ec0ceb1e115ebe501301a"},
> - {file = "mypy-1.13.0-cp38-cp38-macosx_11_0_arm64.whl", hash =
> "sha256:7bcb0bb7f42a978bb323a7c88f1081d1b5dee77ca86f4100735a6f541299d8fb"},
> - {file =
> "mypy-1.13.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl",
> hash =
> "sha256:bde31fc887c213e223bbfc34328070996061b0833b0a4cfec53745ed61f3519b"},
> - {file = "mypy-1.13.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash =
> "sha256:07de989f89786f62b937851295ed62e51774722e5444a27cecca993fc3f9cd74"},
> - {file = "mypy-1.13.0-cp38-cp38-win_amd64.whl", hash =
> "sha256:4bde84334fbe19bad704b3f5b78c4abd35ff1026f8ba72b29de70dda0916beb6"},
> - {file = "mypy-1.13.0-cp39-cp39-macosx_10_9_x86_64.whl", hash =
> "sha256:0246bcb1b5de7f08f2826451abd947bf656945209b140d16ed317f65a17dc7dc"},
> - {file = "mypy-1.13.0-cp39-cp39-macosx_11_0_arm64.whl", hash =
> "sha256:7f5b7deae912cf8b77e990b9280f170381fdfbddf61b4ef80927edd813163732"},
> - {file =
> "mypy-1.13.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl",
> hash =
> "sha256:7029881ec6ffb8bc233a4fa364736789582c738217b133f1b55967115288a2bc"},
> - {file = "mypy-1.13.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash =
> "sha256:3e38b980e5681f28f033f3be86b099a247b13c491f14bb8b1e1e134d23bb599d"},
> - {file = "mypy-1.13.0-cp39-cp39-win_amd64.whl", hash =
> "sha256:a6789be98a2017c912ae6ccb77ea553bbaf13d27605d2ca20a76dfbced631b24"},
> - {file = "mypy-1.13.0-py3-none-any.whl", hash =
> "sha256:9c250883f9fd81d212e0952c92dbfcc96fc237f4b7c92f56ac81fd48460b3e5a"},
> - {file = "mypy-1.13.0.tar.gz", hash =
> "sha256:0291a61b6fbf3e6673e3405cfcc0e7650bebc7939659fdca2702958038bd835e"},
> + {file = "mypy-2.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash =
> "sha256:11a6beb180257a805961aea9ec591bbd0bd17f1e18d35b8456d57aee5bedfedc"},
> + {file = "mypy-2.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash =
> "sha256:8ef78c1d306bbf9a8a12f526c44902c9c28dffd6c52c52bf6a72641ce18d3849"},
> + {file =
> "mypy-2.1.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",
> hash =
> "sha256:c209a90853081ff01d01ee895cafe10f7db1474e0d95beaeef0f6c1db9119bbd"},
> + {file =
> "mypy-2.1.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl",
> hash =
> "sha256:47cebf61abde7c088a4e27718a8b13a81655686b2e9c251f5c0915a802248166"},
> + {file = "mypy-2.1.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash =
> "sha256:d57a90ae5e872138a425ec328edbc9b235d1934c4377881a33ec05b341acc9a8"},
> + {file = "mypy-2.1.0-cp310-cp310-win_amd64.whl", hash =
> "sha256:aea7f7a8a55b459c34275fc468ada6ca7c173a5e43a68f5dbe588a563d8a06b8"},
> + {file = "mypy-2.1.0-cp310-cp310-win_arm64.whl", hash =
> "sha256:c989640253f0d76843e9c6c1bbf4bd48c5e85ada61bde4beb37cb3eca035685e"},
> + {file = "mypy-2.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash =
> "sha256:a683016b16fe2f572dc04c72be7ee0504ac1605a265d0200f5cea695fb788f41"},
> + {file = "mypy-2.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash =
> "sha256:1a293c534adb55271fef24a26da04b855540a8c13cc07bc5917b9fd2c394f2ca"},
> + {file =
> "mypy-2.1.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",
> hash =
> "sha256:7406f4d048e71e576f5356d317e5b0a9e666dfd966bd99f9d14ca06e1a341538"},
> + {file =
> "mypy-2.1.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl",
> hash =
> "sha256:e0210d626fc8b31ccc90233754c7bc90e1f43205e85d96387f7db1285b55c398"},
> + {file = "mypy-2.1.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash =
> "sha256:3712c20deed54e814eaaa825603bada8ea1c390670a397c95b98405347acc563"},
> + {file = "mypy-2.1.0-cp311-cp311-win_amd64.whl", hash =
> "sha256:fcaa0e479066e31f7cceb6a3bea39cb22b2ff51a6b2f24f193d19179ba17c389"},
> + {file = "mypy-2.1.0-cp311-cp311-win_arm64.whl", hash =
> "sha256:0b1a5260c95aa443083f9ed3592662941951bca3d4ca224a5dc517c38b7cf666"},
> + {file = "mypy-2.1.0-cp312-cp312-macosx_10_13_x86_64.whl", hash =
> "sha256:244358bf1c0da7722230bce60683d52e8e9fd030554926f15b747a84efb5b3af"},
> + {file = "mypy-2.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash =
> "sha256:4ec7c57657493c7a75534df2751c8ae2cda383c16ecc55d2106c54476b1b16f6"},
> + {file =
> "mypy-2.1.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",
> hash =
> "sha256:d8161b6ff4392410023224f0969d17db93e1e154bc3e4ba62598e720723ae211"},
> + {file =
> "mypy-2.1.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl",
> hash =
> "sha256:bf03e12003084a67395184d3eb8cbd6a489dc3655b5664b28c210a9e2403ab0b"},
> + {file = "mypy-2.1.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash =
> "sha256:20509760fd791c51579d573153407d226385ec1f8bcce55d730b354f3336bc22"},
> + {file = "mypy-2.1.0-cp312-cp312-win_amd64.whl", hash =
> "sha256:6753d0c1fdd6b1a23b9e4f283ce80b2153b724adcb2653b20b85a8a28ac6436b"},
> + {file = "mypy-2.1.0-cp312-cp312-win_arm64.whl", hash =
> "sha256:98ebb6589bb3b6d0c6f0c459d53ca55b8091fbc13d277c4041c885392e8195e8"},
> + {file = "mypy-2.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash =
> "sha256:35aac3bb114e03888f535d5eb51b8bafbb3266586b599da1940f9b1be3ec5bd5"},
> + {file = "mypy-2.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash =
> "sha256:8de55a8c861f2a49331f807be98d90caeceeef520bde13d43a160207f8af613e"},
> + {file =
> "mypy-2.1.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",
> hash =
> "sha256:5fdf2941a07434af755837d9880f7d7d25f1dacb1af9dcd4b9b66f2220a3024e"},
> + {file =
> "mypy-2.1.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl",
> hash =
> "sha256:e195b817c13f02352a9c124301f9f30f078405444679b6753c1b96b6eed37285"},
> + {file = "mypy-2.1.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash =
> "sha256:5431d42af987ebd92ba2f71d45c85ed41d8e6ca9f5fd209a69f68f707d2469e5"},
> + {file = "mypy-2.1.0-cp313-cp313-win_amd64.whl", hash =
> "sha256:767fe8c66dc3e01e19e1737d4c38ebefead16125e1b8e58ad421903b376f5c65"},
> + {file = "mypy-2.1.0-cp313-cp313-win_arm64.whl", hash =
> "sha256:ecfe70d43775ab99562ab128ce49854a362044c9f894961f68f898c23cb7429d"},
> + {file = "mypy-2.1.0-cp314-cp314-macosx_10_15_x86_64.whl", hash =
> "sha256:7354c5a7f69d9345c3d6e69921d57088eea3ddeeb6b20d34c1b3855b02c36ec2"},
> + {file = "mypy-2.1.0-cp314-cp314-macosx_11_0_arm64.whl", hash =
> "sha256:49890d4f76ac9e06ec117f9e09f3174da70a620a0c300953d8595c926e80947f"},
> + {file =
> "mypy-2.1.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",
> hash =
> "sha256:761be68e023ef5d94678772396a8af1220030f80837a3afd8d0aef3b419666f4"},
> + {file =
> "mypy-2.1.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl",
> hash =
> "sha256:c90345fc182dc363b891350457ec69c35140858538f38b4540845afcc32b1aef"},
> + {file = "mypy-2.1.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash =
> "sha256:b84802e7b5a6daf1f5e15bc9fcd7ddae77be13981ffab037f1c67bb84d67d135"},
> + {file = "mypy-2.1.0-cp314-cp314-win_amd64.whl", hash =
> "sha256:022c771234936ceac541ebaf836fe9e2abeb3f5e09aff21588fe543ff006fe21"},
> + {file = "mypy-2.1.0-cp314-cp314-win_arm64.whl", hash =
> "sha256:498207db725cec88829a6a5c2fc771205fd043719ef98bc49aba8fb9fc4e6d57"},
> + {file = "mypy-2.1.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash =
> "sha256:7d5e5cad0efeba72b93cd17490cc0d69c5ac9ca132994fe3fb0314808aeeb83e"},
> + {file = "mypy-2.1.0-cp314-cp314t-macosx_11_0_arm64.whl", hash =
> "sha256:ff715050c127d724fd260a2e666e7747fdd83511c0c47d449d98238970aef780"},
> + {file =
> "mypy-2.1.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl",
> hash =
> "sha256:82208da9e09414d520e912d3e462d454854bed0810b71540bb016dcbca7308fd"},
> + {file =
> "mypy-2.1.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl",
> hash =
> "sha256:e79ebc1b904b84f0310dff7469655a9c36c7a68bddb37bdd42b67a332df61d08"},
> + {file = "mypy-2.1.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash =
> "sha256:e583edc957cfb0deb142079162ae826f58449b116c1d442f2d91c69d9fced081"},
> + {file = "mypy-2.1.0-cp314-cp314t-win_amd64.whl", hash =
> "sha256:b33b6cd332695bba180d55e717a79d3038e479a2c49cc5eb3d53603409b9a5d7"},
> + {file = "mypy-2.1.0-cp314-cp314t-win_arm64.whl", hash =
> "sha256:4f910fe825376a7b66ef7ca8c98e5a149e8cd64c19ae71d84047a74ee060d4e6"},
> + {file = "mypy-2.1.0-py3-none-any.whl", hash =
> "sha256:a663814603a5c563fb87a4f96fb473eeb30d1f5a4885afcf44f9db000a366289"},
> + {file = "mypy-2.1.0.tar.gz", hash =
> "sha256:81e76ad12c2d804512e9b13240d1588316531bfba07558286078bfbce9613633"},
> ]
>
> [package.dependencies]
> -mypy-extensions = ">=1.0.0"
> +ast-serialize = ">=0.3.0,<1.0.0"
> +librt = {version = ">=0.11.0", markers = "platform_python_implementation
> != \"PyPy\""}
> +mypy_extensions = ">=1.0.0"
> +pathspec = ">=1.0.0"
> tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""}
> -typing-extensions = ">=4.6.0"
> +typing_extensions = [
> + {version = ">=4.6.0", markers = "python_version < \"3.15\""},
> + {version = ">=4.14.0", markers = "python_version >= \"3.15\""},
> +]
>
> [package.extras]
> dmypy = ["psutil (>=4.0)"]
> @@ -307,6 +480,7 @@ version = "1.0.0"
> description = "Type system extensions for programs checked with the mypy
> type checker."
> optional = false
> python-versions = ">=3.5"
> +groups = ["dev"]
> files = [
> {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash =
> "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"},
> {file = "mypy_extensions-1.0.0.tar.gz", hash =
> "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"},
> @@ -318,6 +492,7 @@ version = "3.5.0"
> description = "SSH2 protocol library"
> optional = false
> python-versions = ">=3.6"
> +groups = ["main"]
> files = [
> {file = "paramiko-3.5.0-py3-none-any.whl", hash =
> "sha256:1fedf06b085359051cd7d0d270cebe19e755a8a921cc2ddbfa647fb0cd7d68f9"},
> {file = "paramiko-3.5.0.tar.gz", hash =
> "sha256:ad11e540da4f55cedda52931f1a3f812a8238a7af7f62a60de538cd80bb28124"},
> @@ -329,20 +504,39 @@ cryptography = ">=3.3"
> pynacl = ">=1.5"
>
> [package.extras]
> -all = ["gssapi (>=1.4.1)", "invoke (>=2.0)", "pyasn1 (>=0.1.7)", "pywin32
> (>=2.1.8)"]
> -gssapi = ["gssapi (>=1.4.1)", "pyasn1 (>=0.1.7)", "pywin32 (>=2.1.8)"]
> +all = ["gssapi (>=1.4.1) ; platform_system != \"Windows\"", "invoke
> (>=2.0)", "pyasn1 (>=0.1.7)", "pywin32 (>=2.1.8) ; platform_system ==
> \"Windows\""]
> +gssapi = ["gssapi (>=1.4.1) ; platform_system != \"Windows\"", "pyasn1
> (>=0.1.7)", "pywin32 (>=2.1.8) ; platform_system == \"Windows\""]
> invoke = ["invoke (>=2.0)"]
>
> +[[package]]
> +name = "pathspec"
> +version = "1.1.1"
> +description = "Utility library for gitignore style pattern matching of
> file paths."
> +optional = false
> +python-versions = ">=3.9"
> +groups = ["dev"]
> +files = [
> + {file = "pathspec-1.1.1-py3-none-any.whl", hash =
> "sha256:a00ce642f577bf7f473932318056212bc4f8bfdf53128c78bbd5af0b9b20b189"},
> + {file = "pathspec-1.1.1.tar.gz", hash =
> "sha256:17db5ecd524104a120e173814c90367a96a98d07c45b2e10c2f3919fff91bf5a"},
> +]
> +
> +[package.extras]
> +hyperscan = ["hyperscan (>=0.7)"]
> +optional = ["typing-extensions (>=4)"]
> +re2 = ["google-re2 (>=1.1)"]
> +
> [[package]]
> name = "pycparser"
> version = "2.22"
> description = "C parser in Python"
> optional = false
> python-versions = ">=3.8"
> +groups = ["main", "dev"]
> files = [
> {file = "pycparser-2.22-py3-none-any.whl", hash =
> "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc"},
> {file = "pycparser-2.22.tar.gz", hash =
> "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6"},
> ]
> +markers = {dev = "platform_python_implementation != \"PyPy\""}
>
> [[package]]
> name = "pydantic"
> @@ -350,6 +544,7 @@ version = "2.10.3"
> description = "Data validation using Python type hints"
> optional = false
> python-versions = ">=3.8"
> +groups = ["main"]
> files = [
> {file = "pydantic-2.10.3-py3-none-any.whl", hash =
> "sha256:be04d85bbc7b65651c5f8e6b9976ed9c6f41782a55524cef079a34a0bb82144d"},
> {file = "pydantic-2.10.3.tar.gz", hash =
> "sha256:cb5ac360ce894ceacd69c403187900a02c4b20b693a9dd1d643e1effab9eadf9"},
> @@ -362,7 +557,7 @@ typing-extensions = ">=4.12.2"
>
> [package.extras]
> email = ["email-validator (>=2.0.0)"]
> -timezone = ["tzdata"]
> +timezone = ["tzdata ; python_version >= \"3.9\" and platform_system ==
> \"Windows\""]
>
> [[package]]
> name = "pydantic-core"
> @@ -370,6 +565,7 @@ version = "2.27.1"
> description = "Core functionality for Pydantic validation and
> serialization"
> optional = false
> python-versions = ">=3.8"
> +groups = ["main"]
> files = [
> {file = "pydantic_core-2.27.1-cp310-cp310-macosx_10_12_x86_64.whl",
> hash =
> "sha256:71a5e35c75c021aaf400ac048dacc855f000bdfed91614b4a726f7432f1f3d6a"},
> {file = "pydantic_core-2.27.1-cp310-cp310-macosx_11_0_arm64.whl",
> hash =
> "sha256:f82d068a2d6ecfc6e054726080af69a6764a10015467d7d7b9f66d6ed5afa23b"},
> @@ -482,6 +678,7 @@ version = "1.5.0"
> description = "Python binding to the Networking and Cryptography (NaCl)
> library"
> optional = false
> python-versions = ">=3.6"
> +groups = ["main"]
> files = [
> {file = "PyNaCl-1.5.0-cp36-abi3-macosx_10_10_universal2.whl", hash =
> "sha256:401002a4aaa07c9414132aaed7f6836ff98f59277a234704ff66878c2ee4a0d1"},
> {file =
> "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl",
> hash =
> "sha256:52cb72a79269189d4e0dc537556f4740f7f0a9ec41c1322598799b0bdad4ef92"},
> @@ -508,6 +705,7 @@ version = "6.0.2"
> description = "YAML parser and emitter for Python"
> optional = false
> python-versions = ">=3.8"
> +groups = ["main"]
> files = [
> {file = "PyYAML-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash =
> "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086"},
> {file = "PyYAML-6.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash =
> "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf"},
> @@ -566,29 +764,30 @@ files = [
>
> [[package]]
> name = "ruff"
> -version = "0.8.2"
> +version = "0.15.16"
> description = "An extremely fast Python linter and code formatter,
> written in Rust."
> optional = false
> python-versions = ">=3.7"
> +groups = ["dev"]
> files = [
> - {file = "ruff-0.8.2-py3-none-linux_armv6l.whl", hash =
> "sha256:c49ab4da37e7c457105aadfd2725e24305ff9bc908487a9bf8d548c6dad8bb3d"},
> - {file = "ruff-0.8.2-py3-none-macosx_10_12_x86_64.whl", hash =
> "sha256:ec016beb69ac16be416c435828be702ee694c0d722505f9c1f35e1b9c0cc1bf5"},
> - {file = "ruff-0.8.2-py3-none-macosx_11_0_arm64.whl", hash =
> "sha256:f05cdf8d050b30e2ba55c9b09330b51f9f97d36d4673213679b965d25a785f3c"},
> - {file =
> "ruff-0.8.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",
> hash =
> "sha256:60f578c11feb1d3d257b2fb043ddb47501ab4816e7e221fbb0077f0d5d4e7b6f"},
> - {file =
> "ruff-0.8.2-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash
> =
> "sha256:cbd5cf9b0ae8f30eebc7b360171bd50f59ab29d39f06a670b3e4501a36ba5897"},
> - {file =
> "ruff-0.8.2-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash =
> "sha256:b402ddee3d777683de60ff76da801fa7e5e8a71038f57ee53e903afbcefdaa58"},
> - {file =
> "ruff-0.8.2-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash =
> "sha256:705832cd7d85605cb7858d8a13d75993c8f3ef1397b0831289109e953d833d29"},
> - {file =
> "ruff-0.8.2-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl",
> hash =
> "sha256:32096b41aaf7a5cc095fa45b4167b890e4c8d3fd217603f3634c92a541de7248"},
> - {file =
> "ruff-0.8.2-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash =
> "sha256:e769083da9439508833cfc7c23e351e1809e67f47c50248250ce1ac52c21fb93"},
> - {file =
> "ruff-0.8.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash
> =
> "sha256:5fe716592ae8a376c2673fdfc1f5c0c193a6d0411f90a496863c99cd9e2ae25d"},
> - {file = "ruff-0.8.2-py3-none-musllinux_1_2_aarch64.whl", hash =
> "sha256:81c148825277e737493242b44c5388a300584d73d5774defa9245aaef55448b0"},
> - {file = "ruff-0.8.2-py3-none-musllinux_1_2_armv7l.whl", hash =
> "sha256:d261d7850c8367704874847d95febc698a950bf061c9475d4a8b7689adc4f7fa"},
> - {file = "ruff-0.8.2-py3-none-musllinux_1_2_i686.whl", hash =
> "sha256:1ca4e3a87496dc07d2427b7dd7ffa88a1e597c28dad65ae6433ecb9f2e4f022f"},
> - {file = "ruff-0.8.2-py3-none-musllinux_1_2_x86_64.whl", hash =
> "sha256:729850feed82ef2440aa27946ab39c18cb4a8889c1128a6d589ffa028ddcfc22"},
> - {file = "ruff-0.8.2-py3-none-win32.whl", hash =
> "sha256:ac42caaa0411d6a7d9594363294416e0e48fc1279e1b0e948391695db2b3d5b1"},
> - {file = "ruff-0.8.2-py3-none-win_amd64.whl", hash =
> "sha256:2aae99ec70abf43372612a838d97bfe77d45146254568d94926e8ed5bbb409ea"},
> - {file = "ruff-0.8.2-py3-none-win_arm64.whl", hash =
> "sha256:fb88e2a506b70cfbc2de6fae6681c4f944f7dd5f2fe87233a7233d888bad73e8"},
> - {file = "ruff-0.8.2.tar.gz", hash =
> "sha256:b84f4f414dda8ac7f75075c1fa0b905ac0ff25361f42e6d5da681a465e0f78e5"},
> + {file = "ruff-0.15.16-py3-none-linux_armv6l.whl", hash =
> "sha256:6ac3c0b3969cc6cf6b158c4e2f8f682acb58e7d700d8a44b65ecdc72d66ab0b2"},
> + {file = "ruff-0.15.16-py3-none-macosx_10_12_x86_64.whl", hash =
> "sha256:197c207ed75ffba54a0dec23db4aa939a27a3053073e085e0042433cbdc58e4a"},
> + {file = "ruff-0.15.16-py3-none-macosx_11_0_arm64.whl", hash =
> "sha256:3a39fec45ab316cc23e7558f23fea4a70403ddb5648ea9a4a3854a16973d0071"},
> + {file =
> "ruff-0.15.16-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",
> hash =
> "sha256:ba93191d79003116b95128c9d306e045200fdbd0bccb782b110f3cd1d4abc5cf"},
> + {file =
> "ruff-0.15.16-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl",
> hash =
> "sha256:c6ee4b90520630120ef032aa5cc10db483852dff950e78b1d717e2993a61ac8d"},
> + {file =
> "ruff-0.15.16-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash =
> "sha256:4e4215bc938bc3c8215c1472c1aa437e310fee20cd427335fec9d7e609563628"},
> + {file =
> "ruff-0.15.16-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl",
> hash =
> "sha256:7c8d26be963b090f10e29abc8b3e74a2a321f6fa34e02424e30b5af89350ecbb"},
> + {file =
> "ruff-0.15.16-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash
> =
> "sha256:f198cf4123602a2280ed46c307bcbafe41758d6fee5b456b6b6058ca1514b3b4"},
> + {file =
> "ruff-0.15.16-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
> hash =
> "sha256:bb27515fa6240fb586ae82b901a59e67d24acff86f2190b433dc542fe0435aeb"},
> + {file = "ruff-0.15.16-py3-none-manylinux_2_31_riscv64.whl", hash =
> "sha256:a267c46ba1593fc26b8eecbea050b39d40c0b6bb7781ee11c90a02cd10032951"},
> + {file = "ruff-0.15.16-py3-none-musllinux_1_2_aarch64.whl", hash =
> "sha256:528c68f39a91498a8d50e91ff5985df3d105782bab49cc378e73ac26bff083e8"},
> + {file = "ruff-0.15.16-py3-none-musllinux_1_2_armv7l.whl", hash =
> "sha256:7ed55c58950df60589a9a7a5d2f8fa5f54ebd287163be805adfe6ee95a9de123"},
> + {file = "ruff-0.15.16-py3-none-musllinux_1_2_i686.whl", hash =
> "sha256:d482feaf51512b50f9790ceb417a56a61dd1e9d9bf967662b9ed27c01b34f53a"},
> + {file = "ruff-0.15.16-py3-none-musllinux_1_2_x86_64.whl", hash =
> "sha256:1e15bc8c94513dae2a40cc9ef07c94fdd4ecc9e29dabebeebe170f952322c9e3"},
> + {file = "ruff-0.15.16-py3-none-win32.whl", hash =
> "sha256:580378f7bd4aa25f72e74aa54948a9622f142b1e509521dd10902e886681cc1e"},
> + {file = "ruff-0.15.16-py3-none-win_amd64.whl", hash =
> "sha256:408256017284eddf98fff77b29aa4fb30f586042d535b2d9befc6512f400aaec"},
> + {file = "ruff-0.15.16-py3-none-win_arm64.whl", hash =
> "sha256:8cd61783afb39638a7133ef0d2dfb1e91277593962f81b5a8423eb0b888a6121"},
> + {file = "ruff-0.15.16.tar.gz", hash =
> "sha256:d05e78d38c78caf020b03789e25106c93017db5a0cb6e2819885018c61343b78"},
> ]
>
> [[package]]
> @@ -597,6 +796,7 @@ version = "2.6.1"
> description = "Scapy: interactive packet manipulation tool"
> optional = false
> python-versions = "<4,>=3.7"
> +groups = ["main"]
> files = [
> {file = "scapy-2.6.1-py3-none-any.whl", hash =
> "sha256:88a998572049b511a1f3e44f4aa7c62dd39c6ea2aa1bb58434f503956641789d"},
> {file = "scapy-2.6.1.tar.gz", hash =
> "sha256:7600d7e2383c853e5c3a6e05d37e17643beebf2b3e10d7914dffcc3bc3c6e6c5"},
> @@ -613,6 +813,7 @@ version = "0.10.2"
> description = "Python Library for Tom's Obvious, Minimal Language"
> optional = false
> python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
> +groups = ["dev"]
> files = [
> {file = "toml-0.10.2-py2.py3-none-any.whl", hash =
> "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"},
> {file = "toml-0.10.2.tar.gz", hash =
> "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"},
> @@ -624,6 +825,8 @@ version = "2.2.1"
> description = "A lil' TOML parser"
> optional = false
> python-versions = ">=3.8"
> +groups = ["dev"]
> +markers = "python_version == \"3.10\""
> files = [
> {file = "tomli-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash =
> "sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249"},
> {file = "tomli-2.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash =
> "sha256:023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6"},
> @@ -665,6 +868,7 @@ version = "2.0.0.10"
> description = "Typing stubs for invoke"
> optional = false
> python-versions = ">=3.7"
> +groups = ["dev"]
> files = [
> {file = "types-invoke-2.0.0.10.tar.gz", hash =
> "sha256:a54d7ecdc19e0c22cd2786ef2e64c2631715c78eba8a1bf40b511d0608f33a88"},
> {file = "types_invoke-2.0.0.10-py3-none-any.whl", hash =
> "sha256:2404e4279601fa96e14ef68321fd10a660a828677aabdcaeef6a5189778084ef"},
> @@ -672,13 +876,14 @@ files = [
>
> [[package]]
> name = "types-paramiko"
> -version = "3.5.0.20240928"
> +version = "4.0.0.20260518"
> description = "Typing stubs for paramiko"
> optional = false
> -python-versions = ">=3.8"
> +python-versions = ">=3.10"
> +groups = ["dev"]
> files = [
> - {file = "types-paramiko-3.5.0.20240928.tar.gz", hash =
> "sha256:79dd9b2ee510b76a3b60d8ac1f3f348c45fcecf01347ca79e14db726bbfc442d"},
> - {file = "types_paramiko-3.5.0.20240928-py3-none-any.whl", hash =
> "sha256:cda0aff4905fe8efe4b5448331a80e943d42a796bd4beb77a3eed3485bc96a85"},
> + {file = "types_paramiko-4.0.0.20260518-py3-none-any.whl", hash =
> "sha256:0ffaf1a6eb796833a49653cba4c7be13af51c8269d75234972d6239763dda270"},
> + {file = "types_paramiko-4.0.0.20260518.tar.gz", hash =
> "sha256:286f6830945cba63797eedf375ed87138d93198121253afe66c5d6dbcf91318d"},
> ]
>
> [package.dependencies]
> @@ -686,13 +891,14 @@ cryptography = ">=37.0.0"
>
> [[package]]
> name = "types-pyyaml"
> -version = "6.0.12.20240917"
> +version = "6.0.12.20260518"
> description = "Typing stubs for PyYAML"
> optional = false
> -python-versions = ">=3.8"
> +python-versions = ">=3.10"
> +groups = ["dev"]
> files = [
> - {file = "types-PyYAML-6.0.12.20240917.tar.gz", hash =
> "sha256:d1405a86f9576682234ef83bcb4e6fff7c9305c8b1fbad5e0bcd4f7dbdc9c587"},
> - {file = "types_PyYAML-6.0.12.20240917-py3-none-any.whl", hash =
> "sha256:392b267f1c0fe6022952462bf5d6523f31e37f6cea49b14cee7ad634b6301570"},
> + {file = "types_pyyaml-6.0.12.20260518-py3-none-any.whl", hash =
> "sha256:d2150f75a231c9fe9c7463bd29487d93e60bac90400287351384bc2284eba7cd"},
> + {file = "types_pyyaml-6.0.12.20260518.tar.gz", hash =
> "sha256:d917f83fb38462550338c1297faedd860b3ec83912b96b1e3d73255f7473e466"},
> ]
>
> [[package]]
> @@ -701,17 +907,33 @@ version = "4.12.2"
> description = "Backported and Experimental Type Hints for Python 3.8+"
> optional = false
> python-versions = ">=3.8"
> +groups = ["main", "dev"]
> +markers = "python_version < \"3.15\""
> files = [
> {file = "typing_extensions-4.12.2-py3-none-any.whl", hash =
> "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"},
> {file = "typing_extensions-4.12.2.tar.gz", hash =
> "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"},
> ]
>
> +[[package]]
> +name = "typing-extensions"
> +version = "4.15.0"
> +description = "Backported and Experimental Type Hints for Python 3.9+"
> +optional = false
> +python-versions = ">=3.9"
> +groups = ["main", "dev"]
> +markers = "python_version >= \"3.15\""
> +files = [
> + {file = "typing_extensions-4.15.0-py3-none-any.whl", hash =
> "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548"},
> + {file = "typing_extensions-4.15.0.tar.gz", hash =
> "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466"},
> +]
> +
> [[package]]
> name = "wrapt"
> version = "1.17.2"
> description = "Module for decorators, wrappers and monkey patching."
> optional = false
> python-versions = ">=3.8"
> +groups = ["main"]
> files = [
> {file = "wrapt-1.17.2-cp310-cp310-macosx_10_9_universal2.whl", hash =
> "sha256:3d57c572081fed831ad2d26fd430d565b76aa277ed1d30ff4d40670b1c0dd984"},
> {file = "wrapt-1.17.2-cp310-cp310-macosx_10_9_x86_64.whl", hash =
> "sha256:b5e251054542ae57ac7f3fba5d10bfff615b6c2fb09abeb37d2f1463f841ae22"},
> @@ -795,6 +1017,6 @@ files = [
> ]
>
> [metadata]
> -lock-version = "2.0"
> +lock-version = "2.1"
> python-versions = "^3.10"
> -content-hash =
> "aa6dff54827602c89ee125019291965de50d7a471ca48add889ea23aa5fd9b2f"
> +content-hash =
> "1ca3cdf5bf98c528845b5e22169322db8912fe437988635f4ebea088b2079463"
> diff --git a/dts/pyproject.toml b/dts/pyproject.toml
> index 8b061c3cee..b639af65b6 100644
> --- a/dts/pyproject.toml
> +++ b/dts/pyproject.toml
> @@ -28,12 +28,12 @@ aenum = "^3.1.15"
> pydantic = "^2.9.2"
>
> [tool.poetry.group.dev.dependencies]
> -mypy = "^1.13.0"
> +mypy = "^2.1.0"
> toml = "^0.10.2"
> -ruff = "^0.8.1"
> -types-paramiko = "^3.5.0.20240928"
> +ruff = "^0.15.16"
> +types-paramiko = "^4.0.0.20260518"
> types-invoke = "^2.0.0.10"
> -types-pyyaml = "^6.0.12.20240917"
> +types-pyyaml = "^6.0.12.20260518"
>
> [build-system]
> requires = ["poetry-core>=1.0.0"]
> diff --git a/dts/tests/TestSuite_cryptodev_throughput.py
> b/dts/tests/TestSuite_cryptodev_throughput.py
> index af0a5680ab..2fc0d8779a 100644
> --- a/dts/tests/TestSuite_cryptodev_throughput.py
> +++ b/dts/tests/TestSuite_cryptodev_throughput.py
> @@ -101,12 +101,12 @@ def _print_stats(self, test_vals: list[dict[str, int
> | float | str]]) -> None:
> print(f"{'Throughput Results'.center(border_len)}\n{'=' *
> border_len}")
> for k, v in test_vals[0].items():
> print(f"|{k.title():<{element_len}}", end="")
> - print(f"|\n{'='*border_len}")
> + print(f"|\n{'=' * border_len}")
>
> for test_val in test_vals:
> for k, v in test_val.items():
> print(f"|{v:<{element_len}}", end="")
> - print(f"|\n{'='*border_len}")
> + print(f"|\n{'=' * border_len}")
>
> def _verify_throughput(
> self,
> diff --git a/dts/tests/TestSuite_port_control.py
> b/dts/tests/TestSuite_port_control.py
> index 6be47838d0..b51fdc2959 100644
> --- a/dts/tests/TestSuite_port_control.py
> +++ b/dts/tests/TestSuite_port_control.py
> @@ -44,8 +44,7 @@ def _send_packets_and_verify(self) -> None:
> recv_pakts = [
> p
> for p in recv_pakts
> - if
> - (
> + if (
> # Remove padding from the bytes.
> hasattr(p, "load") and
> p.load.decode("utf-8").replace("\x00", "") == payload
> )
> diff --git a/dts/tests/TestSuite_single_core_forward_perf.py
> b/dts/tests/TestSuite_single_core_forward_perf.py
> index 1e7ab7b036..acdf8ae2f6 100644
> --- a/dts/tests/TestSuite_single_core_forward_perf.py
> +++ b/dts/tests/TestSuite_single_core_forward_perf.py
> @@ -144,7 +144,7 @@ def single_core_forward_perf(self) -> None:
> for params in self.test_parameters:
> verify(
> params["pass"] is True,
> - f"""Packets forwarded is less than {(1
> -self.delta_tolerance)*100}%
> + f"""Packets forwarded is less than {(1 -
> self.delta_tolerance) * 100}%
> of the expected baseline.
> Measured MPPS = {params["measured_mpps"]}
> Expected MPPS = {params["expected_mpps"]}""",
> --
> 2.54.0
>
>
[-- Attachment #2: Type: text/html, Size: 95456 bytes --]
^ permalink raw reply
* RE: [PATCH v1 0/5] prefix lcore role enum values
From: Morten Brørup @ 2026-06-18 18:52 UTC (permalink / raw)
To: Thomas Monjalon, Huisong Li
Cc: dev, andrew.rybchenko, zhanjie9, David Marchand, Bruce Richardson
In-Reply-To: <SdThFrO9S62xAryFCraiCQ@monjalon.net>
> From: Thomas Monjalon [mailto:thomas@monjalon.net]
> Sent: Thursday, 18 June 2026 18.20
>
> 17/06/2026 13:48, Morten Brørup:
> > > From: Huisong Li [mailto:lihuisong@huawei.com]
> > > Sent: Wednesday, 17 June 2026 12.28
> > >
> > > Add the RTE_LCORE_ prefix to the lcore role enum values in
> > > rte_lcore_role_t
> > > to follow DPDK naming conventions.
> > >
> > > - ROLE_RTE -> RTE_LCORE_ROLE_RTE
> > > - ROLE_OFF -> RTE_LCORE_ROLE_OFF
> > > - ROLE_SERVICE -> RTE_LCORE_ROLE_SERVICE
> > > - ROLE_NON_EAL -> RTE_LCORE_ROLE_NON_EAL
> > >
> > > Old names are kept as macros aliasing to the new names to preserve
> > > backward compatibility.
> > >
> >
> > Series-Acked-by: Morten Brørup <mb@smartsharesystems.com>
>
> Squashed and applied, thanks.
>
> I have a doubt about RTE_LCORE_ROLE_RTE: could we find a better name?
Yes, it made more sense when lcores were either used by DPDK or not.
Note that it's used by both workers and the main lcore.
>
> Also we should probably add some comments to explain each role.
+1
BTW, I thought the Non-EAL role was for registered control plane threads. But then I looked into Grout.
Grout uses the Non-EAL role for its dataplane threads. And the RTE role for its main thread, which is handling the control plane (which I suppose is not unusual).
Lcore roles and CPU core isolation is very flexible in DPDK. Maybe too flexible.
^ permalink raw reply
* Re: [PATCH v3 1/1] pcapng: add user-supplied timestamp support
From: Stephen Hemminger @ 2026-06-18 18:51 UTC (permalink / raw)
To: Morten Brørup; +Cc: Dawid Wesierski, dev, thomas, Marek Kasiewicz
In-Reply-To: <98CBD80474FA8B44BF855DF32C47DC35F65924@smartserver.smartshare.dk>
On Thu, 18 Jun 2026 18:45:19 +0200
Morten Brørup <mb@smartsharesystems.com> wrote:
> > From: Stephen Hemminger [mailto:stephen@networkplumber.org]
> > Sent: Thursday, 18 June 2026 17.23
> >
> > On Thu, 18 Jun 2026 10:38:15 -0400
> > Dawid Wesierski <dawid.wesierski@intel.com> wrote:
> >
> > > + * @param ts
> > > + * Packet timestamp in nanoseconds since the Unix epoch. If zero,
> > the
> > > + * current TSC is captured and converted to epoch ns by
> > > + * rte_pcapng_write_packets() when the packet is written.
> > > *
> >
> > It might help users if a helper rte_tsc_to_epoch() was exposed.
>
> +1
>
> Please note that such a helper would need to compensate for rte_rdtsc() drift.
>
> Simplified:
>
> int64_t rte_tsc_to_ns(tsc)
> {
> struct timespec ts = clock_gettime(CLOCK_REALTIME);
> int64_t now_ns = ts.tv_sec * NS_PER_S + ts.tv_nsec;
> int64_t now_tsc = rte_rdtsc();
> int64_t diff_tsc = tsc - tsc_now;
> return now_ns + diff_tsc * NS_PER_S / rte_get_tsc_hz();
> }
>
> A performance optimized version would take "now_ns" and "now_tsc" as parameters.
> And with "now_ns" passed as a parameter, the function also works with other clocks, such as CLOCK_MONOTONIC.
>
> Also see this discussion on the Grout mailing list:
> https://inbox.dpdk.org/grout/98CBD80474FA8B44BF855DF32C47DC35F6590E@smartserver.smartshare.dk/T/#m465a04ca2e8219612dd9c3efb4198d23d5813422
>
>
Inside rte_pcapng is already all the necessary state and setup.
Just not exposed to user. It does it without divide operation
^ permalink raw reply
* [PATCH v3 4/4] net/axgbe: fix descriptor status out-of-bounds access
From: Stephen Hemminger @ 2026-06-18 17:21 UTC (permalink / raw)
To: dev
Cc: Stephen Hemminger, stable, Selwin Sebastian,
Amaranath Somalapuram, Ravi Kumar
In-Reply-To: <20260618172544.338758-1-stephen@networkplumber.org>
Both axgbe_dev_rx_descriptor_status() and
axgbe_dev_tx_descriptor_status() compute the descriptor address as
desc[idx + offset] where idx is the masked ring position. When
idx + offset >= nb_desc, this reads past the end of the
descriptor ring buffer.
Fix by incorporating the offset into the index before masking,
using AXGBE_GET_DESC_IDX() which wraps with (nb_desc - 1).
Fixes: 0962b6055c08 ("net/axgbe: support descriptor status")
Cc: stable@dpdk.org
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
drivers/net/axgbe/axgbe_rxtx.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/net/axgbe/axgbe_rxtx.c b/drivers/net/axgbe/axgbe_rxtx.c
index 51a1aeb0b9..6f750d6ede 100644
--- a/drivers/net/axgbe/axgbe_rxtx.c
+++ b/drivers/net/axgbe/axgbe_rxtx.c
@@ -1205,8 +1205,8 @@ axgbe_dev_rx_descriptor_status(void *rx_queue, uint16_t offset)
if (offset >= rxq->nb_desc - rxq->dirty)
return RTE_ETH_RX_DESC_UNAVAIL;
- idx = AXGBE_GET_DESC_IDX(rxq, rxq->cur);
- desc = &rxq->desc[idx + offset];
+ idx = AXGBE_GET_DESC_IDX(rxq, rxq->cur + offset);
+ desc = &rxq->desc[idx];
if (!AXGMAC_GET_BITS_LE(desc->write.desc3, RX_NORMAL_DESC3, OWN))
return RTE_ETH_RX_DESC_DONE;
@@ -1228,8 +1228,8 @@ axgbe_dev_tx_descriptor_status(void *tx_queue, uint16_t offset)
if (offset >= txq->nb_desc - txq->dirty)
return RTE_ETH_TX_DESC_UNAVAIL;
- idx = AXGBE_GET_DESC_IDX(txq, txq->dirty + txq->free_batch_cnt - 1);
- desc = &txq->desc[idx + offset];
+ idx = AXGBE_GET_DESC_IDX(txq, txq->dirty + txq->free_batch_cnt - 1 + offset);
+ desc = &txq->desc[idx];
if (!AXGMAC_GET_BITS_LE(desc->desc3, TX_NORMAL_DESC3, OWN))
return RTE_ETH_TX_DESC_DONE;
--
2.53.0
^ permalink raw reply related
* [PATCH v3 3/4] net/axgbe: destroy mutexes on device close
From: Stephen Hemminger @ 2026-06-18 17:21 UTC (permalink / raw)
To: dev; +Cc: Stephen Hemminger, stable, Selwin Sebastian, Ravi Kumar
In-Reply-To: <20260618172544.338758-1-stephen@networkplumber.org>
Four pthread mutexes (xpcs_mutex, i2c_mutex, an_mutex, phy_mutex)
are initialized in eth_axgbe_dev_init() but never destroyed in
axgbe_dev_close(). This leaks kernel resources on every device
close/reopen cycle.
Add pthread_mutex_destroy() calls to the close path.
Fixes: 572890ef6625 ("net/axgbe: add structs for MAC init and reset")
Cc: stable@dpdk.org
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
drivers/net/axgbe/axgbe_ethdev.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/drivers/net/axgbe/axgbe_ethdev.c b/drivers/net/axgbe/axgbe_ethdev.c
index 415fc6d739..a4b5e9425f 100644
--- a/drivers/net/axgbe/axgbe_ethdev.c
+++ b/drivers/net/axgbe/axgbe_ethdev.c
@@ -2481,6 +2481,11 @@ axgbe_dev_close(struct rte_eth_dev *eth_dev)
/* Disable all interrupts in the hardware */
XP_IOWRITE(pdata, XP_INT_EN, 0x0);
+ pthread_mutex_destroy(&pdata->xpcs_mutex);
+ pthread_mutex_destroy(&pdata->i2c_mutex);
+ pthread_mutex_destroy(&pdata->an_mutex);
+ pthread_mutex_destroy(&pdata->phy_mutex);
+
return 0;
}
--
2.53.0
^ permalink raw reply related
* [PATCH v3 2/4] net/axgbe: fix Rx queue leak on descriptor init failure
From: Stephen Hemminger @ 2026-06-18 17:21 UTC (permalink / raw)
To: dev; +Cc: Stephen Hemminger, stable, Selwin Sebastian, Ravi Kumar
In-Reply-To: <20260618172544.338758-1-stephen@networkplumber.org>
When wrapper_rx_desc_init() fails to allocate an mbuf for queue i,
only queue i is released. Queues 0 through i-1 have already been
fully populated with mbufs assigned to sw_ring entries and
programmed into hardware descriptors, but are never cleaned up.
This leaks all mbufs from the previously initialized queues.
Fix by allocating all needed buffers ahead of time with
rte_pktmbuf_alloc_bulk().
Fixes: 7c4158a5b592 ("net/axgbe: add DMA programming and start/stop")
Cc: stable@dpdk.org
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
drivers/net/axgbe/axgbe_dev.c | 43 +++++++++++++++++++----------------
1 file changed, 24 insertions(+), 19 deletions(-)
diff --git a/drivers/net/axgbe/axgbe_dev.c b/drivers/net/axgbe/axgbe_dev.c
index 482d3d8062..10ddecf968 100644
--- a/drivers/net/axgbe/axgbe_dev.c
+++ b/drivers/net/axgbe/axgbe_dev.c
@@ -1011,13 +1011,29 @@ static void wrapper_tx_desc_init(struct axgbe_port *pdata)
static int wrapper_rx_desc_init(struct axgbe_port *pdata)
{
- struct axgbe_rx_queue *rxq;
- struct rte_mbuf *mbuf;
volatile union axgbe_rx_desc *desc;
- unsigned int i, j;
+ unsigned int i, j, k;
+ /* Allocate all receive buffers up front. */
for (i = 0; i < pdata->eth_dev->data->nb_rx_queues; i++) {
- rxq = pdata->eth_dev->data->rx_queues[i];
+ struct axgbe_rx_queue *rxq = pdata->eth_dev->data->rx_queues[i];
+
+ if (rte_pktmbuf_alloc_bulk(rxq->mb_pool, rxq->sw_ring, rxq->nb_desc) != 0) {
+ PMD_DRV_LOG_LINE(ERR, "RX mbuf alloc failed queue_id = %u, nb_desc = %u",
+ i, rxq->nb_desc);
+ for (k = 0; k < i; k++) {
+ rxq = pdata->eth_dev->data->rx_queues[k];
+
+ rte_pktmbuf_free_bulk(rxq->sw_ring, rxq->nb_desc);
+ memset(rxq->sw_ring, 0, rxq->nb_desc * sizeof(*rxq->sw_ring));
+ }
+ return -ENOMEM;
+ }
+ }
+
+ /* Buffers are available; publish them to the hardware */
+ for (i = 0; i < pdata->eth_dev->data->nb_rx_queues; i++) {
+ struct axgbe_rx_queue *rxq = pdata->eth_dev->data->rx_queues[i];
/* Initialize software ring entries */
rxq->mbuf_alloc = 0;
@@ -1026,22 +1042,11 @@ static int wrapper_rx_desc_init(struct axgbe_port *pdata)
desc = AXGBE_GET_DESC_PT(rxq, 0);
for (j = 0; j < rxq->nb_desc; j++) {
- mbuf = rte_mbuf_raw_alloc(rxq->mb_pool);
- if (mbuf == NULL) {
- PMD_DRV_LOG_LINE(ERR, "RX mbuf alloc failed queue_id = %u, idx = %d",
- (unsigned int)rxq->queue_id, j);
- axgbe_dev_rx_queue_release(pdata->eth_dev, i);
- return -ENOMEM;
- }
- rxq->sw_ring[j] = mbuf;
- /* Mbuf populate */
- mbuf->next = NULL;
- mbuf->data_off = RTE_PKTMBUF_HEADROOM;
- mbuf->nb_segs = 1;
+ struct rte_mbuf *mbuf = rxq->sw_ring[j];
+
+ /* mbuf is in reset state (nb_segs = 1, headroom, etc) */
mbuf->port = rxq->port_id;
- desc->read.baddr =
- rte_cpu_to_le_64(
- rte_mbuf_data_iova_default(mbuf));
+ desc->read.baddr = rte_cpu_to_le_64(rte_mbuf_data_iova_default(mbuf));
rte_wmb();
AXGMAC_SET_BITS_LE(desc->read.desc3,
RX_NORMAL_DESC3, OWN, 1);
--
2.53.0
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox