From e00fa48c03c1d01a12dcb04a14f2f84a462f728d Mon Sep 17 00:00:00 2001 From: Erik Everson Date: Tue, 12 May 2020 19:17:28 -0700 Subject: [PATCH 001/521] create the plasmapy.analysis sub-package --- plasmapy/analysis/__init__.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 plasmapy/analysis/__init__.py diff --git a/plasmapy/analysis/__init__.py b/plasmapy/analysis/__init__.py new file mode 100644 index 0000000000..e69de29bb2 From 940b9fc7206a68a704bae6a68b6f1e60424c0421 Mon Sep 17 00:00:00 2001 From: Erik Date: Sun, 2 Aug 2020 11:18:20 -0700 Subject: [PATCH 002/521] create the "Analyses & Diagnostics" documenation folder (/docs/ad/); initial commit for /docs/ad/index.rst --- docs/ad/ad_attention.inc | 6 ++++++ docs/ad/index.rst | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 docs/ad/ad_attention.inc create mode 100644 docs/ad/index.rst diff --git a/docs/ad/ad_attention.inc b/docs/ad/ad_attention.inc new file mode 100644 index 0000000000..688a7e70a7 --- /dev/null +++ b/docs/ad/ad_attention.inc @@ -0,0 +1,6 @@ +.. attention:: + The Analysis and Diagnostic framework is in active development at the moment. + For the foreseeable future, the api will be in continuous flux as functionality + is added and modified. To follow the package development please visit our + GitHub Project ( https://github.com/PlasmaPy/PlasmaPy/projects/19 ) and + comment on any of the relevant issues and/or pull requests. diff --git a/docs/ad/index.rst b/docs/ad/index.rst new file mode 100644 index 0000000000..82f7bdf7a7 --- /dev/null +++ b/docs/ad/index.rst @@ -0,0 +1,33 @@ +.. include:: ad_attention.inc + +.. _ad: + +====================== +Analyses & Diagnostics +====================== + +Analyses and diagnostics go hand-in-hand, but have subtle differences. Thus, +PlasmaPy gives them their own sub-packages, `plasmapy.analysis` and +`plasmapy.diagnostics`. + +Think of the `plasmapy.analysis` as your toolbox. It has all the tools +(functionality) you need to analyze your data. Functionality is built around +`numpy` arrays and each function has a well-defined, focused task. For example, +:func:`numpy.fft.fft` does one specific task, compute the one-dimensional +discrete Fourier Transform. Similarly, +:func:`plasmapy.analysis.swept_langmuir.find_floating_potential` only finds the +floating potential for a given langmuir trace. It does not have smoothing. +It does not do any filtering. It does not do any signal conditioning. It has a +singular task. + +Diagnostics on the other-hand have a much broader scope, which leverages the tools +defined in `plasmapy.analysis`. + +---- + +.. toctree:: + :maxdepth: 2 + :caption: The Packages + + Analyses + Diagnostics From 23229d2653c29473c7964c2c12da4bcdd228a14b Mon Sep 17 00:00:00 2001 From: Erik Date: Sun, 2 Aug 2020 11:19:31 -0700 Subject: [PATCH 003/521] move the diagnostics doc files /docs/diagnostics/ -> /docs/ad/diagnostics/; add attention admonition to index.rst --- docs/{ => ad}/diagnostics/index.rst | 4 +++- docs/{ => ad}/diagnostics/langmuir.rst | 0 docs/{ => ad}/diagnostics/thomson.rst | 0 3 files changed, 3 insertions(+), 1 deletion(-) rename docs/{ => ad}/diagnostics/index.rst (75%) rename docs/{ => ad}/diagnostics/langmuir.rst (100%) rename docs/{ => ad}/diagnostics/thomson.rst (100%) diff --git a/docs/diagnostics/index.rst b/docs/ad/diagnostics/index.rst similarity index 75% rename from docs/diagnostics/index.rst rename to docs/ad/diagnostics/index.rst index 719a2dd1e3..6f17442f83 100644 --- a/docs/diagnostics/index.rst +++ b/docs/ad/diagnostics/index.rst @@ -1,3 +1,5 @@ +.. include:: /ad/ad_attention.inc + .. _diagnostics: ******************************************* @@ -11,5 +13,5 @@ Plasma diagnostics (`plasmapy.diagnostics`) :maxdepth: 1 :caption: Sub-Packages and Modules - langmuir + Swept Langmuir Analysis (will be deprecated) thomson diff --git a/docs/diagnostics/langmuir.rst b/docs/ad/diagnostics/langmuir.rst similarity index 100% rename from docs/diagnostics/langmuir.rst rename to docs/ad/diagnostics/langmuir.rst diff --git a/docs/diagnostics/thomson.rst b/docs/ad/diagnostics/thomson.rst similarity index 100% rename from docs/diagnostics/thomson.rst rename to docs/ad/diagnostics/thomson.rst From efce2a13050db14fb450b062b3b832695485b2fa Mon Sep 17 00:00:00 2001 From: Erik Date: Sun, 2 Aug 2020 11:20:49 -0700 Subject: [PATCH 004/521] replace "Diagnostics" sidebar toctree entry with "Analyses & Diagnostics" --- docs/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/index.rst b/docs/index.rst index b5f232d92f..4c9845eb3a 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -40,7 +40,7 @@ package for plasma physics currently under development. :maxdepth: 1 :caption: Package features - Diagnostics + Analyses & Diagnostics Formulary Particles Particle Tracker From c709168e1c9bb10a3ed99a0841bb20094ddac1bf Mon Sep 17 00:00:00 2001 From: Erik Date: Sun, 2 Aug 2020 11:22:03 -0700 Subject: [PATCH 005/521] initial commit for /docs/ad/analysis/ --- docs/ad/analysis/index.rst | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 docs/ad/analysis/index.rst diff --git a/docs/ad/analysis/index.rst b/docs/ad/analysis/index.rst new file mode 100644 index 0000000000..d6ba44f133 --- /dev/null +++ b/docs/ad/analysis/index.rst @@ -0,0 +1,13 @@ +.. include:: /ad/ad_attention.inc + +.. py:currentmodule:: plasmapy.analysis + +.. _analysis: + +============================== +Analyses (`plasmapy.analysis`) +============================== + +blah balh + +.. automodule:: plasmapy.analysis From 4cb96c348f22a2a11a1679ca34a4aafa0c07403c Mon Sep 17 00:00:00 2001 From: Erik Date: Sun, 2 Aug 2020 11:22:30 -0700 Subject: [PATCH 006/521] add basic docstring to plasmapy/analysis/__init__.py --- plasmapy/analysis/__init__.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plasmapy/analysis/__init__.py b/plasmapy/analysis/__init__.py index e69de29bb2..1ea0340e52 100644 --- a/plasmapy/analysis/__init__.py +++ b/plasmapy/analysis/__init__.py @@ -0,0 +1,2 @@ +"""The analysis sub-package for PlasmaPy.""" +__all__ = [] From a13250e9aad225bd7f0577efd34758af7031b52e Mon Sep 17 00:00:00 2001 From: Erik Everson Date: Tue, 12 May 2020 19:27:44 -0700 Subject: [PATCH 007/521] create the plasmapy.diagnostics.swept_langmuir sub-package --- plasmapy/diagnostics/swept_langmuir/__init__.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 plasmapy/diagnostics/swept_langmuir/__init__.py diff --git a/plasmapy/diagnostics/swept_langmuir/__init__.py b/plasmapy/diagnostics/swept_langmuir/__init__.py new file mode 100644 index 0000000000..e69de29bb2 From 023b76303a10bc3e7fab14ed41c59d08fe11ad2e Mon Sep 17 00:00:00 2001 From: Erik Everson Date: Tue, 12 May 2020 19:19:03 -0700 Subject: [PATCH 008/521] create the plasmapy.analysis.swept_langmuir sub-package and define floating_potential.py with the find_floating_potential() function --- plasmapy/analysis/swept_langmuir/__init__.py | 6 + .../swept_langmuir/floating_potential.py | 152 ++++++++++++++++++ 2 files changed, 158 insertions(+) create mode 100644 plasmapy/analysis/swept_langmuir/__init__.py create mode 100644 plasmapy/analysis/swept_langmuir/floating_potential.py diff --git a/plasmapy/analysis/swept_langmuir/__init__.py b/plasmapy/analysis/swept_langmuir/__init__.py new file mode 100644 index 0000000000..07a04d12a2 --- /dev/null +++ b/plasmapy/analysis/swept_langmuir/__init__.py @@ -0,0 +1,6 @@ +""" +Sub-Package containing routines for analyzing swept Langmuir probe traces. +""" +__all__ = ['floating_potential'] + +from . import floating_potential diff --git a/plasmapy/analysis/swept_langmuir/floating_potential.py b/plasmapy/analysis/swept_langmuir/floating_potential.py new file mode 100644 index 0000000000..19b17a4eaf --- /dev/null +++ b/plasmapy/analysis/swept_langmuir/floating_potential.py @@ -0,0 +1,152 @@ +__all__ = ["find_floating_potential"] + +import numpy as np + +from scipy.stats import linregress +from warnings import warn + + +def find_floating_potential( + voltage: np.ndarray, + current: np.ndarray, + threshold: int = 1, + min_points: int = 5, +): + """ + Determines the floating potential (Vf) for a given Current-Voltage (IV) curve + generate by a swept Langmuir probe. The floating potential is the probe + bias where the collected current goes to zero. + + How it works + ------------ + #. The current array ``current` is searched for all points equal to zero and + point pairs that straddle ``current = 0`` to form a set of crossing-points. + #. Crossing-points are then grouped into crossing-islands in accordence to + the ``threshold`` keyword. + #. If multiple crossing-islands are found, then an warning issued and + `~numpy.nan` is returned. + #. To calculated the floating potential, a `~scipy.stats.linregress` is applied + to points making up the cross-island. If the number of points that make + up the crossing-island are less than ``min_points``, then each side of the + crossing-island is padded with the nearest neighbors until `min_points` is + satisfied. + + Parameters + ---------- + + voltage: np.ndarray + 1-D numpy array of ascending probe biases (in Volts) + + current: np.ndarray + 1-D numpy array of probe current (in A) corresponding to the :data:`voltage` + array + + threshold: positive, non-zero int + Max index distance between found crossing-points to group crossing-points + into crossing-islands. That is, if `threshold=5` then consecutive + crossing-points are considered to be in the same crossing-island if they are + within 5 indices of each other. (Default: 1) + + min_points: positive, non-zero int + The minimum number of points required for the linear regression. (Default: 5) + + Returns + ------- + vf: `numpy.float64` or `numpy.nan` + The calculated floating potential (in Volts). Returns `numpy.nan` if the + floating potential can not be determined. + + vf_err: `numpy.float64` or `numpy.nan` + The error associated with the floating potential calculation (in Volts). + Returns `numpy.nan` if the floating potential can not be determined. + + fit: Dict[str, Any] + A dictionary containing the linear regression fit results and parameters. + Keys are `'slope'`, `'slope_err'`, `'intercept'`, `'intercept_err'`, and + `'indices'`, where `'indices'` is a `slice` object corresponding to the + data points used in the fit. Returns an empty dict if the floating + potential can not be determined. + + """ + if current.min() > 0.0 or current.max() < 0: + warn("The Langmuir sweep has no floating potential.") + return np.nan, np.nan, {} + + # condition kwarg threshold + if isinstance(threshold, (int, float)): + threshold = int(np.round(threshold)) + if threshold < 1: + warn(f"threshold ({threshold}) is less than 1 and needs to be" + f" an int >= 1, using a value of 1") + threshold = 1 + else: + warn(f"threshold is NOT a integer >= 1, using a value of 1") + + # find possible crossing points (cp) + lower_vals = np.where(current <= 0, True, False) + upper_vals = np.where(0 <= current, True, False) + cp_exact = np.logical_and(lower_vals, upper_vals).nonzero()[0] + cp_low2high = np.logical_and(np.roll(lower_vals, 1), upper_vals).nonzero()[0] + cp_high2low = np.logical_and(np.roll(lower_vals, -1), upper_vals).nonzero()[0] + cp_candidates = np.concatenate(( + cp_exact, + cp_low2high, + cp_low2high - 1, + cp_high2low, + cp_high2low + 1, + )) + cp_candidates = np.unique(cp_candidates) # sorted and unique + + # How many crossing-islands? + cp_intervals = np.diff(cp_candidates) + if np.count_nonzero(np.where(cp_intervals > threshold, True, False)) != 0: + # There are multiple crossing points + warn("Unable to determine floating potential, Langmuir sweep has multiple " + "crossing-islands. Try adjusting 'threshold'.") + return np.nan, np.nan, {} + + # Construct crossing-island (pad if needed) + istart = cp_candidates[0] + istop = cp_candidates[-1] + iadd = (istop - istart + 1) - min_points + if iadd < 0: + # need to pad + iadd_2_start, iadd_2_stop = int(np.ceil(-iadd / 2.0)) + if istart - iadd_2_start < 0: + iadd_2_stop += iadd_2_start - istart + iadd_2_start = 0 + istart = 0 + if ((current.size - 1) - (istop + iadd_2_stop)) < 0: + iadd_2_start += iadd_2_stop - (current.size - 1 - istop) + # iadd_2_stop = 0 + istop = current.size - 1 + + istart = 0 if (istart - iadd_2_start < 0) else (istart - iadd_2_start) + # iadd_2_start = 0 + if (istop - istart + 1) < min_points: + warn(f"The number of elements in the current array ({current.size}) is less" + f" than 'min_points' ({min_points}).") + + # Perform Linear Regression Fit + volt_sub = voltage[istart:istop + 1] + curr_sub = current[istart:istop + 1] + fit = linregress(volt_sub, curr_sub) + + slope = fit[0] + slope_err = fit[4] + + intercept = fit[1] + intercept_err = np.sum(volt_sub ** 2) - ((np.sum(volt_sub) ** 2) / volt_sub.size) + intercept_err = slope_err * np.sqrt(1.0 / intercept_err) + + vf = -intercept / slope + vf_err = np.abs(vf * np.sqrt(((slope_err / slope) ** 2) + + ((intercept_err / intercept) ** 2))) + + fit = {'slope': slope, + 'slope_err': slope_err, + 'intercept': intercept, + 'intercept_err': intercept_err, + 'indices': slice(istart, istop + 1)} + + return vf, vf_err, fit From 1402b1f5dc8afb1b24dc8c975060bbacd115ba0d Mon Sep 17 00:00:00 2001 From: Erik Date: Sun, 2 Aug 2020 15:55:11 -0700 Subject: [PATCH 009/521] change from attention to important admonition --- docs/ad/ad_attention.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/ad/ad_attention.inc b/docs/ad/ad_attention.inc index 688a7e70a7..aff0f5da82 100644 --- a/docs/ad/ad_attention.inc +++ b/docs/ad/ad_attention.inc @@ -1,4 +1,4 @@ -.. attention:: +.. important:: The Analysis and Diagnostic framework is in active development at the moment. For the foreseeable future, the api will be in continuous flux as functionality is added and modified. To follow the package development please visit our From af979dc2eba68cd5f2206c79bd02aba8e6473a6f Mon Sep 17 00:00:00 2001 From: Erik Date: Sun, 2 Aug 2020 15:55:51 -0700 Subject: [PATCH 010/521] expose plasmapy.analysis.swept_langmuir to the plasmapy.analysis namespace --- plasmapy/analysis/__init__.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plasmapy/analysis/__init__.py b/plasmapy/analysis/__init__.py index 1ea0340e52..d9380bba91 100644 --- a/plasmapy/analysis/__init__.py +++ b/plasmapy/analysis/__init__.py @@ -1,2 +1,4 @@ """The analysis sub-package for PlasmaPy.""" __all__ = [] + +from plasmapy.analysis import swept_langmuir From e8b0e21d16550f5bfa18f161e1bf7ead4a317a48 Mon Sep 17 00:00:00 2001 From: Erik Date: Sun, 2 Aug 2020 15:56:25 -0700 Subject: [PATCH 011/521] add ad admonition and an additional warning admonition --- docs/ad/diagnostics/langmuir.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/ad/diagnostics/langmuir.rst b/docs/ad/diagnostics/langmuir.rst index 3d71ec16cb..ce0bab6fef 100644 --- a/docs/ad/diagnostics/langmuir.rst +++ b/docs/ad/diagnostics/langmuir.rst @@ -1,3 +1,8 @@ +.. include:: /ad/ad_attention.inc + +.. warning:: + This package will be deprecated in favor of `plasmapy.analysis.swept_langmuir`. + .. _langmuir: ***************** From 35e07ada9a274a10654db89a694459fe0736e88e Mon Sep 17 00:00:00 2001 From: Erik Date: Sun, 2 Aug 2020 15:57:05 -0700 Subject: [PATCH 012/521] create /docs/ad/analysis/swept_langmuir.rst page --- docs/ad/analysis/swept_langmuir.rst | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 docs/ad/analysis/swept_langmuir.rst diff --git a/docs/ad/analysis/swept_langmuir.rst b/docs/ad/analysis/swept_langmuir.rst new file mode 100644 index 0000000000..4709fb2201 --- /dev/null +++ b/docs/ad/analysis/swept_langmuir.rst @@ -0,0 +1,26 @@ +.. include:: /ad/ad_attention.inc + +.. py:currentmodule:: plasmapy.analysis.swept_langmuir + +Swept Langmuir Analysis Module +============================== + +this is the swept langmuir module + +API +--- + +.. automodule:: plasmapy.analysis.swept_langmuir + +Sub-Packages & Modules +^^^^^^^^^^^^^^^^^^^^^^ + +.. autosummary:: + + floating_potential + +.. automodapi:: plasmapy.analysis.swept_langmuir + :no-main-docstr: + :no-heading: + :include-all-objects: + :headings: "^-" From d69bad67782c719a85a00ccdde5031250472337f Mon Sep 17 00:00:00 2001 From: Erik Date: Sun, 2 Aug 2020 15:57:28 -0700 Subject: [PATCH 013/521] create api_static stub file plasmapy.analysis.swept_langmuir.floating_potential.rst --- ...mapy.analysis.swept_langmuir.floating_potential.rst | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 docs/api_static/plasmapy.analysis.swept_langmuir.floating_potential.rst diff --git a/docs/api_static/plasmapy.analysis.swept_langmuir.floating_potential.rst b/docs/api_static/plasmapy.analysis.swept_langmuir.floating_potential.rst new file mode 100644 index 0000000000..b576679a60 --- /dev/null +++ b/docs/api_static/plasmapy.analysis.swept_langmuir.floating_potential.rst @@ -0,0 +1,10 @@ +:orphan: + +`plasmapy.analysis.swept_langmuir.floating_potential` +===================================================== + +.. currentmodule:: plasmapy.analysis.swept_langmuir.floating_potential + +.. automodapi:: plasmapy.analysis.swept_langmuir.floating_potential + :include-all-objects: + :no-heading: From 4bd4fb29c5fa6a8c945f48bc88478429153a1501 Mon Sep 17 00:00:00 2001 From: Erik Date: Sun, 2 Aug 2020 15:58:06 -0700 Subject: [PATCH 014/521] add swept langmuir doc pages to /docs/ad/analysis/index.rst --- docs/ad/analysis/index.rst | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/docs/ad/analysis/index.rst b/docs/ad/analysis/index.rst index d6ba44f133..3b8355f0b7 100644 --- a/docs/ad/analysis/index.rst +++ b/docs/ad/analysis/index.rst @@ -8,6 +8,25 @@ Analyses (`plasmapy.analysis`) ============================== -blah balh +.. toctree:: + :maxdepth: 1 + + Swept Langmuir + +API +--- .. automodule:: plasmapy.analysis + +Sub-Packages & Modules +^^^^^^^^^^^^^^^^^^^^^^ + +.. autosummary:: + + swept_langmuir + +.. automodapi:: plasmapy.analysis + :no-main-docstr: + :no-heading: + :include-all-objects: + :headings: "^-" From f0f8c10b96522f5ebe957c4d10d47e145719894c Mon Sep 17 00:00:00 2001 From: Erik Everson Date: Tue, 11 Aug 2020 12:11:34 -0700 Subject: [PATCH 015/521] fix typos MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Dominik StaƄczak --- docs/ad/ad_attention.inc | 2 +- plasmapy/analysis/swept_langmuir/floating_potential.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/ad/ad_attention.inc b/docs/ad/ad_attention.inc index aff0f5da82..48f7036f4e 100644 --- a/docs/ad/ad_attention.inc +++ b/docs/ad/ad_attention.inc @@ -1,6 +1,6 @@ .. important:: The Analysis and Diagnostic framework is in active development at the moment. - For the foreseeable future, the api will be in continuous flux as functionality + For the foreseeable future, the API will be in continuous flux as functionality is added and modified. To follow the package development please visit our GitHub Project ( https://github.com/PlasmaPy/PlasmaPy/projects/19 ) and comment on any of the relevant issues and/or pull requests. diff --git a/plasmapy/analysis/swept_langmuir/floating_potential.py b/plasmapy/analysis/swept_langmuir/floating_potential.py index 19b17a4eaf..f9a649543e 100644 --- a/plasmapy/analysis/swept_langmuir/floating_potential.py +++ b/plasmapy/analysis/swept_langmuir/floating_potential.py @@ -25,7 +25,7 @@ def find_floating_potential( the ``threshold`` keyword. #. If multiple crossing-islands are found, then an warning issued and `~numpy.nan` is returned. - #. To calculated the floating potential, a `~scipy.stats.linregress` is applied + #. To calculate the floating potential, a `~scipy.stats.linregress` is applied to points making up the cross-island. If the number of points that make up the crossing-island are less than ``min_points``, then each side of the crossing-island is padded with the nearest neighbors until `min_points` is From bf7f52020ccc5457ca3009d193557453909265c9 Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 4 Sep 2020 16:36:32 -0700 Subject: [PATCH 016/521] expose `find_floating_potential` to plasmapy.analysis.swept_langmuir namespace --- plasmapy/analysis/swept_langmuir/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plasmapy/analysis/swept_langmuir/__init__.py b/plasmapy/analysis/swept_langmuir/__init__.py index 07a04d12a2..e966f6c190 100644 --- a/plasmapy/analysis/swept_langmuir/__init__.py +++ b/plasmapy/analysis/swept_langmuir/__init__.py @@ -1,6 +1,6 @@ """ Sub-Package containing routines for analyzing swept Langmuir probe traces. """ -__all__ = ['floating_potential'] +__all__ = ['find_floating_potential'] -from . import floating_potential +from plasmapy.analysis.swept_langmuir.floating_potential import find_floating_potential From c233b15133b0f1749a8ac73712287092b3a755e0 Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 4 Sep 2020 16:37:32 -0700 Subject: [PATCH 017/521] fix spelling mistakes --- plasmapy/analysis/swept_langmuir/floating_potential.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plasmapy/analysis/swept_langmuir/floating_potential.py b/plasmapy/analysis/swept_langmuir/floating_potential.py index f9a649543e..de876f40ac 100644 --- a/plasmapy/analysis/swept_langmuir/floating_potential.py +++ b/plasmapy/analysis/swept_langmuir/floating_potential.py @@ -21,11 +21,11 @@ def find_floating_potential( ------------ #. The current array ``current` is searched for all points equal to zero and point pairs that straddle ``current = 0`` to form a set of crossing-points. - #. Crossing-points are then grouped into crossing-islands in accordence to + #. Crossing-points are then grouped into crossing-islands in accordance to the ``threshold`` keyword. #. If multiple crossing-islands are found, then an warning issued and `~numpy.nan` is returned. - #. To calculate the floating potential, a `~scipy.stats.linregress` is applied + #. To calculated the floating potential, a `~scipy.stats.linregress` is applied to points making up the cross-island. If the number of points that make up the crossing-island are less than ``min_points``, then each side of the crossing-island is padded with the nearest neighbors until `min_points` is From b003da9cba8ac6ee812dc45f555d332f023efd13 Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 4 Sep 2020 16:39:12 -0700 Subject: [PATCH 018/521] repair generation of cp_candidates s.t. array endpoints are not accidentally included --- plasmapy/analysis/swept_langmuir/floating_potential.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/plasmapy/analysis/swept_langmuir/floating_potential.py b/plasmapy/analysis/swept_langmuir/floating_potential.py index de876f40ac..aac3b86f20 100644 --- a/plasmapy/analysis/swept_langmuir/floating_potential.py +++ b/plasmapy/analysis/swept_langmuir/floating_potential.py @@ -88,6 +88,12 @@ def find_floating_potential( cp_exact = np.logical_and(lower_vals, upper_vals).nonzero()[0] cp_low2high = np.logical_and(np.roll(lower_vals, 1), upper_vals).nonzero()[0] cp_high2low = np.logical_and(np.roll(lower_vals, -1), upper_vals).nonzero()[0] + + # adjust for array wrapping cause by np.roll + cp_low2high = cp_low2high[np.where(cp_low2high != 0, True, False)] + cp_high2low = cp_high2low[np.where(cp_high2low != current.size-1, True, False)] + + # collect all candidates cp_candidates = np.concatenate(( cp_exact, cp_low2high, From 0f8c227a711771b9052c8e09e8e1f7194c580f21 Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 4 Sep 2020 16:42:57 -0700 Subject: [PATCH 019/521] add kwargs retfit and retislands for returning fit info and island indices respectively --- plasmapy/analysis/swept_langmuir/floating_potential.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plasmapy/analysis/swept_langmuir/floating_potential.py b/plasmapy/analysis/swept_langmuir/floating_potential.py index aac3b86f20..66874bddda 100644 --- a/plasmapy/analysis/swept_langmuir/floating_potential.py +++ b/plasmapy/analysis/swept_langmuir/floating_potential.py @@ -11,6 +11,8 @@ def find_floating_potential( current: np.ndarray, threshold: int = 1, min_points: int = 5, + retfit: bool = False, + retislands: bool = False, ): """ Determines the floating potential (Vf) for a given Current-Voltage (IV) curve From 647416268f497b671751bf908f5b357cd4150be3 Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 4 Sep 2020 16:43:52 -0700 Subject: [PATCH 020/521] introduce meta_dict for island and fit info; update collection of island indices and add to meta_dict --- .../swept_langmuir/floating_potential.py | 27 ++++++++++++++++--- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/plasmapy/analysis/swept_langmuir/floating_potential.py b/plasmapy/analysis/swept_langmuir/floating_potential.py index 66874bddda..2317db740b 100644 --- a/plasmapy/analysis/swept_langmuir/floating_potential.py +++ b/plasmapy/analysis/swept_langmuir/floating_potential.py @@ -70,6 +70,8 @@ def find_floating_potential( potential can not be determined. """ + meta_dict = {} + if current.min() > 0.0 or current.max() < 0: warn("The Langmuir sweep has no floating potential.") return np.nan, np.nan, {} @@ -107,11 +109,28 @@ def find_floating_potential( # How many crossing-islands? cp_intervals = np.diff(cp_candidates) - if np.count_nonzero(np.where(cp_intervals > threshold, True, False)) != 0: + threshold_indices = np.where(cp_intervals > threshold)[0] + n_islands = threshold_indices.size + 1 + if retislands: + if n_islands == 1: + meta_dict['islands'] = [slice(cp_candidates[0], cp_candidates[-1]+1)] + else: + isl_start = np.concatenate(( + [cp_candidates[0]], + cp_candidates[threshold_indices+1], + )) + isl_stop = np.concatenate(( + cp_candidates[threshold_indices]+1, + [cp_candidates[-1]+1], + )) + meta_dict['islands'] = [] + for start, stop in zip(isl_start, isl_stop): + meta_dict['islands'].append(slice(start, stop)) + if n_islands != 1: # There are multiple crossing points - warn("Unable to determine floating potential, Langmuir sweep has multiple " - "crossing-islands. Try adjusting 'threshold'.") - return np.nan, np.nan, {} + warn(f"Unable to determine floating potential, Langmuir sweep has " + f"{n_islands} crossing-islands. Try adjusting keyword 'threshold'" + f"and/or smooth the current.") # Construct crossing-island (pad if needed) istart = cp_candidates[0] From cdf7f6d3bfa5ff95c82e96a4d588a6b22f3936ec Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 4 Sep 2020 16:45:15 -0700 Subject: [PATCH 021/521] repair padding of crossing island s.t. points are actually added to it --- .../swept_langmuir/floating_potential.py | 36 ++++++++++++------- 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/plasmapy/analysis/swept_langmuir/floating_potential.py b/plasmapy/analysis/swept_langmuir/floating_potential.py index 2317db740b..818fc5c8d9 100644 --- a/plasmapy/analysis/swept_langmuir/floating_potential.py +++ b/plasmapy/analysis/swept_langmuir/floating_potential.py @@ -137,22 +137,34 @@ def find_floating_potential( istop = cp_candidates[-1] iadd = (istop - istart + 1) - min_points if iadd < 0: - # need to pad - iadd_2_start, iadd_2_stop = int(np.ceil(-iadd / 2.0)) - if istart - iadd_2_start < 0: - iadd_2_stop += iadd_2_start - istart - iadd_2_start = 0 + # pad front + ipad_2_start = ipad_2_stop = int(np.ceil(-iadd / 2.0)) + if istart - ipad_2_start < 0: + ipad_2_stop += ipad_2_start - istart + ipad_2_start = 0 istart = 0 - if ((current.size - 1) - (istop + iadd_2_stop)) < 0: - iadd_2_start += iadd_2_stop - (current.size - 1 - istop) - # iadd_2_stop = 0 + else: + istart -= ipad_2_start + ipad_2_start = 0 + + # pad rear + if ((current.size - 1) - (istop + ipad_2_stop)) < 0: + ipad_2_start += ipad_2_stop - (current.size - 1 - istop) istop = current.size - 1 + else: + istop += ipad_2_stop + + # re-pad front if possible + if ipad_2_start > 0: + if istart - ipad_2_start < 0: + istart = 0 + else: + istart -= ipad_2_start - istart = 0 if (istart - iadd_2_start < 0) else (istart - iadd_2_start) - # iadd_2_start = 0 if (istop - istart + 1) < min_points: - warn(f"The number of elements in the current array ({current.size}) is less" - f" than 'min_points' ({min_points}).") + warn(f"The number of elements in the current array " + f"({istop - istart + 1}) is less than 'min_points' " + f"({min_points}).") # Perform Linear Regression Fit volt_sub = voltage[istart:istop + 1] From 2c166eae1a2df82d43db415e84a99e01aae86e59 Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 4 Sep 2020 16:47:03 -0700 Subject: [PATCH 022/521] add fit info to meta_dict; cleanup definition of vf_err; fully implement retislands and refit; add check for monotonic voltage array --- .../swept_langmuir/floating_potential.py | 55 +++++++++++++++---- 1 file changed, 44 insertions(+), 11 deletions(-) diff --git a/plasmapy/analysis/swept_langmuir/floating_potential.py b/plasmapy/analysis/swept_langmuir/floating_potential.py index 818fc5c8d9..77be1f6dc2 100644 --- a/plasmapy/analysis/swept_langmuir/floating_potential.py +++ b/plasmapy/analysis/swept_langmuir/floating_potential.py @@ -74,7 +74,23 @@ def find_floating_potential( if current.min() > 0.0 or current.max() < 0: warn("The Langmuir sweep has no floating potential.") - return np.nan, np.nan, {} + + ret = (np.nan, np.nan) + if retislands or retfit: + ret += (meta_dict,) + + return ret + + # check voltage is monotonically increasing/decreasing + voltage_diff = np.diff(voltage) + if not (np.all(voltage_diff >= 0) or np.all(voltage_diff <= 0)): + warn("The voltage array is not monotonically increasing or decreasing.") + + ret = (np.nan, np.nan) + if retislands or retfit: + ret += (meta_dict,) + + return ret # condition kwarg threshold if isinstance(threshold, (int, float)): @@ -132,6 +148,12 @@ def find_floating_potential( f"{n_islands} crossing-islands. Try adjusting keyword 'threshold'" f"and/or smooth the current.") + ret = (np.nan, np.nan) + if retislands or retfit: + ret += (meta_dict,) + + return ret + # Construct crossing-island (pad if needed) istart = cp_candidates[0] istop = cp_candidates[-1] @@ -179,13 +201,24 @@ def find_floating_potential( intercept_err = slope_err * np.sqrt(1.0 / intercept_err) vf = -intercept / slope - vf_err = np.abs(vf * np.sqrt(((slope_err / slope) ** 2) - + ((intercept_err / intercept) ** 2))) - - fit = {'slope': slope, - 'slope_err': slope_err, - 'intercept': intercept, - 'intercept_err': intercept_err, - 'indices': slice(istart, istop + 1)} - - return vf, vf_err, fit + vf_err = ( + np.abs(vf) + * np.sqrt(((slope_err / slope) ** 2) + + ((intercept_err / intercept) ** 2)) + ) + + if retfit: + meta_dict.update({ + 'slope': slope, + 'slope_err': slope_err, + 'intercept': intercept, + 'intercept_err': intercept_err, + 'rsq': fit[2], + 'indices': slice(istart, istop + 1), + }) + + ret = (vf, vf_err) + if retislands or retfit: + ret += (meta_dict,) + + return ret From cff5bc42a8e6c6059537b3664642e495c423a601 Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 7 Sep 2020 19:21:47 -0700 Subject: [PATCH 023/521] add a notebook for adding noise to one of the smooth langmuir samples --- .../langmuir_samples/_generate_noisy.ipynb | 104 ++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 docs/notebooks/langmuir_samples/_generate_noisy.ipynb diff --git a/docs/notebooks/langmuir_samples/_generate_noisy.ipynb b/docs/notebooks/langmuir_samples/_generate_noisy.ipynb new file mode 100644 index 0000000000..26d8e30f3a --- /dev/null +++ b/docs/notebooks/langmuir_samples/_generate_noisy.ipynb @@ -0,0 +1,104 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Generate noisy signals\n", + "\n", + "The default langmuir samples are not noisy and, thus, do not properly reflect real world data. This notebook will add noise to the signals to help simulate real world data." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [], + "source": [ + "import astropy.units as u\n", + "import numpy as np\n", + "import os\n", + "\n", + "from plasmapy.utils.decorators import validate_quantities" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [], + "source": [ + "# noise generator\n", + "@validate_quantities\n", + "def add_noise(signal, snr_db: u.dB = 10 * u.dB):\n", + " sig_pwr = signal ** 2\n", + " sig_pwr_ave = np.mean(sig_pwr)\n", + " sig_pwr_ave_db = 10. * np.log10(sig_pwr_ave)\n", + " \n", + " noise_pwr_ave_db = sig_pwr_ave_db - snr_db.value\n", + " noise_pwr_ave = 10.0 ** (noise_pwr_ave_db / 10.0)\n", + " \n", + " noise = np.random.normal(0.0, np.sqrt(noise_pwr_ave), signal.size)\n", + " \n", + " return signal + noise" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [], + "source": [ + "# read in example data\n", + "# this can be found at \n", + "# https://github.com/PlasmaPy/PlasmaPy/blob/master/docs/notebooks/langmuir_samples/Beckers2017.npy\n", + "#\n", + "filename = \"Beckers2017.npy\"\n", + "samples_path = os.path.join(os.path.abspath(\"./\"))\n", + "path = os.path.join(samples_path, filename)\n", + "voltage, current = np.load(path)\n", + "\n", + "# add some artificial noise to simulate reliztic digitized signals\n", + "voltage = add_noise(voltage, 38 * u.dB)\n", + "current = add_noise(current, 28 * u.dB)" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [], + "source": [ + "save = False\n", + "if save:\n", + " save_path = os.path.join(samples_path, filename + \"_noisy.npy\")\n", + " with open(save_path, \"wb\") as fp:\n", + " np.save(fp, [voltage, current])" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "plasmapy37-nb", + "language": "python", + "name": "plasmapy37-nb" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.6" + }, + "nbsphinx": { + "orphan": true + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} From 44faa1e75755317fc0e14b42c1e9de70bdb6f7eb Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 7 Sep 2020 19:22:30 -0700 Subject: [PATCH 024/521] create a noisy Beckers2017.npy (Beckers2017_noisy.npy) --- .../langmuir_samples/Beckers2017_noisy.npy | Bin 0 -> 4992 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 docs/notebooks/langmuir_samples/Beckers2017_noisy.npy diff --git a/docs/notebooks/langmuir_samples/Beckers2017_noisy.npy b/docs/notebooks/langmuir_samples/Beckers2017_noisy.npy new file mode 100644 index 0000000000000000000000000000000000000000..0577fe83ca1314d79ec47bc0c5a2697f5a7237a3 GIT binary patch literal 4992 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 literal 0 HcmV?d00001 From 1e65c61ec2a373af21a7e03c55b70943de699113 Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 7 Sep 2020 19:23:57 -0700 Subject: [PATCH 025/521] initial commit for plasmapy.analysis.swept_langmuir.fit_functions.py --- .../analysis/swept_langmuir/fit_functions.py | 258 ++++++++++++++++++ 1 file changed, 258 insertions(+) create mode 100644 plasmapy/analysis/swept_langmuir/fit_functions.py diff --git a/plasmapy/analysis/swept_langmuir/fit_functions.py b/plasmapy/analysis/swept_langmuir/fit_functions.py new file mode 100644 index 0000000000..d770003464 --- /dev/null +++ b/plasmapy/analysis/swept_langmuir/fit_functions.py @@ -0,0 +1,258 @@ +""" +`FitFunction` classes designed to assist in curve fitting of swept Langmuir +traces. +""" +__all__ = [ + "AbstractFitFunction", + "ExponentialOffsetFitFunction", + "LinearFitFunction", +] +import numpy as np + +from abc import ABC, abstractmethod +from scipy.stats import linregress +from scipy.optimize import curve_fit, fsolve +from typing import Tuple + + +class AbstractFitFunction(ABC): + """ + Abstract class for defining fit functions and the tools for fitting the + function to a set of data. These were originally designed for assisting in + fitting curves to swept langmuir data. + """ + _parameters = None # type: Tuple + _parameters_err = None # type: Tuple + _covariance_matrix = None + _rsq = None + + def __call__(self, x): + """ + The fit function. + + Parameters + ---------- + x: array_like + Dependent variables. + + Returns + ------- + array_like + Corresponding independent variables of dependent variables `x`. + """ + return self._func(x, *self.parameters) + + def __repr__(self): + return f"{self.__str__()} {self.__class__}" + + def __str__(self): + return f"Unspecified f(x)" + + @abstractmethod + def _func(self, x, *args): + """ + The fit function. + + Parameters + ---------- + x: array_like + Independent variables to be passed to the fit function. + *args + The parameters that will be adjusted to make the fit. + + Returns + ------- + array: + The calculated dependent variables of the independent variables `x`. + """ + raise NotImplementedError + + @property + def parameters(self) -> Tuple: + """The fitted parameters for the fit function.""" + return self._parameters + + @property + def parameters_err(self) -> Tuple: + """The associated errors of the fit `parameters`.""" + return self._parameters_err + + @property + @abstractmethod + def latex_str(self) -> str: + """Latex friendly representation of the fit function.""" + raise NotImplementedError + + def root_solve(self, x0, **kwargs): + """ + Solve for the root of the fit function (i.e. `f(x) = 0`). + + Parameters + ---------- + x0: `~np.ndarray` + The starting estimate for the roots of `f(x) = 0`. + + **kwargs + Any keyword accepted by `scipy.optimize.fsolve`, except for `args`. + + Returns + ------- + x : ndarray + The solution (or the result of the last iteration for an + unsuccessful call). + infodict : dict + A dictionary of optional outputs with the keys: + + ``nfev`` + number of function calls + ``njev`` + number of Jacobian calls + ``fvec`` + function evaluated at the output + ``fjac`` + the orthogonal matrix, q, produced by the QR + factorization of the final approximate Jacobian + matrix, stored column wise + ``r`` + upper triangular matrix produced by QR factorization + of the same matrix + ``qtf`` + the vector ``(transpose(q) * fvec)`` + + ier : int + An integer flag. Set to 1 if a solution was found, otherwise refer + to `mesg` for more information. + mesg : str + If no solution is found, `mesg` details the cause of failure. + """ + kwargs["args"] = self.parameters + return fsolve(self._func, x0, **kwargs) + + @property + def rsq(self): + """Coefficient of determination (r-squared) value of the fit.""" + return self._rsq + + def curve_fit(self, xdata, ydata, **kwargs): + """ + Use non-linear least squares to fit the fit function to (`xdata`, `ydata`). + This uses `scipy.optimize.curve_fit`. + + Parameters + ---------- + xdata: array_like + The independent variable where data is measured. Should be 1D of + length M. + + ydata: array_like + The dependent data associated with `xdata`. + + **kwargs + Any keywords accepted by `scipy.optimize.curve_fit`. + + Returns + ------- + popt : array + Optimal values for the parameters so that the sum of the squared + residuals of ``f(xdata, *popt) - ydata`` is minimized. + + pcov : 2-D array + The estimated covariance of popt. The diagonals provide the variance + of the parameter estimate. To compute one standard deviation errors + on the parameters use ``perr = np.sqrt(np.diag(pcov))``. + How the `sigma` parameter affects the estimated covariance + depends on `absolute_sigma` argument, as described above. + If the Jacobian matrix at the solution doesn't have a full rank, then + 'lm' method returns a matrix filled with ``np.inf``, on the other hand + 'trf' and 'dogbox' methods use Moore-Penrose pseudoinverse to compute + the covariance matrix. + + Raises + ------ + ValueError + if either `ydata` or `xdata` contain NaNs, or if incompatible options + are used. + + RuntimeError + if the least-squares minimization fails. + + ~scipy.optimize.OptimizeWarning + if covariance of the parameters can not be estimated. + + """ + popt, pcov = curve_fit(self._func, xdata, ydata, **kwargs) + self._parameters = tuple(popt.tolist()) + self._parameters_err = tuple(np.sqrt(np.diag(pcov)).tolist()) + + # calc rsq + # rsq = 1 - (ss_res / ss_tot) + residuals = ydata - self._func(xdata, *self.parameters) + ss_res = np.sum(residuals ** 2) + ss_tot = np.sum((ydata - np.mean(ydata)) ** 2) + self._rsq = 1 - (ss_res / ss_tot) + + return popt, pcov + + +class ExponentialOffsetFitFunction(AbstractFitFunction): + def __str__(self): + return f"f(x) = A exp(B x) + C" + + def _func(self, x, a, b, c): + return a * np.exp(b * x) + c + + @property + def latex_str(self) -> str: + return fr"A \, \exp(B \, x) + C" + + def root_solve(self, *args, reterr=True, **kwargs): + a, b, c = self.parameters + root = np.log(-c / a) / b + + if reterr: + a_err, b_err, c_err = self.parameters_err + a_term = a_err / (a * b) + b_term = b_err * root / b + c_term = c_err / (b * c) + err = np.sqrt(a_term ** 2 + b_term ** 2 + c_term ** 2) + + return root, err + return root + + +class LinearFitFunction(AbstractFitFunction): + def __str__(self): + return f"f(x) = m x + b" + + def _func(self, x, m, b): + return m * x + b + + @property + def latex_str(self) -> str: + return fr"m \, x + b" + + def root_solve(self, *args, reterr=True, **kwargs): + m, b = self.parameters + root = -b / m + + if reterr: + m_err, b_err = self.parameters_err + err = np.abs(root) * np.sqrt((m_err / m) ** 2 + (b_err / b) ** 2) + + return root, err + return root + + def curve_fit(self, xdata, ydata, **kwargs): + results = linregress(xdata, ydata) + + m = results[0] + b = results[1] + self._parameters = (m, b) + + m_err = results[4] + b_err = np.sum(xdata ** 2) - ((np.sum(xdata) ** 2) / xdata.size) + b_err = m_err * np.sqrt(1.0 / b_err) + self._parameters_err = (m_err, b_err) + + self._rsq = results[2] ** 2 + return results From 3007c0ec8320f79ec14db8d7b6174fbc2beec824 Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 7 Sep 2020 19:24:54 -0700 Subject: [PATCH 026/521] add to exclude_patterns "notebooks/langmuir_samples" and "*/.ipynb_checkpoints" --- docs/conf.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/docs/conf.py b/docs/conf.py index 0dfbf602e7..f438d5c330 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -107,7 +107,13 @@ # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. # This patterns also effect to html_static_path and html_extra_path -exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"] +exclude_patterns = [ + "_build", + "Thumbs.db", + ".DS_Store", + "notebooks/langmuir_samples", + "*/.ipynb_checkpoints", +] # The name of the Pygments (syntax highlighting) style to use. pygments_style = "sphinx" From b18d451f4c5782b813b5c37edbf420a4cf1d116d Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 7 Sep 2020 19:25:35 -0700 Subject: [PATCH 027/521] create api_static stub file for plasmapy.analysis.swept_langmuir.fit_functions --- .../plasmapy.analysis.swept_langmuir.fit_functions.rst | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 docs/api_static/plasmapy.analysis.swept_langmuir.fit_functions.rst diff --git a/docs/api_static/plasmapy.analysis.swept_langmuir.fit_functions.rst b/docs/api_static/plasmapy.analysis.swept_langmuir.fit_functions.rst new file mode 100644 index 0000000000..912e5fc2b8 --- /dev/null +++ b/docs/api_static/plasmapy.analysis.swept_langmuir.fit_functions.rst @@ -0,0 +1,10 @@ +:orphan: + +`plasmapy.analysis.swept_langmuir.fit_functions` +================================================ + +.. currentmodule:: plasmapy.analysis.swept_langmuir.fit_functions + +.. automodapi:: plasmapy.analysis.swept_langmuir.fit_functions + :include-all-objects: + :no-heading: From 855a2ee2bc34147f234267891402fc951eb5328d Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 7 Sep 2020 19:30:15 -0700 Subject: [PATCH 028/521] implement FitFunctions; create FloatingPotentialResults namedtuple for returning values; eliminate kwargs retfit and retislands; add kwarg fit_type; update behavior of min_points to all for all points, specified number of points, or a fraction of the array size --- .../swept_langmuir/floating_potential.py | 212 ++++++++++-------- 1 file changed, 114 insertions(+), 98 deletions(-) diff --git a/plasmapy/analysis/swept_langmuir/floating_potential.py b/plasmapy/analysis/swept_langmuir/floating_potential.py index 77be1f6dc2..d103c2c8aa 100644 --- a/plasmapy/analysis/swept_langmuir/floating_potential.py +++ b/plasmapy/analysis/swept_langmuir/floating_potential.py @@ -1,18 +1,26 @@ +"""Functionality for determining the floating potential of a Langmuir sweep.""" __all__ = ["find_floating_potential"] import numpy as np -from scipy.stats import linregress +from collections import namedtuple from warnings import warn +from typing import Union +from plasmapy.analysis.swept_langmuir.fit_functions import ( + ExponentialOffsetFitFunction, + LinearFitFunction, +) + +FloatingPotentialResults = namedtuple("FloatingPotentialResults", + ("vf", "vf_err", "info")) def find_floating_potential( voltage: np.ndarray, current: np.ndarray, threshold: int = 1, - min_points: int = 5, - retfit: bool = False, - retislands: bool = False, + min_points: Union[int, float] = None, + fit_type: str = "exponential", ): """ Determines the floating potential (Vf) for a given Current-Voltage (IV) curve @@ -70,27 +78,36 @@ def find_floating_potential( potential can not be determined. """ - meta_dict = {} + fit_funcs = { + "linear": { + "func": LinearFitFunction(), + "min_point_factor": 0.1, + }, + "exponential": { + "func": ExponentialOffsetFitFunction(), + "min_point_factor": 0.2, + }, + } + try: + fit_func = fit_funcs[fit_type]["func"] + min_point_factor = fit_funcs[fit_type]["min_point_factor"] + meta_dict = {"func": fit_func} + except KeyError: + raise KeyError( + f"Requested fit function '{fit_type}' is not a valid option. " + f"Examine kwarg 'fit_curve' for valid options.") if current.min() > 0.0 or current.max() < 0: warn("The Langmuir sweep has no floating potential.") - ret = (np.nan, np.nan) - if retislands or retfit: - ret += (meta_dict,) - - return ret + return FloatingPotentialResults(np.nan, np.nan, meta_dict) # check voltage is monotonically increasing/decreasing voltage_diff = np.diff(voltage) if not (np.all(voltage_diff >= 0) or np.all(voltage_diff <= 0)): warn("The voltage array is not monotonically increasing or decreasing.") - ret = (np.nan, np.nan) - if retislands or retfit: - ret += (meta_dict,) - - return ret + return FloatingPotentialResults(np.nan, np.nan, meta_dict) # condition kwarg threshold if isinstance(threshold, (int, float)): @@ -102,6 +119,20 @@ def find_floating_potential( else: warn(f"threshold is NOT a integer >= 1, using a value of 1") + # condition min_points + if min_points is None: + min_points = int(np.max([5, np.around(min_point_factor * voltage.size)])) + elif min_points == 0: + # this signals to use all points + pass + elif 0 < min_points < 1: + min_points = int(np.round(min_points * voltage.size)) + elif min_points >= 1: + min_points = int(np.round(min_points)) + else: + raise ValueError(f"Got {min_points}, but 'min_points' must be an int or float " + f"greater than or equal to 0.") + # find possible crossing points (cp) lower_vals = np.where(current <= 0, True, False) upper_vals = np.where(0 <= current, True, False) @@ -127,98 +158,83 @@ def find_floating_potential( cp_intervals = np.diff(cp_candidates) threshold_indices = np.where(cp_intervals > threshold)[0] n_islands = threshold_indices.size + 1 - if retislands: - if n_islands == 1: - meta_dict['islands'] = [slice(cp_candidates[0], cp_candidates[-1]+1)] - else: - isl_start = np.concatenate(( - [cp_candidates[0]], - cp_candidates[threshold_indices+1], - )) - isl_stop = np.concatenate(( - cp_candidates[threshold_indices]+1, - [cp_candidates[-1]+1], - )) - meta_dict['islands'] = [] - for start, stop in zip(isl_start, isl_stop): - meta_dict['islands'].append(slice(start, stop)) - if n_islands != 1: - # There are multiple crossing points - warn(f"Unable to determine floating potential, Langmuir sweep has " - f"{n_islands} crossing-islands. Try adjusting keyword 'threshold'" - f"and/or smooth the current.") - ret = (np.nan, np.nan) - if retislands or retfit: - ret += (meta_dict,) - - return ret + if min_points == 0: + meta_dict['islands'] = [slice(cp_candidates[0], cp_candidates[-1]+1)] + elif n_islands == 1: + meta_dict['islands'] = [slice(cp_candidates[0], cp_candidates[-1]+1)] + else: + # There are multiple crossing points + isl_start = np.concatenate(( + [cp_candidates[0]], + cp_candidates[threshold_indices+1], + )) + isl_stop = np.concatenate(( + cp_candidates[threshold_indices]+1, + [cp_candidates[-1]+1], + )) + meta_dict['islands'] = [] + for start, stop in zip(isl_start, isl_stop): + meta_dict['islands'].append(slice(start, stop)) + + # do islands fall within min_points window + isl_window = np.abs(np.r_[meta_dict["islands"][-1]][-1] + - np.r_[meta_dict["islands"][0]][0]) + 1 + if isl_window > min_points: + warn(f"Unable to determine floating potential, Langmuir sweep has " + f"{n_islands} crossing-islands. Try adjusting keyword 'threshold' " + f"and/or smooth the current.") + + return FloatingPotentialResults(np.nan, np.nan, meta_dict) # Construct crossing-island (pad if needed) - istart = cp_candidates[0] - istop = cp_candidates[-1] - iadd = (istop - istart + 1) - min_points - if iadd < 0: - # pad front - ipad_2_start = ipad_2_stop = int(np.ceil(-iadd / 2.0)) - if istart - ipad_2_start < 0: - ipad_2_stop += ipad_2_start - istart - ipad_2_start = 0 - istart = 0 - else: - istart -= ipad_2_start - ipad_2_start = 0 - - # pad rear - if ((current.size - 1) - (istop + ipad_2_stop)) < 0: - ipad_2_start += ipad_2_stop - (current.size - 1 - istop) - istop = current.size - 1 - else: - istop += ipad_2_stop - - # re-pad front if possible - if ipad_2_start > 0: + if min_points == 0: + # us all points + istart = 0 + istop = voltage.size + else: + istart = cp_candidates[0] + istop = cp_candidates[-1] + iadd = (istop - istart + 1) - min_points + if iadd < 0: + # pad front + ipad_2_start = ipad_2_stop = int(np.ceil(-iadd / 2.0)) if istart - ipad_2_start < 0: + ipad_2_stop += ipad_2_start - istart + ipad_2_start = 0 istart = 0 else: istart -= ipad_2_start + ipad_2_start = 0 + + # pad rear + if ((current.size - 1) - (istop + ipad_2_stop)) < 0: + ipad_2_start += ipad_2_stop - (current.size - 1 - istop) + istop = current.size - 1 + else: + istop += ipad_2_stop - if (istop - istart + 1) < min_points: - warn(f"The number of elements in the current array " - f"({istop - istart + 1}) is less than 'min_points' " - f"({min_points}).") + # re-pad front if possible + if ipad_2_start > 0: + if istart - ipad_2_start < 0: + istart = 0 + else: + istart -= ipad_2_start + + if (istop - istart + 1) < min_points: + warn(f"The number of elements in the current array " + f"({istop - istart + 1}) is less than 'min_points' " + f"({min_points}).") # Perform Linear Regression Fit volt_sub = voltage[istart:istop + 1] curr_sub = current[istart:istop + 1] - fit = linregress(volt_sub, curr_sub) - - slope = fit[0] - slope_err = fit[4] - - intercept = fit[1] - intercept_err = np.sum(volt_sub ** 2) - ((np.sum(volt_sub) ** 2) / volt_sub.size) - intercept_err = slope_err * np.sqrt(1.0 / intercept_err) - - vf = -intercept / slope - vf_err = ( - np.abs(vf) - * np.sqrt(((slope_err / slope) ** 2) - + ((intercept_err / intercept) ** 2)) - ) - - if retfit: - meta_dict.update({ - 'slope': slope, - 'slope_err': slope_err, - 'intercept': intercept, - 'intercept_err': intercept_err, - 'rsq': fit[2], - 'indices': slice(istart, istop + 1), - }) - - ret = (vf, vf_err) - if retislands or retfit: - ret += (meta_dict,) - - return ret + fit_func.curve_fit(volt_sub, curr_sub) + + vf, vf_err = fit_func.root_solve() + meta_dict.update({ + "rsq": fit_func.rsq, + "indices": slice(istart, istop+1) + }) + + return FloatingPotentialResults(vf, vf_err, meta_dict) From c6981e111df40c3585b938c893a3d56d969ebdd9 Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 7 Sep 2020 19:30:47 -0700 Subject: [PATCH 029/521] add fit_functions to autosummary --- docs/ad/analysis/swept_langmuir.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/ad/analysis/swept_langmuir.rst b/docs/ad/analysis/swept_langmuir.rst index 4709fb2201..6caa1e49fc 100644 --- a/docs/ad/analysis/swept_langmuir.rst +++ b/docs/ad/analysis/swept_langmuir.rst @@ -18,6 +18,7 @@ Sub-Packages & Modules .. autosummary:: floating_potential + fit_functions .. automodapi:: plasmapy.analysis.swept_langmuir :no-main-docstr: From 5dae863299e615b3caa9af7bba49dfe1da4e55b7 Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 7 Sep 2020 19:32:09 -0700 Subject: [PATCH 030/521] initial commit for the find_floating_potential notebook --- docs/ad/analysis/swept_langmuir.rst | 13 +- docs/ad/index.rst | 11 +- .../find_floating_potential.ipynb | 242 ++++++++++++++++++ 3 files changed, 258 insertions(+), 8 deletions(-) create mode 100644 docs/notebooks/analysis.swept_langmuir/find_floating_potential.ipynb diff --git a/docs/ad/analysis/swept_langmuir.rst b/docs/ad/analysis/swept_langmuir.rst index 6caa1e49fc..8e044e62d5 100644 --- a/docs/ad/analysis/swept_langmuir.rst +++ b/docs/ad/analysis/swept_langmuir.rst @@ -5,13 +5,20 @@ Swept Langmuir Analysis Module ============================== -this is the swept langmuir module +.. automodule:: plasmapy.analysis.swept_langmuir + +Example Notebooks +----------------- + +.. nbgallery:: + :glob: + :reversed: + + /notebooks/analysis.swept_langmuir/* API --- -.. automodule:: plasmapy.analysis.swept_langmuir - Sub-Packages & Modules ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/docs/ad/index.rst b/docs/ad/index.rst index 82f7bdf7a7..a9fd35f913 100644 --- a/docs/ad/index.rst +++ b/docs/ad/index.rst @@ -7,8 +7,8 @@ Analyses & Diagnostics ====================== Analyses and diagnostics go hand-in-hand, but have subtle differences. Thus, -PlasmaPy gives them their own sub-packages, `plasmapy.analysis` and -`plasmapy.diagnostics`. +PlasmaPy gives each their own sub-packages, `plasmapy.analysis` and +`plasmapy.diagnostics` respectively. Think of the `plasmapy.analysis` as your toolbox. It has all the tools (functionality) you need to analyze your data. Functionality is built around @@ -18,10 +18,11 @@ discrete Fourier Transform. Similarly, :func:`plasmapy.analysis.swept_langmuir.find_floating_potential` only finds the floating potential for a given langmuir trace. It does not have smoothing. It does not do any filtering. It does not do any signal conditioning. It has a -singular task. +singular task to find the floating potential of a single langmuir trace. -Diagnostics on the other-hand have a much broader scope, which leverages the tools -defined in `plasmapy.analysis`. +Diagnostics on the other-hand have a much broader scope and leverage the tools +defined in `plasmapy.analysis` to give a more integrated user experience when +analyzing data. ---- diff --git a/docs/notebooks/analysis.swept_langmuir/find_floating_potential.ipynb b/docs/notebooks/analysis.swept_langmuir/find_floating_potential.ipynb new file mode 100644 index 0000000000..484741bbfc --- /dev/null +++ b/docs/notebooks/analysis.swept_langmuir/find_floating_potential.ipynb @@ -0,0 +1,242 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Swept Langmuir Analysis: Floating Potential" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%matplotlib inline\n", + "\n", + "import matplotlib.pyplot as plt\n", + "import numpy as np\n", + "import os\n", + "import pprint\n", + "\n", + "from plasmapy.analysis import swept_langmuir as sla\n", + "\n", + "plt.rcParams['figure.figsize'] = [10.5, 0.56 * 10.5]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### How does `find_floating_potential()` work?\n", + "\n", + "1. The passed current array is scaned for points the equal zero and point-pairs that stradle $I = 0$. This forms an array of \"crossing-points.\"\n", + "1. The crossing-points are then grouped into crossing-islands based on the `threshold` keyword.\n", + " - A new island is formed when a successive crossing-point is more (index) steps away from the previous corssing-point than defined by `threshold`.\n", + " - If multiple crossing-islands are identified, then the function is incapable of identifying $V_f$ and will return `numpy.nan` values.\n", + " - If you want indices associated with the \"crossing-islands\", then set keyword `retislands=True`.\n", + "1. To calculate the floating potential, a `scipy.stats.linregress` fit is applied to the points that make up the \"crossing-island.\"\n", + " - The `min_points` keyword defines the minimum number of points required to perform the fit on.\n", + " - If the number of points that make up the \"crossing-island\" is less than `min_points`, then each side of the \"crossing-island\" is equally padded with the nearest neighbor points until `min_points` is satisfied.\n", + " \n", + "### Notes about usage\n", + "\n", + "- The function provides no signal processng, so, if needed, the user must smooth, sort, crop, etc. the arrays before passing to the function.\n", + "- The function requires the voltage array to be monotonically increasing or decreasing.\n", + "- If the total range spanned by all crossing-islands is less than or equal to `min_points`, then `threshold` is ignored and all crossing-islands are grouped into one island.\n", + "\n", + "\n", + "### Knobs to turn\n", + "\n", + "- `fit_type`\n", + "\n", + " There are two types of curves that can be fitted to the identified crossing point data, `\"linear\"` and `\"expoenetion\"`. The former will fit fit a line to the data, whereas, the later will fit and expoenetial curve with an offset. The default curve is `\"exponential\"` since swept langmuir data is not typically linear as it passes through $I=0$.\n", + "\n", + "- `min_points`\n", + "\n", + " This specifies the minimum number of points that will be used in the curve fitting. As mentioned above, the crossing-islands are identified and then padded until `min_points` is satisfied.\n", + " \n", + " - `min_pints = None` (Default) then the larger of 5 and `factor * array_size` is taken, where `factor = 0.1` for `\"linear\"` and `0.2` for `\"exponential\"`.\n", + " - `min_points = 0` then the entired passed array is fitted.\n", + " - `min_points >= 1` then this is the minimum number of points used.\n", + " - `0 < min_points < 1` then then the minimum number of points is taken as `min_points * array_size`.\n", + "\n", + "- `threshold`\n", + "\n", + "### Calculate the Floating Potential\n", + "\n", + "Below we'll compute the floaing potential using the default fitting behavior (`fit_type=\"exponential\"`) and a linear fit." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# load data\n", + "samples_path = os.path.join(os.path.abspath(\"../\"), \"langmuir_samples\")\n", + "path = os.path.join(samples_path, \"Beckers2017_noisy.npy\")\n", + "# path = os.path.join(samples_path, \"Beckers2017.npy\")\n", + "voltage, current = np.load(path)\n", + "\n", + "# voltage array needs to be monotonically increasing/decreasing\n", + "isort = np.argsort(voltage)\n", + "voltage = voltage[isort]\n", + "current = current[isort]\n", + "\n", + "# get default fit results (exponential fit)\n", + "results = sla.find_floating_potential(voltage, current, min_points=0.3)\n", + "\n", + "# get linear fit results\n", + "results_lin = sla.find_floating_potential(voltage, current, fit_type=\"linear\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The fit returns a three element named tuple, where...\n", + "\n", + "- `results.vf` = the determined floating potential (in Volts)\n", + "- `resutls.vf_err` = the associated error (in Volts)\n", + "- `results.info` = dictionary of meta-info form the fit\n", + "\n", + " - `results.info[\"func\"]` is the constructed fit function\n", + " - `results.info[\"indicies\"]` is a slice object representing the indices used in the fit\n", + " - `results.info[\"islands\"]` is a list of slice objects representing all the indentified crossing-islands\n", + " - `results.info[\"rsq\"]` is the coefficient of determination (or r-squared) value of the fit" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(\n", + " f\"results[0] = results.vf = {results.vf:0.3f} V\\n\"\n", + " f\"results[1] = results.vf_err = {results.vf_err:0.3f} V\\n\"\n", + " f\"results[2] = results.info =\"\n", + ")\n", + "pprint.pprint(results.info, indent=4)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Plot the fits" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "nbsphinx-thumbnail": { + "tooltip": "Floating Potential" + } + }, + "outputs": [], + "source": [ + "figwidth, figheight = plt.rcParams[\"figure.figsize\"]\n", + "figheight = 2. * figheight\n", + "fig, axs = plt.subplots(3, 1, figsize=[figwidth, figheight])\n", + "\n", + "# plot original data\n", + "axs[0].set_xlabel(\"Bias Voltage (V)\", fontsize=12)\n", + "axs[0].set_ylabel(\"Current (A)\", fontsize=12)\n", + "\n", + "axs[0].plot(voltage, current, zorder=10, label=\"Sweep Data\")\n", + "axs[0].axhline(0.0, color='r', linestyle='--', label=\"I = 0\")\n", + "axs[0].legend(fontsize=12)\n", + "\n", + "# zoom on fit\n", + "for ii, label, fit in zip([1, 2], [\"Exponential\", \"Linear\"], [results, results_lin]):\n", + " # calc island points\n", + " isl_pts = np.array([], dtype=np.int64)\n", + " for isl in fit.info[\"islands\"]:\n", + " isl_pts = np.concatenate((isl_pts, np.r_[isl]))\n", + " \n", + " # calc xrange for plot\n", + " xlim = [voltage[fit.info['indices']].min(),\n", + " voltage[fit.info['indices']].max()]\n", + " vpad = 0.25 * (xlim[1] - xlim[0])\n", + " xlim = [xlim[0] - vpad,\n", + " xlim[1] + vpad]\n", + " \n", + " # calc data points for fit curve\n", + " mask1 = np.where(voltage >= xlim[0], True, False)\n", + " mask2 = np.where(voltage <= xlim[1], True, False)\n", + " mask = np.logical_and(mask1, mask2)\n", + " vfit = np.linspace(xlim[0], xlim[1], 201, endpoint=True)\n", + " ifit = fit.info[\"func\"](vfit)\n", + "\n", + " axs[ii].set_xlabel(\"Bias Voltage (V)\", fontsize=12)\n", + " axs[ii].set_ylabel(\"Current (A)\", fontsize=12)\n", + " axs[ii].set_xlim(xlim)\n", + "\n", + " axs[ii].plot(voltage[mask], current[mask],\n", + " marker=\"o\", \n", + " zorder=10, \n", + " label=\"Sweep Data\")\n", + " axs[ii].scatter(voltage[fit.info[\"indices\"]],\n", + " current[fit.info[\"indices\"]],\n", + " linewidth=2, s=6**2, \n", + " facecolors=\"deepskyblue\", edgecolors=\"deepskyblue\",\n", + " zorder=11,\n", + " label=\"Points for Fit\")\n", + " axs[ii].scatter(voltage[isl_pts], current[isl_pts],\n", + " linewidth=2, s=8**2, \n", + " facecolors=\"deepskyblue\", edgecolors=\"black\",\n", + " zorder=12,\n", + " label=\"Island Points\")\n", + " axs[ii].autoscale(False)\n", + " axs[ii].plot(vfit, ifit, color=\"orange\",\n", + " zorder=13,\n", + " label=label + \" Fit\")\n", + " axs[ii].axhline(0.0, color='r', linestyle='--')\n", + " axs[ii].fill_between([fit.vf - fit.vf_err, fit.vf + fit.vf_err], \n", + " axs[1].get_ylim()[0],\n", + " axs[1].get_ylim()[1],\n", + " color='orange', alpha=0.1)\n", + " axs[ii].axvline(fit.vf, color='orange')\n", + " axs[ii].legend(fontsize=12)\n", + "\n", + " # add text\n", + " rsq = fit.info[\"rsq\"]\n", + " txt = (f\"$V_f = {fit.vf:.2f} \\\\pm {fit.vf_err:.2f}$ V\\n\"\n", + " f\"$r^2 = {rsq:.3f}$\")\n", + " txt_loc = [fit.vf, axs[ii].get_ylim()[1]]\n", + " txt_loc = axs[ii].transAxes.inverted().transform(axs[ii].transData.transform(txt_loc))\n", + " txt_loc[0] -= 0.02\n", + " txt_loc[1] -= 0.26\n", + " axs[ii].text(txt_loc[0], txt_loc[1], txt, \n", + " fontsize='large', transform=axs[ii].transAxes,\n", + " ha=\"right\")" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "plasmapy37-nb", + "language": "python", + "name": "plasmapy37-nb" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.6" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} From ae0fc0a5544a921bff49e6e27d263d62a4ae9b45 Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 7 Sep 2020 19:32:55 -0700 Subject: [PATCH 031/521] Revert "initial commit for the find_floating_potential notebook" This reverts commit 5dae8632 --- docs/ad/analysis/swept_langmuir.rst | 13 +- docs/ad/index.rst | 11 +- .../find_floating_potential.ipynb | 242 ------------------ 3 files changed, 8 insertions(+), 258 deletions(-) delete mode 100644 docs/notebooks/analysis.swept_langmuir/find_floating_potential.ipynb diff --git a/docs/ad/analysis/swept_langmuir.rst b/docs/ad/analysis/swept_langmuir.rst index 8e044e62d5..6caa1e49fc 100644 --- a/docs/ad/analysis/swept_langmuir.rst +++ b/docs/ad/analysis/swept_langmuir.rst @@ -5,20 +5,13 @@ Swept Langmuir Analysis Module ============================== -.. automodule:: plasmapy.analysis.swept_langmuir - -Example Notebooks ------------------ - -.. nbgallery:: - :glob: - :reversed: - - /notebooks/analysis.swept_langmuir/* +this is the swept langmuir module API --- +.. automodule:: plasmapy.analysis.swept_langmuir + Sub-Packages & Modules ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/docs/ad/index.rst b/docs/ad/index.rst index a9fd35f913..82f7bdf7a7 100644 --- a/docs/ad/index.rst +++ b/docs/ad/index.rst @@ -7,8 +7,8 @@ Analyses & Diagnostics ====================== Analyses and diagnostics go hand-in-hand, but have subtle differences. Thus, -PlasmaPy gives each their own sub-packages, `plasmapy.analysis` and -`plasmapy.diagnostics` respectively. +PlasmaPy gives them their own sub-packages, `plasmapy.analysis` and +`plasmapy.diagnostics`. Think of the `plasmapy.analysis` as your toolbox. It has all the tools (functionality) you need to analyze your data. Functionality is built around @@ -18,11 +18,10 @@ discrete Fourier Transform. Similarly, :func:`plasmapy.analysis.swept_langmuir.find_floating_potential` only finds the floating potential for a given langmuir trace. It does not have smoothing. It does not do any filtering. It does not do any signal conditioning. It has a -singular task to find the floating potential of a single langmuir trace. +singular task. -Diagnostics on the other-hand have a much broader scope and leverage the tools -defined in `plasmapy.analysis` to give a more integrated user experience when -analyzing data. +Diagnostics on the other-hand have a much broader scope, which leverages the tools +defined in `plasmapy.analysis`. ---- diff --git a/docs/notebooks/analysis.swept_langmuir/find_floating_potential.ipynb b/docs/notebooks/analysis.swept_langmuir/find_floating_potential.ipynb deleted file mode 100644 index 484741bbfc..0000000000 --- a/docs/notebooks/analysis.swept_langmuir/find_floating_potential.ipynb +++ /dev/null @@ -1,242 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Swept Langmuir Analysis: Floating Potential" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "%matplotlib inline\n", - "\n", - "import matplotlib.pyplot as plt\n", - "import numpy as np\n", - "import os\n", - "import pprint\n", - "\n", - "from plasmapy.analysis import swept_langmuir as sla\n", - "\n", - "plt.rcParams['figure.figsize'] = [10.5, 0.56 * 10.5]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### How does `find_floating_potential()` work?\n", - "\n", - "1. The passed current array is scaned for points the equal zero and point-pairs that stradle $I = 0$. This forms an array of \"crossing-points.\"\n", - "1. The crossing-points are then grouped into crossing-islands based on the `threshold` keyword.\n", - " - A new island is formed when a successive crossing-point is more (index) steps away from the previous corssing-point than defined by `threshold`.\n", - " - If multiple crossing-islands are identified, then the function is incapable of identifying $V_f$ and will return `numpy.nan` values.\n", - " - If you want indices associated with the \"crossing-islands\", then set keyword `retislands=True`.\n", - "1. To calculate the floating potential, a `scipy.stats.linregress` fit is applied to the points that make up the \"crossing-island.\"\n", - " - The `min_points` keyword defines the minimum number of points required to perform the fit on.\n", - " - If the number of points that make up the \"crossing-island\" is less than `min_points`, then each side of the \"crossing-island\" is equally padded with the nearest neighbor points until `min_points` is satisfied.\n", - " \n", - "### Notes about usage\n", - "\n", - "- The function provides no signal processng, so, if needed, the user must smooth, sort, crop, etc. the arrays before passing to the function.\n", - "- The function requires the voltage array to be monotonically increasing or decreasing.\n", - "- If the total range spanned by all crossing-islands is less than or equal to `min_points`, then `threshold` is ignored and all crossing-islands are grouped into one island.\n", - "\n", - "\n", - "### Knobs to turn\n", - "\n", - "- `fit_type`\n", - "\n", - " There are two types of curves that can be fitted to the identified crossing point data, `\"linear\"` and `\"expoenetion\"`. The former will fit fit a line to the data, whereas, the later will fit and expoenetial curve with an offset. The default curve is `\"exponential\"` since swept langmuir data is not typically linear as it passes through $I=0$.\n", - "\n", - "- `min_points`\n", - "\n", - " This specifies the minimum number of points that will be used in the curve fitting. As mentioned above, the crossing-islands are identified and then padded until `min_points` is satisfied.\n", - " \n", - " - `min_pints = None` (Default) then the larger of 5 and `factor * array_size` is taken, where `factor = 0.1` for `\"linear\"` and `0.2` for `\"exponential\"`.\n", - " - `min_points = 0` then the entired passed array is fitted.\n", - " - `min_points >= 1` then this is the minimum number of points used.\n", - " - `0 < min_points < 1` then then the minimum number of points is taken as `min_points * array_size`.\n", - "\n", - "- `threshold`\n", - "\n", - "### Calculate the Floating Potential\n", - "\n", - "Below we'll compute the floaing potential using the default fitting behavior (`fit_type=\"exponential\"`) and a linear fit." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# load data\n", - "samples_path = os.path.join(os.path.abspath(\"../\"), \"langmuir_samples\")\n", - "path = os.path.join(samples_path, \"Beckers2017_noisy.npy\")\n", - "# path = os.path.join(samples_path, \"Beckers2017.npy\")\n", - "voltage, current = np.load(path)\n", - "\n", - "# voltage array needs to be monotonically increasing/decreasing\n", - "isort = np.argsort(voltage)\n", - "voltage = voltage[isort]\n", - "current = current[isort]\n", - "\n", - "# get default fit results (exponential fit)\n", - "results = sla.find_floating_potential(voltage, current, min_points=0.3)\n", - "\n", - "# get linear fit results\n", - "results_lin = sla.find_floating_potential(voltage, current, fit_type=\"linear\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The fit returns a three element named tuple, where...\n", - "\n", - "- `results.vf` = the determined floating potential (in Volts)\n", - "- `resutls.vf_err` = the associated error (in Volts)\n", - "- `results.info` = dictionary of meta-info form the fit\n", - "\n", - " - `results.info[\"func\"]` is the constructed fit function\n", - " - `results.info[\"indicies\"]` is a slice object representing the indices used in the fit\n", - " - `results.info[\"islands\"]` is a list of slice objects representing all the indentified crossing-islands\n", - " - `results.info[\"rsq\"]` is the coefficient of determination (or r-squared) value of the fit" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "print(\n", - " f\"results[0] = results.vf = {results.vf:0.3f} V\\n\"\n", - " f\"results[1] = results.vf_err = {results.vf_err:0.3f} V\\n\"\n", - " f\"results[2] = results.info =\"\n", - ")\n", - "pprint.pprint(results.info, indent=4)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Plot the fits" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "nbsphinx-thumbnail": { - "tooltip": "Floating Potential" - } - }, - "outputs": [], - "source": [ - "figwidth, figheight = plt.rcParams[\"figure.figsize\"]\n", - "figheight = 2. * figheight\n", - "fig, axs = plt.subplots(3, 1, figsize=[figwidth, figheight])\n", - "\n", - "# plot original data\n", - "axs[0].set_xlabel(\"Bias Voltage (V)\", fontsize=12)\n", - "axs[0].set_ylabel(\"Current (A)\", fontsize=12)\n", - "\n", - "axs[0].plot(voltage, current, zorder=10, label=\"Sweep Data\")\n", - "axs[0].axhline(0.0, color='r', linestyle='--', label=\"I = 0\")\n", - "axs[0].legend(fontsize=12)\n", - "\n", - "# zoom on fit\n", - "for ii, label, fit in zip([1, 2], [\"Exponential\", \"Linear\"], [results, results_lin]):\n", - " # calc island points\n", - " isl_pts = np.array([], dtype=np.int64)\n", - " for isl in fit.info[\"islands\"]:\n", - " isl_pts = np.concatenate((isl_pts, np.r_[isl]))\n", - " \n", - " # calc xrange for plot\n", - " xlim = [voltage[fit.info['indices']].min(),\n", - " voltage[fit.info['indices']].max()]\n", - " vpad = 0.25 * (xlim[1] - xlim[0])\n", - " xlim = [xlim[0] - vpad,\n", - " xlim[1] + vpad]\n", - " \n", - " # calc data points for fit curve\n", - " mask1 = np.where(voltage >= xlim[0], True, False)\n", - " mask2 = np.where(voltage <= xlim[1], True, False)\n", - " mask = np.logical_and(mask1, mask2)\n", - " vfit = np.linspace(xlim[0], xlim[1], 201, endpoint=True)\n", - " ifit = fit.info[\"func\"](vfit)\n", - "\n", - " axs[ii].set_xlabel(\"Bias Voltage (V)\", fontsize=12)\n", - " axs[ii].set_ylabel(\"Current (A)\", fontsize=12)\n", - " axs[ii].set_xlim(xlim)\n", - "\n", - " axs[ii].plot(voltage[mask], current[mask],\n", - " marker=\"o\", \n", - " zorder=10, \n", - " label=\"Sweep Data\")\n", - " axs[ii].scatter(voltage[fit.info[\"indices\"]],\n", - " current[fit.info[\"indices\"]],\n", - " linewidth=2, s=6**2, \n", - " facecolors=\"deepskyblue\", edgecolors=\"deepskyblue\",\n", - " zorder=11,\n", - " label=\"Points for Fit\")\n", - " axs[ii].scatter(voltage[isl_pts], current[isl_pts],\n", - " linewidth=2, s=8**2, \n", - " facecolors=\"deepskyblue\", edgecolors=\"black\",\n", - " zorder=12,\n", - " label=\"Island Points\")\n", - " axs[ii].autoscale(False)\n", - " axs[ii].plot(vfit, ifit, color=\"orange\",\n", - " zorder=13,\n", - " label=label + \" Fit\")\n", - " axs[ii].axhline(0.0, color='r', linestyle='--')\n", - " axs[ii].fill_between([fit.vf - fit.vf_err, fit.vf + fit.vf_err], \n", - " axs[1].get_ylim()[0],\n", - " axs[1].get_ylim()[1],\n", - " color='orange', alpha=0.1)\n", - " axs[ii].axvline(fit.vf, color='orange')\n", - " axs[ii].legend(fontsize=12)\n", - "\n", - " # add text\n", - " rsq = fit.info[\"rsq\"]\n", - " txt = (f\"$V_f = {fit.vf:.2f} \\\\pm {fit.vf_err:.2f}$ V\\n\"\n", - " f\"$r^2 = {rsq:.3f}$\")\n", - " txt_loc = [fit.vf, axs[ii].get_ylim()[1]]\n", - " txt_loc = axs[ii].transAxes.inverted().transform(axs[ii].transData.transform(txt_loc))\n", - " txt_loc[0] -= 0.02\n", - " txt_loc[1] -= 0.26\n", - " axs[ii].text(txt_loc[0], txt_loc[1], txt, \n", - " fontsize='large', transform=axs[ii].transAxes,\n", - " ha=\"right\")" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "plasmapy37-nb", - "language": "python", - "name": "plasmapy37-nb" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.7.6" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} From 5c458438495c83687172946687e0c7a46565c4dc Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 7 Sep 2020 19:36:25 -0700 Subject: [PATCH 032/521] initial commit for the find_floating_potential notebook --- .../find_floating_potential.ipynb | 242 ++++++++++++++++++ 1 file changed, 242 insertions(+) create mode 100644 docs/notebooks/analysis.swept_langmuir/find_floating_potential.ipynb diff --git a/docs/notebooks/analysis.swept_langmuir/find_floating_potential.ipynb b/docs/notebooks/analysis.swept_langmuir/find_floating_potential.ipynb new file mode 100644 index 0000000000..484741bbfc --- /dev/null +++ b/docs/notebooks/analysis.swept_langmuir/find_floating_potential.ipynb @@ -0,0 +1,242 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Swept Langmuir Analysis: Floating Potential" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%matplotlib inline\n", + "\n", + "import matplotlib.pyplot as plt\n", + "import numpy as np\n", + "import os\n", + "import pprint\n", + "\n", + "from plasmapy.analysis import swept_langmuir as sla\n", + "\n", + "plt.rcParams['figure.figsize'] = [10.5, 0.56 * 10.5]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### How does `find_floating_potential()` work?\n", + "\n", + "1. The passed current array is scaned for points the equal zero and point-pairs that stradle $I = 0$. This forms an array of \"crossing-points.\"\n", + "1. The crossing-points are then grouped into crossing-islands based on the `threshold` keyword.\n", + " - A new island is formed when a successive crossing-point is more (index) steps away from the previous corssing-point than defined by `threshold`.\n", + " - If multiple crossing-islands are identified, then the function is incapable of identifying $V_f$ and will return `numpy.nan` values.\n", + " - If you want indices associated with the \"crossing-islands\", then set keyword `retislands=True`.\n", + "1. To calculate the floating potential, a `scipy.stats.linregress` fit is applied to the points that make up the \"crossing-island.\"\n", + " - The `min_points` keyword defines the minimum number of points required to perform the fit on.\n", + " - If the number of points that make up the \"crossing-island\" is less than `min_points`, then each side of the \"crossing-island\" is equally padded with the nearest neighbor points until `min_points` is satisfied.\n", + " \n", + "### Notes about usage\n", + "\n", + "- The function provides no signal processng, so, if needed, the user must smooth, sort, crop, etc. the arrays before passing to the function.\n", + "- The function requires the voltage array to be monotonically increasing or decreasing.\n", + "- If the total range spanned by all crossing-islands is less than or equal to `min_points`, then `threshold` is ignored and all crossing-islands are grouped into one island.\n", + "\n", + "\n", + "### Knobs to turn\n", + "\n", + "- `fit_type`\n", + "\n", + " There are two types of curves that can be fitted to the identified crossing point data, `\"linear\"` and `\"expoenetion\"`. The former will fit fit a line to the data, whereas, the later will fit and expoenetial curve with an offset. The default curve is `\"exponential\"` since swept langmuir data is not typically linear as it passes through $I=0$.\n", + "\n", + "- `min_points`\n", + "\n", + " This specifies the minimum number of points that will be used in the curve fitting. As mentioned above, the crossing-islands are identified and then padded until `min_points` is satisfied.\n", + " \n", + " - `min_pints = None` (Default) then the larger of 5 and `factor * array_size` is taken, where `factor = 0.1` for `\"linear\"` and `0.2` for `\"exponential\"`.\n", + " - `min_points = 0` then the entired passed array is fitted.\n", + " - `min_points >= 1` then this is the minimum number of points used.\n", + " - `0 < min_points < 1` then then the minimum number of points is taken as `min_points * array_size`.\n", + "\n", + "- `threshold`\n", + "\n", + "### Calculate the Floating Potential\n", + "\n", + "Below we'll compute the floaing potential using the default fitting behavior (`fit_type=\"exponential\"`) and a linear fit." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# load data\n", + "samples_path = os.path.join(os.path.abspath(\"../\"), \"langmuir_samples\")\n", + "path = os.path.join(samples_path, \"Beckers2017_noisy.npy\")\n", + "# path = os.path.join(samples_path, \"Beckers2017.npy\")\n", + "voltage, current = np.load(path)\n", + "\n", + "# voltage array needs to be monotonically increasing/decreasing\n", + "isort = np.argsort(voltage)\n", + "voltage = voltage[isort]\n", + "current = current[isort]\n", + "\n", + "# get default fit results (exponential fit)\n", + "results = sla.find_floating_potential(voltage, current, min_points=0.3)\n", + "\n", + "# get linear fit results\n", + "results_lin = sla.find_floating_potential(voltage, current, fit_type=\"linear\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The fit returns a three element named tuple, where...\n", + "\n", + "- `results.vf` = the determined floating potential (in Volts)\n", + "- `resutls.vf_err` = the associated error (in Volts)\n", + "- `results.info` = dictionary of meta-info form the fit\n", + "\n", + " - `results.info[\"func\"]` is the constructed fit function\n", + " - `results.info[\"indicies\"]` is a slice object representing the indices used in the fit\n", + " - `results.info[\"islands\"]` is a list of slice objects representing all the indentified crossing-islands\n", + " - `results.info[\"rsq\"]` is the coefficient of determination (or r-squared) value of the fit" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(\n", + " f\"results[0] = results.vf = {results.vf:0.3f} V\\n\"\n", + " f\"results[1] = results.vf_err = {results.vf_err:0.3f} V\\n\"\n", + " f\"results[2] = results.info =\"\n", + ")\n", + "pprint.pprint(results.info, indent=4)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Plot the fits" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "nbsphinx-thumbnail": { + "tooltip": "Floating Potential" + } + }, + "outputs": [], + "source": [ + "figwidth, figheight = plt.rcParams[\"figure.figsize\"]\n", + "figheight = 2. * figheight\n", + "fig, axs = plt.subplots(3, 1, figsize=[figwidth, figheight])\n", + "\n", + "# plot original data\n", + "axs[0].set_xlabel(\"Bias Voltage (V)\", fontsize=12)\n", + "axs[0].set_ylabel(\"Current (A)\", fontsize=12)\n", + "\n", + "axs[0].plot(voltage, current, zorder=10, label=\"Sweep Data\")\n", + "axs[0].axhline(0.0, color='r', linestyle='--', label=\"I = 0\")\n", + "axs[0].legend(fontsize=12)\n", + "\n", + "# zoom on fit\n", + "for ii, label, fit in zip([1, 2], [\"Exponential\", \"Linear\"], [results, results_lin]):\n", + " # calc island points\n", + " isl_pts = np.array([], dtype=np.int64)\n", + " for isl in fit.info[\"islands\"]:\n", + " isl_pts = np.concatenate((isl_pts, np.r_[isl]))\n", + " \n", + " # calc xrange for plot\n", + " xlim = [voltage[fit.info['indices']].min(),\n", + " voltage[fit.info['indices']].max()]\n", + " vpad = 0.25 * (xlim[1] - xlim[0])\n", + " xlim = [xlim[0] - vpad,\n", + " xlim[1] + vpad]\n", + " \n", + " # calc data points for fit curve\n", + " mask1 = np.where(voltage >= xlim[0], True, False)\n", + " mask2 = np.where(voltage <= xlim[1], True, False)\n", + " mask = np.logical_and(mask1, mask2)\n", + " vfit = np.linspace(xlim[0], xlim[1], 201, endpoint=True)\n", + " ifit = fit.info[\"func\"](vfit)\n", + "\n", + " axs[ii].set_xlabel(\"Bias Voltage (V)\", fontsize=12)\n", + " axs[ii].set_ylabel(\"Current (A)\", fontsize=12)\n", + " axs[ii].set_xlim(xlim)\n", + "\n", + " axs[ii].plot(voltage[mask], current[mask],\n", + " marker=\"o\", \n", + " zorder=10, \n", + " label=\"Sweep Data\")\n", + " axs[ii].scatter(voltage[fit.info[\"indices\"]],\n", + " current[fit.info[\"indices\"]],\n", + " linewidth=2, s=6**2, \n", + " facecolors=\"deepskyblue\", edgecolors=\"deepskyblue\",\n", + " zorder=11,\n", + " label=\"Points for Fit\")\n", + " axs[ii].scatter(voltage[isl_pts], current[isl_pts],\n", + " linewidth=2, s=8**2, \n", + " facecolors=\"deepskyblue\", edgecolors=\"black\",\n", + " zorder=12,\n", + " label=\"Island Points\")\n", + " axs[ii].autoscale(False)\n", + " axs[ii].plot(vfit, ifit, color=\"orange\",\n", + " zorder=13,\n", + " label=label + \" Fit\")\n", + " axs[ii].axhline(0.0, color='r', linestyle='--')\n", + " axs[ii].fill_between([fit.vf - fit.vf_err, fit.vf + fit.vf_err], \n", + " axs[1].get_ylim()[0],\n", + " axs[1].get_ylim()[1],\n", + " color='orange', alpha=0.1)\n", + " axs[ii].axvline(fit.vf, color='orange')\n", + " axs[ii].legend(fontsize=12)\n", + "\n", + " # add text\n", + " rsq = fit.info[\"rsq\"]\n", + " txt = (f\"$V_f = {fit.vf:.2f} \\\\pm {fit.vf_err:.2f}$ V\\n\"\n", + " f\"$r^2 = {rsq:.3f}$\")\n", + " txt_loc = [fit.vf, axs[ii].get_ylim()[1]]\n", + " txt_loc = axs[ii].transAxes.inverted().transform(axs[ii].transData.transform(txt_loc))\n", + " txt_loc[0] -= 0.02\n", + " txt_loc[1] -= 0.26\n", + " axs[ii].text(txt_loc[0], txt_loc[1], txt, \n", + " fontsize='large', transform=axs[ii].transAxes,\n", + " ha=\"right\")" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "plasmapy37-nb", + "language": "python", + "name": "plasmapy37-nb" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.6" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} From fc8b20e0c8d7a7ca20ae5a3b623c7a55dc44ab3d Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 7 Sep 2020 19:40:55 -0700 Subject: [PATCH 033/521] add the find_floating_potential notebook to the Swept Langmuir analysis page --- docs/ad/analysis/swept_langmuir.rst | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/docs/ad/analysis/swept_langmuir.rst b/docs/ad/analysis/swept_langmuir.rst index 6caa1e49fc..8e044e62d5 100644 --- a/docs/ad/analysis/swept_langmuir.rst +++ b/docs/ad/analysis/swept_langmuir.rst @@ -5,13 +5,20 @@ Swept Langmuir Analysis Module ============================== -this is the swept langmuir module +.. automodule:: plasmapy.analysis.swept_langmuir + +Example Notebooks +----------------- + +.. nbgallery:: + :glob: + :reversed: + + /notebooks/analysis.swept_langmuir/* API --- -.. automodule:: plasmapy.analysis.swept_langmuir - Sub-Packages & Modules ^^^^^^^^^^^^^^^^^^^^^^ From 613824557252c252c3e16e67df9cb7d7d2cf8188 Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 7 Sep 2020 21:22:42 -0700 Subject: [PATCH 034/521] remove .ipynb_checkpoints from exclude_patterns...nbsphinx automatically adds it --- docs/conf.py | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/conf.py b/docs/conf.py index f438d5c330..67bf728660 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -112,7 +112,6 @@ "Thumbs.db", ".DS_Store", "notebooks/langmuir_samples", - "*/.ipynb_checkpoints", ] # The name of the Pygments (syntax highlighting) style to use. From 60022294404f4e3f06b56f9424fc19b456a8b2b7 Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 7 Sep 2020 21:31:02 -0700 Subject: [PATCH 035/521] move notebook find_floating_potential back to notebooks/analysis/swept_langmuir/ --- .../swept_langmuir}/find_floating_potential.ipynb | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) rename docs/notebooks/{analysis.swept_langmuir => analysis/swept_langmuir}/find_floating_potential.ipynb (97%) diff --git a/docs/notebooks/analysis.swept_langmuir/find_floating_potential.ipynb b/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb similarity index 97% rename from docs/notebooks/analysis.swept_langmuir/find_floating_potential.ipynb rename to docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb index 484741bbfc..cba102561e 100644 --- a/docs/notebooks/analysis.swept_langmuir/find_floating_potential.ipynb +++ b/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb @@ -76,9 +76,8 @@ "outputs": [], "source": [ "# load data\n", - "samples_path = os.path.join(os.path.abspath(\"../\"), \"langmuir_samples\")\n", + "samples_path = os.path.join(os.path.abspath(\"../../\"), \"langmuir_samples\")\n", "path = os.path.join(samples_path, \"Beckers2017_noisy.npy\")\n", - "# path = os.path.join(samples_path, \"Beckers2017.npy\")\n", "voltage, current = np.load(path)\n", "\n", "# voltage array needs to be monotonically increasing/decreasing\n", @@ -220,9 +219,9 @@ ], "metadata": { "kernelspec": { - "display_name": "plasmapy37-nb", + "display_name": "Python 3", "language": "python", - "name": "plasmapy37-nb" + "name": "python3" }, "language_info": { "codemirror_mode": { From f069169b594719cb88f02f9ee6f33587956cf7e2 Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 7 Sep 2020 21:48:11 -0700 Subject: [PATCH 036/521] update wording to match changes made to find_floating_potential() --- .../swept_langmuir/find_floating_potential.ipynb | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb b/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb index cba102561e..659691def8 100644 --- a/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb +++ b/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb @@ -31,14 +31,14 @@ "source": [ "### How does `find_floating_potential()` work?\n", "\n", - "1. The passed current array is scaned for points the equal zero and point-pairs that stradle $I = 0$. This forms an array of \"crossing-points.\"\n", - "1. The crossing-points are then grouped into crossing-islands based on the `threshold` keyword.\n", + "1. The passed current array is scanned for points that equal zero and point-pairs that straddle $I = 0$. This forms an array of \"crossing-points.\"\n", + "1. The crossing-points are then grouped into \"crossing-islands\" based on the `threshold` keyword.\n", " - A new island is formed when a successive crossing-point is more (index) steps away from the previous corssing-point than defined by `threshold`.\n", - " - If multiple crossing-islands are identified, then the function is incapable of identifying $V_f$ and will return `numpy.nan` values.\n", - " - If you want indices associated with the \"crossing-islands\", then set keyword `retislands=True`.\n", - "1. To calculate the floating potential, a `scipy.stats.linregress` fit is applied to the points that make up the \"crossing-island.\"\n", - " - The `min_points` keyword defines the minimum number of points required to perform the fit on.\n", - " - If the number of points that make up the \"crossing-island\" is less than `min_points`, then each side of the \"crossing-island\" is equally padded with the nearest neighbor points until `min_points` is satisfied.\n", + " - If multiple crossing-islands are identified, then the function will compare the total span of all crossing-islands to `min_points`. If the span is greater than `min_points`, then the function is incapable of identifying $V_f$ and will return `numpy.nan` values; otherwise, the span will form one larger crossing-island.\n", + "1. To calculate the floating potential...\n", + " - If the number of points that make up the crossing-island is less than `min_points`, then each side of the \"crossing-island\" is equally padded with the nearest neighbor points until `min_points` is satisfied.\n", + " - If `fit_type=\"linear\"`, then a `scipy.stats.linregress` fit is applied to the points that make up the crossing-island.\n", + " - If `fit_type=\"exponential\"`, then a `scipy.optimize.curve_fit` fit is applied to the points that make up the crossing-island.\n", " \n", "### Notes about usage\n", "\n", From 3fbbaab636fac16ac1b3c248a3002be9f0331870 Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 7 Sep 2020 21:48:27 -0700 Subject: [PATCH 037/521] update notebook link --- docs/ad/analysis/swept_langmuir.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/ad/analysis/swept_langmuir.rst b/docs/ad/analysis/swept_langmuir.rst index 8e044e62d5..a6144f91d3 100644 --- a/docs/ad/analysis/swept_langmuir.rst +++ b/docs/ad/analysis/swept_langmuir.rst @@ -14,7 +14,7 @@ Example Notebooks :glob: :reversed: - /notebooks/analysis.swept_langmuir/* + /notebooks/analysis/swept_langmuir/* API --- From 9584198f9b586c0a5157641475c9f7c540d9130a Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 7 Sep 2020 21:48:46 -0700 Subject: [PATCH 038/521] PEP8 white space --- plasmapy/analysis/swept_langmuir/floating_potential.py | 1 + 1 file changed, 1 insertion(+) diff --git a/plasmapy/analysis/swept_langmuir/floating_potential.py b/plasmapy/analysis/swept_langmuir/floating_potential.py index d103c2c8aa..95c6318f54 100644 --- a/plasmapy/analysis/swept_langmuir/floating_potential.py +++ b/plasmapy/analysis/swept_langmuir/floating_potential.py @@ -15,6 +15,7 @@ FloatingPotentialResults = namedtuple("FloatingPotentialResults", ("vf", "vf_err", "info")) + def find_floating_potential( voltage: np.ndarray, current: np.ndarray, From 0d4d44dc2e1c4ebb51574a2b69ac32921f2bf594 Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 7 Sep 2020 21:58:11 -0700 Subject: [PATCH 039/521] some grumpy black fixes --- plasmapy/analysis/swept_langmuir/__init__.py | 2 +- plasmapy/analysis/swept_langmuir/fit_functions.py | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/plasmapy/analysis/swept_langmuir/__init__.py b/plasmapy/analysis/swept_langmuir/__init__.py index e966f6c190..4c3817f25a 100644 --- a/plasmapy/analysis/swept_langmuir/__init__.py +++ b/plasmapy/analysis/swept_langmuir/__init__.py @@ -1,6 +1,6 @@ """ Sub-Package containing routines for analyzing swept Langmuir probe traces. """ -__all__ = ['find_floating_potential'] +__all__ = ["find_floating_potential"] from plasmapy.analysis.swept_langmuir.floating_potential import find_floating_potential diff --git a/plasmapy/analysis/swept_langmuir/fit_functions.py b/plasmapy/analysis/swept_langmuir/fit_functions.py index d770003464..bf668ba59b 100644 --- a/plasmapy/analysis/swept_langmuir/fit_functions.py +++ b/plasmapy/analysis/swept_langmuir/fit_functions.py @@ -7,6 +7,7 @@ "ExponentialOffsetFitFunction", "LinearFitFunction", ] + import numpy as np from abc import ABC, abstractmethod @@ -21,6 +22,7 @@ class AbstractFitFunction(ABC): function to a set of data. These were originally designed for assisting in fitting curves to swept langmuir data. """ + _parameters = None # type: Tuple _parameters_err = None # type: Tuple _covariance_matrix = None From 1378fd211e553216944475ecd31f9a26c04d9bf6 Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 7 Sep 2020 22:04:46 -0700 Subject: [PATCH 040/521] more grumpy black changes --- .../swept_langmuir/floating_potential.py | 28 ++++++++++--------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/plasmapy/analysis/swept_langmuir/floating_potential.py b/plasmapy/analysis/swept_langmuir/floating_potential.py index 95c6318f54..aff42187bd 100644 --- a/plasmapy/analysis/swept_langmuir/floating_potential.py +++ b/plasmapy/analysis/swept_langmuir/floating_potential.py @@ -12,16 +12,17 @@ LinearFitFunction, ) -FloatingPotentialResults = namedtuple("FloatingPotentialResults", - ("vf", "vf_err", "info")) +FloatingPotentialResults = namedtuple( + "FloatingPotentialResults", ("vf", "vf_err", "info") +) def find_floating_potential( - voltage: np.ndarray, - current: np.ndarray, - threshold: int = 1, - min_points: Union[int, float] = None, - fit_type: str = "exponential", + voltage: np.ndarray, + current: np.ndarray, + threshold: int = 1, + min_points: Union[int, float] = None, + fit_type: str = "exponential", ): """ Determines the floating potential (Vf) for a given Current-Voltage (IV) curve @@ -96,7 +97,8 @@ def find_floating_potential( except KeyError: raise KeyError( f"Requested fit function '{fit_type}' is not a valid option. " - f"Examine kwarg 'fit_curve' for valid options.") + f"Examine kwarg 'fit_curve' for valid options." + ) if current.min() > 0.0 or current.max() < 0: warn("The Langmuir sweep has no floating potential.") @@ -143,7 +145,7 @@ def find_floating_potential( # adjust for array wrapping cause by np.roll cp_low2high = cp_low2high[np.where(cp_low2high != 0, True, False)] - cp_high2low = cp_high2low[np.where(cp_high2low != current.size-1, True, False)] + cp_high2low = cp_high2low[np.where(cp_high2low != current.size - 1, True, False)] # collect all candidates cp_candidates = np.concatenate(( @@ -161,9 +163,9 @@ def find_floating_potential( n_islands = threshold_indices.size + 1 if min_points == 0: - meta_dict['islands'] = [slice(cp_candidates[0], cp_candidates[-1]+1)] + meta_dict["islands"] = [slice(cp_candidates[0], cp_candidates[-1] + 1)] elif n_islands == 1: - meta_dict['islands'] = [slice(cp_candidates[0], cp_candidates[-1]+1)] + meta_dict["islands"] = [slice(cp_candidates[0], cp_candidates[-1] + 1)] else: # There are multiple crossing points isl_start = np.concatenate(( @@ -174,9 +176,9 @@ def find_floating_potential( cp_candidates[threshold_indices]+1, [cp_candidates[-1]+1], )) - meta_dict['islands'] = [] + meta_dict["islands"] = [] for start, stop in zip(isl_start, isl_stop): - meta_dict['islands'].append(slice(start, stop)) + meta_dict["islands"].append(slice(start, stop)) # do islands fall within min_points window isl_window = np.abs(np.r_[meta_dict["islands"][-1]][-1] From 1ca68de2f019da7c62813bf5d89619afa225b6a5 Mon Sep 17 00:00:00 2001 From: Erik Date: Tue, 8 Sep 2020 10:21:22 -0700 Subject: [PATCH 041/521] add codestyling to docstirng and fix numpy.ndarray reference --- plasmapy/analysis/swept_langmuir/fit_functions.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/plasmapy/analysis/swept_langmuir/fit_functions.py b/plasmapy/analysis/swept_langmuir/fit_functions.py index bf668ba59b..eeeeb8523e 100644 --- a/plasmapy/analysis/swept_langmuir/fit_functions.py +++ b/plasmapy/analysis/swept_langmuir/fit_functions.py @@ -91,7 +91,7 @@ def root_solve(self, x0, **kwargs): Parameters ---------- - x0: `~np.ndarray` + x0: `~numpy.ndarray` The starting estimate for the roots of `f(x) = 0`. **kwargs @@ -99,10 +99,10 @@ def root_solve(self, x0, **kwargs): Returns ------- - x : ndarray + x : `~numpy.ndarray` The solution (or the result of the last iteration for an unsuccessful call). - infodict : dict + infodict : `dict` A dictionary of optional outputs with the keys: ``nfev`` @@ -121,10 +121,10 @@ def root_solve(self, x0, **kwargs): ``qtf`` the vector ``(transpose(q) * fvec)`` - ier : int + ier : `int` An integer flag. Set to 1 if a solution was found, otherwise refer to `mesg` for more information. - mesg : str + mesg : `str` If no solution is found, `mesg` details the cause of failure. """ kwargs["args"] = self.parameters From 72f91f53d9e32789db00311f5d7ca478a6636a31 Mon Sep 17 00:00:00 2001 From: Erik Date: Tue, 8 Sep 2020 10:50:22 -0700 Subject: [PATCH 042/521] clarify docstrings on AbstractFitFunction --- plasmapy/analysis/swept_langmuir/fit_functions.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/plasmapy/analysis/swept_langmuir/fit_functions.py b/plasmapy/analysis/swept_langmuir/fit_functions.py index eeeeb8523e..b4616a2d5a 100644 --- a/plasmapy/analysis/swept_langmuir/fit_functions.py +++ b/plasmapy/analysis/swept_langmuir/fit_functions.py @@ -18,9 +18,9 @@ class AbstractFitFunction(ABC): """ - Abstract class for defining fit functions and the tools for fitting the - function to a set of data. These were originally designed for assisting in - fitting curves to swept langmuir data. + Abstract class for defining fit functions :math:`f(x)` and the tools for + fitting the function to a set of data. These were originally designed for + assisting in fitting curves to swept langmuir data. """ _parameters = None # type: Tuple @@ -30,7 +30,7 @@ class AbstractFitFunction(ABC): def __call__(self, x): """ - The fit function. + Direct call of the fit function :math:`f(x)``. Parameters ---------- @@ -40,7 +40,8 @@ def __call__(self, x): Returns ------- array_like - Corresponding independent variables of dependent variables `x`. + Corresponding independent variables of dependent variables + :math:`x`. """ return self._func(x, *self.parameters) From 83b4c9509e19bd63ec1ee3f7eabf376d52adb41d Mon Sep 17 00:00:00 2001 From: Erik Date: Tue, 8 Sep 2020 10:51:10 -0700 Subject: [PATCH 043/521] include documentation for inherited members of classes in fit_functions.py --- .../plasmapy.analysis.swept_langmuir.fit_functions.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/api_static/plasmapy.analysis.swept_langmuir.fit_functions.rst b/docs/api_static/plasmapy.analysis.swept_langmuir.fit_functions.rst index 912e5fc2b8..e8e287665c 100644 --- a/docs/api_static/plasmapy.analysis.swept_langmuir.fit_functions.rst +++ b/docs/api_static/plasmapy.analysis.swept_langmuir.fit_functions.rst @@ -7,4 +7,5 @@ .. automodapi:: plasmapy.analysis.swept_langmuir.fit_functions :include-all-objects: + :inherited-members: :no-heading: From 5c80fa0452a4a6d0d07590a504ca871fa818bce6 Mon Sep 17 00:00:00 2001 From: Erik Date: Tue, 8 Sep 2020 10:54:34 -0700 Subject: [PATCH 044/521] add docstrings for ExponentialOffsetFitFunction --- .../analysis/swept_langmuir/fit_functions.py | 80 ++++++++++++++++--- 1 file changed, 71 insertions(+), 9 deletions(-) diff --git a/plasmapy/analysis/swept_langmuir/fit_functions.py b/plasmapy/analysis/swept_langmuir/fit_functions.py index b4616a2d5a..2b98f34a35 100644 --- a/plasmapy/analysis/swept_langmuir/fit_functions.py +++ b/plasmapy/analysis/swept_langmuir/fit_functions.py @@ -198,29 +198,91 @@ def curve_fit(self, xdata, ydata, **kwargs): class ExponentialOffsetFitFunction(AbstractFitFunction): + """ + A sub-class of `AbstractFitFunction` to represent an exponential with an + offset. + + .. math:: + + f(x) = A \\, \\exp(B \\, x) + C + + where :math:`A`, :math:`B`, and :math:`C` are positive real constants + and :math:`x` is the independent variable. + + """ def __str__(self): return f"f(x) = A exp(B x) + C" def _func(self, x, a, b, c): + """ + The fit function, an exponential with an offset. + + .. math:: + + f(x) = A \\, \\exp(B \\, x) + C + + where :math:`A`, :math:`B`, and :math:`C` are positive real constants + and :math:`x` is the independent variable. + + Parameters + ---------- + x: array_like + Independent variable. + + a: float + value for constant :math:`A` + + b: float + value for constant :math:`B` + + c: float + value for constant :math:`C` + + Returns + ------- + y: array_like + dependent variables corresponding to :math:`x` + + """ return a * np.exp(b * x) + c @property def latex_str(self) -> str: return fr"A \, \exp(B \, x) + C" - def root_solve(self, *args, reterr=True, **kwargs): + def root_solve(self, *args, **kwargs): + """ + The root :math:`f(x) = 0` for the fit function. + + Parameters + ---------- + *args + Not needed. This is to ensure signature comparability with + `AbstractFitFunction`. + + *kwargs + Not needed. This is to ensure signature comparability with + `AbstractFitFunction`. + + Returns + ------- + root: float + The root value for the given fit :attr:`parameters`. + + err: float + The error in the calculated root for the given fit + :attr:`parameters` and :attr:`parameters_err`. + """ a, b, c = self.parameters root = np.log(-c / a) / b - if reterr: - a_err, b_err, c_err = self.parameters_err - a_term = a_err / (a * b) - b_term = b_err * root / b - c_term = c_err / (b * c) - err = np.sqrt(a_term ** 2 + b_term ** 2 + c_term ** 2) + a_err, b_err, c_err = self.parameters_err + a_term = a_err / (a * b) + b_term = b_err * root / b + c_term = c_err / (b * c) + err = np.sqrt(a_term ** 2 + b_term ** 2 + c_term ** 2) - return root, err - return root + return root, err class LinearFitFunction(AbstractFitFunction): From ce309be8a2f043a5ecaba89ec6c9ed736e695624 Mon Sep 17 00:00:00 2001 From: Erik Date: Tue, 8 Sep 2020 15:01:25 -0700 Subject: [PATCH 045/521] make the curve_fit return None; curve_fit now stores fit results in curve_fit_results; create property curve_fit_results; Update docstrings accordingly --- .../analysis/swept_langmuir/fit_functions.py | 43 +++++++++---------- 1 file changed, 20 insertions(+), 23 deletions(-) diff --git a/plasmapy/analysis/swept_langmuir/fit_functions.py b/plasmapy/analysis/swept_langmuir/fit_functions.py index 2b98f34a35..dcd2a78522 100644 --- a/plasmapy/analysis/swept_langmuir/fit_functions.py +++ b/plasmapy/analysis/swept_langmuir/fit_functions.py @@ -27,6 +27,7 @@ class AbstractFitFunction(ABC): _parameters_err = None # type: Tuple _covariance_matrix = None _rsq = None + _curve_fit_results = None def __call__(self, x): """ @@ -70,6 +71,15 @@ def _func(self, x, *args): """ raise NotImplementedError + @property + def curve_fit_results(self): + """ + The results returned by the curve fitting routine used by + :attr:`curve_fit`. This is typically from `scipy.stats.linregress` or + `scipy.optimize.curve_fit`. + """ + return self._curve_fit_results + @property def parameters(self) -> Tuple: """The fitted parameters for the fit function.""" @@ -136,10 +146,15 @@ def rsq(self): """Coefficient of determination (r-squared) value of the fit.""" return self._rsq - def curve_fit(self, xdata, ydata, **kwargs): + def curve_fit(self, xdata, ydata, **kwargs) -> None: """ - Use non-linear least squares to fit the fit function to (`xdata`, `ydata`). - This uses `scipy.optimize.curve_fit`. + Use a non-linear least squares method to fit the fit function to + (`xdata`, `ydata`), using `scipy.optimize.curve_fit`. This will set + the attributes :attr:`parameters`, :attr:`parameters_err`, and + :attr:`rsq`. + + The results of `scipy.optimize.curve_fit` can be obtained via + :attr:`curve_fit_results`. Parameters ---------- @@ -153,23 +168,6 @@ def curve_fit(self, xdata, ydata, **kwargs): **kwargs Any keywords accepted by `scipy.optimize.curve_fit`. - Returns - ------- - popt : array - Optimal values for the parameters so that the sum of the squared - residuals of ``f(xdata, *popt) - ydata`` is minimized. - - pcov : 2-D array - The estimated covariance of popt. The diagonals provide the variance - of the parameter estimate. To compute one standard deviation errors - on the parameters use ``perr = np.sqrt(np.diag(pcov))``. - How the `sigma` parameter affects the estimated covariance - depends on `absolute_sigma` argument, as described above. - If the Jacobian matrix at the solution doesn't have a full rank, then - 'lm' method returns a matrix filled with ``np.inf``, on the other hand - 'trf' and 'dogbox' methods use Moore-Penrose pseudoinverse to compute - the covariance matrix. - Raises ------ ValueError @@ -184,6 +182,7 @@ def curve_fit(self, xdata, ydata, **kwargs): """ popt, pcov = curve_fit(self._func, xdata, ydata, **kwargs) + self._curve_fit_results = (popt, pcov) self._parameters = tuple(popt.tolist()) self._parameters_err = tuple(np.sqrt(np.diag(pcov)).tolist()) @@ -194,8 +193,6 @@ def curve_fit(self, xdata, ydata, **kwargs): ss_tot = np.sum((ydata - np.mean(ydata)) ** 2) self._rsq = 1 - (ss_res / ss_tot) - return popt, pcov - class ExponentialOffsetFitFunction(AbstractFitFunction): """ @@ -309,6 +306,7 @@ def root_solve(self, *args, reterr=True, **kwargs): def curve_fit(self, xdata, ydata, **kwargs): results = linregress(xdata, ydata) + self._curve_fit_results = results m = results[0] b = results[1] @@ -320,4 +318,3 @@ def curve_fit(self, xdata, ydata, **kwargs): self._parameters_err = (m_err, b_err) self._rsq = results[2] ** 2 - return results From 537ecd8b0ce2ffdabee8587c25ec4055759edb45 Mon Sep 17 00:00:00 2001 From: Erik Date: Tue, 8 Sep 2020 15:02:32 -0700 Subject: [PATCH 046/521] add docstrings to LinearFitFunction; remove kwarg reterr from root_solve --- .../analysis/swept_langmuir/fit_functions.py | 94 +++++++++++++++++-- 1 file changed, 87 insertions(+), 7 deletions(-) diff --git a/plasmapy/analysis/swept_langmuir/fit_functions.py b/plasmapy/analysis/swept_langmuir/fit_functions.py index dcd2a78522..c2944f6836 100644 --- a/plasmapy/analysis/swept_langmuir/fit_functions.py +++ b/plasmapy/analysis/swept_langmuir/fit_functions.py @@ -283,28 +283,108 @@ def root_solve(self, *args, **kwargs): class LinearFitFunction(AbstractFitFunction): + """ + A sub-class of `AbstractFitFunction` to represent a linear function. + + .. math:: + + f(x) = m \\, x + b + + where :math:`m` and :math:`b` are positive real constants representing the + slope and intercept, respectively, and :math:`x` is the independent + variable. + + """ def __str__(self): return f"f(x) = m x + b" def _func(self, x, m, b): + """ + The fit function, a linear function. + + .. math:: + + f(x) = m \\, x + b + + where :math:`m` and :math:`b` are positive real constants representing the + slope and intercept, respectively, and :math:`x` is the independent + variable. + + Parameters + ---------- + x: array_like + Independent variable. + m: float + value for slope :math:`m` + + b: float + value for intercept :math:`b` + + Returns + ------- + y: array_like + dependent variables corresponding to :math:`x` + + """ return m * x + b @property def latex_str(self) -> str: return fr"m \, x + b" - def root_solve(self, *args, reterr=True, **kwargs): + def root_solve(self, *args, **kwargs): + """ + The root :math:`f(x) = 0` for the fit function. + + Parameters + ---------- + *args + Not needed. This is to ensure signature comparability with + `AbstractFitFunction`. + + *kwargs + Not needed. This is to ensure signature comparability with + `AbstractFitFunction`. + + Returns + ------- + root: float + The root value for the given fit :attr:`parameters`. + + err: float + The error in the calculated root for the given fit + :attr:`parameters` and :attr:`parameters_err`. + """ m, b = self.parameters root = -b / m - if reterr: - m_err, b_err = self.parameters_err - err = np.abs(root) * np.sqrt((m_err / m) ** 2 + (b_err / b) ** 2) + m_err, b_err = self.parameters_err + err = np.abs(root) * np.sqrt((m_err / m) ** 2 + (b_err / b) ** 2) - return root, err - return root + return root, err - def curve_fit(self, xdata, ydata, **kwargs): + def curve_fit(self, xdata, ydata, **kwargs) -> None: + """ + Calculate a linear least-squares regression of (`xdata`, `ydata`) using + `scipy.stats.linregress`. This will set the attributes + :attr:`parameters`, :attr:`parameters_err`, and :attr:`rsq`. + + The results of `scipy.stats.linregress` can be obtained via + :attr:`curve_fit_results`. + + Parameters + ---------- + xdata: array_like + The independent variable where data is measured. Should be 1D of + length M. + + ydata: array_like + The dependent data associated with `xdata`. + + **kwargs + Any keywords accepted by `scipy.stats.linregress.curve_fit`. + + """ results = linregress(xdata, ydata) self._curve_fit_results = results From 2dd2e1514fc4b1f5d4b303b460b18a8d3240eb57 Mon Sep 17 00:00:00 2001 From: Erik Date: Tue, 8 Sep 2020 16:06:12 -0700 Subject: [PATCH 047/521] fix typo; add description for `threshold --- .../analysis/swept_langmuir/find_floating_potential.ipynb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb b/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb index 659691def8..0e47f95b6a 100644 --- a/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb +++ b/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb @@ -58,12 +58,15 @@ " This specifies the minimum number of points that will be used in the curve fitting. As mentioned above, the crossing-islands are identified and then padded until `min_points` is satisfied.\n", " \n", " - `min_pints = None` (Default) then the larger of 5 and `factor * array_size` is taken, where `factor = 0.1` for `\"linear\"` and `0.2` for `\"exponential\"`.\n", - " - `min_points = 0` then the entired passed array is fitted.\n", + " - `min_points = 0` then the entire passed array is fitted.\n", " - `min_points >= 1` then this is the minimum number of points used.\n", " - `0 < min_points < 1` then then the minimum number of points is taken as `min_points * array_size`.\n", "\n", + "\n", "- `threshold`\n", "\n", + " The max allowed index distance between crossing-points before a new crossing-island is formed.\n", + "\n", "### Calculate the Floating Potential\n", "\n", "Below we'll compute the floaing potential using the default fitting behavior (`fit_type=\"exponential\"`) and a linear fit." From 10482bfdbcc9a563e6c53350448146ff06bbbeb9 Mon Sep 17 00:00:00 2001 From: Erik Date: Tue, 8 Sep 2020 16:06:37 -0700 Subject: [PATCH 048/521] update docstring for find_floating_potential --- .../swept_langmuir/floating_potential.py | 108 ++++++++++++------ 1 file changed, 70 insertions(+), 38 deletions(-) diff --git a/plasmapy/analysis/swept_langmuir/floating_potential.py b/plasmapy/analysis/swept_langmuir/floating_potential.py index aff42187bd..883152aee7 100644 --- a/plasmapy/analysis/swept_langmuir/floating_potential.py +++ b/plasmapy/analysis/swept_langmuir/floating_potential.py @@ -25,59 +25,91 @@ def find_floating_potential( fit_type: str = "exponential", ): """ - Determines the floating potential (Vf) for a given Current-Voltage (IV) curve - generate by a swept Langmuir probe. The floating potential is the probe - bias where the collected current goes to zero. - - How it works - ------------ - #. The current array ``current` is searched for all points equal to zero and - point pairs that straddle ``current = 0`` to form a set of crossing-points. - #. Crossing-points are then grouped into crossing-islands in accordance to + Determines the floating potential (:math:`V_f`) for a given Current-Voltage + (IV) curve obtained from a swept Langmuir probe. The floating potential is + the probe bias where the collected current equals to zero :math:`I = 0`. + + **How it works** + + #. The current array ``current`` is scanned for all points equal to zero and + point pairs that straddle :math:`I = 0`. This forms an array of + "crossing-points." + #. The crossing-points are then grouped into "crossing-islands" in based on the ``threshold`` keyword. - #. If multiple crossing-islands are found, then an warning issued and - `~numpy.nan` is returned. - #. To calculated the floating potential, a `~scipy.stats.linregress` is applied - to points making up the cross-island. If the number of points that make - up the crossing-island are less than ``min_points``, then each side of the - crossing-island is padded with the nearest neighbors until `min_points` is - satisfied. - Parameters - ---------- + - A new island is formed when a successive crossing-point is more (index) + steps away from the previous crossing-point than allowed by + ``threshold``. + - If multiple crossing-islands are identified, then the total span of all + crossing-islands is compared to ``min_points``. If the span is greater + than ``min_points`` then the function is incapable of identifying + :math:`V_f` and will return `numpy.nan` values; otherwise, the span + will form one larger crossing-island. - voltage: np.ndarray - 1-D numpy array of ascending probe biases (in Volts) + #. To calculate the floating potential... - current: np.ndarray - 1-D numpy array of probe current (in A) corresponding to the :data:`voltage` - array + - If the crossing-island contains less points than ``min_points``, then + each side of the crossing-island is equally padded with the nearest + neighbor points until ``min_points`` is satisfied. + - A fit is then performed using `scipy.stats.linregress` for + ``fit_type="linear"`` and `scipy.optimize.curve_fit` for + ``fit_type="exponential"``. - threshold: positive, non-zero int - Max index distance between found crossing-points to group crossing-points - into crossing-islands. That is, if `threshold=5` then consecutive - crossing-points are considered to be in the same crossing-island if they are - within 5 indices of each other. (Default: 1) + Parameters + ---------- - min_points: positive, non-zero int - The minimum number of points required for the linear regression. (Default: 5) + voltage: ~numpy.ndarray + 1-D numpy array of monotonically ascending/descending probe biases + (in Volts) + + current: ~numpy.ndarray + 1-D numpy array of probe current (in A) corresponding to the + :data:`voltage` array + + threshold: positive, non-zero `int` + Max allowed index distance between crossing-points before a new + crossing-island is formed. That is, if `threshold=5` then consecutive + crossing-points are considered to be in the same crossing-island if + they are within 5 index steps of each other. (Default: 1) + + min_points: positive `int` or `float` + Specifies the minimum number of points required for the fit to be + applied to. + + - ``min_points = None`` (Default) The larger of 5 and + ``factor * array_size`` is taken, where ``array_size`` is the size of + ``voltage`` and ``factor = 0.1`` for ``fit_type = "linear"`` and + ``0.2`` for ``"exponential"``. + - ``min_points = 0`` The entire passed array is fitted. + - ``min_points >= 1`` Exact minimum number of points. + - ``0 < min_points < 0`` The minimum number of points is taken as + ``min_points * array_size``. + + fit_type: str + The type of curve to be fitted to (``voltage``, ``current``). There + are two types of curves ``"linear"`` and ``"exponential"`` (Default). Returns ------- - vf: `numpy.float64` or `numpy.nan` + vf: `float` or `numpy.nan` The calculated floating potential (in Volts). Returns `numpy.nan` if the floating potential can not be determined. - vf_err: `numpy.float64` or `numpy.nan` + vf_err: `float` or `numpy.nan` The error associated with the floating potential calculation (in Volts). Returns `numpy.nan` if the floating potential can not be determined. - fit: Dict[str, Any] - A dictionary containing the linear regression fit results and parameters. - Keys are `'slope'`, `'slope_err'`, `'intercept'`, `'intercept_err'`, and - `'indices'`, where `'indices'` is a `slice` object corresponding to the - data points used in the fit. Returns an empty dict if the floating - potential can not be determined. + info: Dict[str, Any] + A dictionary containing meta-info about the fit with keys... + + - ``"func"``: The fitted function which is either an instance of + `LinearFitFunction` or `ExponentialOffsetFitFunciton`. + - ``"indices"``: A `slice` object representing the indices of + ``voltage`` and ``current`` used for the fit. + - ``"islands"``: List of `slice` objects reprsenting the indices of the + identified crossing-islands. + - ``"rsq"``: The coefficient of determination (r-squared) vlaue of the + fit. """ fit_funcs = { From 083e005ff0b6483655a07f4754c70c7b3fc76fd2 Mon Sep 17 00:00:00 2001 From: Erik Date: Tue, 8 Sep 2020 19:08:17 -0700 Subject: [PATCH 049/521] add comment organization to CSS; add margin-bottom for a nested unordered list within an ordered list --- docs/_static/rtd_theme_overrides.css | 39 ++++++++++++++++++---------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/docs/_static/rtd_theme_overrides.css b/docs/_static/rtd_theme_overrides.css index ccee92798a..685c322002 100644 --- a/docs/_static/rtd_theme_overrides.css +++ b/docs/_static/rtd_theme_overrides.css @@ -1,3 +1,29 @@ +/* ----------------------------------------------------------------------------- + * RTD Overrides + */ + +/* Style for toctree in a table */ +td .toctree-wrapper ul { + margin-bottom: 0 !important; + line-height: 18px !important; + list-style: none !important; + font-size: 16px; +} + +td .toctree-wrapper ul li { + list-style: none !important; + margin-left: 0 !important; +} + +/* Unordered list nested in ordered list */ +ol li ul { + margin-bottom: 12px !important; +} + +/* ----------------------------------------------------------------------------- + * RTD layout styling additions + */ + /* Style for module/index links in sidebar below the search field. */ div.pkgnav { text-align: center; @@ -27,16 +53,3 @@ div.pkgnav ul li a:hover { color: white; text-shadow: 0px 0px 1px rgba(255, 255, 255, 0.5); } - -/* Style for toctree in a table */ -td .toctree-wrapper ul { - margin-bottom: 0px !important; - line-height: 18px !important; - list-style: none !important; - font-size: 16px; -} - -td .toctree-wrapper ul li { - list-style: none !important; - margin-left: 0px !important; -} From 99086ea1e4c0d04d6244c43ffe0e0e139d3cde70 Mon Sep 17 00:00:00 2001 From: Erik Date: Tue, 8 Sep 2020 19:14:41 -0700 Subject: [PATCH 050/521] fill out description for the "Analyses & Diagnostics" page --- docs/ad/index.rst | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/docs/ad/index.rst b/docs/ad/index.rst index 82f7bdf7a7..7e4c9d3b97 100644 --- a/docs/ad/index.rst +++ b/docs/ad/index.rst @@ -7,8 +7,9 @@ Analyses & Diagnostics ====================== Analyses and diagnostics go hand-in-hand, but have subtle differences. Thus, -PlasmaPy gives them their own sub-packages, `plasmapy.analysis` and -`plasmapy.diagnostics`. +PlasmaPy gives each their own sub-packages, `plasmapy.analysis` and +`plasmapy.diagnostics` respectively. + Think of the `plasmapy.analysis` as your toolbox. It has all the tools (functionality) you need to analyze your data. Functionality is built around @@ -18,16 +19,30 @@ discrete Fourier Transform. Similarly, :func:`plasmapy.analysis.swept_langmuir.find_floating_potential` only finds the floating potential for a given langmuir trace. It does not have smoothing. It does not do any filtering. It does not do any signal conditioning. It has a -singular task. +singular task to find the floating potential of a single langmuir trace. + +Diagnostics on the other-hand have a much broader scope and leverage the tools +defined in `plasmapy.analysis` to give a more integrated user experience when +analyzing data. Diagnostics try to enhance the analysis workflow by focusing +on some of following key areas... + +#. A more human-friendly way of managing data by building an interface around + `xarray` arrays and datasets via custom diagnostic accessors. + + - `xarray` provides labelled multi-dimensional arrays and datasets. + - Diagnostics self-manage the computed analysis data within a `xarray` + dataset while maintaining the computed data's relation to the original + data. -Diagnostics on the other-hand have a much broader scope, which leverages the tools -defined in `plasmapy.analysis`. +#. Quick viewing of analyzed data with default plotting routines. +#. Fully defining the physical parameters of a diagnostic with purposely + designed Probe classes that are integrated into the analysis workflow. +#. Adding GUI's to the analysis workflow via notebook widgets. ---- .. toctree:: :maxdepth: 2 - :caption: The Packages Analyses Diagnostics From 0138ac9bca095a7a3557c64317c1c1b3a654c90e Mon Sep 17 00:00:00 2001 From: Erik Date: Tue, 8 Sep 2020 19:43:42 -0700 Subject: [PATCH 051/521] add FutureWarnings to public facing API of plasmapy.diagnostics.langmuir --- plasmapy/diagnostics/langmuir.py | 39 ++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/plasmapy/diagnostics/langmuir.py b/plasmapy/diagnostics/langmuir.py index ea9e8b013b..87d7cb31c6 100644 --- a/plasmapy/diagnostics/langmuir.py +++ b/plasmapy/diagnostics/langmuir.py @@ -25,11 +25,19 @@ from astropy.constants import si as const from astropy.visualization import quantity_support from scipy.optimize import curve_fit +from warnings import warn from plasmapy.particles import Particle from plasmapy.utils.decorators import validate_quantities +def _langmuir_futurewarning() -> None: + warn("The plasmapy.diagnostics.langmuir module will be deprecated in favor of " + "the plasmapy.analysis.swept_langmuir sub-package. The analysis package " + " is in active development and is scheduled to be released with v0.5.0.", + FutureWarning) + + def _fit_func_lin(x, x0, y0, c0): r"""Linear fitting function.""" @@ -69,6 +77,7 @@ class Characteristic: Array of applied probe currents in units convertible to A. """ + _langmuir_futurewarning() @validate_quantities(bias={"can_be_inf": False}, current={"can_be_inf": False}) def __init__(self, bias: u.V, current: u.A): @@ -284,6 +293,8 @@ def swept_probe_analysis( for OML theory hold. """ + _langmuir_futurewarning() + # Instantiate gas using the Particle class gas = Particle(argument=gas_argument) @@ -467,6 +478,8 @@ def get_plasma_potential(probe_characteristic, return_arg=False): """ + _langmuir_futurewarning() + if not isinstance(probe_characteristic, Characteristic): raise TypeError( f"For 'probe_characteristic' expected type " @@ -517,6 +530,8 @@ def get_floating_potential(probe_characteristic, return_arg=False): """ + _langmuir_futurewarning() + if not isinstance(probe_characteristic, Characteristic): raise TypeError( f"For 'probe_characteristic' expected type " @@ -554,6 +569,8 @@ def get_electron_saturation_current(probe_characteristic): """ + _langmuir_futurewarning() + if not isinstance(probe_characteristic, Characteristic): raise TypeError( f"For 'probe_characteristic' expected type " @@ -589,6 +606,8 @@ def get_ion_saturation_current(probe_characteristic): """ + _langmuir_futurewarning() + if not isinstance(probe_characteristic, Characteristic): raise TypeError( f"For 'probe_characteristic' expected type " @@ -653,6 +672,8 @@ def get_ion_density_LM( """ + _langmuir_futurewarning() + # Calculate the acoustic (Bohm) velocity c_s = np.sqrt(T_e / gas) @@ -713,6 +734,8 @@ def get_electron_density_LM( """ + _langmuir_futurewarning() + # Calculate the thermal electron velocity v_th = np.sqrt(8 * T_e / (np.pi * const.m_e)) @@ -753,6 +776,8 @@ def extract_exponential_section(probe_characteristic, T_e=None, ion_current=None """ + _langmuir_futurewarning() + if not isinstance(probe_characteristic, Characteristic): raise TypeError( f"For 'probe_characteristic' expected type " @@ -807,6 +832,8 @@ def extract_ion_section(probe_characteristic): """ + _langmuir_futurewarning() + if not isinstance(probe_characteristic, Characteristic): raise TypeError( f"For 'probe_characteristic' expected type " @@ -876,6 +903,8 @@ def get_electron_temperature( """ + _langmuir_futurewarning() + if not isinstance(exponential_section, Characteristic): raise TypeError( f"For 'probe_characteristic' expected type " @@ -1038,6 +1067,8 @@ def extrapolate_electron_current( """ + _langmuir_futurewarning() + if not isinstance(probe_characteristic, Characteristic): raise TypeError( f"For 'probe_characteristic' expected type " @@ -1126,6 +1157,8 @@ def reduce_bimaxwellian_temperature(T_e: u.eV, hot_fraction: float) -> u.eV: """ + _langmuir_futurewarning() + # Return the electron temperature itself if it is not bi-Maxwellian # in the first place. if hot_fraction is None or not np.array(T_e).size > 1: @@ -1188,6 +1221,8 @@ def get_ion_density_OML( """ + _langmuir_futurewarning() + if not isinstance(probe_characteristic, Characteristic): raise TypeError( f"For 'probe_characteristic' expected type " @@ -1273,6 +1308,8 @@ def extrapolate_ion_current_OML(probe_characteristic, fit, visualize=False): """ + _langmuir_futurewarning() + if not isinstance(probe_characteristic, Characteristic): raise TypeError( f"For 'probe_characteristic' expected type " @@ -1355,6 +1392,8 @@ def get_EEDF(probe_characteristic, visualize=False): """ + _langmuir_futurewarning() + if not isinstance(probe_characteristic, Characteristic): raise TypeError( f"For 'probe_characteristic' expected type " From ae00207f7eb2eaf2624a307bfccb7adbd89981a6 Mon Sep 17 00:00:00 2001 From: Erik Everson Date: Wed, 9 Sep 2020 11:05:42 -0700 Subject: [PATCH 052/521] Apply suggestions from code review Co-authored-by: Nick Murphy --- docs/ad/index.rst | 2 +- plasmapy/analysis/swept_langmuir/floating_potential.py | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/ad/index.rst b/docs/ad/index.rst index 7e4c9d3b97..e2cf412f45 100644 --- a/docs/ad/index.rst +++ b/docs/ad/index.rst @@ -17,7 +17,7 @@ Think of the `plasmapy.analysis` as your toolbox. It has all the tools :func:`numpy.fft.fft` does one specific task, compute the one-dimensional discrete Fourier Transform. Similarly, :func:`plasmapy.analysis.swept_langmuir.find_floating_potential` only finds the -floating potential for a given langmuir trace. It does not have smoothing. +floating potential for a given Langmuir trace. It does not have smoothing. It does not do any filtering. It does not do any signal conditioning. It has a singular task to find the floating potential of a single langmuir trace. diff --git a/plasmapy/analysis/swept_langmuir/floating_potential.py b/plasmapy/analysis/swept_langmuir/floating_potential.py index 883152aee7..67ff775a05 100644 --- a/plasmapy/analysis/swept_langmuir/floating_potential.py +++ b/plasmapy/analysis/swept_langmuir/floating_potential.py @@ -63,7 +63,7 @@ def find_floating_potential( (in Volts) current: ~numpy.ndarray - 1-D numpy array of probe current (in A) corresponding to the + 1-D numpy array of probe current (in amperes) corresponding to the :data:`voltage` array threshold: positive, non-zero `int` @@ -92,11 +92,11 @@ def find_floating_potential( Returns ------- vf: `float` or `numpy.nan` - The calculated floating potential (in Volts). Returns `numpy.nan` if the + The calculated floating potential (in volts). Returns `numpy.nan` if the floating potential can not be determined. vf_err: `float` or `numpy.nan` - The error associated with the floating potential calculation (in Volts). + The error associated with the floating potential calculation (in volts). Returns `numpy.nan` if the floating potential can not be determined. info: Dict[str, Any] From 993cc2f4df5973d7f8a36394235c622d78a60ddf Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 10 Sep 2020 19:43:10 -0700 Subject: [PATCH 053/521] move _langmuir_futurewarning() into Characteristic.__init__ so the warning is only used when functionality is used --- plasmapy/diagnostics/langmuir.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plasmapy/diagnostics/langmuir.py b/plasmapy/diagnostics/langmuir.py index 87d7cb31c6..3f04f40566 100644 --- a/plasmapy/diagnostics/langmuir.py +++ b/plasmapy/diagnostics/langmuir.py @@ -77,10 +77,11 @@ class Characteristic: Array of applied probe currents in units convertible to A. """ - _langmuir_futurewarning() @validate_quantities(bias={"can_be_inf": False}, current={"can_be_inf": False}) def __init__(self, bias: u.V, current: u.A): + _langmuir_futurewarning() + self.bias = bias self.current = current self.get_unique_bias(True) From 98fd25f0a951d1e1ecb7804dcc16946ce6e6046b Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 10 Sep 2020 19:43:42 -0700 Subject: [PATCH 054/521] remove redundant units --- docs/_static/rtd_theme_overrides.css | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/_static/rtd_theme_overrides.css b/docs/_static/rtd_theme_overrides.css index 685c322002..21554993b8 100644 --- a/docs/_static/rtd_theme_overrides.css +++ b/docs/_static/rtd_theme_overrides.css @@ -46,10 +46,10 @@ div.pkgnav ul li a { /*padding: 0 5px 0 5px;*/ /*line-height: 1.75em;*/ color: #f9f9f0; - text-shadow: 0px 0px 1px rgba(0, 0, 0, 0.5); + text-shadow: 0 0 1px rgba(0, 0, 0, 0.5); } div.pkgnav ul li a:hover { color: white; - text-shadow: 0px 0px 1px rgba(255, 255, 255, 0.5); + text-shadow: 0 0 1px rgba(255, 255, 255, 0.5); } From 168227f4eda1aa0d1188927aa35d7085d376994d Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 10 Sep 2020 19:44:18 -0700 Subject: [PATCH 055/521] update margin-bottom so it's applied whenever an unordered list is nested --- docs/_static/rtd_theme_overrides.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/_static/rtd_theme_overrides.css b/docs/_static/rtd_theme_overrides.css index 21554993b8..c2b750e91e 100644 --- a/docs/_static/rtd_theme_overrides.css +++ b/docs/_static/rtd_theme_overrides.css @@ -16,7 +16,7 @@ td .toctree-wrapper ul li { } /* Unordered list nested in ordered list */ -ol li ul { +.section li ul { margin-bottom: 12px !important; } From faa07f031afed0326b264bc247ce470be36b22a8 Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 10 Sep 2020 19:45:16 -0700 Subject: [PATCH 056/521] convert return of find_floating_potential() to a namedtuple --- .../swept_langmuir/floating_potential.py | 42 ++++++++++++------- 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/plasmapy/analysis/swept_langmuir/floating_potential.py b/plasmapy/analysis/swept_langmuir/floating_potential.py index 883152aee7..0a391d3307 100644 --- a/plasmapy/analysis/swept_langmuir/floating_potential.py +++ b/plasmapy/analysis/swept_langmuir/floating_potential.py @@ -13,7 +13,8 @@ ) FloatingPotentialResults = namedtuple( - "FloatingPotentialResults", ("vf", "vf_err", "info") + "FloatingPotentialResults", + ("vf", "vf_err", "rsq", "func", "islands", "indices"), ) @@ -112,6 +113,15 @@ def find_floating_potential( fit. """ + rtn = FloatingPotentialResults( + vf=np.nan, + vf_err=np.nan, + rsq=None, + func=None, + islands=None, + indices=None + )._asdict() + fit_funcs = { "linear": { "func": LinearFitFunction(), @@ -123,9 +133,9 @@ def find_floating_potential( }, } try: - fit_func = fit_funcs[fit_type]["func"] min_point_factor = fit_funcs[fit_type]["min_point_factor"] - meta_dict = {"func": fit_func} + fit_func = fit_funcs[fit_type]["func"] + rtn["func"] = fit_func except KeyError: raise KeyError( f"Requested fit function '{fit_type}' is not a valid option. " @@ -135,14 +145,14 @@ def find_floating_potential( if current.min() > 0.0 or current.max() < 0: warn("The Langmuir sweep has no floating potential.") - return FloatingPotentialResults(np.nan, np.nan, meta_dict) + return FloatingPotentialResults(**rtn) # check voltage is monotonically increasing/decreasing voltage_diff = np.diff(voltage) if not (np.all(voltage_diff >= 0) or np.all(voltage_diff <= 0)): warn("The voltage array is not monotonically increasing or decreasing.") - return FloatingPotentialResults(np.nan, np.nan, meta_dict) + return FloatingPotentialResults(**rtn) # condition kwarg threshold if isinstance(threshold, (int, float)): @@ -195,9 +205,9 @@ def find_floating_potential( n_islands = threshold_indices.size + 1 if min_points == 0: - meta_dict["islands"] = [slice(cp_candidates[0], cp_candidates[-1] + 1)] + rtn["islands"] = [slice(cp_candidates[0], cp_candidates[-1] + 1)] elif n_islands == 1: - meta_dict["islands"] = [slice(cp_candidates[0], cp_candidates[-1] + 1)] + rtn["islands"] = [slice(cp_candidates[0], cp_candidates[-1] + 1)] else: # There are multiple crossing points isl_start = np.concatenate(( @@ -208,19 +218,19 @@ def find_floating_potential( cp_candidates[threshold_indices]+1, [cp_candidates[-1]+1], )) - meta_dict["islands"] = [] + rtn["islands"] = [] for start, stop in zip(isl_start, isl_stop): - meta_dict["islands"].append(slice(start, stop)) + rtn["islands"].append(slice(start, stop)) # do islands fall within min_points window - isl_window = np.abs(np.r_[meta_dict["islands"][-1]][-1] - - np.r_[meta_dict["islands"][0]][0]) + 1 + isl_window = np.abs(np.r_[rtn["islands"][-1]][-1] + - np.r_[rtn["islands"][0]][0]) + 1 if isl_window > min_points: warn(f"Unable to determine floating potential, Langmuir sweep has " f"{n_islands} crossing-islands. Try adjusting keyword 'threshold' " f"and/or smooth the current.") - return FloatingPotentialResults(np.nan, np.nan, meta_dict) + return FloatingPotentialResults(**rtn) # Construct crossing-island (pad if needed) if min_points == 0: @@ -266,10 +276,10 @@ def find_floating_potential( curr_sub = current[istart:istop + 1] fit_func.curve_fit(volt_sub, curr_sub) - vf, vf_err = fit_func.root_solve() - meta_dict.update({ + rtn["vf"], rtn["vf_err"] = fit_func.root_solve() + rtn.update({ "rsq": fit_func.rsq, - "indices": slice(istart, istop+1) + "indices": slice(istart, istop + 1) }) - return FloatingPotentialResults(vf, vf_err, meta_dict) + return FloatingPotentialResults(**rtn) From 866872fb0b253764bb88b0459a6382355294afa9 Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 10 Sep 2020 20:05:18 -0700 Subject: [PATCH 057/521] update AbstractFitFunction and it's sub-classes s.t. parameters and parameters_err are returned as namedtuples; the names in the tuple are defined with class attr _parameter_names --- .../analysis/swept_langmuir/fit_functions.py | 30 ++++++++++++++----- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/plasmapy/analysis/swept_langmuir/fit_functions.py b/plasmapy/analysis/swept_langmuir/fit_functions.py index c2944f6836..951b282443 100644 --- a/plasmapy/analysis/swept_langmuir/fit_functions.py +++ b/plasmapy/analysis/swept_langmuir/fit_functions.py @@ -11,9 +11,10 @@ import numpy as np from abc import ABC, abstractmethod +from collections import namedtuple from scipy.stats import linregress from scipy.optimize import curve_fit, fsolve -from typing import Tuple +from typing import Any, NamedTuple, Tuple, Union class AbstractFitFunction(ABC): @@ -23,12 +24,16 @@ class AbstractFitFunction(ABC): assisting in fitting curves to swept langmuir data. """ - _parameters = None # type: Tuple - _parameters_err = None # type: Tuple + _parameter_names = () # type: Tuple[str, ...] + _parameters = None # type: Union[None, Tuple[Any, ...]] + _parameters_err = None # type: Union[None, Tuple[Any, ...]] _covariance_matrix = None _rsq = None _curve_fit_results = None + def __init__(self): + self._ParamTuple = namedtuple("_ParamTuple", self._parameter_names) + def __call__(self, x): """ Direct call of the fit function :math:`f(x)``. @@ -81,14 +86,20 @@ def curve_fit_results(self): return self._curve_fit_results @property - def parameters(self) -> Tuple: + def parameters(self) -> Union[None, NamedTuple]: """The fitted parameters for the fit function.""" - return self._parameters + if self._parameters is None: + return self._parameters + else: + return self._ParamTuple(*self._parameters) @property - def parameters_err(self) -> Tuple: + def parameters_err(self) -> Union[None, NamedTuple]: """The associated errors of the fit `parameters`.""" - return self._parameters_err + if self._parameters_err is None: + return self._parameters_err + else: + return self._ParamTuple(*self._parameters_err) @property @abstractmethod @@ -207,6 +218,8 @@ class ExponentialOffsetFitFunction(AbstractFitFunction): and :math:`x` is the independent variable. """ + _parameter_names = ("a", "b", "c") + def __str__(self): return f"f(x) = A exp(B x) + C" @@ -295,6 +308,9 @@ class LinearFitFunction(AbstractFitFunction): variable. """ + + _parameter_names = ("m", "b") + def __str__(self): return f"f(x) = m x + b" From 66ebc7e3b05045cdf4ade8db1e86c15eafb66797 Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 10 Sep 2020 20:06:40 -0700 Subject: [PATCH 058/521] add to docstrings the formulae for the fit function root and its error propogation --- .../analysis/swept_langmuir/fit_functions.py | 27 ++++++++++++++++--- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/plasmapy/analysis/swept_langmuir/fit_functions.py b/plasmapy/analysis/swept_langmuir/fit_functions.py index 951b282443..ef7edd8121 100644 --- a/plasmapy/analysis/swept_langmuir/fit_functions.py +++ b/plasmapy/analysis/swept_langmuir/fit_functions.py @@ -109,12 +109,12 @@ def latex_str(self) -> str: def root_solve(self, x0, **kwargs): """ - Solve for the root of the fit function (i.e. `f(x) = 0`). + Solve for the root of the fit function (i.e. :math:`f(x_r) = 0`). Parameters ---------- x0: `~numpy.ndarray` - The starting estimate for the roots of `f(x) = 0`. + The starting estimate for the roots of :math:`f(x_r) = 0`. **kwargs Any keyword accepted by `scipy.optimize.fsolve`, except for `args`. @@ -262,7 +262,17 @@ def latex_str(self) -> str: def root_solve(self, *args, **kwargs): """ - The root :math:`f(x) = 0` for the fit function. + The root :math:`f(x_r) = 0` for the fit function. + + .. math:: + + x_r &= \\frac{1}{B} \\ln \\left( \\frac{-C}{A} \\right) + + \\delta x_r &= \\sqrt{ + \\left( \\frac{\\delta A}{A B} \\right)^2 + + \\left( x_r \\frac{\\delta B}{B} \\right)^2 + + \\left( \\frac{\\delta C}{B C} \\right)^2 + } Parameters ---------- @@ -350,7 +360,16 @@ def latex_str(self) -> str: def root_solve(self, *args, **kwargs): """ - The root :math:`f(x) = 0` for the fit function. + The root :math:`f(x_r) = 0` for the fit function. + + .. math:: + + x_r &= \\frac{-b}{m} + + \\delta x_r &= |x_r| \\sqrt{ + \\left( \\frac{\\delta m}{m} \\right)^2 + + \\left( \\frac{\\delta b}{b} \\right)^2 + } Parameters ---------- From 22c1d61f7cb5379fee08b80008fbc8b256b72bed Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 10 Sep 2020 20:22:36 -0700 Subject: [PATCH 059/521] add docstrings explaining the method of calculation for rsq. --- .../analysis/swept_langmuir/fit_functions.py | 25 ++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/plasmapy/analysis/swept_langmuir/fit_functions.py b/plasmapy/analysis/swept_langmuir/fit_functions.py index ef7edd8121..ca29b9c290 100644 --- a/plasmapy/analysis/swept_langmuir/fit_functions.py +++ b/plasmapy/analysis/swept_langmuir/fit_functions.py @@ -154,7 +154,22 @@ def root_solve(self, x0, **kwargs): @property def rsq(self): - """Coefficient of determination (r-squared) value of the fit.""" + """ + Coefficient of determination (r-squared) value of the fit. + + .. math:: + + r^2 &= 1 - \\frac{SS_{res}}{SS_{tot}} + + SS_{res} &= \\sum\\limits_{i} (y_i - f(x_i))^2 + + SS_{tot} &= \\sum\\limits_{i} (y_i - \\bar{y})^2 + + where :math:`(x_i, y_i)` are the sample data pairs, :math:`f(x_i)` is + the fitted dependent variable corresponding to :math:`x_i`, and + :math:`\\bar{y}` is the average of the :math:`y_i` values. + + """ return self._rsq def curve_fit(self, xdata, ydata, **kwargs) -> None: @@ -358,6 +373,14 @@ def _func(self, x, m, b): def latex_str(self) -> str: return fr"m \, x + b" + @property + def rsq(self): + """ + Coefficient of determination (r-squared) value of the fit. Calculated + by `scipy.stats.linregress` from the fit. + """ + return self._rsq + def root_solve(self, *args, **kwargs): """ The root :math:`f(x_r) = 0` for the fit function. From c9e34e8809d71134805a7a088cb9a5f0c4bc84f8 Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 10 Sep 2020 20:31:05 -0700 Subject: [PATCH 060/521] update find_floating_potential notebook to reflect recent changes made to FitFunctions and find_floating_potential() --- .../find_floating_potential.ipynb | 71 +++++++++++++------ 1 file changed, 50 insertions(+), 21 deletions(-) diff --git a/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb b/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb index 0e47f95b6a..0d7ce4966e 100644 --- a/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb +++ b/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb @@ -51,7 +51,7 @@ "\n", "- `fit_type`\n", "\n", - " There are two types of curves that can be fitted to the identified crossing point data, `\"linear\"` and `\"expoenetion\"`. The former will fit fit a line to the data, whereas, the later will fit and expoenetial curve with an offset. The default curve is `\"exponential\"` since swept langmuir data is not typically linear as it passes through $I=0$.\n", + " There are two types of curves that can be fitted to the identified crossing point data, `\"linear\"` and `\"expoenetion\"`. The former will fit fit a line to the data, whereas, the later will fit and expoenetial curve with an offset. The default curve is `\"exponential\"` since swept Langmuir data is not typically linear as it passes through $I=0$.\n", "\n", "- `min_points`\n", "\n", @@ -99,16 +99,42 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "The fit returns a three element named tuple, where...\n", + "The `find_floating_potential()` returns a named tuple, where...\n", "\n", - "- `results.vf` = the determined floating potential (in Volts)\n", - "- `resutls.vf_err` = the associated error (in Volts)\n", - "- `results.info` = dictionary of meta-info form the fit\n", + "- `results[0]` = `results.vf` = the determined floating potential (in volts)\n", + "- `results[1]` = `resutls.vf_err` = the associated error (in volts)\n", + "- `results[2]` = `results.rsq` = the coeficient of determination (r-squared) value of the fit\n", + "- `results[3]` = `results.func` = the resulting fitted function\n", "\n", - " - `results.info[\"func\"]` is the constructed fit function\n", - " - `results.info[\"indicies\"]` is a slice object representing the indices used in the fit\n", - " - `results.info[\"islands\"]` is a list of slice objects representing all the indentified crossing-islands\n", - " - `results.info[\"rsq\"]` is the coefficient of determination (or r-squared) value of the fit" + " - Look to the [**FitFuction** classes](../../../api_static/plasmapy.analysis.swept_langmuir.fit_functions.rst) to see the features of `results.func`.\n", + " - Documentaiton for the `root_solve()` method of your respective fit function (e.g. [**ExponentialOffsetFitFunction.root_solve()**](../../../api/plasmapy.analysis.swept_langmuir.fit_functions.ExponentialOffsetFitFunction.rst#plasmapy.analysis.swept_langmuir.fit_functions.ExponentialOffsetFitFunction.root_solve) ) will describe how the root (i.e. $V_F$) is calculated and its associated error propogation.\n", + "\n", + "\n", + "- `results[4]` = `results.islands` = a list of slice objects representing all the indentified crossing-islands\n", + "- `results[5]` = `results.indices` = a slice objec representing the indices used in the fit" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(\n", + " f\"results[0] = results.vf = {results.vf:.3f} V\\n\"\n", + " f\"results[1] = results.vf_err = {results.vf_err:.3f} V\\n\"\n", + " f\"results[2] = results.rsq = {results.rsq:.3f}\\n\"\n", + " f\"results[3] = results.func = {results.func}\\n\"\n", + " f\"results[4] = results.islands = {results.islands}\\n\"\n", + " f\"results[5] = results.indices = {results.indices}\"\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Additional fit parameters can be accessed directly from `resulst.func`." ] }, { @@ -118,11 +144,14 @@ "outputs": [], "source": [ "print(\n", - " f\"results[0] = results.vf = {results.vf:0.3f} V\\n\"\n", - " f\"results[1] = results.vf_err = {results.vf_err:0.3f} V\\n\"\n", - " f\"results[2] = results.info =\"\n", - ")\n", - "pprint.pprint(results.info, indent=4)" + " f\"Fitted parameters = results.func.parameters = \\n\"\n", + " f\" {results.func.parameters}\\n\"\n", + " f\"Fitted parameter errors = results.func.parameters_err = \\n\"\n", + " f\" {results.func.parameters_err}\\n\"\n", + " f\"\\n\"\n", + " f\"These are also namedtuples, so \"\n", + " f\"results.func.parameters.a = {results.func.parameters.a:.4f}.\\n\"\n", + ")" ] }, { @@ -158,12 +187,12 @@ "for ii, label, fit in zip([1, 2], [\"Exponential\", \"Linear\"], [results, results_lin]):\n", " # calc island points\n", " isl_pts = np.array([], dtype=np.int64)\n", - " for isl in fit.info[\"islands\"]:\n", + " for isl in fit.islands:\n", " isl_pts = np.concatenate((isl_pts, np.r_[isl]))\n", " \n", " # calc xrange for plot\n", - " xlim = [voltage[fit.info['indices']].min(),\n", - " voltage[fit.info['indices']].max()]\n", + " xlim = [voltage[fit.indices].min(),\n", + " voltage[fit.indices].max()]\n", " vpad = 0.25 * (xlim[1] - xlim[0])\n", " xlim = [xlim[0] - vpad,\n", " xlim[1] + vpad]\n", @@ -173,7 +202,7 @@ " mask2 = np.where(voltage <= xlim[1], True, False)\n", " mask = np.logical_and(mask1, mask2)\n", " vfit = np.linspace(xlim[0], xlim[1], 201, endpoint=True)\n", - " ifit = fit.info[\"func\"](vfit)\n", + " ifit = fit.func(vfit)\n", "\n", " axs[ii].set_xlabel(\"Bias Voltage (V)\", fontsize=12)\n", " axs[ii].set_ylabel(\"Current (A)\", fontsize=12)\n", @@ -183,8 +212,8 @@ " marker=\"o\", \n", " zorder=10, \n", " label=\"Sweep Data\")\n", - " axs[ii].scatter(voltage[fit.info[\"indices\"]],\n", - " current[fit.info[\"indices\"]],\n", + " axs[ii].scatter(voltage[fit.indices],\n", + " current[fit.indices],\n", " linewidth=2, s=6**2, \n", " facecolors=\"deepskyblue\", edgecolors=\"deepskyblue\",\n", " zorder=11,\n", @@ -207,7 +236,7 @@ " axs[ii].legend(fontsize=12)\n", "\n", " # add text\n", - " rsq = fit.info[\"rsq\"]\n", + " rsq = fit.rsq\n", " txt = (f\"$V_f = {fit.vf:.2f} \\\\pm {fit.vf_err:.2f}$ V\\n\"\n", " f\"$r^2 = {rsq:.3f}$\")\n", " txt_loc = [fit.vf, axs[ii].get_ylim()[1]]\n", From dc4703c4573401aeeddc4f275ade575f2645acff Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 10 Sep 2020 20:31:42 -0700 Subject: [PATCH 061/521] use Langmuir instead of langmuir when talking in general --- docs/ad/index.rst | 4 ++-- docs/notebooks/langmuir_samples/_generate_noisy.ipynb | 2 +- plasmapy/analysis/swept_langmuir/fit_functions.py | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/ad/index.rst b/docs/ad/index.rst index 7e4c9d3b97..887f098eb5 100644 --- a/docs/ad/index.rst +++ b/docs/ad/index.rst @@ -17,9 +17,9 @@ Think of the `plasmapy.analysis` as your toolbox. It has all the tools :func:`numpy.fft.fft` does one specific task, compute the one-dimensional discrete Fourier Transform. Similarly, :func:`plasmapy.analysis.swept_langmuir.find_floating_potential` only finds the -floating potential for a given langmuir trace. It does not have smoothing. +floating potential for a given Langmuir trace. It does not have smoothing. It does not do any filtering. It does not do any signal conditioning. It has a -singular task to find the floating potential of a single langmuir trace. +singular task to find the floating potential of a single Langmuir trace. Diagnostics on the other-hand have a much broader scope and leverage the tools defined in `plasmapy.analysis` to give a more integrated user experience when diff --git a/docs/notebooks/langmuir_samples/_generate_noisy.ipynb b/docs/notebooks/langmuir_samples/_generate_noisy.ipynb index 26d8e30f3a..82a99e5cd2 100644 --- a/docs/notebooks/langmuir_samples/_generate_noisy.ipynb +++ b/docs/notebooks/langmuir_samples/_generate_noisy.ipynb @@ -6,7 +6,7 @@ "source": [ "# Generate noisy signals\n", "\n", - "The default langmuir samples are not noisy and, thus, do not properly reflect real world data. This notebook will add noise to the signals to help simulate real world data." + "The default Langmuir samples are not noisy and, thus, do not properly reflect real world data. This notebook will add noise to the signals to help simulate real world data." ] }, { diff --git a/plasmapy/analysis/swept_langmuir/fit_functions.py b/plasmapy/analysis/swept_langmuir/fit_functions.py index ca29b9c290..1851ff6c34 100644 --- a/plasmapy/analysis/swept_langmuir/fit_functions.py +++ b/plasmapy/analysis/swept_langmuir/fit_functions.py @@ -21,7 +21,7 @@ class AbstractFitFunction(ABC): """ Abstract class for defining fit functions :math:`f(x)` and the tools for fitting the function to a set of data. These were originally designed for - assisting in fitting curves to swept langmuir data. + assisting in fitting curves to swept Langmuir data. """ _parameter_names = () # type: Tuple[str, ...] From f4d4e84c46314915c10580bf83a5d1b9eb848f8e Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 10 Sep 2020 20:33:09 -0700 Subject: [PATCH 062/521] update wording --- .../analysis/swept_langmuir/find_floating_potential.ipynb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb b/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb index 0d7ce4966e..778116dd39 100644 --- a/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb +++ b/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb @@ -107,7 +107,7 @@ "- `results[3]` = `results.func` = the resulting fitted function\n", "\n", " - Look to the [**FitFuction** classes](../../../api_static/plasmapy.analysis.swept_langmuir.fit_functions.rst) to see the features of `results.func`.\n", - " - Documentaiton for the `root_solve()` method of your respective fit function (e.g. [**ExponentialOffsetFitFunction.root_solve()**](../../../api/plasmapy.analysis.swept_langmuir.fit_functions.ExponentialOffsetFitFunction.rst#plasmapy.analysis.swept_langmuir.fit_functions.ExponentialOffsetFitFunction.root_solve) ) will describe how the root (i.e. $V_F$) is calculated and its associated error propogation.\n", + " - For example, the documentaiton for the `root_solve()` method of your respective fit function (e.g. [**ExponentialOffsetFitFunction.root_solve()**](../../../api/plasmapy.analysis.swept_langmuir.fit_functions.ExponentialOffsetFitFunction.rst#plasmapy.analysis.swept_langmuir.fit_functions.ExponentialOffsetFitFunction.root_solve) ) will describe how the root (i.e. $V_F$) is calculated and its associated error propogation.\n", "\n", "\n", "- `results[4]` = `results.islands` = a list of slice objects representing all the indentified crossing-islands\n", From 0c470656f79852bf22cff4043c8459e9b1309d5f Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 10 Sep 2020 21:08:11 -0700 Subject: [PATCH 063/521] update docstrings to indicate implementation of namedtuple return --- .../swept_langmuir/floating_potential.py | 57 +++++++++++++------ 1 file changed, 39 insertions(+), 18 deletions(-) diff --git a/plasmapy/analysis/swept_langmuir/floating_potential.py b/plasmapy/analysis/swept_langmuir/floating_potential.py index 0a391d3307..af74d8df34 100644 --- a/plasmapy/analysis/swept_langmuir/floating_potential.py +++ b/plasmapy/analysis/swept_langmuir/floating_potential.py @@ -61,7 +61,7 @@ def find_floating_potential( voltage: ~numpy.ndarray 1-D numpy array of monotonically ascending/descending probe biases - (in Volts) + (in volts) current: ~numpy.ndarray 1-D numpy array of probe current (in A) corresponding to the @@ -87,30 +87,51 @@ def find_floating_potential( ``min_points * array_size``. fit_type: str - The type of curve to be fitted to (``voltage``, ``current``). There - are two types of curves ``"linear"`` and ``"exponential"`` (Default). + The type of curve to be fitted to the Langmuir trace. There are two + types of curves ``"linear"`` and ``"exponential"`` (Default). These + specified which `FitFunction` class should be applied to the trace. + + +-------------+--------------------------------------------------------------------------------+ + | linear | `~plasmapy.analysis.swept_langmuir.fit_functions.LinearFitFunction` | + +-------------+--------------------------------------------------------------------------------+ + | exponential | `~plasmapy.analysis.swept_langmuir.fit_functions.ExponentialOffsetFitFunction` | + +-------------+--------------------------------------------------------------------------------+ Returns ------- vf: `float` or `numpy.nan` - The calculated floating potential (in Volts). Returns `numpy.nan` if the - floating potential can not be determined. + The calculated floating potential (in volts). Returns `numpy.nan` if the + floating potential can not be determined. How :math:`V_f` is calculated + depends on the fit function. This is described in the `root_solve()` + method of the relevant fit function (e.g. the + :meth:`~plasmapy.analysis.swept_langmuir.fit_functions.ExponentialOffsetFitFunction.root_solve` + method of + `~plasmapy.analysis.swept_langmuir.fit_functions.ExponentialOffsetFitFunction`). vf_err: `float` or `numpy.nan` - The error associated with the floating potential calculation (in Volts). + The error associated with the floating potential calculation (in volts). Returns `numpy.nan` if the floating potential can not be determined. - - info: Dict[str, Any] - A dictionary containing meta-info about the fit with keys... - - - ``"func"``: The fitted function which is either an instance of - `LinearFitFunction` or `ExponentialOffsetFitFunciton`. - - ``"indices"``: A `slice` object representing the indices of - ``voltage`` and ``current`` used for the fit. - - ``"islands"``: List of `slice` objects reprsenting the indices of the - identified crossing-islands. - - ``"rsq"``: The coefficient of determination (r-squared) vlaue of the - fit. + Like :math:`V_f`:, the calculation depends on the applied fit function. + The `rood_solve()` method also describes how this is calculated. + + rsq: `float` + The coefficient of determination (r-squared) value of the fit. See the + documentation of the `rsq` property on the associated fit function + (e.g. the + `~plasmapy.analysis.swept_langmuir.fit_functions.ExponentialOffsetFitFunction.rsq` + property of + `~plasmapy.analysis.swept_langmuir.fit_functions.ExponentialOffsetFitFunction`). + + func: sub-class of `~plasmapy.analysis.swept_langmuir.fit_functions.AbstractFitFunction` + The callable function :math:`f(x)` repressing the fit and its results. + + islands: `List[slice]` + List of `slice` objects representing the indices of the identified + crossing-islands. + + indices: `slice` + A `slice` object representing the indices of ``voltage`` and ``current`` + arrays used for the fit. """ rtn = FloatingPotentialResults( From 25a5f08dc7fcb7a340994eec889a1c739048c66e Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 10 Sep 2020 21:27:46 -0700 Subject: [PATCH 064/521] it appears nbconvert>=6.0.0 is causing build errors on RTD...this is to test that --- requirements/automated-documentation-tests.txt | 1 + setup.cfg | 1 + 2 files changed, 2 insertions(+) diff --git a/requirements/automated-documentation-tests.txt b/requirements/automated-documentation-tests.txt index d6ede1574e..c7e03b0906 100644 --- a/requirements/automated-documentation-tests.txt +++ b/requirements/automated-documentation-tests.txt @@ -12,3 +12,4 @@ sphinx-automodapi sphinx-copybutton sphinx-gallery sphinx_rtd_theme +nbconvert<6.0.0 \ No newline at end of file diff --git a/setup.cfg b/setup.cfg index 24cac1b013..f7f69c3168 100644 --- a/setup.cfg +++ b/setup.cfg @@ -59,6 +59,7 @@ docs = nbsphinx sphinx-copybutton ipywidgets + nbconvert<6.0.0 [options.package_data] plasmapy.particles.data = * From ce9b95490f82e1b77e840baca2dbf95159ed4d07 Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 11 Sep 2020 10:01:41 -0700 Subject: [PATCH 065/521] change color of plot element for Vf --- .../analysis/swept_langmuir/find_floating_potential.ipynb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb b/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb index 778116dd39..cb2fef442e 100644 --- a/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb +++ b/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb @@ -231,8 +231,8 @@ " axs[ii].fill_between([fit.vf - fit.vf_err, fit.vf + fit.vf_err], \n", " axs[1].get_ylim()[0],\n", " axs[1].get_ylim()[1],\n", - " color='orange', alpha=0.1)\n", - " axs[ii].axvline(fit.vf, color='orange')\n", + " color='grey', alpha=0.1)\n", + " axs[ii].axvline(fit.vf, color='grey')\n", " axs[ii].legend(fontsize=12)\n", "\n", " # add text\n", From 889cf8154d0d7f358354d459444f165a51281681 Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 11 Sep 2020 16:10:17 -0700 Subject: [PATCH 066/521] fix notebook misspellings --- .../swept_langmuir/find_floating_potential.ipynb | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb b/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb index cb2fef442e..9de8e0c5c2 100644 --- a/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb +++ b/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb @@ -42,7 +42,7 @@ " \n", "### Notes about usage\n", "\n", - "- The function provides no signal processng, so, if needed, the user must smooth, sort, crop, etc. the arrays before passing to the function.\n", + "- The function provides no signal processing, so, if needed, the user must smooth, sort, crop, etc. the arrays before passing to the function.\n", "- The function requires the voltage array to be monotonically increasing or decreasing.\n", "- If the total range spanned by all crossing-islands is less than or equal to `min_points`, then `threshold` is ignored and all crossing-islands are grouped into one island.\n", "\n", @@ -51,7 +51,7 @@ "\n", "- `fit_type`\n", "\n", - " There are two types of curves that can be fitted to the identified crossing point data, `\"linear\"` and `\"expoenetion\"`. The former will fit fit a line to the data, whereas, the later will fit and expoenetial curve with an offset. The default curve is `\"exponential\"` since swept Langmuir data is not typically linear as it passes through $I=0$.\n", + " There are two types of curves that can be fitted to the identified crossing point data, `\"linear\"` and `\"exponential\"`. The former will fit fit a line to the data, whereas, the later will fit and exponential curve with an offset. The default curve is `\"exponential\"` since swept Langmuir data is not typically linear as it passes through $I=0$.\n", "\n", "- `min_points`\n", "\n", @@ -69,7 +69,7 @@ "\n", "### Calculate the Floating Potential\n", "\n", - "Below we'll compute the floaing potential using the default fitting behavior (`fit_type=\"exponential\"`) and a linear fit." + "Below we'll compute the floaing potential using the default fitting behavior (`fit_type=\"exponential\"`) and a linear fit (`fit_type=\"linear\"`)." ] }, { @@ -102,7 +102,7 @@ "The `find_floating_potential()` returns a named tuple, where...\n", "\n", "- `results[0]` = `results.vf` = the determined floating potential (in volts)\n", - "- `results[1]` = `resutls.vf_err` = the associated error (in volts)\n", + "- `results[1]` = `results.vf_err` = the associated error (in volts)\n", "- `results[2]` = `results.rsq` = the coeficient of determination (r-squared) value of the fit\n", "- `results[3]` = `results.func` = the resulting fitted function\n", "\n", @@ -111,7 +111,7 @@ "\n", "\n", "- `results[4]` = `results.islands` = a list of slice objects representing all the indentified crossing-islands\n", - "- `results[5]` = `results.indices` = a slice objec representing the indices used in the fit" + "- `results[5]` = `results.indices` = a slice object representing the indices used in the fit" ] }, { @@ -134,7 +134,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Additional fit parameters can be accessed directly from `resulst.func`." + "Additional fit parameters can be accessed directly from `results.func`." ] }, { From f1b1e82056216531ff070c00d08843a48b91e9e9 Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 11 Sep 2020 16:52:09 -0700 Subject: [PATCH 067/521] add docstring to add_noise() --- .../langmuir_samples/_generate_noisy.ipynb | 37 ++++++++++++++++++- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/docs/notebooks/langmuir_samples/_generate_noisy.ipynb b/docs/notebooks/langmuir_samples/_generate_noisy.ipynb index 82a99e5cd2..11548f1691 100644 --- a/docs/notebooks/langmuir_samples/_generate_noisy.ipynb +++ b/docs/notebooks/langmuir_samples/_generate_noisy.ipynb @@ -11,7 +11,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -24,13 +24,46 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# noise generator\n", "@validate_quantities\n", "def add_noise(signal, snr_db: u.dB = 10 * u.dB):\n", + " \"\"\"\n", + " Add noise to a signal based on a signal-to-noise ratio (SNR).\n", + " \n", + " .. math::\n", + " \n", + " SNR &= \\\\frac{P_{signal}}{P_{noise}}\n", + " \n", + " SNR_{dB} &= 10 \\\\log_{10}(SNR)\n", + " \n", + " where :math:`P_{signal}` and :math:`P_{noise}` is the average power of\n", + " signal and noise components, respectively.\n", + " \n", + " The noise component is generated using `numpy.random.normal`.\n", + " \n", + " Parameters\n", + " ----------\n", + " signal: array_like\n", + " 1D array to add noise to\n", + " \n", + " snr_db: `~astropy.units.Quantity`\n", + " desired signal-to-noise ratio in decibels\n", + " \n", + " Returns\n", + " -------\n", + " array_like\n", + " the original signal with noise added to it\n", + " \n", + " Refernces\n", + " ---------\n", + " .. [1] https://en.wikipedia.org/wiki/Signal-to-noise_ratio\n", + " .. [2] https://stackoverflow.com/a/53688043\n", + "\n", + " \"\"\"\n", " sig_pwr = signal ** 2\n", " sig_pwr_ave = np.mean(sig_pwr)\n", " sig_pwr_ave_db = 10. * np.log10(sig_pwr_ave)\n", From 1a97c86a68d8884b2d61725e63ffa74ce473b491 Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 11 Sep 2020 16:53:03 -0700 Subject: [PATCH 068/521] update filename so ".npy" is not added twice when saving --- docs/notebooks/langmuir_samples/_generate_noisy.ipynb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/notebooks/langmuir_samples/_generate_noisy.ipynb b/docs/notebooks/langmuir_samples/_generate_noisy.ipynb index 11548f1691..445b32eb46 100644 --- a/docs/notebooks/langmuir_samples/_generate_noisy.ipynb +++ b/docs/notebooks/langmuir_samples/_generate_noisy.ipynb @@ -86,9 +86,9 @@ "# this can be found at \n", "# https://github.com/PlasmaPy/PlasmaPy/blob/master/docs/notebooks/langmuir_samples/Beckers2017.npy\n", "#\n", - "filename = \"Beckers2017.npy\"\n", + "filename = \"Beckers2017\"\n", "samples_path = os.path.join(os.path.abspath(\"./\"))\n", - "path = os.path.join(samples_path, filename)\n", + "path = os.path.join(samples_path, filename + \".npy\")\n", "voltage, current = np.load(path)\n", "\n", "# add some artificial noise to simulate reliztic digitized signals\n", From 074bf0cf8ae36d3a1b2c36176bbc21d581a5aa07 Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 11 Sep 2020 16:53:20 -0700 Subject: [PATCH 069/521] add plotting of noise vs original signals --- .../langmuir_samples/_generate_noisy.ipynb | 47 ++++++++++++++++--- 1 file changed, 41 insertions(+), 6 deletions(-) diff --git a/docs/notebooks/langmuir_samples/_generate_noisy.ipynb b/docs/notebooks/langmuir_samples/_generate_noisy.ipynb index 445b32eb46..a693a186f2 100644 --- a/docs/notebooks/langmuir_samples/_generate_noisy.ipynb +++ b/docs/notebooks/langmuir_samples/_generate_noisy.ipynb @@ -17,9 +17,12 @@ "source": [ "import astropy.units as u\n", "import numpy as np\n", + "import matplotlib.pyplot as plt\n", "import os\n", "\n", - "from plasmapy.utils.decorators import validate_quantities" + "from plasmapy.utils.decorators import validate_quantities\n", + "\n", + "plt.rcParams['figure.figsize'] = [10.5, 0.56 * 10.5]" ] }, { @@ -78,7 +81,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -92,13 +95,45 @@ "voltage, current = np.load(path)\n", "\n", "# add some artificial noise to simulate reliztic digitized signals\n", - "voltage = add_noise(voltage, 38 * u.dB)\n", - "current = add_noise(current, 28 * u.dB)" + "v_noisy = add_noise(voltage, 38 * u.dB)\n", + "i_noisy = add_noise(current, 28 * u.dB)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "figwidth, figheight = plt.rcParams[\"figure.figsize\"]\n", + "figheight = 2. * figheight\n", + "fig, axs = plt.subplots(3, 1, figsize=[figwidth, figheight])\n", + "\n", + "# Current plot\n", + "axs[0].set_ylabel(\"Current\", fontsize=12)\n", + "axs[0].set_xlabel(\"Index\", fontsize=12)\n", + "axs[0].plot(i_noisy, label=\"noisy\")\n", + "axs[0].plot(current, color='r', label=\"original\")\n", + "axs[0].legend(fontsize=12)\n", + "\n", + "# Voltage plot\n", + "axs[1].set_ylabel(\"Voltage\", fontsize=12)\n", + "axs[1].set_xlabel(\"Index\", fontsize=12)\n", + "axs[1].plot(v_noisy, label=\"noisy\")\n", + "axs[1].plot(voltage, color='r', label=\"original\")\n", + "axs[1].legend(fontsize=12)\n", + "\n", + "# IV plot\n", + "axs[2].set_ylabel(\"Current\", fontsize=12)\n", + "axs[2].set_xlabel(\"Voltage\", fontsize=12)\n", + "axs[2].plot(v_noisy, i_noisy, label=\"noisy\")\n", + "axs[2].plot(voltage, current, color='r', label=\"original\")\n", + "axs[2].legend(fontsize=12)" ] }, { "cell_type": "code", - "execution_count": 11, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -106,7 +141,7 @@ "if save:\n", " save_path = os.path.join(samples_path, filename + \"_noisy.npy\")\n", " with open(save_path, \"wb\") as fp:\n", - " np.save(fp, [voltage, current])" + " np.save(fp, [v_noisy, i_noisy])" ] } ], From f5ecdb3c4d9c2842a32e1093a72eb89a4d628595 Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 11 Sep 2020 17:44:44 -0700 Subject: [PATCH 070/521] repair definition of file names...I did not properly update when I moved it from it's previous notebook --- docs/notebooks/langmuir_samples/_generate_noisy.ipynb | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/docs/notebooks/langmuir_samples/_generate_noisy.ipynb b/docs/notebooks/langmuir_samples/_generate_noisy.ipynb index a693a186f2..513529b370 100644 --- a/docs/notebooks/langmuir_samples/_generate_noisy.ipynb +++ b/docs/notebooks/langmuir_samples/_generate_noisy.ipynb @@ -90,9 +90,8 @@ "# https://github.com/PlasmaPy/PlasmaPy/blob/master/docs/notebooks/langmuir_samples/Beckers2017.npy\n", "#\n", "filename = \"Beckers2017\"\n", - "samples_path = os.path.join(os.path.abspath(\"./\"))\n", - "path = os.path.join(samples_path, filename + \".npy\")\n", - "voltage, current = np.load(path)\n", + "voltage, current = np.load(filename + \".npy\")\n", + "\n", "\n", "# add some artificial noise to simulate reliztic digitized signals\n", "v_noisy = add_noise(voltage, 38 * u.dB)\n", @@ -139,8 +138,8 @@ "source": [ "save = False\n", "if save:\n", - " save_path = os.path.join(samples_path, filename + \"_noisy.npy\")\n", - " with open(save_path, \"wb\") as fp:\n", + " savefile = filename + \"_noisy.npy\"\n", + " with open(savefile, \"wb\") as fp:\n", " np.save(fp, [v_noisy, i_noisy])" ] } From e995cf42f3d265512470cca6a1890b0ca0659796 Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 11 Sep 2020 18:46:02 -0700 Subject: [PATCH 071/521] replace use of os.path with pathlib.Path --- .../swept_langmuir/find_floating_potential.ipynb | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb b/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb index 9de8e0c5c2..7a77e8399e 100644 --- a/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb +++ b/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb @@ -17,9 +17,10 @@ "\n", "import matplotlib.pyplot as plt\n", "import numpy as np\n", - "import os\n", "import pprint\n", "\n", + "from pathlib import Path\n", + "\n", "from plasmapy.analysis import swept_langmuir as sla\n", "\n", "plt.rcParams['figure.figsize'] = [10.5, 0.56 * 10.5]" @@ -79,9 +80,9 @@ "outputs": [], "source": [ "# load data\n", - "samples_path = os.path.join(os.path.abspath(\"../../\"), \"langmuir_samples\")\n", - "path = os.path.join(samples_path, \"Beckers2017_noisy.npy\")\n", - "voltage, current = np.load(path)\n", + "filename = \"Beckers2017_noisy.npy\"\n", + "filepath = (Path.cwd() / \"..\" / \"..\" / \"langmuir_samples\" / filename).resolve()\n", + "voltage, current = np.load(filepath)\n", "\n", "# voltage array needs to be monotonically increasing/decreasing\n", "isort = np.argsort(voltage)\n", From e17b15aaa8a2f57e0f8c891c1caf2ded87415d9c Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 11 Sep 2020 23:08:00 -0700 Subject: [PATCH 072/521] blend my wording and Nick's (I prefer "task" over "responsibility") --- docs/ad/index.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/ad/index.rst b/docs/ad/index.rst index 887f098eb5..7c6d26b59a 100644 --- a/docs/ad/index.rst +++ b/docs/ad/index.rst @@ -18,8 +18,8 @@ Think of the `plasmapy.analysis` as your toolbox. It has all the tools discrete Fourier Transform. Similarly, :func:`plasmapy.analysis.swept_langmuir.find_floating_potential` only finds the floating potential for a given Langmuir trace. It does not have smoothing. -It does not do any filtering. It does not do any signal conditioning. It has a -singular task to find the floating potential of a single Langmuir trace. +It does not do any filtering. It does not do any signal conditioning. Its +sole task is to find the floating potential of a single Langmuir trace. Diagnostics on the other-hand have a much broader scope and leverage the tools defined in `plasmapy.analysis` to give a more integrated user experience when From 1b65e8747653545b7d8df8321b8af41e40c9eaf0 Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 18 Sep 2020 14:51:53 -0700 Subject: [PATCH 073/521] remove nbconvert from dependencies --- requirements/automated-documentation-tests.txt | 1 - setup.cfg | 1 - 2 files changed, 2 deletions(-) diff --git a/requirements/automated-documentation-tests.txt b/requirements/automated-documentation-tests.txt index 8d264bacf2..01e1fe99b7 100644 --- a/requirements/automated-documentation-tests.txt +++ b/requirements/automated-documentation-tests.txt @@ -13,4 +13,3 @@ sphinx-automodapi sphinx-copybutton sphinx-gallery sphinx_rtd_theme -nbconvert<6.0.0 \ No newline at end of file diff --git a/setup.cfg b/setup.cfg index 13321d1bd7..6335c630f6 100644 --- a/setup.cfg +++ b/setup.cfg @@ -60,7 +60,6 @@ docs = nbsphinx sphinx-copybutton ipywidgets - nbconvert<6.0.0 [options.package_data] plasmapy.particles.data = * From 96f56985afd78daad746fb3f8fc9514cde8f6b1e Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 18 Sep 2020 21:34:08 -0700 Subject: [PATCH 074/521] add method _func_err for calculating error propagation of dependent variables --- .../analysis/swept_langmuir/fit_functions.py | 71 +++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/plasmapy/analysis/swept_langmuir/fit_functions.py b/plasmapy/analysis/swept_langmuir/fit_functions.py index 1851ff6c34..8b45eac70e 100644 --- a/plasmapy/analysis/swept_langmuir/fit_functions.py +++ b/plasmapy/analysis/swept_langmuir/fit_functions.py @@ -76,6 +76,24 @@ def _func(self, x, *args): """ raise NotImplementedError + def _func_err(self, x): + """ + Calculate dependent variable errors :math:`\\delta y` for dependent + variables :math:`y=f(x)`. + + Parameters + ---------- + x: array_like + Independent variables to be passed to the fit function. + + Returns + ------- + `numpy.ndarray`: + The calculated errors of the dependent variables of the independent + variables `x`. + """ + raise NotImplementedError + @property def curve_fit_results(self): """ @@ -271,6 +289,35 @@ def _func(self, x, a, b, c): """ return a * np.exp(b * x) + c + def _func_err(self, x): + """ + Calculate dependent variable errors :math:`\\delta y` for dependent + variables :math:`y=f(x)`. + + .. math:: + + (\\delta y)^2 = (e^{B \\,x} \\delta A)^2 + + (A \\, B \\, e^{B \\, x} \\delta B)^2 + + (\\delta C)^2 + + Parameters + ---------- + x: array_like + Independent variables to be passed to the fit function. + + Returns + ------- + `numpy.ndarray`: + The calculated errors of the dependent variables of the independent + variables `x`. + """ + a, b, c = self.parameters + a_err, b_err, c_err = self.parameters_err + a_term = (np.exp(b * x) * a_err) ** 2 + b_term = (a * b * np.exp(b * x) * b_err) ** 2 + c_term = c_err ** 2 + return np.sqrt(a_term + b_term + c_term) + @property def latex_str(self) -> str: return fr"A \, \exp(B \, x) + C" @@ -369,6 +416,30 @@ def _func(self, x, m, b): """ return m * x + b + def _func_err(self, x): + """ + Calculate dependent variable errors :math:`\\delta y` for dependent + variables :math:`y=f(x)`. + + .. math:: + + (\\delta y)^2 &= (x \\, \\delta m)^2 + (\\delta b)^2 + + Parameters + ---------- + x: array_like + Independent variables to be passed to the fit function. + + Returns + ------- + `numpy.ndarray`: + The calculated errors of the dependent variables of the independent + variables `x`. + """ + m_term = (self.parameters_err[0] * x) ** 2 + b_term = self.parameters_err[1] ** 2 + return np.sqrt(m_term + b_term) + @property def latex_str(self) -> str: return fr"m \, x + b" From 4414471e1ecb2d94cbb2ab8ba8f6c2d2f0b22b33 Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 18 Sep 2020 21:34:51 -0700 Subject: [PATCH 075/521] add equations for error propagation to class level docstring --- plasmapy/analysis/swept_langmuir/fit_functions.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/plasmapy/analysis/swept_langmuir/fit_functions.py b/plasmapy/analysis/swept_langmuir/fit_functions.py index 8b45eac70e..a35eb4156d 100644 --- a/plasmapy/analysis/swept_langmuir/fit_functions.py +++ b/plasmapy/analysis/swept_langmuir/fit_functions.py @@ -245,7 +245,12 @@ class ExponentialOffsetFitFunction(AbstractFitFunction): .. math:: - f(x) = A \\, \\exp(B \\, x) + C + y &= f(x) = A \\, \\exp(B \\, x) + C + + (\\delta y)^2 &= (e^{B \\,x} \\delta A)^2 + + (A \\, B \\, e^{B \\, x} \\delta B)^2 + + (\\delta C)^2 + where :math:`A`, :math:`B`, and :math:`C` are positive real constants and :math:`x` is the independent variable. @@ -373,7 +378,9 @@ class LinearFitFunction(AbstractFitFunction): .. math:: - f(x) = m \\, x + b + y &= f(x) = m \\, x + b + + (\\delta y)^2 &= (x \\, \\delta m)^2 + (\\delta b)^2 where :math:`m` and :math:`b` are positive real constants representing the slope and intercept, respectively, and :math:`x` is the independent From 9a53a25df0f6be389f6a43bb9696a7b0d7effbd0 Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 18 Sep 2020 21:35:50 -0700 Subject: [PATCH 076/521] add kwarg reterr to __call__ method to allow for calc of error propagation --- .../analysis/swept_langmuir/fit_functions.py | 29 +++++++++++++++---- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/plasmapy/analysis/swept_langmuir/fit_functions.py b/plasmapy/analysis/swept_langmuir/fit_functions.py index a35eb4156d..ac596da2f7 100644 --- a/plasmapy/analysis/swept_langmuir/fit_functions.py +++ b/plasmapy/analysis/swept_langmuir/fit_functions.py @@ -34,7 +34,7 @@ class AbstractFitFunction(ABC): def __init__(self): self._ParamTuple = namedtuple("_ParamTuple", self._parameter_names) - def __call__(self, x): + def __call__(self, x, reterr=False): """ Direct call of the fit function :math:`f(x)``. @@ -43,13 +43,32 @@ def __call__(self, x): x: array_like Dependent variables. + reterr: bool + (Default: `False`) If `True`, return an array of errors associated + with the calculated independent variables + Returns ------- - array_like - Corresponding independent variables of dependent variables - :math:`x`. + y: `numpy.ndarray` + Corresponding dependent variables :math:`y=f(x)` of the independent + variables :math:`x`. + + y_err: `numpy.ndarray` + Errors associated with the calculated dependent variables + :math:`\\delta y` """ - return self._func(x, *self.parameters) + if not isinstance(x, np.ndarray): + x = np.array(x) + y = self._func(x, *self.parameters) + if reterr: + try: + y_err = self._func_err(x) + except NotImplementedError: + y_err = np.tile(np.nan, x.shape) + + return y, y_err + + return y def __repr__(self): return f"{self.__str__()} {self.__class__}" From 9503d56f5034e2792c5419adb6df439b67bfd8aa Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 18 Sep 2020 21:36:50 -0700 Subject: [PATCH 077/521] in docstring array -> `numpy.ndarray` --- plasmapy/analysis/swept_langmuir/fit_functions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plasmapy/analysis/swept_langmuir/fit_functions.py b/plasmapy/analysis/swept_langmuir/fit_functions.py index ac596da2f7..43f00acfa1 100644 --- a/plasmapy/analysis/swept_langmuir/fit_functions.py +++ b/plasmapy/analysis/swept_langmuir/fit_functions.py @@ -90,7 +90,7 @@ def _func(self, x, *args): Returns ------- - array: + `numpy.ndarray`: The calculated dependent variables of the independent variables `x`. """ raise NotImplementedError From c91adadcfaf0fe083a8763f15a7ecf72f171ac6a Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 18 Sep 2020 21:38:05 -0700 Subject: [PATCH 078/521] update notebook; add TOC; create section for interpreting fit results; add plotting or dependent variable error --- .../find_floating_potential.ipynb | 172 ++++++++++++++---- 1 file changed, 132 insertions(+), 40 deletions(-) diff --git a/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb b/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb index 7a77e8399e..d5bce926cd 100644 --- a/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb +++ b/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb @@ -4,7 +4,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## Swept Langmuir Analysis: Floating Potential" + "# Swept Langmuir Analysis: Floating Potential" ] }, { @@ -30,24 +30,47 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### How does `find_floating_potential()` work?\n", + "## Contents:\n", "\n", - "1. The passed current array is scanned for points that equal zero and point-pairs that straddle $I = 0$. This forms an array of \"crossing-points.\"\n", + "1. [How does `find_floating_potential()` work?](#How-does-find_floating_potential()-work?)\n", + " 1. [Notes about usage](#Notes-about-usage)\n", + " 1. [Knobs to turn](#Knobs-to-turn)\n", + "1. [Calculate the Floating Potential](#Calculate-the-Floating-Potential)\n", + " 1. [Interpreting results](#Interpreting-results)\n", + " 1. [Plotting results](#Plotting-results)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## How does `find_floating_potential()` work?\n", + "\n", + "1. The passed current array is scanned for points that equal zero and point-pairs that straddle $I = 0$. This forms an collection of \"crossing-points.\"\n", "1. The crossing-points are then grouped into \"crossing-islands\" based on the `threshold` keyword.\n", - " - A new island is formed when a successive crossing-point is more (index) steps away from the previous corssing-point than defined by `threshold`.\n", + " - A new island is formed when a successive crossing-point is more (index) steps away from the previous corssing-point than defined by `threshold`. For example, if `threshld=4` then an new island is formed if a crossing-point candidate is more than 4 steps away from the previous candidate.\n", " - If multiple crossing-islands are identified, then the function will compare the total span of all crossing-islands to `min_points`. If the span is greater than `min_points`, then the function is incapable of identifying $V_f$ and will return `numpy.nan` values; otherwise, the span will form one larger crossing-island.\n", "1. To calculate the floating potential...\n", " - If the number of points that make up the crossing-island is less than `min_points`, then each side of the \"crossing-island\" is equally padded with the nearest neighbor points until `min_points` is satisfied.\n", " - If `fit_type=\"linear\"`, then a `scipy.stats.linregress` fit is applied to the points that make up the crossing-island.\n", - " - If `fit_type=\"exponential\"`, then a `scipy.optimize.curve_fit` fit is applied to the points that make up the crossing-island.\n", - " \n", + " - If `fit_type=\"exponential\"`, then a `scipy.optimize.curve_fit` fit is applied to the points that make up the crossing-island." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ "### Notes about usage\n", "\n", "- The function provides no signal processing, so, if needed, the user must smooth, sort, crop, etc. the arrays before passing to the function.\n", "- The function requires the voltage array to be monotonically increasing or decreasing.\n", - "- If the total range spanned by all crossing-islands is less than or equal to `min_points`, then `threshold` is ignored and all crossing-islands are grouped into one island.\n", - "\n", - "\n", + "- If the total range spanned by all crossing-islands is less than or equal to `min_points`, then `threshold` is ignored and all crossing-islands are grouped into one island." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ "### Knobs to turn\n", "\n", "- `fit_type`\n", @@ -66,9 +89,14 @@ "\n", "- `threshold`\n", "\n", - " The max allowed index distance between crossing-points before a new crossing-island is formed.\n", - "\n", - "### Calculate the Floating Potential\n", + " The max allowed index distance between crossing-points before a new crossing-island is formed." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Calculate the Floating Potential\n", "\n", "Below we'll compute the floaing potential using the default fitting behavior (`fit_type=\"exponential\"`) and a linear fit (`fit_type=\"linear\"`)." ] @@ -100,19 +128,89 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "The `find_floating_potential()` returns a named tuple, where...\n", + "### Interpreting results\n", "\n", - "- `results[0]` = `results.vf` = the determined floating potential (in volts)\n", - "- `results[1]` = `results.vf_err` = the associated error (in volts)\n", - "- `results[2]` = `results.rsq` = the coeficient of determination (r-squared) value of the fit\n", - "- `results[3]` = `results.func` = the resulting fitted function\n", - "\n", - " - Look to the [**FitFuction** classes](../../../api_static/plasmapy.analysis.swept_langmuir.fit_functions.rst) to see the features of `results.func`.\n", - " - For example, the documentaiton for the `root_solve()` method of your respective fit function (e.g. [**ExponentialOffsetFitFunction.root_solve()**](../../../api/plasmapy.analysis.swept_langmuir.fit_functions.ExponentialOffsetFitFunction.rst#plasmapy.analysis.swept_langmuir.fit_functions.ExponentialOffsetFitFunction.root_solve) ) will describe how the root (i.e. $V_F$) is calculated and its associated error propogation.\n", + "The `find_floating_potential()` returns a six element named tuple, where...\n", "\n", + "- `results[0]` = `results.vf` = the determined floating potential (in volts)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "(results[0], results.vf)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "- `results[1]` = `results.vf_err` = the associated error (in volts)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "(results[1], results.vf_err)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "- `results[2]` = `results.rsq` = the coeficient of determination (r-squared) value of the fit" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "(results[2], results.rsq)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "- `results[3]` = `results.func` = the resulting fitted function\n", "\n", - "- `results[4]` = `results.islands` = a list of slice objects representing all the indentified crossing-islands\n", - "- `results[5]` = `results.indices` = a slice object representing the indices used in the fit" + " - `results.func` is a callable representation of the fitted function `I = results.func(V)`.\n", + " - `resulst.func` is an instance of a sub-class of `AbstractFitFunction`. ([**FitFuction** classes](../../../api_static/plasmapy.analysis.swept_langmuir.fit_functions.rst))\n", + " - Since `results.func` is a class instance, there are many other attribures available. For example,\n", + " - `results.func.parameters` is a named tuple of the fitted parameters\n", + " - `results.func.parameters_err` is a named tuple of the fitted parameter errors\n", + " - `results.func.root_solve()` finds the roots of the fitted function. This is how $V_f$ is calculated." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "(results[3],\n", + " results.func,\n", + " results.func.parameters,\n", + " results.func.parameters.a,\n", + " results.func.parameters_err,\n", + " results.func.parameters_err.a,\n", + " results.func(results.vf),\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "- `results[4]` = `results.islands` = a list of slice objects representing all the indentified crossing-islands" ] }, { @@ -121,13 +219,9 @@ "metadata": {}, "outputs": [], "source": [ - "print(\n", - " f\"results[0] = results.vf = {results.vf:.3f} V\\n\"\n", - " f\"results[1] = results.vf_err = {results.vf_err:.3f} V\\n\"\n", - " f\"results[2] = results.rsq = {results.rsq:.3f}\\n\"\n", - " f\"results[3] = results.func = {results.func}\\n\"\n", - " f\"results[4] = results.islands = {results.islands}\\n\"\n", - " f\"results[5] = results.indices = {results.indices}\"\n", + "(results[4], \n", + " results.islands,\n", + " voltage[results.islands[0]],\n", ")" ] }, @@ -135,7 +229,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Additional fit parameters can be accessed directly from `results.func`." + "- `results[5]` = `results.indices` = a slice object representing the indices used in the fit" ] }, { @@ -144,14 +238,9 @@ "metadata": {}, "outputs": [], "source": [ - "print(\n", - " f\"Fitted parameters = results.func.parameters = \\n\"\n", - " f\" {results.func.parameters}\\n\"\n", - " f\"Fitted parameter errors = results.func.parameters_err = \\n\"\n", - " f\" {results.func.parameters_err}\\n\"\n", - " f\"\\n\"\n", - " f\"These are also namedtuples, so \"\n", - " f\"results.func.parameters.a = {results.func.parameters.a:.4f}.\\n\"\n", + "(results[5],\n", + " results.indices,\n", + " voltage[results.indices],\n", ")" ] }, @@ -159,7 +248,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### Plot the fits" + "### Plotting results" ] }, { @@ -203,7 +292,7 @@ " mask2 = np.where(voltage <= xlim[1], True, False)\n", " mask = np.logical_and(mask1, mask2)\n", " vfit = np.linspace(xlim[0], xlim[1], 201, endpoint=True)\n", - " ifit = fit.func(vfit)\n", + " ifit, ifit_err = fit.func(vfit, reterr=True)\n", "\n", " axs[ii].set_xlabel(\"Bias Voltage (V)\", fontsize=12)\n", " axs[ii].set_ylabel(\"Current (A)\", fontsize=12)\n", @@ -228,6 +317,9 @@ " axs[ii].plot(vfit, ifit, color=\"orange\",\n", " zorder=13,\n", " label=label + \" Fit\")\n", + " axs[ii].fill_between(vfit, ifit + ifit_err, ifit - ifit_err, \n", + " color=\"orange\", alpha=0.12, zorder=0,\n", + " label=\"Fit Error\")\n", " axs[ii].axhline(0.0, color='r', linestyle='--')\n", " axs[ii].fill_between([fit.vf - fit.vf_err, fit.vf + fit.vf_err], \n", " axs[1].get_ylim()[0],\n", From aa43cb79dd8929cfcac2671b89ae8ef4c2244641 Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 18 Sep 2020 22:03:25 -0700 Subject: [PATCH 079/521] replace syntax highlight with bold face --- .../analysis/swept_langmuir/find_floating_potential.ipynb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb b/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb index d5bce926cd..7b5dc1dde4 100644 --- a/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb +++ b/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb @@ -32,7 +32,7 @@ "source": [ "## Contents:\n", "\n", - "1. [How does `find_floating_potential()` work?](#How-does-find_floating_potential()-work?)\n", + "1. [How does **find_floating_potential()** work?](#How-does-find_floating_potential()-work?)\n", " 1. [Notes about usage](#Notes-about-usage)\n", " 1. [Knobs to turn](#Knobs-to-turn)\n", "1. [Calculate the Floating Potential](#Calculate-the-Floating-Potential)\n", From 2f7ab0f197b7419677f2328ff1ae84a16f3488c1 Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 21 Sep 2020 10:56:22 -0700 Subject: [PATCH 080/521] add `/notebooks_for_proto` in .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 878d978f65..4ce6c4d8a1 100644 --- a/.gitignore +++ b/.gitignore @@ -77,6 +77,7 @@ target/ # Jupyter Notebook .ipynb_checkpoints +notebooks_for_proto # pyenv .python-version From b0508916ae44825c6c6c77c39ac408aa176b1e69 Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 21 Sep 2020 10:58:52 -0700 Subject: [PATCH 081/521] add fit function class ExponentialLinearFitFunction --- .../analysis/swept_langmuir/fit_functions.py | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/plasmapy/analysis/swept_langmuir/fit_functions.py b/plasmapy/analysis/swept_langmuir/fit_functions.py index 43f00acfa1..ec218d49f8 100644 --- a/plasmapy/analysis/swept_langmuir/fit_functions.py +++ b/plasmapy/analysis/swept_langmuir/fit_functions.py @@ -4,6 +4,7 @@ """ __all__ = [ "AbstractFitFunction", + "ExponentialLinearFitFunction", "ExponentialOffsetFitFunction", "LinearFitFunction", ] @@ -257,6 +258,29 @@ def curve_fit(self, xdata, ydata, **kwargs) -> None: self._rsq = 1 - (ss_res / ss_tot) +class ExponentialLinearFitFunction(AbstractFitFunction): + _parameter_names = ("a", "alpha", "m", "b") + + def __str__(self): + return f"f(x) = A exp(alpha x) + m x + b" + + def _func(self, x, a, alpha, m, b): + return a * np.exp(alpha * x) + m * x + b + + def _func_err(self, x): + a, alpha, m, b = self.parameters + a_err, alpha_err, m_err, b_err = self.parameters_err + a_term = (np.exp(alpha * x) * a_err) ** 2 + alpha_term = (a * alpha * np.exp(b * x) * alpha_err) ** 2 + m_term = (x * m_err) ** 2 + b_term = b_err ** 2 + return np.sqrt(a_term + alpha_term + m_term + b_term) + + @property + def latex_str(self) -> str: + return fr"A \, \exp(\alpah \, x) + m \, x + b" + + class ExponentialOffsetFitFunction(AbstractFitFunction): """ A sub-class of `AbstractFitFunction` to represent an exponential with an From 19eb1e1c0fd881842f9539c2c442108279f9687c Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 21 Sep 2020 10:59:18 -0700 Subject: [PATCH 082/521] initial commit for find_ion_saturation_current --- plasmapy/analysis/swept_langmuir/__init__.py | 8 ++- .../swept_langmuir/ion_saturation_current.py | 66 +++++++++++++++++++ 2 files changed, 72 insertions(+), 2 deletions(-) create mode 100644 plasmapy/analysis/swept_langmuir/ion_saturation_current.py diff --git a/plasmapy/analysis/swept_langmuir/__init__.py b/plasmapy/analysis/swept_langmuir/__init__.py index 4c3817f25a..cff43935c2 100644 --- a/plasmapy/analysis/swept_langmuir/__init__.py +++ b/plasmapy/analysis/swept_langmuir/__init__.py @@ -1,6 +1,10 @@ """ Sub-Package containing routines for analyzing swept Langmuir probe traces. """ -__all__ = ["find_floating_potential"] +__all__ = [ + "find_floating_potential", + "find_ion_saturation_current", +] -from plasmapy.analysis.swept_langmuir.floating_potential import find_floating_potential +from .floating_potential import find_floating_potential +from .ion_saturation_current import find_ion_saturation_current diff --git a/plasmapy/analysis/swept_langmuir/ion_saturation_current.py b/plasmapy/analysis/swept_langmuir/ion_saturation_current.py new file mode 100644 index 0000000000..e76e007475 --- /dev/null +++ b/plasmapy/analysis/swept_langmuir/ion_saturation_current.py @@ -0,0 +1,66 @@ +""" +Functionality for determining the ion-saturation current of a Langmuir sweep. +""" +__all__ = ["find_ion_saturation_current"] + +import numpy as np + +from collections import namedtuple + +from plasmapy.analysis.swept_langmuir.fit_functions import ( + ExponentialLinearFitFunction, + LinearFitFunction, +) + + +IonSaturationCurrentResults = namedtuple( + "FloatingPotentialResults", + ("isat_func", "rsq", "func", "indices"), +) + + +def find_ion_saturation_current( + voltage: np.ndarray, + current: np.ndarray, + upper_bound=None, + fit_type: str = "explinear", +): + rtn = IonSaturationCurrentResults( + isat_func=None, + rsq=None, + func=None, + indices=None, + )._asdict() + + fit_funcs = { + "linear": LinearFitFunction(), + "explinear": ExponentialLinearFitFunction() + } + try: + fit_func = fit_funcs[fit_type] + rtn["func"] = fit_func + except KeyError: + raise KeyError( + f"Requested fit function '{fit_type}' is not a valid option, " + f"expecting on of '{list(fit_funcs)}'. Examine kwarg 'fit_curve' " + f"for valid options." + ) + + # mask = np.where(current <= 0)[0] + if upper_bound is None: + upper_bound = 0 + mask = np.where(voltage <= upper_bound)[0] + rtn["indices"] = mask + + volt_sub = voltage[mask] + curr_sub = current[mask] + fit_func.curve_fit(volt_sub, curr_sub) + + rtn["rsq"] = fit_func.rsq + + isat = LinearFitFunction() + isat._parameters = [fit_func.parameters.m, fit_func.parameters.b] + isat._parameters_err = [fit_func.parameters_err.m, fit_func.parameters_err.b] + rtn["isat_func"] = isat + + return IonSaturationCurrentResults(**rtn) From bf443bf6195609c1a8ab1e10a04e226f6bd3bab9 Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 21 Sep 2020 11:00:04 -0700 Subject: [PATCH 083/521] initial commit for the jupyter notebook for find_ion_saturation_current --- .../find_ion_saturation_current.ipynb | 517 ++++++++++++++++++ 1 file changed, 517 insertions(+) create mode 100644 docs/notebooks/analysis/swept_langmuir/find_ion_saturation_current.ipynb diff --git a/docs/notebooks/analysis/swept_langmuir/find_ion_saturation_current.ipynb b/docs/notebooks/analysis/swept_langmuir/find_ion_saturation_current.ipynb new file mode 100644 index 0000000000..e91bcf0385 --- /dev/null +++ b/docs/notebooks/analysis/swept_langmuir/find_ion_saturation_current.ipynb @@ -0,0 +1,517 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Swept Langmuir Analysis: Ion-Saturation Current" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "%matplotlib inline\n", + "\n", + "import matplotlib.pyplot as plt\n", + "import numpy as np\n", + "import pprint\n", + "\n", + "from pathlib import Path\n", + "\n", + "from plasmapy.analysis import swept_langmuir as sla\n", + "\n", + "plt.rcParams['figure.figsize'] = [10.5, 0.56 * 10.5]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Contents:\n", + "\n", + "1. [How does **find_floating_potential()** work?](#How-does-find_floating_potential()-work?)\n", + " 1. [Notes about usage](#Notes-about-usage)\n", + " 1. [Knobs to turn](#Knobs-to-turn)\n", + "1. [Calculate the Floating Potential](#Calculate-the-Floating-Potential)\n", + " 1. [Interpreting results](#Interpreting-results)\n", + " 1. [Plotting results](#Plotting-results)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## How does `find_floating_potential()` work?\n", + "\n", + "1. The passed current array is scanned for points that equal zero and point-pairs that straddle $I = 0$. This forms an collection of \"crossing-points.\"\n", + "1. The crossing-points are then grouped into \"crossing-islands\" based on the `threshold` keyword.\n", + " - A new island is formed when a successive crossing-point is more (index) steps away from the previous corssing-point than defined by `threshold`. For example, if `threshld=4` then an new island is formed if a crossing-point candidate is more than 4 steps away from the previous candidate.\n", + " - If multiple crossing-islands are identified, then the function will compare the total span of all crossing-islands to `min_points`. If the span is greater than `min_points`, then the function is incapable of identifying $V_f$ and will return `numpy.nan` values; otherwise, the span will form one larger crossing-island.\n", + "1. To calculate the floating potential...\n", + " - If the number of points that make up the crossing-island is less than `min_points`, then each side of the \"crossing-island\" is equally padded with the nearest neighbor points until `min_points` is satisfied.\n", + " - If `fit_type=\"linear\"`, then a `scipy.stats.linregress` fit is applied to the points that make up the crossing-island.\n", + " - If `fit_type=\"exponential\"`, then a `scipy.optimize.curve_fit` fit is applied to the points that make up the crossing-island." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Notes about usage\n", + "\n", + "- The function provides no signal processing, so, if needed, the user must smooth, sort, crop, etc. the arrays before passing to the function.\n", + "- The function requires the voltage array to be monotonically increasing or decreasing.\n", + "- If the total range spanned by all crossing-islands is less than or equal to `min_points`, then `threshold` is ignored and all crossing-islands are grouped into one island." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Knobs to turn\n", + "\n", + "- `fit_type`\n", + "\n", + " There are two types of curves that can be fitted to the identified crossing point data, `\"linear\"` and `\"exponential\"`. The former will fit fit a line to the data, whereas, the later will fit and exponential curve with an offset. The default curve is `\"exponential\"` since swept Langmuir data is not typically linear as it passes through $I=0$.\n", + "\n", + "- `min_points`\n", + "\n", + " This specifies the minimum number of points that will be used in the curve fitting. As mentioned above, the crossing-islands are identified and then padded until `min_points` is satisfied.\n", + " \n", + " - `min_pints = None` (Default) then the larger of 5 and `factor * array_size` is taken, where `factor = 0.1` for `\"linear\"` and `0.2` for `\"exponential\"`.\n", + " - `min_points = 0` then the entire passed array is fitted.\n", + " - `min_points >= 1` then this is the minimum number of points used.\n", + " - `0 < min_points < 1` then then the minimum number of points is taken as `min_points * array_size`.\n", + "\n", + "\n", + "- `threshold`\n", + "\n", + " The max allowed index distance between crossing-points before a new crossing-island is formed." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Calculate the Floating Potential\n", + "\n", + "Below we'll compute the floaing potential using the default fitting behavior (`fit_type=\"exponential\"`) and a linear fit (`fit_type=\"linear\"`)." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(FloatingPotentialResults(isat_func=f(x) = m x + b , rsq=0.9681862861882226, func=f(x) = A exp(alpha x) + m x + b , indices=array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,\n", + " 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,\n", + " 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,\n", + " 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,\n", + " 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,\n", + " 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77,\n", + " 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,\n", + " 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103,\n", + " 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116,\n", + " 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129,\n", + " 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142,\n", + " 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155,\n", + " 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168,\n", + " 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181,\n", + " 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194,\n", + " 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207,\n", + " 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220,\n", + " 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233,\n", + " 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246,\n", + " 247, 248, 249, 250, 251, 252])),\n", + " _ParamTuple(m=4.2927437446455325e-05, b=-0.001012862175227447),\n", + " _ParamTuple(a=0.010168587334992568, alpha=0.3708483981088679, m=4.2927437446455325e-05, b=-0.001012862175227447),\n", + " '-- break --',\n", + " FloatingPotentialResults(isat_func=f(x) = m x + b , rsq=0.3474805996698669, func=f(x) = m x + b , indices=array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,\n", + " 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,\n", + " 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,\n", + " 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,\n", + " 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,\n", + " 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77,\n", + " 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,\n", + " 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103,\n", + " 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116,\n", + " 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129,\n", + " 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142,\n", + " 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155,\n", + " 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168,\n", + " 169])),\n", + " _ParamTuple(m=4.737764372686474e-05, b=-0.000898585400126526),\n", + " _ParamTuple(m=4.737764372686474e-05, b=-0.000898585400126526))" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# load data\n", + "filename = \"Beckers2017_noisy.npy\"\n", + "filepath = (Path.cwd() / \"..\" / \"..\" / \"langmuir_samples\" / filename).resolve()\n", + "voltage, current = np.load(filepath)\n", + "\n", + "# voltage array needs to be monotonically increasing/decreasing\n", + "isort = np.argsort(voltage)\n", + "voltage = voltage[isort]\n", + "current = current[isort]\n", + "\n", + "# get default fit results (exponential fit)\n", + "# results = sla.find_floating_potential(voltage, current, min_points=0.3)\n", + "results_opt = sla.find_ion_saturation_current(voltage, current, fit_type=\"linear\", upper_bound=-10)\n", + "\n", + "# get linear fit results\n", + "# results_lin = sla.find_floating_potential(voltage, current, fit_type=\"linear\")\n", + "results = sla.find_ion_saturation_current(voltage, current)\n", + "(results,\n", + " results.isat_func.parameters,\n", + " results.func.parameters,\n", + " \"-- break --\",\n", + " results_opt,\n", + " results_opt.isat_func.parameters,\n", + " results_opt.func.parameters,\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Interpreting results\n", + "\n", + "The `find_floating_potential()` returns a six element named tuple, where...\n", + "\n", + "- `results[0]` = `results.vf` = the determined floating potential (in volts)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "# (results[0], results.vf)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "- `results[1]` = `results.vf_err` = the associated error (in volts)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "# (results[1], results.vf_err)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "- `results[2]` = `results.rsq` = the coeficient of determination (r-squared) value of the fit" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "# (results[2], results.rsq)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "- `results[3]` = `results.func` = the resulting fitted function\n", + "\n", + " - `results.func` is a callable representation of the fitted function `I = results.func(V)`.\n", + " - `resulst.func` is an instance of a sub-class of `AbstractFitFunction`. ([**FitFuction** classes](../../../api_static/plasmapy.analysis.swept_langmuir.fit_functions.rst))\n", + " - Since `results.func` is a class instance, there are many other attribures available. For example,\n", + " - `results.func.parameters` is a named tuple of the fitted parameters\n", + " - `results.func.parameters_err` is a named tuple of the fitted parameter errors\n", + " - `results.func.root_solve()` finds the roots of the fitted function. This is how $V_f$ is calculated." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "# (results[3],\n", + "# results.func,\n", + "# results.func.parameters,\n", + "# results.func.parameters.a,\n", + "# results.func.parameters_err,\n", + "# results.func.parameters_err.a,\n", + "# results.func(results.vf),\n", + "# )" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "- `results[4]` = `results.islands` = a list of slice objects representing all the indentified crossing-islands" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "# (results[4], \n", + "# results.islands,\n", + "# voltage[results.islands[0]],\n", + "# )" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "- `results[5]` = `results.indices` = a slice object representing the indices used in the fit" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [], + "source": [ + "# (results[5],\n", + "# results.indices,\n", + "# voltage[results.indices],\n", + "# )" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Plotting results" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(-0.001837668067056153, 0.0011231311264985006)" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "results.isat_func(5, reterr=True)" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": { + "nbsphinx-thumbnail": { + "tooltip": "Floating Potential" + } + }, + "outputs": [ + { + "data": { + "image/png": "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25eXXnqptbNkjDEpS5egslmoakRVhwK9gOEisleSdPeq6jBVHdalS5cmzcOU+UVMeuFzikrKUaCopJxJL3zeZIHlokWLADjjjDNwXZfs7GxGjhzJPvvsA0CfPn2YO3cuAI8//jgiwpdffgnA/fffz5gxYwDwPI+bbrqJ3XbbjYKCAsaNG8f69eur7jNr1iwOOeQQ8vPz2XfffZk5c2bVsREjRjBp0iSGDx9Ohw4dGD16dI1zkxERevXqxbXXXssvf/lL/vSnP1Udu/jii+nduzcdOnTggAMO4L333gPg9ddf54YbbuDpp58mLy+PfffdF4AHH3yQwYMH0/7/s3ff4VFWaePHv2dKksmkkoRAQgyEbnSligoKqy5NQVApuqC8trWvvqg/irDYfRFd29rdpSkCFgQVUZriokiXEgMREyCBQALpdWbO74+ZDCkzyaRBwPtzXXNl5jznOc95JgO559TgYBISEnj77bcb+pYKcca0bdsWi8UCgJ+fn0wmE0KcVVrKOpXpQFyl1+1caZ7yHFZKmYBQINuXc7XWOUqpdTjHXO5uigo/sWIPezPy6sy3/WAOZXZHlbTicjuPffwLi34+WOu558eE8I8RibXm6dKlC0ajkVtvvZXx48dzySWXEB4e7j4+cOBA1q9fT+/evfnuu+9ISEjg+++/JzExke+++46BAwcC8Nprr7Fs2TK+++47oqKiePDBB7nvvvtYtGgR6enpXHPNNSxYsIChQ4eyZs0abrjhBn799VcqgvD58+ezatUqOnTowC233MKDDz7IwoUL63x/Klx//fW88cYbFBYWYrVa6du3LzNnziQ0NJRXXnmFMWPGkJqaytChQ5k2bRopKSlVym/dujVffPGF+/6GDRtG37596dWrl891EKKlSEtL45tvvuHxxx9vkvJOnDjB7bffzjfffENkZCTPPfccN998s8e8EyZMYM2aNRQWFtKmTRsee+wx7rjjjhr59u/fz4UXXsiNN97o/rcYFBRUJU+tlPVLAAAgAElEQVRxcTH33nsvr732WpPchxCiZWspX4M3A52VUh2UUn44J94sr5ZnOXCr6/mNwFqttXalj3fNDu8AdAZ+VkpFKaXCAJRSFuAvwK+n4V6qqB5Q1pVeXyEhIfzwww8opbjzzjuJiopi5MiRZGZmAs6g8rvvvgNgw4YNTJ061f26clD51ltv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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "figwidth, figheight = plt.rcParams[\"figure.figsize\"]\n", + "figheight = 2. * figheight\n", + "fig, axs = plt.subplots(3, 1, figsize=[figwidth, figheight])\n", + "\n", + "# plot original data\n", + "axs[0].set_xlabel(\"Bias Voltage (V)\", fontsize=12)\n", + "axs[0].set_ylabel(\"Current (A)\", fontsize=12)\n", + "\n", + "axs[0].plot(voltage, current, zorder=10, label=\"Sweep Data\")\n", + "axs[0].axhline(0.0, color='r', linestyle='--', label=\"I = 0\")\n", + "axs[0].legend(fontsize=12)\n", + "\n", + "# zoom on fit\n", + "for ii, label, fit in zip([1, 2], [\"Exponential+Linear\", \"Linear\"], [results, results_opt]):\n", + " # calc island points\n", + "# isl_pts = np.array([], dtype=np.int64)\n", + "# for isl in fit.islands:\n", + "# isl_pts = np.concatenate((isl_pts, np.r_[isl]))\n", + " \n", + " # calc xrange for plot\n", + " xlim = [voltage[fit.indices].min(),\n", + " voltage[fit.indices].max()]\n", + " vpad = 0.25 * (xlim[1] - xlim[0])\n", + " xlim = [xlim[0] - 0.1 * vpad,\n", + " xlim[1] + vpad]\n", + " \n", + " # calc yrange for plot\n", + " umask = np.where(voltage >= xlim[0], True, False)\n", + " lmask = np.where(voltage <= xlim[1], True, False)\n", + " mask = np.logical_and(umask, lmask)\n", + " ylim = [current[mask].min(), current[mask].max()]\n", + " ypad = 0.15 * (ylim[1] - ylim[0])\n", + " factor = 7 if label == \"Linear\" else 1\n", + " ylim = [ylim[0] - ypad, ylim[1] + factor * ypad]\n", + "\n", + " # calc data points for fit curve\n", + " vfit = np.linspace(xlim[0], xlim[1], 201, endpoint=True)\n", + " ifit, ifit_err = fit.func(vfit, reterr=True)\n", + " \n", + " # calc isat line\n", + " isat, isat_err = fit.isat_func(vfit, reterr=True)\n", + "\n", + " axs[ii].set_xlabel(\"Bias Voltage (V)\", fontsize=12)\n", + " axs[ii].set_ylabel(\"Current (A)\", fontsize=12)\n", + " axs[ii].set_xlim(xlim)\n", + " axs[ii].set_ylim(ylim)\n", + "\n", + " zorder = 10\n", + " axs[ii].plot(voltage[mask], current[mask],\n", + " marker=\"o\", \n", + " zorder=zorder, \n", + " label=\"Sweep Data\")\n", + " zorder += 1\n", + " axs[ii].scatter(voltage[fit.indices],\n", + " current[fit.indices],\n", + " linewidth=2, s=6**2, \n", + " facecolors=\"deepskyblue\", edgecolors=\"deepskyblue\",\n", + " zorder=zorder,\n", + " label=\"Points for Fit\")\n", + "# axs[ii].scatter(voltage[isl_pts], current[isl_pts],\n", + "# linewidth=2, s=8**2, \n", + "# facecolors=\"deepskyblue\", edgecolors=\"black\",\n", + "# zorder=12,\n", + "# label=\"Island Points\")\n", + " axs[ii].autoscale(False)\n", + " zorder += 1\n", + " axs[ii].plot(vfit, ifit, color=\"orange\",\n", + " zorder=zorder,\n", + " label=label + \" Fit\")\n", + " axs[ii].fill_between(vfit, ifit + ifit_err, ifit - ifit_err,\n", + " color=\"orange\", alpha=0.12, zorder=0,\n", + " label=\"Fit Error\")\n", + " axs[ii].axhline(0.0, color='r', linestyle='--')\n", + " zorder += 1\n", + " axs[ii].plot(vfit, isat, color=\"black\",\n", + " label=\"Isat\", zorder=zorder)\n", + " axs[ii].fill_between(vfit, isat + isat_err, isat - isat_err,\n", + " color=\"black\", alpha=0.12, zorder=0,\n", + " label=\"Isat Error\")\n", + "# axs[ii].fill_between([fit.vf - fit.vf_err, fit.vf + fit.vf_err], \n", + "# axs[1].get_ylim()[0],\n", + "# axs[1].get_ylim()[1],\n", + "# color='grey', alpha=0.1)\n", + " axs[ii].legend(fontsize=12)\n", + "\n", + " # add text\n", + " rsq = fit.rsq\n", + " txt = f\"$r^2 = {rsq:.3f}$\"\n", + "# txt = (f\"$V_f = {fit.vf:.2f} \\\\pm {fit.vf_err:.2f}$ V\\n\"\n", + "# f\"$r^2 = {rsq:.3f}$\")\n", + " txt_loc = [-18, axs[ii].get_ylim()[1]]\n", + " txt_loc = axs[ii].transAxes.inverted().transform(axs[ii].transData.transform(txt_loc))\n", + " txt_loc[0] -= 0.02\n", + " txt_loc[1] -= 0.13\n", + " axs[ii].text(txt_loc[0], txt_loc[1], txt, \n", + " fontsize='large', transform=axs[ii].transAxes,\n", + " ha=\"left\")" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[]" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plt.plot(vfit, isat)\n", + "plt.plot(vfit, ifit, color=\"orange\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.6" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} From f0a1af4a1b9257adec5c11bec05611a763f7c49f Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 21 Sep 2020 12:12:12 -0700 Subject: [PATCH 084/521] remove cell outputs --- .../find_ion_saturation_current.ipynb | 144 ++---------------- 1 file changed, 11 insertions(+), 133 deletions(-) diff --git a/docs/notebooks/analysis/swept_langmuir/find_ion_saturation_current.ipynb b/docs/notebooks/analysis/swept_langmuir/find_ion_saturation_current.ipynb index e91bcf0385..855fd12952 100644 --- a/docs/notebooks/analysis/swept_langmuir/find_ion_saturation_current.ipynb +++ b/docs/notebooks/analysis/swept_langmuir/find_ion_saturation_current.ipynb @@ -9,7 +9,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -103,58 +103,9 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "(FloatingPotentialResults(isat_func=f(x) = m x + b , rsq=0.9681862861882226, func=f(x) = A exp(alpha x) + m x + b , indices=array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,\n", - " 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,\n", - " 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,\n", - " 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,\n", - " 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,\n", - " 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77,\n", - " 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,\n", - " 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103,\n", - " 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116,\n", - " 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129,\n", - " 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142,\n", - " 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155,\n", - " 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168,\n", - " 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181,\n", - " 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194,\n", - " 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207,\n", - " 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220,\n", - " 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233,\n", - " 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246,\n", - " 247, 248, 249, 250, 251, 252])),\n", - " _ParamTuple(m=4.2927437446455325e-05, b=-0.001012862175227447),\n", - " _ParamTuple(a=0.010168587334992568, alpha=0.3708483981088679, m=4.2927437446455325e-05, b=-0.001012862175227447),\n", - " '-- break --',\n", - " FloatingPotentialResults(isat_func=f(x) = m x + b , rsq=0.3474805996698669, func=f(x) = m x + b , indices=array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,\n", - " 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,\n", - " 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,\n", - " 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,\n", - " 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,\n", - " 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77,\n", - " 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,\n", - " 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103,\n", - " 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116,\n", - " 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129,\n", - " 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142,\n", - " 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155,\n", - " 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168,\n", - " 169])),\n", - " _ParamTuple(m=4.737764372686474e-05, b=-0.000898585400126526),\n", - " _ParamTuple(m=4.737764372686474e-05, b=-0.000898585400126526))" - ] - }, - "execution_count": 7, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "# load data\n", "filename = \"Beckers2017_noisy.npy\"\n", @@ -196,7 +147,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -212,7 +163,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -228,7 +179,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -251,7 +202,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -274,7 +225,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -293,7 +244,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -312,46 +263,13 @@ }, { "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "(-0.001837668067056153, 0.0011231311264985006)" - ] - }, - "execution_count": 9, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "results.isat_func(5, reterr=True)" - ] - }, - { - "cell_type": "code", - "execution_count": 25, + "execution_count": null, "metadata": { "nbsphinx-thumbnail": { "tooltip": "Floating Potential" } }, - "outputs": [ - { - "data": { - "image/png": "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25eXXnqptbNkjDEpS5egslmoakRVhwK9gOEisleSdPeq6jBVHdalS5cmzcOU+UVMeuFzikrKUaCopJxJL3zeZIHlokWLADjjjDNwXZfs7GxGjhzJPvvsA0CfPn2YO3cuAI8//jgiwpdffgnA/fffz5gxYwDwPI+bbrqJ3XbbjYKCAsaNG8f69eur7jNr1iwOOeQQ8vPz2XfffZk5c2bVsREjRjBp0iSGDx9Ohw4dGD16dI1zkxERevXqxbXXXssvf/lL/vSnP1Udu/jii+nduzcdOnTggAMO4L333gPg9ddf54YbbuDpp58mLy+PfffdF4AHH3yQwYMH0/7/s3ff4VFWaePHv2dKksmkkoRAQgyEbnSligoKqy5NQVApuqC8trWvvqg/irDYfRFd29rdpSkCFgQVUZriokiXEgMREyCBQALpdWbO74+ZDCkzyaRBwPtzXXNl5jznOc95JgO559TgYBISEnj77bcb+pYKcca0bdsWi8UCgJ+fn0wmE0KcVVrKOpXpQFyl1+1caZ7yHFZKmYBQINuXc7XWOUqpdTjHXO5uigo/sWIPezPy6sy3/WAOZXZHlbTicjuPffwLi34+WOu558eE8I8RibXm6dKlC0ajkVtvvZXx48dzySWXEB4e7j4+cOBA1q9fT+/evfnuu+9ISEjg+++/JzExke+++46BAwcC8Nprr7Fs2TK+++47oqKiePDBB7nvvvtYtGgR6enpXHPNNSxYsIChQ4eyZs0abrjhBn799VcqgvD58+ezatUqOnTowC233MKDDz7IwoUL63x/Klx//fW88cYbFBYWYrVa6du3LzNnziQ0NJRXXnmFMWPGkJqaytChQ5k2bRopKSlVym/dujVffPGF+/6GDRtG37596dWrl891EKKlSEtL45tvvuHxxx9vkvJOnDjB7bffzjfffENkZCTPPfccN998s8e8EyZMYM2aNRQWFtKmTRsee+wx7rjjjhr59u/fz4UXXsiNN97o/rcYFBRUJU+tlPVLAAAgAElEQVRxcTH33nsvr732WpPchxCiZWspX4M3A52VUh2UUn44J94sr5ZnOXCr6/mNwFqttXalj3fNDu8AdAZ+VkpFKaXCAJRSFuAvwK+n4V6qqB5Q1pVeXyEhIfzwww8opbjzzjuJiopi5MiRZGZmAs6g8rvvvgNgw4YNTJ061f26clD51ltv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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "figwidth, figheight = plt.rcParams[\"figure.figsize\"]\n", "figheight = 2. * figheight\n", @@ -451,46 +369,6 @@ " fontsize='large', transform=axs[ii].transAxes,\n", " ha=\"left\")" ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[]" - ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "plt.plot(vfit, isat)\n", - "plt.plot(vfit, ifit, color=\"orange\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] } ], "metadata": { From d3bc503da98f73de2d6e8e75f4df7965fec56d01 Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 21 Sep 2020 10:56:22 -0700 Subject: [PATCH 085/521] add `/notebooks_for_proto` in .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 878d978f65..4ce6c4d8a1 100644 --- a/.gitignore +++ b/.gitignore @@ -77,6 +77,7 @@ target/ # Jupyter Notebook .ipynb_checkpoints +notebooks_for_proto # pyenv .python-version From 12d2d5f274a75aafbec29a789dc0daa89ce619cb Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 21 Sep 2020 17:13:07 -0700 Subject: [PATCH 086/521] rename attr _ParamTuple -> FitParamTuple; update attrs parameters and parameter_errors accordingly; add setters for parameters and parameter_errors --- .../analysis/swept_langmuir/fit_functions.py | 40 ++++++++++++++++--- 1 file changed, 35 insertions(+), 5 deletions(-) diff --git a/plasmapy/analysis/swept_langmuir/fit_functions.py b/plasmapy/analysis/swept_langmuir/fit_functions.py index 43f00acfa1..6ccc114a19 100644 --- a/plasmapy/analysis/swept_langmuir/fit_functions.py +++ b/plasmapy/analysis/swept_langmuir/fit_functions.py @@ -32,7 +32,12 @@ class AbstractFitFunction(ABC): _curve_fit_results = None def __init__(self): - self._ParamTuple = namedtuple("_ParamTuple", self._parameter_names) + self.FitParamTuple = namedtuple("FitParamTuple", self._parameter_names) + """ + A named tuple class used for attributes :attr:`parameters` and + :attr:`parameters_err`. The attribute :attr:`parameter_names` defines + the tuple field names. + """ def __call__(self, x, reterr=False): """ @@ -123,20 +128,45 @@ def curve_fit_results(self): return self._curve_fit_results @property - def parameters(self) -> Union[None, NamedTuple]: + def parameters(self) -> Union[None, tuple]: """The fitted parameters for the fit function.""" if self._parameters is None: return self._parameters else: - return self._ParamTuple(*self._parameters) + return self.FitParamTuple(*self._parameters) + + @parameters.setter + def parameters(self, val) -> None: + if isinstance(val, self.FitParamTuple): + self._parameters = tuple(val) + elif isinstance(val, (tuple, list)) and len(val) == len(self.parameter_names): + self._parameters = tuple(val) + else: + raise ValueError(f"Got type {type(val)} for 'val', expecting tuple of " + f"length {len(self.parameter_names)}.") @property - def parameters_err(self) -> Union[None, NamedTuple]: + def parameters_err(self) -> Union[None, tuple]: """The associated errors of the fit `parameters`.""" if self._parameters_err is None: return self._parameters_err else: - return self._ParamTuple(*self._parameters_err) + return self.FitParamTuple(*self._parameters_err) + + @parameters_err.setter + def parameters_err(self, val) -> None: + if isinstance(val, self.FitParamTuple): + self._parameters_err = tuple(val) + elif isinstance(val, (tuple, list)) and len(val) == len(self.parameter_names): + self._parameters_err = tuple(val) + else: + raise ValueError(f"Got type {type(val)} for 'val', expecting tuple of " + f"length {len(self.parameter_names)}.") + + @property + def parameter_names(self) -> Tuple[str, ...]: + """Names of the fitted parameters.""" + return self._parameter_names @property @abstractmethod From 0d1d03e4833816687b0d3fe00c17b8a26ebdf7c2 Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 21 Sep 2020 17:13:42 -0700 Subject: [PATCH 087/521] remove import of NamedTuple --- plasmapy/analysis/swept_langmuir/fit_functions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plasmapy/analysis/swept_langmuir/fit_functions.py b/plasmapy/analysis/swept_langmuir/fit_functions.py index 6ccc114a19..a38b8ab8f6 100644 --- a/plasmapy/analysis/swept_langmuir/fit_functions.py +++ b/plasmapy/analysis/swept_langmuir/fit_functions.py @@ -14,7 +14,7 @@ from collections import namedtuple from scipy.stats import linregress from scipy.optimize import curve_fit, fsolve -from typing import Any, NamedTuple, Tuple, Union +from typing import Any, Tuple, Union class AbstractFitFunction(ABC): From 05a936bb432e4632b42cf35fa0a536a2a5448fcd Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 21 Sep 2020 17:15:36 -0700 Subject: [PATCH 088/521] add @abstractmethod to _func_err; add to _func_err signature arg y and kwarg x_err --- plasmapy/analysis/swept_langmuir/fit_functions.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/plasmapy/analysis/swept_langmuir/fit_functions.py b/plasmapy/analysis/swept_langmuir/fit_functions.py index a38b8ab8f6..5270b36b56 100644 --- a/plasmapy/analysis/swept_langmuir/fit_functions.py +++ b/plasmapy/analysis/swept_langmuir/fit_functions.py @@ -100,7 +100,8 @@ def _func(self, x, *args): """ raise NotImplementedError - def _func_err(self, x): + @abstractmethod + def _func_err(self, x, y, x_err=None): """ Calculate dependent variable errors :math:`\\delta y` for dependent variables :math:`y=f(x)`. @@ -110,6 +111,13 @@ def _func_err(self, x): x: array_like Independent variables to be passed to the fit function. + y: array_like + Dependent variables associated with :math:`x`, :math:`f(x)`. + + x_err: array_like, optional + Errors associated with the independent variables `x`. Must be of + size one or equal to the size of `x`. + Returns ------- `numpy.ndarray`: @@ -343,7 +351,7 @@ def _func(self, x, a, b, c): """ return a * np.exp(b * x) + c - def _func_err(self, x): + def _func_err(self, x, y, x_err=None): """ Calculate dependent variable errors :math:`\\delta y` for dependent variables :math:`y=f(x)`. @@ -472,7 +480,7 @@ def _func(self, x, m, b): """ return m * x + b - def _func_err(self, x): + def _func_err(self, x, y, x_err=None): """ Calculate dependent variable errors :math:`\\delta y` for dependent variables :math:`y=f(x)`. From 549194dd6aca10076ac900a75b03219e96064666 Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 21 Sep 2020 17:16:55 -0700 Subject: [PATCH 089/521] add to the AbstractFitFunction.__call__ the x_err kwarg so dependent variable errors can be included in the error propagation calculation --- plasmapy/analysis/swept_langmuir/fit_functions.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/plasmapy/analysis/swept_langmuir/fit_functions.py b/plasmapy/analysis/swept_langmuir/fit_functions.py index 5270b36b56..b314091507 100644 --- a/plasmapy/analysis/swept_langmuir/fit_functions.py +++ b/plasmapy/analysis/swept_langmuir/fit_functions.py @@ -39,7 +39,7 @@ def __init__(self): the tuple field names. """ - def __call__(self, x, reterr=False): + def __call__(self, x, x_err=None, reterr=False): """ Direct call of the fit function :math:`f(x)``. @@ -48,7 +48,11 @@ def __call__(self, x, reterr=False): x: array_like Dependent variables. - reterr: bool + x_err: array_like, optional + Errors associated with the independent variables `x`. Must be of + size one or equal to the size of `x`. + + reterr: bool, optional (Default: `False`) If `True`, return an array of errors associated with the calculated independent variables @@ -64,10 +68,12 @@ def __call__(self, x, reterr=False): """ if not isinstance(x, np.ndarray): x = np.array(x) + y = self._func(x, *self.parameters) + if reterr: try: - y_err = self._func_err(x) + y_err = self._func_err(x, y, x_err=x_err) except NotImplementedError: y_err = np.tile(np.nan, x.shape) From a27b186688725f76e74a1fee863806af55eed068 Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 21 Sep 2020 17:18:07 -0700 Subject: [PATCH 090/521] update AbstractFitFunction.root_save() return pattern (val, val) so it is consistent with its sub-classes --- .../analysis/swept_langmuir/fit_functions.py | 46 ++++++++----------- 1 file changed, 20 insertions(+), 26 deletions(-) diff --git a/plasmapy/analysis/swept_langmuir/fit_functions.py b/plasmapy/analysis/swept_langmuir/fit_functions.py index b314091507..793b03776a 100644 --- a/plasmapy/analysis/swept_langmuir/fit_functions.py +++ b/plasmapy/analysis/swept_langmuir/fit_functions.py @@ -190,7 +190,8 @@ def latex_str(self) -> str: def root_solve(self, x0, **kwargs): """ - Solve for the root of the fit function (i.e. :math:`f(x_r) = 0`). + Solve for the root of the fit function (i.e. :math:`f(x_r) = 0`). This + mehtod used `scipy.optimize.fsolve` to find the function roots. Parameters ---------- @@ -205,33 +206,26 @@ def root_solve(self, x0, **kwargs): x : `~numpy.ndarray` The solution (or the result of the last iteration for an unsuccessful call). - infodict : `dict` - A dictionary of optional outputs with the keys: - - ``nfev`` - number of function calls - ``njev`` - number of Jacobian calls - ``fvec`` - function evaluated at the output - ``fjac`` - the orthogonal matrix, q, produced by the QR - factorization of the final approximate Jacobian - matrix, stored column wise - ``r`` - upper triangular matrix produced by QR factorization - of the same matrix - ``qtf`` - the vector ``(transpose(q) * fvec)`` - - ier : `int` - An integer flag. Set to 1 if a solution was found, otherwise refer - to `mesg` for more information. - mesg : `str` - If no solution is found, `mesg` details the cause of failure. + + x_err: `~numpy.ndarray` + The error associated with the root calculation. **Currently this + returns an array of** `numpy.nan` **values equal in shape to** + `x` **, since there is no determined way to calculate the errors.** + + Notes + ----- + If the full output of `scipy.optimize.fsolve` is desired then one can do + + >>> func = FitFunction() # FitFunciton is a subclass of AbstractFitFunction + >>> roots = scipy.optimize.fsolve(func, 0.) + """ kwargs["args"] = self.parameters - return fsolve(self._func, x0, **kwargs) + results = fsolve(self._func, x0, **kwargs) + if isinstance(results, tuple): + results = results[0] + + return results, np.tile(np.nan, results.shape) @property def rsq(self): From 21f26fbbf178cf49d9c658b21d7426c2ddea2fad Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 21 Sep 2020 17:18:50 -0700 Subject: [PATCH 091/521] rename LinearFitFunction -> Linear --- plasmapy/analysis/swept_langmuir/fit_functions.py | 4 ++-- .../analysis/swept_langmuir/floating_potential.py | 11 ++++------- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/plasmapy/analysis/swept_langmuir/fit_functions.py b/plasmapy/analysis/swept_langmuir/fit_functions.py index 793b03776a..feb2038b00 100644 --- a/plasmapy/analysis/swept_langmuir/fit_functions.py +++ b/plasmapy/analysis/swept_langmuir/fit_functions.py @@ -5,7 +5,7 @@ __all__ = [ "AbstractFitFunction", "ExponentialOffsetFitFunction", - "LinearFitFunction", + "Linear", ] import numpy as np @@ -429,7 +429,7 @@ def root_solve(self, *args, **kwargs): return root, err -class LinearFitFunction(AbstractFitFunction): +class Linear(AbstractFitFunction): """ A sub-class of `AbstractFitFunction` to represent a linear function. diff --git a/plasmapy/analysis/swept_langmuir/floating_potential.py b/plasmapy/analysis/swept_langmuir/floating_potential.py index b525134975..a6593f2a1b 100644 --- a/plasmapy/analysis/swept_langmuir/floating_potential.py +++ b/plasmapy/analysis/swept_langmuir/floating_potential.py @@ -7,10 +7,7 @@ from warnings import warn from typing import Union -from plasmapy.analysis.swept_langmuir.fit_functions import ( - ExponentialOffsetFitFunction, - LinearFitFunction, -) +from plasmapy.analysis.swept_langmuir import fit_functions as ffuncs FloatingPotentialResults = namedtuple( "FloatingPotentialResults", @@ -92,7 +89,7 @@ def find_floating_potential( specified which `FitFunction` class should be applied to the trace. +-------------+--------------------------------------------------------------------------------+ - | linear | `~plasmapy.analysis.swept_langmuir.fit_functions.LinearFitFunction` | + | linear | `~plasmapy.analysis.swept_langmuir.fit_functions.Linear` | +-------------+--------------------------------------------------------------------------------+ | exponential | `~plasmapy.analysis.swept_langmuir.fit_functions.ExponentialOffsetFitFunction` | +-------------+--------------------------------------------------------------------------------+ @@ -145,11 +142,11 @@ def find_floating_potential( fit_funcs = { "linear": { - "func": LinearFitFunction(), + "func": ffuncs.Linear(), "min_point_factor": 0.1, }, "exponential": { - "func": ExponentialOffsetFitFunction(), + "func": ffuncs.ExponentialOffsetFitFunction(), "min_point_factor": 0.2, }, } From 468aefb5f54a3d02bd94d48c4faa94c07b87685c Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 21 Sep 2020 17:19:33 -0700 Subject: [PATCH 092/521] add fit function Exponential --- .../analysis/swept_langmuir/fit_functions.py | 78 +++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/plasmapy/analysis/swept_langmuir/fit_functions.py b/plasmapy/analysis/swept_langmuir/fit_functions.py index feb2038b00..3c4a41431d 100644 --- a/plasmapy/analysis/swept_langmuir/fit_functions.py +++ b/plasmapy/analysis/swept_langmuir/fit_functions.py @@ -4,6 +4,7 @@ """ __all__ = [ "AbstractFitFunction", + "Exponential", "ExponentialOffsetFitFunction", "Linear", ] @@ -295,6 +296,83 @@ def curve_fit(self, xdata, ydata, **kwargs) -> None: self._rsq = 1 - (ss_res / ss_tot) +class Exponential(AbstractFitFunction): + """ + A sub-class of `AbstractFitFunction` to represent an exponential with an + offset. + + .. math:: + + y &= f(x) = A \\, e^{\\alpha \\, x} + + \\left( \\frac{\\delta y}{|y|} \\right)^2 &= + \\left( \\frac{\\delta A}{A} \\right)^2 + + (x \\, \\delta \\alpha)^2 + + (\\alpha \\, \\delta x)^2 + + where :math:`A` and :math:`\\alpha` are the real constants to be fitted and + :math:`x` is the independent variable. :math:`\\delta A`, + :math:`\\delta \\alpha`, and :math:`\\delta x` are the respective errors for + :math:`A`, :math:`\\alpha`, and :math:`x`. + + """ + _parameter_names = ("a", "alpha") + + def __str__(self): + return f"f(x) = A exp(alpha x)" + + def _func(self, x, a, alpha): + return a * np.exp(alpha * x) + + def _func_err(self, x, y, x_err=None): + a, alpha = self.parameters + a_err, alpha_err = self.parameters_err + + a_term = (a_err / a) ** 2 + alpha_term = (x * alpha_err) ** 2 + + err = a_term + alpha_term + + if x_err is not None: + x_term = (alpha * x_err) ** 2 + err += x_term + + err = np.abs(y) * np.sqrt(err) + + return err + + @property + def latex_str(self) -> str: + return fr"A \, \exp(\alpha \, x)" + + def root_solve(self, *args, **kwargs): + """ + The root :math:`f(x_r) = 0` for the fit function. **An exponential has no + real roots.** + + Parameters + ---------- + *args + Not needed. This is to ensure signature comparability with + `AbstractFitFunction`. + + *kwargs + Not needed. This is to ensure signature comparability with + `AbstractFitFunction`. + + Returns + ------- + root: float + The root value for the given fit :attr:`parameters`. + + err: float + The error in the calculated root for the given fit + :attr:`parameters` and :attr:`parameters_err`. + """ + + return np.nan, np.nan + + class ExponentialOffsetFitFunction(AbstractFitFunction): """ A sub-class of `AbstractFitFunction` to represent an exponential with an From 66cc18ef0177eb4671cd373f169f57e4daa58676 Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 21 Sep 2020 17:20:26 -0700 Subject: [PATCH 093/521] update Linear's formula for error propagation to include x_err --- .../analysis/swept_langmuir/fit_functions.py | 27 ++++++++++++------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/plasmapy/analysis/swept_langmuir/fit_functions.py b/plasmapy/analysis/swept_langmuir/fit_functions.py index 3c4a41431d..c25a11d60f 100644 --- a/plasmapy/analysis/swept_langmuir/fit_functions.py +++ b/plasmapy/analysis/swept_langmuir/fit_functions.py @@ -515,12 +515,12 @@ class Linear(AbstractFitFunction): y &= f(x) = m \\, x + b - (\\delta y)^2 &= (x \\, \\delta m)^2 + (\\delta b)^2 - - where :math:`m` and :math:`b` are positive real constants representing the - slope and intercept, respectively, and :math:`x` is the independent - variable. + (\\delta y)^2 &= (x \\, \\delta m)^2 + (m \\, \\delta x)^2 + (\\delta b)^2 + where :math:`m` and :math:`b` are real constants to be fitted and :math:`x` is + the independent variable. :math:`\\delta m`, :math:`\\delta b`, and + :math:`\\delta x` are the respective errors for :math:`m`, :math:`b`, + and :math:`x`. """ _parameter_names = ("m", "b") @@ -565,7 +565,7 @@ def _func_err(self, x, y, x_err=None): .. math:: - (\\delta y)^2 &= (x \\, \\delta m)^2 + (\\delta b)^2 + (\\delta y)^2 &= (x \\, \\delta m)^2 + (m \\, \\delta x)^2 + (\\delta b)^2 Parameters ---------- @@ -578,9 +578,18 @@ def _func_err(self, x, y, x_err=None): The calculated errors of the dependent variables of the independent variables `x`. """ - m_term = (self.parameters_err[0] * x) ** 2 - b_term = self.parameters_err[1] ** 2 - return np.sqrt(m_term + b_term) + m, b = self.parameters + m_err, b_err = self.parameters_err + + m_term = (m_err * x) ** 2 + b_term = b_err ** 2 + err = m_term + b_term + + if x_err is not None: + x_term = (m * x_err) ** 2 + err += x_term + + return np.sqrt(err) @property def latex_str(self) -> str: From 0ff95f5e9dd3ef7e2b5d4e97f773c592fac0bb14 Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 21 Sep 2020 17:27:41 -0700 Subject: [PATCH 094/521] rename ExponentialOffsetFitFunction -> ExponentialPlusOffset --- .../analysis/swept_langmuir/fit_functions.py | 4 ++-- .../swept_langmuir/floating_potential.py | 20 +++++++++---------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/plasmapy/analysis/swept_langmuir/fit_functions.py b/plasmapy/analysis/swept_langmuir/fit_functions.py index c25a11d60f..84d5f58dbe 100644 --- a/plasmapy/analysis/swept_langmuir/fit_functions.py +++ b/plasmapy/analysis/swept_langmuir/fit_functions.py @@ -5,7 +5,7 @@ __all__ = [ "AbstractFitFunction", "Exponential", - "ExponentialOffsetFitFunction", + "ExponentialPlusOffset", "Linear", ] @@ -373,7 +373,7 @@ def root_solve(self, *args, **kwargs): return np.nan, np.nan -class ExponentialOffsetFitFunction(AbstractFitFunction): +class ExponentialPlusOffset(AbstractFitFunction): """ A sub-class of `AbstractFitFunction` to represent an exponential with an offset. diff --git a/plasmapy/analysis/swept_langmuir/floating_potential.py b/plasmapy/analysis/swept_langmuir/floating_potential.py index a6593f2a1b..ac956216c3 100644 --- a/plasmapy/analysis/swept_langmuir/floating_potential.py +++ b/plasmapy/analysis/swept_langmuir/floating_potential.py @@ -88,11 +88,11 @@ def find_floating_potential( types of curves ``"linear"`` and ``"exponential"`` (Default). These specified which `FitFunction` class should be applied to the trace. - +-------------+--------------------------------------------------------------------------------+ - | linear | `~plasmapy.analysis.swept_langmuir.fit_functions.Linear` | - +-------------+--------------------------------------------------------------------------------+ - | exponential | `~plasmapy.analysis.swept_langmuir.fit_functions.ExponentialOffsetFitFunction` | - +-------------+--------------------------------------------------------------------------------+ + +-------------+-------------------------------------------------------------------------+ + | linear | `~plasmapy.analysis.swept_langmuir.fit_functions.Linear` | + +-------------+-------------------------------------------------------------------------+ + | exponential | `~plasmapy.analysis.swept_langmuir.fit_functions.ExponentialPlusOffset` | + +-------------+-------------------------------------------------------------------------+ Returns ------- @@ -101,9 +101,9 @@ def find_floating_potential( floating potential can not be determined. How :math:`V_f` is calculated depends on the fit function. This is described in the `root_solve()` method of the relevant fit function (e.g. the - :meth:`~plasmapy.analysis.swept_langmuir.fit_functions.ExponentialOffsetFitFunction.root_solve` + :meth:`~plasmapy.analysis.swept_langmuir.fit_functions.ExponentialPlusOffset.root_solve` method of - `~plasmapy.analysis.swept_langmuir.fit_functions.ExponentialOffsetFitFunction`). + `~plasmapy.analysis.swept_langmuir.fit_functions.ExponentialPlusOffset`). vf_err: `float` or `numpy.nan` The error associated with the floating potential calculation (in volts). @@ -115,9 +115,9 @@ def find_floating_potential( The coefficient of determination (r-squared) value of the fit. See the documentation of the `rsq` property on the associated fit function (e.g. the - `~plasmapy.analysis.swept_langmuir.fit_functions.ExponentialOffsetFitFunction.rsq` + `~plasmapy.analysis.swept_langmuir.fit_functions.ExponentialPlusOffset.rsq` property of - `~plasmapy.analysis.swept_langmuir.fit_functions.ExponentialOffsetFitFunction`). + `~plasmapy.analysis.swept_langmuir.fit_functions.ExponentialPlusOffset`). func: sub-class of `~plasmapy.analysis.swept_langmuir.fit_functions.AbstractFitFunction` The callable function :math:`f(x)` repressing the fit and its results. @@ -146,7 +146,7 @@ def find_floating_potential( "min_point_factor": 0.1, }, "exponential": { - "func": ffuncs.ExponentialOffsetFitFunction(), + "func": ffuncs.ExponentialPlusOffset(), "min_point_factor": 0.2, }, } From 00e044c52d85219d572f0220d260f5342365db3b Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 21 Sep 2020 19:38:05 -0700 Subject: [PATCH 095/521] replace uses of _parameters and _parameter_errors outside of the associated properties with the property instances --- plasmapy/analysis/swept_langmuir/fit_functions.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/plasmapy/analysis/swept_langmuir/fit_functions.py b/plasmapy/analysis/swept_langmuir/fit_functions.py index 84d5f58dbe..3ead6d8ac8 100644 --- a/plasmapy/analysis/swept_langmuir/fit_functions.py +++ b/plasmapy/analysis/swept_langmuir/fit_functions.py @@ -285,8 +285,8 @@ def curve_fit(self, xdata, ydata, **kwargs) -> None: """ popt, pcov = curve_fit(self._func, xdata, ydata, **kwargs) self._curve_fit_results = (popt, pcov) - self._parameters = tuple(popt.tolist()) - self._parameters_err = tuple(np.sqrt(np.diag(pcov)).tolist()) + self.parameters = tuple(popt.tolist()) + self.parameters_err = tuple(np.sqrt(np.diag(pcov)).tolist()) # calc rsq # rsq = 1 - (ss_res / ss_tot) @@ -670,11 +670,11 @@ def curve_fit(self, xdata, ydata, **kwargs) -> None: m = results[0] b = results[1] - self._parameters = (m, b) + self.parameters = (m, b) m_err = results[4] b_err = np.sum(xdata ** 2) - ((np.sum(xdata) ** 2) / xdata.size) b_err = m_err * np.sqrt(1.0 / b_err) - self._parameters_err = (m_err, b_err) + self.parameters_err = (m_err, b_err) self._rsq = results[2] ** 2 From 2f85783545f75b2476951fcfc0532db82fd39436 Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 21 Sep 2020 19:39:24 -0700 Subject: [PATCH 096/521] create class ExponentialPlusLinear; move ExponentialPlusOffset below ExponentialPlusLinear --- .../analysis/swept_langmuir/fit_functions.py | 345 +++++++++++------- 1 file changed, 210 insertions(+), 135 deletions(-) diff --git a/plasmapy/analysis/swept_langmuir/fit_functions.py b/plasmapy/analysis/swept_langmuir/fit_functions.py index 3ead6d8ac8..87f1c3cb7b 100644 --- a/plasmapy/analysis/swept_langmuir/fit_functions.py +++ b/plasmapy/analysis/swept_langmuir/fit_functions.py @@ -5,6 +5,7 @@ __all__ = [ "AbstractFitFunction", "Exponential", + "ExponentialPlusLinear", "ExponentialPlusOffset", "Linear", ] @@ -314,7 +315,6 @@ class Exponential(AbstractFitFunction): :math:`x` is the independent variable. :math:`\\delta A`, :math:`\\delta \\alpha`, and :math:`\\delta x` are the respective errors for :math:`A`, :math:`\\alpha`, and :math:`x`. - """ _parameter_names = ("a", "alpha") @@ -373,140 +373,6 @@ def root_solve(self, *args, **kwargs): return np.nan, np.nan -class ExponentialPlusOffset(AbstractFitFunction): - """ - A sub-class of `AbstractFitFunction` to represent an exponential with an - offset. - - .. math:: - - y &= f(x) = A \\, \\exp(B \\, x) + C - - (\\delta y)^2 &= (e^{B \\,x} \\delta A)^2 - + (A \\, B \\, e^{B \\, x} \\delta B)^2 - + (\\delta C)^2 - - - where :math:`A`, :math:`B`, and :math:`C` are positive real constants - and :math:`x` is the independent variable. - - """ - _parameter_names = ("a", "b", "c") - - def __str__(self): - return f"f(x) = A exp(B x) + C" - - def _func(self, x, a, b, c): - """ - The fit function, an exponential with an offset. - - .. math:: - - f(x) = A \\, \\exp(B \\, x) + C - - where :math:`A`, :math:`B`, and :math:`C` are positive real constants - and :math:`x` is the independent variable. - - Parameters - ---------- - x: array_like - Independent variable. - - a: float - value for constant :math:`A` - - b: float - value for constant :math:`B` - - c: float - value for constant :math:`C` - - Returns - ------- - y: array_like - dependent variables corresponding to :math:`x` - - """ - return a * np.exp(b * x) + c - - def _func_err(self, x, y, x_err=None): - """ - Calculate dependent variable errors :math:`\\delta y` for dependent - variables :math:`y=f(x)`. - - .. math:: - - (\\delta y)^2 = (e^{B \\,x} \\delta A)^2 - + (A \\, B \\, e^{B \\, x} \\delta B)^2 - + (\\delta C)^2 - - Parameters - ---------- - x: array_like - Independent variables to be passed to the fit function. - - Returns - ------- - `numpy.ndarray`: - The calculated errors of the dependent variables of the independent - variables `x`. - """ - a, b, c = self.parameters - a_err, b_err, c_err = self.parameters_err - a_term = (np.exp(b * x) * a_err) ** 2 - b_term = (a * b * np.exp(b * x) * b_err) ** 2 - c_term = c_err ** 2 - return np.sqrt(a_term + b_term + c_term) - - @property - def latex_str(self) -> str: - return fr"A \, \exp(B \, x) + C" - - def root_solve(self, *args, **kwargs): - """ - The root :math:`f(x_r) = 0` for the fit function. - - .. math:: - - x_r &= \\frac{1}{B} \\ln \\left( \\frac{-C}{A} \\right) - - \\delta x_r &= \\sqrt{ - \\left( \\frac{\\delta A}{A B} \\right)^2 - + \\left( x_r \\frac{\\delta B}{B} \\right)^2 - + \\left( \\frac{\\delta C}{B C} \\right)^2 - } - - Parameters - ---------- - *args - Not needed. This is to ensure signature comparability with - `AbstractFitFunction`. - - *kwargs - Not needed. This is to ensure signature comparability with - `AbstractFitFunction`. - - Returns - ------- - root: float - The root value for the given fit :attr:`parameters`. - - err: float - The error in the calculated root for the given fit - :attr:`parameters` and :attr:`parameters_err`. - """ - a, b, c = self.parameters - root = np.log(-c / a) / b - - a_err, b_err, c_err = self.parameters_err - a_term = a_err / (a * b) - b_term = b_err * root / b - c_term = c_err / (b * c) - err = np.sqrt(a_term ** 2 + b_term ** 2 + c_term ** 2) - - return root, err - - class Linear(AbstractFitFunction): """ A sub-class of `AbstractFitFunction` to represent a linear function. @@ -678,3 +544,212 @@ def curve_fit(self, xdata, ydata, **kwargs) -> None: self.parameters_err = (m_err, b_err) self._rsq = results[2] ** 2 + + +class ExponentialPlusLinear(Exponential, Linear): + """ + A sub-class of `AbstractFitFunction` to represent an exponential with an + offset. + + .. math:: + + y =& f(x) = A \\, e^{\\alpha \\, x} + m \\, x + b\\\\ + (\\delta y)^2 =& + \\left( A e^{\\alpha x}\\right)^2 \\left[ + \\left( \\frac{\\delta A}{A} \\right)^2 + + (x \\, \\delta \\alpha)^2 + + (\\alpha \\, \\delta x)^2 + \\right]\\\\ + & + \\left(2 \\, A \\, \\alpha \\, m \\, e^{\\alpha x}\\right) + (\\delta x)^2\\\\ + & + \\left[(x \\, \\delta m)^2 + (\\delta b)^2 +(m \\, \\delta x)^2\\right] + + where :math:`A` and :math:`\\alpha` are the real constants to be fitted and + :math:`x` is the independent variable. :math:`\\delta A`, + :math:`\\delta \\alpha`, and :math:`\\delta x` are the respective errors for + :math:`A`, :math:`\\alpha`, and :math:`x`. + """ + _parameter_names = ("a", "alpha", "m", "b") + + def __init__(self): + super().__init__() + self._exponential = Exponential() + self._linear = Linear() + + def __str__(self): + exp_str = self._exponential.__str__().lstrip("f(x) = ") + lin_str = self._linear.__str__().lstrip("f(x) = ") + return f"f(x) = {exp_str} + {lin_str}" + + @property + def latex_str(self) -> str: + exp_str = self._exponential.latex_str + lin_str = self._linear.latex_str + return fr"{exp_str} + {lin_str}" + + @AbstractFitFunction.parameters.setter + def parameters(self, val) -> None: + AbstractFitFunction.parameters.fset(self, val) + self._exponential.parameters = (self.parameters.a, self.parameters.alpha) + self._linear.parameters = (self.parameters.m, self.parameters.b) + + @AbstractFitFunction.parameters_err.setter + def parameters_err(self, val) -> None: + AbstractFitFunction.parameters_err.fset(self, val) + self._exponential.parameters_err = ( + self.parameters_err.a, + self.parameters_err.alpha, + ) + self._linear.parameters_err = (self.parameters_err.m, self.parameters_err.b) + + def _func(self, x, a, alpha, m , b): + exp_term = self._exponential._func(x, a, alpha) + lin_term = self._linear._func(x, m, b) + return exp_term + lin_term + + def _func_err(self, x, y, x_err=None): + a, alpha, m, b = self.parameters + + exp_y, exp_err = self._exponential(x, x_err=x_err, reterr=True) + lin_y, lin_err = self._linear(x, x_err=x_err, reterr=True) + err = exp_err + lin_err + + if x_err is not None: + blend_err = 2 * a * alpha * m * np.exp(alpha * x) * (x_err ** x) + err += blend_err + + return err + + +class ExponentialPlusOffset(AbstractFitFunction): + """ + A sub-class of `AbstractFitFunction` to represent an exponential with an + offset. + + .. math:: + + y &= f(x) = A \\, \\exp(B \\, x) + C + + (\\delta y)^2 &= (e^{B \\,x} \\delta A)^2 + + (A \\, B \\, e^{B \\, x} \\delta B)^2 + + (\\delta C)^2 + + + where :math:`A`, :math:`B`, and :math:`C` are positive real constants + and :math:`x` is the independent variable. + + """ + _parameter_names = ("a", "b", "c") + + def __str__(self): + return f"f(x) = A exp(B x) + C" + + def _func(self, x, a, b, c): + """ + The fit function, an exponential with an offset. + + .. math:: + + f(x) = A \\, \\exp(B \\, x) + C + + where :math:`A`, :math:`B`, and :math:`C` are positive real constants + and :math:`x` is the independent variable. + + Parameters + ---------- + x: array_like + Independent variable. + + a: float + value for constant :math:`A` + + b: float + value for constant :math:`B` + + c: float + value for constant :math:`C` + + Returns + ------- + y: array_like + dependent variables corresponding to :math:`x` + + """ + return a * np.exp(b * x) + c + + def _func_err(self, x, y, x_err=None): + """ + Calculate dependent variable errors :math:`\\delta y` for dependent + variables :math:`y=f(x)`. + + .. math:: + + (\\delta y)^2 = (e^{B \\,x} \\delta A)^2 + + (A \\, B \\, e^{B \\, x} \\delta B)^2 + + (\\delta C)^2 + + Parameters + ---------- + x: array_like + Independent variables to be passed to the fit function. + + Returns + ------- + `numpy.ndarray`: + The calculated errors of the dependent variables of the independent + variables `x`. + """ + a, b, c = self.parameters + a_err, b_err, c_err = self.parameters_err + a_term = (np.exp(b * x) * a_err) ** 2 + b_term = (a * b * np.exp(b * x) * b_err) ** 2 + c_term = c_err ** 2 + return np.sqrt(a_term + b_term + c_term) + + @property + def latex_str(self) -> str: + return fr"A \, \exp(B \, x) + C" + + def root_solve(self, *args, **kwargs): + """ + The root :math:`f(x_r) = 0` for the fit function. + + .. math:: + + x_r &= \\frac{1}{B} \\ln \\left( \\frac{-C}{A} \\right) + + \\delta x_r &= \\sqrt{ + \\left( \\frac{\\delta A}{A B} \\right)^2 + + \\left( x_r \\frac{\\delta B}{B} \\right)^2 + + \\left( \\frac{\\delta C}{B C} \\right)^2 + } + + Parameters + ---------- + *args + Not needed. This is to ensure signature comparability with + `AbstractFitFunction`. + + *kwargs + Not needed. This is to ensure signature comparability with + `AbstractFitFunction`. + + Returns + ------- + root: float + The root value for the given fit :attr:`parameters`. + + err: float + The error in the calculated root for the given fit + :attr:`parameters` and :attr:`parameters_err`. + """ + a, b, c = self.parameters + root = np.log(-c / a) / b + + a_err, b_err, c_err = self.parameters_err + a_term = a_err / (a * b) + b_term = b_err * root / b + c_term = c_err / (b * c) + err = np.sqrt(a_term ** 2 + b_term ** 2 + c_term ** 2) + + return root, err From ba9d06e1cc0fa00f56053eddde8881b19b8fe9e8 Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 21 Sep 2020 19:53:45 -0700 Subject: [PATCH 097/521] move plasmapy.analysis.swept_langmuir.fit_functions -> plasmapy.analysis.fit_functions (update documentation and references accordingly) --- docs/ad/analysis/index.rst | 2 ++ docs/ad/analysis/swept_langmuir.rst | 1 - .../plasmapy.analysis.fit_functions.rst | 11 ++++++++++ ....analysis.swept_langmuir.fit_functions.rst | 11 ---------- .../find_floating_potential.ipynb | 2 +- plasmapy/analysis/__init__.py | 2 +- .../{swept_langmuir => }/fit_functions.py | 0 .../swept_langmuir/floating_potential.py | 22 +++++++++---------- 8 files changed, 26 insertions(+), 25 deletions(-) create mode 100644 docs/api_static/plasmapy.analysis.fit_functions.rst delete mode 100644 docs/api_static/plasmapy.analysis.swept_langmuir.fit_functions.rst rename plasmapy/analysis/{swept_langmuir => }/fit_functions.py (100%) diff --git a/docs/ad/analysis/index.rst b/docs/ad/analysis/index.rst index 3b8355f0b7..55a8d31309 100644 --- a/docs/ad/analysis/index.rst +++ b/docs/ad/analysis/index.rst @@ -11,6 +11,7 @@ Analyses (`plasmapy.analysis`) .. toctree:: :maxdepth: 1 + Fit Functions Swept Langmuir API @@ -23,6 +24,7 @@ Sub-Packages & Modules .. autosummary:: + fit_functions swept_langmuir .. automodapi:: plasmapy.analysis diff --git a/docs/ad/analysis/swept_langmuir.rst b/docs/ad/analysis/swept_langmuir.rst index a6144f91d3..e03c30447a 100644 --- a/docs/ad/analysis/swept_langmuir.rst +++ b/docs/ad/analysis/swept_langmuir.rst @@ -25,7 +25,6 @@ Sub-Packages & Modules .. autosummary:: floating_potential - fit_functions .. automodapi:: plasmapy.analysis.swept_langmuir :no-main-docstr: diff --git a/docs/api_static/plasmapy.analysis.fit_functions.rst b/docs/api_static/plasmapy.analysis.fit_functions.rst new file mode 100644 index 0000000000..3a3ad61591 --- /dev/null +++ b/docs/api_static/plasmapy.analysis.fit_functions.rst @@ -0,0 +1,11 @@ +:orphan: + +`plasmapy.analysis.fit_functions` +================================= + +.. currentmodule:: plasmapy.analysis.fit_functions + +.. automodapi:: plasmapy.analysis.fit_functions + :include-all-objects: + :inherited-members: + :no-heading: diff --git a/docs/api_static/plasmapy.analysis.swept_langmuir.fit_functions.rst b/docs/api_static/plasmapy.analysis.swept_langmuir.fit_functions.rst deleted file mode 100644 index e8e287665c..0000000000 --- a/docs/api_static/plasmapy.analysis.swept_langmuir.fit_functions.rst +++ /dev/null @@ -1,11 +0,0 @@ -:orphan: - -`plasmapy.analysis.swept_langmuir.fit_functions` -================================================ - -.. currentmodule:: plasmapy.analysis.swept_langmuir.fit_functions - -.. automodapi:: plasmapy.analysis.swept_langmuir.fit_functions - :include-all-objects: - :inherited-members: - :no-heading: diff --git a/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb b/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb index 7b5dc1dde4..31f6222709 100644 --- a/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb +++ b/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb @@ -183,7 +183,7 @@ "- `results[3]` = `results.func` = the resulting fitted function\n", "\n", " - `results.func` is a callable representation of the fitted function `I = results.func(V)`.\n", - " - `resulst.func` is an instance of a sub-class of `AbstractFitFunction`. ([**FitFuction** classes](../../../api_static/plasmapy.analysis.swept_langmuir.fit_functions.rst))\n", + " - `resulst.func` is an instance of a sub-class of `AbstractFitFunction`. ([**FitFuction** classes](../../../api_static/plasmapy.analysis.fit_functions.rst))\n", " - Since `results.func` is a class instance, there are many other attribures available. For example,\n", " - `results.func.parameters` is a named tuple of the fitted parameters\n", " - `results.func.parameters_err` is a named tuple of the fitted parameter errors\n", diff --git a/plasmapy/analysis/__init__.py b/plasmapy/analysis/__init__.py index d9380bba91..4417ca8c9a 100644 --- a/plasmapy/analysis/__init__.py +++ b/plasmapy/analysis/__init__.py @@ -1,4 +1,4 @@ """The analysis sub-package for PlasmaPy.""" __all__ = [] -from plasmapy.analysis import swept_langmuir +from plasmapy.analysis import swept_langmuir, fit_functions diff --git a/plasmapy/analysis/swept_langmuir/fit_functions.py b/plasmapy/analysis/fit_functions.py similarity index 100% rename from plasmapy/analysis/swept_langmuir/fit_functions.py rename to plasmapy/analysis/fit_functions.py diff --git a/plasmapy/analysis/swept_langmuir/floating_potential.py b/plasmapy/analysis/swept_langmuir/floating_potential.py index ac956216c3..6b93b9d8a9 100644 --- a/plasmapy/analysis/swept_langmuir/floating_potential.py +++ b/plasmapy/analysis/swept_langmuir/floating_potential.py @@ -7,7 +7,7 @@ from warnings import warn from typing import Union -from plasmapy.analysis.swept_langmuir import fit_functions as ffuncs +from plasmapy.analysis import fit_functions as ffuncs FloatingPotentialResults = namedtuple( "FloatingPotentialResults", @@ -88,11 +88,11 @@ def find_floating_potential( types of curves ``"linear"`` and ``"exponential"`` (Default). These specified which `FitFunction` class should be applied to the trace. - +-------------+-------------------------------------------------------------------------+ - | linear | `~plasmapy.analysis.swept_langmuir.fit_functions.Linear` | - +-------------+-------------------------------------------------------------------------+ - | exponential | `~plasmapy.analysis.swept_langmuir.fit_functions.ExponentialPlusOffset` | - +-------------+-------------------------------------------------------------------------+ + +-------------+----------------------------------------------------------+ + | linear | `~plasmapy.analysis.fit_functions.Linear` | + +-------------+----------------------------------------------------------+ + | exponential | `~plasmapy.analysis.fit_functions.ExponentialPlusOffset` | + +-------------+----------------------------------------------------------+ Returns ------- @@ -101,9 +101,9 @@ def find_floating_potential( floating potential can not be determined. How :math:`V_f` is calculated depends on the fit function. This is described in the `root_solve()` method of the relevant fit function (e.g. the - :meth:`~plasmapy.analysis.swept_langmuir.fit_functions.ExponentialPlusOffset.root_solve` + :meth:`~plasmapy.analysis.fit_functions.ExponentialPlusOffset.root_solve` method of - `~plasmapy.analysis.swept_langmuir.fit_functions.ExponentialPlusOffset`). + `~plasmapy.analysis.fit_functions.ExponentialPlusOffset`). vf_err: `float` or `numpy.nan` The error associated with the floating potential calculation (in volts). @@ -115,11 +115,11 @@ def find_floating_potential( The coefficient of determination (r-squared) value of the fit. See the documentation of the `rsq` property on the associated fit function (e.g. the - `~plasmapy.analysis.swept_langmuir.fit_functions.ExponentialPlusOffset.rsq` + `~plasmapy.analysis.fit_functions.ExponentialPlusOffset.rsq` property of - `~plasmapy.analysis.swept_langmuir.fit_functions.ExponentialPlusOffset`). + `~plasmapy.analysis.fit_functions.ExponentialPlusOffset`). - func: sub-class of `~plasmapy.analysis.swept_langmuir.fit_functions.AbstractFitFunction` + func: sub-class of `~plasmapy.analysis.fit_functions.AbstractFitFunction` The callable function :math:`f(x)` repressing the fit and its results. islands: `List[slice]` From 8c90bce7bd89eb4785f05f974bc5b11ed7a2ce3c Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 21 Sep 2020 20:24:57 -0700 Subject: [PATCH 098/521] update class level docstrings for ExponentialPlusLinear --- plasmapy/analysis/fit_functions.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/plasmapy/analysis/fit_functions.py b/plasmapy/analysis/fit_functions.py index 87f1c3cb7b..c7cb6eabd6 100644 --- a/plasmapy/analysis/fit_functions.py +++ b/plasmapy/analysis/fit_functions.py @@ -549,7 +549,7 @@ def curve_fit(self, xdata, ydata, **kwargs) -> None: class ExponentialPlusLinear(Exponential, Linear): """ A sub-class of `AbstractFitFunction` to represent an exponential with an - offset. + linear offset. .. math:: @@ -564,10 +564,11 @@ class ExponentialPlusLinear(Exponential, Linear): (\\delta x)^2\\\\ & + \\left[(x \\, \\delta m)^2 + (\\delta b)^2 +(m \\, \\delta x)^2\\right] - where :math:`A` and :math:`\\alpha` are the real constants to be fitted and - :math:`x` is the independent variable. :math:`\\delta A`, - :math:`\\delta \\alpha`, and :math:`\\delta x` are the respective errors for - :math:`A`, :math:`\\alpha`, and :math:`x`. + where :math:`A`, :math:`\\alpha`, :math:`m`, and :math:`b` are the real + constants to be fitted and :math:`x` is the independent variable. + :math:`\\delta A`, :math:`\\delta \\alpha`, :math:`\\delta m`, :math:`\\delta b`, + and :math:`\\delta x` are the respective errors for :math:`A`, :math:`\\alpha`, + :math:`m`, and :math:`b`, and :math:`x`. """ _parameter_names = ("a", "alpha", "m", "b") From 6b2c1a95eef88065257664a34dd8243b04bbe63e Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 21 Sep 2020 20:25:29 -0700 Subject: [PATCH 099/521] redefine curve_fit and root_solve to be that of the AbstractFitFunction class --- plasmapy/analysis/fit_functions.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/plasmapy/analysis/fit_functions.py b/plasmapy/analysis/fit_functions.py index c7cb6eabd6..feffe2b6f6 100644 --- a/plasmapy/analysis/fit_functions.py +++ b/plasmapy/analysis/fit_functions.py @@ -621,6 +621,9 @@ def _func_err(self, x, y, x_err=None): return err + curve_fit = AbstractFitFunction.curve_fit + root_solve = AbstractFitFunction.root_solve + class ExponentialPlusOffset(AbstractFitFunction): """ From 0e7bd71dd55dc8f5215635299a502b06c9999904 Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 21 Sep 2020 22:28:10 -0700 Subject: [PATCH 100/521] have ExponentialPlusLinear be a direct subclass of AbstractFitFunction --- plasmapy/analysis/fit_functions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plasmapy/analysis/fit_functions.py b/plasmapy/analysis/fit_functions.py index feffe2b6f6..8104353665 100644 --- a/plasmapy/analysis/fit_functions.py +++ b/plasmapy/analysis/fit_functions.py @@ -546,7 +546,7 @@ def curve_fit(self, xdata, ydata, **kwargs) -> None: self._rsq = results[2] ** 2 -class ExponentialPlusLinear(Exponential, Linear): +class ExponentialPlusLinear(AbstractFitFunction): """ A sub-class of `AbstractFitFunction` to represent an exponential with an linear offset. From f4b23fddae88cf017ea177ddb5dfd34bb26ccdc9 Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 21 Sep 2020 22:28:52 -0700 Subject: [PATCH 101/521] repair missed squares on ExponentialPlusLinear._func_err --- plasmapy/analysis/fit_functions.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/plasmapy/analysis/fit_functions.py b/plasmapy/analysis/fit_functions.py index 8104353665..821e92037c 100644 --- a/plasmapy/analysis/fit_functions.py +++ b/plasmapy/analysis/fit_functions.py @@ -613,16 +613,13 @@ def _func_err(self, x, y, x_err=None): exp_y, exp_err = self._exponential(x, x_err=x_err, reterr=True) lin_y, lin_err = self._linear(x, x_err=x_err, reterr=True) - err = exp_err + lin_err + err = exp_err ** 2 + lin_err ** 2 if x_err is not None: blend_err = 2 * a * alpha * m * np.exp(alpha * x) * (x_err ** x) err += blend_err - return err - - curve_fit = AbstractFitFunction.curve_fit - root_solve = AbstractFitFunction.root_solve + return np.sqrt(err) class ExponentialPlusOffset(AbstractFitFunction): From 460eb9a61ee67bea1f090018bb1525d67e5b5e10 Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 21 Sep 2020 22:29:34 -0700 Subject: [PATCH 102/521] let ExponentialPlusOffest leverage ExponentialPlusLinear --- plasmapy/analysis/fit_functions.py | 97 ++++++++++-------------------- 1 file changed, 33 insertions(+), 64 deletions(-) diff --git a/plasmapy/analysis/fit_functions.py b/plasmapy/analysis/fit_functions.py index 821e92037c..9f6e341649 100644 --- a/plasmapy/analysis/fit_functions.py +++ b/plasmapy/analysis/fit_functions.py @@ -624,12 +624,12 @@ def _func_err(self, x, y, x_err=None): class ExponentialPlusOffset(AbstractFitFunction): """ - A sub-class of `AbstractFitFunction` to represent an exponential with an + A sub-class of `AbstractFitFunction` to represent an exponential with a DC offset. .. math:: - y &= f(x) = A \\, \\exp(B \\, x) + C + y &= f(x) = A \\, \\exp(\\alpha \\, x) + b (\\delta y)^2 &= (e^{B \\,x} \\delta A)^2 + (A \\, B \\, e^{B \\, x} \\delta B)^2 @@ -640,76 +640,45 @@ class ExponentialPlusOffset(AbstractFitFunction): and :math:`x` is the independent variable. """ - _parameter_names = ("a", "b", "c") - - def __str__(self): - return f"f(x) = A exp(B x) + C" - - def _func(self, x, a, b, c): - """ - The fit function, an exponential with an offset. - - .. math:: - - f(x) = A \\, \\exp(B \\, x) + C + _parameter_names = ("a", "alpha", "b") - where :math:`A`, :math:`B`, and :math:`C` are positive real constants - and :math:`x` is the independent variable. - - Parameters - ---------- - x: array_like - Independent variable. + def __init__(self): + super().__init__() + self._explin = ExponentialPlusLinear() - a: float - value for constant :math:`A` + def __str__(self): + return f"f(x) = A exp(alpha x) + b" - b: float - value for constant :math:`B` + @property + def latex_str(self) -> str: + return fr"A \, \exp(B \, x) + C" - c: float - value for constant :math:`C` + @AbstractFitFunction.parameters.setter + def parameters(self, val) -> None: + AbstractFitFunction.parameters.fset(self, val) + self._explin.parameters = ( + self.parameters.a, + self.parameters.alpha, + 0.0, + self.parameters.b, + ) - Returns - ------- - y: array_like - dependent variables corresponding to :math:`x` + @AbstractFitFunction.parameters_err.setter + def parameters_err(self, val) -> None: + AbstractFitFunction.parameters_err.fset(self, val) + self._explin.parameters_err = ( + self.parameters_err.a, + self.parameters_err.alpha, + 0.0, + self.parameters_err.b, + ) - """ - return a * np.exp(b * x) + c + def _func(self, x, a, alpha, b): + return self._explin._func(x, a, alpha, 0.0, b) def _func_err(self, x, y, x_err=None): - """ - Calculate dependent variable errors :math:`\\delta y` for dependent - variables :math:`y=f(x)`. - - .. math:: - - (\\delta y)^2 = (e^{B \\,x} \\delta A)^2 - + (A \\, B \\, e^{B \\, x} \\delta B)^2 - + (\\delta C)^2 - - Parameters - ---------- - x: array_like - Independent variables to be passed to the fit function. - - Returns - ------- - `numpy.ndarray`: - The calculated errors of the dependent variables of the independent - variables `x`. - """ - a, b, c = self.parameters - a_err, b_err, c_err = self.parameters_err - a_term = (np.exp(b * x) * a_err) ** 2 - b_term = (a * b * np.exp(b * x) * b_err) ** 2 - c_term = c_err ** 2 - return np.sqrt(a_term + b_term + c_term) - - @property - def latex_str(self) -> str: - return fr"A \, \exp(B \, x) + C" + _, err = self._explin(x, x_err=x_err, reterr=True) + return err def root_solve(self, *args, **kwargs): """ From dd52e28312daef72b533a7e754bbce25a48d6f7d Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 21 Sep 2020 22:40:45 -0700 Subject: [PATCH 103/521] update docstrings for ExponentialPlusOffset --- plasmapy/analysis/fit_functions.py | 41 +++++++++++++++++------------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/plasmapy/analysis/fit_functions.py b/plasmapy/analysis/fit_functions.py index 9f6e341649..cbb370b9d7 100644 --- a/plasmapy/analysis/fit_functions.py +++ b/plasmapy/analysis/fit_functions.py @@ -629,15 +629,21 @@ class ExponentialPlusOffset(AbstractFitFunction): .. math:: - y &= f(x) = A \\, \\exp(\\alpha \\, x) + b - - (\\delta y)^2 &= (e^{B \\,x} \\delta A)^2 - + (A \\, B \\, e^{B \\, x} \\delta B)^2 - + (\\delta C)^2 + y =& f(x) = A \\, e^{\\alpha \\, x} + m \\, x + b\\\\ + (\\delta y)^2 =& + \\left( A e^{\\alpha x}\\right)^2 \\left[ + \\left( \\frac{\\delta A}{A} \\right)^2 + + (x \\, \\delta \\alpha)^2 + + (\\alpha \\, \\delta x)^2 + \\right] + + (\\delta b)^2 - where :math:`A`, :math:`B`, and :math:`C` are positive real constants - and :math:`x` is the independent variable. + where :math:`A`, :math:`\\alpha`, and :math:`b` are the real constants to + be fitted and :math:`x` is the independent variable. :math:`\\delta A`, + :math:`\\delta \\alpha`, :math:`\\delta b`, and :math:`\\delta x` are the + respective errors for :math:`A`, :math:`\\alpha`, and :math:`b`, and + :math:`x`. """ _parameter_names = ("a", "alpha", "b") @@ -686,12 +692,12 @@ def root_solve(self, *args, **kwargs): .. math:: - x_r &= \\frac{1}{B} \\ln \\left( \\frac{-C}{A} \\right) + x_r &= \\frac{1}{\\alpha} \\ln \\left( \\frac{-b}{A} \\right) \\delta x_r &= \\sqrt{ - \\left( \\frac{\\delta A}{A B} \\right)^2 - + \\left( x_r \\frac{\\delta B}{B} \\right)^2 - + \\left( \\frac{\\delta C}{B C} \\right)^2 + \\left( \\frac{1}{\\alpha} \\frac{\\delta A}{A} \\right)^2 + + \\left( x_r \\frac{\\delta \\alpha}{\\alpha} \\right)^2 + + \\left( \\frac{1}{\\alpha} \\frac{\\delta b}{b} \\right)^2 } Parameters @@ -713,13 +719,14 @@ def root_solve(self, *args, **kwargs): The error in the calculated root for the given fit :attr:`parameters` and :attr:`parameters_err`. """ - a, b, c = self.parameters - root = np.log(-c / a) / b - + a, alpha, b = self.parameters a_err, b_err, c_err = self.parameters_err - a_term = a_err / (a * b) - b_term = b_err * root / b - c_term = c_err / (b * c) + + root = np.log(-b / a) / alpha + + a_term = a_err / (a * alpha) + b_term = b_err * root / alpha + c_term = c_err / (alpha * b) err = np.sqrt(a_term ** 2 + b_term ** 2 + c_term ** 2) return root, err From 54e10c42dfc0c38918756f2df05e2aa72e3d6c42 Mon Sep 17 00:00:00 2001 From: Erik Date: Tue, 22 Sep 2020 08:58:31 -0700 Subject: [PATCH 104/521] update import of fit functions due to recent move --- .../swept_langmuir/ion_saturation_current.py | 26 ++++++++++++------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/plasmapy/analysis/swept_langmuir/ion_saturation_current.py b/plasmapy/analysis/swept_langmuir/ion_saturation_current.py index e76e007475..dee73d436c 100644 --- a/plasmapy/analysis/swept_langmuir/ion_saturation_current.py +++ b/plasmapy/analysis/swept_langmuir/ion_saturation_current.py @@ -7,10 +7,7 @@ from collections import namedtuple -from plasmapy.analysis.swept_langmuir.fit_functions import ( - ExponentialLinearFitFunction, - LinearFitFunction, -) +from plasmapy.analysis import fit_functions as ffuncs IonSaturationCurrentResults = namedtuple( @@ -33,8 +30,9 @@ def find_ion_saturation_current( )._asdict() fit_funcs = { - "linear": LinearFitFunction(), - "explinear": ExponentialLinearFitFunction() + "linear": ffuncs.Linear(), + "explinear": ffuncs.ExponentialPlusLinear(), + "expffset": ffuncs.ExponentialPlusOffset(), } try: fit_func = fit_funcs[fit_type] @@ -58,9 +56,19 @@ def find_ion_saturation_current( rtn["rsq"] = fit_func.rsq - isat = LinearFitFunction() - isat._parameters = [fit_func.parameters.m, fit_func.parameters.b] - isat._parameters_err = [fit_func.parameters_err.m, fit_func.parameters_err.b] + isat = ffuncs.Linear() + try: + m = fit_func.parameters.m + m_err = fit_func.parameters_err.m + except AttributeError: + m = m_err = 0.0 + try: + b = fit_func.parameters.b + b_err = fit_func.parameters_err.b + except AttributeError: + b = b_err = 0.0 + isat.parameters = [m, b] + isat.parameters_err = [m_err, b_err] rtn["isat_func"] = isat return IonSaturationCurrentResults(**rtn) From b61287393fd7399fe268dadada04cf97ff991e23 Mon Sep 17 00:00:00 2001 From: Erik Date: Tue, 22 Sep 2020 09:33:04 -0700 Subject: [PATCH 105/521] expand example to produce an example FitFunciton sub-class (mainly to get doctests to pass) --- plasmapy/analysis/fit_functions.py | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/plasmapy/analysis/fit_functions.py b/plasmapy/analysis/fit_functions.py index cbb370b9d7..1ebc2268f0 100644 --- a/plasmapy/analysis/fit_functions.py +++ b/plasmapy/analysis/fit_functions.py @@ -218,7 +218,34 @@ def root_solve(self, x0, **kwargs): ----- If the full output of `scipy.optimize.fsolve` is desired then one can do - >>> func = FitFunction() # FitFunciton is a subclass of AbstractFitFunction + >>> import numpy as np + >>> import scipy + + >>> class SomeFunc(AbstractFitFunction): + ... _parameter_names = ("m", "b") + ... + ... @property + ... def latex_str(self) -> str: + ... return return fr"m \, x + b" + ... + ... def _func(self, x, m, b): + ... return m * x + b + ... + ... def _func_err(self, x, y, x_err=None): + ... m, b = self.parameters + ... m_err, b_err = self.parameters_err + ... + ... m_term = x * m_err + ... b_term = b_err + ... err = m_term ** 2 + b_term ** 2 + ... + ... if x_err is not None: + ... x_term = m * x_err + ... err == x_term ** 2 + ... + ... return np.sqrt(err) + ... + >>> func = SomeFunc() >>> roots = scipy.optimize.fsolve(func, 0.) """ From 9638dc2465db476956eccffb85632690592b430f Mon Sep 17 00:00:00 2001 From: Erik Date: Tue, 22 Sep 2020 09:52:54 -0700 Subject: [PATCH 106/521] add complete reporting of fsolve in example --- plasmapy/analysis/fit_functions.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/plasmapy/analysis/fit_functions.py b/plasmapy/analysis/fit_functions.py index 1ebc2268f0..2eaaf3dcec 100644 --- a/plasmapy/analysis/fit_functions.py +++ b/plasmapy/analysis/fit_functions.py @@ -246,7 +246,18 @@ def root_solve(self, x0, **kwargs): ... return np.sqrt(err) ... >>> func = SomeFunc() - >>> roots = scipy.optimize.fsolve(func, 0.) + >>> func.parameters = (1., 5.) + >>> func.parameters_err = (0.0, 0.0) + >>> roots = scipy.optimize.fsolve(func, -4., full_output=True) + >>> roots + (array([-5.]), + {'nfev': 4, + 'fjac': array([[-1.]]), + 'r': array([-1.]), + 'qtf': array([...]), + 'fvec': array([0.])}, + 1, + 'The solution converged.') """ kwargs["args"] = self.parameters From 22609916b27fc0420c67224f38712c00009f6415 Mon Sep 17 00:00:00 2001 From: Erik Date: Tue, 22 Sep 2020 10:20:55 -0700 Subject: [PATCH 107/521] more minor tweaks/fixes to get doctests to pass --- plasmapy/analysis/fit_functions.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plasmapy/analysis/fit_functions.py b/plasmapy/analysis/fit_functions.py index 2eaaf3dcec..2f7219f609 100644 --- a/plasmapy/analysis/fit_functions.py +++ b/plasmapy/analysis/fit_functions.py @@ -226,7 +226,7 @@ def root_solve(self, x0, **kwargs): ... ... @property ... def latex_str(self) -> str: - ... return return fr"m \, x + b" + ... return f"m \\, x + b" ... ... def _func(self, x, m, b): ... return m * x + b @@ -254,7 +254,7 @@ def root_solve(self, x0, **kwargs): {'nfev': 4, 'fjac': array([[-1.]]), 'r': array([-1.]), - 'qtf': array([...]), + 'qtf': array([2.18...e-12]), 'fvec': array([0.])}, 1, 'The solution converged.') From a3af288026cde9988694e4f5d3fdc09bff9fdf5f Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 25 Sep 2020 12:35:52 -0700 Subject: [PATCH 108/521] rename section "How does find_floating_potential() work?" -> "How find_floating_potential() works" --- .../analysis/swept_langmuir/find_floating_potential.ipynb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb b/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb index 31f6222709..fbcb1e04c5 100644 --- a/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb +++ b/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb @@ -32,7 +32,7 @@ "source": [ "## Contents:\n", "\n", - "1. [How does **find_floating_potential()** work?](#How-does-find_floating_potential()-work?)\n", + "1. [How find_floating_potential() works](#How-find_floating_potential()-works)\n", " 1. [Notes about usage](#Notes-about-usage)\n", " 1. [Knobs to turn](#Knobs-to-turn)\n", "1. [Calculate the Floating Potential](#Calculate-the-Floating-Potential)\n", @@ -44,7 +44,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## How does `find_floating_potential()` work?\n", + "## How `find_floating_potential()` works\n", "\n", "1. The passed current array is scanned for points that equal zero and point-pairs that straddle $I = 0$. This forms an collection of \"crossing-points.\"\n", "1. The crossing-points are then grouped into \"crossing-islands\" based on the `threshold` keyword.\n", From f225ae4ace672447f70ba3fd67bdbc0a0dbf9586 Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 25 Sep 2020 12:36:20 -0700 Subject: [PATCH 109/521] add brief description to the top of the notebook --- .../analysis/swept_langmuir/find_floating_potential.ipynb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb b/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb index fbcb1e04c5..a479324d5a 100644 --- a/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb +++ b/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb @@ -4,7 +4,9 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Swept Langmuir Analysis: Floating Potential" + "# Swept Langmuir Analysis: Floating Potential\n", + "\n", + "This notebook covers the use of the [**find_floating_potential()**](../../../api/plasmapy.analysis.swept_langmuir.floating_potential.find_floating_potential.rst#find-floating-potential) function to detering the floating potential from a swept Langmuir trace." ] }, { From afc5cd19bbc6cc14f3cc263819b0b7a712ad73be Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 25 Sep 2020 12:36:31 -0700 Subject: [PATCH 110/521] fix typos --- .../analysis/swept_langmuir/find_floating_potential.ipynb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb b/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb index a479324d5a..a63837e07b 100644 --- a/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb +++ b/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb @@ -100,7 +100,7 @@ "source": [ "## Calculate the Floating Potential\n", "\n", - "Below we'll compute the floaing potential using the default fitting behavior (`fit_type=\"exponential\"`) and a linear fit (`fit_type=\"linear\"`)." + "Below we'll compute the floating potential using the default fitting behavior (`fit_type=\"exponential\"`) and a linear fit (`fit_type=\"linear\"`)." ] }, { @@ -185,7 +185,7 @@ "- `results[3]` = `results.func` = the resulting fitted function\n", "\n", " - `results.func` is a callable representation of the fitted function `I = results.func(V)`.\n", - " - `resulst.func` is an instance of a sub-class of `AbstractFitFunction`. ([**FitFuction** classes](../../../api_static/plasmapy.analysis.fit_functions.rst))\n", + " - `resulst.func` is an instance of a sub-class of `AbstractFitFunction`. ([FitFuction classes](../../../api_static/plasmapy.analysis.fit_functions.rst))\n", " - Since `results.func` is a class instance, there are many other attribures available. For example,\n", " - `results.func.parameters` is a named tuple of the fitted parameters\n", " - `results.func.parameters_err` is a named tuple of the fitted parameter errors\n", From eac8ed2f639ffcf1382f25a2f9a898290d189cc0 Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 25 Sep 2020 12:37:15 -0700 Subject: [PATCH 111/521] reword sections of docstring to improve readability/clarity --- .../swept_langmuir/floating_potential.py | 57 ++++++++++--------- 1 file changed, 30 insertions(+), 27 deletions(-) diff --git a/plasmapy/analysis/swept_langmuir/floating_potential.py b/plasmapy/analysis/swept_langmuir/floating_potential.py index 6b93b9d8a9..b11f9c5ae7 100644 --- a/plasmapy/analysis/swept_langmuir/floating_potential.py +++ b/plasmapy/analysis/swept_langmuir/floating_potential.py @@ -29,22 +29,23 @@ def find_floating_potential( **How it works** - #. The current array ``current`` is scanned for all points equal to zero and + 1. The current array ``current`` is scanned for all points equal to zero and point pairs that straddle :math:`I = 0`. This forms an array of "crossing-points." - #. The crossing-points are then grouped into "crossing-islands" in based on + 2. The crossing-points are then grouped into "crossing-islands" in based on the ``threshold`` keyword. - A new island is formed when a successive crossing-point is more (index) steps away from the previous crossing-point than allowed by ``threshold``. - - If multiple crossing-islands are identified, then the total span of all - crossing-islands is compared to ``min_points``. If the span is greater - than ``min_points`` then the function is incapable of identifying - :math:`V_f` and will return `numpy.nan` values; otherwise, the span - will form one larger crossing-island. + - If multiple crossing-islands are identified, then the span from the + first point in the first island to the last point in the last island is + compared to ``min_points``. If the span is less than or equal to + ``min_points``, then that span is taken as one larger crossing-island + for the fit; otherwise, the function is incapable of identifying + :math:`V_f` and will return `numpy.nan` values. - #. To calculate the floating potential... + 3. To calculate the floating potential... - If the crossing-island contains less points than ``min_points``, then each side of the crossing-island is equally padded with the nearest @@ -58,11 +59,11 @@ def find_floating_potential( voltage: ~numpy.ndarray 1-D numpy array of monotonically ascending/descending probe biases - (in volts) + (should be in volts) current: ~numpy.ndarray - 1-D numpy array of probe current (in amperes) corresponding to the - :data:`voltage` array + 1-D numpy array of probe current (should be in amperes) corresponding + to the :data:`voltage` array threshold: positive, non-zero `int` Max allowed index distance between crossing-points before a new @@ -71,8 +72,9 @@ def find_floating_potential( they are within 5 index steps of each other. (Default: 1) min_points: positive `int` or `float` - Specifies the minimum number of points required for the fit to be - applied to. + Minimum number of data points required for the fitting to be applied to. + See **How it works** above for additional details. The following list + specifies the optional values: - ``min_points = None`` (Default) The larger of 5 and ``factor * array_size`` is taken, where ``array_size`` is the size of @@ -84,9 +86,9 @@ def find_floating_potential( ``min_points * array_size``. fit_type: str - The type of curve to be fitted to the Langmuir trace. There are two - types of curves ``"linear"`` and ``"exponential"`` (Default). These - specified which `FitFunction` class should be applied to the trace. + The type of curve to be fitted to the Langmuir trace, ``"linear"`` or + ``"exponential"`` (Default). This selects which `FitFunction` class + should be applied to the trace. +-------------+----------------------------------------------------------+ | linear | `~plasmapy.analysis.fit_functions.Linear` | @@ -97,19 +99,20 @@ def find_floating_potential( Returns ------- vf: `float` or `numpy.nan` - The calculated floating potential (in volts). Returns `numpy.nan` if the - floating potential can not be determined. How :math:`V_f` is calculated - depends on the fit function. This is described in the `root_solve()` - method of the relevant fit function (e.g. the + The calculated floating potential (same units as the `voltage` array). + Returns `numpy.nan` if the floating potential can not be determined. + How :math:`V_f` is calculated depends on the fit function. This is + described in the `root_solve()` method of the relevant fit function + (e.g. the :meth:`~plasmapy.analysis.fit_functions.ExponentialPlusOffset.root_solve` - method of - `~plasmapy.analysis.fit_functions.ExponentialPlusOffset`). + method of `~plasmapy.analysis.fit_functions.ExponentialPlusOffset`). vf_err: `float` or `numpy.nan` - The error associated with the floating potential calculation (in volts). - Returns `numpy.nan` if the floating potential can not be determined. - Like :math:`V_f`:, the calculation depends on the applied fit function. - The `rood_solve()` method also describes how this is calculated. + The uncertainty associated with the floating potential calculation + (units same as `vf`). Returns `numpy.nan` if the floating potential + can not be determined. Like :math:`V_f`:, the calculation depends on + the applied fit function. The `root_solve()` method also describes + how this is calculated. rsq: `float` The coefficient of determination (r-squared) value of the fit. See the @@ -120,7 +123,7 @@ def find_floating_potential( `~plasmapy.analysis.fit_functions.ExponentialPlusOffset`). func: sub-class of `~plasmapy.analysis.fit_functions.AbstractFitFunction` - The callable function :math:`f(x)` repressing the fit and its results. + The callable function :math:`f(x)` representing the fit and its results. islands: `List[slice]` List of `slice` objects representing the indices of the identified From a7cb308d210b28ecf13f45440a8b339c99a9ea80 Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 25 Sep 2020 12:38:33 -0700 Subject: [PATCH 112/521] rename dict fit_funcs -> _settings; instantiate fit functions at time of selection and not in _settings --- plasmapy/analysis/swept_langmuir/floating_potential.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/plasmapy/analysis/swept_langmuir/floating_potential.py b/plasmapy/analysis/swept_langmuir/floating_potential.py index b11f9c5ae7..0386207ee6 100644 --- a/plasmapy/analysis/swept_langmuir/floating_potential.py +++ b/plasmapy/analysis/swept_langmuir/floating_potential.py @@ -143,19 +143,19 @@ def find_floating_potential( indices=None )._asdict() - fit_funcs = { + _settings = { "linear": { - "func": ffuncs.Linear(), + "func": ffuncs.Linear, "min_point_factor": 0.1, }, "exponential": { - "func": ffuncs.ExponentialPlusOffset(), + "func": ffuncs.ExponentialPlusOffset, "min_point_factor": 0.2, }, } try: - min_point_factor = fit_funcs[fit_type]["min_point_factor"] - fit_func = fit_funcs[fit_type]["func"] + min_point_factor = _settings[fit_type]["min_point_factor"] + fit_func = _settings[fit_type]["func"]() rtn["func"] = fit_func except KeyError: raise KeyError( From 9f074bc02cf309bd72ca7e6f23978df6cea7306b Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 25 Sep 2020 12:39:28 -0700 Subject: [PATCH 113/521] speed improvements by replacing instance of np.where(conditional, True, False) --- plasmapy/analysis/swept_langmuir/floating_potential.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/plasmapy/analysis/swept_langmuir/floating_potential.py b/plasmapy/analysis/swept_langmuir/floating_potential.py index 0386207ee6..89fd4bf4a6 100644 --- a/plasmapy/analysis/swept_langmuir/floating_potential.py +++ b/plasmapy/analysis/swept_langmuir/floating_potential.py @@ -200,15 +200,15 @@ def find_floating_potential( f"greater than or equal to 0.") # find possible crossing points (cp) - lower_vals = np.where(current <= 0, True, False) - upper_vals = np.where(0 <= current, True, False) + lower_vals = current <= 0 + upper_vals = 0 <= current cp_exact = np.logical_and(lower_vals, upper_vals).nonzero()[0] cp_low2high = np.logical_and(np.roll(lower_vals, 1), upper_vals).nonzero()[0] cp_high2low = np.logical_and(np.roll(lower_vals, -1), upper_vals).nonzero()[0] # adjust for array wrapping cause by np.roll - cp_low2high = cp_low2high[np.where(cp_low2high != 0, True, False)] - cp_high2low = cp_high2low[np.where(cp_high2low != current.size - 1, True, False)] + cp_low2high = cp_low2high[cp_low2high != 0] + cp_high2low = cp_high2low[cp_high2low != current.size - 1] # collect all candidates cp_candidates = np.concatenate(( From 896b5901ee8f22eca6ab492077d43ccec7dbf51b Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 25 Sep 2020 12:40:49 -0700 Subject: [PATCH 114/521] only allow kwarg threshold be an integer; define threshold = 1 in not an int >= 1 --- plasmapy/analysis/swept_langmuir/floating_potential.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/plasmapy/analysis/swept_langmuir/floating_potential.py b/plasmapy/analysis/swept_langmuir/floating_potential.py index 89fd4bf4a6..b5099b45e0 100644 --- a/plasmapy/analysis/swept_langmuir/floating_potential.py +++ b/plasmapy/analysis/swept_langmuir/floating_potential.py @@ -176,13 +176,14 @@ def find_floating_potential( return FloatingPotentialResults(**rtn) # condition kwarg threshold - if isinstance(threshold, (int, float)): - threshold = int(np.round(threshold)) + if isinstance(threshold, (int, np.integer)): if threshold < 1: + threshold = 1 warn(f"threshold ({threshold}) is less than 1 and needs to be" f" an int >= 1, using a value of 1") - threshold = 1 + else: + threshold = 1 warn(f"threshold is NOT a integer >= 1, using a value of 1") # condition min_points From ecc3d50142f4bb4c3f90a26f24acf78d0ad8d03f Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 25 Sep 2020 12:41:12 -0700 Subject: [PATCH 115/521] improve wording of warning about no floating potential --- plasmapy/analysis/swept_langmuir/floating_potential.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plasmapy/analysis/swept_langmuir/floating_potential.py b/plasmapy/analysis/swept_langmuir/floating_potential.py index b5099b45e0..19d4db2c4f 100644 --- a/plasmapy/analysis/swept_langmuir/floating_potential.py +++ b/plasmapy/analysis/swept_langmuir/floating_potential.py @@ -164,7 +164,8 @@ def find_floating_potential( ) if current.min() > 0.0 or current.max() < 0: - warn("The Langmuir sweep has no floating potential.") + warn("The swept Langmuir trace never crosses 'current = 0', floating " + "potential does not exist.") return FloatingPotentialResults(**rtn) From a3dd8670da639bd483c6f139ca876c343de59746 Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 25 Sep 2020 12:50:32 -0700 Subject: [PATCH 116/521] in docstrings and descriptions replace wording of "error" with "uncertainty" --- .../find_floating_potential.ipynb | 4 +- plasmapy/analysis/fit_functions.py | 47 ++++++++++--------- 2 files changed, 26 insertions(+), 25 deletions(-) diff --git a/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb b/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb index a63837e07b..08f60ede63 100644 --- a/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb +++ b/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb @@ -134,7 +134,7 @@ "\n", "The `find_floating_potential()` returns a six element named tuple, where...\n", "\n", - "- `results[0]` = `results.vf` = the determined floating potential (in volts)\n" + "- `results[0]` = `results.vf` = the determined floating potential (same units as the pass `voltage` array)\n" ] }, { @@ -150,7 +150,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "- `results[1]` = `results.vf_err` = the associated error (in volts)" + "- `results[1]` = `results.vf_err` = the associated uncertainty in the $V_F$ calculation (same units as `results.vf`)" ] }, { diff --git a/plasmapy/analysis/fit_functions.py b/plasmapy/analysis/fit_functions.py index 2f7219f609..92a00cce7b 100644 --- a/plasmapy/analysis/fit_functions.py +++ b/plasmapy/analysis/fit_functions.py @@ -55,8 +55,8 @@ def __call__(self, x, x_err=None, reterr=False): size one or equal to the size of `x`. reterr: bool, optional - (Default: `False`) If `True`, return an array of errors associated - with the calculated independent variables + (Default: `False`) If `True`, return an array of uncertainties + associated with the calculated independent variables Returns ------- @@ -65,7 +65,7 @@ def __call__(self, x, x_err=None, reterr=False): variables :math:`x`. y_err: `numpy.ndarray` - Errors associated with the calculated dependent variables + Uncertainties associated with the calculated dependent variables :math:`\\delta y` """ if not isinstance(x, np.ndarray): @@ -111,8 +111,8 @@ def _func(self, x, *args): @abstractmethod def _func_err(self, x, y, x_err=None): """ - Calculate dependent variable errors :math:`\\delta y` for dependent - variables :math:`y=f(x)`. + Calculate dependent variable uncertainties :math:`\\delta y` for + dependent variables :math:`y=f(x)`. Parameters ---------- @@ -129,8 +129,8 @@ def _func_err(self, x, y, x_err=None): Returns ------- `numpy.ndarray`: - The calculated errors of the dependent variables of the independent - variables `x`. + The calculated uncertainties of the dependent variables of the + independent variables `x`. """ raise NotImplementedError @@ -210,9 +210,10 @@ def root_solve(self, x0, **kwargs): unsuccessful call). x_err: `~numpy.ndarray` - The error associated with the root calculation. **Currently this - returns an array of** `numpy.nan` **values equal in shape to** - `x` **, since there is no determined way to calculate the errors.** + The uncertainty associated with the root calculation. **Currently + this returns an array of** `numpy.nan` **values equal in shape to** + `x` **, since there is no determined way to calculate the + uncertaintyes.** Notes ----- @@ -351,8 +352,8 @@ class Exponential(AbstractFitFunction): where :math:`A` and :math:`\\alpha` are the real constants to be fitted and :math:`x` is the independent variable. :math:`\\delta A`, - :math:`\\delta \\alpha`, and :math:`\\delta x` are the respective errors for - :math:`A`, :math:`\\alpha`, and :math:`x`. + :math:`\\delta \\alpha`, and :math:`\\delta x` are the respective + uncertainties for :math:`A`, :math:`\\alpha`, and :math:`x`. """ _parameter_names = ("a", "alpha") @@ -404,7 +405,7 @@ def root_solve(self, *args, **kwargs): The root value for the given fit :attr:`parameters`. err: float - The error in the calculated root for the given fit + The uncertainty in the calculated root for the given fit :attr:`parameters` and :attr:`parameters_err`. """ @@ -423,7 +424,7 @@ class Linear(AbstractFitFunction): where :math:`m` and :math:`b` are real constants to be fitted and :math:`x` is the independent variable. :math:`\\delta m`, :math:`\\delta b`, and - :math:`\\delta x` are the respective errors for :math:`m`, :math:`b`, + :math:`\\delta x` are the respective uncertainties for :math:`m`, :math:`b`, and :math:`x`. """ @@ -464,8 +465,8 @@ def _func(self, x, m, b): def _func_err(self, x, y, x_err=None): """ - Calculate dependent variable errors :math:`\\delta y` for dependent - variables :math:`y=f(x)`. + Calculate dependent variable uncertainties :math:`\\delta y` for + dependent variables :math:`y=f(x)`. .. math:: @@ -479,8 +480,8 @@ def _func_err(self, x, y, x_err=None): Returns ------- `numpy.ndarray`: - The calculated errors of the dependent variables of the independent - variables `x`. + The calculated uncertainty of the dependent variables of the + independent variables `x`. """ m, b = self.parameters m_err, b_err = self.parameters_err @@ -536,7 +537,7 @@ def root_solve(self, *args, **kwargs): The root value for the given fit :attr:`parameters`. err: float - The error in the calculated root for the given fit + The uncertainty in the calculated root for the given fit :attr:`parameters` and :attr:`parameters_err`. """ m, b = self.parameters @@ -605,8 +606,8 @@ class ExponentialPlusLinear(AbstractFitFunction): where :math:`A`, :math:`\\alpha`, :math:`m`, and :math:`b` are the real constants to be fitted and :math:`x` is the independent variable. :math:`\\delta A`, :math:`\\delta \\alpha`, :math:`\\delta m`, :math:`\\delta b`, - and :math:`\\delta x` are the respective errors for :math:`A`, :math:`\\alpha`, - :math:`m`, and :math:`b`, and :math:`x`. + and :math:`\\delta x` are the respective uncertainties for :math:`A`, + :math:`\\alpha`, :math:`m`, and :math:`b`, and :math:`x`. """ _parameter_names = ("a", "alpha", "m", "b") @@ -680,7 +681,7 @@ class ExponentialPlusOffset(AbstractFitFunction): where :math:`A`, :math:`\\alpha`, and :math:`b` are the real constants to be fitted and :math:`x` is the independent variable. :math:`\\delta A`, :math:`\\delta \\alpha`, :math:`\\delta b`, and :math:`\\delta x` are the - respective errors for :math:`A`, :math:`\\alpha`, and :math:`b`, and + respective uncertainties for :math:`A`, :math:`\\alpha`, and :math:`b`, and :math:`x`. """ @@ -754,7 +755,7 @@ def root_solve(self, *args, **kwargs): The root value for the given fit :attr:`parameters`. err: float - The error in the calculated root for the given fit + The uncertainty in the calculated root for the given fit :attr:`parameters` and :attr:`parameters_err`. """ a, alpha, b = self.parameters From 284322d16e588bd875f60faa98d8e85a2b4553c3 Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 25 Sep 2020 13:18:39 -0700 Subject: [PATCH 117/521] make all warnings a PlasmaPyWarning (vs. UserWarning) --- .../analysis/swept_langmuir/floating_potential.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/plasmapy/analysis/swept_langmuir/floating_potential.py b/plasmapy/analysis/swept_langmuir/floating_potential.py index 19d4db2c4f..45699e4d7f 100644 --- a/plasmapy/analysis/swept_langmuir/floating_potential.py +++ b/plasmapy/analysis/swept_langmuir/floating_potential.py @@ -8,6 +8,7 @@ from typing import Union from plasmapy.analysis import fit_functions as ffuncs +from plasmapy.utils.exceptions import PlasmaPyWarning FloatingPotentialResults = namedtuple( "FloatingPotentialResults", @@ -165,14 +166,15 @@ def find_floating_potential( if current.min() > 0.0 or current.max() < 0: warn("The swept Langmuir trace never crosses 'current = 0', floating " - "potential does not exist.") + "potential does not exist.", PlasmaPyWarning) return FloatingPotentialResults(**rtn) # check voltage is monotonically increasing/decreasing voltage_diff = np.diff(voltage) if not (np.all(voltage_diff >= 0) or np.all(voltage_diff <= 0)): - warn("The voltage array is not monotonically increasing or decreasing.") + warn("The voltage array is not monotonically increasing or decreasing.", + PlasmaPyWarning) return FloatingPotentialResults(**rtn) @@ -181,11 +183,11 @@ def find_floating_potential( if threshold < 1: threshold = 1 warn(f"threshold ({threshold}) is less than 1 and needs to be" - f" an int >= 1, using a value of 1") + f" an int >= 1, using a value of 1", PlasmaPyWarning) else: threshold = 1 - warn(f"threshold is NOT a integer >= 1, using a value of 1") + warn(f"threshold is NOT a integer >= 1, using a value of 1", PlasmaPyWarning) # condition min_points if min_points is None: @@ -251,7 +253,7 @@ def find_floating_potential( if isl_window > min_points: warn(f"Unable to determine floating potential, Langmuir sweep has " f"{n_islands} crossing-islands. Try adjusting keyword 'threshold' " - f"and/or smooth the current.") + f"and/or smooth the current.", PlasmaPyWarning) return FloatingPotentialResults(**rtn) @@ -292,7 +294,7 @@ def find_floating_potential( if (istop - istart + 1) < min_points: warn(f"The number of elements in the current array " f"({istop - istart + 1}) is less than 'min_points' " - f"({min_points}).") + f"({min_points}).", PlasmaPyWarning) # Perform Linear Regression Fit volt_sub = voltage[istart:istop + 1] From 2c16af794deb6ec4bb4e41eca649870e908ae490 Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 25 Sep 2020 17:08:12 -0700 Subject: [PATCH 118/521] create plasmapy/analysis/swept_langmuir/helpers.py file with check_sweep() function. --- plasmapy/analysis/swept_langmuir/helpers.py | 72 +++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 plasmapy/analysis/swept_langmuir/helpers.py diff --git a/plasmapy/analysis/swept_langmuir/helpers.py b/plasmapy/analysis/swept_langmuir/helpers.py new file mode 100644 index 0000000000..d42837102a --- /dev/null +++ b/plasmapy/analysis/swept_langmuir/helpers.py @@ -0,0 +1,72 @@ +"""Helper functions for analyzing swept Langmuir traces.""" +__all__ = ["check_sweep"] + +import numpy as np + + +def check_sweep(voltage, current) -> None: + """ + Function for checking that the voltage and current arrays are properly formated + for analysis by `plasmapy.analysis.swept_langmuir`. + + Parameters + ---------- + voltage: `numpy.ndarray` + 1D `numpy.ndarray` representing the voltage of the swept Langmuir trace. + Voltage should be monotonically increasing. + + current: `numpy.ndarray` + 1D `numpy.ndarray` representing the current of the swept Langmuir trace. + Values should start from a negative ion-saturation current and increase + to a positive electron-saturation current. + + Raises + ------ + `TypeError` + If either the `voltage` or `current` arrays are not instances of a `numpy` + array. + + `ValueError` + If either the `voltage` or `current` arrays are not 1D. + + If the `voltage` array is not monotonically increasing. + + If the `current` array never cross zero (i.e. has not floating potential). + + If the `current` array does not start form a negative ion-saturation current + and increases to a positive electron-saturation current. + + """ + # examine voltage array + if not isinstance(voltage, np.ndarray): + raise TypeError( + f"Expected 1D numpy array for voltage, but got {type(voltage)}", + ) + elif voltage.ndim != 1: + raise ValueError( + f"Expected 1D numpy array for voltage, but got array with " + f"{voltage.ndim} dimensions.", + ) + elif not np.all(np.diff(voltage) >= 0): + raise ValueError(f"The voltage array is not monotonically increasing.") + + # examine current array + if not isinstance(current, np.ndarray): + raise TypeError( + f"Expected 1D numpy array for current, but got {type(current)}", + ) + elif current.ndim != 1: + raise ValueError( + f"Expected 1D numpy array for current, but got array with " + f"{current.ndim} dimensions.", + ) + elif current.min() > 0.0 or current.max() < 0: + raise ValueError( + "Invalid swept Langmuir trace, the current never crosses zero " + "'current = 0'." + ) + elif current[0] > 0.0 or current[-1] < 0.0: + raise ValueError( + "The current array needs to start from a negative ion-saturation current" + " to a positive electron-saturation current." + ) From 9430502b89ac8843a6d2b0bd819175fb38b870fa Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 25 Sep 2020 17:08:55 -0700 Subject: [PATCH 119/521] add check_sweep() to plasmapy/analysis/swept_langmuir/__init__.py --- plasmapy/analysis/swept_langmuir/__init__.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/plasmapy/analysis/swept_langmuir/__init__.py b/plasmapy/analysis/swept_langmuir/__init__.py index 4c3817f25a..aaeeebdf06 100644 --- a/plasmapy/analysis/swept_langmuir/__init__.py +++ b/plasmapy/analysis/swept_langmuir/__init__.py @@ -1,6 +1,7 @@ """ Sub-Package containing routines for analyzing swept Langmuir probe traces. """ -__all__ = ["find_floating_potential"] +__all__ = ["check_sweep", "find_floating_potential"] -from plasmapy.analysis.swept_langmuir.floating_potential import find_floating_potential +from .floating_potential import find_floating_potential +from .helpers import check_sweep From 81537f6f0db218994c9d7c245bc536341775ddf2 Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 25 Sep 2020 17:14:02 -0700 Subject: [PATCH 120/521] add plasmapy.analysis.swept_langmuir.helpers and check_sweep() to documentaiton --- docs/ad/analysis/swept_langmuir.rst | 1 + .../plasmapy.analysis.swept_langmuir.helpers.rst | 10 ++++++++++ 2 files changed, 11 insertions(+) create mode 100644 docs/api_static/plasmapy.analysis.swept_langmuir.helpers.rst diff --git a/docs/ad/analysis/swept_langmuir.rst b/docs/ad/analysis/swept_langmuir.rst index e03c30447a..8851c8fcc0 100644 --- a/docs/ad/analysis/swept_langmuir.rst +++ b/docs/ad/analysis/swept_langmuir.rst @@ -25,6 +25,7 @@ Sub-Packages & Modules .. autosummary:: floating_potential + helpers .. automodapi:: plasmapy.analysis.swept_langmuir :no-main-docstr: diff --git a/docs/api_static/plasmapy.analysis.swept_langmuir.helpers.rst b/docs/api_static/plasmapy.analysis.swept_langmuir.helpers.rst new file mode 100644 index 0000000000..1cdd4d43ae --- /dev/null +++ b/docs/api_static/plasmapy.analysis.swept_langmuir.helpers.rst @@ -0,0 +1,10 @@ +:orphan: + +`plasmapy.analysis.swept_langmuir.helpers` +===================================================== + +.. currentmodule:: plasmapy.analysis.swept_langmuir.helpers + +.. automodapi:: plasmapy.analysis.swept_langmuir.helpers + :include-all-objects: + :no-heading: From 0e6d93f6f0f407caaf1ba7ab00989a84fc20a044 Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 25 Sep 2020 17:19:58 -0700 Subject: [PATCH 121/521] add typing --- plasmapy/analysis/swept_langmuir/helpers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plasmapy/analysis/swept_langmuir/helpers.py b/plasmapy/analysis/swept_langmuir/helpers.py index d42837102a..2d1b0b6b23 100644 --- a/plasmapy/analysis/swept_langmuir/helpers.py +++ b/plasmapy/analysis/swept_langmuir/helpers.py @@ -4,7 +4,7 @@ import numpy as np -def check_sweep(voltage, current) -> None: +def check_sweep(voltage: np.ndarray, current: np.ndarray) -> None: """ Function for checking that the voltage and current arrays are properly formated for analysis by `plasmapy.analysis.swept_langmuir`. From c21c48bfc7732bd3993cc5251dc6ad6533ba6ae8 Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 25 Sep 2020 17:20:14 -0700 Subject: [PATCH 122/521] incorporate check_sweep() --- .../swept_langmuir/floating_potential.py | 22 +++++++------------ 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/plasmapy/analysis/swept_langmuir/floating_potential.py b/plasmapy/analysis/swept_langmuir/floating_potential.py index 45699e4d7f..8e31afd022 100644 --- a/plasmapy/analysis/swept_langmuir/floating_potential.py +++ b/plasmapy/analysis/swept_langmuir/floating_potential.py @@ -8,6 +8,7 @@ from typing import Union from plasmapy.analysis import fit_functions as ffuncs +from plasmapy.analysis.swept_langmuir.helpers import check_sweep from plasmapy.utils.exceptions import PlasmaPyWarning FloatingPotentialResults = namedtuple( @@ -58,11 +59,11 @@ def find_floating_potential( Parameters ---------- - voltage: ~numpy.ndarray + voltage: `numpy.ndarray` 1-D numpy array of monotonically ascending/descending probe biases (should be in volts) - current: ~numpy.ndarray + current: `numpy.ndarray` 1-D numpy array of probe current (should be in amperes) corresponding to the :data:`voltage` array @@ -164,18 +165,11 @@ def find_floating_potential( f"Examine kwarg 'fit_curve' for valid options." ) - if current.min() > 0.0 or current.max() < 0: - warn("The swept Langmuir trace never crosses 'current = 0', floating " - "potential does not exist.", PlasmaPyWarning) - - return FloatingPotentialResults(**rtn) - - # check voltage is monotonically increasing/decreasing - voltage_diff = np.diff(voltage) - if not (np.all(voltage_diff >= 0) or np.all(voltage_diff <= 0)): - warn("The voltage array is not monotonically increasing or decreasing.", - PlasmaPyWarning) - + # check voltage and current arrays + try: + check_sweep(voltage, current) + except (TypeError, ValueError): + # did not pass checks return FloatingPotentialResults(**rtn) # condition kwarg threshold From ceabd4abbbbd8229556f6359408d765af47e818a Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 25 Sep 2020 17:33:02 -0700 Subject: [PATCH 123/521] missed period --- plasmapy/analysis/swept_langmuir/helpers.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plasmapy/analysis/swept_langmuir/helpers.py b/plasmapy/analysis/swept_langmuir/helpers.py index 2d1b0b6b23..e9b5571d8e 100644 --- a/plasmapy/analysis/swept_langmuir/helpers.py +++ b/plasmapy/analysis/swept_langmuir/helpers.py @@ -40,7 +40,7 @@ def check_sweep(voltage: np.ndarray, current: np.ndarray) -> None: # examine voltage array if not isinstance(voltage, np.ndarray): raise TypeError( - f"Expected 1D numpy array for voltage, but got {type(voltage)}", + f"Expected 1D numpy array for voltage, but got {type(voltage)}.", ) elif voltage.ndim != 1: raise ValueError( @@ -53,7 +53,7 @@ def check_sweep(voltage: np.ndarray, current: np.ndarray) -> None: # examine current array if not isinstance(current, np.ndarray): raise TypeError( - f"Expected 1D numpy array for current, but got {type(current)}", + f"Expected 1D numpy array for current, but got {type(current)}.", ) elif current.ndim != 1: raise ValueError( From 47a75fe346a1721315c96e1df76518d235563fc0 Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 25 Sep 2020 17:33:23 -0700 Subject: [PATCH 124/521] warn with error message from check_sweep() --- plasmapy/analysis/swept_langmuir/floating_potential.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plasmapy/analysis/swept_langmuir/floating_potential.py b/plasmapy/analysis/swept_langmuir/floating_potential.py index 8e31afd022..d0e502d133 100644 --- a/plasmapy/analysis/swept_langmuir/floating_potential.py +++ b/plasmapy/analysis/swept_langmuir/floating_potential.py @@ -168,8 +168,9 @@ def find_floating_potential( # check voltage and current arrays try: check_sweep(voltage, current) - except (TypeError, ValueError): + except (TypeError, ValueError) as err: # did not pass checks + warn(err.args[0], PlasmaPyWarning) return FloatingPotentialResults(**rtn) # condition kwarg threshold From abb93d4959a2af36859fd830c7ed68b08f544312 Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 1 Oct 2020 14:55:19 -0700 Subject: [PATCH 125/521] move instantiation of class variables that are really instance variables into __init__ --- plasmapy/analysis/fit_functions.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/plasmapy/analysis/fit_functions.py b/plasmapy/analysis/fit_functions.py index 92a00cce7b..10cdf2fc6d 100644 --- a/plasmapy/analysis/fit_functions.py +++ b/plasmapy/analysis/fit_functions.py @@ -26,12 +26,8 @@ class AbstractFitFunction(ABC): assisting in fitting curves to swept Langmuir data. """ - _parameter_names = () # type: Tuple[str, ...] - _parameters = None # type: Union[None, Tuple[Any, ...]] - _parameters_err = None # type: Union[None, Tuple[Any, ...]] - _covariance_matrix = None - _rsq = None - _curve_fit_results = None + _parameter_names = NotImplemented # type: Tuple[str, ...] + def __init__(self): self.FitParamTuple = namedtuple("FitParamTuple", self._parameter_names) @@ -41,6 +37,12 @@ def __init__(self): the tuple field names. """ + self._parameters = None # type: Union[None, Tuple[Any, ...]] + self._parameters_err = None # type: Union[None, Tuple[Any, ...]] + self._covariance_matrix = None + self._rsq = None + self._curve_fit_results = None + def __call__(self, x, x_err=None, reterr=False): """ Direct call of the fit function :math:`f(x)``. From 11c67d8fa5d14fe228d0a63fd4f0627f977bc04e Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 1 Oct 2020 15:22:34 -0700 Subject: [PATCH 126/521] rename _func -> func and make staticmethod and expand docstring --- plasmapy/analysis/fit_functions.py | 39 ++++++++++++++++++++---------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/plasmapy/analysis/fit_functions.py b/plasmapy/analysis/fit_functions.py index 10cdf2fc6d..694687d866 100644 --- a/plasmapy/analysis/fit_functions.py +++ b/plasmapy/analysis/fit_functions.py @@ -91,15 +91,24 @@ def __repr__(self): def __str__(self): return f"Unspecified f(x)" + @staticmethod @abstractmethod - def _func(self, x, *args): + def func(x, *args): """ - The fit function. + The fit function. This signature of the function must first take the + independent variable followed by the parameters to be fitted as + separate arguments. + + When sub-classing the definition should look something like:: + + def func(x, a, b, c): + return a * x ** 2 + b * x + c Parameters ---------- x: array_like Independent variables to be passed to the fit function. + *args The parameters that will be adjusted to make the fit. @@ -231,7 +240,8 @@ def root_solve(self, x0, **kwargs): ... def latex_str(self) -> str: ... return f"m \\, x + b" ... - ... def _func(self, x, m, b): + ... @staticmethod + ... def func(x, m, b): ... return m * x + b ... ... def _func_err(self, x, y, x_err=None): @@ -264,7 +274,7 @@ def root_solve(self, x0, **kwargs): """ kwargs["args"] = self.parameters - results = fsolve(self._func, x0, **kwargs) + results = fsolve(self.func, x0, **kwargs) if isinstance(results, tuple): results = results[0] @@ -325,14 +335,14 @@ def curve_fit(self, xdata, ydata, **kwargs) -> None: if covariance of the parameters can not be estimated. """ - popt, pcov = curve_fit(self._func, xdata, ydata, **kwargs) + popt, pcov = curve_fit(self.func, xdata, ydata, **kwargs) self._curve_fit_results = (popt, pcov) self.parameters = tuple(popt.tolist()) self.parameters_err = tuple(np.sqrt(np.diag(pcov)).tolist()) # calc rsq # rsq = 1 - (ss_res / ss_tot) - residuals = ydata - self._func(xdata, *self.parameters) + residuals = ydata - self.func(xdata, *self.params) ss_res = np.sum(residuals ** 2) ss_tot = np.sum((ydata - np.mean(ydata)) ** 2) self._rsq = 1 - (ss_res / ss_tot) @@ -362,7 +372,8 @@ class Exponential(AbstractFitFunction): def __str__(self): return f"f(x) = A exp(alpha x)" - def _func(self, x, a, alpha): + @staticmethod + def func(x, a, alpha): return a * np.exp(alpha * x) def _func_err(self, x, y, x_err=None): @@ -435,7 +446,8 @@ class Linear(AbstractFitFunction): def __str__(self): return f"f(x) = m x + b" - def _func(self, x, m, b): + @staticmethod + def func(x, m, b): """ The fit function, a linear function. @@ -644,9 +656,9 @@ def parameters_err(self, val) -> None: ) self._linear.parameters_err = (self.parameters_err.m, self.parameters_err.b) - def _func(self, x, a, alpha, m , b): - exp_term = self._exponential._func(x, a, alpha) - lin_term = self._linear._func(x, m, b) + def func(self, x, a, alpha, m, b): + exp_term = self._exponential.func(x, a, alpha) + lin_term = self._linear.func(x, m, b) return exp_term + lin_term def _func_err(self, x, y, x_err=None): @@ -720,8 +732,9 @@ def parameters_err(self, val) -> None: self.parameters_err.b, ) - def _func(self, x, a, alpha, b): - return self._explin._func(x, a, alpha, 0.0, b) + def func(self, x, a, alpha, b): + return self._explin.func(x, a, alpha, 0.0, b) + def _func_err(self, x, y, x_err=None): _, err = self._explin(x, x_err=x_err, reterr=True) From 7e881c8d758a93e14bbeb6330bdc8bfcf76f878e Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 1 Oct 2020 15:26:50 -0700 Subject: [PATCH 127/521] rename _func_err -> func_err; add kwarg `rety` to signature and drop arg `y`; rename _parameters (parameters) -> _params (params) --- plasmapy/analysis/fit_functions.py | 132 +++++++++++++++++------------ 1 file changed, 80 insertions(+), 52 deletions(-) diff --git a/plasmapy/analysis/fit_functions.py b/plasmapy/analysis/fit_functions.py index 694687d866..fee5519da3 100644 --- a/plasmapy/analysis/fit_functions.py +++ b/plasmapy/analysis/fit_functions.py @@ -32,12 +32,12 @@ class AbstractFitFunction(ABC): def __init__(self): self.FitParamTuple = namedtuple("FitParamTuple", self._parameter_names) """ - A named tuple class used for attributes :attr:`parameters` and + A named tuple class used for attributes :attr:`params` and :attr:`parameters_err`. The attribute :attr:`parameter_names` defines the tuple field names. """ - self._parameters = None # type: Union[None, Tuple[Any, ...]] + self._params = None # type: Union[None, Tuple[Any, ...]] self._parameters_err = None # type: Union[None, Tuple[Any, ...]] self._covariance_matrix = None self._rsq = None @@ -73,16 +73,17 @@ def __call__(self, x, x_err=None, reterr=False): if not isinstance(x, np.ndarray): x = np.array(x) - y = self._func(x, *self.parameters) - if reterr: try: - y_err = self._func_err(x, y, x_err=x_err) + y_err, y = self.func_err(x, x_err=x_err, rety=True) except NotImplementedError: + y = self.func(x, *self.params) y_err = np.tile(np.nan, x.shape) return y, y_err + y = self.func(x, *self.params) + return y def __repr__(self): @@ -120,7 +121,7 @@ def func(x, a, b, c): raise NotImplementedError @abstractmethod - def _func_err(self, x, y, x_err=None): + def func_err(self, x, x_err=None, rety=False): """ Calculate dependent variable uncertainties :math:`\\delta y` for dependent variables :math:`y=f(x)`. @@ -130,18 +131,24 @@ def _func_err(self, x, y, x_err=None): x: array_like Independent variables to be passed to the fit function. - y: array_like - Dependent variables associated with :math:`x`, :math:`f(x)`. - x_err: array_like, optional Errors associated with the independent variables `x`. Must be of size one or equal to the size of `x`. + rety: bool + Set `True` to also return the associated dependent variables + :math:`y = f(x)`. + Returns ------- - `numpy.ndarray`: - The calculated uncertainties of the dependent variables of the - independent variables `x`. + err: `numpy.ndarray` + The calculated uncertainties :math:`\\delta y` of the dependent + variables (:math:`y = f(x)`) of the independent variables `x`. + + y: `numpy.ndarray`, optional + (if `rety = True`) The associated dependent variables + :math:`y = f(x)`. + """ raise NotImplementedError @@ -155,19 +162,19 @@ def curve_fit_results(self): return self._curve_fit_results @property - def parameters(self) -> Union[None, tuple]: + def params(self) -> Union[None, tuple]: """The fitted parameters for the fit function.""" - if self._parameters is None: - return self._parameters + if self._params is None: + return self._params else: - return self.FitParamTuple(*self._parameters) + return self.FitParamTuple(*self._params) - @parameters.setter - def parameters(self, val) -> None: + @params.setter + def params(self, val) -> None: if isinstance(val, self.FitParamTuple): - self._parameters = tuple(val) + self._params = tuple(val) elif isinstance(val, (tuple, list)) and len(val) == len(self.parameter_names): - self._parameters = tuple(val) + self._params = tuple(val) else: raise ValueError(f"Got type {type(val)} for 'val', expecting tuple of " f"length {len(self.parameter_names)}.") @@ -244,8 +251,8 @@ def root_solve(self, x0, **kwargs): ... def func(x, m, b): ... return m * x + b ... - ... def _func_err(self, x, y, x_err=None): - ... m, b = self.parameters + ... def func_err(self, x, x_err=None, rety=False): + ... m, b = self.params ... m_err, b_err = self.parameters_err ... ... m_term = x * m_err @@ -254,12 +261,17 @@ def root_solve(self, x0, **kwargs): ... ... if x_err is not None: ... x_term = m * x_err - ... err == x_term ** 2 + ... err += x_term ** 2 + ... err = np.sqrt(err) + ... + ... if rety: + ... y = self.func(x, m, b) + ... return err, y ... - ... return np.sqrt(err) + ... return err ... >>> func = SomeFunc() - >>> func.parameters = (1., 5.) + >>> func.params = (1., 5.) >>> func.parameters_err = (0.0, 0.0) >>> roots = scipy.optimize.fsolve(func, -4., full_output=True) >>> roots @@ -273,7 +285,7 @@ def root_solve(self, x0, **kwargs): 'The solution converged.') """ - kwargs["args"] = self.parameters + kwargs["args"] = self.params results = fsolve(self.func, x0, **kwargs) if isinstance(results, tuple): results = results[0] @@ -337,7 +349,7 @@ def curve_fit(self, xdata, ydata, **kwargs) -> None: """ popt, pcov = curve_fit(self.func, xdata, ydata, **kwargs) self._curve_fit_results = (popt, pcov) - self.parameters = tuple(popt.tolist()) + self.params = tuple(popt.tolist()) self.parameters_err = tuple(np.sqrt(np.diag(pcov)).tolist()) # calc rsq @@ -376,9 +388,10 @@ def __str__(self): def func(x, a, alpha): return a * np.exp(alpha * x) - def _func_err(self, x, y, x_err=None): - a, alpha = self.parameters + def func_err(self, x, x_err=None, rety=False): + a, alpha = self.params a_err, alpha_err = self.parameters_err + y = self.func(x, a, alpha) a_term = (a_err / a) ** 2 alpha_term = (x * alpha_err) ** 2 @@ -391,6 +404,9 @@ def _func_err(self, x, y, x_err=None): err = np.abs(y) * np.sqrt(err) + if rety: + return err, y + return err @property @@ -477,7 +493,7 @@ def func(x, m, b): """ return m * x + b - def _func_err(self, x, y, x_err=None): + def func_err(self, x, x_err=None, rety=False): """ Calculate dependent variable uncertainties :math:`\\delta y` for dependent variables :math:`y=f(x)`. @@ -497,7 +513,7 @@ def _func_err(self, x, y, x_err=None): The calculated uncertainty of the dependent variables of the independent variables `x`. """ - m, b = self.parameters + m, b = self.params m_err, b_err = self.parameters_err m_term = (m_err * x) ** 2 @@ -507,8 +523,13 @@ def _func_err(self, x, y, x_err=None): if x_err is not None: x_term = (m * x_err) ** 2 err += x_term + err = np.sqrt(err) + + if rety: + y = self.func(x, m, b) + return err, y - return np.sqrt(err) + return err @property def latex_str(self) -> str: @@ -554,7 +575,7 @@ def root_solve(self, *args, **kwargs): The uncertainty in the calculated root for the given fit :attr:`parameters` and :attr:`parameters_err`. """ - m, b = self.parameters + m, b = self.params root = -b / m m_err, b_err = self.parameters_err @@ -589,7 +610,7 @@ def curve_fit(self, xdata, ydata, **kwargs) -> None: m = results[0] b = results[1] - self.parameters = (m, b) + self.params = (m, b) m_err = results[4] b_err = np.sum(xdata ** 2) - ((np.sum(xdata) ** 2) / xdata.size) @@ -641,11 +662,11 @@ def latex_str(self) -> str: lin_str = self._linear.latex_str return fr"{exp_str} + {lin_str}" - @AbstractFitFunction.parameters.setter - def parameters(self, val) -> None: - AbstractFitFunction.parameters.fset(self, val) - self._exponential.parameters = (self.parameters.a, self.parameters.alpha) - self._linear.parameters = (self.parameters.m, self.parameters.b) + @AbstractFitFunction.params.setter + def params(self, val) -> None: + AbstractFitFunction.params.fset(self, val) + self._exponential.params = (self.params.a, self.params.alpha) + self._linear.params = (self.params.m, self.params.b) @AbstractFitFunction.parameters_err.setter def parameters_err(self, val) -> None: @@ -661,8 +682,8 @@ def func(self, x, a, alpha, m, b): lin_term = self._linear.func(x, m, b) return exp_term + lin_term - def _func_err(self, x, y, x_err=None): - a, alpha, m, b = self.parameters + def func_err(self, x, x_err=None, rety=False): + a, alpha, m, b = self.params exp_y, exp_err = self._exponential(x, x_err=x_err, reterr=True) lin_y, lin_err = self._linear(x, x_err=x_err, reterr=True) @@ -671,8 +692,12 @@ def _func_err(self, x, y, x_err=None): if x_err is not None: blend_err = 2 * a * alpha * m * np.exp(alpha * x) * (x_err ** x) err += blend_err + err = np.sqrt(err) + + if rety: + return err, exp_y + lin_y - return np.sqrt(err) + return err class ExponentialPlusOffset(AbstractFitFunction): @@ -712,14 +737,14 @@ def __str__(self): def latex_str(self) -> str: return fr"A \, \exp(B \, x) + C" - @AbstractFitFunction.parameters.setter - def parameters(self, val) -> None: - AbstractFitFunction.parameters.fset(self, val) - self._explin.parameters = ( - self.parameters.a, - self.parameters.alpha, + @AbstractFitFunction.params.setter + def params(self, val) -> None: + AbstractFitFunction.params.fset(self, val) + self._explin.params = ( + self.params.a, + self.params.alpha, 0.0, - self.parameters.b, + self.params.b, ) @AbstractFitFunction.parameters_err.setter @@ -735,9 +760,12 @@ def parameters_err(self, val) -> None: def func(self, x, a, alpha, b): return self._explin.func(x, a, alpha, 0.0, b) + def func_err(self, x, x_err=None, rety=False): + y, err = self._explin(x, x_err=x_err, reterr=True) + + if rety: + return err, y - def _func_err(self, x, y, x_err=None): - _, err = self._explin(x, x_err=x_err, reterr=True) return err def root_solve(self, *args, **kwargs): @@ -773,7 +801,7 @@ def root_solve(self, *args, **kwargs): The uncertainty in the calculated root for the given fit :attr:`parameters` and :attr:`parameters_err`. """ - a, alpha, b = self.parameters + a, alpha, b = self.params a_err, b_err, c_err = self.parameters_err root = np.log(-b / a) / alpha From e0ce9c618e2fd2cddb5abeef413bf82fd72974c2 Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 1 Oct 2020 15:37:18 -0700 Subject: [PATCH 128/521] rename _parameters_err (parameters_err) -> _param_errors (param_errors) --- plasmapy/analysis/fit_functions.py | 64 +++++++++++++++--------------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/plasmapy/analysis/fit_functions.py b/plasmapy/analysis/fit_functions.py index fee5519da3..6f376cd45b 100644 --- a/plasmapy/analysis/fit_functions.py +++ b/plasmapy/analysis/fit_functions.py @@ -33,12 +33,12 @@ def __init__(self): self.FitParamTuple = namedtuple("FitParamTuple", self._parameter_names) """ A named tuple class used for attributes :attr:`params` and - :attr:`parameters_err`. The attribute :attr:`parameter_names` defines + :attr:`param_errors`. The attribute :attr:`parameter_names` defines the tuple field names. """ self._params = None # type: Union[None, Tuple[Any, ...]] - self._parameters_err = None # type: Union[None, Tuple[Any, ...]] + self._param_errors = None # type: Union[None, Tuple[Any, ...]] self._covariance_matrix = None self._rsq = None self._curve_fit_results = None @@ -180,19 +180,19 @@ def params(self, val) -> None: f"length {len(self.parameter_names)}.") @property - def parameters_err(self) -> Union[None, tuple]: + def param_errors(self) -> Union[None, tuple]: """The associated errors of the fit `parameters`.""" - if self._parameters_err is None: - return self._parameters_err + if self._param_errors is None: + return self._param_errors else: - return self.FitParamTuple(*self._parameters_err) + return self.FitParamTuple(*self._param_errors) - @parameters_err.setter - def parameters_err(self, val) -> None: + @param_errors.setter + def param_errors(self, val) -> None: if isinstance(val, self.FitParamTuple): - self._parameters_err = tuple(val) + self._param_errors = tuple(val) elif isinstance(val, (tuple, list)) and len(val) == len(self.parameter_names): - self._parameters_err = tuple(val) + self._param_errors = tuple(val) else: raise ValueError(f"Got type {type(val)} for 'val', expecting tuple of " f"length {len(self.parameter_names)}.") @@ -253,7 +253,7 @@ def root_solve(self, x0, **kwargs): ... ... def func_err(self, x, x_err=None, rety=False): ... m, b = self.params - ... m_err, b_err = self.parameters_err + ... m_err, b_err = self.param_errors ... ... m_term = x * m_err ... b_term = b_err @@ -272,7 +272,7 @@ def root_solve(self, x0, **kwargs): ... >>> func = SomeFunc() >>> func.params = (1., 5.) - >>> func.parameters_err = (0.0, 0.0) + >>> func.param_errors = (0.0, 0.0) >>> roots = scipy.optimize.fsolve(func, -4., full_output=True) >>> roots (array([-5.]), @@ -350,7 +350,7 @@ def curve_fit(self, xdata, ydata, **kwargs) -> None: popt, pcov = curve_fit(self.func, xdata, ydata, **kwargs) self._curve_fit_results = (popt, pcov) self.params = tuple(popt.tolist()) - self.parameters_err = tuple(np.sqrt(np.diag(pcov)).tolist()) + self.param_errors = tuple(np.sqrt(np.diag(pcov)).tolist()) # calc rsq # rsq = 1 - (ss_res / ss_tot) @@ -390,7 +390,7 @@ def func(x, a, alpha): def func_err(self, x, x_err=None, rety=False): a, alpha = self.params - a_err, alpha_err = self.parameters_err + a_err, alpha_err = self.param_errors y = self.func(x, a, alpha) a_term = (a_err / a) ** 2 @@ -514,7 +514,7 @@ def func_err(self, x, x_err=None, rety=False): independent variables `x`. """ m, b = self.params - m_err, b_err = self.parameters_err + m_err, b_err = self.param_errors m_term = (m_err * x) ** 2 b_term = b_err ** 2 @@ -578,7 +578,7 @@ def root_solve(self, *args, **kwargs): m, b = self.params root = -b / m - m_err, b_err = self.parameters_err + m_err, b_err = self.param_errors err = np.abs(root) * np.sqrt((m_err / m) ** 2 + (b_err / b) ** 2) return root, err @@ -615,7 +615,7 @@ def curve_fit(self, xdata, ydata, **kwargs) -> None: m_err = results[4] b_err = np.sum(xdata ** 2) - ((np.sum(xdata) ** 2) / xdata.size) b_err = m_err * np.sqrt(1.0 / b_err) - self.parameters_err = (m_err, b_err) + self.param_errors = (m_err, b_err) self._rsq = results[2] ** 2 @@ -668,14 +668,14 @@ def params(self, val) -> None: self._exponential.params = (self.params.a, self.params.alpha) self._linear.params = (self.params.m, self.params.b) - @AbstractFitFunction.parameters_err.setter - def parameters_err(self, val) -> None: - AbstractFitFunction.parameters_err.fset(self, val) - self._exponential.parameters_err = ( - self.parameters_err.a, - self.parameters_err.alpha, + @AbstractFitFunction.param_errors.setter + def param_errors(self, val) -> None: + AbstractFitFunction.param_errors.fset(self, val) + self._exponential.param_errors = ( + self.param_errors.a, + self.param_errors.alpha, ) - self._linear.parameters_err = (self.parameters_err.m, self.parameters_err.b) + self._linear.param_errors = (self.param_errors.m, self.param_errors.b) def func(self, x, a, alpha, m, b): exp_term = self._exponential.func(x, a, alpha) @@ -747,14 +747,14 @@ def params(self, val) -> None: self.params.b, ) - @AbstractFitFunction.parameters_err.setter - def parameters_err(self, val) -> None: - AbstractFitFunction.parameters_err.fset(self, val) - self._explin.parameters_err = ( - self.parameters_err.a, - self.parameters_err.alpha, + @AbstractFitFunction.param_errors.setter + def param_errors(self, val) -> None: + AbstractFitFunction.param_errors.fset(self, val) + self._explin.param_errors = ( + self.param_errors.a, + self.param_errors.alpha, 0.0, - self.parameters_err.b, + self.param_errors.b, ) def func(self, x, a, alpha, b): @@ -802,7 +802,7 @@ def root_solve(self, *args, **kwargs): :attr:`parameters` and :attr:`parameters_err`. """ a, alpha, b = self.params - a_err, b_err, c_err = self.parameters_err + a_err, b_err, c_err = self.param_errors root = np.log(-b / a) / alpha From 1f100701033c0962f07dcb7689eeef29b5d4c906 Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 1 Oct 2020 15:42:19 -0700 Subject: [PATCH 129/521] rename _parameter_names (parameter_names) -> _param_names (param_names) --- plasmapy/analysis/fit_functions.py | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/plasmapy/analysis/fit_functions.py b/plasmapy/analysis/fit_functions.py index 6f376cd45b..4bbad5408f 100644 --- a/plasmapy/analysis/fit_functions.py +++ b/plasmapy/analysis/fit_functions.py @@ -25,12 +25,14 @@ class AbstractFitFunction(ABC): fitting the function to a set of data. These were originally designed for assisting in fitting curves to swept Langmuir data. """ + _param_names = NotImplemented # type: Tuple[str, ...] + _parameter_names = NotImplemented # type: Tuple[str, ...] - def __init__(self): - self.FitParamTuple = namedtuple("FitParamTuple", self._parameter_names) + + self.FitParamTuple = namedtuple("FitParamTuple", self._param_names) """ A named tuple class used for attributes :attr:`params` and :attr:`param_errors`. The attribute :attr:`parameter_names` defines @@ -173,11 +175,11 @@ def params(self) -> Union[None, tuple]: def params(self, val) -> None: if isinstance(val, self.FitParamTuple): self._params = tuple(val) - elif isinstance(val, (tuple, list)) and len(val) == len(self.parameter_names): + elif isinstance(val, (tuple, list)) and len(val) == len(self.param_names): self._params = tuple(val) else: raise ValueError(f"Got type {type(val)} for 'val', expecting tuple of " - f"length {len(self.parameter_names)}.") + f"length {len(self.param_names)}.") @property def param_errors(self) -> Union[None, tuple]: @@ -191,16 +193,16 @@ def param_errors(self) -> Union[None, tuple]: def param_errors(self, val) -> None: if isinstance(val, self.FitParamTuple): self._param_errors = tuple(val) - elif isinstance(val, (tuple, list)) and len(val) == len(self.parameter_names): + elif isinstance(val, (tuple, list)) and len(val) == len(self.param_names): self._param_errors = tuple(val) else: raise ValueError(f"Got type {type(val)} for 'val', expecting tuple of " - f"length {len(self.parameter_names)}.") + f"length {len(self.param_names)}.") @property - def parameter_names(self) -> Tuple[str, ...]: + def param_names(self) -> Tuple[str, ...]: """Names of the fitted parameters.""" - return self._parameter_names + return self._param_names @property @abstractmethod @@ -241,7 +243,7 @@ def root_solve(self, x0, **kwargs): >>> import scipy >>> class SomeFunc(AbstractFitFunction): - ... _parameter_names = ("m", "b") + ... _param_names = ("m", "b") ... ... @property ... def latex_str(self) -> str: @@ -379,7 +381,7 @@ class Exponential(AbstractFitFunction): :math:`\\delta \\alpha`, and :math:`\\delta x` are the respective uncertainties for :math:`A`, :math:`\\alpha`, and :math:`x`. """ - _parameter_names = ("a", "alpha") + _param_names = ("a", "alpha") def __str__(self): return f"f(x) = A exp(alpha x)" @@ -457,7 +459,7 @@ class Linear(AbstractFitFunction): and :math:`x`. """ - _parameter_names = ("m", "b") + _param_names = ("m", "b") def __str__(self): return f"f(x) = m x + b" @@ -644,7 +646,7 @@ class ExponentialPlusLinear(AbstractFitFunction): and :math:`\\delta x` are the respective uncertainties for :math:`A`, :math:`\\alpha`, :math:`m`, and :math:`b`, and :math:`x`. """ - _parameter_names = ("a", "alpha", "m", "b") + _param_names = ("a", "alpha", "m", "b") def __init__(self): super().__init__() @@ -724,7 +726,7 @@ class ExponentialPlusOffset(AbstractFitFunction): :math:`x`. """ - _parameter_names = ("a", "alpha", "b") + _param_names = ("a", "alpha", "b") def __init__(self): super().__init__() From bb1ff7fbba44758491a22721b32025c3f2c6e106 Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 1 Oct 2020 15:43:12 -0700 Subject: [PATCH 130/521] make __str__ an abstractmethod for AbstractFitFunction --- plasmapy/analysis/fit_functions.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plasmapy/analysis/fit_functions.py b/plasmapy/analysis/fit_functions.py index 4bbad5408f..138ae87a83 100644 --- a/plasmapy/analysis/fit_functions.py +++ b/plasmapy/analysis/fit_functions.py @@ -91,8 +91,9 @@ def __call__(self, x, x_err=None, reterr=False): def __repr__(self): return f"{self.__str__()} {self.__class__}" + @abstractmethod def __str__(self): - return f"Unspecified f(x)" + raise NotImplementedError @staticmethod @abstractmethod From 65ad507591902f17febabfaa2e790f073af13fea Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 1 Oct 2020 15:45:40 -0700 Subject: [PATCH 131/521] add kwargs params and param_errors to AbstractFitFunction signature --- plasmapy/analysis/fit_functions.py | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/plasmapy/analysis/fit_functions.py b/plasmapy/analysis/fit_functions.py index 138ae87a83..37a360d1b6 100644 --- a/plasmapy/analysis/fit_functions.py +++ b/plasmapy/analysis/fit_functions.py @@ -25,12 +25,26 @@ class AbstractFitFunction(ABC): fitting the function to a set of data. These were originally designed for assisting in fitting curves to swept Langmuir data. """ - _param_names = NotImplemented # type: Tuple[str, ...] + _param_names = NotImplemented # type: Tuple[str, ...] - _parameter_names = NotImplemented # type: Tuple[str, ...] + def __init__( + self, + params: Tuple[float, ...] = None, + param_errors: Tuple[float, ...] = None, + ): + """ + Parameters + ---------- + params: Tuple[float, ...], optional + Tuple of values for the function parameters. Equal in size to + :attr:`param_names`. + param_errors: Tuple[float, ...], optional + Tuple of values for the errors associated with the function + parameters. Equal in size to :attr:`param_names`. + """ self.FitParamTuple = namedtuple("FitParamTuple", self._param_names) """ @@ -39,8 +53,16 @@ class AbstractFitFunction(ABC): the tuple field names. """ - self._params = None # type: Union[None, Tuple[Any, ...]] - self._param_errors = None # type: Union[None, Tuple[Any, ...]] + if params is None: + self._params = None + else: + self.params = params + + if param_errors is None: + self._param_errors = None + else: + self.param_errors = param_errors + self._covariance_matrix = None self._rsq = None self._curve_fit_results = None From 72fc5f2060d6847c2a8d05cf360aaf8499101163 Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 2 Oct 2020 10:46:19 -0700 Subject: [PATCH 132/521] remove unused import of typing.Any --- plasmapy/analysis/fit_functions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plasmapy/analysis/fit_functions.py b/plasmapy/analysis/fit_functions.py index 37a360d1b6..b1f91de4e5 100644 --- a/plasmapy/analysis/fit_functions.py +++ b/plasmapy/analysis/fit_functions.py @@ -16,7 +16,7 @@ from collections import namedtuple from scipy.stats import linregress from scipy.optimize import curve_fit, fsolve -from typing import Any, Tuple, Union +from typing import Tuple, Union class AbstractFitFunction(ABC): From 20f5116c1ccad8c37d0c8f7348377cadc4aa8ece Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 2 Oct 2020 10:47:01 -0700 Subject: [PATCH 133/521] update to reflect renaming of parameters (parameters_err) -> params (param_errors) --- .../swept_langmuir/find_floating_potential.ipynb | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb b/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb index 08f60ede63..58da18a42e 100644 --- a/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb +++ b/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb @@ -187,8 +187,8 @@ " - `results.func` is a callable representation of the fitted function `I = results.func(V)`.\n", " - `resulst.func` is an instance of a sub-class of `AbstractFitFunction`. ([FitFuction classes](../../../api_static/plasmapy.analysis.fit_functions.rst))\n", " - Since `results.func` is a class instance, there are many other attribures available. For example,\n", - " - `results.func.parameters` is a named tuple of the fitted parameters\n", - " - `results.func.parameters_err` is a named tuple of the fitted parameter errors\n", + " - `results.func.params` is a named tuple of the fitted parameters\n", + " - `results.func.param_errors` is a named tuple of the fitted parameter errors\n", " - `results.func.root_solve()` finds the roots of the fitted function. This is how $V_f$ is calculated." ] }, @@ -200,10 +200,10 @@ "source": [ "(results[3],\n", " results.func,\n", - " results.func.parameters,\n", - " results.func.parameters.a,\n", - " results.func.parameters_err,\n", - " results.func.parameters_err.a,\n", + " results.func.params,\n", + " results.func.params.a,\n", + " results.func.param_errors,\n", + " results.func.param_errors.a,\n", " results.func(results.vf),\n", ")" ] From 551bca2636f615ea19a1bb32861d7097d98aedb0 Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 2 Oct 2020 10:50:06 -0700 Subject: [PATCH 134/521] initial commit for fit_function tests --- plasmapy/analysis/tests/__init__.py | 0 plasmapy/analysis/tests/test_fit_functions.py | 131 ++++++++++++++++++ 2 files changed, 131 insertions(+) create mode 100644 plasmapy/analysis/tests/__init__.py create mode 100644 plasmapy/analysis/tests/test_fit_functions.py diff --git a/plasmapy/analysis/tests/__init__.py b/plasmapy/analysis/tests/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/plasmapy/analysis/tests/test_fit_functions.py b/plasmapy/analysis/tests/test_fit_functions.py new file mode 100644 index 0000000000..d7e16f741e --- /dev/null +++ b/plasmapy/analysis/tests/test_fit_functions.py @@ -0,0 +1,131 @@ +""" +Tests for the fitting function classes defined in `plasmapy.analysis.fit_functions`. +""" +import inspect +import numpy as np +import pytest + +from abc import ABC, abstractmethod + +import plasmapy.analysis.fit_functions as ffuncs + + +class BaseFFTests(ABC): + abc = ffuncs.AbstractFitFunction + + @property + @abstractmethod + def ff_class(self): + raise NotImplementedError + + @staticmethod + @abstractmethod + def func(x, *args): + raise NotImplementedError + + def test_basics(self): + assert hasattr(self.ff_class, "_param_names") + if self.ff_class._param_names == NotImplemented: + pytest.fail( + f"{self.ff_class} class attribute '_param_names' needs to " + f" be defined as a tuple of strings representing the names of " + f"the fit parameters." + ) + + foo = self.ff_class() + + assert hasattr(foo, "func") + assert hasattr(foo, "func_err") + + assert hasattr(foo, "FitParamTuple") + assert issubclass(foo.FitParamTuple, tuple) + + assert hasattr(foo, "curve_fit_results") + assert foo.curve_fit_results is None + + assert hasattr(foo, "param_names") + assert isinstance(foo.param_names, tuple) + assert all(isinstance(val, str) for val in foo.param_names) + + for attr in ("params", "param_errors"): + assert hasattr(foo, attr) + assert getattr(foo, attr) is None + params = [1] * len(foo.param_names) + setattr(foo, attr, params) + assert getattr(foo, attr) == foo.FitParamTuple(*params) + assert all(hasattr(getattr(foo, attr), name) + for name in foo.param_names) + + assert hasattr(foo, "latex_str") + assert isinstance(foo.latex_str, str) + + assert hasattr(foo, "rsq") + assert foo.rsq is None + + def test_inheritance(self): + assert issubclass(self.ff_class, self.abc) + + def test_iscallable(self): + assert callable(self.ff_class()) + + +# class TestAbstractFitFunction(BaseFFTests): +# @staticmethod +# def func(x, a, b, c): +# return a * x ** 2 + b * x + c +# +# class FooFitFunc(ffuncs.AbstractFitFunction): +# _param_names = ("a", "b", "c") +# +# @property +# def latex_str(self) -> str: +# return fr"a \, x^2 + b \, x + c" +# +# @staticmethod +# def func(x, a, b, c): +# return a * x ** 2 + b * x + c +# +# def func_err(self, x, x_err=None, rety=False): +# a, b, c = self.parameters +# a_err, b_err, c_err = self.parameters_err +# +# a_term = ((x ** 2) * a_err) ** 2 +# b_term = (x * b_err) ** 2 +# c_term = c_err ** 2 +# err = a_term + b_term + c_term +# +# if x_err is not None: +# x_term = ((2 * a * x + b) * x_err) ** 2 +# err += x_term +# err = np.sqrt(err) +# +# if rety: +# y = self.func(x, a, b, c) +# return err, y +# +# return err +# +# ff_class = FooFitFunc +# +# def test_basics(self): +# pass + + +class TestFFLinear(BaseFFTests): + """ + Tests for fit function class `plasmapy.analysis.fit_functions.Linear`. + """ + ff_class = ffuncs.Linear + + @staticmethod + def func(x, m, b): + return m * x + b + + def test_basics(self): + super().test_basics() + + foo = self.ff_class() + + assert foo.param_names == ("m", "b") + assert foo.latex_str == fr"m \, x + b" + assert foo.__str__() == f"f(x) = m x + b" From 10629a9f5c872f0238a33cf704753e69f90b8998 Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 2 Oct 2020 14:36:23 -0700 Subject: [PATCH 135/521] update crossing-point identification so that the routine does not accidentally add candidates around current == 0 --- plasmapy/analysis/swept_langmuir/floating_potential.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plasmapy/analysis/swept_langmuir/floating_potential.py b/plasmapy/analysis/swept_langmuir/floating_potential.py index d0e502d133..defbd47430 100644 --- a/plasmapy/analysis/swept_langmuir/floating_potential.py +++ b/plasmapy/analysis/swept_langmuir/floating_potential.py @@ -199,9 +199,9 @@ def find_floating_potential( f"greater than or equal to 0.") # find possible crossing points (cp) - lower_vals = current <= 0 - upper_vals = 0 <= current - cp_exact = np.logical_and(lower_vals, upper_vals).nonzero()[0] + lower_vals = current < 0 + upper_vals = 0 < current + cp_exact = (current == 0.).nonzero()[0] cp_low2high = np.logical_and(np.roll(lower_vals, 1), upper_vals).nonzero()[0] cp_high2low = np.logical_and(np.roll(lower_vals, -1), upper_vals).nonzero()[0] From 0ad91660b6c343c6f97065a03c3d5b265143d534 Mon Sep 17 00:00:00 2001 From: Erik Date: Wed, 28 Oct 2020 16:52:57 -0700 Subject: [PATCH 136/521] spelling fix & make nick happy w/ double back ticks --- plasmapy/analysis/swept_langmuir/helpers.py | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/plasmapy/analysis/swept_langmuir/helpers.py b/plasmapy/analysis/swept_langmuir/helpers.py index e9b5571d8e..285d9c3754 100644 --- a/plasmapy/analysis/swept_langmuir/helpers.py +++ b/plasmapy/analysis/swept_langmuir/helpers.py @@ -6,8 +6,8 @@ def check_sweep(voltage: np.ndarray, current: np.ndarray) -> None: """ - Function for checking that the voltage and current arrays are properly formated - for analysis by `plasmapy.analysis.swept_langmuir`. + Function for checking that the voltage and current arrays are properly + formatted for analysis by `plasmapy.analysis.swept_langmuir`. Parameters ---------- @@ -23,18 +23,19 @@ def check_sweep(voltage: np.ndarray, current: np.ndarray) -> None: Raises ------ `TypeError` - If either the `voltage` or `current` arrays are not instances of a `numpy` - array. + If either the ``voltage`` or ``current`` arrays are not instances of a + `numpy.ndarray`. `ValueError` - If either the `voltage` or `current` arrays are not 1D. + If either the ``voltage`` or ``current`` arrays are not 1D. - If the `voltage` array is not monotonically increasing. + If the ``voltage`` array is not monotonically increasing. - If the `current` array never cross zero (i.e. has not floating potential). + If the ``current`` array never cross zero (i.e. has not floating + potential). - If the `current` array does not start form a negative ion-saturation current - and increases to a positive electron-saturation current. + If the ``current`` array does not start form a negative ion-saturation + current and increases to a positive electron-saturation current. """ # examine voltage array From 7033f72bcc3dba1bb3b5e6fe07985d48dc0a0d13 Mon Sep 17 00:00:00 2001 From: Erik Date: Wed, 28 Oct 2020 22:18:20 -0700 Subject: [PATCH 137/521] create test directory for plasmapy.analysis.swept_langmuir --- plasmapy/analysis/swept_langmuir/tests/__init__.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 plasmapy/analysis/swept_langmuir/tests/__init__.py diff --git a/plasmapy/analysis/swept_langmuir/tests/__init__.py b/plasmapy/analysis/swept_langmuir/tests/__init__.py new file mode 100644 index 0000000000..e69de29bb2 From 674df27b031b147944e697954b58baec02de4e19 Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 29 Oct 2020 13:26:55 -0700 Subject: [PATCH 138/521] initial commit for test_helpers.py --- .../swept_langmuir/tests/test_helpers.py | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 plasmapy/analysis/swept_langmuir/tests/test_helpers.py diff --git a/plasmapy/analysis/swept_langmuir/tests/test_helpers.py b/plasmapy/analysis/swept_langmuir/tests/test_helpers.py new file mode 100644 index 0000000000..288b7f577e --- /dev/null +++ b/plasmapy/analysis/swept_langmuir/tests/test_helpers.py @@ -0,0 +1,33 @@ +"""Tests for `plasmapy.analysis.swept_langmuir.helpers`.""" + +import numpy as np +import pytest + +from contextlib import ExitStack as does_not_raise + +from plasmapy.analysis.swept_langmuir.helpers import check_sweep + + +@pytest.mark.parametrize( + "voltage, current, with_context", + [ + (np.linspace(-40., 40., 100), np.linspace(-10., 30, 100), does_not_raise()), + ("not a numpy array", np.linspace(-10., 30, 100), pytest.raises(TypeError)), + # voltage not 1D + ( + np.empty((2, 2), dtype=np.float64), + np.linspace(-10., 30, 100), + pytest.raises(ValueError), + ), + # voltage not linearly increasing + ( + np.linspace(40., -40., 100), + np.linspace(-10., 30, 100), + pytest.raises(ValueError), + ), + ], +) +def test_check_sweep(voltage, current, with_context): + """Test functionality of `plasmapy.analysis.swept_langmuir.helpers.check_sweep`.""" + with with_context: + check_sweep(voltage=voltage, current=current) From 6b9251280be77d6674de73efda4502edf5694656 Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 29 Oct 2020 13:27:04 -0700 Subject: [PATCH 139/521] add todo --- plasmapy/analysis/swept_langmuir/helpers.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plasmapy/analysis/swept_langmuir/helpers.py b/plasmapy/analysis/swept_langmuir/helpers.py index 285d9c3754..101b1b7209 100644 --- a/plasmapy/analysis/swept_langmuir/helpers.py +++ b/plasmapy/analysis/swept_langmuir/helpers.py @@ -71,3 +71,5 @@ def check_sweep(voltage: np.ndarray, current: np.ndarray) -> None: "The current array needs to start from a negative ion-saturation current" " to a positive electron-saturation current." ) + + # TODO: voltage and current must have the same size From 1d4d5e0e2ccfe834dc6d7c26f51bf252d5d62526 Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 30 Oct 2020 11:47:57 -0700 Subject: [PATCH 140/521] add a check that current and voltage must have the same size --- plasmapy/analysis/swept_langmuir/helpers.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/plasmapy/analysis/swept_langmuir/helpers.py b/plasmapy/analysis/swept_langmuir/helpers.py index 101b1b7209..ec85ccfaa1 100644 --- a/plasmapy/analysis/swept_langmuir/helpers.py +++ b/plasmapy/analysis/swept_langmuir/helpers.py @@ -72,4 +72,8 @@ def check_sweep(voltage: np.ndarray, current: np.ndarray) -> None: " to a positive electron-saturation current." ) - # TODO: voltage and current must have the same size + if voltage.size != current.size: + raise ValueError( + f"Incompatible arrays, 'voltage' size {voltage.size} must be the same" + f" as the 'current' size {current.size}." + ) From cda13e8bc992b30714b6e9b81ccbf349ad77d997 Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 30 Oct 2020 11:50:33 -0700 Subject: [PATCH 141/521] complete test for check_sweep --- .../swept_langmuir/tests/test_helpers.py | 41 ++++++++++++++++++- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/plasmapy/analysis/swept_langmuir/tests/test_helpers.py b/plasmapy/analysis/swept_langmuir/tests/test_helpers.py index 288b7f577e..71dabb0fef 100644 --- a/plasmapy/analysis/swept_langmuir/tests/test_helpers.py +++ b/plasmapy/analysis/swept_langmuir/tests/test_helpers.py @@ -3,6 +3,7 @@ import numpy as np import pytest +# ExitStack can be replaced with nullcontext when we require >= python 3.7 from contextlib import ExitStack as does_not_raise from plasmapy.analysis.swept_langmuir.helpers import check_sweep @@ -11,20 +12,56 @@ @pytest.mark.parametrize( "voltage, current, with_context", [ + # the one that works (np.linspace(-40., 40., 100), np.linspace(-10., 30, 100), does_not_raise()), + # -- voltage cases -- + # not the right type ("not a numpy array", np.linspace(-10., 30, 100), pytest.raises(TypeError)), - # voltage not 1D + # not 1D ( np.empty((2, 2), dtype=np.float64), np.linspace(-10., 30, 100), pytest.raises(ValueError), ), - # voltage not linearly increasing + # not linearly increasing ( np.linspace(40., -40., 100), np.linspace(-10., 30, 100), pytest.raises(ValueError), ), + # -- current cases -- + # not the right type + (np.linspace(-40., 40., 100), "not a numpy array", pytest.raises(TypeError)), + # not 1D + ( + np.linspace(-40., 40., 100), + np.empty((2, 2), dtype=np.float64), + pytest.raises(ValueError), + ), + # no floating potential (i.e. current never crosses zero) + ( + np.linspace(-40., 40., 100), + np.linspace(10., 30, 100), + pytest.raises(ValueError), + ), + ( + np.linspace(-40., 40., 100), + np.linspace(-30., -5., 100), + pytest.raises(ValueError), + ), + # current needs to start from negative and go positive + ( + np.linspace(-40., 40., 100), + np.linspace(30., -5., 100), + pytest.raises(ValueError), + ), + # -- mixed cases -- + # voltage and current must have the same size + ( + np.linspace(-40., 40., 100), + np.linspace(-5., 30., 150), + pytest.raises(ValueError), + ), ], ) def test_check_sweep(voltage, current, with_context): From 233f7285dc8caf0ca51c5f14bdb31af8b5fc23b7 Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 30 Oct 2020 11:52:45 -0700 Subject: [PATCH 142/521] appease grumpy black --- .../swept_langmuir/tests/test_helpers.py | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/plasmapy/analysis/swept_langmuir/tests/test_helpers.py b/plasmapy/analysis/swept_langmuir/tests/test_helpers.py index 71dabb0fef..f3c17b161f 100644 --- a/plasmapy/analysis/swept_langmuir/tests/test_helpers.py +++ b/plasmapy/analysis/swept_langmuir/tests/test_helpers.py @@ -13,53 +13,53 @@ "voltage, current, with_context", [ # the one that works - (np.linspace(-40., 40., 100), np.linspace(-10., 30, 100), does_not_raise()), + (np.linspace(-40.0, 40, 100), np.linspace(-10.0, 30, 100), does_not_raise()), # -- voltage cases -- # not the right type - ("not a numpy array", np.linspace(-10., 30, 100), pytest.raises(TypeError)), + ("not a numpy array", np.linspace(-10.0, 30, 100), pytest.raises(TypeError)), # not 1D ( np.empty((2, 2), dtype=np.float64), - np.linspace(-10., 30, 100), + np.linspace(-10.0, 30, 100), pytest.raises(ValueError), ), # not linearly increasing ( - np.linspace(40., -40., 100), - np.linspace(-10., 30, 100), + np.linspace(40.0, -40, 100), + np.linspace(-10.0, 30, 100), pytest.raises(ValueError), ), # -- current cases -- # not the right type - (np.linspace(-40., 40., 100), "not a numpy array", pytest.raises(TypeError)), + (np.linspace(-40.0, 40, 100), "not a numpy array", pytest.raises(TypeError)), # not 1D ( - np.linspace(-40., 40., 100), + np.linspace(-40.0, 40, 100), np.empty((2, 2), dtype=np.float64), pytest.raises(ValueError), ), # no floating potential (i.e. current never crosses zero) ( - np.linspace(-40., 40., 100), - np.linspace(10., 30, 100), + np.linspace(-40.0, 40, 100), + np.linspace(10.0, 30, 100), pytest.raises(ValueError), ), ( - np.linspace(-40., 40., 100), - np.linspace(-30., -5., 100), + np.linspace(-40.0, 40, 100), + np.linspace(-30.0, -5, 100), pytest.raises(ValueError), ), # current needs to start from negative and go positive ( - np.linspace(-40., 40., 100), - np.linspace(30., -5., 100), + np.linspace(-40.0, 40, 100), + np.linspace(30.0, -5, 100), pytest.raises(ValueError), ), # -- mixed cases -- # voltage and current must have the same size ( - np.linspace(-40., 40., 100), - np.linspace(-5., 30., 150), + np.linspace(-40.0, 40, 100), + np.linspace(-5.0, 30, 150), pytest.raises(ValueError), ), ], From efb656d65770e4e69462152d07ad7dddf2d9923d Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 30 Oct 2020 12:02:10 -0700 Subject: [PATCH 143/521] appease grumpy black --- .../swept_langmuir/floating_potential.py | 90 +++++++++---------- 1 file changed, 40 insertions(+), 50 deletions(-) diff --git a/plasmapy/analysis/swept_langmuir/floating_potential.py b/plasmapy/analysis/swept_langmuir/floating_potential.py index defbd47430..9e6d735864 100644 --- a/plasmapy/analysis/swept_langmuir/floating_potential.py +++ b/plasmapy/analysis/swept_langmuir/floating_potential.py @@ -12,8 +12,7 @@ from plasmapy.utils.exceptions import PlasmaPyWarning FloatingPotentialResults = namedtuple( - "FloatingPotentialResults", - ("vf", "vf_err", "rsq", "func", "islands", "indices"), + "FloatingPotentialResults", ("vf", "vf_err", "rsq", "func", "islands", "indices"), ) @@ -137,23 +136,12 @@ def find_floating_potential( """ rtn = FloatingPotentialResults( - vf=np.nan, - vf_err=np.nan, - rsq=None, - func=None, - islands=None, - indices=None + vf=np.nan, vf_err=np.nan, rsq=None, func=None, islands=None, indices=None )._asdict() _settings = { - "linear": { - "func": ffuncs.Linear, - "min_point_factor": 0.1, - }, - "exponential": { - "func": ffuncs.ExponentialPlusOffset, - "min_point_factor": 0.2, - }, + "linear": {"func": ffuncs.Linear, "min_point_factor": 0.1}, + "exponential": {"func": ffuncs.ExponentialPlusOffset, "min_point_factor": 0.2}, } try: min_point_factor = _settings[fit_type]["min_point_factor"] @@ -177,8 +165,11 @@ def find_floating_potential( if isinstance(threshold, (int, np.integer)): if threshold < 1: threshold = 1 - warn(f"threshold ({threshold}) is less than 1 and needs to be" - f" an int >= 1, using a value of 1", PlasmaPyWarning) + warn( + f"threshold ({threshold}) is less than 1 and needs to be" + f" an int >= 1, using a value of 1", + PlasmaPyWarning, + ) else: threshold = 1 @@ -195,13 +186,15 @@ def find_floating_potential( elif min_points >= 1: min_points = int(np.round(min_points)) else: - raise ValueError(f"Got {min_points}, but 'min_points' must be an int or float " - f"greater than or equal to 0.") + raise ValueError( + f"Got {min_points}, but 'min_points' must be an int or float " + f"greater than or equal to 0." + ) # find possible crossing points (cp) lower_vals = current < 0 upper_vals = 0 < current - cp_exact = (current == 0.).nonzero()[0] + cp_exact = (current == 0.0).nonzero()[0] cp_low2high = np.logical_and(np.roll(lower_vals, 1), upper_vals).nonzero()[0] cp_high2low = np.logical_and(np.roll(lower_vals, -1), upper_vals).nonzero()[0] @@ -210,13 +203,9 @@ def find_floating_potential( cp_high2low = cp_high2low[cp_high2low != current.size - 1] # collect all candidates - cp_candidates = np.concatenate(( - cp_exact, - cp_low2high, - cp_low2high - 1, - cp_high2low, - cp_high2low + 1, - )) + cp_candidates = np.concatenate( + (cp_exact, cp_low2high, cp_low2high - 1, cp_high2low, cp_high2low + 1) + ) cp_candidates = np.unique(cp_candidates) # sorted and unique # How many crossing-islands? @@ -230,25 +219,27 @@ def find_floating_potential( rtn["islands"] = [slice(cp_candidates[0], cp_candidates[-1] + 1)] else: # There are multiple crossing points - isl_start = np.concatenate(( - [cp_candidates[0]], - cp_candidates[threshold_indices+1], - )) - isl_stop = np.concatenate(( - cp_candidates[threshold_indices]+1, - [cp_candidates[-1]+1], - )) + isl_start = np.concatenate( + ([cp_candidates[0]], cp_candidates[threshold_indices + 1]) + ) + isl_stop = np.concatenate( + (cp_candidates[threshold_indices] + 1, [cp_candidates[-1] + 1]) + ) rtn["islands"] = [] for start, stop in zip(isl_start, isl_stop): rtn["islands"].append(slice(start, stop)) # do islands fall within min_points window - isl_window = np.abs(np.r_[rtn["islands"][-1]][-1] - - np.r_[rtn["islands"][0]][0]) + 1 + isl_window = ( + np.abs(np.r_[rtn["islands"][-1]][-1] - np.r_[rtn["islands"][0]][0]) + 1 + ) if isl_window > min_points: - warn(f"Unable to determine floating potential, Langmuir sweep has " - f"{n_islands} crossing-islands. Try adjusting keyword 'threshold' " - f"and/or smooth the current.", PlasmaPyWarning) + warn( + f"Unable to determine floating potential, Langmuir sweep has " + f"{n_islands} crossing-islands. Try adjusting keyword 'threshold' " + f"and/or smooth the current.", + PlasmaPyWarning, + ) return FloatingPotentialResults(**rtn) @@ -287,19 +278,18 @@ def find_floating_potential( istart -= ipad_2_start if (istop - istart + 1) < min_points: - warn(f"The number of elements in the current array " - f"({istop - istart + 1}) is less than 'min_points' " - f"({min_points}).", PlasmaPyWarning) + warn( + f"The number of elements in the current array ({istop - istart + 1}) " + f"is less than 'min_points' ({min_points}).", + PlasmaPyWarning, + ) # Perform Linear Regression Fit - volt_sub = voltage[istart:istop + 1] - curr_sub = current[istart:istop + 1] + volt_sub = voltage[istart : istop + 1] + curr_sub = current[istart : istop + 1] fit_func.curve_fit(volt_sub, curr_sub) rtn["vf"], rtn["vf_err"] = fit_func.root_solve() - rtn.update({ - "rsq": fit_func.rsq, - "indices": slice(istart, istop + 1) - }) + rtn.update({"rsq": fit_func.rsq, "indices": slice(istart, istop + 1)}) return FloatingPotentialResults(**rtn) From ee5dfe75c77991b68ce873ff2c4ac4fbd439e110 Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 30 Oct 2020 12:14:37 -0700 Subject: [PATCH 144/521] more grumpy black appeasement --- plasmapy/analysis/__init__.py | 2 +- plasmapy/analysis/swept_langmuir/floating_potential.py | 2 +- plasmapy/diagnostics/langmuir.py | 10 ++++++---- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/plasmapy/analysis/__init__.py b/plasmapy/analysis/__init__.py index 4417ca8c9a..f89496db3e 100644 --- a/plasmapy/analysis/__init__.py +++ b/plasmapy/analysis/__init__.py @@ -1,4 +1,4 @@ """The analysis sub-package for PlasmaPy.""" __all__ = [] -from plasmapy.analysis import swept_langmuir, fit_functions +from plasmapy.analysis import fit_functions, swept_langmuir diff --git a/plasmapy/analysis/swept_langmuir/floating_potential.py b/plasmapy/analysis/swept_langmuir/floating_potential.py index 9e6d735864..85c2d11edc 100644 --- a/plasmapy/analysis/swept_langmuir/floating_potential.py +++ b/plasmapy/analysis/swept_langmuir/floating_potential.py @@ -4,8 +4,8 @@ import numpy as np from collections import namedtuple -from warnings import warn from typing import Union +from warnings import warn from plasmapy.analysis import fit_functions as ffuncs from plasmapy.analysis.swept_langmuir.helpers import check_sweep diff --git a/plasmapy/diagnostics/langmuir.py b/plasmapy/diagnostics/langmuir.py index 3f04f40566..4f414f6f4a 100644 --- a/plasmapy/diagnostics/langmuir.py +++ b/plasmapy/diagnostics/langmuir.py @@ -32,10 +32,12 @@ def _langmuir_futurewarning() -> None: - warn("The plasmapy.diagnostics.langmuir module will be deprecated in favor of " - "the plasmapy.analysis.swept_langmuir sub-package. The analysis package " - " is in active development and is scheduled to be released with v0.5.0.", - FutureWarning) + warn( + "The plasmapy.diagnostics.langmuir module will be deprecated in favor of " + "the plasmapy.analysis.swept_langmuir sub-package. The analysis package " + " is in active development and is scheduled to be released with v0.5.0.", + FutureWarning, + ) def _fit_func_lin(x, x0, y0, c0): From ed05eab64fdb2bf72e2bfc9ddd0a2be8033052ac Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 30 Oct 2020 16:26:21 -0700 Subject: [PATCH 145/521] replace comment about ExitStack with a TODO --- plasmapy/analysis/swept_langmuir/tests/test_helpers.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plasmapy/analysis/swept_langmuir/tests/test_helpers.py b/plasmapy/analysis/swept_langmuir/tests/test_helpers.py index f3c17b161f..a46eab6a16 100644 --- a/plasmapy/analysis/swept_langmuir/tests/test_helpers.py +++ b/plasmapy/analysis/swept_langmuir/tests/test_helpers.py @@ -3,11 +3,12 @@ import numpy as np import pytest -# ExitStack can be replaced with nullcontext when we require >= python 3.7 from contextlib import ExitStack as does_not_raise from plasmapy.analysis.swept_langmuir.helpers import check_sweep +# TODO: replace ExitStack with nullcontext when we require >= python 3.7 + @pytest.mark.parametrize( "voltage, current, with_context", From 63d9160fd78b5168b543ff99e0372a4a60d1a24f Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 30 Oct 2020 16:26:54 -0700 Subject: [PATCH 146/521] replace comment about ExitStack with a TODO --- plasmapy/analysis/tests/test_fit_functions.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plasmapy/analysis/tests/test_fit_functions.py b/plasmapy/analysis/tests/test_fit_functions.py index d25890f8cc..e5ac6b90e9 100644 --- a/plasmapy/analysis/tests/test_fit_functions.py +++ b/plasmapy/analysis/tests/test_fit_functions.py @@ -6,10 +6,11 @@ from abc import ABC, abstractmethod from contextlib import ExitStack as does_not_raise -# ^ ExitStack can be replaced with nullcontext when we require >= python 3.7 import plasmapy.analysis.fit_functions as ffuncs +# TODO: replace ExitStack with nullcontext when we require >= python 3.7 + class TestAbstractFitFunction: """ From a9e22deb6d1c3ba88c4ed5e47a0d8f46409d8859 Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 30 Oct 2020 16:31:17 -0700 Subject: [PATCH 147/521] add changelog --- changelog/889.feature.rst | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 changelog/889.feature.rst diff --git a/changelog/889.feature.rst b/changelog/889.feature.rst new file mode 100644 index 0000000000..e6be2b7962 --- /dev/null +++ b/changelog/889.feature.rst @@ -0,0 +1,4 @@ +Create the analysis sub-package `plasmapy.analysis.swept_langmuir` for analysis +code related to analyzing swept Langmuir traces. Sub-package is initiated with +functionality for calculating the floating potential, +`~plasmapy.analysis.swept_langmuir.floating_potential.find_floating_potential`. From 06c973e923d5dfdf8507faff9d42e6fdc2dfa3a2 Mon Sep 17 00:00:00 2001 From: Erik Date: Sun, 1 Nov 2020 10:12:01 -0800 Subject: [PATCH 148/521] add static image for the langmuir_analysis notebook --- .../notebook_images/langmuir_analysis.png | Bin 0 -> 25254 bytes docs/conf.py | 5 ++++- docs/notebooks/langmuir_analysis.ipynb | 3 --- 3 files changed, 4 insertions(+), 4 deletions(-) create mode 100644 docs/_static/notebook_images/langmuir_analysis.png diff --git a/docs/_static/notebook_images/langmuir_analysis.png b/docs/_static/notebook_images/langmuir_analysis.png new file mode 100644 index 0000000000000000000000000000000000000000..4be289db8e741d35560f35543f8b2d42704130a2 GIT binary patch literal 25254 zcmb5V1yq#L+bupc2uMjwI0^_ziAa|Y(#?P(-QC@xG$J4+t>n<%FoLv%ASqo#r*z%J z@4MfWL5Pd%fB&D;-pQPcDKc9Q0%3&6!X!03 z(za(kJv3IQ&JOlOdEY%kdt@Ym{BTbdm-r=?WZ+T|xvGvtZ&yF}^%jPa?8ikpct<_An%Ox)gIGi~C7DcnQ}lpyypw zWC_nCsli9(60@T49z$cod)QrlqF#`wk{pb!I&MaW6_dn1%CDGxOOm3F^C;y_JLwn8 zeV9pV*hBJID9QO7SYD*ekxcg(aeesVjC~amd?ycar0kR?C;JX=Ua+}3zc!iYScPdy z6IleW5gevn#}`p^#BzLrm_L^pZ>Nzb9EO#>IqtTKLiiD0;rCz?$DTtEtx4WtK134= zmk}oMl!l#z_b`(*d~df~k}}B)dq^648zwWP64>onjI<(d!i5XqpzLCg2p|D;=oLj!bDi06^5&9(9^IUEu_|NrFghZY1qRD zv8zxg$H@yllJk@>8#nP$Cz1_DDE}M%O&s<_eF`YSHHrZ*2; z6zy+-{OtLCB+Y{3>9vmm&M@IV8jk>FKV^UiBmN}5&xGzRPu7F_AG)V3NKN-SjAuCX zSVnlwx=P}-k&66z_dj$^Lp@Eb|VZ9g+vAi@@DH`9_ z5xqYVbWrEZv?t{j-fmf9{zH})f1PcNK^tI=cvof=^ff4TrX$f7f*qQ^#h~eU^BT_z zZC{=-_v?_3ZcrojTat}=rqplNmEJvh74@2Ml%{$j?aTT5llh3y_C(umPdm7!FPtz! zCZj1GeFwH8G1;iMFv|8RB}koY(kCd{J#>KKN1-DlR5w7po`-4aPefwo0`DWJIGP<% zB=1x-T3U|JH-Ywaj4KJ)F8+Ipt=+mlV=V{aeRhMEFdHntLd4$KLVZ5zcT4Ct^%u)~ z?M>VBc-5q_IpwBwfn^(QMOAe^=4p!)r_@zvLk1i=jn&UF$Fno~hc%t!{5FxUt#7uwyPO1C`Er`_IDOXYbAQvE=$F$TzS(LNE8q)P{$t0>QB2% zgxo?tO#6AtpVmdaAmV(fU)MQj0oTQzK@$l*I_F;$VMi1$B56oi(QiH+>Fg9B=+XQL zpE<>hiTgZ0P24g?jtSI>wV{V(v^y$3eu8*ukPY(Ux-s8V<0u~0-v3vYEQ07az^h@;u_K#<7MZx|AWWI!4YlRpC~0nV5~s6ib7$0j*D}O<4etWEd2@c zIXRhXQN}7W%%;rB^ShEtS8~W|2(2B&;O6Q)mhj2FmYa($NECy(m=Vv)%F6zTJXeMH z>49FOn!0+!@%VdcZUc!DhN1rqO72xJZkAS=-qn`=?NYk?+#@OiP3_Z8N_~^LX3v_8 zoVz5h@OapJ&34A==IM=oOzgasxS*h*LWW4gw24MSTpa1zP^LZJ=3g*kCN8d+rKKgA zP$MfzA0LsOzjZ9k%*-R%RAfARJ8uUgjz`Z2spkVn6;$%$lV2Gb8&f|w>9M3cg?-ft z>g(@+%*q;GUHt;a=0hvX=foENf)^0gCOwN>Wh@f4xQ zCZvHCX_i2|vEfA#k&zsNe5BA z4Gn`&AJGZ92=sncR5mnx1mV#B!Z5oUv%AwG?KQD|G8b;8_&YASZz{ZQD%eVhi>p^C+Q3uc@gi0(y~T%h5cz zoRVHy61eCM+~{5fCL9Aqz||Um+ang1{P9!YgHFmS%TeZ9+rMw#yuq%U^I}g)Nm*H2 zJDj#I``zO0{+yThd_&n^+pdY>_N?1wYdqSpBP4;3bh6o#w7xm({oqmDbz%%Ii{Ak9ZgD}l~&NGTmm;$~!Wu9q@ z8cZjk6Z(?<+7_u{+#1ayev2QLq<=!Izas=5TOmy#c4TD4X(+W>k848DnYZ^=kW|7;ywy?PbIsn>k=rM672%4|RbUQ=DI zA^quLAy@N$klkz}Tngsw-HXPjdY2*1;&`LSqPegtAOj!E8SeKsd z4I1KcGk&N?Y=kXwbDZZho`@^{VH~Iwv0e%>*y5UJq5@6 z+Vy77qZfjL@0^{T`G|2XZf~xSN0r6l@G<8>LFv=o*-Kkx;}rGll&|Z29{UD#A|4KR zLCDp5_O117DbjQ=CXrr!D87WxReQDV=rahH!tQ0&ESp2G7B8??V|_KnwUGYm2I?8f;yv00Zu~ zn#P{TV_MWNEQou1dvo&hkGg2>AxcYN<+#{(PAmI4m(Nj|T;6T|w|EupJ*Io3(bv<% z`1mnKz)t8%+~u*fNuIvqQSzD77GL5DW@46=2{Hgpo8f5vdki|aaTmeONnP9TDs$yV*R8I<_HDYBZ80K; zxR%wlQAm@ zSSoG|3h$Ym?JthYv};rvc3{7>nIzue{-);V=Qri?j)>!&-GWto!`ZvR)yc`J9+lxu zBjtonT(b23XSCFOt8dLxz(;VtEMFZB#i+pYI46gy4{&E+)g5H9rHc6qEx7Rg*-jyV z`8>Ejr4h+kK8^zEIPr2??zOBEv{DDoe!OaO2M8=B@=7oHJ40Xc2yM0XG39S>+uR%` zwS8$h^=cu63Z{qg#c_8fW1AeB4+WM9#$V2>))p^0vyd!)65h2K?!_y{1~iNCO$NP@ z_uRwER%cOL(zrkbt<;&1m|aWF<{FAH93=B7OGZ86TFgH~@xjb!WBd^wyA7ysrGLMT z8rGcwOtKs+O&<uNh^60O=HC^$sA>Aj0}=Di4WRbh%_)`W7fkjNfv zlBp+9BDg9&3zT>Ea0vEfK-VuN>=|V&e0R%zi`ULr;ky3chw*=+nh9NLd7=&%3*8T1u^Nzpxh3GB*E{9n3$F%axeABvM@{`nYrKfPD< zbVhyryeQ0J$~39M;78D#gtRO_YZXdJs)lPMA`x;6DJ?7?7<6o)#F(BW>#>W2m z8BXT8S(yK}#j9pEjwkQFXvHC6#7P;nXjP!LWJbsB^m~QR#0G4WSJIcz1=o9iPFHhG z$P>DRp$)-;Ku74431<+9)FR<9gc-&ZWMgB41|j<4Lr4QIcJKpA29B+j7eBX-8|Mc# z<>cAtPwpiYStZnUqNAC=0}1fs$Bzkp@o{l|eRt7(mutW=1rC;fd-Iu{k(8s2uGV0M zM)U7NliT63+w zmz6mG%Gz$ca#j6DM@RdGw$pix-{j7xbLuua{Fb6b>u$=$n<#nDe{sBZH+){RUj-T& z2?C?jT`+ zve@|t5SEGT$_fh4gl}dVoO}EG*|jp#(tf#4=;9!87<`bsvrYX86JvXNDhc|OSJ=ur zY_o0u5`~GN?cn?z`nNGkd$p(M3Sy4~ODIxCND11Acjoueb?%2HW-P`G#HSd+2IUC6 z#h_Okld2(C`CHpoTK$ZNC-&!07d+s=sR(b@)FOBY^ybC+-Jo(z1(=V~su z`7*n-WF+cyR=zt~@p?!Q^^k*;bNu@9)EaQxsakUBN`M*5L7-G`UxP0$j%QKk^lmfi zya#uE^ZR;s&rhqi`F))oIN&u0hK43U?(w@MJLHh+82a<)6Ijy?@UT#Ds0gfajh*ES z7o8Tmu~mre3}*+stq)7K=#?p@zT_BL9Ao=t2-Ai8GI+GLS4wxRMF!FqP440?gbNXs zXGGKRMWm%Y^g7uN599VcGyzojU7Me8bglpSYElZfA$pA1#ZwRtfPT@sZ2k%V{ardf zB}LZDOQ^-`7~v=~BzE}>0CFNgNsxP|&b>@YU$&?lz5%er>#!gJg1X_bkNy1aS(c5d z)f0wo*)ZIFFU%u|d_UUsz~tTHQd1+txDDGsyt$rXO(U!`q!GDHc}X8h$%Xw)bw|u8 zpz79zQ_r4V&i{fO0%#+0>-cc9sO)8w2jv0AoUa=gKF&NlH`tDHO@qmHf2QU_ywZv^T_n-{l7d(h}`&scw@x%}ygv`JFzi z3Z)`=?lkU!#OK;$d%t^hF0fTx1*Oo+c?)FQ@1h!gFmSPgk&%8&d^Q-^R)S8`UA{BlWyv2$9IGdwU)@47dGD&K z7JS_c#UT;(D!X=?RDf}qeXgH*5Vd;`JjzOFe17j3_WMhk8bB9~VLe#I^$Iuo-~Q*!vxS zf`{i}>T&7m10Otxg3Jk5%-hvamr4f*2dg2r%8H6ie0+RCvEyy(C6XmLVpwkqHklzL z=Z+=PV?9hyp8T=GDPq?uH33-NXU}`SNMr5v^57hLY8xcM7%;I_a^kD_f%MO5n|_7) zv(d?4>B5v*y#(6H@$nr$=dX#b7Pw`En)jIiK^ESv4}NdoQlk@p$nidn!Z%&WHA18Q zcvmA+QWs|%eJ#94A7(r`3e01^`A`Osh%{){i~$lMU=T|a^Sy8Yd_L(o zjmPiG!|&gB21k(Ie;2B=01A#J(Bb8Cv5|kbEZyQa6{SiI;poaD2bjttzt@GL3&-{K z&-H_rQvJL`Q*Od?obhu$~77 zwTQvOV5+TOIc2Rzx!#Lq9Pb8Fj}%aYEIO$5-``j5jPIC36g6+&wl6p??rsR4FZW%Q z*%crMt3>{17(}A~h>g3V4A*|8+|mDF9HO}7DyfTt3<{x@pc-yV8S_0opw4#t4t_?%3c&-k9s`dl4!L$;@DBEg+1{jR;< ze0tbR$UlQrR~GHu^S`}h^Ok*?m)$owxV9%Nk8C3!cj;`h#Nc|dh)n_)Eb$gccu{$f zd%$6XNXw@O>RFOZ1u}wD9IZ_9iRErP+Cb^R6_7OoWC|R6fqqDh%Fy z$0ZC(1)F|p2T7G}z5>TvCVc5Ks&LMx?dN*lJ2g)IS|!@>WnYbln%{-;g`?hd8j7}e z`$fdWl>JL%eW1)ul>@}hG3NDs4;p9j*t`ue9cJxO^X=t2`z}G^rCq3_1Z!f$hbL0A zPye*}`%`de{{+Apf=Zm~il*)D=`oln)qSSh_`m`C`snid2@{he5Js#{-R~loP_5Q+ z`HkE5q$E(IqKyi7lPxVRi**_*Z63@IiQhKAxs+E@Vipxm2jCjRA#Rvb-^a1tR_WwC z%JOMtRaMGx&+i1{dBt9SeDca!@bjsFcbui1WG+jaCELk75N4hSSU~oEhBSJn+Hy4cr7h5p3&`$NE03i|R5)4O7$WD=R##FpfK+fB{R|U|;r%-4K%4iY zDzh-$?e24Dofr=Kq?q>%?B0vu*YR)YLEGW{Ga+MHcf4@ceSQ_ZqFtzJ5YGf>|B_yL zFN~h#C!_(gj0_>9-Q*rwH(my^@V7VXMR;2JzOEl07t;Ob_J@Y`WrAn!9jFZtv1u1= zzI<@v2GEF$+Yx*<2~u;tXn0PjZ`>+nOH&H|q35;1l*i#iySp!GApUGUzs7Uzu_y9RKPr=RYCD_+yn|VaPc|s*37lU7Vtl8GAxI}!_ zAw>9Io~*2{R)B>1f5^`vBRU5=J;_a8g6+1E7tX;`E3`?l9#Q5=HlmCQ+5Mn*<5 z%F1^iOMdeNP~YBomZS0ZhW&Lf|Vud`w5ObN~;9t z*>3Bl9eS`(dyWUL%?Dl4N0;(>N-5gbHF<#UjP?1^kjevLzJO$o$fTORh|l*q4*fdz zK~cbiGk0$hc}<>Nig+@WadR{Ekrf(QD&ubxzfyRMwh5W0P0Y=C_m?D_SEnGS-LJ2# z1V-rmyovYBJzYnrjE*Y17F?xG%=&%4lBUfia1)1Uh24U5}>2M{}GRSF1pxxEc1I)sDzKt6;yV4m=)d` zX&>_Fq~4Fof3=~-XpZC;U95?ASio=AD;xW|nGBQ&g?P%w=sKf*Y%yVDE)%Tm3DsdP ziBUs!=3m;%3I-fnx~}8^)}PGgc^QB@G8x~U)@$E=k12P^-EKj=*Ly)HYnB<89z!2r zz(ed;Z)n1Mke`5L|NL9s;hPwGy4dA6ad)@*BO@zYSmhf^I+BRdH09{_`FKuby_{0b zIi1|cTte0S?27x>{JkGs=|5d|YE%!RSOMPq)*XZSpLOE#y>Nka#W3izU#7Ns@c8@f z=_a1>SMu7Cx%7noNmt7Dc$AFo?cF{Cq)Fj*KL|gMRBe~WZ*XRy_4M^cI6OJ-1_c#n zt2Ct`HTcQ-b@TB#>S{S&x#!r6)h6L*>txH9vkA%mPKOti%>&4J`g>mO7mq(z(M7yW z+UZ_C;9g&n1Syw~EtBhA5CRAK{NWkd0@e)zp$vZ-gQ16h0l`92!DrVJMG0o^V+Jr3 zZnkal7;Jq64ut>m0=O6}h^oWypIvW1V>O(pFuwcKtEGRi(dhcXL*${XQr=U+@BsRN zj?{%>K9w`3?HOE539OU4062$%aF*3AdWF7DcJ$!>``fnO7%uh)U(1$RR&^(c9 zpjZx{2q|$BF4u<-k;kS6%%dB_a@ZZnh6ycjev!v=B4`SRh76(#sr|Wo77adk1R@U# z+b`QC0(^6Gw@)vpw6yy+Q|&RQ>FN;%wY!gfU~mxb3s!g|C5tONEjT?zM- zg~jnbl+qUM%g}DJ5#0eL(8}IfeI;GY#=4vjiqbKf+Iq9xp<|q7W(Ggi=VEr|PxK9a zvCt8iugegaNY4^(29apjYs8lVHBth#Z+#U8O!)Rnz1n`_Xo&v`7NAJwL>; zH9j`B8y!wVk7QRnq4^qf;1NdtXx#UhlG3?63u4bL<75PtCZf;zx2`G@7{H4ae1?vu zjfq~(CK&RCB0Klvix{mzn{?!wV$o!!E1|;!k#3~cJ;&V73*DKRH}&@dJ29jKFpz%c zhYwzD8_Ecvhoi}ag`RoH$OI(nwh+{}&>kEx{p?O6rPO*=q$xRFORkXwk+a-*U;I`z z)4cAa+IFkC^zFe`54IX8^RZl<&ifpaE5H73{p1nU9o-$>Wqb0V`jofYR9+0Aw@qUW z_ic4uPI%JfjqNRqcI#mzmj}Qoz4J|!svN1f*p|*~Kq4ED<}1>Sy&d2u*5pLUaIbIk zQo%G-gL0}B7q50vRZhopZj{^1PbJYaAZW?~S(pdjR}UyCD_t+OEQ*)HLxVi_e+K`= zaFlpvL16I=)0a3555Jk}j7A31hYXD((US3(nvf1uj9c1p!&K}jjyR3C9Wl43zISI8nj z)are_*%?93-j|pzV_RCbtJsuAW#IJY5x5j9PL)h>NMj@V0eg2+~TDF@C-;Nrd?` z1g$$_@O&^*i}443xY+5K_Z8o7d^|CW-H$6&GKYd?97c>&II=v$ zGpOz5NuH-1ALB?-d@uBMwiOCF+Fm<{qgeo6E?xby|TWo0a6+x#d;8=Q$mGR!<$ z2KK#Dm%)4~D6spq^6q;WDP0`#{#Hgbb?dU=IFk;(F`!a%dUwx9A3pJ+#F=PV7ry62 zD+`MB-=%VB_t^%W^WBir5-2jhxb?qvWg(3P;_&Q9I^v2*ot#gOh%I(WwZFC5(nGsG z4OUp*hwk4=G4Y^tjA4lbMZ)t4SNV~)_^!l~)Jgrf5PH`>5wuf2+>9*e>{Cn`1-U1= ziub%vcGvcQLpA;ghDhUm`*Ie^I@v~a98gbbEwcOZefwPGk>2dN99cIiSU~;Er;{~n zw~EnSte_jUr5zP8gdygbM-}6|c)Hl!^?^C9H&T5~-TbgIo@KqY(Nhh5u=xYCxX0B3 zD;7tH!N$P{QaQFoS!R(94F$2>Tw+|@>r0|<@S^bqu~9%jWR#T54p(}|1G0kvQAZyx z({IC-R=b3mG$2k&s++~gzR>oZ2ADhC=-ree+9+c6(fT!x=}5wH^sv3qE(22AY2a56 z&mIkm`^Re>>$3=H&gVSQ9nV)j|M*?HW7fSR_VIqp9(>N?%ERgT^Loplog$uQ0a;0v ztP8<{^k={DOIjRKC(eoZ)?2Zg%ZKr4MTe&`lDr>1?ViB%F!+e$=9QIzQz>Hi&Vr7p z_!Nm2NI@?{W}ce$P~SWhsTyd8UcyxT>w2$VA`6!0UrIJ>YD%dQ2u(B9JH;V(ND3Vn zTx$)@$NWE$Q>5J}`Fz2gRyEylY z;_cPReSR#P>V5pixJ`(DZ#H#>SQzUw%4M>L72{ z2F@Lu++5DrzxUxJ^F=-a)NOyZ$@3{+jnnz%-fJUh^FDg>jo0eo`BD1B{4M>QcbU(- zSLj#$Ejl7M0vaNITjTp{se@M?M6Z=ThT!h}?O-pfXE7qJpOI!=vR- z*x5Kq}A$!gq#i7r=4$=g$4y30_~G$md@7W>Q{Uy$$osMz|rdv z6h6)U|kBAZ-HMr9kMs0hEq)T zJShGP7p90IMU1XD72Kl^f;AD3=6vZh;iFPT9PU!Wws z?C`ZYs+3Bvjd$m?WAB>yUx%-sz|fvfbIb0QrubEx8t#|&FN`jQ`)w0)3*Ea{{Q{?9 z9jgmEIX^7Lv=44CV;ndS7ko~$m(ov91M+9j#WfC&eCRwzXYHKGSM|}0W|s4`RQ)g~ zI}c2zze(X6E%^-kKbE+49?JDC(<89_o9G675c2d84BqE5R-+-+7&tQTY7jP_PXnVi zrxU6IqJq%X#!GX*(T3hP?Yq77ClK(V%J5h^Q}>=Y8WJa>rrzIe+W$A2Q0sr#%aZ*X zCt0w{DTq7o-mzXVLOI_%k_%7@+THpOyj~YSTCzg)_||nK*jqvda4-zZBvC;$ts=xH zVpI-&9r_r#N)3Xp*?SGuK$FnI++HT*gr#aN~SD*`HRB&Q3oVM<0{P-KQ}W7SR^ z+NlRzY0sJKRwZvqzm9Ck?!>2X_AT5?9#XwC9ohWBLvV)mR3dg0-ta~?_`Rr3rqymX z;F(CW2%mC3gaf;0@`d?-8$De&D<9J#EzAGUuL_Sy-l6_4Kj{DEdqRZ3Rvbyr)nJ+t zJr7ANQJj<{o|>?i4Xdua)hm|7vGd_QUi_s~(2)_{3}&eG>`(g{OUZN!}NV`W%K6Us3@ zOyt3aht(?>@Kv&%HfPMK5ZB1UZ4o~(pM(zF;wEnn`V*Z|D&3}E2M$5$tly?3VTifk z)FJI>&tDk0<}3?$CO4t$FSta1y>ElvtV+ChE`iO>uufYm@^#43l}CD2uoQaJ9gqnV z`V{|j-E~Nxg>hW8O!qOJ7U9wyb`E%Z*o3cuMr|zE&^}f5B_q}ZgsadPZ&(dBtvM}; zS+MyKe%xfAq|$(~SKu6!{9ou*!E&nITJ4OcXVX{2`FWIaoKSYy3K>a*fSP1F z%;Oi~sz|6cE=oY>wNUqIV_o1aC)6A!l+5-b$C+9wP!QCnVY^W-+~ebE;B?aebHQX-4?9Hf$Qg5YgiW7o8e*b?qY6pn|tl zhZGGWsa*~z1zu0M-G(!$8Q9SrDV@+j-|yk()A|PU!N1gHSNt6-Y$^6u(ut3@?f7 zy@BNyZzI+lYG^bDM46z}0^bq#IJ-_sZ84*9_GE(vGj&qT&1|BfqtLC_BxrBHA>7fD zAZ?_vYH35xNr>G@o#a&w>MBGjN$f;mjX>Sau4?pEeFyaUy)#}1=6!!?r5e19G2%Z# zxFuNHZbH)A-q2Y`m`pt7z@`pw3!A~eqRp3@pNG3De&`TNsS23d1>Rc^I9xo;L}Gj_ z_CJR0I}bn?jOk7bF#dMOo`Ll9|FkLoZ!&D<9*!=Bd4@VCe+JS=C?Wx?~)G()-NPasz)d~v?qzkFCfqU%Do z-^j!=Itji#&k(n5z`X8MA>IHC$`S(05gc@&>u?M)-6LK6998J78T>pCO=S#fK)>%^ zd}8ty7u@y5!!k5cAW?k9ZR#}tkLR55|I>l~|Myw{r*Ykq5oQt{Mj$A8?n823rY$sn z=T@h^e7@##H*oAbySffdFO^13Dq_%m*;4_gSJ+`Zpfc9KWp&&2=L4A5Z)ss?P`Y5A zSRidA+e^ZBiDMO^mCCR=l2|uG)1*6N1?z)YO4v&LFoyui`KK_SXHeiO=YsOWa!e;{ z|H4-Cp@&QkZ(%;!+G$|~IDXhsBzOLJ=(8MWm`UuNYh4f;x3tTp2-ASsk;UqeOmRWo z!)3(pvhDq_9%sXD1}-Q*a1WEk63q^s-`U1@2N68?!6c?Jlbmzz(;B=OrkK2c)xjZ; zW`;(DQ4&aqlv+$}`df=Jh$94vfeZW`K*A;D;m4sAh)o=1JW>H}TZ$0vs67{RpdH2z z!}3!z%%nt559C4eB8LLy1MQF&B-A>cCmm)e5LO22h&3OoKjbrNt^(-y&%ZF&&nq&F1wnT-S=J~|&Jo%lwwzSR{ z(`dJNEvjQs5?08dTfb9Bp9bvk)t=PKvjt^jrv&Msc;qGfws?|yov_Uf?r`&~bAH1k z=^_t(M_&gk_f+M_6vnOOMUvFc7jEdN4|8EMylHFBd?KI(cb zRIR>%=#L6z4b8t!fl9|7BF2!r8IGVL2`5rSS|e?taZFH00a+9;d=~qPVOSSd>iT|h z79%HQhaK-J`aP)?n}tC2s8w1RE$fY(T^j2{3 z>wFx79-R}Tw5#Fc898?~XN)C5K*2aF9o_gVb6s9MP8591Gxk$=atP8&rRxs~Ny96c zc4OVGU&v9ErR;}}=XpQC;wj8h2aH~DFrZE*Yw{;eW|El)>_Ax(^mu?Rde`wmb4=+9 z%zZC7I5Nq3-oW1_FMrOaNZd@ z|73t@&B@=RmU`jktvU z$K8x^GI(MtQn^m8X`3W*`5Z{C4Ww#q$@cw6 z=mQ>6o{>ke5@3x;9AID-?Rwm=x7K;9uq<)&{4-S?>1D;`wJSk}NHVAckrH5Uan$~| zSGtdC)FYajm-+5$VEIi%+2>B&&UI1hw*@EezBc;%dCup--y4CL*ZN#$o*#@NqoYlM zhqb0vA4F7gL2T+40dyw&bttYhsc6s-#`v2(&zsgo)B6m1_n&$+A`f|gpYm7oabJEp zWrcbGm-PLIGQj+yR9`9@jChQNg{6=w)-qEG?5Mv%=}1mqKIP8HVOv>Q33SXQuokBC z!nhOv%c)^3mG{k()96*g7lvMHYDV`N*h#CFFRZ~-&1pEYehZFk#w_C$CLEi|tbzcCJ1}M_R zfda248-uVLutxBJ3eOil>v0V>B424^P@}S$sjtv^r=UP!-2Dk_AzoR`5SWBk`^d=1 zsKFONKoJf&(93i@ot&QE)j=T)KKqin;)$S0?+h%E7yzvAfqH^UsmTAdx9ku3-^7EG zLL$5Ue5+`Zo)_za59-Ok&YsWz{<&Zi(Gws+&G9LSX05qgdCI%uY=B&wyFr^b-}x-? zLp}tyo4cZFLSO3i-rPyB_j#zlAgw$l$+JNWeNxtg*BdE+L+*zzr&XkO3(6WUcSQrM zaQ%!Y1h}KHz~gPtw`B$ahM}&$F<4X-%dn%YaJWg&{X-q2s)7v|AP z@pGxU>xdJ#A)h9qK#}Uxe+1Y&aXLY-#Y&=yy?|q45R}s^7ONZF-VA5FY zz@h+?1$%@LOZy{g<6o@(y}gD&^k_a_eO13^bGG|(pE9UAa8`6-fTP?Up1Y%6ZSh0b zeHLy$7Fh)R4F+PrY2^%LTkF6I8UB$0+rE$FuS?=fJj zj79XaR<}Tu(ZD%2V>RADR!^1%;?=j-zO0hc-8ia{HyfJ>xVaYG@y))?D~6m!6N_NC zy1b3Yt>TxcXw%^+ESza9da9i%nNGM8(lUg>De~ju6fFsz1Gb_APuF(Df)8L<{;+(a z8d*VOy!o~u5xA&G7G;!l*D2g){QzK1#NODv=mr$@B z=80f5Jw;uhU@GxBHn{g#zRLUOpJZ4HawW`3WV>Y*_|fKLY-GBq)LSZlR<9USC1AJ7 z1&%~7*y5dwF6`(`HV#_u?=J*{O;IW7FU=aaS(S2bjU;B2f*l6v7i`YMR`eF;1vpND zXqIrv4NxsE+r+xzZ`$=?v*9ADfAY9)K{c%VLC(;aA6B+o_p$nBe3*n*PsrP?~y{+i9+~;=6nQbpJjcvUHnWprf zE3q=6kPow6?=vwT4+e?x*nJOm`#gbR=8J`+neHUtY`+{Q&sjKnE&cdEshVW-x3C&; z5_@dA$9uAr(_dgevL-60yh8nGH{Snk26L0j`TaUyDSdNQ;P=n}94a3|JbL^35EILH zM_3Pj+wwBS`|P2Kg?ao8-n2JF_B#P|){p1bAHDb~ZDnQELeC#p%nzW|pMuF$PvE-q z^z?i{NjcGb06bJ(tsOY52Vc;4&-9jpNdq5ucVEiM$YcRO)z8k(G1-TFsu~)Y62SHG zn4+VOoPj|Z_!h&%S;h5as!yJf)QIW+!{aq;M&HbKFB2R4#Qg4e@0(1KsS8&@px?)#RBefI#o+-sL5?cxq2F@{6L?6pYi(q~ST&w} z44I4n@SlP%xEPo(`KI$6C$i$=T;64htx|rXCv=}Dl>US~ZPoJpez4rz+q2M?N!v5R zIoJ?RvVZUFrzQR#3F?#|)IrdBHh*1`2L&iE5@3}DajiF>vOU0FbRZ@T{!D?Xk4$Oa zy$XSB6TL#^B)W*YVCqYR;RSFpo?W$5vKC@$=a0jL`Mbm#lVpXhUE z(*(bOA9jDB-O2fgh1gHEBg2bw0JszAp zIiC2(@hk@z11gOlMntdXT9-PK{uADl=v008w=Psm&vA`KF(~5kjoSwL)YRZry8Ek- zs_jYF7NJ z(QwtvviL31;K1l?YKSdK{3y!#K5FnIOGbf?m@SQo39@OgeNcyRu5N}o9|>$o&snd@|(Vh##iDr)F(9e#nWXBJbW5s}%5 z8|A;XA6HEN?Hi8!pHQQ2H?>wHR^ye6vEk}RsG)p|bf@?C&O{eZ8_Vb?w*p@gd58|n zF)}Vt);$z>=*3lzgW?N_ua|QiKVZjvkl0lAgU#qH2xIsgV!c)<9{n1@rhgwPF8pJe z@*~%62o+l9b~{UX7MBReATo{Tp>jFX1s80Q_u~qll2bIEBHAR4PfQlW+y-tx#^Ccz z1|#_&sQJzyUs_e7XELEdC&cRLt)yWbff9HtHXiu5JnK#bBApAu*gVodXamp(dpU~YSJ14M0CasTd7W~cwHIXP35({TYhSub^rQvpTzOzUBSjhbR)Lw*P$$s z7^$9{$mCAHPAA##4CKf5saSADweT#26Q&ZiTu97l#SAr=a_XIqrFZ+rbf=#NH6Crc zCgQYYp-aXb(GcT?=sCuhHR4g2&y}gr6blvl(b6+^E&q`-o?+DxCL9xM+5GcDRPr$_Qm&ZG;$w zr4&1%Za`m7=@QxVQ8$DlE^9hjof$Y^c;+Y9inR)Jl2EZJG^cuEYQcHs3}F5UP$5{fIj zu4r&LVMpkf@x*$>&b3QET+@7nek)3QR+m^$cD9V$cDWX0B6(t8q9Tyg-S0{ z1J+4-q$+wXv^>F5lp*1^_!X{;5FK!Nj4`)4XvH1O(0y;j(2DqeWU=X-X`!P41|c)49itj9G&`fXu)N z94w-UxoTGQ{jXh_l{0k8hGsN0@cX*IC{Ov!~VT;@TPOXtLACLRK|3qQ&UCxgxs+yncCoUU}F4{&e=x#{nADTns-zDVz(6Dib z12ZAK+DVAt&U31Jn1&M+eMs9e3N1W=NTeQaE$L3RwB<%_=T2+oNB0t@>c-kE9ksYU z2ZzB$gUj)f?HfBXU@u`R^ye=}qbxWK-TG5VrmCvy8j z@kIk#8FK~b8H6|h8a-Z_+qG%Qu`2kmKCnaBjobI1#kQO9oA}s&OdC&JWf7CD6}p~x zmMzdbl_uaA1Po~o{Ty}W))Snd`>q3&Mm<0b#Hu}aT9MK7Tuq3W5Cyd=V3$i=U$@XK z(U#KCc+mZc&KQ_iK@$KeF)g$t%Lr&%9^(C<1o40?!gU8L?^~3># zR_{oze98+;Qqa|Pb+#Onla~jYU)w8;y9NBN1c1BqjjhisVXQVfhhR!gCo%3CG55y+F`4%;#s#8}W~E7U1zb*6nTr- z!=f<-6_sbFbC=d?YP%Md*>im7_CxDGipGMS#os2p4J!MitH4nZ@;PyVu9 zf<9hKJVHWK&_xRTcz`adSf_yoU$g#1j`d?Nv!M*#1LOYr`ApCy963C!0&JRr17?r^ zn~;N!MyLG+$vaz~qT=f1UYj{E^xky<5z@Z&Se;3dQ;ARuUQP|WWDZ~HK*jYwJ8GUV^W)Q`pQ*cD2q(tc)$pI;)L6BBDL`n$;3e8aV^&xnETxKx%b)o+WU8*LvtlBr0oU) zl_-v)77=n=X)P;_*-H9hlJFYqt@o5C6oKcM?X4sFV$-~A>?lX0EQx%JQAA{)*Orf{ zd1J2Sy$(yUPW->Z_XiY+8|?=lmVOI@?>9GvClYnmv4z`Jo%1TP6&~j@DI}BzvaOB%%(xA{jijQx% zY?$~M-o_GTDrh*&J6}*S^T47aFcNGL-xh3`aJJWclji1)h=MVL-wC(5W-L8u8K1&! zlqjgFC6!b{dJbh%Qd|w*Ym{B@7$_6HxY$2AeffQ$Y@?(N3WBcj@^b-ti8QsFN@aNo zLu&bL3Lwc>t*VU8qJiIB&%F&O{;6tDMsTle57vgFUpxpFi)>HtDXS+YA|_@%cms!k zjr#1_v$1AZ^ZD$Vl`1DQcEgoUJp^9w2&d*Obixxmd{s7J6M?`umkZW})jNFT@gRMk zGW^%CRF_{xWi5-5yDbVTh;SlRIyxmqMQMrBuwBB4plyewr5ogzG~owkOU%r?054~s z@iu+cYsZhlsQwtRh@3Vzu?@WQ*q?}~ffhQL*4ny5fBYy{!?TxOD(y?)(cM`mF+{P! zfr4pv98Wg2y!Pfzaq*-CV{RDR-k){@67{BdwT;BlHNmF8Ov07~_>q0!gs`{gW>9L@ z1tcT_x5n9kgCSKsRt{1q@LX=f;qdU7nALCBGzP~a)U`Cl#_gCkK}TY2kh_B`wXH$p>H(%+j|&``JI z;@Ug0tLHCOo9{*4vFmw-sw168hK)=)RbttHBQvPmS$60M}9 zgk5{^2m}oK{?C#is$#8T+W|^M>>!W~P`6+p!Mz7F?UjCqF9<#gS!kJ8~FU%NZxfl z1R9M#IT+C{`}+yZ_Tr-+H7)JP;@jIB4|>fY?xH5@NBa&fS#lrs`dxD;SxO#Ii5k*b zc>4D6OG&XX^Z7cSoBr^j5YJ4ztRxHzdfn=-@WNaf6tBSl;xytoQO~N@-ZP6QA;z=H zSA4!#P*pl=vOdAJE^L5_Ni3tioposQp)eDCa9tDB<(_MK4^2Gop}Dvnm&g@Qq{8g| za(cK;oSi>;CD%jI{Ch$6UBm|2Ts2vbXiL#N&BeJNC$ddBY=MZ%HuEO7FHfA)HGc5M zTC|w!n77-ucN`GZK`bfddHk$m%7?$Re_E38b4927+YFAtb*68e&JRVVLwNWixa8-r zClx{RL^)Egc}W4um$U)mmO5DK+CUXgi@j(cg;v*OBB3q|(hDNIE4l*>OL~ZmvUH4z zPQ>s%K16olA#-IalF-3CIJEVSr8tClaQ(2?=h$3pE%0Sii(o3z@2y0&bYm8 z@p*!zD~xt_cKD(785e#*Ll_3*yDZtwJm($5~qYyaM>d% zCI_CiIUuhIFn83}In+I$VM|owl~2^uQj!*EAoL+};71zqAerW72>Bw0{c>`0%H4j# zFaBg)mY>vjtkrsvZt|=#U7=uIn91AweW@qqaa%m#&!fcUC#jyNtJthP@A8$e>mx+4 zMG+?4g4?pLo(Dndc9gesvd5$RKRj~0wiM+=Mld8qm6d1zZh1|L)nhsgeP#V@04lY| z|NQSy6D(79kMh@oI2)&n8(wE%q;qO@WO$gM@P>kWy=VREk5{XX@&&S(OyIHtxe`He z%dH+=F{SmaHskyHm!Ou*=m{^!4ZoqxXTS8iDO*j`!JQ0Eu(iF5hfO3Um!;TlpZxoS zix&Uw;C27!cWGmrx7e}gZqhg>#-f>*2t9BL*{s+-XJlj~5DbrqD7?o5FFOXQHencN zMr9=}>LdHt`4)b^CW}9B95BXXxQ;xY2tC?b)S0w=hX2v->O1FYA1?mL(LtT@J6!G# ztpw?7lW}eXYgGl0b1Quot=f}_XoCE)kwzSWXYMsmpUT$9e?`L~Dyhr0Po%l&si}3h zYgDXRK@=u*DIVvnn~l!6)|TX`G^VPkNC;lKIjZcZqnb1k=uy+=Z*B3S_C^jBZpFn> zH7c9~9UUT)ciu^~d@>bS5x^Ai=iUlKln4DG=LU%fCl^;JI3z9hS&GVEB=QS6bg6IR z8coh~3C_+MEUPb&ecm*Im#nPkzD<2A9@H#;1?}Ds5%wtVd|+nr;H6KW3Kx&E?uL`0 zE;Z#{27`2I)s*SJ%t4)}Q8BA?`8>T3MjtlJEO#ZiYluHj9bRZrV2`_NT$zKr$6;%0 zi;~c2C9FaFGDUMszQ+AnAF19|MM%5UUP}`sfE|pv(9)qa;a@jjMwlYHLzmIFy>Sq}G7ST&7 zcISx?*hwQl@$!F;8z{i#)`lLN?|z%Lv~aNpF^k@|Pc?@9T5HE}B*}V6CX)jHRU<=q zG6A_B4vO9%vy{I$u?8+S-{zY90d1QdczH47J?*S;h+j6vSymXk6(|y-Sj9h7R^9{2 z0a$j!h8*XuTa!)x;&^!5sAN0>rvq$vZUTJw_FJ-Rx4=3;i4mKULeUEPWB6VZI1E8& zF&+fU&yt=JfYf};oqtG{m`SHxFz#NIs5~|GB{kujZ(f26A>o%H3}uXxDlIOkyEsY1 zUm}`*ptSX69wl>8HM+)iUJGRR0M@nxEhkic55$8k_}bZ7`W+FGil?hcCoxKIf2!c% zrlEBfaoUHzJ<6bBEj5>RX*u`ClSpc6Y9$yxU~N-wbQdg%ilC*)>#c#o(_CV#OLOCH zbK~MZ0H*=il<#8(5D_>| zj2J2=R_3mQNuzhj&Ij&bz%4xQ{sxyYxUhEGr0{X!s5i8%(Nju#;vH?Q+-dXahVo+mhDtMTB zMn;fUYG0DHLF#F-j{uVubEvC@5~cNX@NP$ccsWxCX7;%NkL9{kw?y@;KTX5SYj%|& z0JMvIm!ieh5QxQbQ`Z#$?tqc^I8d!*09Xs(O!5Q;(!}Zc95Cepg}b_*9u1xo8$v4^ z&dS}o6$0KqJmt9yynUp0J5x9GU9#JxsTa+$%=P{1y#59zfsA|NSjC*cB)$HEmDf)d zq|HCUFlUuD=Y?HX^eYIAAY)N~nsso;*PTVHkb}Pwir2*-lp~z1&wx9_ua>F{R<>4Y zC_MUgL9oP!_1kU~g0kAv?2Xa)mx28H1@#W>hu3>|V zCd(EWlt%&-{l~V5oIn+W>Lf%$i-P=fP=P9r&iXJU6A=lKEI|>}D!SOtKn>PzV|mZP z^CfThVJ{b#MVkBoQDkT}qo5@;#6n5so`BfLwydl^kEaFAKpsh!_7v3KeiJca(ENQe z&YJmh*k@ZkNsK8oKYy(O9Q;kf$0iGX+H90hnjs7K-83GtYVZbLzllsHS=LYbEHka& zOFap4$zQuIPv|(j#$8s^KC>~{+b7soQ9It-hp+aZU4mZ8QJcrL>+}1<_;0G6_|kVe zyDHL|@{?y_oJ@^`oZMepsjSMRgy3Ytn(Sn}bPQv|yQ1gXnaR_vhUohE6+SG$AlKX1 z0poi0E_B}{Nigbtc&kol3j3FzYt7l=ks-3HN9C?VaxQ6s{QFt^$k5P&9oZN#LZHBv z|ItdZsNT5rt$iAr=TK+Mt8#Hh68yTOk0>a5B7uSSp^4_z*)PItSuin|nQ*LH_)x>a zJrB{ks?IdzyLW}lUN`>Oh2RKpLtu+TG$Tq2ibCJBc}lvo;%V@Y_5eIubHR8bV&j== z{_CLj$ZY;wzZx)xf40Tq3tK;xNUmJr$@I55##!W>jhN*02_cOroJeUxp?RUu7bx)YB8HVboWw46m=7!~rr(RE`bx^Bcj9XEO4f1tY}0xE96y5C z?5PNZE_ZCdpLs?lWe@kC-d`ap0#<3yfO(YuuQC3K*n2FGx>h{0$_|KEe|NsrP0wTx zDBr(fRpJthM4JhLK-1t8=M@dt#k)ybultJQKK9j1Bz^mvJWfQy`T-wzHa=4`gv##NsI>yvgnP~b+3SK4&Z zgoK3PO;B3Sw_Sm~MVpgY6*$r__QK>Xt4*eWW!ix3F&nUz0e)9eU?PT=k+BmvgQ;m~ zScA)Fx=IFyR5}N<9-ac1qElcuQf^X$|0JlMMPBX9@LSafWXuQrxpsNBDnC{4$qg9a zI|SJ((ThOt!QW&OQc@AyZaO>`9YRX!bMiB+2z9zP-y#oeLbyRm7ZgMQP*i8U8&i&Y z0)&DBf78I>`mWw{)dMioA|QhRb_nWPTEBp4$4VD>hSQ$AJ_SNIKr?Qn>!1BVyi0{! zITj`SHaMlCLNoe343@cX%Nd}bpJ5QIJ)siDDt@Q7pug&kICs$)0`v$vmVggaY4_bF z(A@k2oOAG~ZELFn&H2BpTJ4Q z8dSLYFU%gi1De$$C)Gz(tV>1t)|PREx!_+C(tRzfTeQgRg`eXw2Bu;cQZ1b;whs!eYo~|w8$Om4 zbo-s0o|?O-7s#;JPCo+4PBcZs@9W{ek|)MqmCZaxIVN}50U7X8bEd{w6D+;Q&U)vX zxSJGL=yAiV)sL~Un|zXO7(uzDHsxfC%@lx$wg%%*WHwnpy1|BCuyjo;t6N~mXlt^9 zcrb!NDy`q7=PBOE5DcRcyPfPk1EWrAnwrIr?>^YB0y9HfQ&oBBh+QDX>Es<#Qc%F; zi`xTG#rToNDm-romGg-}q)l#elIQMpc*k(D{xI zYTxLnACBQSA47fKAphxw@X3?wHv^%$sQV8P`|-m}nnfujfbD#8nlIh`#>z1Jlhy6Dw~`Kh&ND=@D307+}>+_m`@8vkmTnPw3uEv}K098=QJs zcU914z53rb;{s`rabqZ^W?U{(QZ*Vnz8;5$o~(PxtT7)98utBotqQ1d}!H ztfv2*ngkthj^#W`6`P~V>cH0?k8TzfM|Dh1oyl^C0g>DM?A-V8J8KHvjYq86L(@O2 zuYhSRrH{`AxL*~d0#zR`Tj!uAW`p83)&hLQ{x%fu@^axXA$Ufw^5QEgI4hea0@;If zsj2aM*~mvi>JVch1l+R}Z6MC$4)f{{2CVA%11@leuj@BP(wee+}(j5k(F@0H(<~NI9oygy6}+F#U2&i2M^p$ zf(>|Ue43e=A!{j{eM7}-p4?X=-A3=9>-(Z_MfL3L3_SUVX|;wRRBkxD`rk@3Y;612 zcr4WJ)lRPv8ZB%=JS)`PYH{*dfv{^9TM!zh!U;@HqWuQW|JgsQvW@#3uwoWaf^UEj zCf|P^Z@A>34w@C+`lx!dfaKI3kTY!qtEe@vvr2R6VIZ;_yk-CNc@7ipa)8;)q}$a6 zUtYLhHP#J|=((=0pI=7Q(Jk_Uo5P{1xN1(#Ykm%5WO+x4IW#CD@M{sI|6Tf%GEh4H z{xd{){NIU~^w+PY{}K)avg&C@t7Twq)mxv^)!~ph%Fj-Vwb3NMKb^>?rbg7;Vr!C3 zO}}JXx$p|y@Z{#T9bMrsTPGP~LqesCQsciR6(pOgI7Zf2cTn>E`nbq1Qk10{f#!+O z)&mzwr@RjqHa2fMN0mwVq*oxjx?={nNJ{UivHw1KOcInybRFCU3@GsV#e^pzdUVRV z0r3c(m$#8Vx{wNONQEk-!T>_OWGsY)xyGxk&0dE8BZ01OOLQ}ig%on~ z+CIaC1uLAc#rp@@>Q!BX(895<`vgTWj2S=1%a7fKctdWWDanlM7eFKQ5UHr&_6t11 zt*jyjcQCyuy^G~-iH#*bk$=k~E*P@^WbGJ~wBo{JyYuj?vrXmpn8z&wblR5O~U9s2eo+oZ$gv*f2P@PpM6BnyE zi}=@okuj2w{^>o0i#e#(Q0VJm?NF$=`8eXBI=LxVaNpqDYD|Stqsdt-d_fs2G{P8c zIP|8M2VcWIr-oxm$0=Y`>b&B<{7i|Nd~tdghBw5`sfrafbQm(NF{@HO;s{BFoPs7E;f08(Y>^@C9=D0f8E-Qxa`8Tw77Ji5;jNH z?DWfx<*WS%+t+Hm0_oG9@Nn(H2EL|`nNJukZcxBz_+-D3ODxx4O74Z*-=9}lK%?&E zbr2W7gDwg#Fk42UDzU?Vd0@yn&r7nKgc3VxJVk}PcGx8uUC1*Aczbro*;{d|VoD3S z?}kHsANFlmeLCHku#*G?gbVn;5kN@(g}z6Bi+~0R-G@VHg{iks{@#TtWkPS&oyp;X zxXRc~!NzEmgoi7&MjL#!F0?;q!Nvus2J0;t&QX+^xT2$fm~dlFRHk!KkAtU!7?Dsa z?0~2~B4xKpxF}!Dj(0^7)-E4(6eNOP2w{(*N_mM=UNOp{#;sec-)^ zLn;PMMR*Y!I{0LC9)T_J;7eUIF5{WF`yc^{K9PVav102vq}6!0;o{Q(EBQljNO{!XGCu^Jn_<8jew$AsdU2Q3eVSYNSEwk|4Hn z%e;v#9(`YW3>*>$3JBw?P6Ttx)#<2BB*>|T{fbHavT0BrX*%XWTfs*(@D=}m>-oRq c-zE9;Iv0du`3DNB{r; literal 0 HcmV?d00001 diff --git a/docs/conf.py b/docs/conf.py index 67bf728660..fa01e8b2a0 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -220,7 +220,10 @@ # -- NBSphinx options -nbsphinx_thumbnails = {"notebooks/*": "_images/graphic-circular.png"} +nbsphinx_thumbnails = { + "notebooks/*": "_images/graphic-circular.png", + "notebooks/langmuir_analysis": "_static/notebook_images/langmuir_analysis.png", +} # adapted from https://github.com/spatialaudio/nbsphinx/blob/58b8034dd9d7349c1b4ac3e7a7d6baa87ab2a6a9/doc/conf.py diff --git a/docs/notebooks/langmuir_analysis.ipynb b/docs/notebooks/langmuir_analysis.ipynb index bd7985c66b..e9907acdb4 100644 --- a/docs/notebooks/langmuir_analysis.ipynb +++ b/docs/notebooks/langmuir_analysis.ipynb @@ -92,9 +92,6 @@ "collapsed": false, "jupyter": { "outputs_hidden": false - }, - "nbsphinx-thumbnail": { - "output-index": 2 } }, "outputs": [], From 12198216d04399df094a4d56e4f1b11541023763 Mon Sep 17 00:00:00 2001 From: Erik Everson Date: Sun, 17 Jan 2021 11:10:10 -0800 Subject: [PATCH 149/521] Apply suggestions from code review Co-authored-by: Nick Murphy --- docs/ad/index.rst | 2 +- plasmapy/analysis/__init__.py | 2 +- plasmapy/analysis/swept_langmuir/__init__.py | 2 +- plasmapy/analysis/swept_langmuir/floating_potential.py | 6 +++--- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/ad/index.rst b/docs/ad/index.rst index 99a56497ab..84b3bc2858 100644 --- a/docs/ad/index.rst +++ b/docs/ad/index.rst @@ -15,7 +15,7 @@ Think of the `plasmapy.analysis` as your toolbox. It has all the tools (functionality) you need to analyze your data. Functionality is built around `numpy arrays `_ and each function has a well-defined, focused task. For example, :func:`numpy.fft.fft` -does one specific task, compute the one-dimensional discrete Fourier Transform. +does one specific task: compute the one-dimensional discrete Fourier Transform. Similarly, :func:`plasmapy.analysis.swept_langmuir.find_floating_potential` only finds the floating potential for a given Langmuir trace. It does not have smoothing. It does not do any filtering. It does not do any signal diff --git a/plasmapy/analysis/__init__.py b/plasmapy/analysis/__init__.py index f89496db3e..c71ceecb53 100644 --- a/plasmapy/analysis/__init__.py +++ b/plasmapy/analysis/__init__.py @@ -1,4 +1,4 @@ -"""The analysis sub-package for PlasmaPy.""" +"""The analysis subpackage for PlasmaPy.""" __all__ = [] from plasmapy.analysis import fit_functions, swept_langmuir diff --git a/plasmapy/analysis/swept_langmuir/__init__.py b/plasmapy/analysis/swept_langmuir/__init__.py index aaeeebdf06..5b747c23eb 100644 --- a/plasmapy/analysis/swept_langmuir/__init__.py +++ b/plasmapy/analysis/swept_langmuir/__init__.py @@ -1,5 +1,5 @@ """ -Sub-Package containing routines for analyzing swept Langmuir probe traces. +Subpackage containing routines for analyzing swept Langmuir probe traces. """ __all__ = ["check_sweep", "find_floating_potential"] diff --git a/plasmapy/analysis/swept_langmuir/floating_potential.py b/plasmapy/analysis/swept_langmuir/floating_potential.py index 85c2d11edc..91b5f03f87 100644 --- a/plasmapy/analysis/swept_langmuir/floating_potential.py +++ b/plasmapy/analysis/swept_langmuir/floating_potential.py @@ -68,7 +68,7 @@ def find_floating_potential( threshold: positive, non-zero `int` Max allowed index distance between crossing-points before a new - crossing-island is formed. That is, if `threshold=5` then consecutive + crossing-island is formed. That is, if ``threshold=5`` then consecutive crossing-points are considered to be in the same crossing-island if they are within 5 index steps of each other. (Default: 1) @@ -110,14 +110,14 @@ def find_floating_potential( vf_err: `float` or `numpy.nan` The uncertainty associated with the floating potential calculation - (units same as `vf`). Returns `numpy.nan` if the floating potential + (units same as ``vf``). Returns `numpy.nan` if the floating potential can not be determined. Like :math:`V_f`:, the calculation depends on the applied fit function. The `root_solve()` method also describes how this is calculated. rsq: `float` The coefficient of determination (r-squared) value of the fit. See the - documentation of the `rsq` property on the associated fit function + documentation of the ``rsq`` property on the associated fit function (e.g. the `~plasmapy.analysis.fit_functions.ExponentialPlusOffset.rsq` property of From 47e9be997c02417011a269ae3e0a4a52a334a801 Mon Sep 17 00:00:00 2001 From: Erik Date: Sun, 17 Jan 2021 12:14:18 -0800 Subject: [PATCH 150/521] initial commit for test class TestFindFloatingPotential --- .../tests/test_floating_potential.py | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py diff --git a/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py b/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py new file mode 100644 index 0000000000..fa9871d303 --- /dev/null +++ b/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py @@ -0,0 +1,32 @@ +""" +Tests for functionality contained in +`plasmapy.analysis.swept_langmuir.floating_potential`. +""" + +import numpy as np +import pytest + +from plasmapy.analysis import fit_functions as ffuncs +from plasmapy.analysis.swept_langmuir.floating_potential import ( + FloatingPotentialResults, + find_floating_potential, +) + + +class TestFindFloatingPotential: + """ + Tests for function + `~plasmapy.analysis.swept_langmuir.floating_potential.find_floating_potential`. + """ + + def test_return_namedtuple(self): + """Test structure of the namedtuple used to return computed data.""" + + assert issubclass(FloatingPotentialResults, tuple) + assert hasattr(FloatingPotentialResults, "_fields") + assert ( + FloatingPotentialResults._fields + == ("vf", "vf_err", "rsq", "func", "islands", "indices") + ) + assert hasattr(FloatingPotentialResults, "_fields_defaults") + assert FloatingPotentialResults._field_defaults == {} From 4809b1d962405d637b2897711f3d175f546b2779 Mon Sep 17 00:00:00 2001 From: Erik Date: Sun, 17 Jan 2021 13:19:33 -0800 Subject: [PATCH 151/521] add test method test_call_of_check_sweep --- .../tests/test_floating_potential.py | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py b/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py index fa9871d303..803ba504b3 100644 --- a/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py +++ b/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py @@ -6,7 +6,10 @@ import numpy as np import pytest +from unittest import mock + from plasmapy.analysis import fit_functions as ffuncs +from plasmapy.analysis import swept_langmuir as _sl from plasmapy.analysis.swept_langmuir.floating_potential import ( FloatingPotentialResults, find_floating_potential, @@ -30,3 +33,23 @@ def test_return_namedtuple(self): ) assert hasattr(FloatingPotentialResults, "_fields_defaults") assert FloatingPotentialResults._field_defaults == {} + + def test_call_of_check_sweep(self): + """ + Test `find_floating_potential` appropriately calls + `plasmapy.analysis.swept_langmuir.helpers.check_sweep` so we can relay on + the `check_sweep` tests. + """ + varr = np.linspace(-20.0, 20.0, 100) + carr = np.linspace(-20.0, 20.0, 100) + + assert _sl.helpers.check_sweep is _sl.floating_potential.check_sweep + + with mock.patch(_sl.floating_potential.__name__ + '.check_sweep') as mock_cs: + find_floating_potential(voltage=varr, current=carr, fit_type="linear") + + assert mock_cs.call_count == 1 + assert mock_cs.call_args.kwargs == {} + assert len(mock_cs.call_args.args) == 2 + assert np.array_equal(mock_cs.call_args.args[0], varr) + assert np.array_equal(mock_cs.call_args.args[1], carr) From ab22acbd05872113d7a2471340b096a66faf4386 Mon Sep 17 00:00:00 2001 From: Erik Date: Sun, 17 Jan 2021 13:29:45 -0800 Subject: [PATCH 152/521] appease grumpy black --- .../swept_langmuir/tests/test_floating_potential.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py b/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py index 803ba504b3..dda1ae3345 100644 --- a/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py +++ b/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py @@ -27,9 +27,13 @@ def test_return_namedtuple(self): assert issubclass(FloatingPotentialResults, tuple) assert hasattr(FloatingPotentialResults, "_fields") - assert ( - FloatingPotentialResults._fields - == ("vf", "vf_err", "rsq", "func", "islands", "indices") + assert FloatingPotentialResults._fields == ( + "vf", + "vf_err", + "rsq", + "func", + "islands", + "indices", ) assert hasattr(FloatingPotentialResults, "_fields_defaults") assert FloatingPotentialResults._field_defaults == {} @@ -45,7 +49,7 @@ def test_call_of_check_sweep(self): assert _sl.helpers.check_sweep is _sl.floating_potential.check_sweep - with mock.patch(_sl.floating_potential.__name__ + '.check_sweep') as mock_cs: + with mock.patch(_sl.floating_potential.__name__ + ".check_sweep") as mock_cs: find_floating_potential(voltage=varr, current=carr, fit_type="linear") assert mock_cs.call_count == 1 From e405882d0285dce2a30f68e51d88d7081fc0acce Mon Sep 17 00:00:00 2001 From: Erik Date: Sun, 17 Jan 2021 13:30:46 -0800 Subject: [PATCH 153/521] appease grumpy black --- .../analysis/swept_langmuir/tests/test_floating_potential.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py b/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py index dda1ae3345..3f71792224 100644 --- a/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py +++ b/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py @@ -11,8 +11,8 @@ from plasmapy.analysis import fit_functions as ffuncs from plasmapy.analysis import swept_langmuir as _sl from plasmapy.analysis.swept_langmuir.floating_potential import ( - FloatingPotentialResults, find_floating_potential, + FloatingPotentialResults, ) From a10212f32a9a2aa89791c46af2d9f0a2823e1925 Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 18 Jan 2021 09:05:03 -0800 Subject: [PATCH 154/521] rename -> test_returned_namedtuple --- .../analysis/swept_langmuir/tests/test_floating_potential.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py b/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py index 3f71792224..28b260f717 100644 --- a/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py +++ b/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py @@ -22,7 +22,7 @@ class TestFindFloatingPotential: `~plasmapy.analysis.swept_langmuir.floating_potential.find_floating_potential`. """ - def test_return_namedtuple(self): + def test_returned_namedtuple(self): """Test structure of the namedtuple used to return computed data.""" assert issubclass(FloatingPotentialResults, tuple) From c36eee81da477eae202603be53595f93bd389c82 Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 18 Jan 2021 09:15:22 -0800 Subject: [PATCH 155/521] replace raise KeyError w/ more appropriate ValueError and descr --- plasmapy/analysis/swept_langmuir/floating_potential.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plasmapy/analysis/swept_langmuir/floating_potential.py b/plasmapy/analysis/swept_langmuir/floating_potential.py index 91b5f03f87..2b1cd3dda6 100644 --- a/plasmapy/analysis/swept_langmuir/floating_potential.py +++ b/plasmapy/analysis/swept_langmuir/floating_potential.py @@ -148,9 +148,9 @@ def find_floating_potential( fit_func = _settings[fit_type]["func"]() rtn["func"] = fit_func except KeyError: - raise KeyError( - f"Requested fit function '{fit_type}' is not a valid option. " - f"Examine kwarg 'fit_curve' for valid options." + raise ValueError( + f"Requested fit '{fit_type}' is not a valid option. Valid options " + f"are {list(_settings.keys())}." ) # check voltage and current arrays From 8622bddab1c0cc1dd22330e568701eef3f6f87f7 Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 18 Jan 2021 09:28:50 -0800 Subject: [PATCH 156/521] add TypeError check for min_points --- plasmapy/analysis/swept_langmuir/floating_potential.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/plasmapy/analysis/swept_langmuir/floating_potential.py b/plasmapy/analysis/swept_langmuir/floating_potential.py index 2b1cd3dda6..6c4a241011 100644 --- a/plasmapy/analysis/swept_langmuir/floating_potential.py +++ b/plasmapy/analysis/swept_langmuir/floating_potential.py @@ -178,6 +178,11 @@ def find_floating_potential( # condition min_points if min_points is None: min_points = int(np.max([5, np.around(min_point_factor * voltage.size)])) + elif not isinstance(min_points, (float, np.floating, int, np.integer)): + raise TypeError( + f"Argument 'min_points' is wrong type '{type(min_points)}', expecting " + f"an int or float." + ) elif min_points == 0: # this signals to use all points pass From 330ec495d85d7f4d4b78f1c11c1043deb1be3eee Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 18 Jan 2021 09:29:20 -0800 Subject: [PATCH 157/521] rephrase ValueError check for min_points --- plasmapy/analysis/swept_langmuir/floating_potential.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/plasmapy/analysis/swept_langmuir/floating_potential.py b/plasmapy/analysis/swept_langmuir/floating_potential.py index 6c4a241011..375426e031 100644 --- a/plasmapy/analysis/swept_langmuir/floating_potential.py +++ b/plasmapy/analysis/swept_langmuir/floating_potential.py @@ -77,7 +77,7 @@ def find_floating_potential( See **How it works** above for additional details. The following list specifies the optional values: - - ``min_points = None`` (Default) The larger of 5 and + - ``min_points = None`` (Default) The largest of 5 and ``factor * array_size`` is taken, where ``array_size`` is the size of ``voltage`` and ``factor = 0.1`` for ``fit_type = "linear"`` and ``0.2`` for ``"exponential"``. @@ -191,10 +191,7 @@ def find_floating_potential( elif min_points >= 1: min_points = int(np.round(min_points)) else: - raise ValueError( - f"Got {min_points}, but 'min_points' must be an int or float " - f"greater than or equal to 0." - ) + raise ValueError(f"Argument 'min_points' can not be negative ({min_points}).") # find possible crossing points (cp) lower_vals = current < 0 From 847109bd2274df8466d607887ba8d2626de864cf Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 18 Jan 2021 09:31:21 -0800 Subject: [PATCH 158/521] add test method test_raises --- .../tests/test_floating_potential.py | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py b/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py index 28b260f717..adcd34e1f2 100644 --- a/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py +++ b/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py @@ -57,3 +57,40 @@ def test_call_of_check_sweep(self): assert len(mock_cs.call_args.args) == 2 assert np.array_equal(mock_cs.call_args.args[0], varr) assert np.array_equal(mock_cs.call_args.args[1], carr) + + @pytest.mark.parametrize( + "kwargs, _error", + [ + # errors on kwarg fit_type + ( + { + "voltage": np.array([1.0, 2, 3, 4]), + "current": np.array([-1.0, 0, 1, 2]), + "fit_type": "wrong", + }, + ValueError, + ), + # + # errors on kwarg min_points + ( + { + "voltage": np.array([1.0, 2, 3, 4]), + "current": np.array([-1.0, 0, 1, 2]), + "min_points": "wrong", + }, + TypeError, + ), + ( + { + "voltage": np.array([1.0, 2, 3, 4]), + "current": np.array([-1.0, 0, 1, 2]), + "min_points": -1, + }, + ValueError, + ), + ], + ) + def test_raises(self, kwargs, _error): + """Test scenarios that raise `Exception`s.""" + with pytest.raises(_error): + find_floating_potential(**kwargs) From d1c780e8e8a3ff9a4475ef90d23d9d2f68f46ed1 Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 18 Jan 2021 15:07:57 -0800 Subject: [PATCH 159/521] move namedtuple test outside of TestFindFloatingPotential --- .../tests/test_floating_potential.py | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py b/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py index adcd34e1f2..4c56a012ee 100644 --- a/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py +++ b/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py @@ -5,6 +5,7 @@ import numpy as np import pytest +import sys from unittest import mock @@ -16,6 +17,28 @@ ) +def test_floating_potential_namedtuple(): + """ + Test structure of the namedtuple used to return computed floating potential + data. + """ + + assert issubclass(FloatingPotentialResults, tuple) + assert hasattr(FloatingPotentialResults, "_fields") + assert FloatingPotentialResults._fields == ( + "vf", + "vf_err", + "rsq", + "func", + "islands", + "indices", + ) + if sys.version_info >= (3, 7): + # TODO: remove if clause when python 3.6 support is dropped + assert hasattr(FloatingPotentialResults, "_field_defaults") + assert FloatingPotentialResults._field_defaults == {} + + class TestFindFloatingPotential: """ Tests for function From 94a6246e0f1fd672448f82e0e769081353596cec Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 18 Jan 2021 15:18:24 -0800 Subject: [PATCH 160/521] actually delete test_returned_namedtuple from TestFindFloatingPotential *facepalm* --- .../tests/test_floating_potential.py | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py b/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py index 4c56a012ee..4843aaf5aa 100644 --- a/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py +++ b/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py @@ -45,22 +45,6 @@ class TestFindFloatingPotential: `~plasmapy.analysis.swept_langmuir.floating_potential.find_floating_potential`. """ - def test_returned_namedtuple(self): - """Test structure of the namedtuple used to return computed data.""" - - assert issubclass(FloatingPotentialResults, tuple) - assert hasattr(FloatingPotentialResults, "_fields") - assert FloatingPotentialResults._fields == ( - "vf", - "vf_err", - "rsq", - "func", - "islands", - "indices", - ) - assert hasattr(FloatingPotentialResults, "_fields_defaults") - assert FloatingPotentialResults._field_defaults == {} - def test_call_of_check_sweep(self): """ Test `find_floating_potential` appropriately calls From f447f08912b422b06ab2d3f33fdb248d23772786 Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 18 Jan 2021 15:22:56 -0800 Subject: [PATCH 161/521] update test_call_of_check_sweep s.t. mock test work on py36+ --- .../swept_langmuir/tests/test_floating_potential.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py b/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py index 4843aaf5aa..3ee9f3e86c 100644 --- a/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py +++ b/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py @@ -60,10 +60,14 @@ def test_call_of_check_sweep(self): find_floating_potential(voltage=varr, current=carr, fit_type="linear") assert mock_cs.call_count == 1 - assert mock_cs.call_args.kwargs == {} - assert len(mock_cs.call_args.args) == 2 - assert np.array_equal(mock_cs.call_args.args[0], varr) - assert np.array_equal(mock_cs.call_args.args[1], carr) + + # passed args + assert len(mock_cs.call_args[0]) == 2 + assert np.array_equal(mock_cs.call_args[0][0], varr) + assert np.array_equal(mock_cs.call_args[0][1], carr) + + # passed kwargs + assert mock_cs.call_args[1] == {} @pytest.mark.parametrize( "kwargs, _error", From 387d25c79e3f9dde619d7a97b9cb13b0c4c889bc Mon Sep 17 00:00:00 2001 From: Erik Date: Sun, 31 Jan 2021 10:45:34 -0800 Subject: [PATCH 162/521] fix wording --- plasmapy/analysis/swept_langmuir/floating_potential.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plasmapy/analysis/swept_langmuir/floating_potential.py b/plasmapy/analysis/swept_langmuir/floating_potential.py index 375426e031..437fa46414 100644 --- a/plasmapy/analysis/swept_langmuir/floating_potential.py +++ b/plasmapy/analysis/swept_langmuir/floating_potential.py @@ -26,7 +26,7 @@ def find_floating_potential( """ Determines the floating potential (:math:`V_f`) for a given Current-Voltage (IV) curve obtained from a swept Langmuir probe. The floating potential is - the probe bias where the collected current equals to zero :math:`I = 0`. + the probe bias where the collected current equals zero :math:`I = 0`. **How it works** From 436d40cd0cffe3e9b65cd3b4718143b5ae3b0646 Mon Sep 17 00:00:00 2001 From: Erik Everson Date: Sun, 31 Jan 2021 10:45:45 -0800 Subject: [PATCH 163/521] Apply suggestions from code review Co-authored-by: Nick Murphy --- docs/ad/diagnostics/langmuir.rst | 2 +- plasmapy/analysis/swept_langmuir/helpers.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/ad/diagnostics/langmuir.rst b/docs/ad/diagnostics/langmuir.rst index ce0bab6fef..17522b7560 100644 --- a/docs/ad/diagnostics/langmuir.rst +++ b/docs/ad/diagnostics/langmuir.rst @@ -1,7 +1,7 @@ .. include:: /ad/ad_attention.inc .. warning:: - This package will be deprecated in favor of `plasmapy.analysis.swept_langmuir`. + This module will be deprecated in favor of `plasmapy.analysis.swept_langmuir`. .. _langmuir: diff --git a/plasmapy/analysis/swept_langmuir/helpers.py b/plasmapy/analysis/swept_langmuir/helpers.py index ec85ccfaa1..e842f93278 100644 --- a/plasmapy/analysis/swept_langmuir/helpers.py +++ b/plasmapy/analysis/swept_langmuir/helpers.py @@ -31,7 +31,7 @@ def check_sweep(voltage: np.ndarray, current: np.ndarray) -> None: If the ``voltage`` array is not monotonically increasing. - If the ``current`` array never cross zero (i.e. has not floating + If the ``current`` array never crosses zero (i.e. has no floating potential). If the ``current`` array does not start form a negative ion-saturation From 1d7ce218bd02b04fc9fd935f949268b65a6154e1 Mon Sep 17 00:00:00 2001 From: Erik Date: Sun, 31 Jan 2021 10:52:23 -0800 Subject: [PATCH 164/521] py36 was dropped, so remove associated conditionals/restrictions --- .../swept_langmuir/tests/test_floating_potential.py | 7 ++----- plasmapy/analysis/swept_langmuir/tests/test_helpers.py | 4 +--- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py b/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py index 3ee9f3e86c..3934fb6717 100644 --- a/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py +++ b/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py @@ -5,7 +5,6 @@ import numpy as np import pytest -import sys from unittest import mock @@ -33,10 +32,8 @@ def test_floating_potential_namedtuple(): "islands", "indices", ) - if sys.version_info >= (3, 7): - # TODO: remove if clause when python 3.6 support is dropped - assert hasattr(FloatingPotentialResults, "_field_defaults") - assert FloatingPotentialResults._field_defaults == {} + assert hasattr(FloatingPotentialResults, "_field_defaults") + assert FloatingPotentialResults._field_defaults == {} class TestFindFloatingPotential: diff --git a/plasmapy/analysis/swept_langmuir/tests/test_helpers.py b/plasmapy/analysis/swept_langmuir/tests/test_helpers.py index a46eab6a16..4607a0f751 100644 --- a/plasmapy/analysis/swept_langmuir/tests/test_helpers.py +++ b/plasmapy/analysis/swept_langmuir/tests/test_helpers.py @@ -3,12 +3,10 @@ import numpy as np import pytest -from contextlib import ExitStack as does_not_raise +from contextlib import nullcontext as does_not_raise from plasmapy.analysis.swept_langmuir.helpers import check_sweep -# TODO: replace ExitStack with nullcontext when we require >= python 3.7 - @pytest.mark.parametrize( "voltage, current, with_context", From 1e0eb571f21e536af36c0168164a8987469f09e9 Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 1 Feb 2021 13:58:42 -0800 Subject: [PATCH 165/521] for `check_sweep`, add functionality that returns the voltage/current arrays; converts input types of list/tuple; add check for appropriate dtype; add kwarg strip_units (handling of astropy units) --- plasmapy/analysis/swept_langmuir/helpers.py | 77 +++++++++++++++++++-- 1 file changed, 71 insertions(+), 6 deletions(-) diff --git a/plasmapy/analysis/swept_langmuir/helpers.py b/plasmapy/analysis/swept_langmuir/helpers.py index e842f93278..3ee7816c6b 100644 --- a/plasmapy/analysis/swept_langmuir/helpers.py +++ b/plasmapy/analysis/swept_langmuir/helpers.py @@ -1,10 +1,13 @@ """Helper functions for analyzing swept Langmuir traces.""" __all__ = ["check_sweep"] +import astropy.units as u import numpy as np -def check_sweep(voltage: np.ndarray, current: np.ndarray) -> None: +def check_sweep( + voltage: np.ndarray, current: np.ndarray, strip_units: bool = True, +) -> (np.ndarray, np.ndarray): """ Function for checking that the voltage and current arrays are properly formatted for analysis by `plasmapy.analysis.swept_langmuir`. @@ -20,29 +23,66 @@ def check_sweep(voltage: np.ndarray, current: np.ndarray) -> None: Values should start from a negative ion-saturation current and increase to a positive electron-saturation current. + strip_units: `bool` + (Default: `True`) If `True``, then the units on ``voltage`` and/or + ``current`` will be stripped if either are passed in as an Astropy + `~astropy.units.Quantity`. + + Returns + ------- + voltage : `numpy.ndarray` + Input argument ``voltage`` after it goes through all of its checks + and conditioning. + + current : `numpy.ndarray` + Input argument ``current`` after it goes through all of its checks + and conditioning. + Raises ------ `TypeError` If either the ``voltage`` or ``current`` arrays are not instances of a `numpy.ndarray`. - `ValueError` + `ValueError`: If either the ``voltage`` or ``current`` arrays are not 1D. + `ValueError` If the ``voltage`` array is not monotonically increasing. + `ValueError` If the ``current`` array never crosses zero (i.e. has no floating potential). + `ValueError` If the ``current`` array does not start form a negative ion-saturation current and increases to a positive electron-saturation current. + `ValueError` + If either the ``voltage`` or ``current`` array does not have a + `numpy.dtype` of either `numpy.integer` or `numpy.floating`. + """ - # examine voltage array - if not isinstance(voltage, np.ndarray): + # -- examine voltage array -- + # check type + if isinstance(voltage, np.ndarray): + pass + elif isinstance(voltage, (list, tuple)): + voltage = np.array(voltage) + else: raise TypeError( f"Expected 1D numpy array for voltage, but got {type(voltage)}.", ) + + # check array structure + if not ( + np.issubdtype(voltage.dtype, np.floating) + or np.issubdtype(voltage.dtype, np.integer) + ): + raise ValueError( + f"Expected 1D numpy array of floats or integers for voltage, but" + f" got an array with dytpe '{voltage.dtype}'." + ) elif voltage.ndim != 1: raise ValueError( f"Expected 1D numpy array for voltage, but got array with " @@ -51,11 +91,30 @@ def check_sweep(voltage: np.ndarray, current: np.ndarray) -> None: elif not np.all(np.diff(voltage) >= 0): raise ValueError(f"The voltage array is not monotonically increasing.") - # examine current array - if not isinstance(current, np.ndarray): + # strip units + if isinstance(voltage, u.Quantity) and strip_units: + voltage = voltage.value + + # -- examine current array -- + # check type + if isinstance(current, np.ndarray): + pass + elif isinstance(current, (list, tuple)): + current = np.array(current) + else: raise TypeError( f"Expected 1D numpy array for current, but got {type(current)}.", ) + + # check array structure + if not ( + np.issubdtype(current.dtype, np.floating) + or np.issubdtype(current.dtype, np.integer) + ): + raise ValueError( + f"Expected 1D numpy array of floats or integers for current, but" + f" got an array with dytpe '{current.dtype}'." + ) elif current.ndim != 1: raise ValueError( f"Expected 1D numpy array for current, but got array with " @@ -77,3 +136,9 @@ def check_sweep(voltage: np.ndarray, current: np.ndarray) -> None: f"Incompatible arrays, 'voltage' size {voltage.size} must be the same" f" as the 'current' size {current.size}." ) + + # strip units + if isinstance(current, u.Quantity) and strip_units: + current = current.value + + return voltage, current From c71f5fdc980042bc036f83b862167e7f4b65f8f5 Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 1 Feb 2021 13:59:01 -0800 Subject: [PATCH 166/521] update tests for `check_sweep` --- .../swept_langmuir/tests/test_helpers.py | 128 +++++++++++++++++- 1 file changed, 122 insertions(+), 6 deletions(-) diff --git a/plasmapy/analysis/swept_langmuir/tests/test_helpers.py b/plasmapy/analysis/swept_langmuir/tests/test_helpers.py index 4607a0f751..6c07cb8138 100644 --- a/plasmapy/analysis/swept_langmuir/tests/test_helpers.py +++ b/plasmapy/analysis/swept_langmuir/tests/test_helpers.py @@ -1,5 +1,6 @@ """Tests for `plasmapy.analysis.swept_langmuir.helpers`.""" +import astropy.units as u import numpy as np import pytest @@ -9,61 +10,176 @@ @pytest.mark.parametrize( - "voltage, current, with_context", + "voltage, current, kwargs, with_context, expected", [ # the one that works - (np.linspace(-40.0, 40, 100), np.linspace(-10.0, 30, 100), does_not_raise()), + ( + np.linspace(-40.0, 40, 100), + np.linspace(-10.0, 30, 100), + {}, + does_not_raise(), + "expected same as inputs", + ), # -- voltage cases -- # not the right type - ("not a numpy array", np.linspace(-10.0, 30, 100), pytest.raises(TypeError)), + ( + "not a numpy array", + np.linspace(-10.0, 30, 100), + {}, + pytest.raises(TypeError), + None, + ), # not 1D ( np.empty((2, 2), dtype=np.float64), np.linspace(-10.0, 30, 100), + {}, pytest.raises(ValueError), + None, ), # not linearly increasing ( np.linspace(40.0, -40, 100), np.linspace(-10.0, 30, 100), + {}, + pytest.raises(ValueError), + None, + ), + # list to array + ( + [-5.0, -4, -3, -2, -1, 0, 1, 2, 3, 4], + np.linspace(-10.0, 30, 10), + {}, + does_not_raise(), + ( + np.array([-5.0, -4, -3, -2, -1, 0, 1, 2, 3, 4]), + np.linspace(-10.0, 30, 10), + ), + ), + # wrong dtype + ( + np.array(["one", "two", "three", "four", "five"]), + np.linspace(-10.0, 30, 5), + {}, pytest.raises(ValueError), + None, + ), + ( + ["one", "two", "three", "four", "five"], + np.linspace(-10.0, 30, 5), + {}, + pytest.raises(ValueError), + None, ), # -- current cases -- # not the right type - (np.linspace(-40.0, 40, 100), "not a numpy array", pytest.raises(TypeError)), + ( + np.linspace(-40.0, 40, 100), + "not a numpy array", + {}, + pytest.raises(TypeError), + None, + ), # not 1D ( np.linspace(-40.0, 40, 100), np.empty((2, 2), dtype=np.float64), + {}, pytest.raises(ValueError), + None, ), # no floating potential (i.e. current never crosses zero) ( np.linspace(-40.0, 40, 100), np.linspace(10.0, 30, 100), + {}, pytest.raises(ValueError), + None, ), ( np.linspace(-40.0, 40, 100), np.linspace(-30.0, -5, 100), + {}, pytest.raises(ValueError), + None, ), # current needs to start from negative and go positive ( np.linspace(-40.0, 40, 100), np.linspace(30.0, -5, 100), + {}, + pytest.raises(ValueError), + None, + ), + # list to array + ( + np.linspace(-40.0, 40, 10), + [-5.0, -4, -3, -2, -1, 0, 1, 2, 3, 4], + {}, + does_not_raise(), + ( + np.linspace(-40.0, 40, 10), + np.array([-5.0, -4, -3, -2, -1, 0, 1, 2, 3, 4]), + ), + ), + # wrong dtype + ( + np.linspace(-40.0, 40, 5), + np.array(["one", "two", "three", "four", "five"]), + {}, pytest.raises(ValueError), + None, + ), + ( + np.linspace(-40.0, 40, 5), + ["one", "two", "three", "four", "five"], + {}, + pytest.raises(ValueError), + None, ), # -- mixed cases -- # voltage and current must have the same size ( np.linspace(-40.0, 40, 100), np.linspace(-5.0, 30, 150), + {}, pytest.raises(ValueError), + None, + ), + # -- cases with units -- + # Note: u.Quantity is a subclass of np.ndarray, so all the tests above + # still work for an input argument that is a u.Quantity + ( + np.linspace(-40.0, 40, 100) * u.volt, + np.linspace(-10.0, 30, 100) * u.amp, + {"strip_units": False}, + does_not_raise(), + "expected same as inputs", + ), + ( + np.linspace(-40.0, 40, 100) * u.volt, + np.linspace(-10.0, 30, 100) * u.amp, + {}, + does_not_raise(), + ( + np.linspace(-40.0, 40, 100), + np.linspace(-10.0, 30, 100), + ) ), ], ) -def test_check_sweep(voltage, current, with_context): +def test_check_sweep(voltage, current, kwargs, with_context, expected): """Test functionality of `plasmapy.analysis.swept_langmuir.helpers.check_sweep`.""" with with_context: - check_sweep(voltage=voltage, current=current) + rtn_voltage, rtn_current = check_sweep( + voltage=voltage, + current=current, + **kwargs, + ) + + if expected == "expected same as inputs": + assert np.allclose(rtn_voltage, voltage) + assert np.allclose(rtn_current, current) + else: + assert np.allclose(rtn_voltage, expected[0]) + assert np.allclose(rtn_current, expected[1]) From f0037799a7ef098ec106f78ce93c9a4b914f2186 Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 1 Feb 2021 14:06:16 -0800 Subject: [PATCH 167/521] appease grumpy black --- plasmapy/analysis/swept_langmuir/helpers.py | 4 ++-- plasmapy/analysis/swept_langmuir/tests/test_helpers.py | 9 ++------- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/plasmapy/analysis/swept_langmuir/helpers.py b/plasmapy/analysis/swept_langmuir/helpers.py index 3ee7816c6b..cd2a6f0652 100644 --- a/plasmapy/analysis/swept_langmuir/helpers.py +++ b/plasmapy/analysis/swept_langmuir/helpers.py @@ -108,8 +108,8 @@ def check_sweep( # check array structure if not ( - np.issubdtype(current.dtype, np.floating) - or np.issubdtype(current.dtype, np.integer) + np.issubdtype(current.dtype, np.floating) + or np.issubdtype(current.dtype, np.integer) ): raise ValueError( f"Expected 1D numpy array of floats or integers for current, but" diff --git a/plasmapy/analysis/swept_langmuir/tests/test_helpers.py b/plasmapy/analysis/swept_langmuir/tests/test_helpers.py index 6c07cb8138..ba28df2b08 100644 --- a/plasmapy/analysis/swept_langmuir/tests/test_helpers.py +++ b/plasmapy/analysis/swept_langmuir/tests/test_helpers.py @@ -161,10 +161,7 @@ np.linspace(-10.0, 30, 100) * u.amp, {}, does_not_raise(), - ( - np.linspace(-40.0, 40, 100), - np.linspace(-10.0, 30, 100), - ) + (np.linspace(-40.0, 40, 100), np.linspace(-10.0, 30, 100)), ), ], ) @@ -172,9 +169,7 @@ def test_check_sweep(voltage, current, kwargs, with_context, expected): """Test functionality of `plasmapy.analysis.swept_langmuir.helpers.check_sweep`.""" with with_context: rtn_voltage, rtn_current = check_sweep( - voltage=voltage, - current=current, - **kwargs, + voltage=voltage, current=current, **kwargs, ) if expected == "expected same as inputs": From 031cdb0dd1eb9d776ae9e4dc38953c90389cd39a Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 1 Feb 2021 15:31:20 -0800 Subject: [PATCH 168/521] replace ' with " --- .../find_floating_potential.ipynb | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb b/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb index 58da18a42e..ac02bf0bbb 100644 --- a/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb +++ b/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb @@ -25,7 +25,7 @@ "\n", "from plasmapy.analysis import swept_langmuir as sla\n", "\n", - "plt.rcParams['figure.figsize'] = [10.5, 0.56 * 10.5]" + "plt.rcParams[\"figure.figsize\"] = [10.5, 0.56 * 10.5]" ] }, { @@ -272,7 +272,7 @@ "axs[0].set_ylabel(\"Current (A)\", fontsize=12)\n", "\n", "axs[0].plot(voltage, current, zorder=10, label=\"Sweep Data\")\n", - "axs[0].axhline(0.0, color='r', linestyle='--', label=\"I = 0\")\n", + "axs[0].axhline(0.0, color=\"r\", linestyle=\"--\", label=\"I = 0\")\n", "axs[0].legend(fontsize=12)\n", "\n", "# zoom on fit\n", @@ -322,12 +322,12 @@ " axs[ii].fill_between(vfit, ifit + ifit_err, ifit - ifit_err, \n", " color=\"orange\", alpha=0.12, zorder=0,\n", " label=\"Fit Error\")\n", - " axs[ii].axhline(0.0, color='r', linestyle='--')\n", + " axs[ii].axhline(0.0, color=\"r\", linestyle=\"--)\n", " axs[ii].fill_between([fit.vf - fit.vf_err, fit.vf + fit.vf_err], \n", " axs[1].get_ylim()[0],\n", " axs[1].get_ylim()[1],\n", - " color='grey', alpha=0.1)\n", - " axs[ii].axvline(fit.vf, color='grey')\n", + " color=\"grey\", alpha=0.1)\n", + " axs[ii].axvline(fit.vf, color=\"grey\")\n", " axs[ii].legend(fontsize=12)\n", "\n", " # add text\n", @@ -339,9 +339,16 @@ " txt_loc[0] -= 0.02\n", " txt_loc[1] -= 0.26\n", " axs[ii].text(txt_loc[0], txt_loc[1], txt, \n", - " fontsize='large', transform=axs[ii].transAxes,\n", + " fontsize=\"large\", transform=axs[ii].transAxes,\n", " ha=\"right\")" ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": { From f9b890c01e8b17e93a992ed13004fa4050ed64a6 Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 1 Feb 2021 15:45:33 -0800 Subject: [PATCH 169/521] appease grumpy black --- docs/notebooks/langmuir_samples/_generate_noisy.ipynb | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/notebooks/langmuir_samples/_generate_noisy.ipynb b/docs/notebooks/langmuir_samples/_generate_noisy.ipynb index 513529b370..f54e90963d 100644 --- a/docs/notebooks/langmuir_samples/_generate_noisy.ipynb +++ b/docs/notebooks/langmuir_samples/_generate_noisy.ipynb @@ -22,7 +22,7 @@ "\n", "from plasmapy.utils.decorators import validate_quantities\n", "\n", - "plt.rcParams['figure.figsize'] = [10.5, 0.56 * 10.5]" + "plt.rcParams[\"figure.figsize\"] = [10.5, 0.56 * 10.5]" ] }, { @@ -105,28 +105,28 @@ "outputs": [], "source": [ "figwidth, figheight = plt.rcParams[\"figure.figsize\"]\n", - "figheight = 2. * figheight\n", + "figheight = 2.0 * figheight\n", "fig, axs = plt.subplots(3, 1, figsize=[figwidth, figheight])\n", "\n", "# Current plot\n", "axs[0].set_ylabel(\"Current\", fontsize=12)\n", "axs[0].set_xlabel(\"Index\", fontsize=12)\n", "axs[0].plot(i_noisy, label=\"noisy\")\n", - "axs[0].plot(current, color='r', label=\"original\")\n", + "axs[0].plot(current, color=\"r\", label=\"original\")\n", "axs[0].legend(fontsize=12)\n", "\n", "# Voltage plot\n", "axs[1].set_ylabel(\"Voltage\", fontsize=12)\n", "axs[1].set_xlabel(\"Index\", fontsize=12)\n", "axs[1].plot(v_noisy, label=\"noisy\")\n", - "axs[1].plot(voltage, color='r', label=\"original\")\n", + "axs[1].plot(voltage, color=\"r\", label=\"original\")\n", "axs[1].legend(fontsize=12)\n", "\n", "# IV plot\n", "axs[2].set_ylabel(\"Current\", fontsize=12)\n", "axs[2].set_xlabel(\"Voltage\", fontsize=12)\n", "axs[2].plot(v_noisy, i_noisy, label=\"noisy\")\n", - "axs[2].plot(voltage, current, color='r', label=\"original\")\n", + "axs[2].plot(voltage, current, color=\"r\", label=\"original\")\n", "axs[2].legend(fontsize=12)" ] }, From aa7da052cce4d59e31bcaee45989a94e4c57340f Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 1 Feb 2021 15:46:15 -0800 Subject: [PATCH 170/521] appease grumpy black --- .../analysis/swept_langmuir/find_floating_potential.ipynb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb b/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb index ac02bf0bbb..4d6289696d 100644 --- a/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb +++ b/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb @@ -264,7 +264,7 @@ "outputs": [], "source": [ "figwidth, figheight = plt.rcParams[\"figure.figsize\"]\n", - "figheight = 2. * figheight\n", + "figheight = 2.0 * figheight\n", "fig, axs = plt.subplots(3, 1, figsize=[figwidth, figheight])\n", "\n", "# plot original data\n", From cca67508c7ece2b54ce8141857c21487eda692ee Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 1 Feb 2021 15:50:17 -0800 Subject: [PATCH 171/521] appease grumpy black --- docs/notebooks/langmuir_samples/_generate_noisy.ipynb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/notebooks/langmuir_samples/_generate_noisy.ipynb b/docs/notebooks/langmuir_samples/_generate_noisy.ipynb index f54e90963d..4bec43933e 100644 --- a/docs/notebooks/langmuir_samples/_generate_noisy.ipynb +++ b/docs/notebooks/langmuir_samples/_generate_noisy.ipynb @@ -16,8 +16,8 @@ "outputs": [], "source": [ "import astropy.units as u\n", - "import numpy as np\n", "import matplotlib.pyplot as plt\n", + "import numpy as np\n", "import os\n", "\n", "from plasmapy.utils.decorators import validate_quantities\n", @@ -69,7 +69,7 @@ " \"\"\"\n", " sig_pwr = signal ** 2\n", " sig_pwr_ave = np.mean(sig_pwr)\n", - " sig_pwr_ave_db = 10. * np.log10(sig_pwr_ave)\n", + " sig_pwr_ave_db = 10.0 * np.log10(sig_pwr_ave)\n", " \n", " noise_pwr_ave_db = sig_pwr_ave_db - snr_db.value\n", " noise_pwr_ave = 10.0 ** (noise_pwr_ave_db / 10.0)\n", From c0a7f97e57dbd9caf1ef78ab32927b08fd805acf Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 1 Feb 2021 15:54:07 -0800 Subject: [PATCH 172/521] appease grumpy black --- docs/notebooks/langmuir_samples/_generate_noisy.ipynb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/notebooks/langmuir_samples/_generate_noisy.ipynb b/docs/notebooks/langmuir_samples/_generate_noisy.ipynb index 4bec43933e..f3349d85f0 100644 --- a/docs/notebooks/langmuir_samples/_generate_noisy.ipynb +++ b/docs/notebooks/langmuir_samples/_generate_noisy.ipynb @@ -70,12 +70,12 @@ " sig_pwr = signal ** 2\n", " sig_pwr_ave = np.mean(sig_pwr)\n", " sig_pwr_ave_db = 10.0 * np.log10(sig_pwr_ave)\n", - " \n", + "\n", " noise_pwr_ave_db = sig_pwr_ave_db - snr_db.value\n", " noise_pwr_ave = 10.0 ** (noise_pwr_ave_db / 10.0)\n", - " \n", + "\n", " noise = np.random.normal(0.0, np.sqrt(noise_pwr_ave), signal.size)\n", - " \n", + "\n", " return signal + noise" ] }, @@ -86,7 +86,7 @@ "outputs": [], "source": [ "# read in example data\n", - "# this can be found at \n", + "# this can be found at\n", "# https://github.com/PlasmaPy/PlasmaPy/blob/master/docs/notebooks/langmuir_samples/Beckers2017.npy\n", "#\n", "filename = \"Beckers2017\"\n", From 1e6920e5c86349315901ca8aa262f7eeb9fbc6e9 Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 1 Feb 2021 15:59:00 -0800 Subject: [PATCH 173/521] appease grumpy black --- .../swept_langmuir/find_floating_potential.ipynb | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb b/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb index 4d6289696d..a34c246890 100644 --- a/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb +++ b/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb @@ -322,7 +322,7 @@ " axs[ii].fill_between(vfit, ifit + ifit_err, ifit - ifit_err, \n", " color=\"orange\", alpha=0.12, zorder=0,\n", " label=\"Fit Error\")\n", - " axs[ii].axhline(0.0, color=\"r\", linestyle=\"--)\n", + " axs[ii].axhline(0.0, color=\"r\", linestyle=\"--\")\n", " axs[ii].fill_between([fit.vf - fit.vf_err, fit.vf + fit.vf_err], \n", " axs[1].get_ylim()[0],\n", " axs[1].get_ylim()[1],\n", @@ -342,13 +342,6 @@ " fontsize=\"large\", transform=axs[ii].transAxes,\n", " ha=\"right\")" ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] } ], "metadata": { From 47cc7d8432a4ee51a7a31fc5793a4f91569a7cc8 Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 1 Feb 2021 16:09:03 -0800 Subject: [PATCH 174/521] appease grumpy black --- .../find_floating_potential.ipynb | 120 +++++++++++------- 1 file changed, 71 insertions(+), 49 deletions(-) diff --git a/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb b/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb index a34c246890..ac67572647 100644 --- a/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb +++ b/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb @@ -198,13 +198,14 @@ "metadata": {}, "outputs": [], "source": [ - "(results[3],\n", - " results.func,\n", - " results.func.params,\n", - " results.func.params.a,\n", - " results.func.param_errors,\n", - " results.func.param_errors.a,\n", - " results.func(results.vf),\n", + "(\n", + " results[3],\n", + " results.func,\n", + " results.func.params,\n", + " results.func.params.a,\n", + " results.func.param_errors,\n", + " results.func.param_errors.a,\n", + " results.func(results.vf),\n", ")" ] }, @@ -221,9 +222,10 @@ "metadata": {}, "outputs": [], "source": [ - "(results[4], \n", - " results.islands,\n", - " voltage[results.islands[0]],\n", + "(\n", + " results[4], \n", + " results.islands,\n", + " voltage[results.islands[0]],\n", ")" ] }, @@ -240,9 +242,10 @@ "metadata": {}, "outputs": [], "source": [ - "(results[5],\n", - " results.indices,\n", - " voltage[results.indices],\n", + "(\n", + " results[5],\n", + " results.indices,\n", + " voltage[results.indices],\n", ")" ] }, @@ -281,14 +284,12 @@ " isl_pts = np.array([], dtype=np.int64)\n", " for isl in fit.islands:\n", " isl_pts = np.concatenate((isl_pts, np.r_[isl]))\n", - " \n", + "\n", " # calc xrange for plot\n", - " xlim = [voltage[fit.indices].min(),\n", - " voltage[fit.indices].max()]\n", + " xlim = [voltage[fit.indices].min(), voltage[fit.indices].max()]\n", " vpad = 0.25 * (xlim[1] - xlim[0])\n", - " xlim = [xlim[0] - vpad,\n", - " xlim[1] + vpad]\n", - " \n", + " xlim = [xlim[0] - vpad, xlim[1] + vpad]\n", + "\n", " # calc data points for fit curve\n", " mask1 = np.where(voltage >= xlim[0], True, False)\n", " mask2 = np.where(voltage <= xlim[1], True, False)\n", @@ -300,47 +301,68 @@ " axs[ii].set_ylabel(\"Current (A)\", fontsize=12)\n", " axs[ii].set_xlim(xlim)\n", "\n", - " axs[ii].plot(voltage[mask], current[mask],\n", - " marker=\"o\", \n", - " zorder=10, \n", - " label=\"Sweep Data\")\n", - " axs[ii].scatter(voltage[fit.indices],\n", - " current[fit.indices],\n", - " linewidth=2, s=6**2, \n", - " facecolors=\"deepskyblue\", edgecolors=\"deepskyblue\",\n", - " zorder=11,\n", - " label=\"Points for Fit\")\n", - " axs[ii].scatter(voltage[isl_pts], current[isl_pts],\n", - " linewidth=2, s=8**2, \n", - " facecolors=\"deepskyblue\", edgecolors=\"black\",\n", - " zorder=12,\n", - " label=\"Island Points\")\n", + " axs[ii].plot(\n", + " voltage[mask], current[mask], marker=\"o\", zorder=10, label=\"Sweep Data\")\n", + " axs[ii].scatter(\n", + " voltage[fit.indices],\n", + " current[fit.indices],\n", + " linewidth=2,\n", + " s=6 ** 2, \n", + " facecolors=\"deepskyblue\",\n", + " edgecolors=\"deepskyblue\",\n", + " zorder=11,\n", + " label=\"Points for Fit\",\n", + " )\n", + " axs[ii].scatter(\n", + " voltage[isl_pts],\n", + " current[isl_pts],\n", + " linewidth=2,\n", + " s=8 ** 2, \n", + " facecolors=\"deepskyblue\",\n", + " edgecolors=\"black\",\n", + " zorder=12,\n", + " label=\"Island Points\",\n", + " )\n", " axs[ii].autoscale(False)\n", - " axs[ii].plot(vfit, ifit, color=\"orange\",\n", - " zorder=13,\n", - " label=label + \" Fit\")\n", - " axs[ii].fill_between(vfit, ifit + ifit_err, ifit - ifit_err, \n", - " color=\"orange\", alpha=0.12, zorder=0,\n", - " label=\"Fit Error\")\n", + " axs[ii].plot(vfit, ifit, color=\"orange\", zorder=13, label=label + \" Fit\")\n", + " axs[ii].fill_between(\n", + " vfit,\n", + " ifit + ifit_err,\n", + " ifit - ifit_err, \n", + " color=\"orange\",\n", + " alpha=0.12,\n", + " zorder=0,\n", + " label=\"Fit Error\",\n", + " )\n", " axs[ii].axhline(0.0, color=\"r\", linestyle=\"--\")\n", - " axs[ii].fill_between([fit.vf - fit.vf_err, fit.vf + fit.vf_err], \n", - " axs[1].get_ylim()[0],\n", - " axs[1].get_ylim()[1],\n", - " color=\"grey\", alpha=0.1)\n", + " axs[ii].fill_between(\n", + " [fit.vf - fit.vf_err, fit.vf + fit.vf_err], \n", + " axs[1].get_ylim()[0],\n", + " axs[1].get_ylim()[1],\n", + " color=\"grey\",\n", + " alpha=0.1,\n", + " )\n", " axs[ii].axvline(fit.vf, color=\"grey\")\n", " axs[ii].legend(fontsize=12)\n", "\n", " # add text\n", " rsq = fit.rsq\n", - " txt = (f\"$V_f = {fit.vf:.2f} \\\\pm {fit.vf_err:.2f}$ V\\n\"\n", - " f\"$r^2 = {rsq:.3f}$\")\n", + " txt = (\n", + " f\"$V_f = {fit.vf:.2f} \\\\pm {fit.vf_err:.2f}$ V\\n\"\n", + " f\"$r^2 = {rsq:.3f}$\"\n", + " )\n", " txt_loc = [fit.vf, axs[ii].get_ylim()[1]]\n", " txt_loc = axs[ii].transAxes.inverted().transform(axs[ii].transData.transform(txt_loc))\n", " txt_loc[0] -= 0.02\n", " txt_loc[1] -= 0.26\n", - " axs[ii].text(txt_loc[0], txt_loc[1], txt, \n", - " fontsize=\"large\", transform=axs[ii].transAxes,\n", - " ha=\"right\")" + " axs[ii].text(\n", + " txt_loc[0],\n", + " txt_loc[1],\n", + " txt, \n", + " fontsize=\"large\",\n", + " transform=axs[ii].transAxes,\n", + " ha=\"right\",\n", + " )" ] } ], From 55abf8bed7f4b5d073f0ee398da306c56d5250cb Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 1 Feb 2021 16:13:33 -0800 Subject: [PATCH 175/521] appease grumpy black --- .../find_floating_potential.ipynb | 25 ++++++++++--------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb b/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb index ac67572647..03105baa87 100644 --- a/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb +++ b/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb @@ -223,7 +223,7 @@ "outputs": [], "source": [ "(\n", - " results[4], \n", + " results[4],\n", " results.islands,\n", " voltage[results.islands[0]],\n", ")" @@ -302,12 +302,13 @@ " axs[ii].set_xlim(xlim)\n", "\n", " axs[ii].plot(\n", - " voltage[mask], current[mask], marker=\"o\", zorder=10, label=\"Sweep Data\")\n", + " voltage[mask], current[mask], marker=\"o\", zorder=10, label=\"Sweep Data\",\n", + " )\n", " axs[ii].scatter(\n", " voltage[fit.indices],\n", " current[fit.indices],\n", " linewidth=2,\n", - " s=6 ** 2, \n", + " s=6 ** 2,\n", " facecolors=\"deepskyblue\",\n", " edgecolors=\"deepskyblue\",\n", " zorder=11,\n", @@ -317,7 +318,7 @@ " voltage[isl_pts],\n", " current[isl_pts],\n", " linewidth=2,\n", - " s=8 ** 2, \n", + " s=8 ** 2,\n", " facecolors=\"deepskyblue\",\n", " edgecolors=\"black\",\n", " zorder=12,\n", @@ -328,7 +329,7 @@ " axs[ii].fill_between(\n", " vfit,\n", " ifit + ifit_err,\n", - " ifit - ifit_err, \n", + " ifit - ifit_err,\n", " color=\"orange\",\n", " alpha=0.12,\n", " zorder=0,\n", @@ -336,7 +337,7 @@ " )\n", " axs[ii].axhline(0.0, color=\"r\", linestyle=\"--\")\n", " axs[ii].fill_between(\n", - " [fit.vf - fit.vf_err, fit.vf + fit.vf_err], \n", + " [fit.vf - fit.vf_err, fit.vf + fit.vf_err],\n", " axs[1].get_ylim()[0],\n", " axs[1].get_ylim()[1],\n", " color=\"grey\",\n", @@ -347,18 +348,18 @@ "\n", " # add text\n", " rsq = fit.rsq\n", - " txt = (\n", - " f\"$V_f = {fit.vf:.2f} \\\\pm {fit.vf_err:.2f}$ V\\n\"\n", - " f\"$r^2 = {rsq:.3f}$\"\n", - " )\n", + " txt = f\"$V_f = {fit.vf:.2f} \\\\pm {fit.vf_err:.2f}$ V\\n\"\n", + " txt += f\"$r^2 = {rsq:.3f}$\"\n", " txt_loc = [fit.vf, axs[ii].get_ylim()[1]]\n", - " txt_loc = axs[ii].transAxes.inverted().transform(axs[ii].transData.transform(txt_loc))\n", + " txt_loc = axs[ii].transAxes.inverted().transform(\n", + " axs[ii].transData.transform(txt_loc),\n", + " )\n", " txt_loc[0] -= 0.02\n", " txt_loc[1] -= 0.26\n", " axs[ii].text(\n", " txt_loc[0],\n", " txt_loc[1],\n", - " txt, \n", + " txt,\n", " fontsize=\"large\",\n", " transform=axs[ii].transAxes,\n", " ha=\"right\",\n", From 42ed9369f9c1204891463e2d7a57d6305fb18654 Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 1 Feb 2021 16:16:17 -0800 Subject: [PATCH 176/521] appease grumpy black --- .../analysis/swept_langmuir/find_floating_potential.ipynb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb b/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb index 03105baa87..55b6140899 100644 --- a/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb +++ b/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb @@ -351,8 +351,8 @@ " txt = f\"$V_f = {fit.vf:.2f} \\\\pm {fit.vf_err:.2f}$ V\\n\"\n", " txt += f\"$r^2 = {rsq:.3f}$\"\n", " txt_loc = [fit.vf, axs[ii].get_ylim()[1]]\n", - " txt_loc = axs[ii].transAxes.inverted().transform(\n", - " axs[ii].transData.transform(txt_loc),\n", + " txt_loc = (\n", + " axs[ii].transAxes.inverted().transform(axs[ii].transData.transform(txt_loc)),\n", " )\n", " txt_loc[0] -= 0.02\n", " txt_loc[1] -= 0.26\n", From d23b3b186e152c19c97fc857f59d08d8eccea9fa Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 1 Feb 2021 16:41:18 -0800 Subject: [PATCH 177/521] fix issues caused by grumpy black --- .../analysis/swept_langmuir/find_floating_potential.ipynb | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb b/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb index 55b6140899..157d054e70 100644 --- a/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb +++ b/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb @@ -351,9 +351,8 @@ " txt = f\"$V_f = {fit.vf:.2f} \\\\pm {fit.vf_err:.2f}$ V\\n\"\n", " txt += f\"$r^2 = {rsq:.3f}$\"\n", " txt_loc = [fit.vf, axs[ii].get_ylim()[1]]\n", - " txt_loc = (\n", - " axs[ii].transAxes.inverted().transform(axs[ii].transData.transform(txt_loc)),\n", - " )\n", + " txt_loc = axs[ii].transData.transform(txt_loc)\n", + " txt_loc = axs[ii].transAxes.inverted().transform(txt_loc)\n", " txt_loc[0] -= 0.02\n", " txt_loc[1] -= 0.26\n", " axs[ii].text(\n", From 9f761995da96b47197b65717b261dacac2cad0c1 Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 1 Feb 2021 16:48:32 -0800 Subject: [PATCH 178/521] update warning string for deprecation of plasmapy.diagnostics.langmuir --- plasmapy/diagnostics/langmuir.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plasmapy/diagnostics/langmuir.py b/plasmapy/diagnostics/langmuir.py index 4f414f6f4a..2d98e07520 100644 --- a/plasmapy/diagnostics/langmuir.py +++ b/plasmapy/diagnostics/langmuir.py @@ -34,8 +34,8 @@ def _langmuir_futurewarning() -> None: warn( "The plasmapy.diagnostics.langmuir module will be deprecated in favor of " - "the plasmapy.analysis.swept_langmuir sub-package. The analysis package " - " is in active development and is scheduled to be released with v0.5.0.", + "the plasmapy.analysis.swept_langmuir sub-package and phased out over " + "2021. The plasmapy.analysis package was released in v0.5.0.", FutureWarning, ) From ddc60f5e1948fcd15cc547172595ec9fc0f20d05 Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 1 Feb 2021 16:51:36 -0800 Subject: [PATCH 179/521] py36 was dropped, replace ExitStack with nullcontext --- plasmapy/analysis/tests/test_fit_functions.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/plasmapy/analysis/tests/test_fit_functions.py b/plasmapy/analysis/tests/test_fit_functions.py index a606a22122..4681f4e82b 100644 --- a/plasmapy/analysis/tests/test_fit_functions.py +++ b/plasmapy/analysis/tests/test_fit_functions.py @@ -5,12 +5,10 @@ import pytest from abc import ABC, abstractmethod -from contextlib import ExitStack as does_not_raise +from contextlib import nullcontext as does_not_raise import plasmapy.analysis.fit_functions as ffuncs -# TODO: replace ExitStack with nullcontext when we require >= python 3.7 - class TestAbstractFitFunction: """ From e455e15ef28c8bd20b3c18dc0633aea9bb429e6c Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 1 Feb 2021 17:10:59 -0800 Subject: [PATCH 180/521] replace threshold warnings with exceptions; add associated tests cases --- .../swept_langmuir/floating_potential.py | 15 +++++++-------- .../tests/test_floating_potential.py | 18 ++++++++++++++++++ 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/plasmapy/analysis/swept_langmuir/floating_potential.py b/plasmapy/analysis/swept_langmuir/floating_potential.py index 437fa46414..bdf93c2ad5 100644 --- a/plasmapy/analysis/swept_langmuir/floating_potential.py +++ b/plasmapy/analysis/swept_langmuir/floating_potential.py @@ -164,16 +164,15 @@ def find_floating_potential( # condition kwarg threshold if isinstance(threshold, (int, np.integer)): if threshold < 1: - threshold = 1 - warn( - f"threshold ({threshold}) is less than 1 and needs to be" - f" an int >= 1, using a value of 1", - PlasmaPyWarning, + raise ValueError( + f"Keyword 'threshold' has value ({threshold}) less than 1, " + f"value must be an int >= 1." ) - else: - threshold = 1 - warn(f"threshold is NOT a integer >= 1, using a value of 1", PlasmaPyWarning) + raise TypeError( + f"Keyword 'threshold' is of type {type(threshold)}, expected an int " + f"int >= 1." + ) # condition min_points if min_points is None: diff --git a/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py b/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py index 3934fb6717..e0d63a982c 100644 --- a/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py +++ b/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py @@ -96,6 +96,24 @@ def test_call_of_check_sweep(self): }, ValueError, ), + # + # errors on kwarg threshold + ( + { + "voltage": np.array([1.0, 2, 3, 4]), + "current": np.array([-1.0, 0, 1, 2]), + "threshold": -1, + }, + ValueError, + ), + ( + { + "voltage": np.array([1.0, 2, 3, 4]), + "current": np.array([-1.0, 0, 1, 2]), + "threshold": "wrong type", + }, + TypeError, + ), ], ) def test_raises(self, kwargs, _error): From 0a2800676b8dab245e08a2371b5b98a1b59724d7 Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 1 Feb 2021 17:18:40 -0800 Subject: [PATCH 181/521] "minor" fixes --- plasmapy/analysis/swept_langmuir/floating_potential.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plasmapy/analysis/swept_langmuir/floating_potential.py b/plasmapy/analysis/swept_langmuir/floating_potential.py index bdf93c2ad5..18d15ec341 100644 --- a/plasmapy/analysis/swept_langmuir/floating_potential.py +++ b/plasmapy/analysis/swept_langmuir/floating_potential.py @@ -155,7 +155,7 @@ def find_floating_potential( # check voltage and current arrays try: - check_sweep(voltage, current) + voltage, current = check_sweep(voltage, current, strip_units=True) except (TypeError, ValueError) as err: # did not pass checks warn(err.args[0], PlasmaPyWarning) @@ -248,7 +248,7 @@ def find_floating_potential( if min_points == 0: # us all points istart = 0 - istop = voltage.size + istop = voltage.size - 1 else: istart = cp_candidates[0] istop = cp_candidates[-1] From bb426531dd3fb735c61050a219c77ec054c6fe1d Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 1 Feb 2021 19:19:44 -0800 Subject: [PATCH 182/521] add test case for warnings issued --- .../tests/test_floating_potential.py | 92 +++++++++++++++++++ 1 file changed, 92 insertions(+) diff --git a/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py b/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py index e0d63a982c..55038882d0 100644 --- a/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py +++ b/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py @@ -14,6 +14,7 @@ find_floating_potential, FloatingPotentialResults, ) +from plasmapy.utils.exceptions import PlasmaPyWarning def test_floating_potential_namedtuple(): @@ -42,6 +43,14 @@ class TestFindFloatingPotential: `~plasmapy.analysis.swept_langmuir.floating_potential.find_floating_potential`. """ + _null_result = FloatingPotentialResults( + vf=np.nan, vf_err=np.nan, rsq=None, func=None, islands=None, indices=None + )._asdict() + _linear_p_sine_voltage = np.linspace(-10.0, 15, 70) + _linear_p_sine_current = ( + np.linspace(-3.1, 4.1, 70) + 1.2 * np.sin(1.2 * _linear_p_sine_voltage), + ) + def test_call_of_check_sweep(self): """ Test `find_floating_potential` appropriately calls @@ -120,3 +129,86 @@ def test_raises(self, kwargs, _error): """Test scenarios that raise `Exception`s.""" with pytest.raises(_error): find_floating_potential(**kwargs) + + @pytest.mark.parametrize( + "kwargs, expected, _warning", + [ + # check_sweep returns a TypeError + ( + { + "voltage": "not an array", + "current": np.array([-1.0, 0, 1, 2]), + "fit_type": "linear", + }, + {**_null_result, "func": ffuncs.Linear()}, + PlasmaPyWarning, + ), + # + # check_sweep returns a ValueError (not linearly increasing) + ( + { + "voltage": np.array([2.0, 1, 0, -1]), + "current": np.array([-1.0, 0, 1, 2]), + "fit_type": "linear", + }, + {**_null_result, "func": ffuncs.Linear()}, + PlasmaPyWarning, + ), + # + # too many crossing islands + ( + { + "voltage": _linear_p_sine_voltage, + "current": _linear_p_sine_current, + "fit_type": "linear", + }, + { + **_null_result, + "func": ffuncs.Linear(), + "islands": [slice(27, 29), slice(36, 38), slice(39, 41)], + }, + PlasmaPyWarning, + ), + # + # min_points is larger than array size + ( + { + "voltage": _linear_p_sine_voltage, + "current": _linear_p_sine_current, + "fit_type": "linear", + "threshold": 8, + "min_points": 80, + }, + { + **_null_result, + "vf": 0.6355491, + "vf_err": 0.03306472, + "rsq": 0.8446441, + "func": ffuncs.Linear(), + "islands": [slice(27, 41),], + "indices": slice(0, 70), + }, + PlasmaPyWarning, + ), + ], + ) + def test_warnings(self, kwargs, expected, _warning): + """Test scenarios that issue warnings.""" + with pytest.warns(_warning): + results = find_floating_potential(**kwargs) + assert isinstance(results, FloatingPotentialResults) + + for key, val in expected.items(): + rtn_val = getattr(results, key) + + if val is None: + assert rtn_val is None + elif key == "func" and val is not None: + assert isinstance(rtn_val, val.__class__) + elif np.isscalar(val): + if np.isnan(val): + assert np.isnan(rtn_val) + else: + assert np.isclose(rtn_val, val) + else: + assert rtn_val == val From bb149a95db676b9a7a03a6af40f786ec6b3f6db8 Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 1 Feb 2021 20:43:31 -0800 Subject: [PATCH 183/521] for `check_sweep` make note that units are not assumed or checked --- plasmapy/analysis/swept_langmuir/helpers.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/plasmapy/analysis/swept_langmuir/helpers.py b/plasmapy/analysis/swept_langmuir/helpers.py index cd2a6f0652..6c1b8fd903 100644 --- a/plasmapy/analysis/swept_langmuir/helpers.py +++ b/plasmapy/analysis/swept_langmuir/helpers.py @@ -16,12 +16,14 @@ def check_sweep( ---------- voltage: `numpy.ndarray` 1D `numpy.ndarray` representing the voltage of the swept Langmuir trace. - Voltage should be monotonically increasing. + Voltage should be monotonically increasing. *No units are assumed or + checked, but values should be in volts.* current: `numpy.ndarray` 1D `numpy.ndarray` representing the current of the swept Langmuir trace. Values should start from a negative ion-saturation current and increase - to a positive electron-saturation current. + to a positive electron-saturation current. *No units are assumed or + checked, but values should be in amperes.* strip_units: `bool` (Default: `True`) If `True``, then the units on ``voltage`` and/or From 716b0e80f353b13e2f59dae0e6c2c3b7f19ead0d Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 1 Feb 2021 20:57:03 -0800 Subject: [PATCH 184/521] update test_call_of_check_sweep to account for kwarg strip_units and new return --- .../analysis/swept_langmuir/tests/test_floating_potential.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py b/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py index 55038882d0..a994fbcc2f 100644 --- a/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py +++ b/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py @@ -63,6 +63,7 @@ def test_call_of_check_sweep(self): assert _sl.helpers.check_sweep is _sl.floating_potential.check_sweep with mock.patch(_sl.floating_potential.__name__ + ".check_sweep") as mock_cs: + mock_cs.return_value = varr, carr find_floating_potential(voltage=varr, current=carr, fit_type="linear") assert mock_cs.call_count == 1 @@ -73,7 +74,7 @@ def test_call_of_check_sweep(self): assert np.array_equal(mock_cs.call_args[0][1], carr) # passed kwargs - assert mock_cs.call_args[1] == {} + assert mock_cs.call_args[1] == {"strip_units": True} @pytest.mark.parametrize( "kwargs, _error", From e3d0958cffdc86d78ebf64df64d4429bee93012c Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 1 Feb 2021 21:02:28 -0800 Subject: [PATCH 185/521] have check_sweep in find_floating_potential actually raise exceptions instead of translating them to warnings --- .../swept_langmuir/floating_potential.py | 7 +--- .../tests/test_floating_potential.py | 38 +++++++++---------- 2 files changed, 19 insertions(+), 26 deletions(-) diff --git a/plasmapy/analysis/swept_langmuir/floating_potential.py b/plasmapy/analysis/swept_langmuir/floating_potential.py index 18d15ec341..4515f1d401 100644 --- a/plasmapy/analysis/swept_langmuir/floating_potential.py +++ b/plasmapy/analysis/swept_langmuir/floating_potential.py @@ -154,12 +154,7 @@ def find_floating_potential( ) # check voltage and current arrays - try: - voltage, current = check_sweep(voltage, current, strip_units=True) - except (TypeError, ValueError) as err: - # did not pass checks - warn(err.args[0], PlasmaPyWarning) - return FloatingPotentialResults(**rtn) + voltage, current = check_sweep(voltage, current, strip_units=True) # condition kwarg threshold if isinstance(threshold, (int, np.integer)): diff --git a/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py b/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py index a994fbcc2f..935c09a40c 100644 --- a/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py +++ b/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py @@ -47,9 +47,8 @@ class TestFindFloatingPotential: vf=np.nan, vf_err=np.nan, rsq=None, func=None, islands=None, indices=None )._asdict() _linear_p_sine_voltage = np.linspace(-10.0, 15, 70) - _linear_p_sine_current = ( - np.linspace(-3.1, 4.1, 70) + 1.2 * np.sin(1.2 * _linear_p_sine_voltage), - ) + _linear_p_sine_current = \ + np.linspace(-3.1, 4.1, 70) + 1.2 * np.sin(1.2 * _linear_p_sine_voltage) def test_call_of_check_sweep(self): """ @@ -124,38 +123,37 @@ def test_call_of_check_sweep(self): }, TypeError, ), - ], - ) - def test_raises(self, kwargs, _error): - """Test scenarios that raise `Exception`s.""" - with pytest.raises(_error): - find_floating_potential(**kwargs) - - @pytest.mark.parametrize( - "kwargs, expected, _warning", - [ - # check_sweep returns a TypeError + # + # TypeError on voltage/current arrays from check_sweep ( { "voltage": "not an array", "current": np.array([-1.0, 0, 1, 2]), "fit_type": "linear", }, - {**_null_result, "func": ffuncs.Linear()}, - PlasmaPyWarning, + TypeError, ), # - # check_sweep returns a ValueError (not linearly increasing) + # ValueError on voltage/current arrays from check_sweep + # (not linearly increasing) ( { "voltage": np.array([2.0, 1, 0, -1]), "current": np.array([-1.0, 0, 1, 2]), "fit_type": "linear", }, - {**_null_result, "func": ffuncs.Linear()}, - PlasmaPyWarning, + ValueError, ), - # + ], + ) + def test_raises(self, kwargs, _error): + """Test scenarios that raise `Exception`s.""" + with pytest.raises(_error): + find_floating_potential(**kwargs) + + @pytest.mark.parametrize( + "kwargs, expected, _warning", + [ # too many crossing islands ( { From d784989e0a3107d71c5be8c9bea5fc5fc7ee20b3 Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 1 Feb 2021 21:05:25 -0800 Subject: [PATCH 186/521] appease grumpy black --- .../tests/test_floating_potential.py | 39 ++++++++++--------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py b/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py index 935c09a40c..027305332b 100644 --- a/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py +++ b/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py @@ -47,8 +47,9 @@ class TestFindFloatingPotential: vf=np.nan, vf_err=np.nan, rsq=None, func=None, islands=None, indices=None )._asdict() _linear_p_sine_voltage = np.linspace(-10.0, 15, 70) - _linear_p_sine_current = \ - np.linspace(-3.1, 4.1, 70) + 1.2 * np.sin(1.2 * _linear_p_sine_voltage) + _linear_p_sine_current = np.linspace(-3.1, 4.1, 70) + 1.2 * np.sin( + 1.2 * _linear_p_sine_voltage + ) def test_call_of_check_sweep(self): """ @@ -171,23 +172,23 @@ def test_raises(self, kwargs, _error): # # min_points is larger than array size ( - { - "voltage": _linear_p_sine_voltage, - "current": _linear_p_sine_current, - "fit_type": "linear", - "threshold": 8, - "min_points": 80, - }, - { - **_null_result, - "vf": 0.6355491, - "vf_err": 0.03306472, - "rsq": 0.8446441, - "func": ffuncs.Linear(), - "islands": [slice(27, 41),], - "indices": slice(0, 70), - }, - PlasmaPyWarning, + { + "voltage": _linear_p_sine_voltage, + "current": _linear_p_sine_current, + "fit_type": "linear", + "threshold": 8, + "min_points": 80, + }, + { + **_null_result, + "vf": 0.6355491, + "vf_err": 0.03306472, + "rsq": 0.8446441, + "func": ffuncs.Linear(), + "islands": [slice(27, 41),], + "indices": slice(0, 70), + }, + PlasmaPyWarning, ), ], ) From d26dbce563454b504c2935f13c1fe3de2548e5b5 Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 1 Feb 2021 21:08:14 -0800 Subject: [PATCH 187/521] refactor default current and voltage arrays used for testing --- .../swept_langmuir/tests/test_floating_potential.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py b/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py index 027305332b..46daf93576 100644 --- a/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py +++ b/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py @@ -46,10 +46,9 @@ class TestFindFloatingPotential: _null_result = FloatingPotentialResults( vf=np.nan, vf_err=np.nan, rsq=None, func=None, islands=None, indices=None )._asdict() - _linear_p_sine_voltage = np.linspace(-10.0, 15, 70) - _linear_p_sine_current = np.linspace(-3.1, 4.1, 70) + 1.2 * np.sin( - 1.2 * _linear_p_sine_voltage - ) + _voltage = np.linspace(-10.0, 15, 70) + _linear_current = np.linspace(-3.1, 4.1, 70) + _linear_p_sine_current = _linear_current + 1.2 * np.sin(1.2 * _voltage) def test_call_of_check_sweep(self): """ @@ -158,7 +157,7 @@ def test_raises(self, kwargs, _error): # too many crossing islands ( { - "voltage": _linear_p_sine_voltage, + "voltage": _voltage, "current": _linear_p_sine_current, "fit_type": "linear", }, @@ -173,7 +172,7 @@ def test_raises(self, kwargs, _error): # min_points is larger than array size ( { - "voltage": _linear_p_sine_voltage, + "voltage": _voltage, "current": _linear_p_sine_current, "fit_type": "linear", "threshold": 8, From 5b7fd733f1e32983bfcf2442bcf7f0deeb49e806 Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 1 Feb 2021 21:43:45 -0800 Subject: [PATCH 188/521] add test `test_kwarg_min_points` --- .../tests/test_floating_potential.py | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py b/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py index 46daf93576..a53d326524 100644 --- a/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py +++ b/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py @@ -49,6 +49,7 @@ class TestFindFloatingPotential: _voltage = np.linspace(-10.0, 15, 70) _linear_current = np.linspace(-3.1, 4.1, 70) _linear_p_sine_current = _linear_current + 1.2 * np.sin(1.2 * _voltage) + _exp_current = -1.3 + 2.2 * np.exp(_voltage) def test_call_of_check_sweep(self): """ @@ -211,3 +212,30 @@ def test_warnings(self, kwargs, expected, _warning): assert np.isclose(rtn_val, val) else: assert rtn_val == val + + @pytest.mark.parametrize( + "min_points, fit_type, islands, indices", + [ + (0, "linear", [slice(29, 31), ], slice(0, 70)), + (1, "linear", [slice(29, 31), ], slice(29, 31)), + (15, "linear", [slice(29, 31), ], slice(22, 38)), + (16, "linear", [slice(29, 31), ], slice(22, 38)), + (0.14, "linear", [slice(29, 31), ], slice(25, 35)), + # + # rely on default min_points + # - linear -> 0.1 * array size & ceiling to the nearest even + # - exponential -> 0.2 * array size & ceiling to the nearest even + (None, "linear", [slice(29, 31), ], slice(26, 34)), + (None, "exponential", [slice(26, 28), ], slice(20, 34)), + ], + ) + def test_kwarg_min_points(self, min_points, fit_type, islands, indices): + voltage = self._voltage + current = self._linear_current if fit_type == "linear" else self._exp_current + results = find_floating_potential( + voltage, current, min_points=min_points, fit_type=fit_type, + ) + assert isinstance(results, FloatingPotentialResults) + + assert results.islands == islands + assert results.indices == indices From 296497f15aa91616cf8e64b48f3d91ce797e14bd Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 1 Feb 2021 22:23:13 -0800 Subject: [PATCH 189/521] add test `test_kwarg_min_points`; some PEP fixes; add docstring to `test_kwarg_min_points` --- .../tests/test_floating_potential.py | 108 +++++++++++++++++- 1 file changed, 107 insertions(+), 1 deletion(-) diff --git a/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py b/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py index a53d326524..dca24662b4 100644 --- a/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py +++ b/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py @@ -185,7 +185,7 @@ def test_raises(self, kwargs, _error): "vf_err": 0.03306472, "rsq": 0.8446441, "func": ffuncs.Linear(), - "islands": [slice(27, 41),], + "islands": [slice(27, 41), ], "indices": slice(0, 70), }, PlasmaPyWarning, @@ -230,6 +230,10 @@ def test_warnings(self, kwargs, expected, _warning): ], ) def test_kwarg_min_points(self, min_points, fit_type, islands, indices): + """ + Test functionality of keyword `min_points` and how it affects the + size of the crossing-point island. + """ voltage = self._voltage current = self._linear_current if fit_type == "linear" else self._exp_current results = find_floating_potential( @@ -239,3 +243,105 @@ def test_kwarg_min_points(self, min_points, fit_type, islands, indices): assert results.islands == islands assert results.indices == indices + + @pytest.mark.parametrize( + "kwargs, expected", + [ + # simple linear + ( + { + "voltage": _voltage, + "current": _linear_current, + "fit_type": "linear", + "min_points": 16, + }, + { + **_null_result, + "vf": 0.7638889, + "vf_err": 0.0, + "rsq": 1.0, + "func": ffuncs.Linear(), + "islands": [slice(29, 31), ], + "indices": slice(22, 38), + }, + ), + # + # multiple islands merged with min_points + ( + { + "voltage": _voltage, + "current": _linear_p_sine_current, + "fit_type": "linear", + "min_points": 16, + }, + { + **_null_result, + "vf": -8.8243208, + "vf_err": 032.9961, + "rsq": 0.005084178, + "func": ffuncs.Linear(), + "islands": [slice(27, 29), slice(36, 38), slice(39, 41)], + "indices": slice(26, 42), + }, + ), + # + # crossing-point near front of the array + ( + { + "voltage": _voltage, + "current": _linear_current + 2.5, + "fit_type": "linear", + "min_points": 16, + }, + { + **_null_result, + "vf": -7.91666667, + "vf_err": 3.153378e-8, + "rsq": 1.0, + "func": ffuncs.Linear(), + "islands": [slice(5, 7), ], + "indices": slice(0, 16), + }, + ), + # + # crossing-point near end of the array + ( + { + "voltage": _voltage, + "current": _linear_current - 4.0, + "fit_type": "linear", + "min_points": 16, + }, + { + **_null_result, + "vf": 14.6527778, + "vf_err": 0.0, + "rsq": 1.0, + "func": ffuncs.Linear(), + "islands": [slice(68, 70), ], + "indices": slice(54, 70), + }, + ), + ], + ) + def test_island_finding(self, kwargs, expected): + """ + Test scenarios related to the identification of crossing-point islands. + """ + results = find_floating_potential(**kwargs) + assert isinstance(results, FloatingPotentialResults) + + for key, val in expected.items(): + rtn_val = getattr(results, key) + + if val is None: + assert rtn_val is None + elif key == "func" and val is not None: + assert isinstance(rtn_val, val.__class__) + elif np.isscalar(val): + if np.isnan(val): + assert np.isnan(rtn_val) + else: + assert np.isclose(rtn_val, val) + else: + assert rtn_val == val From d4d0605dbafc48f7f92300466501866109e2ee92 Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 1 Feb 2021 22:25:23 -0800 Subject: [PATCH 190/521] appease grumpy black --- .../tests/test_floating_potential.py | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py b/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py index dca24662b4..8e927823d2 100644 --- a/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py +++ b/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py @@ -185,7 +185,7 @@ def test_raises(self, kwargs, _error): "vf_err": 0.03306472, "rsq": 0.8446441, "func": ffuncs.Linear(), - "islands": [slice(27, 41), ], + "islands": [slice(27, 41)], "indices": slice(0, 70), }, PlasmaPyWarning, @@ -216,17 +216,17 @@ def test_warnings(self, kwargs, expected, _warning): @pytest.mark.parametrize( "min_points, fit_type, islands, indices", [ - (0, "linear", [slice(29, 31), ], slice(0, 70)), - (1, "linear", [slice(29, 31), ], slice(29, 31)), - (15, "linear", [slice(29, 31), ], slice(22, 38)), - (16, "linear", [slice(29, 31), ], slice(22, 38)), - (0.14, "linear", [slice(29, 31), ], slice(25, 35)), + (0, "linear", [slice(29, 31)], slice(0, 70)), + (1, "linear", [slice(29, 31)], slice(29, 31)), + (15, "linear", [slice(29, 31)], slice(22, 38)), + (16, "linear", [slice(29, 31)], slice(22, 38)), + (0.14, "linear", [slice(29, 31)], slice(25, 35)), # # rely on default min_points # - linear -> 0.1 * array size & ceiling to the nearest even # - exponential -> 0.2 * array size & ceiling to the nearest even - (None, "linear", [slice(29, 31), ], slice(26, 34)), - (None, "exponential", [slice(26, 28), ], slice(20, 34)), + (None, "linear", [slice(29, 31)], slice(26, 34)), + (None, "exponential", [slice(26, 28)], slice(20, 34)), ], ) def test_kwarg_min_points(self, min_points, fit_type, islands, indices): @@ -261,7 +261,7 @@ def test_kwarg_min_points(self, min_points, fit_type, islands, indices): "vf_err": 0.0, "rsq": 1.0, "func": ffuncs.Linear(), - "islands": [slice(29, 31), ], + "islands": [slice(29, 31)], "indices": slice(22, 38), }, ), @@ -299,7 +299,7 @@ def test_kwarg_min_points(self, min_points, fit_type, islands, indices): "vf_err": 3.153378e-8, "rsq": 1.0, "func": ffuncs.Linear(), - "islands": [slice(5, 7), ], + "islands": [slice(5, 7)], "indices": slice(0, 16), }, ), @@ -318,7 +318,7 @@ def test_kwarg_min_points(self, min_points, fit_type, islands, indices): "vf_err": 0.0, "rsq": 1.0, "func": ffuncs.Linear(), - "islands": [slice(68, 70), ], + "islands": [slice(68, 70)], "indices": slice(54, 70), }, ), From aeb524792e13dfaab0a9b53260eaac8f87cd21ff Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 1 Feb 2021 22:33:58 -0800 Subject: [PATCH 191/521] add atol=1e-7 to isclose in test_island_finding --- .../analysis/swept_langmuir/tests/test_floating_potential.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py b/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py index 8e927823d2..863c985445 100644 --- a/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py +++ b/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py @@ -342,6 +342,6 @@ def test_island_finding(self, kwargs, expected): if np.isnan(val): assert np.isnan(rtn_val) else: - assert np.isclose(rtn_val, val) + assert np.isclose(rtn_val, val, atol=1e-7) else: assert rtn_val == val From 2f4f997065f874a48e4e93ed4a9f4af2cedfa1ea Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 1 Feb 2021 22:58:00 -0800 Subject: [PATCH 192/521] add test for perfect linear and exponential --- .../tests/test_floating_potential.py | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py b/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py index 863c985445..ebffbb9b28 100644 --- a/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py +++ b/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py @@ -345,3 +345,41 @@ def test_island_finding(self, kwargs, expected): assert np.isclose(rtn_val, val, atol=1e-7) else: assert rtn_val == val + + @pytest.mark.parametrize("m, b", [(2.0, 0.0), (1.33, -0.1), (0.5, -0.1)]) + def test_perfect_linear(self, m, b): + """Test calculated fit parameters on a few perfectly linear cases.""" + voltage = self._voltage + current = m * voltage + b + + results = find_floating_potential( + voltage=voltage, current=current, fit_type="linear", min_points=0.8, + ) + + assert isinstance(results, FloatingPotentialResults) + assert np.isclose(results.vf, -b/m) + assert np.isclose(results.vf_err, 0.0) + assert np.isclose(results.rsq, 1.0) + assert isinstance(results.func, ffuncs.Linear) + assert np.allclose(results.func.params, (m, b)) + assert np.allclose(results.func.param_errors, (0.0, 0.0), atol=2e-8) + + @pytest.mark.parametrize( + "a, alpha, b", [(1.0, 0.2, -0.2), (2.7, 0.2, -10.0), (6.0, 0.6, -10.0)], + ) + def test_perfect_exponential(self, a, alpha, b): + """Test calculated fit parameters on a few perfectly exponential cases.""" + voltage = self._voltage + current = a * np.exp(alpha * voltage) + b + + results = find_floating_potential( + voltage=voltage, current=current, fit_type="exponential", min_points=0.8, + ) + + assert isinstance(results, FloatingPotentialResults) + assert np.isclose(results.vf, np.log(-b / a) / alpha) + assert np.isclose(results.vf_err, 0.0, 1e-7) + assert np.isclose(results.rsq, 1.0) + assert isinstance(results.func, ffuncs.ExponentialPlusOffset) + assert np.allclose(results.func.params, (a, alpha, b)) + assert np.allclose(results.func.param_errors, (0.0, 0.0, 0.0), atol=2e-8) From f2e4f4370ad6cb6c1093dce9f884418a47127fc8 Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 1 Feb 2021 22:58:25 -0800 Subject: [PATCH 193/521] appeas grumpy black --- .../analysis/swept_langmuir/tests/test_floating_potential.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py b/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py index ebffbb9b28..9ff00b82b9 100644 --- a/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py +++ b/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py @@ -357,7 +357,7 @@ def test_perfect_linear(self, m, b): ) assert isinstance(results, FloatingPotentialResults) - assert np.isclose(results.vf, -b/m) + assert np.isclose(results.vf, -b / m) assert np.isclose(results.vf_err, 0.0) assert np.isclose(results.rsq, 1.0) assert isinstance(results.func, ffuncs.Linear) From 0ac26b904f91fa33951c2b94b246bbee4fc89870 Mon Sep 17 00:00:00 2001 From: Erik Everson Date: Tue, 2 Feb 2021 10:01:10 -0800 Subject: [PATCH 194/521] Apply suggestions from code review Co-authored-by: Nick Murphy --- plasmapy/analysis/swept_langmuir/floating_potential.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plasmapy/analysis/swept_langmuir/floating_potential.py b/plasmapy/analysis/swept_langmuir/floating_potential.py index 4515f1d401..f30d6abb76 100644 --- a/plasmapy/analysis/swept_langmuir/floating_potential.py +++ b/plasmapy/analysis/swept_langmuir/floating_potential.py @@ -24,7 +24,7 @@ def find_floating_potential( fit_type: str = "exponential", ): """ - Determines the floating potential (:math:`V_f`) for a given Current-Voltage + Determines the floating potential (:math:`V_f`) for a given current-voltage (IV) curve obtained from a swept Langmuir probe. The floating potential is the probe bias where the collected current equals zero :math:`I = 0`. @@ -48,7 +48,7 @@ def find_floating_potential( 3. To calculate the floating potential... - - If the crossing-island contains less points than ``min_points``, then + - If the crossing-island contains fewer points than ``min_points``, then each side of the crossing-island is equally padded with the nearest neighbor points until ``min_points`` is satisfied. - A fit is then performed using `scipy.stats.linregress` for @@ -225,7 +225,7 @@ def find_floating_potential( for start, stop in zip(isl_start, isl_stop): rtn["islands"].append(slice(start, stop)) - # do islands fall within min_points window + # do islands fall within min_points window? isl_window = ( np.abs(np.r_[rtn["islands"][-1]][-1] - np.r_[rtn["islands"][0]][0]) + 1 ) From bae6520e318c6543cce24e236bd2f9d81740f823 Mon Sep 17 00:00:00 2001 From: Erik Date: Tue, 2 Feb 2021 10:01:57 -0800 Subject: [PATCH 195/521] phrasing --- plasmapy/analysis/swept_langmuir/floating_potential.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plasmapy/analysis/swept_langmuir/floating_potential.py b/plasmapy/analysis/swept_langmuir/floating_potential.py index f30d6abb76..64575879b0 100644 --- a/plasmapy/analysis/swept_langmuir/floating_potential.py +++ b/plasmapy/analysis/swept_langmuir/floating_potential.py @@ -225,7 +225,7 @@ def find_floating_potential( for start, stop in zip(isl_start, isl_stop): rtn["islands"].append(slice(start, stop)) - # do islands fall within min_points window? + # do islands fall within the min_points window? isl_window = ( np.abs(np.r_[rtn["islands"][-1]][-1] - np.r_[rtn["islands"][0]][0]) + 1 ) From 25e14e608c7af14bd6664b9689376a18e9f97a91 Mon Sep 17 00:00:00 2001 From: Erik Everson Date: Tue, 2 Feb 2021 12:41:51 -0800 Subject: [PATCH 196/521] Apply suggestions from code review Co-authored-by: Nick Murphy --- plasmapy/analysis/swept_langmuir/floating_potential.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plasmapy/analysis/swept_langmuir/floating_potential.py b/plasmapy/analysis/swept_langmuir/floating_potential.py index f30d6abb76..1216919de9 100644 --- a/plasmapy/analysis/swept_langmuir/floating_potential.py +++ b/plasmapy/analysis/swept_langmuir/floating_potential.py @@ -157,7 +157,7 @@ def find_floating_potential( voltage, current = check_sweep(voltage, current, strip_units=True) # condition kwarg threshold - if isinstance(threshold, (int, np.integer)): + if isinstance(threshold, numbers.Integral): if threshold < 1: raise ValueError( f"Keyword 'threshold' has value ({threshold}) less than 1, " From cea466c8b5398d61cb37d8592e6ec4125ec1b6e1 Mon Sep 17 00:00:00 2001 From: Erik Date: Tue, 2 Feb 2021 13:46:21 -0800 Subject: [PATCH 197/521] add import of numbers --- plasmapy/analysis/swept_langmuir/floating_potential.py | 1 + 1 file changed, 1 insertion(+) diff --git a/plasmapy/analysis/swept_langmuir/floating_potential.py b/plasmapy/analysis/swept_langmuir/floating_potential.py index 126ca86070..63f76369d3 100644 --- a/plasmapy/analysis/swept_langmuir/floating_potential.py +++ b/plasmapy/analysis/swept_langmuir/floating_potential.py @@ -1,6 +1,7 @@ """Functionality for determining the floating potential of a Langmuir sweep.""" __all__ = ["find_floating_potential"] +import numbers import numpy as np from collections import namedtuple From d20998a46f8f4b7ed97080810cfadd0acb6093d7 Mon Sep 17 00:00:00 2001 From: Erik Date: Tue, 2 Feb 2021 14:08:02 -0800 Subject: [PATCH 198/521] move the "How it works" "section" to the numpydoc "Notes" section --- .../swept_langmuir/floating_potential.py | 60 ++++++++++--------- 1 file changed, 31 insertions(+), 29 deletions(-) diff --git a/plasmapy/analysis/swept_langmuir/floating_potential.py b/plasmapy/analysis/swept_langmuir/floating_potential.py index 63f76369d3..ee5e332db8 100644 --- a/plasmapy/analysis/swept_langmuir/floating_potential.py +++ b/plasmapy/analysis/swept_langmuir/floating_potential.py @@ -27,34 +27,8 @@ def find_floating_potential( """ Determines the floating potential (:math:`V_f`) for a given current-voltage (IV) curve obtained from a swept Langmuir probe. The floating potential is - the probe bias where the collected current equals zero :math:`I = 0`. - - **How it works** - - 1. The current array ``current`` is scanned for all points equal to zero and - point pairs that straddle :math:`I = 0`. This forms an array of - "crossing-points." - 2. The crossing-points are then grouped into "crossing-islands" in based on - the ``threshold`` keyword. - - - A new island is formed when a successive crossing-point is more (index) - steps away from the previous crossing-point than allowed by - ``threshold``. - - If multiple crossing-islands are identified, then the span from the - first point in the first island to the last point in the last island is - compared to ``min_points``. If the span is less than or equal to - ``min_points``, then that span is taken as one larger crossing-island - for the fit; otherwise, the function is incapable of identifying - :math:`V_f` and will return `numpy.nan` values. - - 3. To calculate the floating potential... - - - If the crossing-island contains fewer points than ``min_points``, then - each side of the crossing-island is equally padded with the nearest - neighbor points until ``min_points`` is satisfied. - - A fit is then performed using `scipy.stats.linregress` for - ``fit_type="linear"`` and `scipy.optimize.curve_fit` for - ``fit_type="exponential"``. + the probe bias where the collected current equals zero :math:`I = 0`. (For + additional details see the **Notes** section below.) Parameters ---------- @@ -75,7 +49,7 @@ def find_floating_potential( min_points: positive `int` or `float` Minimum number of data points required for the fitting to be applied to. - See **How it works** above for additional details. The following list + See **Notes** above for additional details. The following list specifies the optional values: - ``min_points = None`` (Default) The largest of 5 and @@ -135,6 +109,34 @@ def find_floating_potential( A `slice` object representing the indices of ``voltage`` and ``current`` arrays used for the fit. + Notes + ----- + The internal functionality works like: + + 1. The current array ``current`` is scanned for all points equal to zero and + point pairs that straddle :math:`I = 0`. This forms an array of + "crossing-points." + 2. The crossing-points are then grouped into "crossing-islands" in based on + the ``threshold`` keyword. + + - A new island is formed when a successive crossing-point is more (index) + steps away from the previous crossing-point than allowed by + ``threshold``. + - If multiple crossing-islands are identified, then the span from the + first point in the first island to the last point in the last island is + compared to ``min_points``. If the span is less than or equal to + ``min_points``, then that span is taken as one larger crossing-island + for the fit; otherwise, the function is incapable of identifying + :math:`V_f` and will return `numpy.nan` values. + + 3. To calculate the floating potential... + + - If the crossing-island contains fewer points than ``min_points``, then + each side of the crossing-island is equally padded with the nearest + neighbor points until ``min_points`` is satisfied. + - A fit is then performed using `scipy.stats.linregress` for + ``fit_type="linear"`` and `scipy.optimize.curve_fit` for + ``fit_type="exponential"``. """ rtn = FloatingPotentialResults( vf=np.nan, vf_err=np.nan, rsq=None, func=None, islands=None, indices=None From b5eee888282110fa1fd8409b579c5c7c192862f9 Mon Sep 17 00:00:00 2001 From: Erik Date: Tue, 2 Feb 2021 14:12:41 -0800 Subject: [PATCH 199/521] create and test alias find_vf_ for find_floating_potential --- plasmapy/analysis/swept_langmuir/__init__.py | 4 ++-- plasmapy/analysis/swept_langmuir/floating_potential.py | 8 +++++++- .../swept_langmuir/tests/test_floating_potential.py | 5 +++++ 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/plasmapy/analysis/swept_langmuir/__init__.py b/plasmapy/analysis/swept_langmuir/__init__.py index 5b747c23eb..f143e82927 100644 --- a/plasmapy/analysis/swept_langmuir/__init__.py +++ b/plasmapy/analysis/swept_langmuir/__init__.py @@ -1,7 +1,7 @@ """ Subpackage containing routines for analyzing swept Langmuir probe traces. """ -__all__ = ["check_sweep", "find_floating_potential"] +__all__ = ["check_sweep", "find_floating_potential", "find_vf_"] -from .floating_potential import find_floating_potential +from .floating_potential import find_floating_potential, find_vf_ from .helpers import check_sweep diff --git a/plasmapy/analysis/swept_langmuir/floating_potential.py b/plasmapy/analysis/swept_langmuir/floating_potential.py index ee5e332db8..eb507969f2 100644 --- a/plasmapy/analysis/swept_langmuir/floating_potential.py +++ b/plasmapy/analysis/swept_langmuir/floating_potential.py @@ -1,5 +1,5 @@ """Functionality for determining the floating potential of a Langmuir sweep.""" -__all__ = ["find_floating_potential"] +__all__ = ["find_floating_potential", "find_vf_"] import numbers import numpy as np @@ -30,6 +30,8 @@ def find_floating_potential( the probe bias where the collected current equals zero :math:`I = 0`. (For additional details see the **Notes** section below.) + **Aliases:** `find_vf_` + Parameters ---------- @@ -292,3 +294,7 @@ def find_floating_potential( rtn.update({"rsq": fit_func.rsq, "indices": slice(istart, istop + 1)}) return FloatingPotentialResults(**rtn) + + +find_vf_ = find_floating_potential +"""Alias to :func:`find_floating_potential`. """ diff --git a/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py b/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py index 9ff00b82b9..dbf05f5791 100644 --- a/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py +++ b/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py @@ -12,6 +12,7 @@ from plasmapy.analysis import swept_langmuir as _sl from plasmapy.analysis.swept_langmuir.floating_potential import ( find_floating_potential, + find_vf_, FloatingPotentialResults, ) from plasmapy.utils.exceptions import PlasmaPyWarning @@ -51,6 +52,10 @@ class TestFindFloatingPotential: _linear_p_sine_current = _linear_current + 1.2 * np.sin(1.2 * _voltage) _exp_current = -1.3 + 2.2 * np.exp(_voltage) + def test_alias(self): + """Test the associated alias(es) is(are) defined correctly.""" + assert find_vf_ is find_floating_potential + def test_call_of_check_sweep(self): """ Test `find_floating_potential` appropriately calls From 6fac0d1126408f45df95a044b582be4e487ab834 Mon Sep 17 00:00:00 2001 From: Erik Date: Tue, 2 Feb 2021 14:28:07 -0800 Subject: [PATCH 200/521] replace `min_points == 0` functionality with `min_points == np.inf` --- .../swept_langmuir/find_floating_potential.ipynb | 2 +- plasmapy/analysis/swept_langmuir/floating_potential.py | 8 ++++---- .../swept_langmuir/tests/test_floating_potential.py | 10 +++++++++- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb b/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb index 157d054e70..dc54a95233 100644 --- a/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb +++ b/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb @@ -84,7 +84,7 @@ " This specifies the minimum number of points that will be used in the curve fitting. As mentioned above, the crossing-islands are identified and then padded until `min_points` is satisfied.\n", " \n", " - `min_pints = None` (Default) then the larger of 5 and `factor * array_size` is taken, where `factor = 0.1` for `\"linear\"` and `0.2` for `\"exponential\"`.\n", - " - `min_points = 0` then the entire passed array is fitted.\n", + " - `min_points = numpy.inf` then the entire passed array is fitted.\n", " - `min_points >= 1` then this is the minimum number of points used.\n", " - `0 < min_points < 1` then then the minimum number of points is taken as `min_points * array_size`.\n", "\n", diff --git a/plasmapy/analysis/swept_langmuir/floating_potential.py b/plasmapy/analysis/swept_langmuir/floating_potential.py index eb507969f2..f753c5db1e 100644 --- a/plasmapy/analysis/swept_langmuir/floating_potential.py +++ b/plasmapy/analysis/swept_langmuir/floating_potential.py @@ -58,7 +58,7 @@ def find_floating_potential( ``factor * array_size`` is taken, where ``array_size`` is the size of ``voltage`` and ``factor = 0.1`` for ``fit_type = "linear"`` and ``0.2`` for ``"exponential"``. - - ``min_points = 0`` The entire passed array is fitted. + - ``min_points = numpy.inf`` The entire passed array is fitted. - ``min_points >= 1`` Exact minimum number of points. - ``0 < min_points < 0`` The minimum number of points is taken as ``min_points * array_size``. @@ -182,7 +182,7 @@ def find_floating_potential( f"Argument 'min_points' is wrong type '{type(min_points)}', expecting " f"an int or float." ) - elif min_points == 0: + elif np.isinf(min_points): # this signals to use all points pass elif 0 < min_points < 1: @@ -214,7 +214,7 @@ def find_floating_potential( threshold_indices = np.where(cp_intervals > threshold)[0] n_islands = threshold_indices.size + 1 - if min_points == 0: + if np.isinf(min_points): rtn["islands"] = [slice(cp_candidates[0], cp_candidates[-1] + 1)] elif n_islands == 1: rtn["islands"] = [slice(cp_candidates[0], cp_candidates[-1] + 1)] @@ -245,7 +245,7 @@ def find_floating_potential( return FloatingPotentialResults(**rtn) # Construct crossing-island (pad if needed) - if min_points == 0: + if np.isinf(min_points): # us all points istart = 0 istop = voltage.size - 1 diff --git a/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py b/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py index dbf05f5791..22e1cf4d98 100644 --- a/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py +++ b/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py @@ -111,6 +111,14 @@ def test_call_of_check_sweep(self): }, ValueError, ), + ( + { + "voltage": np.array([1.0, 2, 3, 4]), + "current": np.array([-1.0, 0, 1, 2]), + "min_points": 0, + }, + ValueError, + ), # # errors on kwarg threshold ( @@ -221,7 +229,7 @@ def test_warnings(self, kwargs, expected, _warning): @pytest.mark.parametrize( "min_points, fit_type, islands, indices", [ - (0, "linear", [slice(29, 31)], slice(0, 70)), + (np.inf, "linear", [slice(29, 31)], slice(0, 70)), (1, "linear", [slice(29, 31)], slice(29, 31)), (15, "linear", [slice(29, 31)], slice(22, 38)), (16, "linear", [slice(29, 31)], slice(22, 38)), From dd0cc762c581a13610aff1c45ebd1ae24bf35206 Mon Sep 17 00:00:00 2001 From: Erik Date: Tue, 2 Feb 2021 14:37:10 -0800 Subject: [PATCH 201/521] it's below not above --- plasmapy/analysis/swept_langmuir/floating_potential.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plasmapy/analysis/swept_langmuir/floating_potential.py b/plasmapy/analysis/swept_langmuir/floating_potential.py index f753c5db1e..2082e9ca6f 100644 --- a/plasmapy/analysis/swept_langmuir/floating_potential.py +++ b/plasmapy/analysis/swept_langmuir/floating_potential.py @@ -51,7 +51,7 @@ def find_floating_potential( min_points: positive `int` or `float` Minimum number of data points required for the fitting to be applied to. - See **Notes** above for additional details. The following list + See **Notes** section below for additional details. The following list specifies the optional values: - ``min_points = None`` (Default) The largest of 5 and From 1b4c81d0734fa00908fca86663c1b69bdc58f201 Mon Sep 17 00:00:00 2001 From: Erik Date: Tue, 2 Feb 2021 17:02:09 -0800 Subject: [PATCH 202/521] remove extra space --- plasmapy/analysis/swept_langmuir/floating_potential.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plasmapy/analysis/swept_langmuir/floating_potential.py b/plasmapy/analysis/swept_langmuir/floating_potential.py index 2082e9ca6f..071d5c5ad2 100644 --- a/plasmapy/analysis/swept_langmuir/floating_potential.py +++ b/plasmapy/analysis/swept_langmuir/floating_potential.py @@ -297,4 +297,4 @@ def find_floating_potential( find_vf_ = find_floating_potential -"""Alias to :func:`find_floating_potential`. """ +"""Alias to :func:`find_floating_potential`.""" From f15b32dd42d98a97114fa51ef60310de0475aaab Mon Sep 17 00:00:00 2001 From: Erik Date: Tue, 2 Feb 2021 17:05:36 -0800 Subject: [PATCH 203/521] create alias find_isat_ --- plasmapy/analysis/swept_langmuir/__init__.py | 3 ++- plasmapy/analysis/swept_langmuir/ion_saturation_current.py | 6 +++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/plasmapy/analysis/swept_langmuir/__init__.py b/plasmapy/analysis/swept_langmuir/__init__.py index a8f5351a1e..1d2e62a740 100644 --- a/plasmapy/analysis/swept_langmuir/__init__.py +++ b/plasmapy/analysis/swept_langmuir/__init__.py @@ -5,10 +5,11 @@ "check_sweep", "find_floating_potential", "find_ion_saturation_current", + "find_isat_", "find_vf_", ] from .floating_potential import find_floating_potential, find_vf_ from .helpers import check_sweep -from .ion_saturation_current import find_ion_saturation_current +from .ion_saturation_current import find_ion_saturation_current, find_isat_ diff --git a/plasmapy/analysis/swept_langmuir/ion_saturation_current.py b/plasmapy/analysis/swept_langmuir/ion_saturation_current.py index dee73d436c..8e033ec863 100644 --- a/plasmapy/analysis/swept_langmuir/ion_saturation_current.py +++ b/plasmapy/analysis/swept_langmuir/ion_saturation_current.py @@ -1,7 +1,7 @@ """ Functionality for determining the ion-saturation current of a Langmuir sweep. """ -__all__ = ["find_ion_saturation_current"] +__all__ = ["find_ion_saturation_current", "find_isat_"] import numpy as np @@ -72,3 +72,7 @@ def find_ion_saturation_current( rtn["isat_func"] = isat return IonSaturationCurrentResults(**rtn) + + +find_isat_ = find_ion_saturation_current +"""Alias to :func:`find_ion_saturation_current`.""" From 11d2cde103aef57faf30d3cfd605f15baa0d55d9 Mon Sep 17 00:00:00 2001 From: Erik Date: Tue, 2 Feb 2021 21:44:32 -0800 Subject: [PATCH 204/521] create test_ion_saturation_current.py and initate with test for IonSaturationCurrentResults --- .../tests/test_ion_saturation_current.py | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 plasmapy/analysis/swept_langmuir/tests/test_ion_saturation_current.py diff --git a/plasmapy/analysis/swept_langmuir/tests/test_ion_saturation_current.py b/plasmapy/analysis/swept_langmuir/tests/test_ion_saturation_current.py new file mode 100644 index 0000000000..5cb2786feb --- /dev/null +++ b/plasmapy/analysis/swept_langmuir/tests/test_ion_saturation_current.py @@ -0,0 +1,36 @@ +""" +Tests for functionality contained in +`plasmapy.analysis.swept_langmuir.ion_saturation_current`. +""" + +import numpy as np +import pytest + +from unittest import mock + +from plasmapy.analysis import fit_functions as ffuncs +from plasmapy.analysis import swept_langmuir as _sl +from plasmapy.analysis.swept_langmuir.ion_saturation_current import ( + find_ion_saturation_current, + find_isat_, + IonSaturationCurrentResults, +) + + +def test_ion_saturation_current_namedtuple(): + """ + Test structure of the namedtuple used to return the computed ion saturation + current data. + """ + + assert issubclass(IonSaturationCurrentResults, tuple) + assert hasattr(IonSaturationCurrentResults, "_fields") + assert IonSaturationCurrentResults._fields == ( + "isat_func", + "rsq", + "func", + "indices", + ) + assert hasattr(IonSaturationCurrentResults, "_field_defaults") + assert IonSaturationCurrentResults._field_defaults == {} + From ff1aa24be8e9e55a4d3ab8dfe07b73cc097e2aae Mon Sep 17 00:00:00 2001 From: Erik Date: Tue, 2 Feb 2021 21:46:45 -0800 Subject: [PATCH 205/521] create test class TestFindIonSaturationCurrent and initiate with test of alias find_isat_ --- .../tests/test_ion_saturation_current.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/plasmapy/analysis/swept_langmuir/tests/test_ion_saturation_current.py b/plasmapy/analysis/swept_langmuir/tests/test_ion_saturation_current.py index 5cb2786feb..01bba445c8 100644 --- a/plasmapy/analysis/swept_langmuir/tests/test_ion_saturation_current.py +++ b/plasmapy/analysis/swept_langmuir/tests/test_ion_saturation_current.py @@ -34,3 +34,13 @@ def test_ion_saturation_current_namedtuple(): assert hasattr(IonSaturationCurrentResults, "_field_defaults") assert IonSaturationCurrentResults._field_defaults == {} + +class TestFindIonSaturationCurrent: + """ + Tests for function + `~plasmapy.analysis.swept_langmuir.ion_saturation_current.find_ion_saturation_current`. + """ + + def test_alias(self): + """Test the associated alias(es) is(are) defined correctly.""" + assert find_isat_ is find_ion_saturation_current From 89bb8eb11eacd99138e455560811aba3445ce597 Mon Sep 17 00:00:00 2001 From: Erik Date: Tue, 2 Feb 2021 21:48:12 -0800 Subject: [PATCH 206/521] handful of cleanup refactoring based on what was learned with find_floating_potential --- .../swept_langmuir/ion_saturation_current.py | 78 +++++++++++-------- 1 file changed, 46 insertions(+), 32 deletions(-) diff --git a/plasmapy/analysis/swept_langmuir/ion_saturation_current.py b/plasmapy/analysis/swept_langmuir/ion_saturation_current.py index 8e033ec863..b43266ffe4 100644 --- a/plasmapy/analysis/swept_langmuir/ion_saturation_current.py +++ b/plasmapy/analysis/swept_langmuir/ion_saturation_current.py @@ -3,12 +3,13 @@ """ __all__ = ["find_ion_saturation_current", "find_isat_"] +import numbers import numpy as np from collections import namedtuple from plasmapy.analysis import fit_functions as ffuncs - +from plasmapy.analysis.swept_langmuir.helpers import check_sweep IonSaturationCurrentResults = namedtuple( "FloatingPotentialResults", @@ -19,35 +20,56 @@ def find_ion_saturation_current( voltage: np.ndarray, current: np.ndarray, - upper_bound=None, - fit_type: str = "explinear", + upper_bound: float = None, + fit_type: str = "exp_plus_linear", ): rtn = IonSaturationCurrentResults( - isat_func=None, - rsq=None, - func=None, - indices=None, + isat_func=None, rsq=None, func=None, indices=None, )._asdict() - fit_funcs = { - "linear": ffuncs.Linear(), - "explinear": ffuncs.ExponentialPlusLinear(), - "expffset": ffuncs.ExponentialPlusOffset(), + _settings = { + "linear": { + "func": ffuncs.Linear, "default_ubound_frac": 0.4, + }, + "exp_plus_linear": { + "func": ffuncs.ExponentialPlusLinear, "default_ubound_frac": 1.0, + }, + "exp_plus_offset": { + "func": ffuncs.ExponentialPlusOffset, "default_ubound_frac": 1.0, + }, } try: - fit_func = fit_funcs[fit_type] + default_ubound_frac = _settings[fit_type]["default_ubound_frac"] + fit_func = _settings[fit_type]["func"]() rtn["func"] = fit_func except KeyError: - raise KeyError( - f"Requested fit function '{fit_type}' is not a valid option, " - f"expecting on of '{list(fit_funcs)}'. Examine kwarg 'fit_curve' " - f"for valid options." + raise ValueError( + f"Requested fit '{fit_type}' is not a valid option. Valid options " + f"are {list(_settings.keys())}." ) - # mask = np.where(current <= 0)[0] + # check voltage and current arrays + voltage, current = check_sweep(voltage, current, strip_units=True) + + # condition kwarg upper_bound if upper_bound is None: - upper_bound = 0 - mask = np.where(voltage <= upper_bound)[0] + current_min = current.min() + current_bound = (1.0 - default_ubound_frac) * current_min + mask = np.where(current <= current_bound)[0] + + elif not isinstance(upper_bound, numbers.Real): + raise TypeError( + f"Keyword 'upper_bound' is of type {type(upper_bound)}, expected an " + f"int or float." + ) + else: + mask = np.where(voltage <= upper_bound)[0] + if mask.size == 0: + raise ValueError( + f"The value for keyword 'upper_bound' ({upper_bound}) resulted in " + f"identifying a fit window of size 0." + ) + mask = slice(0, mask[-1] + 1) rtn["indices"] = mask volt_sub = voltage[mask] @@ -56,19 +78,11 @@ def find_ion_saturation_current( rtn["rsq"] = fit_func.rsq - isat = ffuncs.Linear() - try: - m = fit_func.parameters.m - m_err = fit_func.parameters_err.m - except AttributeError: - m = m_err = 0.0 - try: - b = fit_func.parameters.b - b_err = fit_func.parameters_err.b - except AttributeError: - b = b_err = 0.0 - isat.parameters = [m, b] - isat.parameters_err = [m_err, b_err] + m = getattr(fit_func.params, "m", 0.0) + b = getattr(fit_func.params, "b", 0.0) + m_err = getattr(fit_func.param_errors, "m", 0.0) + b_err = getattr(fit_func.param_errors, "b", 0.0) + isat = ffuncs.Linear(params=(m, b), param_errors=(m_err, b_err)) rtn["isat_func"] = isat return IonSaturationCurrentResults(**rtn) From 85996535acf85e8908a9b1c0c9e73e38a32d0d6e Mon Sep 17 00:00:00 2001 From: Erik Date: Tue, 2 Feb 2021 21:56:09 -0800 Subject: [PATCH 207/521] fix typo --- .../analysis/swept_langmuir/find_floating_potential.ipynb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb b/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb index dc54a95233..4d29e1e3ce 100644 --- a/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb +++ b/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb @@ -6,7 +6,7 @@ "source": [ "# Swept Langmuir Analysis: Floating Potential\n", "\n", - "This notebook covers the use of the [**find_floating_potential()**](../../../api/plasmapy.analysis.swept_langmuir.floating_potential.find_floating_potential.rst#find-floating-potential) function to detering the floating potential from a swept Langmuir trace." + "This notebook covers the use of the [**find_floating_potential()**](../../../api/plasmapy.analysis.swept_langmuir.floating_potential.find_floating_potential.rst#find-floating-potential) function to determining the floating potential from a swept Langmuir trace." ] }, { From 1900b934855cd5d819c2fd005ef522bcd6aa6b89 Mon Sep 17 00:00:00 2001 From: Erik Date: Tue, 2 Feb 2021 22:12:02 -0800 Subject: [PATCH 208/521] add plasmapy.analysis.swept_langmuir.ion_saturation_current documentaiton files --- docs/ad/analysis/swept_langmuir.rst | 1 + ....analysis.swept_langmuir.ion_saturation_current.rst | 10 ++++++++++ 2 files changed, 11 insertions(+) create mode 100644 docs/api_static/plasmapy.analysis.swept_langmuir.ion_saturation_current.rst diff --git a/docs/ad/analysis/swept_langmuir.rst b/docs/ad/analysis/swept_langmuir.rst index 8851c8fcc0..ccc4229d16 100644 --- a/docs/ad/analysis/swept_langmuir.rst +++ b/docs/ad/analysis/swept_langmuir.rst @@ -26,6 +26,7 @@ Sub-Packages & Modules floating_potential helpers + ion_saturation_current .. automodapi:: plasmapy.analysis.swept_langmuir :no-main-docstr: diff --git a/docs/api_static/plasmapy.analysis.swept_langmuir.ion_saturation_current.rst b/docs/api_static/plasmapy.analysis.swept_langmuir.ion_saturation_current.rst new file mode 100644 index 0000000000..e089d8a0e6 --- /dev/null +++ b/docs/api_static/plasmapy.analysis.swept_langmuir.ion_saturation_current.rst @@ -0,0 +1,10 @@ +:orphan: + +`plasmapy.analysis.swept_langmuir.ion_saturation_current` +========================================================= + +.. currentmodule:: plasmapy.analysis.swept_langmuir.ion_saturation_current + +.. automodapi:: plasmapy.analysis.swept_langmuir.ion_saturation_current + :include-all-objects: + :no-heading: From 6498a660f2266266e525b95ca7bf7aaa19cf504c Mon Sep 17 00:00:00 2001 From: Erik Date: Tue, 2 Feb 2021 22:22:46 -0800 Subject: [PATCH 209/521] grammar fix --- .../analysis/swept_langmuir/find_floating_potential.ipynb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb b/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb index 4d29e1e3ce..270c70138a 100644 --- a/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb +++ b/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb @@ -132,7 +132,7 @@ "source": [ "### Interpreting results\n", "\n", - "The `find_floating_potential()` returns a six element named tuple, where...\n", + "The `find_floating_potential()` function returns a six element named tuple, where...\n", "\n", "- `results[0]` = `results.vf` = the determined floating potential (same units as the pass `voltage` array)\n" ] From 20fde538c70447948e899e55d86de30443054691 Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 8 Mar 2021 14:19:15 -0800 Subject: [PATCH 210/521] remove bold syntax in hyperlink that does not render correctly on RTD --- .../analysis/swept_langmuir/find_floating_potential.ipynb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb b/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb index c105bca4d8..3a90fcb1eb 100644 --- a/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb +++ b/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb @@ -6,7 +6,7 @@ "source": [ "# Swept Langmuir Analysis: Floating Potential\n", "\n", - "This notebook covers the use of the [**find_floating_potential()**](../../../api/plasmapy.analysis.swept_langmuir.floating_potential.find_floating_potential.rst#find-floating-potential) function and how it is used to determine the floating potential from a swept Langmuir trace.\n", + "This notebook covers the use of the [find_floating_potential()](../../../api/plasmapy.analysis.swept_langmuir.floating_potential.find_floating_potential.rst#find-floating-potential) function and how it is used to determine the floating potential from a swept Langmuir trace.\n", "\n", "The floating potential, $V_f$, is defined as the probe bias voltage at which there is no net collected current, $I=0$. This occurs because the floating potential slows the collected electrons and accelerates the collected ions to a point where the electron- and ion-currents balance each other out." ] From 10abc650faa5ad68b0176c2aa742ee4677ab7ae3 Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 24 Jan 2022 12:07:47 -0800 Subject: [PATCH 211/521] fix attribute calls --- .../find_ion_saturation_current.ipynb | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/docs/notebooks/analysis/swept_langmuir/find_ion_saturation_current.ipynb b/docs/notebooks/analysis/swept_langmuir/find_ion_saturation_current.ipynb index 855fd12952..68be4cd134 100644 --- a/docs/notebooks/analysis/swept_langmuir/find_ion_saturation_current.ipynb +++ b/docs/notebooks/analysis/swept_langmuir/find_ion_saturation_current.ipynb @@ -125,12 +125,12 @@ "# results_lin = sla.find_floating_potential(voltage, current, fit_type=\"linear\")\n", "results = sla.find_ion_saturation_current(voltage, current)\n", "(results,\n", - " results.isat_func.parameters,\n", - " results.func.parameters,\n", + " results.isat_func.params,\n", + " results.func.params,\n", " \"-- break --\",\n", " results_opt,\n", - " results_opt.isat_func.parameters,\n", - " results_opt.func.parameters,\n", + " results_opt.isat_func.params,\n", + " results_opt.func.params,\n", ")" ] }, @@ -195,8 +195,8 @@ " - `results.func` is a callable representation of the fitted function `I = results.func(V)`.\n", " - `resulst.func` is an instance of a sub-class of `AbstractFitFunction`. ([**FitFuction** classes](../../../api_static/plasmapy.analysis.swept_langmuir.fit_functions.rst))\n", " - Since `results.func` is a class instance, there are many other attribures available. For example,\n", - " - `results.func.parameters` is a named tuple of the fitted parameters\n", - " - `results.func.parameters_err` is a named tuple of the fitted parameter errors\n", + " - `results.func.params` is a named tuple of the fitted parameters\n", + " - `results.func.param_errors` is a named tuple of the fitted parameter errors\n", " - `results.func.root_solve()` finds the roots of the fitted function. This is how $V_f$ is calculated." ] }, @@ -208,10 +208,10 @@ "source": [ "# (results[3],\n", "# results.func,\n", - "# results.func.parameters,\n", - "# results.func.parameters.a,\n", - "# results.func.parameters_err,\n", - "# results.func.parameters_err.a,\n", + "# results.func.params,\n", + "# results.func.params.a,\n", + "# results.func.param_errors,\n", + "# results.func.param_errors.a,\n", "# results.func(results.vf),\n", "# )" ] From c953d68963b5dbfd5c6f865277244b25cb9dddfe Mon Sep 17 00:00:00 2001 From: Erik Date: Tue, 25 Jan 2022 09:57:01 -0800 Subject: [PATCH 212/521] move isat notebook into notebook_for_proto dir --- .../find_ion_saturation_current.ipynb | 395 ------------------ 1 file changed, 395 deletions(-) delete mode 100644 docs/notebooks/analysis/swept_langmuir/find_ion_saturation_current.ipynb diff --git a/docs/notebooks/analysis/swept_langmuir/find_ion_saturation_current.ipynb b/docs/notebooks/analysis/swept_langmuir/find_ion_saturation_current.ipynb deleted file mode 100644 index 68be4cd134..0000000000 --- a/docs/notebooks/analysis/swept_langmuir/find_ion_saturation_current.ipynb +++ /dev/null @@ -1,395 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Swept Langmuir Analysis: Ion-Saturation Current" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "%matplotlib inline\n", - "\n", - "import matplotlib.pyplot as plt\n", - "import numpy as np\n", - "import pprint\n", - "\n", - "from pathlib import Path\n", - "\n", - "from plasmapy.analysis import swept_langmuir as sla\n", - "\n", - "plt.rcParams['figure.figsize'] = [10.5, 0.56 * 10.5]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Contents:\n", - "\n", - "1. [How does **find_floating_potential()** work?](#How-does-find_floating_potential()-work?)\n", - " 1. [Notes about usage](#Notes-about-usage)\n", - " 1. [Knobs to turn](#Knobs-to-turn)\n", - "1. [Calculate the Floating Potential](#Calculate-the-Floating-Potential)\n", - " 1. [Interpreting results](#Interpreting-results)\n", - " 1. [Plotting results](#Plotting-results)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## How does `find_floating_potential()` work?\n", - "\n", - "1. The passed current array is scanned for points that equal zero and point-pairs that straddle $I = 0$. This forms an collection of \"crossing-points.\"\n", - "1. The crossing-points are then grouped into \"crossing-islands\" based on the `threshold` keyword.\n", - " - A new island is formed when a successive crossing-point is more (index) steps away from the previous corssing-point than defined by `threshold`. For example, if `threshld=4` then an new island is formed if a crossing-point candidate is more than 4 steps away from the previous candidate.\n", - " - If multiple crossing-islands are identified, then the function will compare the total span of all crossing-islands to `min_points`. If the span is greater than `min_points`, then the function is incapable of identifying $V_f$ and will return `numpy.nan` values; otherwise, the span will form one larger crossing-island.\n", - "1. To calculate the floating potential...\n", - " - If the number of points that make up the crossing-island is less than `min_points`, then each side of the \"crossing-island\" is equally padded with the nearest neighbor points until `min_points` is satisfied.\n", - " - If `fit_type=\"linear\"`, then a `scipy.stats.linregress` fit is applied to the points that make up the crossing-island.\n", - " - If `fit_type=\"exponential\"`, then a `scipy.optimize.curve_fit` fit is applied to the points that make up the crossing-island." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Notes about usage\n", - "\n", - "- The function provides no signal processing, so, if needed, the user must smooth, sort, crop, etc. the arrays before passing to the function.\n", - "- The function requires the voltage array to be monotonically increasing or decreasing.\n", - "- If the total range spanned by all crossing-islands is less than or equal to `min_points`, then `threshold` is ignored and all crossing-islands are grouped into one island." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Knobs to turn\n", - "\n", - "- `fit_type`\n", - "\n", - " There are two types of curves that can be fitted to the identified crossing point data, `\"linear\"` and `\"exponential\"`. The former will fit fit a line to the data, whereas, the later will fit and exponential curve with an offset. The default curve is `\"exponential\"` since swept Langmuir data is not typically linear as it passes through $I=0$.\n", - "\n", - "- `min_points`\n", - "\n", - " This specifies the minimum number of points that will be used in the curve fitting. As mentioned above, the crossing-islands are identified and then padded until `min_points` is satisfied.\n", - " \n", - " - `min_pints = None` (Default) then the larger of 5 and `factor * array_size` is taken, where `factor = 0.1` for `\"linear\"` and `0.2` for `\"exponential\"`.\n", - " - `min_points = 0` then the entire passed array is fitted.\n", - " - `min_points >= 1` then this is the minimum number of points used.\n", - " - `0 < min_points < 1` then then the minimum number of points is taken as `min_points * array_size`.\n", - "\n", - "\n", - "- `threshold`\n", - "\n", - " The max allowed index distance between crossing-points before a new crossing-island is formed." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Calculate the Floating Potential\n", - "\n", - "Below we'll compute the floaing potential using the default fitting behavior (`fit_type=\"exponential\"`) and a linear fit (`fit_type=\"linear\"`)." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# load data\n", - "filename = \"Beckers2017_noisy.npy\"\n", - "filepath = (Path.cwd() / \"..\" / \"..\" / \"langmuir_samples\" / filename).resolve()\n", - "voltage, current = np.load(filepath)\n", - "\n", - "# voltage array needs to be monotonically increasing/decreasing\n", - "isort = np.argsort(voltage)\n", - "voltage = voltage[isort]\n", - "current = current[isort]\n", - "\n", - "# get default fit results (exponential fit)\n", - "# results = sla.find_floating_potential(voltage, current, min_points=0.3)\n", - "results_opt = sla.find_ion_saturation_current(voltage, current, fit_type=\"linear\", upper_bound=-10)\n", - "\n", - "# get linear fit results\n", - "# results_lin = sla.find_floating_potential(voltage, current, fit_type=\"linear\")\n", - "results = sla.find_ion_saturation_current(voltage, current)\n", - "(results,\n", - " results.isat_func.params,\n", - " results.func.params,\n", - " \"-- break --\",\n", - " results_opt,\n", - " results_opt.isat_func.params,\n", - " results_opt.func.params,\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Interpreting results\n", - "\n", - "The `find_floating_potential()` returns a six element named tuple, where...\n", - "\n", - "- `results[0]` = `results.vf` = the determined floating potential (in volts)\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# (results[0], results.vf)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "- `results[1]` = `results.vf_err` = the associated error (in volts)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# (results[1], results.vf_err)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "- `results[2]` = `results.rsq` = the coeficient of determination (r-squared) value of the fit" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# (results[2], results.rsq)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "- `results[3]` = `results.func` = the resulting fitted function\n", - "\n", - " - `results.func` is a callable representation of the fitted function `I = results.func(V)`.\n", - " - `resulst.func` is an instance of a sub-class of `AbstractFitFunction`. ([**FitFuction** classes](../../../api_static/plasmapy.analysis.swept_langmuir.fit_functions.rst))\n", - " - Since `results.func` is a class instance, there are many other attribures available. For example,\n", - " - `results.func.params` is a named tuple of the fitted parameters\n", - " - `results.func.param_errors` is a named tuple of the fitted parameter errors\n", - " - `results.func.root_solve()` finds the roots of the fitted function. This is how $V_f$ is calculated." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# (results[3],\n", - "# results.func,\n", - "# results.func.params,\n", - "# results.func.params.a,\n", - "# results.func.param_errors,\n", - "# results.func.param_errors.a,\n", - "# results.func(results.vf),\n", - "# )" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "- `results[4]` = `results.islands` = a list of slice objects representing all the indentified crossing-islands" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# (results[4], \n", - "# results.islands,\n", - "# voltage[results.islands[0]],\n", - "# )" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "- `results[5]` = `results.indices` = a slice object representing the indices used in the fit" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# (results[5],\n", - "# results.indices,\n", - "# voltage[results.indices],\n", - "# )" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Plotting results" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "nbsphinx-thumbnail": { - "tooltip": "Floating Potential" - } - }, - "outputs": [], - "source": [ - "figwidth, figheight = plt.rcParams[\"figure.figsize\"]\n", - "figheight = 2. * figheight\n", - "fig, axs = plt.subplots(3, 1, figsize=[figwidth, figheight])\n", - "\n", - "# plot original data\n", - "axs[0].set_xlabel(\"Bias Voltage (V)\", fontsize=12)\n", - "axs[0].set_ylabel(\"Current (A)\", fontsize=12)\n", - "\n", - "axs[0].plot(voltage, current, zorder=10, label=\"Sweep Data\")\n", - "axs[0].axhline(0.0, color='r', linestyle='--', label=\"I = 0\")\n", - "axs[0].legend(fontsize=12)\n", - "\n", - "# zoom on fit\n", - "for ii, label, fit in zip([1, 2], [\"Exponential+Linear\", \"Linear\"], [results, results_opt]):\n", - " # calc island points\n", - "# isl_pts = np.array([], dtype=np.int64)\n", - "# for isl in fit.islands:\n", - "# isl_pts = np.concatenate((isl_pts, np.r_[isl]))\n", - " \n", - " # calc xrange for plot\n", - " xlim = [voltage[fit.indices].min(),\n", - " voltage[fit.indices].max()]\n", - " vpad = 0.25 * (xlim[1] - xlim[0])\n", - " xlim = [xlim[0] - 0.1 * vpad,\n", - " xlim[1] + vpad]\n", - " \n", - " # calc yrange for plot\n", - " umask = np.where(voltage >= xlim[0], True, False)\n", - " lmask = np.where(voltage <= xlim[1], True, False)\n", - " mask = np.logical_and(umask, lmask)\n", - " ylim = [current[mask].min(), current[mask].max()]\n", - " ypad = 0.15 * (ylim[1] - ylim[0])\n", - " factor = 7 if label == \"Linear\" else 1\n", - " ylim = [ylim[0] - ypad, ylim[1] + factor * ypad]\n", - "\n", - " # calc data points for fit curve\n", - " vfit = np.linspace(xlim[0], xlim[1], 201, endpoint=True)\n", - " ifit, ifit_err = fit.func(vfit, reterr=True)\n", - " \n", - " # calc isat line\n", - " isat, isat_err = fit.isat_func(vfit, reterr=True)\n", - "\n", - " axs[ii].set_xlabel(\"Bias Voltage (V)\", fontsize=12)\n", - " axs[ii].set_ylabel(\"Current (A)\", fontsize=12)\n", - " axs[ii].set_xlim(xlim)\n", - " axs[ii].set_ylim(ylim)\n", - "\n", - " zorder = 10\n", - " axs[ii].plot(voltage[mask], current[mask],\n", - " marker=\"o\", \n", - " zorder=zorder, \n", - " label=\"Sweep Data\")\n", - " zorder += 1\n", - " axs[ii].scatter(voltage[fit.indices],\n", - " current[fit.indices],\n", - " linewidth=2, s=6**2, \n", - " facecolors=\"deepskyblue\", edgecolors=\"deepskyblue\",\n", - " zorder=zorder,\n", - " label=\"Points for Fit\")\n", - "# axs[ii].scatter(voltage[isl_pts], current[isl_pts],\n", - "# linewidth=2, s=8**2, \n", - "# facecolors=\"deepskyblue\", edgecolors=\"black\",\n", - "# zorder=12,\n", - "# label=\"Island Points\")\n", - " axs[ii].autoscale(False)\n", - " zorder += 1\n", - " axs[ii].plot(vfit, ifit, color=\"orange\",\n", - " zorder=zorder,\n", - " label=label + \" Fit\")\n", - " axs[ii].fill_between(vfit, ifit + ifit_err, ifit - ifit_err,\n", - " color=\"orange\", alpha=0.12, zorder=0,\n", - " label=\"Fit Error\")\n", - " axs[ii].axhline(0.0, color='r', linestyle='--')\n", - " zorder += 1\n", - " axs[ii].plot(vfit, isat, color=\"black\",\n", - " label=\"Isat\", zorder=zorder)\n", - " axs[ii].fill_between(vfit, isat + isat_err, isat - isat_err,\n", - " color=\"black\", alpha=0.12, zorder=0,\n", - " label=\"Isat Error\")\n", - "# axs[ii].fill_between([fit.vf - fit.vf_err, fit.vf + fit.vf_err], \n", - "# axs[1].get_ylim()[0],\n", - "# axs[1].get_ylim()[1],\n", - "# color='grey', alpha=0.1)\n", - " axs[ii].legend(fontsize=12)\n", - "\n", - " # add text\n", - " rsq = fit.rsq\n", - " txt = f\"$r^2 = {rsq:.3f}$\"\n", - "# txt = (f\"$V_f = {fit.vf:.2f} \\\\pm {fit.vf_err:.2f}$ V\\n\"\n", - "# f\"$r^2 = {rsq:.3f}$\")\n", - " txt_loc = [-18, axs[ii].get_ylim()[1]]\n", - " txt_loc = axs[ii].transAxes.inverted().transform(axs[ii].transData.transform(txt_loc))\n", - " txt_loc[0] -= 0.02\n", - " txt_loc[1] -= 0.13\n", - " axs[ii].text(txt_loc[0], txt_loc[1], txt, \n", - " fontsize='large', transform=axs[ii].transAxes,\n", - " ha=\"left\")" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.7.6" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} From 97a31f88e7c8114d70e121c94289d9b992572237 Mon Sep 17 00:00:00 2001 From: Erik Date: Tue, 25 Jan 2022 09:57:43 -0800 Subject: [PATCH 213/521] update the automodapi call to reflect that of the directive defined by plasmapy_sphinx --- .../plasmapy.analysis.swept_langmuir.ion_saturation_current.rst | 2 -- 1 file changed, 2 deletions(-) diff --git a/docs/api_static/plasmapy.analysis.swept_langmuir.ion_saturation_current.rst b/docs/api_static/plasmapy.analysis.swept_langmuir.ion_saturation_current.rst index e089d8a0e6..7e8c3abb72 100644 --- a/docs/api_static/plasmapy.analysis.swept_langmuir.ion_saturation_current.rst +++ b/docs/api_static/plasmapy.analysis.swept_langmuir.ion_saturation_current.rst @@ -6,5 +6,3 @@ .. currentmodule:: plasmapy.analysis.swept_langmuir.ion_saturation_current .. automodapi:: plasmapy.analysis.swept_langmuir.ion_saturation_current - :include-all-objects: - :no-heading: From 9561b67ad91c8cea5ae5b635d2d619cb418e2f70 Mon Sep 17 00:00:00 2001 From: Erik Date: Sun, 6 Mar 2022 16:01:06 -0800 Subject: [PATCH 214/521] update isat return so it returns the isat function and an extras namedtuple --- .../swept_langmuir/ion_saturation_current.py | 30 +++++++++---------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/plasmapy/analysis/swept_langmuir/ion_saturation_current.py b/plasmapy/analysis/swept_langmuir/ion_saturation_current.py index b43266ffe4..d5a4842777 100644 --- a/plasmapy/analysis/swept_langmuir/ion_saturation_current.py +++ b/plasmapy/analysis/swept_langmuir/ion_saturation_current.py @@ -7,14 +7,12 @@ import numpy as np from collections import namedtuple +from typing import Tuple from plasmapy.analysis import fit_functions as ffuncs from plasmapy.analysis.swept_langmuir.helpers import check_sweep -IonSaturationCurrentResults = namedtuple( - "FloatingPotentialResults", - ("isat_func", "rsq", "func", "indices"), -) +ISatExtras = namedtuple("ISatExtras", ("rsq", "fitted_func", "fitted_indices")) def find_ion_saturation_current( @@ -22,26 +20,27 @@ def find_ion_saturation_current( current: np.ndarray, upper_bound: float = None, fit_type: str = "exp_plus_linear", -): - rtn = IonSaturationCurrentResults( - isat_func=None, rsq=None, func=None, indices=None, - )._asdict() +) -> Tuple[ffuncs.Linear, ISatExtras]: + rtn_extras = ISatExtras(rsq=None, fitted_func=None, fitted_indices=None)._asdict() _settings = { "linear": { - "func": ffuncs.Linear, "default_ubound_frac": 0.4, + "func": ffuncs.Linear, + "default_ubound_frac": 0.4, }, "exp_plus_linear": { - "func": ffuncs.ExponentialPlusLinear, "default_ubound_frac": 1.0, + "func": ffuncs.ExponentialPlusLinear, + "default_ubound_frac": 1.0, }, "exp_plus_offset": { - "func": ffuncs.ExponentialPlusOffset, "default_ubound_frac": 1.0, + "func": ffuncs.ExponentialPlusOffset, + "default_ubound_frac": 1.0, }, } try: default_ubound_frac = _settings[fit_type]["default_ubound_frac"] fit_func = _settings[fit_type]["func"]() - rtn["func"] = fit_func + rtn_extras["fitted_func"] = fit_func except KeyError: raise ValueError( f"Requested fit '{fit_type}' is not a valid option. Valid options " @@ -70,22 +69,21 @@ def find_ion_saturation_current( f"identifying a fit window of size 0." ) mask = slice(0, mask[-1] + 1) - rtn["indices"] = mask + rtn_extras["fitted_indices"] = mask volt_sub = voltage[mask] curr_sub = current[mask] fit_func.curve_fit(volt_sub, curr_sub) - rtn["rsq"] = fit_func.rsq + rtn_extras["rsq"] = fit_func.rsq m = getattr(fit_func.params, "m", 0.0) b = getattr(fit_func.params, "b", 0.0) m_err = getattr(fit_func.param_errors, "m", 0.0) b_err = getattr(fit_func.param_errors, "b", 0.0) isat = ffuncs.Linear(params=(m, b), param_errors=(m_err, b_err)) - rtn["isat_func"] = isat - return IonSaturationCurrentResults(**rtn) + return isat, ISatExtras(**rtn_extras) find_isat_ = find_ion_saturation_current From dcb0950122e98bd818fc40c0a99a4f2a1e398d9c Mon Sep 17 00:00:00 2001 From: Erik Date: Sun, 6 Mar 2022 16:11:35 -0800 Subject: [PATCH 215/521] update test_ion_saturation_current_namedtuple --- .../tests/test_ion_saturation_current.py | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/plasmapy/analysis/swept_langmuir/tests/test_ion_saturation_current.py b/plasmapy/analysis/swept_langmuir/tests/test_ion_saturation_current.py index 01bba445c8..beffcb5358 100644 --- a/plasmapy/analysis/swept_langmuir/tests/test_ion_saturation_current.py +++ b/plasmapy/analysis/swept_langmuir/tests/test_ion_saturation_current.py @@ -13,7 +13,7 @@ from plasmapy.analysis.swept_langmuir.ion_saturation_current import ( find_ion_saturation_current, find_isat_, - IonSaturationCurrentResults, + ISatExtras, ) @@ -23,16 +23,15 @@ def test_ion_saturation_current_namedtuple(): current data. """ - assert issubclass(IonSaturationCurrentResults, tuple) - assert hasattr(IonSaturationCurrentResults, "_fields") - assert IonSaturationCurrentResults._fields == ( - "isat_func", + assert issubclass(ISatExtras, tuple) + assert hasattr(ISatExtras, "_fields") + assert ISatExtras._fields == ( "rsq", - "func", - "indices", + "fitted_func", + "fitted_indices", ) - assert hasattr(IonSaturationCurrentResults, "_field_defaults") - assert IonSaturationCurrentResults._field_defaults == {} + assert hasattr(ISatExtras, "_field_defaults") + assert ISatExtras._field_defaults == {} class TestFindIonSaturationCurrent: From 565c6c564b92584c4f59baf578736007523732b7 Mon Sep 17 00:00:00 2001 From: Erik Date: Sun, 6 Mar 2022 16:11:48 -0800 Subject: [PATCH 216/521] add some class attributes --- .../swept_langmuir/tests/test_ion_saturation_current.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/plasmapy/analysis/swept_langmuir/tests/test_ion_saturation_current.py b/plasmapy/analysis/swept_langmuir/tests/test_ion_saturation_current.py index beffcb5358..86143c187b 100644 --- a/plasmapy/analysis/swept_langmuir/tests/test_ion_saturation_current.py +++ b/plasmapy/analysis/swept_langmuir/tests/test_ion_saturation_current.py @@ -40,6 +40,15 @@ class TestFindIonSaturationCurrent: `~plasmapy.analysis.swept_langmuir.ion_saturation_current.find_ion_saturation_current`. """ + _null_result = ( + None, + ISatExtras(rsq=None, fitted_func=None, fitted_indices=None)._asdict(), + ) + _voltage = np.linspace(-10.0, 15, 70) + _linear_current = np.linspace(-3.1, 4.1, 70) + _linear_p_sine_current = _linear_current + 1.2 * np.sin(1.2 * _voltage) + _exp_current = -1.3 + 2.2 * np.exp(_voltage) + def test_alias(self): """Test the associated alias(es) is(are) defined correctly.""" assert find_isat_ is find_ion_saturation_current From 0c4de1b5dff81df20b788b8b27895308ca8c5b91 Mon Sep 17 00:00:00 2001 From: Erik Date: Sun, 6 Mar 2022 17:49:36 -0800 Subject: [PATCH 217/521] add fit-function to glossary --- docs/glossary.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/glossary.rst b/docs/glossary.rst index dda0d2a763..9f79c01245 100644 --- a/docs/glossary.rst +++ b/docs/glossary.rst @@ -20,6 +20,12 @@ Glossary charge number The charge of a particle in units of elementary charge. + fit-function + fit-functions + Any instance of a subclass of + `~plasmapy.analysis.fit_functions.AbstractFitFunction`. Also see + module `~plasmapy.analysis.fit_functions`. + integration test An **integration test** verifies that multiple software components work together as intended. From 279914adcdc23363f90fccff99f5687e59e7b312 Mon Sep 17 00:00:00 2001 From: Erik Date: Sun, 6 Mar 2022 18:19:33 -0800 Subject: [PATCH 218/521] use typeing.NamedTuple instead of collections.namedtuple to improve documentation --- .../swept_langmuir/ion_saturation_current.py | 29 +++++++++++++++++-- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/plasmapy/analysis/swept_langmuir/ion_saturation_current.py b/plasmapy/analysis/swept_langmuir/ion_saturation_current.py index d5a4842777..732aff1738 100644 --- a/plasmapy/analysis/swept_langmuir/ion_saturation_current.py +++ b/plasmapy/analysis/swept_langmuir/ion_saturation_current.py @@ -6,13 +6,36 @@ import numbers import numpy as np -from collections import namedtuple -from typing import Tuple +from typing import Tuple, NamedTuple from plasmapy.analysis import fit_functions as ffuncs from plasmapy.analysis.swept_langmuir.helpers import check_sweep -ISatExtras = namedtuple("ISatExtras", ("rsq", "fitted_func", "fitted_indices")) +__all__ += __aliases__ + + +class ISatExtras(NamedTuple): + """ + Create a tuple containing the extra parameters calculated by + `find_ion_saturation_current`. + """ + rsq: float = None + """ + Alies for field number 0, the r-squared value of the ion-saturation + curve fit. + """ + + fitted_func: ffuncs.AbstractFitFunction = None + """ + Alias for field number 1, the :term:`fit-function` fitted during + the ion-satuaration cureve fit. + """ + + fitted_indices: slice = None + """ + Alias for field number 2, the indices used in the ion-saturation + curve fit. + """ def find_ion_saturation_current( From a197e1c63d662864750d8e1b06b7ac84496e3de8 Mon Sep 17 00:00:00 2001 From: Erik Date: Sun, 6 Mar 2022 18:20:16 -0800 Subject: [PATCH 219/521] cleanup dunder definitions --- plasmapy/analysis/swept_langmuir/ion_saturation_current.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plasmapy/analysis/swept_langmuir/ion_saturation_current.py b/plasmapy/analysis/swept_langmuir/ion_saturation_current.py index 732aff1738..037b2ff630 100644 --- a/plasmapy/analysis/swept_langmuir/ion_saturation_current.py +++ b/plasmapy/analysis/swept_langmuir/ion_saturation_current.py @@ -1,7 +1,8 @@ """ Functionality for determining the ion-saturation current of a Langmuir sweep. """ -__all__ = ["find_ion_saturation_current", "find_isat_"] +__all__ = ["find_ion_saturation_current", "ISatExtras"] +__aliases__ = ["find_isat_"] import numbers import numpy as np From 153edc2f9e220b0b5d6a7e4b3ca3ccdf21952253 Mon Sep 17 00:00:00 2001 From: Erik Date: Sun, 6 Mar 2022 18:28:31 -0800 Subject: [PATCH 220/521] let None by a valid type --- .../analysis/swept_langmuir/ion_saturation_current.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/plasmapy/analysis/swept_langmuir/ion_saturation_current.py b/plasmapy/analysis/swept_langmuir/ion_saturation_current.py index 037b2ff630..4ede15833a 100644 --- a/plasmapy/analysis/swept_langmuir/ion_saturation_current.py +++ b/plasmapy/analysis/swept_langmuir/ion_saturation_current.py @@ -7,7 +7,7 @@ import numbers import numpy as np -from typing import Tuple, NamedTuple +from typing import Tuple, NamedTuple, Union from plasmapy.analysis import fit_functions as ffuncs from plasmapy.analysis.swept_langmuir.helpers import check_sweep @@ -20,19 +20,19 @@ class ISatExtras(NamedTuple): Create a tuple containing the extra parameters calculated by `find_ion_saturation_current`. """ - rsq: float = None + rsq: Union[float, None] """ Alies for field number 0, the r-squared value of the ion-saturation curve fit. """ - fitted_func: ffuncs.AbstractFitFunction = None + fitted_func: Union[ffuncs.AbstractFitFunction, None] """ Alias for field number 1, the :term:`fit-function` fitted during the ion-satuaration cureve fit. """ - fitted_indices: slice = None + fitted_indices: Union[slice, None] """ Alias for field number 2, the indices used in the ion-saturation curve fit. From f7ffdfd6f2a5366b10787b798ee9426936d1a24f Mon Sep 17 00:00:00 2001 From: Erik Date: Sun, 6 Mar 2022 18:32:24 -0800 Subject: [PATCH 221/521] fix typos --- plasmapy/analysis/swept_langmuir/ion_saturation_current.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plasmapy/analysis/swept_langmuir/ion_saturation_current.py b/plasmapy/analysis/swept_langmuir/ion_saturation_current.py index 4ede15833a..40acb932c0 100644 --- a/plasmapy/analysis/swept_langmuir/ion_saturation_current.py +++ b/plasmapy/analysis/swept_langmuir/ion_saturation_current.py @@ -22,14 +22,14 @@ class ISatExtras(NamedTuple): """ rsq: Union[float, None] """ - Alies for field number 0, the r-squared value of the ion-saturation + Alias for field number 0, the r-squared value of the ion-saturation curve fit. """ fitted_func: Union[ffuncs.AbstractFitFunction, None] """ Alias for field number 1, the :term:`fit-function` fitted during - the ion-satuaration cureve fit. + the ion-saturation curve fit. """ fitted_indices: Union[slice, None] From f5f1453412301e95ae3dbd793818da87ecb71803 Mon Sep 17 00:00:00 2001 From: Erik Date: Sun, 6 Mar 2022 18:32:47 -0800 Subject: [PATCH 222/521] make keywords keyword-only --- plasmapy/analysis/swept_langmuir/ion_saturation_current.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plasmapy/analysis/swept_langmuir/ion_saturation_current.py b/plasmapy/analysis/swept_langmuir/ion_saturation_current.py index 40acb932c0..b8ee73ab21 100644 --- a/plasmapy/analysis/swept_langmuir/ion_saturation_current.py +++ b/plasmapy/analysis/swept_langmuir/ion_saturation_current.py @@ -42,6 +42,8 @@ class ISatExtras(NamedTuple): def find_ion_saturation_current( voltage: np.ndarray, current: np.ndarray, + *, + fit_type: str = "exp_plus_linear", upper_bound: float = None, fit_type: str = "exp_plus_linear", ) -> Tuple[ffuncs.Linear, ISatExtras]: From a42db860ed9d90364aeb01515f94264ce60bf913 Mon Sep 17 00:00:00 2001 From: Erik Date: Sun, 6 Mar 2022 18:39:50 -0800 Subject: [PATCH 223/521] add initial docstring --- .../swept_langmuir/ion_saturation_current.py | 42 ++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/plasmapy/analysis/swept_langmuir/ion_saturation_current.py b/plasmapy/analysis/swept_langmuir/ion_saturation_current.py index b8ee73ab21..84ff3db448 100644 --- a/plasmapy/analysis/swept_langmuir/ion_saturation_current.py +++ b/plasmapy/analysis/swept_langmuir/ion_saturation_current.py @@ -45,8 +45,48 @@ def find_ion_saturation_current( *, fit_type: str = "exp_plus_linear", upper_bound: float = None, - fit_type: str = "exp_plus_linear", ) -> Tuple[ffuncs.Linear, ISatExtras]: + """ + Determines the ion-saturation current (:math:`I_{sat}`) for a given + current-voltage (IV) curve obtained from a swept Langmuir probe. + The current collected by a Langmuir probe reaches ion-saturation + when the probe is sufficiently biased so the influx of electrons is + completely repelled leading to only the collection of ions. (For + additional details see the **Notes** section below.) + + **Aliases:** `find_isat_` + + Parameters + ---------- + + voltage: `numpy.ndarray` + 1-D numpy array of monotonically ascending/descending probe + biases (should be in volts). + + current: `numpy.ndarray` + 1-D numpy array of probe current (should be in amperes) + corresponding to the ``voltage`` array. + + fit_type: `str` + The type of curve (:term:`fit-function`) to be fitted to the + Langmuir trace, valid options are listed below. + (DEFAULT ``"exp_plus_linear"``) + + +-----------------------+----------------------------------------------------------+ + | ``"linear"`` | `~plasmapy.analysis.fit_functions.Linear` | + +-----------------------+----------------------------------------------------------+ + | ``"exponential"`` | `~plasmapy.analysis.fit_functions.ExponentialPlusOffset` | + +-----------------------+----------------------------------------------------------+ + | ``"exp_plus_linear"`` | `~plasmapy.analysis.fit_functions.ExponentialPlusLinear` | + +-----------------------+----------------------------------------------------------+ + + upper_bound: `float` + A bias voltage (in volts) that specifies an upper bound used to + collect the points for the curve fit. That is, points that + satisfy ``voltage <= upper_bound`` are used in the fit. + (DEFAULT ``None``) + + """ rtn_extras = ISatExtras(rsq=None, fitted_func=None, fitted_indices=None)._asdict() _settings = { From 1f51aa292402f1dafe227ffce57400c4b61f6564 Mon Sep 17 00:00:00 2001 From: Erik Date: Sun, 6 Mar 2022 20:31:23 -0800 Subject: [PATCH 224/521] add a Returns section to the docstring --- .../swept_langmuir/ion_saturation_current.py | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/plasmapy/analysis/swept_langmuir/ion_saturation_current.py b/plasmapy/analysis/swept_langmuir/ion_saturation_current.py index 84ff3db448..3d6d8b2a4f 100644 --- a/plasmapy/analysis/swept_langmuir/ion_saturation_current.py +++ b/plasmapy/analysis/swept_langmuir/ion_saturation_current.py @@ -86,6 +86,28 @@ def find_ion_saturation_current( satisfy ``voltage <= upper_bound`` are used in the fit. (DEFAULT ``None``) + | + + If ``upper_bound`` is not specified, then the route will collect + indices based on a current bound relative to ``np.min(current)`` + that is dependent on the ``fit_type`` specified. + + Returns + ------- + isat: `~plasmapy.analysis.fit_functions.Linear` + A :term:`fit-function` representing the linear portion of the + fitter curve. + + extras: `ISatExtras` + Additional information from the curve fit: + + * ``extras.fitted_func`` is the :term:`fit-function` (specified + by ``fit_type``) fitted to the IV-curve + * ``extras.rsq`` is the coefficient of determination + (r-squared) value of the ``extras.fitted_func`` to the IV-curve + * ``extras.fitted_indices`` is a `slice` object representing the + points used in the curve fit (i.e. + ``(voltage[extras.fitted_indices], current[extras.fitted_indices])``). """ rtn_extras = ISatExtras(rsq=None, fitted_func=None, fitted_indices=None)._asdict() @@ -121,7 +143,6 @@ def find_ion_saturation_current( current_min = current.min() current_bound = (1.0 - default_ubound_frac) * current_min mask = np.where(current <= current_bound)[0] - elif not isinstance(upper_bound, numbers.Real): raise TypeError( f"Keyword 'upper_bound' is of type {type(upper_bound)}, expected an " From 647fd8301a9028061e58acd6fe68a1bba36ee2c3 Mon Sep 17 00:00:00 2001 From: Erik Date: Sun, 6 Mar 2022 20:48:27 -0800 Subject: [PATCH 225/521] expand notes section in the docstring --- .../swept_langmuir/ion_saturation_current.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/plasmapy/analysis/swept_langmuir/ion_saturation_current.py b/plasmapy/analysis/swept_langmuir/ion_saturation_current.py index 3d6d8b2a4f..d1591fc66a 100644 --- a/plasmapy/analysis/swept_langmuir/ion_saturation_current.py +++ b/plasmapy/analysis/swept_langmuir/ion_saturation_current.py @@ -108,6 +108,25 @@ def find_ion_saturation_current( * ``extras.fitted_indices`` is a `slice` object representing the points used in the curve fit (i.e. ``(voltage[extras.fitted_indices], current[extras.fitted_indices])``). + + Notes + ----- + This routine works by: + + 1. Selecting the points to be used in the fit as determined by + ``upper_bound``, or internal parameters if ``upper_bound` is + not specific. + 2. Fitting the selected points with the :term:`fit-function` + specified by ``fit_type`. + 3. Extracting the linear component of the fit and returning that as + the ion-saturation current. + + This routine opts to return a function representing a linear + ion-saturation current, since, while ideal planar Langmuir probes + reach a steady-state ion-saturation current, real world Langmuir + probes "suffer" from expanding sheaths as the bias voltage + increases. This sheath expansion results the ion-saturation + current also increasing. """ rtn_extras = ISatExtras(rsq=None, fitted_func=None, fitted_indices=None)._asdict() From a64406d4b7ca12847e968466188d3b1149e43a17 Mon Sep 17 00:00:00 2001 From: Erik Date: Sun, 6 Mar 2022 21:54:38 -0800 Subject: [PATCH 226/521] replace upper_bound for voltage_bound and current_bound --- .../swept_langmuir/ion_saturation_current.py | 92 +++++++++++++------ 1 file changed, 62 insertions(+), 30 deletions(-) diff --git a/plasmapy/analysis/swept_langmuir/ion_saturation_current.py b/plasmapy/analysis/swept_langmuir/ion_saturation_current.py index d1591fc66a..c13a8d7a3f 100644 --- a/plasmapy/analysis/swept_langmuir/ion_saturation_current.py +++ b/plasmapy/analysis/swept_langmuir/ion_saturation_current.py @@ -44,7 +44,8 @@ def find_ion_saturation_current( current: np.ndarray, *, fit_type: str = "exp_plus_linear", - upper_bound: float = None, + current_bound: float = None, + voltage_bound: float = None, ) -> Tuple[ffuncs.Linear, ISatExtras]: """ Determines the ion-saturation current (:math:`I_{sat}`) for a given @@ -80,17 +81,31 @@ def find_ion_saturation_current( | ``"exp_plus_linear"`` | `~plasmapy.analysis.fit_functions.ExponentialPlusLinear` | +-----------------------+----------------------------------------------------------+ - upper_bound: `float` - A bias voltage (in volts) that specifies an upper bound used to - collect the points for the curve fit. That is, points that - satisfy ``voltage <= upper_bound`` are used in the fit. - (DEFAULT ``None``) + current_bound: `float` + A fraction representing a percentile window around the minimum + current for which to collect the points. For example, a value + of ``0.1`` indicates to use all points within 10% of the + minimum current. (DEFAULT ``None``) | - If ``upper_bound`` is not specified, then the route will collect - indices based on a current bound relative to ``np.min(current)`` - that is dependent on the ``fit_type`` specified. + If neither ``current_bound`` or ``voltage_bound`` are specified, + then the routine will collect indices based on an internal + ``current_bound`` setting for the specified ``fit_type``. + + +-----------------------+--------------------------------------+ + | ``"linear"`` | 0.4 | + +-----------------------+--------------------------------------+ + | ``"exponential"`` | 1.0 | + +-----------------------+--------------------------------------+ + | ``"exp_plus_linear"`` | 1.0 | + +-----------------------+--------------------------------------+ + + voltage_bound: `float` + A bias voltage (in volts) that specifies an upper bound used to + collect the points for the curve fit. That is, points that + satisfy ``voltage <= voltage_bound`` are used in the fit. + (DEFAULT ``None``) Returns ------- @@ -114,10 +129,9 @@ def find_ion_saturation_current( This routine works by: 1. Selecting the points to be used in the fit as determined by - ``upper_bound``, or internal parameters if ``upper_bound` is - not specific. + ``voltage_bound`` or ``current_bound``. 2. Fitting the selected points with the :term:`fit-function` - specified by ``fit_type`. + specified by ``fit_type``. 3. Extracting the linear component of the fit and returning that as the ion-saturation current. @@ -133,19 +147,19 @@ def find_ion_saturation_current( _settings = { "linear": { "func": ffuncs.Linear, - "default_ubound_frac": 0.4, + "current_bound": 0.4, }, "exp_plus_linear": { "func": ffuncs.ExponentialPlusLinear, - "default_ubound_frac": 1.0, + "current_bound": 1.0, }, "exp_plus_offset": { "func": ffuncs.ExponentialPlusOffset, - "default_ubound_frac": 1.0, + "current_bound": 1.0, }, } try: - default_ubound_frac = _settings[fit_type]["default_ubound_frac"] + default_current_bound = _settings[fit_type]["current_bound"] fit_func = _settings[fit_type]["func"]() rtn_extras["fitted_func"] = fit_func except KeyError: @@ -157,23 +171,41 @@ def find_ion_saturation_current( # check voltage and current arrays voltage, current = check_sweep(voltage, current, strip_units=True) - # condition kwarg upper_bound - if upper_bound is None: + # condition kwargs voltage_bound and current_bound + if voltage_bound is None and current_bound is None: + current_bound = default_current_bound + elif voltage_bound is not None and current_bound is not None: + raise ValueError( + "Both keywords 'current_bound' and `voltage_bound' are specified, " + "use only one." + ) + + if current_bound is not None: + if not isinstance(current_bound, numbers.Real): + raise TypeError( + f"Keyword 'current_bound' is of type {type(current_bound)}, " + f"expected an int or float." + ) + current_min = current.min() - current_bound = (1.0 - default_ubound_frac) * current_min + current_bound = (1.0 - current_bound) * current_min mask = np.where(current <= current_bound)[0] - elif not isinstance(upper_bound, numbers.Real): - raise TypeError( - f"Keyword 'upper_bound' is of type {type(upper_bound)}, expected an " - f"int or float." - ) - else: - mask = np.where(voltage <= upper_bound)[0] - if mask.size == 0: - raise ValueError( - f"The value for keyword 'upper_bound' ({upper_bound}) resulted in " - f"identifying a fit window of size 0." + else: # voltage_bound is not None + if not isinstance(voltage_bound, numbers.Real): + raise TypeError( + f"Keyword 'voltage_bound' is of type {type(voltage_bound)}, " + f"expected an int or float." ) + + mask = np.where(voltage <= voltage_bound)[0] + + if mask.size == 0: + raise ValueError( + f"The specified bounding keywords, 'voltage_bound' " + f"({voltage_bound}) and 'current_bound' ({current_bound}), " + f"resulted in a fit window containing no points." + ) + mask = slice(0, mask[-1] + 1) rtn_extras["fitted_indices"] = mask From 725484eab87937ec246d49f641bf3e1379874ad3 Mon Sep 17 00:00:00 2001 From: Erik Date: Tue, 8 Mar 2022 10:43:19 -0800 Subject: [PATCH 227/521] initial commit for test_raises --- .../tests/test_ion_saturation_current.py | 84 +++++++++++++++++++ 1 file changed, 84 insertions(+) diff --git a/plasmapy/analysis/swept_langmuir/tests/test_ion_saturation_current.py b/plasmapy/analysis/swept_langmuir/tests/test_ion_saturation_current.py index 86143c187b..96ad80ce52 100644 --- a/plasmapy/analysis/swept_langmuir/tests/test_ion_saturation_current.py +++ b/plasmapy/analysis/swept_langmuir/tests/test_ion_saturation_current.py @@ -52,3 +52,87 @@ class TestFindIonSaturationCurrent: def test_alias(self): """Test the associated alias(es) is(are) defined correctly.""" assert find_isat_ is find_ion_saturation_current + + @pytest.mark.parametrize( + "kwargs, _error", + [ + # errors on kwarg fit_type + ( + { + "voltage": np.array([1.0, 2, 3, 4]), + "current": np.array([-1.0, 0, 1, 2]), + "fit_type": "wrong", + }, + ValueError, + ), + # # + # # errors on kwarg upper_bound + # ( + # { + # "voltage": np.array([1.0, 2, 3, 4]), + # "current": np.array([-1.0, 0, 1, 2]), + # "min_points": "wrong", + # }, + # TypeError, + # ), + # ( + # { + # "voltage": np.array([1.0, 2, 3, 4]), + # "current": np.array([-1.0, 0, 1, 2]), + # "min_points": -1, + # }, + # ValueError, + # ), + # ( + # { + # "voltage": np.array([1.0, 2, 3, 4]), + # "current": np.array([-1.0, 0, 1, 2]), + # "min_points": 0, + # }, + # ValueError, + # ), + # # + # # errors on kwarg threshold + # ( + # { + # "voltage": np.array([1.0, 2, 3, 4]), + # "current": np.array([-1.0, 0, 1, 2]), + # "threshold": -1, + # }, + # ValueError, + # ), + # ( + # { + # "voltage": np.array([1.0, 2, 3, 4]), + # "current": np.array([-1.0, 0, 1, 2]), + # "threshold": "wrong type", + # }, + # TypeError, + # ), + # # + # # TypeError on voltage/current arrays from check_sweep + # ( + # { + # "voltage": "not an array", + # "current": np.array([-1.0, 0, 1, 2]), + # "fit_type": "linear", + # }, + # TypeError, + # ), + # # + # # ValueError on voltage/current arrays from check_sweep + # # (not linearly increasing) + # ( + # { + # "voltage": np.array([2.0, 1, 0, -1]), + # "current": np.array([-1.0, 0, 1, 2]), + # "fit_type": "linear", + # }, + # ValueError, + # ), + ], + ) + def test_raises(self, kwargs, _error): + """Test scenarios that raise `Exception`s.""" + with pytest.raises(_error): + find_ion_saturation_current(**kwargs) From ee2651ecabaa59b8aaf55e39812e702cd0e5f211 Mon Sep 17 00:00:00 2001 From: Erik Date: Tue, 8 Mar 2022 10:52:15 -0800 Subject: [PATCH 228/521] fillout test_raises cases --- .../tests/test_ion_saturation_current.py | 104 +++++++----------- 1 file changed, 39 insertions(+), 65 deletions(-) diff --git a/plasmapy/analysis/swept_langmuir/tests/test_ion_saturation_current.py b/plasmapy/analysis/swept_langmuir/tests/test_ion_saturation_current.py index 96ad80ce52..1d5fe9439c 100644 --- a/plasmapy/analysis/swept_langmuir/tests/test_ion_saturation_current.py +++ b/plasmapy/analysis/swept_langmuir/tests/test_ion_saturation_current.py @@ -65,71 +65,45 @@ def test_alias(self): }, ValueError, ), - # # - # # errors on kwarg upper_bound - # ( - # { - # "voltage": np.array([1.0, 2, 3, 4]), - # "current": np.array([-1.0, 0, 1, 2]), - # "min_points": "wrong", - # }, - # TypeError, - # ), - # ( - # { - # "voltage": np.array([1.0, 2, 3, 4]), - # "current": np.array([-1.0, 0, 1, 2]), - # "min_points": -1, - # }, - # ValueError, - # ), - # ( - # { - # "voltage": np.array([1.0, 2, 3, 4]), - # "current": np.array([-1.0, 0, 1, 2]), - # "min_points": 0, - # }, - # ValueError, - # ), - # # - # # errors on kwarg threshold - # ( - # { - # "voltage": np.array([1.0, 2, 3, 4]), - # "current": np.array([-1.0, 0, 1, 2]), - # "threshold": -1, - # }, - # ValueError, - # ), - # ( - # { - # "voltage": np.array([1.0, 2, 3, 4]), - # "current": np.array([-1.0, 0, 1, 2]), - # "threshold": "wrong type", - # }, - # TypeError, - # ), - # # - # # TypeError on voltage/current arrays from check_sweep - # ( - # { - # "voltage": "not an array", - # "current": np.array([-1.0, 0, 1, 2]), - # "fit_type": "linear", - # }, - # TypeError, - # ), - # # - # # ValueError on voltage/current arrays from check_sweep - # # (not linearly increasing) - # ( - # { - # "voltage": np.array([2.0, 1, 0, -1]), - # "current": np.array([-1.0, 0, 1, 2]), - # "fit_type": "linear", - # }, - # ValueError, - # ), + # + # current_bound and voltage_bound specified + ( + { + "voltage": np.array([1.0, 2, 3, 4]), + "current": np.array([-1.0, 0, 1, 2]), + "current_bound": 0.5, + "voltage_bound": 0.0, + }, + ValueError, + ), + # + # current_bound/voltage_bound not the right type + ( + { + "voltage": np.array([1.0, 2, 3, 4]), + "current": np.array([-1.0, 0, 1, 2]), + "current_bound": "not a number", + }, + TypeError, + ), + ( + { + "voltage": np.array([1.0, 2, 3, 4]), + "current": np.array([-1.0, 0, 1, 2]), + "voltage_bound": "not a number", + }, + TypeError, + ), + # + # arguments result in no collected indices to fit + ( + { + "voltage": np.array([1.0, 2, 3, 4]), + "current": np.array([-1.0, 0, 1, 2]), + "voltage_bound": 0.0, + }, + ValueError, + ), ], ) def test_raises(self, kwargs, _error): From b44d6147042d72740337a2bdfcb2a1fdea41c36d Mon Sep 17 00:00:00 2001 From: Erik Date: Tue, 8 Mar 2022 10:52:57 -0800 Subject: [PATCH 229/521] update docstring --- .../swept_langmuir/tests/test_ion_saturation_current.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plasmapy/analysis/swept_langmuir/tests/test_ion_saturation_current.py b/plasmapy/analysis/swept_langmuir/tests/test_ion_saturation_current.py index 1d5fe9439c..68539683e8 100644 --- a/plasmapy/analysis/swept_langmuir/tests/test_ion_saturation_current.py +++ b/plasmapy/analysis/swept_langmuir/tests/test_ion_saturation_current.py @@ -107,6 +107,6 @@ def test_alias(self): ], ) def test_raises(self, kwargs, _error): - """Test scenarios that raise `Exception`s.""" + """Test scenarios that raise exceptions.""" with pytest.raises(_error): find_ion_saturation_current(**kwargs) From 2bce434ac92bcf5c3f9b860b7993d6307067208a Mon Sep 17 00:00:00 2001 From: Erik Date: Tue, 8 Mar 2022 10:59:32 -0800 Subject: [PATCH 230/521] update docstring...voltage is monotonically increasing --- plasmapy/analysis/swept_langmuir/ion_saturation_current.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plasmapy/analysis/swept_langmuir/ion_saturation_current.py b/plasmapy/analysis/swept_langmuir/ion_saturation_current.py index c13a8d7a3f..4ebdff772f 100644 --- a/plasmapy/analysis/swept_langmuir/ion_saturation_current.py +++ b/plasmapy/analysis/swept_langmuir/ion_saturation_current.py @@ -61,8 +61,8 @@ def find_ion_saturation_current( ---------- voltage: `numpy.ndarray` - 1-D numpy array of monotonically ascending/descending probe - biases (should be in volts). + 1-D numpy array of monotonically increasing probe biases + (should be in volts). current: `numpy.ndarray` 1-D numpy array of probe current (should be in amperes) From c018cf1b0a9b3b19db2d62b683363ec91c41d187 Mon Sep 17 00:00:00 2001 From: Erik Date: Tue, 8 Mar 2022 11:00:15 -0800 Subject: [PATCH 231/521] update docstring...voltage is monotonically increasing --- plasmapy/analysis/swept_langmuir/floating_potential.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/plasmapy/analysis/swept_langmuir/floating_potential.py b/plasmapy/analysis/swept_langmuir/floating_potential.py index ea783261d6..34c4a2d7cd 100644 --- a/plasmapy/analysis/swept_langmuir/floating_potential.py +++ b/plasmapy/analysis/swept_langmuir/floating_potential.py @@ -38,8 +38,7 @@ def find_floating_potential( ---------- voltage: `numpy.ndarray` - 1-D numpy array of monotonically ascending/descending probe biases - (should be in volts) + 1-D numpy array of monotonically ascending probe biases (should be in volts) current: `numpy.ndarray` 1-D numpy array of probe current (should be in amperes) corresponding From bd6027ea07a659503d8cf12b135ded2c18dfee03 Mon Sep 17 00:00:00 2001 From: Erik Everson Date: Wed, 9 Mar 2022 12:08:37 -0800 Subject: [PATCH 232/521] Apply suggestions from code review Co-authored-by: Nick Murphy --- plasmapy/analysis/swept_langmuir/ion_saturation_current.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plasmapy/analysis/swept_langmuir/ion_saturation_current.py b/plasmapy/analysis/swept_langmuir/ion_saturation_current.py index 4ebdff772f..64280a621a 100644 --- a/plasmapy/analysis/swept_langmuir/ion_saturation_current.py +++ b/plasmapy/analysis/swept_langmuir/ion_saturation_current.py @@ -17,7 +17,7 @@ class ISatExtras(NamedTuple): """ - Create a tuple containing the extra parameters calculated by + Create a `tuple` containing the extra parameters calculated by `find_ion_saturation_current`. """ rsq: Union[float, None] @@ -52,7 +52,7 @@ def find_ion_saturation_current( current-voltage (IV) curve obtained from a swept Langmuir probe. The current collected by a Langmuir probe reaches ion-saturation when the probe is sufficiently biased so the influx of electrons is - completely repelled leading to only the collection of ions. (For + completely repelled, which leads to only the collection of ions. (For additional details see the **Notes** section below.) **Aliases:** `find_isat_` @@ -176,7 +176,7 @@ def find_ion_saturation_current( current_bound = default_current_bound elif voltage_bound is not None and current_bound is not None: raise ValueError( - "Both keywords 'current_bound' and `voltage_bound' are specified, " + "Both keywords 'current_bound' and 'voltage_bound' are specified, " "use only one." ) From 8544d197183e5ee701628417f4c9259dbddc2470 Mon Sep 17 00:00:00 2001 From: Erik Date: Tue, 17 May 2022 15:47:43 -0700 Subject: [PATCH 233/521] update docstring to indicate voltage_bound and current_bound can not be used simultaneously --- .../analysis/swept_langmuir/ion_saturation_current.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/plasmapy/analysis/swept_langmuir/ion_saturation_current.py b/plasmapy/analysis/swept_langmuir/ion_saturation_current.py index 64280a621a..05b4dd26e2 100644 --- a/plasmapy/analysis/swept_langmuir/ion_saturation_current.py +++ b/plasmapy/analysis/swept_langmuir/ion_saturation_current.py @@ -101,12 +101,20 @@ def find_ion_saturation_current( | ``"exp_plus_linear"`` | 1.0 | +-----------------------+--------------------------------------+ + | + + Can not be used with keyword ``voltage_bound``. + voltage_bound: `float` A bias voltage (in volts) that specifies an upper bound used to collect the points for the curve fit. That is, points that satisfy ``voltage <= voltage_bound`` are used in the fit. (DEFAULT ``None``) + | + + Can not be used with keyword ``current_bound``. + Returns ------- isat: `~plasmapy.analysis.fit_functions.Linear` From cd1721d66cb1a87e693c442de6dc8422dcccfd73 Mon Sep 17 00:00:00 2001 From: Erik Date: Tue, 17 May 2022 17:35:05 -0700 Subject: [PATCH 234/521] add test_analytical_fits --- .../tests/test_ion_saturation_current.py | 75 +++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/plasmapy/analysis/swept_langmuir/tests/test_ion_saturation_current.py b/plasmapy/analysis/swept_langmuir/tests/test_ion_saturation_current.py index 68539683e8..6e8d2b7b42 100644 --- a/plasmapy/analysis/swept_langmuir/tests/test_ion_saturation_current.py +++ b/plasmapy/analysis/swept_langmuir/tests/test_ion_saturation_current.py @@ -39,6 +39,15 @@ class TestFindIonSaturationCurrent: Tests for function `~plasmapy.analysis.swept_langmuir.ion_saturation_current.find_ion_saturation_current`. """ + analytical_funcs = { + "linear": ffuncs.Linear(params=(0.0004, -0.014)), + } + analytical_data = {"voltage": np.linspace(-30.0, 35, 100)} + analytical_data.update( + { + "current_linear": analytical_funcs["linear"](analytical_data["voltage"]), + }, + ) _null_result = ( None, @@ -110,3 +119,69 @@ def test_raises(self, kwargs, _error): """Test scenarios that raise exceptions.""" with pytest.raises(_error): find_ion_saturation_current(**kwargs) + + @pytest.mark.parametrize( + "kwargs, expected", + [ + ( + { + "voltage": analytical_data["voltage"], + "current": analytical_data["current_linear"], + "fit_type": "linear", + }, + ( + analytical_funcs["linear"], + ISatExtras( + fitted_func=analytical_funcs["linear"], + rsq=None, + fitted_indices=slice(0, 40), + ), + ), + ), + ( + { + "voltage": analytical_data["voltage"], + "current": analytical_data["current_linear"], + "fit_type": "linear", + "current_bound": 0.2 + }, + ( + analytical_funcs["linear"], + ISatExtras( + fitted_func=analytical_funcs["linear"], + rsq=None, + fitted_indices=slice(0, 20), + ), + ), + ), + ( + { + "voltage": analytical_data["voltage"], + "current": analytical_data["current_linear"], + "fit_type": "linear", + "voltage_bound": 0.0 + }, + ( + analytical_funcs["linear"], + ISatExtras( + fitted_func=analytical_funcs["linear"], + rsq=None, + fitted_indices=slice(0, 46), + ), + ), + ), + ], + ) + def test_analytical_fits(self, kwargs, expected): + isat, extras = find_ion_saturation_current(**kwargs) + + # assertions on isat + assert isinstance(isat, type(expected[0])) + assert np.allclose(isat.params, expected[0].params) + + # assertions on extras + assert isinstance(extras, ISatExtras) + assert isinstance(extras.fitted_func, type(expected[1].fitted_func)) + assert np.allclose(extras.fitted_func.params, expected[1].fitted_func.params) + assert np.isclose(extras.rsq, 1.0) + assert extras.fitted_indices == expected[1].fitted_indices From 7b4db0b7d8e6275e6391baf9ee9289991de22b71 Mon Sep 17 00:00:00 2001 From: Erik Date: Tue, 17 May 2022 18:18:03 -0700 Subject: [PATCH 235/521] update docstring for fit_type (exp_plus_offset, not exponential) --- plasmapy/analysis/swept_langmuir/ion_saturation_current.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plasmapy/analysis/swept_langmuir/ion_saturation_current.py b/plasmapy/analysis/swept_langmuir/ion_saturation_current.py index 05b4dd26e2..13fe6ef7c8 100644 --- a/plasmapy/analysis/swept_langmuir/ion_saturation_current.py +++ b/plasmapy/analysis/swept_langmuir/ion_saturation_current.py @@ -76,7 +76,7 @@ def find_ion_saturation_current( +-----------------------+----------------------------------------------------------+ | ``"linear"`` | `~plasmapy.analysis.fit_functions.Linear` | +-----------------------+----------------------------------------------------------+ - | ``"exponential"`` | `~plasmapy.analysis.fit_functions.ExponentialPlusOffset` | + | ``"exp_plus_offset"`` | `~plasmapy.analysis.fit_functions.ExponentialPlusOffset` | +-----------------------+----------------------------------------------------------+ | ``"exp_plus_linear"`` | `~plasmapy.analysis.fit_functions.ExponentialPlusLinear` | +-----------------------+----------------------------------------------------------+ From 3a0ec9a3e93d3bf26fcfe2f92f1b36fa499bc967 Mon Sep 17 00:00:00 2001 From: Erik Date: Tue, 17 May 2022 18:18:17 -0700 Subject: [PATCH 236/521] add test case for analytical exponenetial plus offset --- .../tests/test_ion_saturation_current.py | 40 +++++++++++++++++-- 1 file changed, 37 insertions(+), 3 deletions(-) diff --git a/plasmapy/analysis/swept_langmuir/tests/test_ion_saturation_current.py b/plasmapy/analysis/swept_langmuir/tests/test_ion_saturation_current.py index 6e8d2b7b42..d3e4337c77 100644 --- a/plasmapy/analysis/swept_langmuir/tests/test_ion_saturation_current.py +++ b/plasmapy/analysis/swept_langmuir/tests/test_ion_saturation_current.py @@ -6,10 +6,7 @@ import numpy as np import pytest -from unittest import mock - from plasmapy.analysis import fit_functions as ffuncs -from plasmapy.analysis import swept_langmuir as _sl from plasmapy.analysis.swept_langmuir.ion_saturation_current import ( find_ion_saturation_current, find_isat_, @@ -41,11 +38,15 @@ class TestFindIonSaturationCurrent: """ analytical_funcs = { "linear": ffuncs.Linear(params=(0.0004, -0.014)), + "exp_offset": ffuncs.ExponentialPlusOffset(params=(0.001, 0.1, -0.01)), } analytical_data = {"voltage": np.linspace(-30.0, 35, 100)} analytical_data.update( { "current_linear": analytical_funcs["linear"](analytical_data["voltage"]), + "current_exp_offset": analytical_funcs["exp_offset"]( + analytical_data["voltage"] + ), }, ) @@ -123,6 +124,7 @@ def test_raises(self, kwargs, _error): @pytest.mark.parametrize( "kwargs, expected", [ + # linear fit to linear analytical data ( { "voltage": analytical_data["voltage"], @@ -170,6 +172,38 @@ def test_raises(self, kwargs, _error): ), ), ), + # exponential plus offset fit to exponential plus offset analytical data + ( + { + "voltage": analytical_data["voltage"], + "current": analytical_data["current_exp_offset"], + "fit_type": "exp_plus_offset", + }, + ( + ffuncs.Linear(params=(0.0, analytical_funcs["exp_offset"].params.b)), + ISatExtras( + fitted_func=analytical_funcs["exp_offset"], + rsq=None, + fitted_indices=slice(0, 81), + ), + ), + ), + ( + { + "voltage": analytical_data["voltage"], + "current": analytical_data["current_exp_offset"], + "fit_type": "exp_plus_offset", + "voltage_bound": 30, + }, + ( + ffuncs.Linear(params=(0.0, analytical_funcs["exp_offset"].params.b)), + ISatExtras( + fitted_func=analytical_funcs["exp_offset"], + rsq=None, + fitted_indices=slice(0, 92), + ), + ), + ), ], ) def test_analytical_fits(self, kwargs, expected): From 1d59ef4803c275fadc864ef07af055bfa941f5d1 Mon Sep 17 00:00:00 2001 From: Erik Date: Tue, 17 May 2022 18:19:18 -0700 Subject: [PATCH 237/521] add placeholder test for testing on pace data --- .../swept_langmuir/tests/test_ion_saturation_current.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/plasmapy/analysis/swept_langmuir/tests/test_ion_saturation_current.py b/plasmapy/analysis/swept_langmuir/tests/test_ion_saturation_current.py index d3e4337c77..4d309b5117 100644 --- a/plasmapy/analysis/swept_langmuir/tests/test_ion_saturation_current.py +++ b/plasmapy/analysis/swept_langmuir/tests/test_ion_saturation_current.py @@ -204,6 +204,7 @@ def test_raises(self, kwargs, _error): ), ), ), + # exponential plus linear fit to exponential plus linear analytical data ], ) def test_analytical_fits(self, kwargs, expected): @@ -219,3 +220,7 @@ def test_analytical_fits(self, kwargs, expected): assert np.allclose(extras.fitted_func.params, expected[1].fitted_func.params) assert np.isclose(extras.rsq, 1.0) assert extras.fitted_indices == expected[1].fitted_indices + + @pytest.mark.skip + def test_pace_data(self): + ... From ce91d9d84d0d69ce34e9914da3333d45581a5678 Mon Sep 17 00:00:00 2001 From: Erik Date: Tue, 17 May 2022 18:25:08 -0700 Subject: [PATCH 238/521] add test case for analytical exponential plus linear --- .../tests/test_ion_saturation_current.py | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/plasmapy/analysis/swept_langmuir/tests/test_ion_saturation_current.py b/plasmapy/analysis/swept_langmuir/tests/test_ion_saturation_current.py index 4d309b5117..8abf07aee7 100644 --- a/plasmapy/analysis/swept_langmuir/tests/test_ion_saturation_current.py +++ b/plasmapy/analysis/swept_langmuir/tests/test_ion_saturation_current.py @@ -39,6 +39,7 @@ class TestFindIonSaturationCurrent: analytical_funcs = { "linear": ffuncs.Linear(params=(0.0004, -0.014)), "exp_offset": ffuncs.ExponentialPlusOffset(params=(0.001, 0.1, -0.01)), + "exp_linear": ffuncs.ExponentialPlusLinear(params=(0.001, 0.1, 0.00005, -0.01)), } analytical_data = {"voltage": np.linspace(-30.0, 35, 100)} analytical_data.update( @@ -47,6 +48,9 @@ class TestFindIonSaturationCurrent: "current_exp_offset": analytical_funcs["exp_offset"]( analytical_data["voltage"] ), + "current_exp_linear": analytical_funcs["exp_linear"]( + analytical_data["voltage"] + ), }, ) @@ -205,6 +209,45 @@ def test_raises(self, kwargs, _error): ), ), # exponential plus linear fit to exponential plus linear analytical data + ( + { + "voltage": analytical_data["voltage"], + "current": analytical_data["current_exp_linear"], + "fit_type": "exp_plus_linear", + }, + ( + ffuncs.Linear(params=( + analytical_funcs["exp_linear"].params.m, + analytical_funcs["exp_linear"].params.b + )), + ISatExtras( + fitted_func=analytical_funcs["exp_linear"], + rsq=None, + fitted_indices=slice(0, 79), + ), + ), + ), + ( + { + "voltage": analytical_data["voltage"], + "current": analytical_data["current_exp_linear"], + "fit_type": "exp_plus_linear", + "voltage_bound": 30, + }, + ( + ffuncs.Linear( + params=( + analytical_funcs["exp_linear"].params.m, + analytical_funcs["exp_linear"].params.b + ) + ), + ISatExtras( + fitted_func=analytical_funcs["exp_linear"], + rsq=None, + fitted_indices=slice(0, 92), + ), + ), + ), ], ) def test_analytical_fits(self, kwargs, expected): From f8b3895d730c71bcfc3aa31ae15b445bbbb18f19 Mon Sep 17 00:00:00 2001 From: Erik Date: Tue, 17 May 2022 18:26:57 -0700 Subject: [PATCH 239/521] appease grumpy black --- .../swept_langmuir/ion_saturation_current.py | 3 ++- .../tests/test_ion_saturation_current.py | 25 ++++++++++++------- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/plasmapy/analysis/swept_langmuir/ion_saturation_current.py b/plasmapy/analysis/swept_langmuir/ion_saturation_current.py index 13fe6ef7c8..0445e3ce25 100644 --- a/plasmapy/analysis/swept_langmuir/ion_saturation_current.py +++ b/plasmapy/analysis/swept_langmuir/ion_saturation_current.py @@ -20,13 +20,14 @@ class ISatExtras(NamedTuple): Create a `tuple` containing the extra parameters calculated by `find_ion_saturation_current`. """ + rsq: Union[float, None] """ Alias for field number 0, the r-squared value of the ion-saturation curve fit. """ - fitted_func: Union[ffuncs.AbstractFitFunction, None] + fitted_func: Union[ffuncs.AbstractFitFunction, None] """ Alias for field number 1, the :term:`fit-function` fitted during the ion-saturation curve fit. diff --git a/plasmapy/analysis/swept_langmuir/tests/test_ion_saturation_current.py b/plasmapy/analysis/swept_langmuir/tests/test_ion_saturation_current.py index 8abf07aee7..241be0eb08 100644 --- a/plasmapy/analysis/swept_langmuir/tests/test_ion_saturation_current.py +++ b/plasmapy/analysis/swept_langmuir/tests/test_ion_saturation_current.py @@ -36,6 +36,7 @@ class TestFindIonSaturationCurrent: Tests for function `~plasmapy.analysis.swept_langmuir.ion_saturation_current.find_ion_saturation_current`. """ + analytical_funcs = { "linear": ffuncs.Linear(params=(0.0004, -0.014)), "exp_offset": ffuncs.ExponentialPlusOffset(params=(0.001, 0.1, -0.01)), @@ -149,7 +150,7 @@ def test_raises(self, kwargs, _error): "voltage": analytical_data["voltage"], "current": analytical_data["current_linear"], "fit_type": "linear", - "current_bound": 0.2 + "current_bound": 0.2, }, ( analytical_funcs["linear"], @@ -165,7 +166,7 @@ def test_raises(self, kwargs, _error): "voltage": analytical_data["voltage"], "current": analytical_data["current_linear"], "fit_type": "linear", - "voltage_bound": 0.0 + "voltage_bound": 0.0, }, ( analytical_funcs["linear"], @@ -184,7 +185,9 @@ def test_raises(self, kwargs, _error): "fit_type": "exp_plus_offset", }, ( - ffuncs.Linear(params=(0.0, analytical_funcs["exp_offset"].params.b)), + ffuncs.Linear( + params=(0.0, analytical_funcs["exp_offset"].params.b) + ), ISatExtras( fitted_func=analytical_funcs["exp_offset"], rsq=None, @@ -200,7 +203,9 @@ def test_raises(self, kwargs, _error): "voltage_bound": 30, }, ( - ffuncs.Linear(params=(0.0, analytical_funcs["exp_offset"].params.b)), + ffuncs.Linear( + params=(0.0, analytical_funcs["exp_offset"].params.b) + ), ISatExtras( fitted_func=analytical_funcs["exp_offset"], rsq=None, @@ -216,10 +221,12 @@ def test_raises(self, kwargs, _error): "fit_type": "exp_plus_linear", }, ( - ffuncs.Linear(params=( - analytical_funcs["exp_linear"].params.m, - analytical_funcs["exp_linear"].params.b - )), + ffuncs.Linear( + params=( + analytical_funcs["exp_linear"].params.m, + analytical_funcs["exp_linear"].params.b, + ) + ), ISatExtras( fitted_func=analytical_funcs["exp_linear"], rsq=None, @@ -238,7 +245,7 @@ def test_raises(self, kwargs, _error): ffuncs.Linear( params=( analytical_funcs["exp_linear"].params.m, - analytical_funcs["exp_linear"].params.b + analytical_funcs["exp_linear"].params.b, ) ), ISatExtras( From b107a6d0e78aa5abafa8b09d0fd9a823d663889b Mon Sep 17 00:00:00 2001 From: Erik Date: Tue, 17 May 2022 18:32:33 -0700 Subject: [PATCH 240/521] appease grumpy linters --- .../analysis/swept_langmuir/ion_saturation_current.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/plasmapy/analysis/swept_langmuir/ion_saturation_current.py b/plasmapy/analysis/swept_langmuir/ion_saturation_current.py index 0445e3ce25..18599f46a4 100644 --- a/plasmapy/analysis/swept_langmuir/ion_saturation_current.py +++ b/plasmapy/analysis/swept_langmuir/ion_saturation_current.py @@ -7,7 +7,7 @@ import numbers import numpy as np -from typing import Tuple, NamedTuple, Union +from typing import Tuple, NamedTuple, Optional, Union from plasmapy.analysis import fit_functions as ffuncs from plasmapy.analysis.swept_langmuir.helpers import check_sweep @@ -21,19 +21,19 @@ class ISatExtras(NamedTuple): `find_ion_saturation_current`. """ - rsq: Union[float, None] + rsq: Optional[float] """ Alias for field number 0, the r-squared value of the ion-saturation curve fit. """ - fitted_func: Union[ffuncs.AbstractFitFunction, None] + fitted_func: Optional[ffuncs.AbstractFitFunction] """ Alias for field number 1, the :term:`fit-function` fitted during the ion-saturation curve fit. """ - fitted_indices: Union[slice, None] + fitted_indices: Optional[slice] """ Alias for field number 2, the indices used in the ion-saturation curve fit. From 067579259c6a8a3344363b7da824e5d5db09c5dd Mon Sep 17 00:00:00 2001 From: Erik Date: Tue, 17 May 2022 18:33:41 -0700 Subject: [PATCH 241/521] remove unused import --- plasmapy/analysis/swept_langmuir/ion_saturation_current.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plasmapy/analysis/swept_langmuir/ion_saturation_current.py b/plasmapy/analysis/swept_langmuir/ion_saturation_current.py index 18599f46a4..624a7ab28d 100644 --- a/plasmapy/analysis/swept_langmuir/ion_saturation_current.py +++ b/plasmapy/analysis/swept_langmuir/ion_saturation_current.py @@ -7,7 +7,7 @@ import numbers import numpy as np -from typing import Tuple, NamedTuple, Optional, Union +from typing import Tuple, NamedTuple, Optional from plasmapy.analysis import fit_functions as ffuncs from plasmapy.analysis.swept_langmuir.helpers import check_sweep From 91391415dff7d5fe17cd26a4f6d064f72ee91615 Mon Sep 17 00:00:00 2001 From: Erik Date: Tue, 17 May 2022 18:34:08 -0700 Subject: [PATCH 242/521] organize imports --- plasmapy/analysis/swept_langmuir/ion_saturation_current.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plasmapy/analysis/swept_langmuir/ion_saturation_current.py b/plasmapy/analysis/swept_langmuir/ion_saturation_current.py index 624a7ab28d..bf76ac13d6 100644 --- a/plasmapy/analysis/swept_langmuir/ion_saturation_current.py +++ b/plasmapy/analysis/swept_langmuir/ion_saturation_current.py @@ -7,7 +7,7 @@ import numbers import numpy as np -from typing import Tuple, NamedTuple, Optional +from typing import NamedTuple, Optional, Tuple from plasmapy.analysis import fit_functions as ffuncs from plasmapy.analysis.swept_langmuir.helpers import check_sweep From 3cb003f0459edaae05f9a2c6fb02dd84cbcc5abe Mon Sep 17 00:00:00 2001 From: Erik Date: Wed, 18 May 2022 13:19:13 -0700 Subject: [PATCH 243/521] copied pace data to langmuir test dir --- .../analysis/swept_langmuir/tests/Pace2015.npy | Bin 0 -> 38480 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 plasmapy/analysis/swept_langmuir/tests/Pace2015.npy diff --git a/plasmapy/analysis/swept_langmuir/tests/Pace2015.npy b/plasmapy/analysis/swept_langmuir/tests/Pace2015.npy new file mode 100644 index 0000000000000000000000000000000000000000..52797cfcf5048f25b7946983dc43683b8fa68490 GIT binary patch literal 38480 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 literal 0 HcmV?d00001 From 73c045e36f124afa8473908a22629a173f1390ff Mon Sep 17 00:00:00 2001 From: Erik Date: Wed, 18 May 2022 13:19:24 -0700 Subject: [PATCH 244/521] added test on pace data --- .../tests/test_ion_saturation_current.py | 21 ++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/plasmapy/analysis/swept_langmuir/tests/test_ion_saturation_current.py b/plasmapy/analysis/swept_langmuir/tests/test_ion_saturation_current.py index 241be0eb08..448fd8f3ed 100644 --- a/plasmapy/analysis/swept_langmuir/tests/test_ion_saturation_current.py +++ b/plasmapy/analysis/swept_langmuir/tests/test_ion_saturation_current.py @@ -6,6 +6,8 @@ import numpy as np import pytest +from pathlib import Path + from plasmapy.analysis import fit_functions as ffuncs from plasmapy.analysis.swept_langmuir.ion_saturation_current import ( find_ion_saturation_current, @@ -271,6 +273,19 @@ def test_analytical_fits(self, kwargs, expected): assert np.isclose(extras.rsq, 1.0) assert extras.fitted_indices == expected[1].fitted_indices - @pytest.mark.skip - def test_pace_data(self): - ... + def test_on_pace_data(self): + filepath = (Path.cwd() / "Pace2015.npy").resolve() + voltage, current = np.load(filepath) + + isort = np.argsort(voltage) + voltage = voltage[isort] + current = current[isort] + + isat, extras = find_ion_saturation_current( + voltage, current, fit_type="exp_plus_linear", current_bound=3.6 + ) + + assert np.isclose(isat.params.m, 3.81079e-6) + assert np.isclose(isat.params.b, 0.000110284) + assert np.isclose(extras.rsq, 0.982, atol=0.001) + assert np.isclose(np.min(isat(voltage)), -0.00014275) From 6ba601ba6f87239d895200fc05115654f7847224 Mon Sep 17 00:00:00 2001 From: Erik Date: Wed, 18 May 2022 13:20:48 -0700 Subject: [PATCH 245/521] add docstrings to tests --- .../swept_langmuir/tests/test_ion_saturation_current.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/plasmapy/analysis/swept_langmuir/tests/test_ion_saturation_current.py b/plasmapy/analysis/swept_langmuir/tests/test_ion_saturation_current.py index 448fd8f3ed..11cbc4d7a3 100644 --- a/plasmapy/analysis/swept_langmuir/tests/test_ion_saturation_current.py +++ b/plasmapy/analysis/swept_langmuir/tests/test_ion_saturation_current.py @@ -260,6 +260,7 @@ def test_raises(self, kwargs, _error): ], ) def test_analytical_fits(self, kwargs, expected): + """Test functionality on analytical traces.""" isat, extras = find_ion_saturation_current(**kwargs) # assertions on isat @@ -274,6 +275,11 @@ def test_analytical_fits(self, kwargs, expected): assert extras.fitted_indices == expected[1].fitted_indices def test_on_pace_data(self): + """ + Test functionality on D. Pace data. + + Data was obtained from: https://davidpace.com/example-of-langmuir-probe-analysis/ + """ filepath = (Path.cwd() / "Pace2015.npy").resolve() voltage, current = np.load(filepath) From a190cb080cfec9daf09316e5a44545a4486edb68 Mon Sep 17 00:00:00 2001 From: Erik Date: Wed, 18 May 2022 13:35:55 -0700 Subject: [PATCH 246/521] correct path to pace data --- .../swept_langmuir/tests/test_ion_saturation_current.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plasmapy/analysis/swept_langmuir/tests/test_ion_saturation_current.py b/plasmapy/analysis/swept_langmuir/tests/test_ion_saturation_current.py index 11cbc4d7a3..628bef9045 100644 --- a/plasmapy/analysis/swept_langmuir/tests/test_ion_saturation_current.py +++ b/plasmapy/analysis/swept_langmuir/tests/test_ion_saturation_current.py @@ -280,7 +280,7 @@ def test_on_pace_data(self): Data was obtained from: https://davidpace.com/example-of-langmuir-probe-analysis/ """ - filepath = (Path.cwd() / "Pace2015.npy").resolve() + filepath = (Path(__file__).parent / "Pace2015.npy").resolve() voltage, current = np.load(filepath) isort = np.argsort(voltage) From 6bd03f756ab7868d8bba66eb7082d42de33124f7 Mon Sep 17 00:00:00 2001 From: Erik Date: Wed, 18 May 2022 13:42:12 -0700 Subject: [PATCH 247/521] add change log --- changelog/1469.feature.rst | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 changelog/1469.feature.rst diff --git a/changelog/1469.feature.rst b/changelog/1469.feature.rst new file mode 100644 index 0000000000..be6ebbfb10 --- /dev/null +++ b/changelog/1469.feature.rst @@ -0,0 +1,4 @@ +Added +`~plamsapy.analysis.swept_langmuir.ion_saturation_current.find_ion_saturation_current` +to the `~plasmapy.analysis.swept_langmuir` module to fit and return the +ion-saturation current of a swept Langmuir probe trace. From 63696e332987474a7af26690b93a9121f3fd8bfe Mon Sep 17 00:00:00 2001 From: Erik Date: Wed, 18 May 2022 16:24:07 -0700 Subject: [PATCH 248/521] define the VFExtras namedtuple --- .../swept_langmuir/floating_potential.py | 39 ++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/plasmapy/analysis/swept_langmuir/floating_potential.py b/plasmapy/analysis/swept_langmuir/floating_potential.py index f7e4cd927c..785656a03f 100644 --- a/plasmapy/analysis/swept_langmuir/floating_potential.py +++ b/plasmapy/analysis/swept_langmuir/floating_potential.py @@ -6,7 +6,7 @@ import numpy as np from collections import namedtuple -from typing import Union +from typing import List, NamedTuple, Optional, Union from warnings import warn from plasmapy.analysis import fit_functions as ffuncs @@ -19,6 +19,43 @@ ) +class VFExtras(NamedTuple): + """ + Create a `tuple` containing the extra parameters calculated by + `find_floating_potential`. + """ + vf_err: Optional[float] + """ + Alias for field number 0, the error in the calculated floating + potential from the floating potential curve fit. + """ + + rsq: Optional[float] + """ + Alias for field number 1, the r-squared value of the ion-saturation + curve fit. + """ + + fitted_func: Optional[float] + """ + Alias for field number 2, the :term:`fit-function` fitted during + the floating potential curve fit. + """ + + islands: Optional[List[slice]] + """ + Alias for field number 3, a list of `slice` objects representing + the indices of the identified crossing-islands discovered during + the floating potential curve fit. + """ + + fitted_indices: Optional[slice] + """ + Alias for field number 4, the indices used in the floating potential + curve fit. + """ + + def find_floating_potential( voltage: np.ndarray, current: np.ndarray, From c4de72bb64a085e1846edac35067b80a42d8fb2e Mon Sep 17 00:00:00 2001 From: Erik Date: Wed, 18 May 2022 16:24:46 -0700 Subject: [PATCH 249/521] incorporate the return pattern of (vf, extras) --- .../swept_langmuir/floating_potential.py | 31 ++++++++----------- 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/plasmapy/analysis/swept_langmuir/floating_potential.py b/plasmapy/analysis/swept_langmuir/floating_potential.py index 785656a03f..4e2c8a9995 100644 --- a/plasmapy/analysis/swept_langmuir/floating_potential.py +++ b/plasmapy/analysis/swept_langmuir/floating_potential.py @@ -13,11 +13,6 @@ from plasmapy.analysis.swept_langmuir.helpers import check_sweep from plasmapy.utils.exceptions import PlasmaPyWarning -FloatingPotentialResults = namedtuple( - "FloatingPotentialResults", - ("vf", "vf_err", "rsq", "func", "islands", "indices"), -) - class VFExtras(NamedTuple): """ @@ -178,8 +173,8 @@ def find_floating_potential( ``fit_type="linear"`` and `scipy.optimize.curve_fit` for ``fit_type="exponential"``. """ - rtn = FloatingPotentialResults( - vf=np.nan, vf_err=np.nan, rsq=None, func=None, islands=None, indices=None + rtn_extras = VFExtras( + vf_err=None, rsq=None, fitted_func=None, islands=None, fitted_indices=None )._asdict() _settings = { @@ -189,7 +184,7 @@ def find_floating_potential( try: min_point_factor = _settings[fit_type]["min_point_factor"] fit_func = _settings[fit_type]["func"]() - rtn["func"] = fit_func + rtn_extras["fitted_func"] = fit_func except KeyError: raise ValueError( f"Requested fit '{fit_type}' is not a valid option. Valid options " @@ -253,7 +248,7 @@ def find_floating_potential( n_islands = threshold_indices.size + 1 if np.isinf(min_points) or n_islands == 1: - rtn["islands"] = [slice(cp_candidates[0], cp_candidates[-1] + 1)] + rtn_extras["islands"] = [slice(cp_candidates[0], cp_candidates[-1] + 1)] else: # There are multiple crossing points isl_start = np.concatenate( @@ -262,13 +257,13 @@ def find_floating_potential( isl_stop = np.concatenate( (cp_candidates[threshold_indices] + 1, [cp_candidates[-1] + 1]) ) - rtn["islands"] = [] + rtn_extras["islands"] = [] for start, stop in zip(isl_start, isl_stop): - rtn["islands"].append(slice(start, stop)) + rtn_extras["islands"].append(slice(start, stop)) # do islands fall within the min_points window? isl_window = ( - np.abs(np.r_[rtn["islands"][-1]][-1] - np.r_[rtn["islands"][0]][0]) + 1 + np.abs(np.r_[rtn_extras["islands"][-1]][-1] - np.r_[rtn_extras["islands"][0]][0]) + 1 ) if isl_window > min_points: warn( @@ -278,7 +273,7 @@ def find_floating_potential( PlasmaPyWarning, ) - return FloatingPotentialResults(**rtn) + return None, VFExtras(**rtn_extras) # Construct crossing-island (pad if needed) if np.isinf(min_points): @@ -322,14 +317,14 @@ def find_floating_potential( ) # Perform Linear Regression Fit - volt_sub = voltage[istart : istop + 1] - curr_sub = current[istart : istop + 1] + volt_sub = voltage[istart: istop + 1] + curr_sub = current[istart: istop + 1] fit_func.curve_fit(volt_sub, curr_sub) - rtn["vf"], rtn["vf_err"] = fit_func.root_solve() - rtn.update({"rsq": fit_func.rsq, "indices": slice(istart, istop + 1)}) + vf, rtn_extras["vf_err"] = fit_func.root_solve() + rtn_extras.update({"rsq": fit_func.rsq, "fitted_indices": slice(istart, istop + 1)}) - return FloatingPotentialResults(**rtn) + return vf, VFExtras(**rtn_extras) find_vf_ = find_floating_potential From 06dd3a3c990115782afa215cd086160fb626ca76 Mon Sep 17 00:00:00 2001 From: Erik Date: Wed, 18 May 2022 16:26:09 -0700 Subject: [PATCH 250/521] use explicit intersphinx link --- plasmapy/analysis/swept_langmuir/ion_saturation_current.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/plasmapy/analysis/swept_langmuir/ion_saturation_current.py b/plasmapy/analysis/swept_langmuir/ion_saturation_current.py index bf76ac13d6..079d28820c 100644 --- a/plasmapy/analysis/swept_langmuir/ion_saturation_current.py +++ b/plasmapy/analysis/swept_langmuir/ion_saturation_current.py @@ -234,4 +234,7 @@ def find_ion_saturation_current( find_isat_ = find_ion_saturation_current -"""Alias to :func:`find_ion_saturation_current`.""" +""" +Alias to +:func:`~plasmapy.analysis.swept_langmuir.ion_saturation_current.find_ion_saturation_current`. +""" From 1b2449c066e67bb06872a3fa184cf0305257bb11 Mon Sep 17 00:00:00 2001 From: Erik Date: Wed, 18 May 2022 17:15:43 -0700 Subject: [PATCH 251/521] updated tests for FloatingPotentialResults -> VFExtras --- .../tests/test_floating_potential.py | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py b/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py index f258b1636a..b8b94d26d2 100644 --- a/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py +++ b/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py @@ -13,7 +13,7 @@ from plasmapy.analysis.swept_langmuir.floating_potential import ( find_floating_potential, find_vf_, - FloatingPotentialResults, + VFExtras, ) from plasmapy.utils.exceptions import PlasmaPyWarning @@ -24,18 +24,17 @@ def test_floating_potential_namedtuple(): data. """ - assert issubclass(FloatingPotentialResults, tuple) - assert hasattr(FloatingPotentialResults, "_fields") - assert FloatingPotentialResults._fields == ( - "vf", + assert issubclass(VFExtras, tuple) + assert hasattr(VFExtras, "_fields") + assert VFExtras._fields == ( "vf_err", "rsq", - "func", + "fitted_func", "islands", - "indices", + "fitted_indices", ) - assert hasattr(FloatingPotentialResults, "_field_defaults") - assert FloatingPotentialResults._field_defaults == {} + assert hasattr(VFExtras, "_field_defaults") + assert VFExtras._field_defaults == {} class TestFindFloatingPotential: From b23843edaad5de2a74809f2921d47f4c76c528e7 Mon Sep 17 00:00:00 2001 From: Erik Date: Wed, 18 May 2022 17:17:06 -0700 Subject: [PATCH 252/521] rename import _sl -> sla --- .../swept_langmuir/tests/test_floating_potential.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py b/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py index b8b94d26d2..b518885f2d 100644 --- a/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py +++ b/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py @@ -9,7 +9,7 @@ from unittest import mock from plasmapy.analysis import fit_functions as ffuncs -from plasmapy.analysis import swept_langmuir as _sl +from plasmapy.analysis import swept_langmuir as sla from plasmapy.analysis.swept_langmuir.floating_potential import ( find_floating_potential, find_vf_, @@ -64,9 +64,9 @@ def test_call_of_check_sweep(self): varr = np.linspace(-20.0, 20.0, 100) carr = np.linspace(-20.0, 20.0, 100) - assert _sl.helpers.check_sweep is _sl.floating_potential.check_sweep + assert sla.helpers.check_sweep is sla.floating_potential.check_sweep - with mock.patch(_sl.floating_potential.__name__ + ".check_sweep") as mock_cs: + with mock.patch(sla.floating_potential.__name__ + ".check_sweep") as mock_cs: mock_cs.return_value = varr, carr find_floating_potential(voltage=varr, current=carr, fit_type="linear") From 6b8c24b65eb1b5a6462e5f500f8ee0810b830221 Mon Sep 17 00:00:00 2001 From: Erik Date: Wed, 18 May 2022 17:53:15 -0700 Subject: [PATCH 253/521] update tests for return patter (vf, extras) --- .../swept_langmuir/floating_potential.py | 4 +- .../tests/test_floating_potential.py | 94 ++++++++++--------- 2 files changed, 54 insertions(+), 44 deletions(-) diff --git a/plasmapy/analysis/swept_langmuir/floating_potential.py b/plasmapy/analysis/swept_langmuir/floating_potential.py index 4e2c8a9995..3cd5423d57 100644 --- a/plasmapy/analysis/swept_langmuir/floating_potential.py +++ b/plasmapy/analysis/swept_langmuir/floating_potential.py @@ -174,7 +174,7 @@ def find_floating_potential( ``fit_type="exponential"``. """ rtn_extras = VFExtras( - vf_err=None, rsq=None, fitted_func=None, islands=None, fitted_indices=None + vf_err=np.nan, rsq=None, fitted_func=None, islands=None, fitted_indices=None )._asdict() _settings = { @@ -273,7 +273,7 @@ def find_floating_potential( PlasmaPyWarning, ) - return None, VFExtras(**rtn_extras) + return np.nan, VFExtras(**rtn_extras) # Construct crossing-island (pad if needed) if np.isinf(min_points): diff --git a/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py b/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py index b518885f2d..6fad465354 100644 --- a/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py +++ b/plasmapy/analysis/swept_langmuir/tests/test_floating_potential.py @@ -43,9 +43,13 @@ class TestFindFloatingPotential: `~plasmapy.analysis.swept_langmuir.floating_potential.find_floating_potential`. """ - _null_result = FloatingPotentialResults( - vf=np.nan, vf_err=np.nan, rsq=None, func=None, islands=None, indices=None - )._asdict() + _null_result = { + **VFExtras( + vf_err=np.nan, rsq=None, fitted_func=None, islands=None, fitted_indices=None + )._asdict(), + "vf": np.nan, + } + _voltage = np.linspace(-10.0, 15, 70) _linear_current = np.linspace(-3.1, 4.1, 70) _linear_p_sine_current = _linear_current + 1.2 * np.sin(1.2 * _voltage) @@ -176,7 +180,7 @@ def test_raises(self, kwargs, _error): }, { **_null_result, - "func": ffuncs.Linear(), + "fitted_func": ffuncs.Linear(), "islands": [slice(27, 29), slice(36, 38), slice(39, 41)], }, PlasmaPyWarning, @@ -196,9 +200,9 @@ def test_raises(self, kwargs, _error): "vf": 0.6355491, "vf_err": 0.03306472, "rsq": 0.8446441, - "func": ffuncs.Linear(), + "fitted_func": ffuncs.Linear(), "islands": [slice(27, 41)], - "indices": slice(0, 70), + "fitted_indices": slice(0, 70), }, PlasmaPyWarning, ), @@ -207,15 +211,18 @@ def test_raises(self, kwargs, _error): def test_warnings(self, kwargs, expected, _warning): """Test scenarios that issue warnings.""" with pytest.warns(_warning): - results = find_floating_potential(**kwargs) - assert isinstance(results, FloatingPotentialResults) + vf, extras = find_floating_potential(**kwargs) + assert isinstance(extras, VFExtras) for key, val in expected.items(): - rtn_val = getattr(results, key) + if key == "vf": + rtn_val = vf + else: + rtn_val = getattr(extras, key) if val is None: assert rtn_val is None - elif key == "func" and val is not None: + elif key == "fitted_func" and val is not None: assert isinstance(rtn_val, val.__class__) elif np.isscalar(val): if np.isnan(val): @@ -248,16 +255,16 @@ def test_kwarg_min_points(self, min_points, fit_type, islands, indices): """ voltage = self._voltage current = self._linear_current if fit_type == "linear" else self._exp_current - results = find_floating_potential( + vf, extras = find_floating_potential( voltage, current, min_points=min_points, fit_type=fit_type, ) - assert isinstance(results, FloatingPotentialResults) + assert isinstance(extras, VFExtras) - assert results.islands == islands - assert results.indices == indices + assert extras.islands == islands + assert extras.fitted_indices == indices @pytest.mark.parametrize( "kwargs, expected", @@ -275,9 +282,9 @@ def test_kwarg_min_points(self, min_points, fit_type, islands, indices): "vf": 0.7638889, "vf_err": 0.0, "rsq": 1.0, - "func": ffuncs.Linear(), + "fitted_func": ffuncs.Linear(), "islands": [slice(29, 31)], - "indices": slice(22, 38), + "fitted_indices": slice(22, 38), }, ), # @@ -294,9 +301,9 @@ def test_kwarg_min_points(self, min_points, fit_type, islands, indices): "vf": -8.8243208, "vf_err": 032.9961, "rsq": 0.005084178, - "func": ffuncs.Linear(), + "fitted_func": ffuncs.Linear(), "islands": [slice(27, 29), slice(36, 38), slice(39, 41)], - "indices": slice(26, 42), + "fitted_indices": slice(26, 42), }, ), # @@ -313,9 +320,9 @@ def test_kwarg_min_points(self, min_points, fit_type, islands, indices): "vf": -7.91666667, "vf_err": 3.153378e-8, "rsq": 1.0, - "func": ffuncs.Linear(), + "fitted_func": ffuncs.Linear(), "islands": [slice(5, 7)], - "indices": slice(0, 16), + "fitted_indices": slice(0, 16), }, ), # @@ -332,9 +339,9 @@ def test_kwarg_min_points(self, min_points, fit_type, islands, indices): "vf": 14.6527778, "vf_err": 0.0, "rsq": 1.0, - "func": ffuncs.Linear(), + "fitted_func": ffuncs.Linear(), "islands": [slice(68, 70)], - "indices": slice(54, 70), + "fitted_indices": slice(54, 70), }, ), ], @@ -343,15 +350,18 @@ def test_island_finding(self, kwargs, expected): """ Test scenarios related to the identification of crossing-point islands. """ - results = find_floating_potential(**kwargs) - assert isinstance(results, FloatingPotentialResults) + vf, extras = find_floating_potential(**kwargs) + assert isinstance(extras, VFExtras) for key, val in expected.items(): - rtn_val = getattr(results, key) + if key == "vf": + rtn_val = vf + else: + rtn_val = getattr(extras, key) if val is None: assert rtn_val is None - elif key == "func" and val is not None: + elif key == "fitted_func" and val is not None: assert isinstance(rtn_val, val.__class__) elif np.isscalar(val): if np.isnan(val): @@ -367,20 +377,20 @@ def test_perfect_linear(self, m, b): voltage = self._voltage current = m * voltage + b - results = find_floating_potential( + vf, extras = find_floating_potential( voltage=voltage, current=current, fit_type="linear", min_points=0.8, ) - assert isinstance(results, FloatingPotentialResults) - assert np.isclose(results.vf, -b / m) - assert np.isclose(results.vf_err, 0.0) - assert np.isclose(results.rsq, 1.0) - assert isinstance(results.func, ffuncs.Linear) - assert np.allclose(results.func.params, (m, b)) - assert np.allclose(results.func.param_errors, (0.0, 0.0), atol=2e-8) + assert isinstance(extras, VFExtras) + assert np.isclose(vf, -b / m) + assert np.isclose(extras.vf_err, 0.0) + assert np.isclose(extras.rsq, 1.0) + assert isinstance(extras.fitted_func, ffuncs.Linear) + assert np.allclose(extras.fitted_func.params, (m, b)) + assert np.allclose(extras.fitted_func.param_errors, (0.0, 0.0), atol=2e-8) @pytest.mark.parametrize( "a, alpha, b", @@ -391,17 +401,17 @@ def test_perfect_exponential(self, a, alpha, b): voltage = self._voltage current = a * np.exp(alpha * voltage) + b - results = find_floating_potential( + vf, extras = find_floating_potential( voltage=voltage, current=current, fit_type="exponential", min_points=0.8, ) - assert isinstance(results, FloatingPotentialResults) - assert np.isclose(results.vf, np.log(-b / a) / alpha) - assert np.isclose(results.vf_err, 0.0, 1e-7) - assert np.isclose(results.rsq, 1.0) - assert isinstance(results.func, ffuncs.ExponentialPlusOffset) - assert np.allclose(results.func.params, (a, alpha, b)) - assert np.allclose(results.func.param_errors, (0.0, 0.0, 0.0), atol=2e-8) + assert isinstance(extras, VFExtras) + assert np.isclose(vf, np.log(-b / a) / alpha) + assert np.isclose(extras.vf_err, 0.0, 1e-7) + assert np.isclose(extras.rsq, 1.0) + assert isinstance(extras.fitted_func, ffuncs.ExponentialPlusOffset) + assert np.allclose(extras.fitted_func.params, (a, alpha, b)) + assert np.allclose(extras.fitted_func.param_errors, (0.0, 0.0, 0.0), atol=2e-8) From c80e3d4c524fdf5bace17d0e29bcc65a5704847f Mon Sep 17 00:00:00 2001 From: Erik Date: Wed, 18 May 2022 19:29:52 -0700 Subject: [PATCH 254/521] update __all__ and __aliases__ --- plasmapy/analysis/swept_langmuir/floating_potential.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/plasmapy/analysis/swept_langmuir/floating_potential.py b/plasmapy/analysis/swept_langmuir/floating_potential.py index 3cd5423d57..64e0018ff4 100644 --- a/plasmapy/analysis/swept_langmuir/floating_potential.py +++ b/plasmapy/analysis/swept_langmuir/floating_potential.py @@ -1,11 +1,10 @@ """Functionality for determining the floating potential of a Langmuir sweep.""" -__all__ = ["find_floating_potential", "find_vf_"] +__all__ = ["find_floating_potential", "VFExtras"] __aliases__ = ["find_vf_"] import numbers import numpy as np -from collections import namedtuple from typing import List, NamedTuple, Optional, Union from warnings import warn @@ -13,6 +12,8 @@ from plasmapy.analysis.swept_langmuir.helpers import check_sweep from plasmapy.utils.exceptions import PlasmaPyWarning +__all__ += __aliases__ + class VFExtras(NamedTuple): """ From 81dcff6cc93f3aa81502edea47e0c22ecbc3330e Mon Sep 17 00:00:00 2001 From: Erik Date: Wed, 18 May 2022 19:30:25 -0700 Subject: [PATCH 255/521] update the vf notebook to work with the (vf, extras) return pattern --- .../find_floating_potential.ipynb | 254 +++++++++++++----- 1 file changed, 193 insertions(+), 61 deletions(-) diff --git a/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb b/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb index 88c1d2f6e4..ef58d632a3 100644 --- a/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb +++ b/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb @@ -4,16 +4,18 @@ "cell_type": "markdown", "metadata": {}, "source": [ + "[find_floating_potential()]: ../../../api/plasmapy.analysis.swept_langmuir.floating_potential.find_floating_potential.rst#find-floating-potential\n", + "\n", "# Swept Langmuir Analysis: Floating Potential\n", "\n", - "This notebook covers the use of the [find_floating_potential()](../../../api/plasmapy.analysis.swept_langmuir.floating_potential.find_floating_potential.rst#find-floating-potential) function and how it is used to determine the floating potential from a swept Langmuir trace.\n", + "This notebook covers the use of the [find_floating_potential()] function and how it is used to determine the floating potential from a swept Langmuir trace.\n", "\n", "The floating potential, $V_f$, is defined as the probe bias voltage at which there is no net collected current, $I=0$. This occurs because the floating potential slows the collected electrons and accelerates the collected ions to a point where the electron- and ion-currents balance each other out." ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ @@ -27,7 +29,9 @@ "\n", "from plasmapy.analysis import swept_langmuir as sla\n", "\n", - "plt.rcParams[\"figure.figsize\"] = [10.5, 0.56 * 10.5]" + "plt.rcParams[\"figure.figsize\"] = [10.5, 0.56 * 10.5]\n", + "\n", + "np.set_printoptions(precision=4, threshold=16)" ] }, { @@ -107,7 +111,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 2, "metadata": {}, "outputs": [], "source": [ @@ -132,82 +136,168 @@ "cell_type": "markdown", "metadata": {}, "source": [ + "[find_floating_potential()]: ../../../api/plasmapy.analysis.swept_langmuir.floating_potential.find_floating_potential.rst#find-floating-potential\n", + "[VFExtras]: ../../../api/plasmapy.analysis.swept_langmuir.floating_potential.VFExtras.rst#vfextras\n", + "\n", "### Interpreting results\n", "\n", - "The `find_floating_potential()` function returns a six element named tuple, where...\n", + "The [find_floating_potential()] function returns a 2 element named tuple, where the first element is the calculated floating potential $V_f$ and the second element is a named tuple [VFExtras] containing additional parameters resulting from the calculation.\n", "\n", - "- `results[0]` = `results.vf` = the determined floating potential (same units as the pass `voltage` array)\n" + "- `results[0]` is the determined floating potential (same units as the pass `voltage` array)" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 3, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "-5.665729878703537" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ - "(results[0], results.vf)" + "vf = results[0]\n", + "vf" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "- `results[1]` = `results.vf_err` = the associated uncertainty in the $V_F$ calculation (same units as `results.vf`)" + "[VFExtras]: ../../../api/plasmapy.analysis.swept_langmuir.floating_potential.VFExtras.rst#vfextras\n", + "\n", + "- `results[1]` is an instance of [VFExtras] and contains additioanl information from the calculation" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 4, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "VFExtras(vf_err=0.45174046362475595, rsq=0.9564766142728284, fitted_func=f(x) = a exp(alpha x) + b , islands=[slice(192, 195, None), slice(201, 210, None)], fitted_indices=slice(155, 247, None))" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ - "(results[1], results.vf_err)" + "extras = results[1]\n", + "extras" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "- `results[2]` = `results.rsq` = the coefficient of determination (r-squared) value of the fit" + "- `extras[0]` = `extras.vf_err` = the associated uncertainty in the $V_F$ calculation (same units as `vf`)" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 5, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "(0.45174046362475595, 0.45174046362475595)" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ - "(results[2], results.rsq)" + "(extras[0], extras.vf_err)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "- `results[3]` = `results.func` = the resulting fitted function\n", - "\n", - " - `results.func` is a callable representation of the fitted function `I = results.func(V)`.\n", - " - `resulst.func` is an instance of a sub-class of `AbstractFitFunction`. ([FitFuction classes](../../../api_static/plasmapy.analysis.fit_functions.rst))\n", - " - Since `results.func` is a class instance, there are many other attributes available. For example,\n", - " - `results.func.params` is a named tuple of the fitted parameters\n", - " - `results.func.param_errors` is a named tuple of the fitted parameter errors\n", - " - `results.func.root_solve()` finds the roots of the fitted function. This is how $V_f$ is calculated." + "- `extras[1]` = `extras.rsq` = the coefficient of determination (r-squared) value of the fit" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(0.9564766142728284, 0.9564766142728284)" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "(extras[1], extras.rsq)" + ] + }, + { + "cell_type": "markdown", "metadata": {}, - "outputs": [], + "source": [ + "[FitFunction]: ../../../api_static/plasmapy.analysis.fit_functions.rst\n", + "\n", + "- `extras[2]` = `extras.fitted_func` = the resulting fitted function\n", + "\n", + " - `extras.fitted_func` is a callable representation of the fitted function `I = results.func(V)`.\n", + " - `extras.fitted_func` is an instance of a sub-class of `AbstractFitFunction`. ([FitFunction classes][FitFunction])\n", + " - Since `extras.fitted_func` is a class instance, there are many other attributes available. For example,\n", + " - `extras.fitted_func.params` is a named tuple of the fitted parameters\n", + " - `extras.fitted_func.param_errors` is a named tuple of the fitted parameter errors\n", + " - `extras.fitted_func.root_solve()` finds the roots of the fitted function. This is how $V_f$ is calculated." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(f(x) = a exp(alpha x) + b ,\n", + " f(x) = a exp(alpha x) + b ,\n", + " FitParamTuple(a=0.010275377527636112, alpha=0.33827816441206754, b=-0.001511583532931966),\n", + " 0.010275377527636112,\n", + " FitParamTuple(a=0.0003144059149671168, alpha=0.02163130023989389, b=0.0001299928251489394),\n", + " 0.0003144059149671168,\n", + " 0.0)" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "(\n", - " results[3],\n", - " results.func,\n", - " results.func.params,\n", - " results.func.params.a,\n", - " results.func.param_errors,\n", - " results.func.param_errors.a,\n", - " results.func(results.vf),\n", + " extras[2],\n", + " extras.fitted_func,\n", + " extras.fitted_func.params,\n", + " extras.fitted_func.params.a,\n", + " extras.fitted_func.param_errors,\n", + " extras.fitted_func.param_errors.a,\n", + " extras.fitted_func(vf),\n", ")" ] }, @@ -215,19 +305,32 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "- `results[4]` = `results.islands` = a list of slice objects representing all the identified crossing-islands" + "- `extras[3]` = `extras.islands` = a list of slice objects representing all the identified crossing-islands" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 8, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "([slice(192, 195, None), slice(201, 210, None)],\n", + " [slice(192, 195, None), slice(201, 210, None)],\n", + " array([-7.496 , -7.2238, -7.1512]))" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "(\n", - " results[4],\n", - " results.islands,\n", - " voltage[results.islands[0]],\n", + " extras[3],\n", + " extras.islands,\n", + " voltage[extras.islands[0]],\n", ")" ] }, @@ -235,19 +338,32 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "- `results[5]` = `results.indices` = a slice object representing the indices used in the fit" + "- `extras[4]` = `extras.fitted_indices` = a slice object representing the indices used in the fit" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 9, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "(slice(155, 247, None),\n", + " slice(155, 247, None),\n", + " array([-11.6594, -11.6488, -11.5358, ..., -1.251 , -0.9812, -0.8504]))" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "(\n", - " results[5],\n", - " results.indices,\n", - " voltage[results.indices],\n", + " extras[4],\n", + " extras.fitted_indices,\n", + " voltage[extras.fitted_indices],\n", ")" ] }, @@ -260,13 +376,26 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 10, "metadata": { "nbsphinx-thumbnail": { "tooltip": "Floating Potential" } }, - "outputs": [], + "outputs": [ + { + "data": { + "image/png": "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Y2MLWnS6d+/O9u3bWbVqFQMH2nYsuOaaaxg0aBAtWrSgcePGuLm5FemmPxk4+Pv706VLF7y9vXn33XcZNWoUderU4bvvvmP48OEV8HQvDO3atSsRbD722GM8+uijBAUFVVOtzt2UKVOYPHkyvXr1wsHBgeDgYIKDS/979eOPP1KvXj369et3XtfMyMjgxx9/5MUXX8TLy4u+ffsyfPhwZs6cWeY5s2fPxs/PjyuvvPKcrzty5EgSExOLtNwmJyfz22+/MWbMmHMuVyl1EbFk2WafO3lBbhL8+zh4N4c2TxRkuaK5NwaYdHUof0666txiFWNMtb8AR+AA0BRwAbYCbYrluQ/42P5+NDDH/t4T6AvcC7xf7JxVQLdSrldqWad7de3a1ZRm165dpaYrm/79+5vPPvusuqtRpWrTd+LVV181N9xwQ8HnhQsXmqCgIJORkVHmOUOHDjW+vr6lvoYOHVqh9evfv78JCAgw/v7+pnfv3mblypVl5rVYLMbZ2dm8+uqr5pJLLjHBwcHm/vvvN5mZmaXmv/zyy82UKVPOWIcpU6acNt+///5r3N3di6S98cYb5tprry01f0pKimnevLk5cuSImTJlirn11luLHD+be7777rvNXXfdVfD5zTffNO3btzepqann9Pr888/N559/fs7np6ammvj4+DM+U6VUDZBvNSZ5jzEpe4xJO2TMH1ca872LMTGLjUmPLHjt3POvafzkL2bx1pjTFgeEmzJiqJrSstkDiDDGHDTG5AKzgRHF8owAvra/nwdcKSJijMkwxqwDss/ieqWWde7VV6p2KtyyabVaeeqpp3j55Zfx8PAAIC4ujn79+jF06NCCc3755ZciY3QLv3755ZcKrd9rr73GwYMHiYmJYcKECQwbNowDBw6UmjcuLo68vDzmzZvH2rVr2bJlC5s3b+all14qkTcqKorVq1dz++23l1rWtddei5+fH35+fkybNo1p06YVfL722muL5E1PT8fHx6dImq+vL2lpaaWW/dxzz3HXXXcREhJy3vd8++23M2/ePLKzbf/8zZkzR1s1lVLlkxUH+bm27vODX0Lccmj7NPiemug8f2s8Y2cfA2DKol3nvBZ4TQk2g4EjhT5H29NKzWOMsQApgH85yv7S3oX+XKGAslxlicgEEQkXkfD4+PizuR+laoW2bduyf/9+8vLymDFjBq6u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xJaYEORnt/HSyK70bFGfBz78nR+2+J6gfLKoMy2bp4onF29kU2K5Se/lrN2TRoHLXSott9DFQx/9wZzf9lR4boeYcJ4Y0LHSa7Rt2xa73c6YMWMYOXIk5557LpGRRzZLuvjii1m2bBlnn30233//PS1btuSHH36gY8eOfP/991x88cUAvPzyyyxcuJDvv/+e6Oho7r77bu644w7mzJlDQkIC/fv3Z+bMmfTt25dvvvmGa665hr/++ouiSVUzZsxgyZIltGjRghtuuIG7776b999/v9L6F7n66qt59dVXyc7OJiQkhB49ejBhwgTq1avHSy+9xLBhw9i1axd9+/blkUceYdu2baXKb9iwIZ9++mnx/V155ZX06NGDbt26VbkOSimlVHXLzneSmlNIXGTp2eeBDjtvjunOiP/+wu3vr2b2refSJT6idipZDbRls5aUDTQrSz8W4eHhrFixAhHh1ltvJTo6moEDB5KUlARYweb3338PwPLlyxk/fnzx95LB5uuvv86UKVOIi4sjICCAiRMn8tFHH+F0Onn//ffp168f/fr1w2azcfnll9O9e3c+//zIiIjrr7+eM888k5CQECZNmsS8efOOarelmJgYjDGkpaUBMHr0aBo0aICfnx/3338/+fn5bN682ef5/fv3p1WrVogIF198MX369CluDVVKKaVqS4JnPc2ywSZAeKCD927qQVRoADe+8xvbDmad6OpVG23ZrGZVaXEEuOCZb4t/yEqKjQjig7+fV231OeOMM3j33XcB+Ouvvxg9ejT33nsvc+bM4eKLL+aBBx5g//79uFwuhg8fzpNPPsmuXbtIT0+nS5cuAOzevZshQ4aUWnfSbreTlJTE7t27+fDDD1m8eHHxscLCQi655JLi7/HxR1amatasGYWFhSQnJ9OoUdXW0k9ISEBEiIiIAOC5557j7bffJjExEREhIyOD5ORkn+d/8cUXPPnkk2zZsgW3201OTg6dOnWq0rWVUkqpmpKQ6jvYBGgYFsjMm8/hmtd+5oa3f2X+/51Pk3on3xqc2rJZSx68oh1BDnuptCCHnQevaFdj12zfvj1jx45lw4YNALRu3Zrg4GBefvllLrroIsLDw2ncuDFvvPEGF154YXFwGR8fzxdffEFaWlrxKy8vj9jYWOLj47n++utLHcvOzmbcuHHF192798gGT3v27MHhcBAVFVXlei9YsIBu3boREhLC8uXLmTZtGvPmzSM1NZW0tDTq1auHtQoW5XZxys/P55prruGBBx4gKSmJtLQ0+vXrV5xfKaWUqi37UnMAiicIedOsQQjv3tiDzDwng1/5kfOe/oYW4z7jgme+rdZ5HjVJg81aMrhrLE9f3YnYiCAEq0Xz6as7Vets9L/++ovnn3+effv2AVbQN2fOHM4999ziPBdffDGvvPJKcZd57969S30HuP3223n00UfZvXs3AIcOHeKTT6ylSUePHs3ixYtZsmQJLpeLvLw8li1bVnxNgPfff59NmzaRk5PDhAkTGDp0KHZ76UC7rKLZ6E8++SRvvfUWU6dOBSAzMxM/Pz+io6NxOp089dRTZGQcGSPbqFEjdu3ahdttDUcoKCggPz+f6Oho/Pz8+OKLL1i6dOkxP1N1/FwuF0FBQaxfv77csVGjRjF27NgTX6ky+vXrR3R0NE2aNKFJkyYVju8tylP0ioiI4IEHHig+vnnzZq666iri4uLo3LlzqV6A45GSksKoUaNo3LgxHTt2ZN68eRXmr0o9tm3bRnR0NLfccovPcoYMGcLkyZPLpX/22We0bt0ap9N59Dej1GlqX1ou/nYb0aEVrxJzZmw9bji/GUmZ+exPz6uxicU1RYPNWjS4ayw/jvsbO5/pz4/j/latgSZAWFgYv/76Kz179iQkJIRzzz2XM888k+eff744z8UXX0xmZiYXXXSR1+9gzf4eOHAgffr0ISwsjHPPPZdff7W2mY+Pj+eTTz5h6tSpREdHEx8fz/Tp04uDPbDGbI4dO5bGjRuTl5fHv//9b591TkxMLF5ns0ePHqxfv55ly5bRp08fAK644gr69u1L27ZtadasGYGBgaW66YcNs1bHatCgAd26dSMsLIx///vfDB8+nMjISGbPns3AgQO9XludGHa7nfbt27Np06ZS6atWrWLx4sXF/7Gobc899xz79+9n//79rFmzxme+ojz79+9n69atBAUFMWTIEACcTicjR46kb9++7N69m3//+9/ceuutbN26tcJrT506tdLncP/99+Pv78+2bdt46623uO+++/jzzz+95q1qPe6///5KJ86NGjWKefPmlesdmDt3LsOHD8fPT0dnKVVV+1JziYkIxGbzulJjKQvXJpZLyy10MX2J7zkLdYVod2LVdO/e3axatapc+p9//skZZ5xRCzU6OfTu3ZvRo0dX2FJSl+mfb824/vrradmyJU8++WRxWu/evenduzcTJ048IXVITk72ueZsv379GDFiBGPGjPF63JdZs2bx7LPP8vvvvyMibNq0iUsvvbR4fDHAoEGD6N69O48//rjPcooCzUceecTr8ezsbJo2bcovv/xCmzZtALj11luJiYkp9UyLVKUeH330EYsXL6Zdu3bs2LGDt956y+u1c3NzadOmDR988AEXXHABAKmpqbRt25Zvv/32qMdDF7XIDh8+/KjOU9UvPz//qIY4qeM3+D8/EhJgZ9Yt51aat8W4z/AWsQmw85n+1V63oyUiq40x3b0d05ZNpdQJ17Fjx+I1XQEWL17M1q1beeihh3yec9VVVxEREeH1ddVVV1V7HSdOnEjz5s25/PLLq7x6wZw5cxg5cmS5scNl+WqBrKpt27bh5+dXHGgCdOrU6ajLLcqfkZHBlClTqtSqXNRyO2fOnOK0BQsW0LZtW514p9RR2peaS1yE7/GaJcVEeJ8Y5Cu9LtFgUyl1wp155pnF3egul4tx48YxZcoUgoOtf3STkpLo1asX/fsf+d/6p59+WmoiWsnXp59+Wq31e/LJJ/njjz/YvHkzY8eOZcSIEezYsaPCc/bs2cOKFSsYNWpUcVqbNm2Ijo7mpZdeorCwkG+++YYVK1aQk5NT7vxhw4YRHx9PfHw8L774Ii+++GLx96LhIUWys7MJCwsrlRYeHk5WlvelUSqrx+TJk7nhhhuIja3aUJ5Ro0bxySefkJeXB1hB9rXXXlulc5VSlrxCF8lZ+cT6mIleVm1MLK4uOrhG1aiSuwkpVaRjx45s3bqVwsJC3nnnHQICArjhhhuKj8+ZM4d77rmHoUOHVsv1evfuXbyGbFnnnntuuUljPXr0KP583XXX8dFHH7F06VJuv/12n9eYO3cu5513Hs2bNy9OczgczJ49mwcffJAXX3yRrl27MmTIEK/d9x9++GHx58q60UNCQsjMzCyVlpmZSWhoqNf8FdXjjz/+YNmyZaxYscLnvZV13nnnUb9+fT799FO6devG6tWrmTVrVpXPV0pVvMamN0XzOp798i/2p+cRHujHU4POrPb5HjVBg02l1AnXvHlzAgICWLt2LU888QRz5swpXmpr+fLlTJkyhbZt2xIYGFjcRX7llVf67M7u1asXX3zxhc/reftPT0VjNssSkUqXy5ozZw733XdfufQzzzyzVN0uu+yyUq2fx6Jo1ve2bdto3bo1AOvXr69wfLGveixfvpw9e/bQoUMHwGo1dblc9OrVq8LhA9deey1z5sxh69atXHrppTRs2PC47kmp082+4jU2q9aNDlbAObhrLD2nfs2FraNPikATNNhUStUCEaFDhw7cfvvt9OzZk969excf69WrFx06dOC7774rtZFARcFkdUpLS2PVqlVceOGF+Pn5MX/+fH766SeeffZZn+f8+uuv7N+/n8GDB5c7tmHDBlq3bo3b7eatt94iKSmJ6667rsI6+GrRLBISEsKAAQOYMmUKr7zyCuvXr+fzzz/nq6++8nmOr3q4XK5SLcj//ve/2bNnDy+++GKFdbj22muZPn06Gzdu5Omnn64wr1KqvKIF3avajV5Sq+hQth86eXYU0jGbSqlaceaZZ7JhwwamT59eKt3lciEipQLNE8npdDJp0iRatmxJixYt+O9//8vs2bNLTca5+uqree6554q/z549mwEDBpQbRwlW93rbtm1p1aoVy5YtY+HChV5bVK+++upya3YWva6++upy+V944QXy8vJo1aoVN910Ey+88EKpls2ydfRVj+DgYBo1alT8CgkJISAgoNJZyc2aNaNnz57k5OTQr1+/ih+qUqqcfak5+NmERmFV62EpqXXDULYfzDppNijRpY+qSJc+Oj3pn++J9+eff/Liiy/yxhtv1Oh1jqYbXdUcXfqo7tClj06se+auZfXuVFY8/LejPve9n3bxxKKN/PbIpTQMD6yB2h09XfpIKXXS+P333+ncuXNtV0MppWrUvtTcKk8OKqt1Q2sy4LaDJ0dXep0JNkWkr4hsFpFtIjLOy/EAEfnAc/xXEWle4th4T/pmEbmiRPr/ROSgiGwoU9ZEEUkQkXWel/YBldGxY8cTMpN88+bNdOnSpXinn5py++23M2nSpBorX1WfkSNHcscdd9R2NZRSqkbtS80htoprbJbVKtoKNk+WcZt1ItgUETvwH+BKoANwrYh0KJPtZiDVGNMaeBF41nNuB2Ak0BHoC7zqKQ/gXU+aNy8aY7p4Xp9X5/3UJc2bNycoKIjQ0FAaNWrE2LFjfa7FV9LGjRtLTdqo7Bpff/31MdVv2rRpXHLJJWRmZnL33XcfUxklTZw4EYfDUbzlZWhoKNOmTeP1118v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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], "source": [ "figwidth, figheight = plt.rcParams[\"figure.figsize\"]\n", "figheight = 2.0 * figheight\n", @@ -281,14 +410,17 @@ "axs[0].legend(fontsize=12)\n", "\n", "# zoom on fit\n", - "for ii, label, fit in zip([1, 2], [\"Exponential\", \"Linear\"], [results, results_lin]):\n", + "for ii, label, rtn in zip([1, 2], [\"Exponential\", \"Linear\"], [results, results_lin]):\n", + " vf = rtn[0]\n", + " extras = rtn[1]\n", + " \n", " # calc island points\n", " isl_pts = np.array([], dtype=np.int64)\n", - " for isl in fit.islands:\n", + " for isl in extras.islands:\n", " isl_pts = np.concatenate((isl_pts, np.r_[isl]))\n", "\n", " # calc xrange for plot\n", - " xlim = [voltage[fit.indices].min(), voltage[fit.indices].max()]\n", + " xlim = [voltage[extras.fitted_indices].min(), voltage[extras.fitted_indices].max()]\n", " vpad = 0.25 * (xlim[1] - xlim[0])\n", " xlim = [xlim[0] - vpad, xlim[1] + vpad]\n", "\n", @@ -297,7 +429,7 @@ " mask2 = np.where(voltage <= xlim[1], True, False)\n", " mask = np.logical_and(mask1, mask2)\n", " vfit = np.linspace(xlim[0], xlim[1], 201, endpoint=True)\n", - " ifit, ifit_err = fit.func(vfit, reterr=True)\n", + " ifit, ifit_err = extras.fitted_func(vfit, reterr=True)\n", "\n", " axs[ii].set_xlabel(\"Bias Voltage (V)\", fontsize=12)\n", " axs[ii].set_ylabel(\"Current (A)\", fontsize=12)\n", @@ -311,8 +443,8 @@ " label=\"Sweep Data\",\n", " )\n", " axs[ii].scatter(\n", - " voltage[fit.indices],\n", - " current[fit.indices],\n", + " voltage[extras.fitted_indices],\n", + " current[extras.fitted_indices],\n", " linewidth=2,\n", " s=6 ** 2,\n", " facecolors=\"deepskyblue\",\n", @@ -343,20 +475,20 @@ " )\n", " axs[ii].axhline(0.0, color=\"r\", linestyle=\"--\")\n", " axs[ii].fill_between(\n", - " [fit.vf - fit.vf_err, fit.vf + fit.vf_err],\n", + " [vf - extras.vf_err, vf + extras.vf_err],\n", " axs[1].get_ylim()[0],\n", " axs[1].get_ylim()[1],\n", " color=\"grey\",\n", " alpha=0.1,\n", " )\n", - " axs[ii].axvline(fit.vf, color=\"grey\")\n", + " axs[ii].axvline(vf, color=\"grey\")\n", " axs[ii].legend(fontsize=12)\n", "\n", " # add text\n", - " rsq = fit.rsq\n", - " txt = f\"$V_f = {fit.vf:.2f} \\\\pm {fit.vf_err:.2f}$ V\\n\"\n", + " rsq = extras.rsq\n", + " txt = f\"$V_f = {vf:.2f} \\\\pm {extras.vf_err:.2f}$ V\\n\"\n", " txt += f\"$r^2 = {rsq:.3f}$\"\n", - " txt_loc = [fit.vf, axs[ii].get_ylim()[1]]\n", + " txt_loc = [vf, axs[ii].get_ylim()[1]]\n", " txt_loc = axs[ii].transData.transform(txt_loc)\n", " txt_loc = axs[ii].transAxes.inverted().transform(txt_loc)\n", " txt_loc[0] -= 0.02\n", @@ -374,7 +506,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -388,7 +520,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.6" + "version": "3.9.6" } }, "nbformat": 4, From ef6018156d5ced1689ba5eca0e0af8cb0d3e9674 Mon Sep 17 00:00:00 2001 From: Erik Date: Wed, 18 May 2022 19:39:12 -0700 Subject: [PATCH 256/521] whoops...clear notebook outputs --- .../find_floating_potential.ipynb | 138 +++--------------- 1 file changed, 19 insertions(+), 119 deletions(-) diff --git a/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb b/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb index ef58d632a3..6595948746 100644 --- a/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb +++ b/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb @@ -15,7 +15,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -111,7 +111,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -148,20 +148,9 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "-5.665729878703537" - ] - }, - "execution_count": 3, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "vf = results[0]\n", "vf" @@ -178,20 +167,9 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "VFExtras(vf_err=0.45174046362475595, rsq=0.9564766142728284, fitted_func=f(x) = a exp(alpha x) + b , islands=[slice(192, 195, None), slice(201, 210, None)], fitted_indices=slice(155, 247, None))" - ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "extras = results[1]\n", "extras" @@ -206,20 +184,9 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "(0.45174046362475595, 0.45174046362475595)" - ] - }, - "execution_count": 5, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "(extras[0], extras.vf_err)" ] @@ -233,20 +200,9 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "(0.9564766142728284, 0.9564766142728284)" - ] - }, - "execution_count": 6, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "(extras[1], extras.rsq)" ] @@ -269,26 +225,9 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "(f(x) = a exp(alpha x) + b ,\n", - " f(x) = a exp(alpha x) + b ,\n", - " FitParamTuple(a=0.010275377527636112, alpha=0.33827816441206754, b=-0.001511583532931966),\n", - " 0.010275377527636112,\n", - " FitParamTuple(a=0.0003144059149671168, alpha=0.02163130023989389, b=0.0001299928251489394),\n", - " 0.0003144059149671168,\n", - " 0.0)" - ] - }, - "execution_count": 7, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "(\n", " extras[2],\n", @@ -310,22 +249,9 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "([slice(192, 195, None), slice(201, 210, None)],\n", - " [slice(192, 195, None), slice(201, 210, None)],\n", - " array([-7.496 , -7.2238, -7.1512]))" - ] - }, - "execution_count": 8, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "(\n", " extras[3],\n", @@ -343,22 +269,9 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "(slice(155, 247, None),\n", - " slice(155, 247, None),\n", - " array([-11.6594, -11.6488, -11.5358, ..., -1.251 , -0.9812, -0.8504]))" - ] - }, - "execution_count": 9, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "(\n", " extras[4],\n", @@ -376,26 +289,13 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": null, "metadata": { "nbsphinx-thumbnail": { "tooltip": "Floating Potential" } }, - "outputs": [ - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAApsAAAKvCAYAAAAleQTfAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/YYfK9AAAACXBIWXMAAAsTAAALEwEAmpwYAAEAAElEQVR4nOzdd3hU1dbA4d9K7wkkoaRAQHrvIEWwIUWKDUFBsfF5Vbx2xQLYsaDXXrGBCohKERGUjgoSpPcACSSBkIT0PpP9/TFDSIUAqbDe55knM/vss88+hwFWdhVjDEoppZRSSlUGh+qugFJKKaWUunBpsKmUUkoppSqNBptKKaWUUqrSaLCplFJKKaUqjQabSimllFKq0miwqZRSSimlKo1TdVegtggICDBhYWHVXQ2llFJKqRpn06ZNCcaYwNKOabBZTmFhYYSHh1d3NZRSSimlahwRiSrrmHajK6WUUkqpSqPBplJKKaWUqjQabCqllFJKqUqjwaZSSimllKo0OkHoPOXn55OQkEBycjJWq7W6q6POg5ubGyEhITg7O1d3VZRSSqkLhgab5yk6OhoRISwsDGdnZ0SkuqukzoExhsTERKKjo2nSpEl1V0cppZQql+TMXN5dHsFtlzYmLMCzuqtTKu1GP08ZGRkEBwfj4uKigWYtJiL4+/uTnZ1d3VVRSimlym3Zzji++PMQQ99dy+x/DpOcmQtAanYeH66KIDE9p5prqC2bFcLBQWP2C4H+sqCUUqq2ORCfjouTA22CfHjqp+089dN2Lgn0JDIxE2u+IdDLlZu6hVZrHTXYVEoppZSq4TJzLXi4lAzbIo6n0zTAk9kTLmVj5AnCI0+wMTIJEWHa9e3pFla3GmpblAabSimllFI12PqDiYz+dD0z7+pBv+ZFd4Q8EJ9O2yBfHB2EXk396dXUv5pqWTbt/73ArVu3jt69e+Pr60vdunXp06cPGzdurO5qlWrVqlU4ODjg5eWFl5cXISEhjBo16qzqO3XqVMaOHVuJtVRKKaWqTmRCBvd9+y8Ac8OjixzLzrNy+EQml9Tzqo6qlVutCDZFZJCI7BWRCBF5qpTjriIyx358g4iE2dN7iMgW+2uriFxX3jIvBKmpqVx77bVMnDiREydOEBMTw5QpU3B1da3uqpUpKCiI9PR00tLSWL9+Pa1ataJfv34sX768uqumlFJKVYldsam89MsuthxJ5pbP1mOMoVUDb9btj8dizQcgLTuPaUv2kG+guQab50dEHIEPgMFAG2CMiLQplu0uIMkY0wx4G3jNnr4D6GaM6QQMAj4REadyllnr7du3D4AxY8bg6OiIu7s7AwcOpEOHDgA0btyYTZs2AfDtt98iIuzcuROAGTNmMHLkSMC2lui0adO45JJL8Pf3Z9SoUZw4caLgOuvXr6d37974+fnRsWNHVq1aVXBswIABTJo0iR49euDj48OIESOKnFsWESEkJIQXXniBu+++myeffLLg2H//+19CQ0Px8fGha9eurF27FoDffvuNV155hTlz5uDl5UXHjh0B+PLLL2ndujXe3t40bdqUTz755ByfqFJKKVX5pi7cyefrDjHygz/JyLUy6+6e/PfK5iRl5vHPoRPM2xTN5W+u5uu/IxndPZRr2jao7iqfVm0Ys9kDiDDGHAQQkdnACGBXoTwjgKn29/OA90VEjDGZhfK4AeYsyjwnzy/aya7Y1PMt5rTaBPkwZVjbM+Zr0aIFjo6O3H777YwePZpevXpRp06dguP9+/dn1apVdO3aldWrV9O0aVPWrFlD27ZtWb16Nf379wfgvffeY/78+axevZrAwEAefPBB7r//fr7//ntiYmIYOnQoM2fOZNCgQSxfvpwbbriBPXv2EBhoG1fyzTffsHTpUpo0acJtt93Ggw8+yKxZs8p9v9dffz0ffvghGRkZeHp60r17dyZPnoyvry/vvPMON910E5GRkQwaNIinn36aiIiIIuXXq1ePX375peD+Bg8eTPfu3enSpUu566CUUkpVpn8OneBoShbBfu78E3mC8b3DSMnK484+TWgb5EuTAE9cnRy455twMnKtdAr144vx3egQ4lfdVT+jGt+yCQQDRwp9jranlZrHGGMBUgB/ABHpKSI7ge3Avfbj5SkTEZkgIuEiEh4fH19Bt1N1fHx8WLduHSLCPffcQ2BgIMOHDycuLg6wBZurV68GYO3atUyaNKngc+Fg8+OPP+bll18mJCQEV1dXpk6dyrx587BYLMyaNYshQ4YwZMgQHBwcuPrqq+nWrRu//vprQT3GjRtHu3bt8PT05MUXX2Tu3LlntdtSUFAQxhiSk5MBGDt2LP7+/jg5OfHoo4+Sk5PD3r17yzx/6NChXHLJJYgI/fv3Z+DAgQWtoUoppVR1OpSQwd1fhzPqk795aM4W3lsRQR0PZ54Y1JK3b+5E+xBfADxcnBjaviHuLo68cWMHfvpP71oRaELtaNk8L8aYDUBbEWkNfC0iS87i3E+BTwG6detmzpAdoFwtjlWpdevWfPXVVwDs2bOHsWPH8tBDD/H999/Tv39/HnvsMY4ePYrVamXUqFE8//zzREZGkpKSQqdOnQCIioriuuuuK7KeqKOjI3FxcURFRfHDDz+waNGigmN5eXlcfvnlBZ9DQ0+t79W4cWPy8vJISEigfv365bqHmJgYRAQ/Pz8A3nzzTWbMmEFsbCwiQmpqKgkJCWWev2TJEp5//nn27dtHfn4+mZmZtG/fvlzXVkoppSrT3V9vJC41h86N/Nh8OJnV++J5+KoWpS5z9MZNHRHAwaF2rQtdG1o2Y4DCq5GG2NNKzSMiToAvkFg4gzFmN5AOtCtnmRecVq1aMX78eHbs2AFAs2bN8PDw4L333uOyyy7Dx8eHBg0a8Omnn9K3b9+C4DI0NJQlS5aQnJxc8MrOziY4OJjQ0FDGjRtX5FhGRgZPPXVqztWRI6cakQ8fPoyzszMBAQHlrvfPP/9Mly5d8PT0ZO3atbz++uvMnTuXpKQkkpOT8fX1xRjb7wLFF2bPycnhhhtu4LHHHiMuLo7k5GSGDBlSkF8ppZSqLonpORyIz+A/Ay5heMcgADxcHLm9d+NS8zs6SK0LNKF2BJsbgeYi0kREXIDRwMJieRYCt9vf3wisMMYY+zlOACLSGGgFRJazzFpvz549TJ8+neho21IJR44c4fvvv6dXr14Fefr378/7779f0GU+YMCAIp8B7r33Xp555hmioqIAiI+PZ8GCBYCtS3vRokUsXboUq9VKdnY2q1atKrgmwKxZs9i1axeZmZlMnjyZG2+8EUdHx9PW3RhDTEwMzz//PJ9//jmvvPIKAGlpaTg5OREYGIjFYuGFF14gNfXUGNn69esTGRlJfr5ttl5ubi45OTkEBgbi5OTEkiVLWLZs2Tk/U6WUUqoiLN8dR9eX/gCgWT0vXJxsIdktPRrh5+FSnVWrcDU+2LSPsXwAWArsBuYaY3aKyAsiMtyebQbgLyIRwCPAyWa1vsBWEdkC/AzcZ4xJKKvMKrupKuLt7c2GDRvo2bMnnp6e9OrVi3bt2jF9+vSCPP379yctLY3LLrus1M9gm/09fPhwBg4ciLe3N7169WLDhg2ArdVzwYIFvPLKKwQGBhIaGsobb7xREOyBbczm+PHjadCgAdnZ2bz77rtl1jk2NrZgnc3u3buzfft2Vq1axcCBAwG45pprGDRoEC1atKBx48a4ubkV6aa/6aabAPD396dLly54e3vz7rvvMmrUKOrUqcN3333H8OHDS722UkopVVU+WX2w4H3zel40C/Qi2M+du/o1qcZaVQ7R7sTy6datmwkPDy+Rvnv3blq3bl0NNaodBgwYwNixY7n77ruruyrlon+eSimlKtuOmBSufW9dweeIlwfj5Fjj2/9OS0Q2GWO6lXbsgp8gpJRSSilVk3z1VyQeLo6seeJyci35tT7QPJML++6UUkoppapReo6Flxfv4nCibenvhPQcFm6J5YYuIQR4uRLk517NNax82rKpKlXh3YSUUkqpi0lKZh73ztrE3wcTiU3J5oNbuvD9hsPkWvO5vXdYdVevymiwqZRSSilVwQ4lZHDXVxs5kpSJh4sjy3fHkZiew8z1UVzWIpBmNXw/84qk3ehKKaWUUhXor4gERn7wJ8lZeXx3Ty9mT+hFdl4+D3y3meNpOdzRJ6y6q1iltGVTKaWUUqqCHDmRyfivNhLm78GM27sTWtcDYwytG/rw98FEmgZ40r95YHVXs0ppy6ZSSimlVAV5c9leHAS+ubMnoXU9ANvudqO729aEvr13WK3cBeh8aMumUkoppVQF2B6dwoItsTxweTMa+LoVOXZz91BEYFS30DLOvnBpsKmUUkopdZ6MMbzy627qerrwf/2bljju5uzIbZeGVX3FagDtRr/AhYWF8ccff1RomcYYnnzySfz9/fH39+fJJ59Ed6JSSil1MVu9L56/Dyby3yub4+3mXN3VqVE02FRn7dNPP2X+/Pls3bqVbdu2sWjRIj755JPqrpZSSilVJZIzc/lwVQTZedaCtBV7juPl6sSYHo2qsWY1kwab6qx9/fXXPProo4SEhBAcHMyjjz7KV199Vd3VUkopparEsl1xvP7bXt5Zvr8gLT3bgp+HMy5OGloVp2M2K8OAASXTRo2C++6DzEwYMqTk8fHjba+EBLjxxpLH//MfuPlmOHIEQitmcPF3333HfffdV+bxbdu20ahRyd/Qdu7cSceOHQs+d+zYkZ07d1ZInZRSSqma6nhqNodPZBKbnAXAp2sOMrhdAzqE+JGeY8HLVcOq0mj4fRG75ZZbSE5OLvNVWqAJkJ6ejq+vb8FnX19f0tPTddymUkqpC9q7K/Zz9zfhHE3Oxs/DmUAvVx7/YRs5FisZuRY8NdgslT6VynC6/cA9PE5/PCDg9McrqFXzfHh5eZGamlrwOTU1FS8vL0QurnXDlFJKXVwOJWSQnJlHTHIWjep68PBVLbjjq41881cU6TlWfN11YlBpanzLpogMEpG9IhIhIk+VctxVRObYj28QkTB7+tUisklEttt/XlHonFX2MrfYX/Wq8JZqjG+//RYvL68yX4cPHy71vLZt27J169aCz1u3bqVt27ZVVW2llFKqWhw+kQlAxPF0Gvq6cXmrerRq4M3aiAQycix4ujhWcw1rphodbIqII/ABMBhoA4wRkTbFst0FJBljmgFvA6/Z0xOAYcaY9sDtwMxi591qjOlkfx2vtJuowW699VbS09PLfJXVjX7bbbfx1ltvERMTQ2xsLNOnT2f8+PFVW3mllFKqkqVl57E/Lg2APGs+scnZABxLzaahrzsAnUL92BadTHq2dqOXpUYHm0APIMIYc9AYkwvMBkYUyzMC+Nr+fh5wpYiIMWazMSbWnr4TcBcR1yqp9QXu//7v/xg2bBjt27enXbt2DB06lP/7v/+r7moppZRSFeqWzzZw9dtrAIhNzsKaf2puQpCfbYegjqF+JGfmcSw1WycIlaGmP5Vg4Eihz9FAz7LyGGMsIpIC+GNr2TzpBuBfY0xOobQvRcQK/Ai8ZC7Q2S2RkZEVXqaI8Prrr/P6669XeNlKKaVUTbE9JgWwbWZysgv9pJMtmx1D/ArSPF21G700Nb1l87yJSFtsXeuFm95utXev97O/xpVx7gQRCReR8Pj4+MqvrFJKKaVqnDyrISqxaLB5smWzRX0v3Jxt4ZR2o5eupgebMUDh6dch9rRS84iIE+ALJNo/hwA/A7cZYw6cPMEYE2P/mQZ8h627vgRjzKfGmG7GmG6BgYEVckNKKaWUql3yrPkcKaNl08nRgXZBtuUAtRu9dDU92NwINBeRJiLiAowGFhbLsxDbBCCAG4EVxhgjIn7AYuApY8yfJzOLiJOIBNjfOwPXAjsq9zaUUkopVVvlWvKJSszEwz7b3EGgnvepaSAdQ/0A8HTRYLM0NTrYNMZYgAeApcBuYK4xZqeIvCAiw+3ZZgD+IhIBPAKcXB7pAaAZMLnYEkeuwFIR2QZswdYy+lmV3ZRSSimlapU8az6HT2TSuqEPAPW83XByPBVCFQSbOmazVDU+BDfG/Ar8WixtcqH32cBNpZz3EvBSGcV2rcg65ufn4+BQo+N2VQ4X6BwxpZRS5ynHYutGH9k5mE1RSTS0j9c86bLmAVzVuj6dG9WpphrWbBohnSdPT09iYmLIzc3VYKUWM8aQmJiIm5vbmTMrpZS64BX+P/14Wg5pORbCAjzxcHEkyD5e8yQ/Dxc+v70b9X30/5DS1PiWzZouJCSEhIQEoqKisFgs1V0ddR7c3NwICQmp7moopZSqAaKTsgreHzieDkCjuh4Mbd+QPs0CqqtatZIGm+fJwcGBevXqUa/eRbnjpVJKKXVBevv3fQXvI+JtwWZjfw/euKljdVWp1tJudKWUUkqpQnYfTeXnLTG0sU8IirC3bIbW8ajOatVaGmwqpZRSShXy4aoDeLo48eCVzQA4EJ9OPW9X3F10tvm50GBTKaWUUsouKjGDxdtiubVXIwK8bGtpHjmRSaO62qp5rjTYVEoppZSy+2TNQZwcHbirTxNcnGxhUr5Bg83zoMGmUkoppRRwPDWbeeHR3Ng1hHo+bjgXWri9kb8Gm+dKg02llFJKKWDGukNY8vP5v8uaAhS0bIK2bJ4PDTaVUkopddFLycxj1voohnYIorG/JwAujhpsVgQNNpVSSil10ZsbfoSMXGtBqyag3egVRINNpZRSSl3UjDF8v/EwXRvXoV2wb0H6yW50N2cHAu0z09XZ02BTKaWUUhe18KgkDsZnMLp7aJF0Z0cBbF3oIlIdVbsgaLCplFJKqYvav1FJAAxs06BI+smWzUZ1Pau8ThcSDTaVUkopdVGLOpFJXU8XfD2ci6Q7O5wMNnW85vlwqu4KKKWUUkpVp6jEjFIDSgcH4fUbOtCjSd1qqNWFo1a0bIrIIBHZKyIRIvJUKcddRWSO/fgGEQmzp18tIptEZLv95xWFzulqT48QkXdFB2MopZRSF6XIhEzCyphtPqp7KGEB2o1+Piq1ZVNE6gHXAB0BPyAZ2Ar8bow5Vs4yHIEPgKuBaGCjiCw0xuwqlO0uIMkY00xERgOvATcDCcAwY0ysiLQDlgLB9nM+Au4BNgC/AoOAJed+t0oppZSqbXIsVmJTsmjsH1LdVblgVUrLpoi0FpF5wG5gHOAMHLP/HAfsFJF5ItKmHMX1ACKMMQeNMbnAbGBEsTwjgK/t7+cBV4qIGGM2G2Ni7ek7AXd7K2hDwMcYs94YY4BvgJHnfMNKKaWUqjU2HExkyfajABw5kYUxEBag4zIrS2W1bH4FvAHcaozJKX5QRFyB4cAM4NIzlBUMHCn0ORroWVYeY4xFRFIAf2wtmyfdAPxrjMkRkWB7OYXLDKYYEZkATABo1KjRGaqplFJKqZrsREYu3m5OfLb2EP8cSuTqNvWJSswAKNg1SFW8Sgk2jTHFg8Hix3OAH+yvSicibbF1rQ88m/OMMZ8CnwJ069bNVELVlFJKKVUFMnIs9H9jJfdf3ow8az6p2Ra2HEkmKjETgMY647zSVPkEIRFxEJGhIjK3nKfEAIVXWQ2xp5WaR0ScAF8g0f45BPgZuM0Yc6BQ/sKDM0orUymllFIXiDX74knLthAeeYI8az4Aq/fFE5WYgberE3U9Xaq5hheuKgs2RaSjiLwFxALfAcfLeepGoLmINBERF2A0sLBYnoXA7fb3NwIrjDFGRPyAxcBTxpg/T2Y2xhwFUkWkl30W+m3AgnO8NaWUUkrVcL/vjgNgZ2wqFquts3L1vngiEzNpHKA7BFWmqpiNPhZbINgGWAN4Au2NMZHlKcM+BvMBbDPJHYEvjDE7ReQFINwYsxDb2M+ZIhIBnMAWkAI8ADQDJovIZHvaQGPMceA+bGNL3bHNQteZ6EoppdQFyGLNZ+We4zg7CkdTsgt2BtoWnUJdTxcuvcS/mmt4Yau0YFNEFmNbrmgbtpnis+1LEB0FMs+mLGPMr9iWJyqcNrnQ+2zgplLOewl4qYwyw4F2Z1MPpZRSStU+/x5OJikzj1t7NuLbDYeJSsykvo8rcak5nMjILXONTVUxKrMbvT+Qiq3F8NdCSxAppZRSSlWZP3bH4eLowH8GXFKQ1jHEjwAv2zjNxrr3eaWqzGCzPvAI0Bvbupr/isij2Nba1JndSimllKp0xhh+3xVHr0v8CanjQbCfOwAuTg5c1jwQgMbaslmpKi3YNMZkGGO+McZcCTQFfsK2ZmVdbOMrh1TWtZVSSimlwDYh6FBCBle3rgdAmyAfAFwcHRjeKYi6ni60bOBdnVW84FXJbHRjTJQx5iVjTEugDxAFzKyKayullFLq4vXO8v34uDkxorNt75a29mDT2dGBAS3r8e9zV+PnocseVaYqX2fTGPO3Meb/gKCqvrZSSimlLh47YlL4fVccd/drio+bMwBtg3wBcHLUpY6qSmXtjf6WiDQ4Q7Y69nU3lVJKKaUq3P/+2IevuzN39AkrSGtTqGVTVY3KWvpoL/CPiOwGVts/pwHeQAtgANCSMpYlUkoppZQ6H9uik/lj93EeG9gCb3urJkCQrxttg3xoVs+rGmt3camsvdE/EZEvgBHAYGAk4AckYVt382NgkTHGUhnXV0oppdTF7Z0/9uPn4cztvcOKpIsIix/sVz2VukhV2qLuxpg8YJ79pZRSSilVJbYeSWb5nuM8fk3LIq2aqnrogAWllFJKXVD+98c+6pTSqqmqhwabSimllLpg/Hs4iZV747nnsqZ4uVZaB646CxpsKqWUUuqC8ebSvQR4uTBeWzVrDA02lVJKKXVB+Csigb8OJPKfAc3wcNFWzZqi0oNNETlRRvrxyr62UkoppS4ec8KP4O/pwq09G1V3VVQhVdGyWWIamIg4A45VcG2llFJKXSSOp+bQJMATN2cNMWqSSmtjFpG1gAHcRGRNscMhwF+VdW2llFJKXXySMnMJretR3dVQxVTmgIbPAQG6AzMKpRsgDlhRnkJEZBDwDraW0M+NMdOKHXcFvgG6AonAzcaYSBHxx7bGZ3fgK2PMA4XOWQU0BLLsSQONMdqtr5RSStViiRm5dAr1q+5qqGIqc1H3rwFEZL0xZs+5lCEijsAHwNVANLBRRBYaY3YVynYXkGSMaSYio4HXgJuBbOA5oJ39Vdytxpjwc6mXUkoppWoWYwxJGbnU8XSp7qqoYip9qpYxZo+IDAQ6AV7Fjk0+w+k9gAhjzEEAEZmNbQvMwsHmCGCq/f084H0REWNMBrBORJqd900opZRSqkZLzbZgyTf4a7BZ41TFbPT3gVnYurlDC71CynF6MHCk0Odoe1qpeex7racA/uUo+0sR2SIiz4mIlFH3CSISLiLh8fHx5ShSKaWUUtUhOikTgLoabNY4VbEI1S1AR2PMkTPmrDq3GmNiRMQb+BEYh23cZxHGmE+BTwG6detmqraKSimllCoPa77h+UW78HJ14tJLytPepKpSVSx9lAAkn+O5MdhaQU8KsaeVmkdEnABfbBOFymSMibH/TAO+w9Zdr5RSSqla6LO1B/nn0AmeH96Whr7u1V0dVUxVBJvTgW9F5FIRaVr4VY5zNwLNRaSJiLgAo4GFxfIsBG63v78RWGGMKbMVUkScRCTA/t4ZuBbYcZb3pJRSSqlqkGOxEpOcVfB5R0wK05ftZUj7BlzfpfhIO1UTVEU3+kf2n9cWSzecYWF3Y4xFRB4AltrzfmGM2SkiLwDhxpiF2JZVmikiEcAJbAEpACISCfgALiIyEhgIRAFLCy0s/wfw2XndoVJKKaWqxIx1h3hr2T7evKkjg9o14OE5W6jj4cLLI9tTxhQMVc2qYjb6ebWeGmN+BX4tlja50Pts4KYyzg0ro9iu51MnpZRSSlWPyIQMLPmGh+ZsofPffuw/ns43d/bQJY9qsCrbpV5EQoFgY8z6qrqmUkoppS4scak5tGrgTaO6HizbFcf43mFc1iKwuqulTqPSg00RaQR8j22dTQN4iciNwCBjzN2VfX2llFJKXTjiUrMJrevBh7d2YW1EAn0uCajuKqkzqIoJQp8AiwFvIM+e9ju2XYGUUkoppUp4d/l+NkaeKJEel5pNfR9XnBwduLxlPVycqiKUUeejKv6EegDTjDH52Fo2McakYFuiSCmllFKqiPx8w1u/7+Omj/8ukp5jsZKUmUd9b7dqqpk6F1URbMYBRbaMFJE2wOEquLZSSimlapmUrLxS04+n5gBQ31eDzdqkKoLNN4FfROQOwElExgBzgNeq4NpKKaWUqmUSM3JLTY9LzQagvo8Gm7VJVSx99IWIJAL/h20P89uA54wx8yv72koppZSqfU7Yg01356LLcR+zB5sNNNisVSo12BQRR2A5cI0xZkFlXksppZRSF4YTGbbucg+XosFm3MludB/XKq+TOneV2o1ujLECTSr7OkoppZS6cMSn2YJKt2Itm8dTs3FxcsDX3bk6qqXOUVUEgc8DH4lIYxFxFBGHk68quLZSSimlapl1EQkAeLsV7YA9lppNAx833ZaylqmKHYQ+t/8cVyhNKMfe6EoppZS6uGTkWFi1Nx6AXEt+Qboxhm3RKTT296iuqqlzVBXBZnPAUgXXUUoppVQtt2LPcXIs+TQJ8CQrz1qQHh6VxKGEDO6/vNlpzlY1UVVMENoB+BljcirzWkoppZSq/RZsiSXQ25U+zfxZtPVoQfrcjUfwdHFkSPsG1Vg7dS6qYoLQPsC/Mq+jlFJKqdrvuw2H+WN3HLf2bISnq1NBy2Z6joXF248yrGMQHi5V0SmrKlJVTNL5Ftui7reLyJUicsXJVxVcWymllFK1wPqDiUxesIMBLQOZeEVzPJydyLXkY803LN4WS2aulVHdQ6u7muocVMWvB/+x/5xaLN0ATavg+koppZSqoX7eHM3x1Bw+Xn2ARv4evDumM44OgruLrT0sO8/KnI1HaFbPi86hftVbWXVOKr1l0xjTpIxXuQNNERkkIntFJEJEnirluKuIzLEf3yAiYfZ0fxFZKSLpIvJ+sXO6ish2+znviq6joJRSSlWpiOPpPDFvG68u2YM13zDj9u74uNnW0Dy5e9D2mBT+PZzMzd1CdcmjWqrGr3Vpn2T0ATAYaAOMEZE2xbLdBSQZY5oBb3Nq3/Vs4DngsVKK/gi4B9ts+ebAoIqvvVJKKaVKY4xh8oId5FkNAC0beNMkwLPg+MkF3b/5OxInB+G6LsHVUk91/io92BSRIyJyuLRXOYvoAUQYYw4aY3KB2cCIYnlGAF/b388DrhQRMcZkGGPWYQs6C9epIeBjjFlvjDHAN8DIc7xFpZRSSp2lX7Yd5a8DiTx4hW0po6jEzCLH3e1bVS7dGceVresR4KVbVNZWVTFmc2yxzw2B/2ILGssjGDhS6HM00LOsPMYYi4ikYJsBn3CaMqOLlVniVyYRmQBMAGjUqFE5q6uUUkqp00nPsfDS4l20DfLhv1e1wNfDhS6N/IrkOdmNbs03jOqmE4Nqs0oPNo0xq4unicgq4Dfgncq+/vkwxnwKfArQrVs3U83VUUoppS4I//t9H3GpOXw0tiuODsJdfZuUyHMy2Kzn7Ur/FoFVXUVVgaprzGYOUPKbVboYoPCvNCH2tFLziIgT4AsknqHMkDOUqZRSSqkKtvdYGl/+Fcno7qF0aVSnzHwnu9Fv6BqCk2ONn2KiTqPSWzZF5IViSR7AEGBJOYvYCDQXkSbYAsLRwC3F8iwEbgf+Bm4EVtjHYpbKGHNURFJFpBewAbgNeK+c9VFKKaXUOTDG8NyCHXi7OfHEoFanzdu6oQ+3XdqYO/qEVU3lVKWpijGbxQdaZABvATPLc7J9DOYDwFLAEfjCGLPTHsSGG2MWAjOAmSISAZzAFpACICKRgA/gIiIjgYHGmF3AfcBXgDu2wLe8wa9SSimlzoIxhqjETBZsieWfQyd45br21PV0Oe05bs6OvDCiXRXVUFUmOU0DoCqkW7duJjw8vLqroZRSStUay3Ye47edx/j7QCJHU2wLw7Ru6MPiiX1xcNA1My8kIrLJGNOttGOV1rIpIn2A4caYJ0s5Ng2Yb4xZX1nXV0oppVT1ScrI5f9mbcLP3ZnelwTQ0NeN8KgkXrmuvQaaF5nK7EZ/GviwjGOrgGeAYZV4faWUUkpVk01RSRgDn4zrRo8mdau7OqoaVeb0rk7YljcqzR9A10q8tlJKKaWqWGp2Hiv2xAGwMeoELo4OdAjxreZaqepWmcGmD1DW6F9nwLsSr62UUkqpKvb8wl3c+VU4B+LTCY9Mon2Ib8G2k+riVZnB5h5gYBnHBtqPK6WUUuoCsPdYGj9ttm3O99uOY2yLTqZb47LX0VQXj8ocs/k28ImIOGKbDJQvIg7Y9iD/AHikEq+tlFJKqSr0xtK9eLk4UcfThc/XHiTPaugWpmM1VSUGm8aY70SkAfA14CoiCUAAtt2Dphhjvq+sayullFKq6oRHnuCP3XE8fk1LUrPy+GTNQQC6asumopIXdTfGvCUinwOXAv7YtpD82xiTWpnXVUoppVTVMMbw2m97CPR25Y4+YWyLTuGTNQdpVs/rjAu3q4tDpe8gZA8sl1b2dZRSSilV9VbuPc7GyCReHNkODxcnujaug7+nC70v8a/uqqkaoiq2q1RKKaXUBciab3j9t7009vdgdHfb7tTOjg4sfrAfPu4aYiibypyNrpRSSqkL2IItMew5lsajA1vi7HgqpGjg64aHiwabykaDTaWUUkqdtciEDKYu3EmHEF+ubd+wuqujajANNpVSSil1VlKz87jnm3AcHIQPbumie52r09I2bqWUUkqdljXf8PeBRDYcSmTDwRNsOZKM1Rhm3tmD0Loe1V09VcNpsKmUUkqpMq0/mMjoT9cD4OggtAv2ZXyfMK5p20DX0VTlUiuCTREZBLwDOAKfG2OmFTvuCnwDdMW2lufNxphI+7FJwF2AFXjQGLPUnh4JpNnTLcaYblVyM0oppVQtcjLQBNg6ZSBerrUidFA1SI3/xti3u/wAuBqIBjaKyEJjzK5C2e4CkowxzURkNPAacLOItAFGA22BIOAPEWlhjLHaz7vcGJNQZTejlFJK1WIaaKpzURsmCPUAIowxB40xucBsYESxPCOwbYsJMA+4UkTEnj7bGJNjjDkERNjLU0oppdQZWKz51V0FdQGoDcFmMHCk0Odoe1qpeYwxFiAF2/aYpzvXAMtEZJOITKiEeiullFI12sH4dHIs1jKPRyZmVGFt1IWqNgSblaWvMaYLMBi4X0QuK55BRCaISLiIhMfHx1d9DZVSSqlKcjgxk6vfXsOPm2LKzLMzNrUKa6QuVLUh2IwBQgt9DrGnlZpHRJwAX2wThco81xhz8udx4GdK6V43xnxqjOlmjOkWGBhYITejlFJK1QRzw49gzTckpOcUSX91yW5GfvAnUYkZvP7bXup6unBd52BmT+hVTTVVtV1tGOm7EWguIk2wBYqjgVuK5VkI3A78DdwIrDDGGBFZCHwnIm9hmyDUHPhHRDwBB2NMmv39QOCFqrkdpZRSqnpZrPn8sMk2yiwz91Q3+pYjyXy65iDGwIgP/kSAmXf1pF2wbzXVVF0IanywaYyxiMgDwFJsSx99YYzZKSIvAOHGmIXADGCmiEQAJ7AFpNjzzQV2ARbgfmOMVUTqAz/b5hDhBHxnjPmtym9OKaWUqgar9sYTl2pr0czMtQCQnWfl6Z+24+/pQkJ6Lk4ODnx7d09aNvCuzqqqC4AYY6q7DrVCt27dTHh4eHVXQymllDpvd38dzpYjyTgI9G0WQM+mdXn79/0cS83m47FdcXV2oFmgl+4OpMpNRDaVtWZ5jW/ZVEoppVTFiUvNZsWeOCZcdgnLdh7jp80x/LQ5hk6hfvxvdCd6NfWv7iqqC0xtmCCklFJKqQrS85Xl5Bu4uXsoufZ1NP/vsqb8fF9vDTRVpdBgUymllLpInMjILXjfJMATa75tKF3LBt7Y5zEoVeE02FRKKaVquWMp2ZRnDsbfBxIB+Om+3gBY7MGmt5tz5VVOXfQ02FRKKaVqsU1RSfR6dTmPzN162t2AANZFJODt6kQH+1JG1oJgU6dwqMqjwaZSSilVi/224ygOAj9vjuGWzzZwPDW71HxZuVbWRcTT6xJ/nBxt//2f3Ptcg01VmTTYVEoppWqx5XuO06dZAB/c0oWdsSlc/uYq3lu+n6xcK0kZuczbFM0934TT+cVlHDmRxcA29QvOPdmy6aPd6KoS6a8ySimlVC2UZ81nwZZYDsZncFuvxgzt0JA2QT68tmQP03/fx4w/D5GWbcGab2jo68bN3UK5pm0DLr3k1IxziwabqgposKmUUkrVABZrPpuPJNOtcZ0zzgzPsViZ+N1mlu2KA+CKVrbWyiYBnnw8risbI0/w1Z+RNAnwZGDb+rQP9i21zFt6NuLLPyPxdHWs+BtSyk53ECon3UFIKaVUZZr9z2Ge+mk7g9s14I2bOuLlWnp7UHaelf/M2sTKvfEFaZHThp7TNfPzDTmWfNxdNNhU5+d0OwjpmE2llFKqBtgRm4Kzo7B05zEm/bS9xPHMXAs/hB/hho/+YtW+eCZc1hSAFvW9zvmaDg6igaaqdNqNrpRSSlWjiOPpODsK++LS6RjiR1iAJyv2HC9YN3NHTCrfbzzMwi2xpOdYaBrgyftjujC4XQPcnB0Z0yO0mu9AqdPTYFMppZSqBNZ8Q3aeFc8yusMBVu49zr0zNxHo7UpatoUh7RvSPtiXeZuieWf5fpbtjGPX0VTcnB0Y0r4ho7s3onvYqTGdj1zdoqpuR6lzpsGmUkopVcG2Hknm0R+2EpWYwQ1dQnhiUCvqeroAEJ+Wg5uzA95uzrz+217cnB2JTsoCoGV9L7o09gPgf3/sp22QDy+ObMfwjkH4uuuMcVU7abCplFJKVYB/Dp3g87UHmTK8LTd98jd1PVy4vnMIP/0bw9r9CXwyritbo5N55ucdAAR4uXIiI4d7+1/C8t3H2RuXRosG3rSs7807oztxSaAX7ew7/ShVm2mwqZRSSlWAtfvjWbYrDj8PZ3It+Xw0tgudG9Xhlp6N+M+sTVz/4V/kWvMZ0DKQXk39ORSfwdHUbIZ1DKJzozpMXbiTtkG2JYpGdAqu7ttRqsLUimBTRAYB7wCOwOfGmGnFjrsC3wBdgUTgZmNMpP3YJOAuwAo8aIxZWp4ylVJKqbORmJELwLxN0bg4OdA2yNYq2THUj0UT+/LEvG24uzgyfVRHXJ2KzgBv3dCHqwvt7KPUhaTGB5si4gh8AFwNRAMbRWShMWZXoWx3AUnGmGYiMhp4DbhZRNoAo4G2QBDwh4icHE19pjKVUkqpcknOzGXd/gQA8g20C/LBxenU6oL+Xq7MGN+9uqqnVLWq8cEm0AOIMMYcBBCR2cAIoHBgOAKYan8/D3hfbFP1RgCzjTE5wCERibCXRznKLGrvXhgwoGjaqFFw332QmQlDhpQ8Z/x42yshAW68seTx//wHbr4ZjhyBceNKHn/0URg2zHbt//u/kseffRauugq2bIGHHip5/JVXoHdv+OsvePrpksf/9z/o1An++ANeeqnk8U8+gZYtYdEimD695PGZMyE0FObMgY8+Knl83jwICICvvrK9ivv1V/DwgA8/hLlzSx5ftcr288034Zdfih5zd4clS2zvX3wRli8vetzfH3780fZ+0iT4+++ix0NCYNYs2/uHHrI9w8JatIBPP7W9nzAB9u0rerxTJ9vzAxg7FqKjix6/9FJ49VXb+xtugMTEosevvBKee872fvBgyMoqevzaa+Gxx2zvi3/vQL97+t2zvdfvXpFDFoRv7n6O7gO60v7wzrP67hngo6AeDH5oHE16tC/zu5f71dd8fCCXvRt38urvH+JjzWW/uz93tLyeaDe/gnyd02JLf3763bO9v8C+e4D+u3catWFR92DgSKHP0fa0UvMYYyxACuB/mnPLUyYiMkFEwkUkPC8v7zxvQyml1EnrjqRxwsm9wspLcXTljlY38MKOLMbO2EBEmrVc5x1wq8PSOs1IcXTj9Ub9eXhtHPn5pe+st9OjHiN+iOCt3/exJNmJW1rfzCL/llzf9lYSnD0BcHIQhrZvyEjfnAq7N6Vquxq/XaWI3AgMMsbcbf88DuhpjHmgUJ4d9jzR9s8HgJ7YWjvXG2Nm2dNnAPbQ/PRlFqfbVSqlVMXIyrXSevJvdGtch3n/6V3ieJ41n5//jeHajg3xcCnaAZdryWfBlhicHR0Y2dnWRhBxPJ17vgknOimTh69uwRfrDiEizLyrB4Fervy28xiLtx3laEo2D1zejOu7BBesU/no3K38vDmaWXf15JbPNwDw6vXtGdOjUZFrfrgqgvdXRODn4cLL17XDxdGBe2dtIseST6sG3rx/Sxeuems1wX7u/PnUFZX16JSqsU63XWVt6EaPAQpvjxBiTystT7SIOAG+2CYKne7cM5WplFK1Un6+4XhaDg183arkesYYnv55BylZuYTU8SC0jjvDOwWXWBdy77E0Fm8/yq09bYFcZGJGqeW9tyKCd5fvJ9eaz9hejQHIsViZtymaD1ceICY5CxcnBy5vVY+Ozy8DIMDLhe/v6UW3sLpc3bo+Y2ds4LoPbLO/rfmGpgGeeLo68ugPW5m98TAvjmxHqwY+HDmRSb6Bab/tAcDZUZi2ZA/1fVzZfTSNLUeS2Xw4mYT0HEZ0CmLqsLbUsa+XOfOunvy+6xj/vaoFXq5OfDKuKy3re1fKM1aqNqsNweZGoLmINMEWEI4GbimWZyFwO/A3cCOwwhhjRGQh8J2IvIVtglBz4B9AylGmUkrVSgu3xvLw3C3MuL0bV7QqOcP5h/AjfPlnJB/c2oUmAZ5llpOdZ0WEEjOni4tOyuL7fw4T4OXCH7uPk2vJ54/dx/nqju4FLYhbjyRz2xf/kJKVR6dQ2yzthPRcjDEFeQD+PZzEBysjANhw6AS39mzE7I1HeHf5fo6mZNMp1I8xPUJ5c9k+bv/in4LzFjzQl2A/W7d88/rezLu3N9N+20OYvwdD2wfRuqE3xsDc8CO89tsehr67jus6B7P/eBouTg5si04B4M6+TZix9hB3fmXryWoa4Em/5gEM69iwxLPs0aQuPZrULfh8TdsGp31OSl2sanywaYyxiMgDwFJsyxR9YYzZKSIvAOHGmIXADGCmfQLQCWzBI/Z8c7FN/LEA9xtjrACllVnV96bUxaZ4YFGZUjLz8PVwLngfk5xFmyCfKrn2STkWK+v2J9CveWDBzGRjDIu3H+WDlQd46Krm5xSgJGXkYsk3BHq7FklPzszl580x7D6aijHw0OwtLH6wH6F1PYrk2xadwq6jqdzw0V98Mb47nUL9Sr3OvbM2se9YGt9P6EVj/7KD0n8PJwHw9Z09aN3Ah8/XHeSVX/fw078xDO8UxK7YVG79fAOW/HzAtjTQSVe/vYYh7RuCMcSn57ByTzwNfNxoUd+LDQcTeWnxbmasO0S3xnV4/cYO9G0WAEB6jpUZ6w5Sz9uVdU9eUWTmN0BoXQ8+uKVLkTQRGN2jEde0bcD03/eyYHMsaTkWHri8Ge/bA9w2DX347p5eZOVZ6Rjii5+HS5n3rZQqnxo/ZrOm0DGblcuab8jIteDjdmFsx2aMISvPWmK8WW1gzTd8/89hruscfNo9nc/WnmOpjPl0PWN7NebRgS0rrNzi8vMNy3Yd495Z//J//Zvy2MCWvPLrbr7+K5L/je7M8I5Bpz3/r4gE/jyQwOPXtCr1+MmA+ciJTIASgVxhUxfu5Ku/ImlZ35tHB7Ygx5LPrPVRbDh0AoCujevwo33MYp41H2fH08/ZzMq18tnag3y8+gDN63mx4IG+BcdyLflc/uYqYpJtM3ybBHiSmJ5DaF0PZk/ohXehv1uPzNnCir3H8XZzIiEtlw/HduHylvWKlHUkKZMrp68GoKGvG7NPE3BOXbiTORuPsH3qQJwcHciz5jP03bXsi0vH08WRjFwrXq5OfDS2C+Nm/FPk3G6N6xAelYQI+Hu6EuTnxtThbdkVm8qz82077YzvHcbka9vg4FD0F5XY5CwcRM55uECeNZ+9x9JoVs+LIycyWbTtKHf1aVLwS4pSqvxq+5hNdQEwxrBy73E6hvjh7+Va4viXfx7i3eX7+ePR/tTzrppxZuWVn2+Y9280g9o1KDMYNsYQcTydDYdO8I/9FZ+ew5wJtjFktcma/fE8O38HadkW/jPgknKft3LPcRZsiWFEp2AuaxGIY7HA4NVf95CUmcd7KyK4b0Az3F1O3zV7Ltbuj+fB7zeTlJmHo4PwyeqDbDuSgoht7cOHZm/GQeDaDkUDzlxLPq/8upv4tBwWbz8KwIR+lxQJOpIzc3lk7laSMnOZ+3+X0u/1lQB8e3dP+thb2wr7KyKBr/6K5KrW9dgRk8qEmZsAqOPhzMvXtSM5M483lu4lMiGD9BwL13/0F5+M7crlrU4FfSlZeVis+dTxcOHnzTG8sXQvx1Kz8fNw5kjSqWVjkjJyee23PQWBJkCfZv5c3rIe93wTzsC31/DCiHZc3aY+++PS+PdwEkG+7nx1Z3fu+HIjd38dzrTr23NTt1AWbY1l4vebcXYUnByEL8Z357+zNzP60/XMmXApjfxPBdfWfMPXf0UyN/wIXRvXwckeLDs7OvDjf3qzdn8C6w8m8teBRPo2C6CjvQVVBCZe0ZwbugTT2N+TtOw83J0dC84HCPRyxdvNiTv6NOHhq5qX2iIe5Hd+s9mdHR0KtoNsXt+bR67W8ZZKVQYNNi9Qmw8n0cDXjYa+Fbe0SHHZeVZW7T3ONW0bnLZr1BhT0BXWMdSPORN6cSA+nTYNfQrOi07KIjXbwv/+2M8r17WvtDqXVb/opCxC6riXeh/z/o3miXnb+DMigVt7NqZJgCd1PV3YfTSVfw6dYMOhRDZGJnHCvntIPW9Xejb15+8DCby+dC9zJvSqtK7jL/88xN5jaTwysAWBXq7sjE2lRX3vEl2Kf0Yk8PPmGK7vHMyll/iftj4bDtpa3Wb+HckdfcJwcz7TeL1Mvt1wmH8OnWBTVBLzt8QS7OfOfwZcUjC548+IBFbvi6dHWF3+iTxBpxeW8er17bm+S0iJ8tbsi+e7DYd5/5bORYKPlMw85m+JYVC7Bgjw98FEhncMKriXWeujmLJwJ1b7sjVXtqpHjyZ1eWnxbhwdhMHtGpCYnst/Z2/BQcTWdQvEp+Vw37eb2BiZVKQe22NS6NvcFkTuiEnh3lmbiE7KwtvNiUVbYwvy3fX1RhY/2I9LAr2KnP/0z9tpGuDJe2O6YMnPZ+uRFAK8XQjz98TN2ZFjKdm8uWwvP22OISkjl1xLPs/O38G1HRqyNy6NvcfSOJqSjYPYWikPxGfQMcSXd8d0Zt3+eN5bGcFXfx5i6c44/ok8gTXfMKR9A37dfgyw7UhzZev6/Pif3kz6aTv3fBPO4HYN2GjPO2V4W+p521os/zPrXx6ft4241Gx+3xVHaF13rmxVn5YNvLmsRSDf3t2LWz5fz5jP1jP33ksJ9nNnR0wKT/+8nW3RKfRvEcgr1xf9e+vt5syQ9g0LnjPY/q7V83blilb1eOTqFkXyFhda14MtkweW+KVFKVX7aDd6OVV3N3pmroVdsakFrWTZedYyg4CkjFx6vbqcYR2DePOmjgXp6w8m0jbIB283Z3Is1jIH/adm53H1W6vp1zyQ54a2KdGllJ9vEIE3l+3lg5UHWPFof5oW+4/2JGu+YdJP25gbHs1lLQJZsy+ejqF+bD2SzLCOQbx2Q3s8XJx4Yt5W5oZH4+ggLH2oH83qlWxhKE8349nacyyVF3/ZxZ8RiXwxvuRkiowcC71eXU5atqVIupODYLEHNaF13enZxJ8eTerSs0ldGtX1QET46s9DTF20i1l39SwIWk76KyKBp37aztNDWjGoXUPOxcq9x7njy40A+Lg50SHEj3URCUy7vj2jCy3bsm5/And+vZFci228XLN6Xozr1ZjruwSX+p/8dR/+yY6YFPKstvtbP+nKEt2UxhhSsvLYGJnEE/O2kpR5ah3aD2/twox1h9gUlcQvE/vSpqEPwz9YR1JGHt/f04vL3lhZkPeyFoF4ODvy36ua07qhDymZeVz19mri03JY+EAfOoT4kZFj4cs/D/HpmoOkZlvo3yKQtkE+fLjqAP+9sjkPXtmclxfv5os/D3F5y0AMsGpvPE8Masn43mH0fHk5aTkWnhjUktsuDWP8F/+w+UgyH9zSmWA/DybMDCcpM5fHBrbkpcW7C+r2xKCW3DegGT9uiubpn7dT19OFtkG+rNgTR5i/JyLw7pjO3DbjH3zcnfn5vt4F4/tSsvLo+Pwynh7SigmXld06PG7GBg7GZ5CZa6G+jxv7j6fjKEKzel60bOCNj5sTq/bF4+ggPHhFc4Z3DMLBQfj6r0imLLQNM29ez4tr2jZgYNv6BHq7cumrKwD46b7edGlUB7D93fl0zUHeWb6fXEs+b9/ckes6nwr0cy35PD5vKwu22ILoqcPaML5PkyJ13R6dwi2fr6eupwtXtqrP139HUsfDmcnD2jKsQ8Ny/0KVlJGLt5tTkV8klFK1n3ajXwBeW7KHmeujCH/2at5ctpcfwo/ww729Sx3YPzf8CDmWfPbFpRWk/bw5mofnbKVjiC8DWtbjg5UR3Hd5Mx66snmJcVDHUrKJS81h3qZo1uyL5+buofi6O+Pj5oy3mxNTF+2kdUMf/rGPO8u15hc532LNx8nRgRyLlYfnbOHX7cd48MrmPHxVc55ftIuv/ooEYNHWWCKOp/Pl+O5sj0kl2M+d1Kw8Hp+3je5hdYlPyyEhPYd2wb40quvBlAU7uaNvGI9e3bJEyx2UPvlkX1wa7s6OJcbVncjI5a3f9/LdhsN4uznj6CBsikri8pb1iE3JJsjXDRFh//F00rItNKrrweETmYT5e3B77zCOpmTTNsiH7mF1y+zKG9OzEZ+uOcjkBTv4+b4+BUH7+oOJ3PV1OFl5Vl5avJur2zQ469ab2OQsHpmzhVYNvJk+qiMv/rKLdRG2rfLSc2yB8b+HkziWks3Dc7bQNMCTL+/ozp8Ricz82xaovPbbHoZ1CGJg2/r0aRaAs6MDi7bGsj06hXGXNubLP21/TuO//If+LQI5lprNsZTsgp859uC1RX2vIsHmkPYN6ds8gP6vr+S13/ZwY9cQdsSk8taojjTy90AEjIEujfxIzcpje3Qyoz5J4Ivx3fnp32gS022LYa/dn8A/h07w0aoDJGbkclXrejSq68kXfx4iwZ7nneX7Wbn3ONuiU7ijTxjPDGnNmv3xrNobz4AW9fBwcWJYpyC+23CYSwK98HJ14qs7ezDm0/XcO+tfXJ0cCPByZd69vWkX7Fsk2Pw3KonJC3bwzd9RXNrUn/du6cyxlGz+2B3HwYQM/ndzJ9oG+fLxuK7c8tl67v/uX766owfOjg5EJ9nHc9YpezwnwA1dQnhozhYA3rypI10a1SlXIDayUzCuTg70aFK3yC96J58LQKsGp35hc3Z04P7LmzGkfUMWbIkpMSnJxcmBt0d1oqGvO7/vOsb1XUu2OLcP8eXrO3sw7vMNfPHnIcb0COWpQa3PenzjyWWDlFIXD23ZLKfqbNlMy86j1yvLyci1MrhdA5bssHWTXdGqHl8U22vXmm8Y8OZKjpzIwtPFka1TBrL/eDo3fPQXwX7uHErIwJJvaFbPi4jj6TQN8OSGriHc0CWkoPXq38NJXP/hXzx+TUuW7jzG9pgUTvc1WfLffrRu6IPFms83f0fx1u/7GNaxIZm5VhZsieXZoa25u19TwDY798aP/mZHbAof3NKFh+dswdFByMy18sEtXTiaksVLi3fj6uRAoLcr3m7O7D6aCthaEI+cyKJdsA//u7kzzeoVbU297Yt/WLMvnndGd2JEp2ByLfm0eNa2hn/ktKGArQVn5voo3vljHxm5Vsb1asxDVzVn1Cd/E1LHg3bBvry7fD+XNvXn8UEtiUrM4OE5W3nu2ja8+MsuGvq68fekK8v9Z/fPoROM/XwDXRr78c2dPdkancztX/xDsJ87t13amOcW7OTTcV25snV9vtsQRXhUEr/tOEaOJR8R2xpdIoIADg5CpxA/Wjf05q8DicQmZ7FoYl+aBnphjGF7TAojPviTiVc0p1vjOtxmXxamRX0vvr+nV5GxsluPJDNzfRRLdxwjLceCu7MjdT1diEnOolUDbz67rRt1PV3YcCiR+7/djDXfUN/XlQY+bjTwdaeBjyv1fdwI8nNnQMtA+kxbQVJmHoPaNuDjcV0B+HztQV5avBsfNyeC63iweGJfHByEhPQcPF2cCsZsRidlctuMf4hJziLHks+Ey5qybOcxIhNtAVvfZgE8OrAFnRvVIc+az6D/reFAfAauTg5cEujF3rg0pg5vyzh7lz3YJtKcLD/ieDqTftrGx2O7FjyDh+ds4efNMXQI8eXL8d0L0h//YSs/bIqmf4tAVu+LB2DCZU154pqWBQHgiPfXkZSZx4pH+xek/RB+hMfnbWNcr8YMbteA15buZeuRZH57qB+tGpQ9Az4z10L3l/7A1dmRDU9fed4t9ydbVOHUd76i7YtLIzvPSocQv0opXylVO52uZVODzXKqqmDTGMPfBxLpGlanoJu7cJcZwFWt69ExxI/pv+/jl4l9Cwa45+cbfvw3msfnbaNf8wDW7k/A2VGw5hvqerqw+MF+7DmWxtHkLG7uHsrCrbF8u/4w/0SewEGgX/NAbuoWgoeLI3d+Fc4P915K97C65Ocb0nMtpGblkZZtYdh767DkG/w9XUjMyOXXB/uRY7HyzM872HU0leb1vNh/PB2AoR0allh+5HhaNlsOJzOwbQNW7T3OvbM28X+XXcLD9jFcWblW3JwdEBGMMXy0+gA7Y1N588aOrN0fz5M/biMrz8pz17bhlh6NEBG2R6cw7P11Bde4b8AlxKXm8OO/tiVWHrm6BfW8Xfl0zUEOJmRwWYtAnhvamub2BZgfmr2ZX3ccI9eST59m/uw5mkaifQwmwNYpA+n4/DIevqoF/72q+Vn9mZ5sVe7cyI99x9Kob5/ZW9fDhf5vrKJRXQ9Gdg7iyR+3E+TrRvP63gR4uRLs54bB1gpoMOTk5bMuIoGYpCzq+bgyaXBrrmpTtNt/4NurcXdxIvpEJokZufRqWpf3xnQpsUTOSbmWfDYcSuT3XXEcSsjg1p6NGNimQZHW7lxLPs6Octpu0tjkLDJzrUV+AcjOs3LFm6uITcnmmzt7cFmLwDLPT0jP4Y4vN5KRa2HxxH7MXB/J2v0J3DegGZdeUnTP3TX74rnti38I9HZl6UOXEZ+WQ8sGZzexY274EZ6Yt42/nrqiSMu0xZrP0ZRs/jl0gqkLd/LqDe1LTCY6npZNfj4lhha8+utuPllzELDN3n746haM6hbKmczdeAQXp1O74ZyPzFwLbSYvBSov2FRKqdJosFkBqirYXLEnjju/CqdRXQ8mDW7FNW0bcNXbq/F2cyYuJRtHB2Hxg7YWoj7TVtDnkgAeGdiC+ZtjWLAllpjkLJoEeLJoYl+W7jhGRHw6zo4OjO3ZiHo+pc/yjkzIYN6maH78N7pgQgLA6scvL3VZl7CnFgPw1OBWTFuyhwEtba1A9bxdmTKsra1l57e9fLz6AP1bBPL1nT1Oe8+nG39amrjUbB77YStr9ydwVev6PHZNC95ato+/DybyxyP9+d8f+/n+n8MADG7XgL1xaRxKyMAY2wLNz17bmstb1isSPH265gCv/LqHvs0C+PKO7uRa8vnyz0O8tyKCVg19WHB/H7LzrLg4OpQYdlAeV0xfxcH4DJrV8+Lbu3tS3/5n8fHqA0xbsoe6ni6E1nFn/v19zmsy0WM/bGXepmg8XBxZ+ECfUse+VqWNkScIj0wq16z2/HxDrjW/XN+F+77dRExyNgvu73POdcvPN2X+WRpjMIaz+rO25hveXLaXQC9XbunZ6Ky+0xXFYs2n2TNLuKFLCNNHdTzzCUopVUE02KwAVRVsTl+2lw9XHaCZvXuwZX1v9sal8fbNHWkW6I2fh3NBAPjWsr28u8K2ELGjg9C3WQAjOwcxsE2Dc1of0Zpv+DMigRV7jjOgZSADCq27V9jJYPPTcV2ZMHMTDgLjezfh4aubF0w4McYwa8NhOgT7Fix3UpHy8w1f/HmI13/bWzBmdOIVzXh0YEuMMXywMoKMXCtPXNMSESEjx0JUYibN6nmVOt4zJjmLz9Yc5JGBLYosb2Sx5iMi5z0jdv3BRA4lZHB9l+AiE7OSM22TubLz8vnyju5F1jo8F9//c5hJP23nfzd3qpCWsprKYs3Hkm+qJaCr6ZIycvFxd9ZZ3EqpKqXBZgWoqmBz/Jf/cCwlm18m9mVO+BGmL9uHi6MDq58YUGL2eEpWHi8s2kX7YB+Gdggqs6u0oq3eF09adh79mgUy/fe9jOoWWtCVX9WOnMjk38NJxKflMKZHowpdhLyqvLVsL7uPpfHpuK7nvURSrsW2SHX7kOr581BKKXVx0mCzAlRVsDnpp+34ujvz1GDb7iUZORZyLPnU1RmcSimllKqhdOmjWuTVYgsje7o64Vk1DZZKKaWUUhVOV9VVSimllFKVRoNNpZRSSilVaTTYVEoppZRSlUaDTaWUUkopVWk02FRKKaWUUpVGg02llFJKKVVpNNhUSimllFKVRhd1LycRiQeiqrseQACQUN2VqMH0+ZyZPqPT0+dzZvqMTk+fz+np8zmz2viMGhtjAks7oMFmLSMi4WWt0K/0+ZSHPqPT0+dzZvqMTk+fz+np8zmzC+0ZaTe6UkoppZSqNBpsKqWUUkqpSqPBZu3zaXVXoIbT53Nm+oxOT5/PmekzOj19Pqenz+fMLqhnpGM2lVJKKaVUpdGWTaWUUkopVWk02KwlRORFEdkmIltEZJmIBNnTRUTeFZEI+/Eu1V3X6iAib4jIHvsz+FlE/OzpYSKSZX9uW0Tk42quarUo6/nYj02yf3/2isg11VjNaiUiN4nIThHJF5FuhdL1O0TZz8d+TL9DxYjIVBGJKfS9GVLddaoJRGSQ/XsSISJPVXd9ahoRiRSR7fbvTHh116eiaLBZe7xhjOlgjOkE/AJMtqcPBprbXxOAj6qnetXud6CdMaYDsA+YVOjYAWNMJ/vr3uqpXrUr9fmISBtgNNAWGAR8KCKO1VbL6rUDuB5YU8ox/Q6V8Xz0O3Rabxf63vxa3ZWpbvbvxQfY/t9qA4yxf39UUZfbvzO69JGqWsaY1EIfPYGTg21HAN8Ym/WAn4g0rPIKVjNjzDJjjMX+cT0QUp31qWlO83xGALONMTnGmENABNCjOupY3Ywxu40xe6u7HjXVaZ6PfodUefUAIowxB40xucBsbN8fdYHTYLMWEZGXReQIcCunWjaDgSOFskXb0y5mdwJLCn1uIiKbRWS1iPSrrkrVIIWfj35/yke/Q2XT71DZHrAPXflCROpUd2VqAP2unJkBlonIJhGZUN2VqShO1V0BdYqI/AE0KOXQM8aYBcaYZ4BnRGQS8AAwpUorWM3O9HzseZ4BLMC39mNHgUbGmEQR6QrMF5G2xVqKLwjn+HwuKuV5RqXQ79Dpn89F63TPC9uQphexBQ8vAtOx/aKn1On0NcbEiEg94HcR2WOMKW1oT62iwWYNYoy5qpxZvwV+xRZsxgChhY6F2NMuOGd6PiIyHrgWuNLY1/QyxuQAOfb3m0TkANACuGAGXp90Ls+Hi+j7A2f1d6zwOfodOr2L6jtUWHmfl4h8hm2s/cXuov2ulJcxJsb+87iI/Ixt6EGtDza1G72WEJHmhT6OAPbY3y8EbrPPSu8FpBhjjlZ5BauZiAwCngCGG2MyC6UHnpysICJNsU2kOlg9taw+ZT0fbN+f0SLiKiJNsD2ff6qjjjWVfofOSL9DpSg2dv46bBOsLnYbgeYi0kREXLBNLFtYzXWqMUTEU0S8T74HBnKBfG+0ZbP2mCYiLYF8IAo4OSP2V2AItkH5mcAd1VO9avc+4Iqt2wFgvX3W8GXACyKSh+3Z3WuMOVF91aw2pT4fY8xOEZkL7MLWvX6/McZajfWsNiJyHfAeEAgsFpEtxphr0O8QUPbz0e9QmV4XkU7YutEjgf+r1trUAMYYi4g8ACwFHIEvjDE7q7laNUl94Gf7v9FOwHfGmN+qt0oVQ3cQUkoppZRSlUa70ZVSSimlVKXRYFMppZRSSlUaDTaVUkoppVSl0WBTKaWUUkpVGg02lVJKKaVUpdFgUymlyiAiH4vIc9Vdj5NEJFJEzmXh9QpnX390j4i4lzP/RBF5rbLrpZSqeTTYVEpdtOzBW5aIpItIkogsFpGCHU7sa5G+WIHXG22/phRLdxKR4yJy7VmUNVVEZlVU3c7BU8BXxpgse1D+TfEMItJRRHJEpC7wGXCrfRs+pdRFRINNpdTFbpgxxgtoCMRhW7i8sswH/ID+xdIHYVv8u1Ys4CwirsDtwMlg92vgevuuJ4WNA34xxpwwxmQDS4Dbqq6mSqmaQINNpZQC7MHQPKDNyTQR+UpEXrK/ryMiv4hIvL0V9BcRCSmUd7yIHBSRNBE5JCK3lnGNuZQMuG7DtluIRUSGi8hOEUkWkVUi0rp4OfbtR58Gbra3ym61p98hIrvtdTgoIv9X7LwnROSoiMSKyN0iYkSkmf2Yq4i8KSKHRSTO3lpZVhd5TyDZGBNtv6+/se1xfUOhazkCtwCFWzxXAUPLKFMpdYHSYFMppQAR8QBuBtaXkcUB+BJoDDQCsrBtA3pyH+N3gcHGGG+gN7CljHK+Bm48GciJiC8wDPhaRFoA3wMPYdsW8ldgkX0f6QL2LexeAeYYY7yMMR3th44D1wI+2LaufVtEutivMwh4BLgKaAYMKFavaUALoJP9eDAwuYx7aA/sLZb2DUWD6KsAZ/s9nLQb6IhS6qKiwaZS6mI3X0SSgRTgauCN0jIZYxKNMT8aYzKNMWnAyxTtDs8H2omIuzHmaFl7Phtj/sTWXX+dPWkUsM8YswVbsLvYGPO7MSYPeBNwxxa8npExZrEx5oCxWQ0sA/oVus6XxpidxphMYOrJ8+xjSCcAD9u7vNOwBbOjy7iUH5BWLG0m0L9Qa+/J1tq8QnnSAN/y3ItS6sKhwaZS6mI30hjjB7gBDwCrRaRB8Uwi4iEin4hIlIikAmsAPxFxNMZkYAsU7wWO2icatTrNNQu3Ao7jVFdzEBB1MpMxJh84gq2V8YxEZLCIrBeRE/YAeggQUKjsI4WyF34fCHgAm+zd98nYxo8GlnGpJMC7cIIx5jC2ZzJWRLyAkRTtQsd+Tkp57kUpdeHQYFMppQBjjNUY8xNgBfqWkuVRoCXQ0xjjA1xmTxf7+UuNMVdjm2i0B9vs67LMBK4UkUuBXsC39vRYbN30toJtLY6h2MZDlqhy4Q/2STs/YmsNrW8PoH89WT/gKBBS6JTQQu8TsA0LaGuM8bO/fO0Tp0qzDVuXe3FfYwuebwAOGWM2FTveGthaRplKqQuUBptKKYUtsBOREUAdbGMLi/PGFpAl25fymVLo3PoiMsI+djMHSMfWrV4qY0wksA7b+MzfjTHH7IfmAkNF5EoRccYW4OYAf5VSTBwQJiIn/x13AVyBeMAiIoOBgYXyzwXuEJHW9vGpBeuH2ltQP8M2xrOe/Z6CReSaMm7hH2ytusVbXH/ENp71eWyBZ3H9sc1IV0pdRDTYVEpd7BaJSDqQim0c5u1ljLf8H7bxkwnYJhEVXqbIAdvkm1jgBLag6j9nuO7X2FoxC7qajTF7gbHYll9KwDZxaJgxJreU83+w/0wUkX/t4ywfxBZUJmGbCb6wUNlLsE1iWglEcGoiVI7955Mn0+3DBP7A1pJbgr0+X9nrWjg9A1vAGcKp1loARMQNW7d+aUGoUuoCJsaYM+dSSil1QbEvqbQDcDXGWM7h/EBgLdDZGJNVjvwTgVBjzBNnXVmlVK2mwaZSSl0kROQ6bOM4PbC1MOYbY0ZWa6WUUhc87UZXSqmLx/9hW4vzALaJUGfq6ldKqfOmLZtKKaWUUqrSaMumUkoppZSqNDUm2BSRQSKyV0QiROSpUo67isgc+/ENIhJmT/cXkZX2/YHfL5TfW0S2FHoliMj/7MfG2/c3Pnns7qq6T6WUUkqpi4lTdVcAQEQcgQ+wbRUXDWwUkYXGmF2Fst0FJBljmonIaOA1bDt2ZGNbL66d/QWAfRmQToWusQn4qVB5c4wxD5S3jgEBASYsLOws70wppaqO1WrlfIZGJScnA+Dn53fOZYgIjo6O53y+UqoWsOYABsQBd2crc8bvp9EDeckWq6lTWvYaEWwCPYAIY8xBABGZDYwACgebIzi1l+884H0REfu6butEpFlZhYtIC6AetmU6zklYWBjh4eHnerpSSlW6hIQEXF1dz/n8uXPnAjBq1KhzLiMnJ4eAgIAzZ1RK1U65KZARCS5+ts87XoIDu3B1KnWnM6DmdKMHU3Sf3mhK7gVckMe+JlwK4F/O8kdja8ks/Cv/DSKyTUTmiUhoaSeJyAQRCReR8Pj4+HJeSimllFLqApRvgcxocLLvZJu8HQ58AWG3nPa0mhJsVrbR2LaFO2kREGaM6QD8Thk7WhhjPjXGdDPGdAsMDKyCaiqllFJK1VDZ8YABBydb4LnlKXD1hzZPnva0mhJsxgCFWxdD7Gml5hERJ8AXSDxTwSLSEXAyxmw6mWaMSTTGnNyi7XOg67lXXSmllFLqAmfJgpzjp1o1D8yAlJ3Q4Xlw9j3tqTUl2NwINBeRJiLigq0lcmGxPAuB2+3vbwRWmPKNhB9D0VZNRKRhoY/Dgd3nVGullFJKqQudMZAZA45uIALpB2HPW9Dgamg4+Iyn14gJQsYYi4g8ACwFHIEvjDE7ReQFINwYsxCYAcwUkQjgBLaAFAARiQR8ABcRGQkMLDSTfRQwpNglHxSR4YDFXtb486l/amoqx48fJy8v73yKUbWcs7Mz9erVw8fHp7qropRSSlWc3GSwZoCLH/O3JdJk90QaOzlzW/gd3OmRwsj2fqc9vUYEmwDGmF+x7dlbOG1yoffZwE1lnBt2mnKblpI2CZh0rnUtLDU1lbi4OIKDg3F3d0dEKqJYVcsYY8jKyiImxjb6QwNOpZRSF4T8PMiKBmdv5m9PZtffnzCywU4eOfww25J9mLS4zEnoBWpKN3qtdfz4cYKDg/Hw8NBA8yImInh4eBAcHMzx48eruzpKKaVUxcg8CjiAOPLd2s08XO9rVqR246fkKwDIyjO8sTLutEVosHme8vLycHd3r+5qqBrC3d1dh1MopZS6MOSlQV4SOHuByedh37fIM448HfMAcKqBLTbl9P/vabBZAbRFU52k3wWllFIXhHwrZB4BJ0/b58hvudRrOy8fvYtjeUU3bgjycSTHQpkRpwabSimllFKqqOzjYKzM35nB9R+sIX3zK/yZ3ok5JwYWyebuJDx+RUOs+VjLKkqDTaWUUkopdYolE3Limb/HyqTF0Tzk+zaC4ckjExGEOu6OCBDs48Srg/0Z2aPtaYvTYPMCt27dOnr37o2vry9169alT58+bNy4sbqrVapVq1bh4OCAl5cXXl5ehISEMGrUqLOq79SpUxk7dmwl1lIppZS6gJl825aUjm68sfI4I7x/4zLvzbx67A6i8+pjAA8XBw4925Y//9PAFmg6nH5xIw02q9H8zTH0mbaCJk8tps+0FczffOblA85Gamoq1157LRMnTuTEiRPExMQwZcoUXF1dK/Q6FSkoKIj09HTS0tJYv349rVq1ol+/fixfvry6q6aUUkpd+LITwJoDjq44Z0XxXMPPWZfWkW8TTy3eHpuSZ5s85FrPNnnoDDTYrCbzN8cw6aftxCRnYYCY5Cwm/bS9QgPOffv2ATBmzBgcHR1xd3dn4MCBdOjQAYDGjRuzaZNtF89vv/0WEWHnzp0AzJgxg5EjRwKQn5/PtGnTuOSSS/D392fUqFGcOHGi4Drr16+nd+/e+Pn50bFjR1atWlVwbMCAAUyaNIkePXrg4+PDiBEjipxbFhEhJCSEF154gbvvvpsnnzy17+p///tfQkND8fHxoWvXrqxduxaA3377jVdeeYU5c+bg5eVFx44dAfjyyy9p3bo13t7eNG3alE8++eQcn6hSSil1AbNmQ/YxWwCZb+Hdxm9hMY48Fv0wplDI6OfuYNtNyL1+uYqtMYu6XyieX7STXbGpZ8y3+XAyudb8ImlZeVaemLeN7/85fNpz2wT5MGXY6cdHALRo0QJHR0duv/12Ro8eTa9evahTp07B8f79+7Nq1Sq6du3K6tWradq0KWvWrKFt27asXr2a/v37A/Dee+8xf/58Vq9eTWBgIA8++CD3338/33//PTExMQwdOpSZM2cyaNAgli9fzg033MCePXsIDAwE4JtvvmHp0qU0adKE2267jQcffJBZs2adsf4nXX/99Xz44YdkZGTg6elJ9+7dmTx5Mr6+vrzzzjvcdNNNREZGMmjQIJ5++mkiIiKKlF+vXj1++eWXgvsbPHgw3bt3p0uXLuWug1JKKXVBM/mQEQ2OriAOsO8DOrjvYWLU4yVmnxtjwDPUlq8ctGWzmhQPNM+Ufi58fHxYt24dIsI999xDYGAgw4cPJy7Otvhq//79Wb16NQBr165l0qRJBZ8LB5sff/wxL7/8MiEhIbi6ujJ16lTmzZuHxWJh1qxZDBkyhCFDhuDg4MDVV19Nt27d+PXXU5tBjRs3jnbt2uHp6cmLL77I3LlzsVrLnLRWQlBQEMYYkpOTARg7diz+/v44OTnx6KOPkpOTw969e8s8f+jQoVxyySWICP3792fgwIEFraFKKaWUArITIT/L1mKZtA32vsOCpP4sSulfImtKtrHlKydt2axg5WlxBOgzbQUxyVkl0oP93Jnzf5dWWH1at27NV199BcCePXsYO3YsDz30EN9//z39+/fnscce4+jRo1itVkaNGsXzzz9PZGQkKSkpdOrUCYCoqCiuu+46HBxO/W7i6OhIXFwcUVFR/PDDDyxatKjgWF5eHpdffnnB59DQ0IL3jRs3Ji8vj4SEBOrXL1/ze0xMDCKCn58fAG+++SYzZswgNjYWESE1NZWEhIQyz1+yZAnPP/88+/btIz8/n8zMTNq3b1+uayullFIXPGs2ZB8FZ2+wZMG/D4NrIB+lTyw1e5Df2W1moy2b1eTxa1ri7uxYJM3d2ZHHr2lZadds1aoV48ePZ8eOHQA0a9YMDw8P3nvvPS677DJ8fHxo0KABn376KX379i0ILkNDQ1myZAnJyckFr+zsbIKDgwkNDWXcuHFFjmVkZPDUU08VXPfIkSMF7w8fPoyzszMBAUWb5E/n559/pkuXLnh6erJ27Vpef/115s6dS1JSEsnJyfj6+tqa9Cm5qHpOTg433HADjz32GHFxcSQnJzNkyJCC/Bczq9WKu7s727dvL3HslltuYfz48VVfqWIGDBiAm5tbwQoFLVue+e/H7Nmzad26NZ6enlxyySVFWrFPlnPy5ejoyMSJpf9jejZOnDjBddddh6enJ40bN+a777474zn79+/Hzc2txOoJ5b3nQYMGMXny5BLpixcvplmzZlgslnO7GaXUxaV49/muaZB+ALq8yb39m+HuXPT/VXdnh7OOVTTYrCYjOwfz6vXtCfZzt61V5efOq9e3Z2Tn4Aq7xp49e5g+fTrR0dGALej7/vvv6dWrV0Ge/v378/777xd0mQ8YMKDIZ4B7772XZ555hqioKADi4+NZsGABYOvSXrRoEUuXLsVqtZKdnc2qVasKrgkwa9Ysdu3aRWZmJpMnT+bGG2/E0bFooF2cMYaYmBief/55Pv/8c1555RUA0tLScHJyIjAwEIvFwgsvvEBq6qkxsvXr1ycyMpL8fNtwhNzcXHJycggMDMTJyYklS5awbNmyc36mFxJHR0datWrFrl27iqSHh4ezaNGigmde3d5//33S09NJT08/7XAJgN9//50nn3ySL7/8krS0NNasWUPTpk0Ljp8sJz09nWPHjuHu7s5NN9102jKnTp3K1KlTT5vn/vvvx8XFhbi4OL799lv+85//FEy2O9053bt3L/VYee759ttvZ9asWSV+cZo9ezajRo3CyUk7rpRS5ZCdcKr7/PhqOPQ1NL0TAvswsr0frw4NLtiYMtjXlVev73DWsUqNCTZFZJCI7BWRCBF5qpTjriIyx358g4iE2dP9RWSliKSLyPvFzlllL3OL/VXvdGVVtZGdg/nzqSs4NG0ofz51RYUGmgDe3t5s2LCBnj174unpSa9evWjXrh3Tp08vyNO/f3/S0tK47LLLSv0Mttnfw4cPZ+DAgXh7e9OrVy82bNgA2Fo9FyxYwCuvvEJgYCChoaG88cYbBcEe2MZsjh8/ngYNGpCdnc27775bZp1jY2MLWnS6d+/O9u3bWbVqFQMH2nYsuOaaaxg0aBAtWrSgcePGuLm5FemmPxk4+Pv706VLF7y9vXn33XcZNWoUderU4bvvvmP48OEV8HQvDO3atSsRbD722GM8+uijBAUFVVOtzt2UKVOYPHkyvXr1wsHBgeDgYIKDS/979eOPP1KvXj369et3XtfMyMjgxx9/5MUXX8TLy4u+ffsyfPhwZs6cWeY5s2fPxs/PjyuvvPKcrzty5EgSExOLtNwmJyfz22+/MWbMmHMuVyl1EbFk2WafO3lBbhL8+zh4N4c2TxRkuaK5NwaYdHUof0666txiFWNMtb8AR+AA0BRwAbYCbYrluQ/42P5+NDDH/t4T6AvcC7xf7JxVQLdSrldqWad7de3a1ZRm165dpaYrm/79+5vPPvusuqtRpWrTd+LVV181N9xwQ8HnhQsXmqCgIJORkVHmOUOHDjW+vr6lvoYOHVqh9evfv78JCAgw/v7+pnfv3mblypVl5rVYLMbZ2dm8+uqr5pJLLjHBwcHm/vvvN5mZmaXmv/zyy82UKVPOWIcpU6acNt+///5r3N3di6S98cYb5tprry01f0pKimnevLk5cuSImTJlirn11luLHD+be7777rvNXXfdVfD5zTffNO3btzepqann9Pr888/N559/fs7np6ammvj4+DM+U6VUDZBvNSZ5jzEpe4xJO2TMH1ca872LMTGLjUmPLHjt3POvafzkL2bx1pjTFgeEmzJiqJrSstkDiDDGHDTG5AKzgRHF8owAvra/nwdcKSJijMkwxqwDss/ieqWWde7VV6p2KtyyabVaeeqpp3j55Zfx8PAAIC4ujn79+jF06NCCc3755ZciY3QLv3755ZcKrd9rr73GwYMHiYmJYcKECQwbNowDBw6UmjcuLo68vDzmzZvH2rVr2bJlC5s3b+all14qkTcqKorVq1dz++23l1rWtddei5+fH35+fkybNo1p06YVfL722muL5E1PT8fHx6dImq+vL2lpaaWW/dxzz3HXXXcREhJy3vd8++23M2/ePLKzbf/8zZkzR1s1lVLlkxUH+bm27vODX0Lccmj7NPiemug8f2s8Y2cfA2DKol3nvBZ4TQk2g4EjhT5H29NKzWOMsQApgH85yv7S3oX+XKGAslxlicgEEQkXkfD4+PizuR+laoW2bduyf/9+8vLymDFjBq6u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xJaYEORnt/HSyK70bFGfBz78nR+2+J6gfLKoMy2bp4onF29kU2K5Se/lrN2TRoHLXSott9DFQx/9wZzf9lR4boeYcJ4Y0LHSa7Rt2xa73c6YMWMYOXIk5557LpGRRzZLuvjii1m2bBlnn30233//PS1btuSHH36gY8eOfP/991x88cUAvPzyyyxcuJDvv/+e6Oho7r77bu644w7mzJlDQkIC/fv3Z+bMmfTt25dvvvmGa665hr/++ouiSVUzZsxgyZIltGjRghtuuIG7776b999/v9L6F7n66qt59dVXyc7OJiQkhB49ejBhwgTq1avHSy+9xLBhw9i1axd9+/blkUceYdu2baXKb9iwIZ9++mnx/V155ZX06NGDbt26VbkOSimlVHXLzneSmlNIXGTp2eeBDjtvjunOiP/+wu3vr2b2refSJT6idipZDbRls5aUDTQrSz8W4eHhrFixAhHh1ltvJTo6moEDB5KUlARYweb3338PwPLlyxk/fnzx95LB5uuvv86UKVOIi4sjICCAiRMn8tFHH+F0Onn//ffp168f/fr1w2azcfnll9O9e3c+//zIiIjrr7+eM888k5CQECZNmsS8efOOarelmJgYjDGkpaUBMHr0aBo0aICfnx/3338/+fn5bN682ef5/fv3p1WrVogIF198MX369CluDVVKKaVqS4JnPc2ywSZAeKCD927qQVRoADe+8xvbDmad6OpVG23ZrGZVaXEEuOCZb4t/yEqKjQjig7+fV231OeOMM3j33XcB+Ouvvxg9ejT33nsvc+bM4eKLL+aBBx5g//79uFwuhg8fzpNPPsmuXbtIT0+nS5cuAOzevZshQ4aUWnfSbreTlJTE7t27+fDDD1m8eHHxscLCQi655JLi7/HxR1amatasGYWFhSQnJ9OoUdXW0k9ISEBEiIiIAOC5557j7bffJjExEREhIyOD5ORkn+d/8cUXPPnkk2zZsgW3201OTg6dOnWq0rWVUkqpmpKQ6jvYBGgYFsjMm8/hmtd+5oa3f2X+/51Pk3on3xqc2rJZSx68oh1BDnuptCCHnQevaFdj12zfvj1jx45lw4YNALRu3Zrg4GBefvllLrroIsLDw2ncuDFvvPEGF154YXFwGR8fzxdffEFaWlrxKy8vj9jYWOLj47n++utLHcvOzmbcuHHF192798gGT3v27MHhcBAVFVXlei9YsIBu3boREhLC8uXLmTZtGvPmzSM1NZW0tDTq1auHtQoW5XZxys/P55prruGBBx4gKSmJtLQ0+vXrV5xfKaWUqi37UnMAiicIedOsQQjv3tiDzDwng1/5kfOe/oYW4z7jgme+rdZ5HjVJg81aMrhrLE9f3YnYiCAEq0Xz6as7Vets9L/++ovnn3+effv2AVbQN2fOHM4999ziPBdffDGvvPJKcZd57969S30HuP3223n00UfZvXs3AIcOHeKTT6ylSUePHs3ixYtZsmQJLpeLvLw8li1bVnxNgPfff59NmzaRk5PDhAkTGDp0KHZ76UC7rKLZ6E8++SRvvfUWU6dOBSAzMxM/Pz+io6NxOp089dRTZGQcGSPbqFEjdu3ahdttDUcoKCggPz+f6Oho/Pz8+OKLL1i6dOkxP1N1/FwuF0FBQaxfv77csVGjRjF27NgTX6ky+vXrR3R0NE2aNKFJkyYVju8tylP0ioiI4IEHHig+vnnzZq666iri4uLo3LlzqV6A45GSksKoUaNo3LgxHTt2ZN68eRXmr0o9tm3bRnR0NLfccovPcoYMGcLkyZPLpX/22We0bt0ap9N59Dej1GlqX1ou/nYb0aEVrxJzZmw9bji/GUmZ+exPz6uxicU1RYPNWjS4ayw/jvsbO5/pz4/j/latgSZAWFgYv/76Kz179iQkJIRzzz2XM888k+eff744z8UXX0xmZiYXXXSR1+9gzf4eOHAgffr0ISwsjHPPPZdff7W2mY+Pj+eTTz5h6tSpREdHEx8fz/Tp04uDPbDGbI4dO5bGjRuTl5fHv//9b591TkxMLF5ns0ePHqxfv55ly5bRp08fAK644gr69u1L27ZtadasGYGBgaW66YcNs1bHatCgAd26dSMsLIx///vfDB8+nMjISGbPns3AgQO9XludGHa7nfbt27Np06ZS6atWrWLx4sXF/7Gobc899xz79+9n//79rFmzxme+ojz79+9n69atBAUFMWTIEACcTicjR46kb9++7N69m3//+9/ceuutbN26tcJrT506tdLncP/99+Pv78+2bdt46623uO+++/jzzz+95q1qPe6///5KJ86NGjWKefPmlesdmDt3LsOHD8fPT0dnKVVV+1JziYkIxGbzulJjKQvXJpZLyy10MX2J7zkLdYVod2LVdO/e3axatapc+p9//skZZ5xRCzU6OfTu3ZvRo0dX2FJSl+mfb824/vrradmyJU8++WRxWu/evenduzcTJ048IXVITk72ueZsv379GDFiBGPGjPF63JdZs2bx7LPP8vvvvyMibNq0iUsvvbR4fDHAoEGD6N69O48//rjPcooCzUceecTr8ezsbJo2bcovv/xCmzZtALj11luJiYkp9UyLVKUeH330EYsXL6Zdu3bs2LGDt956y+u1c3NzadOmDR988AEXXHABAKmpqbRt25Zvv/32qMdDF7XIDh8+/KjOU9UvPz//qIY4qeM3+D8/EhJgZ9Yt51aat8W4z/AWsQmw85n+1V63oyUiq40x3b0d05ZNpdQJ17Fjx+I1XQEWL17M1q1beeihh3yec9VVVxEREeH1ddVVV1V7HSdOnEjz5s25/PLLq7x6wZw5cxg5cmS5scNl+WqBrKpt27bh5+dXHGgCdOrU6ajLLcqfkZHBlClTqtSqXNRyO2fOnOK0BQsW0LZtW514p9RR2peaS1yE7/GaJcVEeJ8Y5Cu9LtFgUyl1wp155pnF3egul4tx48YxZcoUgoOtf3STkpLo1asX/fsf+d/6p59+WmoiWsnXp59+Wq31e/LJJ/njjz/YvHkzY8eOZcSIEezYsaPCc/bs2cOKFSsYNWpUcVqbNm2Ijo7mpZdeorCwkG+++YYVK1aQk5NT7vxhw4YRHx9PfHw8L774Ii+++GLx96LhIUWys7MJCwsrlRYeHk5WlvelUSqrx+TJk7nhhhuIja3aUJ5Ro0bxySefkJeXB1hB9rXXXlulc5VSlrxCF8lZ+cT6mIleVm1MLK4uOrhG1aiSuwkpVaRjx45s3bqVwsJC3nnnHQICArjhhhuKj8+ZM4d77rmHoUOHVsv1evfuXbyGbFnnnntuuUljPXr0KP583XXX8dFHH7F06VJuv/12n9eYO3cu5513Hs2bNy9OczgczJ49mwcffJAXX3yRrl27MmTIEK/d9x9++GHx58q60UNCQsjMzCyVlpmZSWhoqNf8FdXjjz/+YNmyZaxYscLnvZV13nnnUb9+fT799FO6devG6tWrmTVrVpXPV0pVvMamN0XzOp798i/2p+cRHujHU4POrPb5HjVBg02l1AnXvHlzAgICWLt2LU888QRz5swpXmpr+fLlTJkyhbZt2xIYGFjcRX7llVf67M7u1asXX3zxhc/reftPT0VjNssSkUqXy5ozZw733XdfufQzzzyzVN0uu+yyUq2fx6Jo1ve2bdto3bo1AOvXr69wfLGveixfvpw9e/bQoUMHwGo1dblc9OrVq8LhA9deey1z5sxh69atXHrppTRs2PC47kmp082+4jU2q9aNDlbAObhrLD2nfs2FraNPikATNNhUStUCEaFDhw7cfvvt9OzZk969excf69WrFx06dOC7774rtZFARcFkdUpLS2PVqlVceOGF+Pn5MX/+fH766SeeffZZn+f8+uuv7N+/n8GDB5c7tmHDBlq3bo3b7eatt94iKSmJ6667rsI6+GrRLBISEsKAAQOYMmUKr7zyCuvXr+fzzz/nq6++8nmOr3q4XK5SLcj//ve/2bNnDy+++GKFdbj22muZPn06Gzdu5Omnn64wr1KqvKIF3avajV5Sq+hQth86eXYU0jGbSqlaceaZZ7JhwwamT59eKt3lciEipQLNE8npdDJp0iRatmxJixYt+O9//8vs2bNLTca5+uqree6554q/z549mwEDBpQbRwlW93rbtm1p1aoVy5YtY+HChV5bVK+++upya3YWva6++upy+V944QXy8vJo1aoVN910Ey+88EKpls2ydfRVj+DgYBo1alT8CgkJISAgoNJZyc2aNaNnz57k5OTQr1+/ih+qUqqcfak5+NmERmFV62EpqXXDULYfzDppNijRpY+qSJc+Oj3pn++J9+eff/Liiy/yxhtv1Oh1jqYbXdUcXfqo7tClj06se+auZfXuVFY8/LejPve9n3bxxKKN/PbIpTQMD6yB2h09XfpIKXXS+P333+ncuXNtV0MppWrUvtTcKk8OKqt1Q2sy4LaDJ0dXep0JNkWkr4hsFpFtIjLOy/EAEfnAc/xXEWle4th4T/pmEbmiRPr/ROSgiGwoU9ZEEUkQkXWel/YBldGxY8cTMpN88+bNdOnSpXinn5py++23M2nSpBorX1WfkSNHcscdd9R2NZRSqkbtS80htoprbJbVKtoKNk+WcZt1ItgUETvwH+BKoANwrYh0KJPtZiDVGNMaeBF41nNuB2Ak0BHoC7zqKQ/gXU+aNy8aY7p4Xp9X5/3UJc2bNycoKIjQ0FAaNWrE2LFjfa7FV9LGjRtLTdqo7Bpff/31MdVv2rRpXHLJJWRmZnL33XcfUxklTZw4EYfDUbzlZWhoKNOmTeP1118v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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "figwidth, figheight = plt.rcParams[\"figure.figsize\"]\n", "figheight = 2.0 * figheight\n", @@ -525,4 +425,4 @@ }, "nbformat": 4, "nbformat_minor": 4 -} +} \ No newline at end of file From 135308b77a4bc3913fcaaf292e865a9d3870f565 Mon Sep 17 00:00:00 2001 From: Erik Date: Wed, 18 May 2022 19:39:43 -0700 Subject: [PATCH 257/521] appease grumpy black --- .../analysis/swept_langmuir/floating_potential.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/plasmapy/analysis/swept_langmuir/floating_potential.py b/plasmapy/analysis/swept_langmuir/floating_potential.py index 64e0018ff4..951db6ee51 100644 --- a/plasmapy/analysis/swept_langmuir/floating_potential.py +++ b/plasmapy/analysis/swept_langmuir/floating_potential.py @@ -20,6 +20,7 @@ class VFExtras(NamedTuple): Create a `tuple` containing the extra parameters calculated by `find_floating_potential`. """ + vf_err: Optional[float] """ Alias for field number 0, the error in the calculated floating @@ -264,7 +265,11 @@ def find_floating_potential( # do islands fall within the min_points window? isl_window = ( - np.abs(np.r_[rtn_extras["islands"][-1]][-1] - np.r_[rtn_extras["islands"][0]][0]) + 1 + np.abs( + np.r_[rtn_extras["islands"][-1]][-1] + - np.r_[rtn_extras["islands"][0]][0] + ) + + 1 ) if isl_window > min_points: warn( @@ -318,8 +323,8 @@ def find_floating_potential( ) # Perform Linear Regression Fit - volt_sub = voltage[istart: istop + 1] - curr_sub = current[istart: istop + 1] + volt_sub = voltage[istart : istop + 1] + curr_sub = current[istart : istop + 1] fit_func.curve_fit(volt_sub, curr_sub) vf, rtn_extras["vf_err"] = fit_func.root_solve() From 7d0e2753a291353be77d2b3582a5b26047057243 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 19 May 2022 02:42:35 +0000 Subject: [PATCH 258/521] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- .../analysis/swept_langmuir/find_floating_potential.ipynb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb b/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb index 6595948746..50fff3734b 100644 --- a/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb +++ b/docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb @@ -313,7 +313,7 @@ "for ii, label, rtn in zip([1, 2], [\"Exponential\", \"Linear\"], [results, results_lin]):\n", " vf = rtn[0]\n", " extras = rtn[1]\n", - " \n", + "\n", " # calc island points\n", " isl_pts = np.array([], dtype=np.int64)\n", " for isl in extras.islands:\n", @@ -425,4 +425,4 @@ }, "nbformat": 4, "nbformat_minor": 4 -} \ No newline at end of file +} From b5d0c138da3cac93d4c1bd673dc02710a3695e94 Mon Sep 17 00:00:00 2001 From: Erik Everson Date: Thu, 19 May 2022 10:18:25 -0700 Subject: [PATCH 259/521] Apply suggestions from code review Co-authored-by: Nick Murphy --- changelog/1469.feature.rst | 2 +- plasmapy/analysis/swept_langmuir/ion_saturation_current.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/changelog/1469.feature.rst b/changelog/1469.feature.rst index be6ebbfb10..7039c5c137 100644 --- a/changelog/1469.feature.rst +++ b/changelog/1469.feature.rst @@ -1,4 +1,4 @@ Added -`~plamsapy.analysis.swept_langmuir.ion_saturation_current.find_ion_saturation_current` +`~plasmapy.analysis.swept_langmuir.ion_saturation_current.find_ion_saturation_current` to the `~plasmapy.analysis.swept_langmuir` module to fit and return the ion-saturation current of a swept Langmuir probe trace. diff --git a/plasmapy/analysis/swept_langmuir/ion_saturation_current.py b/plasmapy/analysis/swept_langmuir/ion_saturation_current.py index 079d28820c..187739fecc 100644 --- a/plasmapy/analysis/swept_langmuir/ion_saturation_current.py +++ b/plasmapy/analysis/swept_langmuir/ion_saturation_current.py @@ -104,7 +104,7 @@ def find_ion_saturation_current( | - Can not be used with keyword ``voltage_bound``. + Cannot be used with keyword ``voltage_bound``. voltage_bound: `float` A bias voltage (in volts) that specifies an upper bound used to From 3cc421d6e5b60e2fb4e89b037c6ecf07fce3bb06 Mon Sep 17 00:00:00 2001 From: Erik Everson Date: Thu, 19 May 2022 15:21:44 -0700 Subject: [PATCH 260/521] Apply suggestions from code review Co-authored-by: Nick Murphy --- plasmapy/analysis/swept_langmuir/ion_saturation_current.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plasmapy/analysis/swept_langmuir/ion_saturation_current.py b/plasmapy/analysis/swept_langmuir/ion_saturation_current.py index 187739fecc..cd028b8882 100644 --- a/plasmapy/analysis/swept_langmuir/ion_saturation_current.py +++ b/plasmapy/analysis/swept_langmuir/ion_saturation_current.py @@ -45,8 +45,8 @@ def find_ion_saturation_current( current: np.ndarray, *, fit_type: str = "exp_plus_linear", - current_bound: float = None, - voltage_bound: float = None, + current_bound: numbers.Real = None, + voltage_bound: numbers.Real = None, ) -> Tuple[ffuncs.Linear, ISatExtras]: """ Determines the ion-saturation current (:math:`I_{sat}`) for a given @@ -114,7 +114,7 @@ def find_ion_saturation_current( | - Can not be used with keyword ``current_bound``. + Cannot be used with keyword ``current_bound``. Returns ------- From 84015a19c48643b5d3a574019836c07b14fd3dfb Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 9 Jun 2025 17:46:46 -0700 Subject: [PATCH 261/521] add argument allow_unsorted to check_sweep --- .../analysis/swept_langmuir/helpers.py | 34 ++++++++++++------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/src/plasmapy/analysis/swept_langmuir/helpers.py b/src/plasmapy/analysis/swept_langmuir/helpers.py index 54f5edf46d..22d329506e 100644 --- a/src/plasmapy/analysis/swept_langmuir/helpers.py +++ b/src/plasmapy/analysis/swept_langmuir/helpers.py @@ -10,28 +10,36 @@ def check_sweep( # noqa: C901, PLR0912 voltage: np.ndarray, current: np.ndarray, strip_units: bool = True, + allow_unsorted: bool = False, ) -> tuple[np.ndarray, np.ndarray]: """ - Function for checking that the voltage and current arrays are properly - formatted for analysis by `plasmapy.analysis.swept_langmuir`. + Function for checking that the voltage and current arrays are + properly formatted for analysis by + `plasmapy.analysis.swept_langmuir`. Parameters ---------- voltage: `numpy.ndarray` - 1D `numpy.ndarray` representing the voltage of the swept Langmuir trace. - Voltage should be monotonically increasing. *No units are assumed or - checked, but values should be in volts.* + 1D `numpy.ndarray` representing the voltage of the swept + Langmuir trace. Voltage should be monotonically increasing. + *No units are assumed or checked, but values should be in + volts.* current: `numpy.ndarray` - 1D `numpy.ndarray` representing the current of the swept Langmuir trace. - Values should start from a negative ion-saturation current and increase - to a positive electron-saturation current. *No units are assumed or - checked, but values should be in amperes.* + 1D `numpy.ndarray` representing the current of the swept + Langmuir trace. Values should start from a negative + ion-saturation current and increase to a positive + electron-saturation current. *No units are assumed or checked, + but values should be in amperes.* strip_units: `bool` - (Default: `True`) If `True`, then the units on ``voltage`` and/or - ``current`` will be stripped if either are passed in as an Astropy - `~astropy.units.Quantity`. + (Default: `True`) If `True`, then the units on ``voltage`` + and/or ``current`` will be stripped if either are passed in as + an Astropy `~astropy.units.Quantity`. + + allow_unsorted: `bool` + (Default: `False`) If `True`, then the supplied ``voltage`` + array must be monotonically increasing. Returns ------- @@ -93,7 +101,7 @@ def check_sweep( # noqa: C901, PLR0912 f"Expected 1D numpy array for voltage, but got array with " f"{voltage.ndim} dimensions.", ) - elif not np.all(np.diff(voltage) >= 0): + elif not np.all(np.diff(voltage) >= 0) and not allow_unsorted: raise ValueError("The voltage array is not monotonically increasing.") if isinstance(voltage, u.Quantity) and strip_units: From aa50427879a8f697e8969faf5c497ed318e11383 Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 9 Jun 2025 17:49:13 -0700 Subject: [PATCH 262/521] rough out helper function sort_sweep_arrays --- .../analysis/swept_langmuir/__init__.py | 6 ++++- .../analysis/swept_langmuir/helpers.py | 26 ++++++++++++++++++- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/src/plasmapy/analysis/swept_langmuir/__init__.py b/src/plasmapy/analysis/swept_langmuir/__init__.py index 2c65d8359e..8561ae8c8f 100644 --- a/src/plasmapy/analysis/swept_langmuir/__init__.py +++ b/src/plasmapy/analysis/swept_langmuir/__init__.py @@ -7,6 +7,7 @@ "check_sweep", "find_floating_potential", "find_ion_saturation_current", + "sort_sweep_arrays", "ISatExtras", "VFExtras", ] @@ -17,7 +18,10 @@ find_floating_potential, find_vf_, ) -from plasmapy.analysis.swept_langmuir.helpers import check_sweep +from plasmapy.analysis.swept_langmuir.helpers import ( + check_sweep, + sort_sweep_arrays, +) from plasmapy.analysis.swept_langmuir.ion_saturation_current import ( ISatExtras, find_ion_saturation_current, diff --git a/src/plasmapy/analysis/swept_langmuir/helpers.py b/src/plasmapy/analysis/swept_langmuir/helpers.py index 22d329506e..c2e2feae9c 100644 --- a/src/plasmapy/analysis/swept_langmuir/helpers.py +++ b/src/plasmapy/analysis/swept_langmuir/helpers.py @@ -1,10 +1,12 @@ """Helper functions for analyzing swept Langmuir traces.""" -__all__ = ["check_sweep"] +__all__ = ["check_sweep", "sort_sweep_arrays"] import astropy.units as u import numpy as np +from typing import Literal + def check_sweep( # noqa: C901, PLR0912 voltage: np.ndarray, @@ -153,3 +155,25 @@ def check_sweep( # noqa: C901, PLR0912 current = current.value return voltage, current + + +def sort_sweep_arrays( + voltage: np.ndarray, + current: np.ndarray, + voltage_order: Literal["ascending", "descending"] = "ascending", +) -> tuple[np.ndarray, np.ndarray]: + if voltage_order not in ["ascending", "descending"]: + raise ValueError() + + voltage, current = check_sweep( + voltage, current, strip_units=True, allow_unsorted=True + ) + + index_sort = np.argsort(voltage) + if voltage_order == "descending": + index_sort = index_sort[::-1] + + voltage = voltage[index_sort] + current = current[index_sort] + + return voltage, current From a3094ad9e378e9dc28186c6e6cf691334ac01f80 Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 9 Jun 2025 17:50:09 -0700 Subject: [PATCH 263/521] add a lint E402 ignore for swept_langmuir/__init__.py --- pyproject.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/pyproject.toml b/pyproject.toml index 77843ccda4..19c8363d81 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -326,6 +326,7 @@ lint.per-file-ignores."docs/notebooks/plasma/grids_nonuniform.ipynb" = [ "NPY002 lint.per-file-ignores."setup.py" = [ "D100" ] lint.per-file-ignores."src/plasmapy/analysis/fit_functions.py" = [ "D301" ] +lint.per-file-ignores."src/plasmapy/analysis/swept_langmuir/__init__.py" = [ "E402" ] lint.per-file-ignores."src/plasmapy/formulary/braginskii.py" = [ "C901", "RET503", "RET504" ] lint.per-file-ignores."src/plasmapy/plasma/sources/*.py" = [ "D102" ] lint.per-file-ignores."src/plasmapy/utils/_pytest_helpers/pytest_helpers.py" = [ "BLE001", "PLR", "SLF001" ] From 4242fe6b77f4cf28030ad5c51be192075d5df9bd Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 9 Jun 2025 17:50:38 -0700 Subject: [PATCH 264/521] move full construction of the __all__ dunder to the top of the file --- src/plasmapy/analysis/swept_langmuir/__init__.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/plasmapy/analysis/swept_langmuir/__init__.py b/src/plasmapy/analysis/swept_langmuir/__init__.py index 8561ae8c8f..387fd40008 100644 --- a/src/plasmapy/analysis/swept_langmuir/__init__.py +++ b/src/plasmapy/analysis/swept_langmuir/__init__.py @@ -12,6 +12,7 @@ "VFExtras", ] __aliases__ = ["find_isat_", "find_vf_"] +__all__ += __aliases__ from plasmapy.analysis.swept_langmuir.floating_potential import ( VFExtras, @@ -27,5 +28,3 @@ find_ion_saturation_current, find_isat_, ) - -__all__ += __aliases__ From 8805ca59eb63278b13785ddd652b652a88888633 Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 9 Jun 2025 19:22:47 -0700 Subject: [PATCH 265/521] rough out a merge_voltage_clusters() helper func --- .../analysis/swept_langmuir/__init__.py | 2 + .../analysis/swept_langmuir/helpers.py | 97 ++++++++++++++++++- 2 files changed, 98 insertions(+), 1 deletion(-) diff --git a/src/plasmapy/analysis/swept_langmuir/__init__.py b/src/plasmapy/analysis/swept_langmuir/__init__.py index 387fd40008..3da6d9bacb 100644 --- a/src/plasmapy/analysis/swept_langmuir/__init__.py +++ b/src/plasmapy/analysis/swept_langmuir/__init__.py @@ -7,6 +7,7 @@ "check_sweep", "find_floating_potential", "find_ion_saturation_current", + "merge_voltage_clusters", "sort_sweep_arrays", "ISatExtras", "VFExtras", @@ -21,6 +22,7 @@ ) from plasmapy.analysis.swept_langmuir.helpers import ( check_sweep, + merge_voltage_clusters, sort_sweep_arrays, ) from plasmapy.analysis.swept_langmuir.ion_saturation_current import ( diff --git a/src/plasmapy/analysis/swept_langmuir/helpers.py b/src/plasmapy/analysis/swept_langmuir/helpers.py index c2e2feae9c..f83ac47e54 100644 --- a/src/plasmapy/analysis/swept_langmuir/helpers.py +++ b/src/plasmapy/analysis/swept_langmuir/helpers.py @@ -1,6 +1,6 @@ """Helper functions for analyzing swept Langmuir traces.""" -__all__ = ["check_sweep", "sort_sweep_arrays"] +__all__ = ["check_sweep", "merge_voltage_clusters", "sort_sweep_arrays"] import astropy.units as u import numpy as np @@ -177,3 +177,98 @@ def sort_sweep_arrays( current = current[index_sort] return voltage, current + + +def merge_voltage_clusters( + voltage: np.ndarray, + current: np.ndarray, + voltage_step_size: float = None, + force_regular_grid: bool = False, +): + # step_size = 0 (only merge identical voltages) + # None : calculate steps size as average of array step sizes + + voltage, current = check_sweep(voltage, current) + + if not isinstance(force_regular_grid, bool): + raise TypeError( + "Expected 'force_regular_grid' to be a bool, but got type " + f"{type(force_regular_grid)}." + ) + + if voltage_step_size is None: + voltage_step_size = np.abs(np.average(np.diff(voltage))) + elif voltage_step_size == 0: + voltage_step_size = 0.0 + elif not isinstance(voltage_step_size, float): + raise TypeError( + "Expected 'voltage_step_size' to be a float or None, got type " + f"{type(voltage_step_size)}." + ) + elif voltage_step_size < 0: + voltage_step_size = -voltage_step_size + + voltage_ascending = bool(np.all(np.diff(voltage) >= 0)) + if not voltage_ascending: + voltage, current = sort_sweep_arrays(voltage, current, voltage_order="ascending") + + # now merge clusters + new_voltage = np.unique(voltage) + if voltage_step_size == 0 and new_voltage.size == voltage.size: + new_current = current.copy() + elif voltage_step_size == 0: + new_current = np.empty_like(new_voltage, dtype=current.dtype) + + for ii in range(new_voltage.size): + mask = voltage == new_voltage[ii] + if np.count_nonzero(mask) == 1: + new_current[ii] = current[mask] + else: + new_current[ii] = np.average(current[mask]) + else: + new_voltage = np.empty_like(voltage, dtype=voltage.dtype) + new_voltage[...] = np.nan + new_current = np.empty_like(current, dtype=current.dtype) + new_current[...] = np.nan + + start_voltage = voltage[0] + stop_voltage = start_voltage + voltage_step_size + + ii = 0 + while start_voltage <= voltage[-1]: + mask1 = voltage >= start_voltage + mask2 = voltage < stop_voltage + mask = np.logical_and(mask1, mask2) + + if np.count_nonzero(mask) > 0: + new_voltage[ii] = ( + start_voltage + 0.5 * voltage_step_size if force_regular_grid + else np.average(voltage[mask]) + ) + new_current[ii] = np.average(current[mask]) + + ii += 1 + + start_voltage = stop_voltage + stop_voltage = start_voltage + voltage_step_size + + # filter out NaN values + new_voltage = new_voltage[:ii] + new_current = new_current[:ii] + + # force regular spacing + if force_regular_grid: + # Need to fill array with NaN values to force the regular spacing + ... + + if not voltage_ascending: + voltage, current = sort_sweep_arrays(voltage, current, voltage_order="descending") + new_voltage, new_current = sort_sweep_arrays( + new_voltage, new_current, voltage_order="descending" + ) + else: + new_voltage, new_current = sort_sweep_arrays( + new_voltage, new_current, voltage_order="ascending" + ) + + return new_voltage, new_current From 289dbcc5d24658203eb94c6694a1c6d05a2f7d74 Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 12 Jun 2025 11:29:51 -0700 Subject: [PATCH 266/521] fix error string --- src/plasmapy/analysis/swept_langmuir/helpers.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plasmapy/analysis/swept_langmuir/helpers.py b/src/plasmapy/analysis/swept_langmuir/helpers.py index f83ac47e54..ac5010ff97 100644 --- a/src/plasmapy/analysis/swept_langmuir/helpers.py +++ b/src/plasmapy/analysis/swept_langmuir/helpers.py @@ -141,8 +141,8 @@ def check_sweep( # noqa: C901, PLR0912 ) elif current[0] > 0.0 or current[-1] < 0.0: raise ValueError( - "The current array needs to start from a negative ion-saturation current" - " to a positive electron-saturation current." + "The current array needs to start from a negative ion-saturation " + "current to a positive electron-saturation current." ) if voltage.size != current.size: From 95cbbee74d29a36df504c2298e551015dbb3d788 Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 12 Jun 2025 11:30:29 -0700 Subject: [PATCH 267/521] too much to explain --- .../analysis/swept_langmuir/helpers.py | 188 ++++++++++++++---- 1 file changed, 145 insertions(+), 43 deletions(-) diff --git a/src/plasmapy/analysis/swept_langmuir/helpers.py b/src/plasmapy/analysis/swept_langmuir/helpers.py index ac5010ff97..675cdfbbfb 100644 --- a/src/plasmapy/analysis/swept_langmuir/helpers.py +++ b/src/plasmapy/analysis/swept_langmuir/helpers.py @@ -179,61 +179,164 @@ def sort_sweep_arrays( return voltage, current -def merge_voltage_clusters( +def _nan_stuff_regular_grid( voltage: np.ndarray, current: np.ndarray, - voltage_step_size: float = None, - force_regular_grid: bool = False, -): - # step_size = 0 (only merge identical voltages) - # None : calculate steps size as average of array step sizes + voltage_step_size: float, +) -> tuple[np.ndarray, np.ndarray]: + size = int(np.round((voltage[-1] - voltage[0]) / voltage_step_size)) + 1 + reg_voltage = np.linspace(voltage[0], voltage[-1], num=size, dtype=voltage.dtype) - voltage, current = check_sweep(voltage, current) + _, reg_indices, new_indices = np.intersect1d( + np.round(reg_voltage, decimals=5), + np.round(voltage, decimals=5), + return_indices=True, + ) + mask = np.ones_like(reg_voltage, dtype=bool) + mask[reg_indices] = False + reg_voltage[mask] = np.nan + + reg_current = np.full(size, np.nan, dtype=current.dtype) + reg_current[np.logical_not(mask)] = current[...] - if not isinstance(force_regular_grid, bool): + return reg_voltage, reg_current + + +def merge_voltage_clusters( + voltage: np.ndarray, + current: np.ndarray, + voltage_step_size: float = None, + force_regular_spacing: bool = False, +) -> tuple[np.ndarray, np.ndarray]: + # condition force_regular_grid + if not isinstance(force_regular_spacing, bool): raise TypeError( - "Expected 'force_regular_grid' to be a bool, but got type " - f"{type(force_regular_grid)}." + "Expected 'force_regular_spacing' to be a bool, but got type " + f"{type(force_regular_spacing)}." ) - if voltage_step_size is None: - voltage_step_size = np.abs(np.average(np.diff(voltage))) - elif voltage_step_size == 0: - voltage_step_size = 0.0 - elif not isinstance(voltage_step_size, float): + # condition voltage_step_size + if ( + voltage_step_size is not None + and not isinstance(voltage_step_size, (float, np.floating, int, np.integer)) + ): raise TypeError( "Expected 'voltage_step_size' to be a float or None, got type " f"{type(voltage_step_size)}." ) + elif isinstance(voltage_step_size, (int, np.integer)): + voltage_step_size = float(voltage_step_size) + + voltage, current = check_sweep(voltage, current) + + # check if grid is regularly spaced + voltage_diff = np.diff(voltage) + mask_zero_diff = np.isclose(voltage_diff, 0.0) + if np.count_nonzero(mask_zero_diff) > 0: + is_regular_grid = False + elif np.allclose(voltage_diff, voltage_diff[0]): + # grid is already regularly spaced + is_regular_grid = True + elif np.allclose( + np.rint(voltage_diff / np.min(voltage_diff)) + - voltage_diff / np.min(voltage_diff), + 0, + ): + # grid has a common dV, but at times jumps N * dV times + if force_regular_spacing and (voltage_step_size is None or voltage_step_size == 0): + # need to stuff with NaN values + voltage, current = _nan_stuff_regular_grid( + voltage=voltage, + current=current, + voltage_step_size=np.min(voltage_diff), + ) + is_regular_grid = True + else: + is_regular_grid = False + + # return if voltage is already regularly spaced and no voltage merging is + # requested + if is_regular_grid and (voltage_step_size is None or voltage_step_size == 0): + return voltage.copy(), current.copy() + + # condition voltage_step_size ... Round 2 + if voltage_step_size is None: + voltage_step_size = np.abs( + np.average(voltage_diff[np.logical_not(mask_zero_diff)]) + ) + elif voltage_step_size == 0: + voltage_step_size = 0.0 elif voltage_step_size < 0: voltage_step_size = -voltage_step_size - voltage_ascending = bool(np.all(np.diff(voltage) >= 0)) + # ensure voltage is ascending for calculation + voltage_ascending = bool(np.all(voltage_diff >= 0)) if not voltage_ascending: voltage, current = sort_sweep_arrays(voltage, current, voltage_order="ascending") # now merge clusters - new_voltage = np.unique(voltage) - if voltage_step_size == 0 and new_voltage.size == voltage.size: + voltage_diff = np.diff(voltage) + if voltage_step_size != 0 and np.all(voltage_diff >= voltage_step_size): + new_voltage = voltage.copy() new_current = current.copy() + + if force_regular_spacing: + size = int( + np.round((new_voltage[-1] - new_voltage[0]) / voltage_step_size) + ) + 1 + reg_voltage = np.linspace( + new_voltage[0], new_voltage[-1], num=size, dtype=new_voltage.dtype + ) + reg_current = np.interp(reg_voltage, new_voltage, new_current) + + new_voltage = reg_voltage + new_current = reg_current elif voltage_step_size == 0: - new_current = np.empty_like(new_voltage, dtype=current.dtype) + voltage_diff = np.diff(voltage) + mask_zero_diff = np.isclose(voltage_diff, 0.0) + mask_zero_diff = np.append(mask_zero_diff, [mask_zero_diff[-1]]) + + new_voltage = np.full(voltage.shape, np.nan, dtype=voltage.dtype) + new_current = np.full(current.shape, np.nan, dtype=current.dtype) + + mask = np.logical_not(mask_zero_diff) + new_voltage[mask] = voltage[mask] + new_current[mask] = current[mask] + + while np.any(mask_zero_diff): + volt = voltage[mask_zero_diff][0] + index = np.where(new_voltage == volt)[0] + if len(index) == 0: + index = np.where(mask_zero_diff)[0] + + index = index[0] + volt_mask = np.isclose(voltage, volt) + + new_voltage[index] = volt + new_current[index] = np.average(current[volt_mask]) + + mask_zero_diff[volt_mask] = False + + # remove nan entries + mask = np.logical_not(np.isnan(new_voltage)) + new_voltage = new_voltage[mask] + new_current = new_current[mask] + + if force_regular_spacing: + new_voltage, new_current = merge_voltage_clusters( + voltage=new_voltage, + current=new_current, + voltage_step_size=voltage_step_size, + ) - for ii in range(new_voltage.size): - mask = voltage == new_voltage[ii] - if np.count_nonzero(mask) == 1: - new_current[ii] = current[mask] - else: - new_current[ii] = np.average(current[mask]) else: - new_voltage = np.empty_like(voltage, dtype=voltage.dtype) - new_voltage[...] = np.nan - new_current = np.empty_like(current, dtype=current.dtype) - new_current[...] = np.nan + new_voltage = np.full(voltage.shape, np.nan, dtype=voltage.dtype) + new_current = np.full(current.shape, np.nan, dtype=current.dtype) start_voltage = voltage[0] stop_voltage = start_voltage + voltage_step_size + # populate ii = 0 while start_voltage <= voltage[-1]: mask1 = voltage >= start_voltage @@ -242,7 +345,7 @@ def merge_voltage_clusters( if np.count_nonzero(mask) > 0: new_voltage[ii] = ( - start_voltage + 0.5 * voltage_step_size if force_regular_grid + start_voltage + 0.5 * voltage_step_size if force_regular_spacing else np.average(voltage[mask]) ) new_current[ii] = np.average(current[mask]) @@ -250,25 +353,24 @@ def merge_voltage_clusters( ii += 1 start_voltage = stop_voltage - stop_voltage = start_voltage + voltage_step_size + stop_voltage += voltage_step_size - # filter out NaN values + # crop new arrays new_voltage = new_voltage[:ii] new_current = new_current[:ii] - # force regular spacing - if force_regular_grid: + if force_regular_spacing: # Need to fill array with NaN values to force the regular spacing - ... + new_voltage, new_current = _nan_stuff_regular_grid( + voltage=new_voltage, + current=new_current, + voltage_step_size=voltage_step_size, + ) if not voltage_ascending: - voltage, current = sort_sweep_arrays(voltage, current, voltage_order="descending") - new_voltage, new_current = sort_sweep_arrays( - new_voltage, new_current, voltage_order="descending" - ) - else: - new_voltage, new_current = sort_sweep_arrays( - new_voltage, new_current, voltage_order="ascending" - ) + voltage = voltage[::-1] + current = current[::-1] + new_voltage = new_voltage[::-1] + new_current = new_current[::-1] return new_voltage, new_current From 0368af3a887696ef356047508f017b56f820dfc4 Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 9 Jun 2025 17:46:46 -0700 Subject: [PATCH 268/521] add argument allow_unsorted to check_sweep --- .../analysis/swept_langmuir/helpers.py | 34 ++++++++++++------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/src/plasmapy/analysis/swept_langmuir/helpers.py b/src/plasmapy/analysis/swept_langmuir/helpers.py index 54f5edf46d..22d329506e 100644 --- a/src/plasmapy/analysis/swept_langmuir/helpers.py +++ b/src/plasmapy/analysis/swept_langmuir/helpers.py @@ -10,28 +10,36 @@ def check_sweep( # noqa: C901, PLR0912 voltage: np.ndarray, current: np.ndarray, strip_units: bool = True, + allow_unsorted: bool = False, ) -> tuple[np.ndarray, np.ndarray]: """ - Function for checking that the voltage and current arrays are properly - formatted for analysis by `plasmapy.analysis.swept_langmuir`. + Function for checking that the voltage and current arrays are + properly formatted for analysis by + `plasmapy.analysis.swept_langmuir`. Parameters ---------- voltage: `numpy.ndarray` - 1D `numpy.ndarray` representing the voltage of the swept Langmuir trace. - Voltage should be monotonically increasing. *No units are assumed or - checked, but values should be in volts.* + 1D `numpy.ndarray` representing the voltage of the swept + Langmuir trace. Voltage should be monotonically increasing. + *No units are assumed or checked, but values should be in + volts.* current: `numpy.ndarray` - 1D `numpy.ndarray` representing the current of the swept Langmuir trace. - Values should start from a negative ion-saturation current and increase - to a positive electron-saturation current. *No units are assumed or - checked, but values should be in amperes.* + 1D `numpy.ndarray` representing the current of the swept + Langmuir trace. Values should start from a negative + ion-saturation current and increase to a positive + electron-saturation current. *No units are assumed or checked, + but values should be in amperes.* strip_units: `bool` - (Default: `True`) If `True`, then the units on ``voltage`` and/or - ``current`` will be stripped if either are passed in as an Astropy - `~astropy.units.Quantity`. + (Default: `True`) If `True`, then the units on ``voltage`` + and/or ``current`` will be stripped if either are passed in as + an Astropy `~astropy.units.Quantity`. + + allow_unsorted: `bool` + (Default: `False`) If `True`, then the supplied ``voltage`` + array must be monotonically increasing. Returns ------- @@ -93,7 +101,7 @@ def check_sweep( # noqa: C901, PLR0912 f"Expected 1D numpy array for voltage, but got array with " f"{voltage.ndim} dimensions.", ) - elif not np.all(np.diff(voltage) >= 0): + elif not np.all(np.diff(voltage) >= 0) and not allow_unsorted: raise ValueError("The voltage array is not monotonically increasing.") if isinstance(voltage, u.Quantity) and strip_units: From 4e6ff2c92419329e7fc93be5a1ffb14fd19a4b8f Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 9 Jun 2025 17:49:13 -0700 Subject: [PATCH 269/521] rough out helper function sort_sweep_arrays --- .../analysis/swept_langmuir/__init__.py | 6 ++++- .../analysis/swept_langmuir/helpers.py | 26 ++++++++++++++++++- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/src/plasmapy/analysis/swept_langmuir/__init__.py b/src/plasmapy/analysis/swept_langmuir/__init__.py index 2c65d8359e..8561ae8c8f 100644 --- a/src/plasmapy/analysis/swept_langmuir/__init__.py +++ b/src/plasmapy/analysis/swept_langmuir/__init__.py @@ -7,6 +7,7 @@ "check_sweep", "find_floating_potential", "find_ion_saturation_current", + "sort_sweep_arrays", "ISatExtras", "VFExtras", ] @@ -17,7 +18,10 @@ find_floating_potential, find_vf_, ) -from plasmapy.analysis.swept_langmuir.helpers import check_sweep +from plasmapy.analysis.swept_langmuir.helpers import ( + check_sweep, + sort_sweep_arrays, +) from plasmapy.analysis.swept_langmuir.ion_saturation_current import ( ISatExtras, find_ion_saturation_current, diff --git a/src/plasmapy/analysis/swept_langmuir/helpers.py b/src/plasmapy/analysis/swept_langmuir/helpers.py index 22d329506e..c2e2feae9c 100644 --- a/src/plasmapy/analysis/swept_langmuir/helpers.py +++ b/src/plasmapy/analysis/swept_langmuir/helpers.py @@ -1,10 +1,12 @@ """Helper functions for analyzing swept Langmuir traces.""" -__all__ = ["check_sweep"] +__all__ = ["check_sweep", "sort_sweep_arrays"] import astropy.units as u import numpy as np +from typing import Literal + def check_sweep( # noqa: C901, PLR0912 voltage: np.ndarray, @@ -153,3 +155,25 @@ def check_sweep( # noqa: C901, PLR0912 current = current.value return voltage, current + + +def sort_sweep_arrays( + voltage: np.ndarray, + current: np.ndarray, + voltage_order: Literal["ascending", "descending"] = "ascending", +) -> tuple[np.ndarray, np.ndarray]: + if voltage_order not in ["ascending", "descending"]: + raise ValueError() + + voltage, current = check_sweep( + voltage, current, strip_units=True, allow_unsorted=True + ) + + index_sort = np.argsort(voltage) + if voltage_order == "descending": + index_sort = index_sort[::-1] + + voltage = voltage[index_sort] + current = current[index_sort] + + return voltage, current From 271d00deda25be30e2e9f34ced9d1aaab43d26b9 Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 9 Jun 2025 17:50:09 -0700 Subject: [PATCH 270/521] add a lint E402 ignore for swept_langmuir/__init__.py --- pyproject.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/pyproject.toml b/pyproject.toml index 77843ccda4..19c8363d81 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -326,6 +326,7 @@ lint.per-file-ignores."docs/notebooks/plasma/grids_nonuniform.ipynb" = [ "NPY002 lint.per-file-ignores."setup.py" = [ "D100" ] lint.per-file-ignores."src/plasmapy/analysis/fit_functions.py" = [ "D301" ] +lint.per-file-ignores."src/plasmapy/analysis/swept_langmuir/__init__.py" = [ "E402" ] lint.per-file-ignores."src/plasmapy/formulary/braginskii.py" = [ "C901", "RET503", "RET504" ] lint.per-file-ignores."src/plasmapy/plasma/sources/*.py" = [ "D102" ] lint.per-file-ignores."src/plasmapy/utils/_pytest_helpers/pytest_helpers.py" = [ "BLE001", "PLR", "SLF001" ] From 1bf8b15f7b235bd5299712514e9ec3d43790863e Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 9 Jun 2025 17:50:38 -0700 Subject: [PATCH 271/521] move full construction of the __all__ dunder to the top of the file --- src/plasmapy/analysis/swept_langmuir/__init__.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/plasmapy/analysis/swept_langmuir/__init__.py b/src/plasmapy/analysis/swept_langmuir/__init__.py index 8561ae8c8f..387fd40008 100644 --- a/src/plasmapy/analysis/swept_langmuir/__init__.py +++ b/src/plasmapy/analysis/swept_langmuir/__init__.py @@ -12,6 +12,7 @@ "VFExtras", ] __aliases__ = ["find_isat_", "find_vf_"] +__all__ += __aliases__ from plasmapy.analysis.swept_langmuir.floating_potential import ( VFExtras, @@ -27,5 +28,3 @@ find_ion_saturation_current, find_isat_, ) - -__all__ += __aliases__ From 984d7cdb57892318d2c737855dba1383561ea028 Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 12 Jun 2025 11:29:51 -0700 Subject: [PATCH 272/521] fix error string --- src/plasmapy/analysis/swept_langmuir/helpers.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plasmapy/analysis/swept_langmuir/helpers.py b/src/plasmapy/analysis/swept_langmuir/helpers.py index c2e2feae9c..d7cc0dac0c 100644 --- a/src/plasmapy/analysis/swept_langmuir/helpers.py +++ b/src/plasmapy/analysis/swept_langmuir/helpers.py @@ -141,8 +141,8 @@ def check_sweep( # noqa: C901, PLR0912 ) elif current[0] > 0.0 or current[-1] < 0.0: raise ValueError( - "The current array needs to start from a negative ion-saturation current" - " to a positive electron-saturation current." + "The current array needs to start from a negative ion-saturation " + "current to a positive electron-saturation current." ) if voltage.size != current.size: From c3ee9ff5677ae2c53e733c1a6e060c4cfc0d400b Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 12 Jun 2025 12:33:19 -0700 Subject: [PATCH 273/521] add messages to raised errors --- src/plasmapy/analysis/swept_langmuir/helpers.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/plasmapy/analysis/swept_langmuir/helpers.py b/src/plasmapy/analysis/swept_langmuir/helpers.py index d7cc0dac0c..a2985f41fe 100644 --- a/src/plasmapy/analysis/swept_langmuir/helpers.py +++ b/src/plasmapy/analysis/swept_langmuir/helpers.py @@ -162,8 +162,16 @@ def sort_sweep_arrays( current: np.ndarray, voltage_order: Literal["ascending", "descending"] = "ascending", ) -> tuple[np.ndarray, np.ndarray]: - if voltage_order not in ["ascending", "descending"]: - raise ValueError() + if not isinstance(voltage_order, str): + raise TypeError( + "Expected 'voltage_order' to be a string equal to 'ascending' " + f"or 'descending', but got type {type(voltage_order)}." + ) + elif voltage_order not in ["ascending", "descending"]: + raise ValueError( + "Expected 'voltage_order' to be a string equal to 'ascending' " + f"or 'descending', but got '{voltage_order}'." + ) voltage, current = check_sweep( voltage, current, strip_units=True, allow_unsorted=True From a8040167eb720a6efe7c660d58198cf64d3711a2 Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 12 Jun 2025 12:35:16 -0700 Subject: [PATCH 274/521] appease grumpy ruff --- src/plasmapy/analysis/swept_langmuir/helpers.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plasmapy/analysis/swept_langmuir/helpers.py b/src/plasmapy/analysis/swept_langmuir/helpers.py index a2985f41fe..4b8045ff24 100644 --- a/src/plasmapy/analysis/swept_langmuir/helpers.py +++ b/src/plasmapy/analysis/swept_langmuir/helpers.py @@ -2,11 +2,11 @@ __all__ = ["check_sweep", "sort_sweep_arrays"] +from typing import Literal + import astropy.units as u import numpy as np -from typing import Literal - def check_sweep( # noqa: C901, PLR0912 voltage: np.ndarray, From e6bbf798878d6d0f9ad29aa4fa793e7374ea7994 Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 12 Jun 2025 12:39:57 -0700 Subject: [PATCH 275/521] add docstring --- .../analysis/swept_langmuir/helpers.py | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/src/plasmapy/analysis/swept_langmuir/helpers.py b/src/plasmapy/analysis/swept_langmuir/helpers.py index 4b8045ff24..7ff26680cd 100644 --- a/src/plasmapy/analysis/swept_langmuir/helpers.py +++ b/src/plasmapy/analysis/swept_langmuir/helpers.py @@ -162,6 +162,37 @@ def sort_sweep_arrays( current: np.ndarray, voltage_order: Literal["ascending", "descending"] = "ascending", ) -> tuple[np.ndarray, np.ndarray]: + """ + Sort the swept langmuir ``voltage`` and ``current`` traces to + ensure the ``voltage`` array is either monotonically increasing or + decreasing. + + Parameters + ---------- + voltage: `numpy.ndarray` + 1D `numpy.ndarray` representing the voltage of the swept + Langmuir trace. *No units are assumed or checked, but values + should be in volts.* + + current: `numpy.ndarray` + 1D `numpy.ndarray` representing the current of the swept + Langmuir trace. Values should start from a negative + ion-saturation current and increase to a positive + electron-saturation current. *No units are assumed or checked, + but values should be in amperes.* + + voltage_order: `str` + Either 'ascending' or 'descending' to indicate how the + ``voltage`` array should be sorted. (DEFAULT: ``'ascending'``) + + Returns + ------- + voltage : `numpy.ndarray` + Sorted ``voltage`` array. + + current : `numpy.ndarray` + Matched ``current`` array to the sorted ``voltage`` array. + """ if not isinstance(voltage_order, str): raise TypeError( "Expected 'voltage_order' to be a string equal to 'ascending' " From fa733711c63e4c53ae522d0b4d6e15e3002958ec Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 12 Jun 2025 16:57:35 -0700 Subject: [PATCH 276/521] add test case for allow_unsort == True --- .../swept_langmuir/test_swept_langmuir_helpers.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/analysis/swept_langmuir/test_swept_langmuir_helpers.py b/tests/analysis/swept_langmuir/test_swept_langmuir_helpers.py index fb34917fff..fcce2a18b5 100644 --- a/tests/analysis/swept_langmuir/test_swept_langmuir_helpers.py +++ b/tests/analysis/swept_langmuir/test_swept_langmuir_helpers.py @@ -163,6 +163,14 @@ does_not_raise(), (np.linspace(-40.0, 40, 100), np.linspace(-10.0, 30, 100)), ), + # -- allow_unsorted == True -- + ( + 30.0 * np.random.rand(100) - 20.0, + np.linspace(-10.0, 30, 100), + {"allow_unsorted": True}, + does_not_raise(), + "expected same as inputs", + ), ], ) def test_check_sweep(voltage, current, kwargs, with_context, expected) -> None: From 7ed8c0561be5a8b144b4bb50fe21532a005a46ac Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 12 Jun 2025 17:49:51 -0700 Subject: [PATCH 277/521] use np.diff to decide if we can manually reorder arrays or need to use argsort --- .../analysis/swept_langmuir/helpers.py | 28 +++++++++++++++---- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/src/plasmapy/analysis/swept_langmuir/helpers.py b/src/plasmapy/analysis/swept_langmuir/helpers.py index 7ff26680cd..48b3395d87 100644 --- a/src/plasmapy/analysis/swept_langmuir/helpers.py +++ b/src/plasmapy/analysis/swept_langmuir/helpers.py @@ -208,11 +208,29 @@ def sort_sweep_arrays( voltage, current, strip_units=True, allow_unsorted=True ) - index_sort = np.argsort(voltage) - if voltage_order == "descending": - index_sort = index_sort[::-1] + # determine order + voltage_diff = np.diff(voltage) + if np.all(voltage_diff >= 0): + _order = "ascending" + elif np.all(voltage_diff <= 0): + _order = "descending" + else: + _order = None + + if _order == voltage_order: + # already ordered + return voltage, current - voltage = voltage[index_sort] - current = current[index_sort] + # perform sorting + if _order is None: + index_sort = np.argsort(voltage) + if voltage_order == "descending": + index_sort = index_sort[::-1] + + voltage = voltage[index_sort] + current = current[index_sort] + else: + voltage = voltage[::-1] + current = current[::-1] return voltage, current From 79feb5591989290fadef6f7361c6f3c417cf7b99 Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 12 Jun 2025 17:50:10 -0700 Subject: [PATCH 278/521] add value test cases for sort_sweep_arrays --- .../test_swept_langmuir_helpers.py | 92 ++++++++++++++++++- 1 file changed, 91 insertions(+), 1 deletion(-) diff --git a/tests/analysis/swept_langmuir/test_swept_langmuir_helpers.py b/tests/analysis/swept_langmuir/test_swept_langmuir_helpers.py index fcce2a18b5..3fd0a2d5ce 100644 --- a/tests/analysis/swept_langmuir/test_swept_langmuir_helpers.py +++ b/tests/analysis/swept_langmuir/test_swept_langmuir_helpers.py @@ -1,12 +1,13 @@ """Tests for `plasmapy.analysis.swept_langmuir.helpers`.""" from contextlib import nullcontext as does_not_raise +from unittest import mock import astropy.units as u import numpy as np import pytest -from plasmapy.analysis.swept_langmuir.helpers import check_sweep +from plasmapy.analysis.swept_langmuir.helpers import check_sweep, sort_sweep_arrays @pytest.mark.parametrize( @@ -188,3 +189,92 @@ def test_check_sweep(voltage, current, kwargs, with_context, expected) -> None: else: assert np.allclose(rtn_voltage, expected[0]) assert np.allclose(rtn_current, expected[1]) + + +@pytest.mark.parametrize( + ("voltage", "current", "kwargs", "with_context", "expected"), + [ + # raises + ( + np.linspace(-40.0, 40, 100), + np.linspace(-10.0, 30, 100), + {"voltage_order": 5.0}, # not a string + pytest.raises(TypeError), + None, + ), + ( + np.linspace(-40.0, 40, 100), + np.linspace(-10.0, 30, 100), + {"voltage_order": "wrong string"}, + pytest.raises(ValueError), + None, + ), + # values + ( + np.linspace(-40.0, 40, 100), + np.linspace(-10.0, 30, 100), + {"voltage_order": "ascending"}, + does_not_raise(), + None, + ), + ( + np.linspace(-40.0, 40, 100), + np.linspace(-10.0, 30, 100), + {"voltage_order": "descending"}, + does_not_raise(), + (np.linspace(40.0, -40, 100), np.linspace(30.0, -10, 100)), + ), + ( + np.linspace(40.0, -40, 100), + np.linspace(-10.0, 30, 100), + {"voltage_order": "descending"}, + does_not_raise(), + None, + ), + ( + np.linspace(40.0, -40, 100), + np.linspace(-10.0, 30, 100), + {"voltage_order": "ascending"}, + does_not_raise(), + (np.linspace(-40.0, 40, 100), np.linspace(30.0, -10, 100)), + ), + ( + np.array([-40.0, 20.0, -22.0, 40.0]), + np.array([-10.0, 10.0, -5.0, 30.0]), + {"voltage_order": "ascending"}, + does_not_raise(), + (np.array([-40.0, -22.0, 20.0, 40.0]), np.array([-10.0, -5.0, 10.0, 30.0])), + ), + ( + np.array([-40.0, 20.0, -22.0, 40.0]), + np.array([-10.0, 10.0, -5.0, 30.0]), + {"voltage_order": "descending"}, + does_not_raise(), + (np.array([40.0, 20.0, -22.0, -40.0]), np.array([30.0, 10.0, -5.0, -10.0])), + ), + ], +) +def test_sort_sweep_arrays(voltage, current, kwargs, with_context, expected) -> None: + with with_context, mock.patch( + "plasmapy.analysis.swept_langmuir.helpers.check_sweep", + wraps=check_sweep, + ) as mock_check_sweep: + rtn_voltage, rtn_current = sort_sweep_arrays( + voltage=voltage, + current=current, + **kwargs, + ) + + if expected is not None: + assert np.allclose(rtn_voltage, expected[0]) + assert np.allclose(rtn_current, expected[1]) + elif kwargs["voltage_order"] in ("ascending", "descending"): + ... + elif kwargs["voltage_order"] == "descending": + ... + else: + assert np.allclose(rtn_voltage, voltage) + assert np.allclose(rtn_current, current) + + mock_check_sweep.assert_called_once() + mock_check_sweep.reset_mock() From 4c210803f7c5b27fc9dec2c661686d6d0637f656 Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 12 Jun 2025 20:07:09 -0700 Subject: [PATCH 279/521] remove unused code --- tests/analysis/swept_langmuir/test_swept_langmuir_helpers.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tests/analysis/swept_langmuir/test_swept_langmuir_helpers.py b/tests/analysis/swept_langmuir/test_swept_langmuir_helpers.py index 3fd0a2d5ce..ca5aa7223f 100644 --- a/tests/analysis/swept_langmuir/test_swept_langmuir_helpers.py +++ b/tests/analysis/swept_langmuir/test_swept_langmuir_helpers.py @@ -268,10 +268,6 @@ def test_sort_sweep_arrays(voltage, current, kwargs, with_context, expected) -> if expected is not None: assert np.allclose(rtn_voltage, expected[0]) assert np.allclose(rtn_current, expected[1]) - elif kwargs["voltage_order"] in ("ascending", "descending"): - ... - elif kwargs["voltage_order"] == "descending": - ... else: assert np.allclose(rtn_voltage, voltage) assert np.allclose(rtn_current, current) From 45a61c5be8d066fcf2236841cf05c11755d39a66 Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 13 Jun 2025 09:16:09 -0700 Subject: [PATCH 280/521] use the newer numpy.random.Generator --- tests/analysis/swept_langmuir/test_swept_langmuir_helpers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/analysis/swept_langmuir/test_swept_langmuir_helpers.py b/tests/analysis/swept_langmuir/test_swept_langmuir_helpers.py index ca5aa7223f..1db38ad10e 100644 --- a/tests/analysis/swept_langmuir/test_swept_langmuir_helpers.py +++ b/tests/analysis/swept_langmuir/test_swept_langmuir_helpers.py @@ -166,7 +166,7 @@ ), # -- allow_unsorted == True -- ( - 30.0 * np.random.rand(100) - 20.0, + 30.0 * np.random.default_rng().random(100) - 20.0, np.linspace(-10.0, 30, 100), {"allow_unsorted": True}, does_not_raise(), From b5b76daabd122c8fd1036c5eab47f2914906f8e0 Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 13 Jun 2025 09:19:18 -0700 Subject: [PATCH 281/521] add change log --- changelog/3034.feature.rst | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 changelog/3034.feature.rst diff --git a/changelog/3034.feature.rst b/changelog/3034.feature.rst new file mode 100644 index 0000000000..34f84d391d --- /dev/null +++ b/changelog/3034.feature.rst @@ -0,0 +1,4 @@ +.. currentmodule:: plasmapy.analysis.swept_langmuir + +Added helper function `~helper.sort_sweep_arrays` to the +`~plasmapy.analysis.swept_analysis` module. From 58710bd68d440510d9d1915dd5517239e529f281 Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 13 Jun 2025 09:29:27 -0700 Subject: [PATCH 282/521] reformat with statement --- .../swept_langmuir/test_swept_langmuir_helpers.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/tests/analysis/swept_langmuir/test_swept_langmuir_helpers.py b/tests/analysis/swept_langmuir/test_swept_langmuir_helpers.py index 1db38ad10e..daab228c7b 100644 --- a/tests/analysis/swept_langmuir/test_swept_langmuir_helpers.py +++ b/tests/analysis/swept_langmuir/test_swept_langmuir_helpers.py @@ -255,10 +255,13 @@ def test_check_sweep(voltage, current, kwargs, with_context, expected) -> None: ], ) def test_sort_sweep_arrays(voltage, current, kwargs, with_context, expected) -> None: - with with_context, mock.patch( - "plasmapy.analysis.swept_langmuir.helpers.check_sweep", - wraps=check_sweep, - ) as mock_check_sweep: + with ( + with_context, + mock.patch( + "plasmapy.analysis.swept_langmuir.helpers.check_sweep", + wraps=check_sweep, + ) as mock_check_sweep, + ): rtn_voltage, rtn_current = sort_sweep_arrays( voltage=voltage, current=current, From ee7c4a2651530befba0156275778435a8d976f86 Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 13 Jun 2025 09:30:25 -0700 Subject: [PATCH 283/521] fix references --- changelog/3034.feature.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/changelog/3034.feature.rst b/changelog/3034.feature.rst index 34f84d391d..38f150ade6 100644 --- a/changelog/3034.feature.rst +++ b/changelog/3034.feature.rst @@ -1,4 +1,4 @@ .. currentmodule:: plasmapy.analysis.swept_langmuir -Added helper function `~helper.sort_sweep_arrays` to the -`~plasmapy.analysis.swept_analysis` module. +Added helper function `~helpers.sort_sweep_arrays` to the +`~plasmapy.analysis.swept_langmuir` module. From 18bb22bca53eb9f68c5901d8d9ede70db0bd485f Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 9 Jun 2025 19:22:47 -0700 Subject: [PATCH 284/521] rough out a merge_voltage_clusters() helper func --- .../analysis/swept_langmuir/__init__.py | 2 + .../analysis/swept_langmuir/helpers.py | 97 ++++++++++++++++++- 2 files changed, 98 insertions(+), 1 deletion(-) diff --git a/src/plasmapy/analysis/swept_langmuir/__init__.py b/src/plasmapy/analysis/swept_langmuir/__init__.py index 387fd40008..3da6d9bacb 100644 --- a/src/plasmapy/analysis/swept_langmuir/__init__.py +++ b/src/plasmapy/analysis/swept_langmuir/__init__.py @@ -7,6 +7,7 @@ "check_sweep", "find_floating_potential", "find_ion_saturation_current", + "merge_voltage_clusters", "sort_sweep_arrays", "ISatExtras", "VFExtras", @@ -21,6 +22,7 @@ ) from plasmapy.analysis.swept_langmuir.helpers import ( check_sweep, + merge_voltage_clusters, sort_sweep_arrays, ) from plasmapy.analysis.swept_langmuir.ion_saturation_current import ( diff --git a/src/plasmapy/analysis/swept_langmuir/helpers.py b/src/plasmapy/analysis/swept_langmuir/helpers.py index 48b3395d87..53da0e631d 100644 --- a/src/plasmapy/analysis/swept_langmuir/helpers.py +++ b/src/plasmapy/analysis/swept_langmuir/helpers.py @@ -1,6 +1,6 @@ """Helper functions for analyzing swept Langmuir traces.""" -__all__ = ["check_sweep", "sort_sweep_arrays"] +__all__ = ["check_sweep", "merge_voltage_clusters", "sort_sweep_arrays"] from typing import Literal @@ -234,3 +234,98 @@ def sort_sweep_arrays( current = current[::-1] return voltage, current + + +def merge_voltage_clusters( + voltage: np.ndarray, + current: np.ndarray, + voltage_step_size: float = None, + force_regular_grid: bool = False, +): + # step_size = 0 (only merge identical voltages) + # None : calculate steps size as average of array step sizes + + voltage, current = check_sweep(voltage, current) + + if not isinstance(force_regular_grid, bool): + raise TypeError( + "Expected 'force_regular_grid' to be a bool, but got type " + f"{type(force_regular_grid)}." + ) + + if voltage_step_size is None: + voltage_step_size = np.abs(np.average(np.diff(voltage))) + elif voltage_step_size == 0: + voltage_step_size = 0.0 + elif not isinstance(voltage_step_size, float): + raise TypeError( + "Expected 'voltage_step_size' to be a float or None, got type " + f"{type(voltage_step_size)}." + ) + elif voltage_step_size < 0: + voltage_step_size = -voltage_step_size + + voltage_ascending = bool(np.all(np.diff(voltage) >= 0)) + if not voltage_ascending: + voltage, current = sort_sweep_arrays(voltage, current, voltage_order="ascending") + + # now merge clusters + new_voltage = np.unique(voltage) + if voltage_step_size == 0 and new_voltage.size == voltage.size: + new_current = current.copy() + elif voltage_step_size == 0: + new_current = np.empty_like(new_voltage, dtype=current.dtype) + + for ii in range(new_voltage.size): + mask = voltage == new_voltage[ii] + if np.count_nonzero(mask) == 1: + new_current[ii] = current[mask] + else: + new_current[ii] = np.average(current[mask]) + else: + new_voltage = np.empty_like(voltage, dtype=voltage.dtype) + new_voltage[...] = np.nan + new_current = np.empty_like(current, dtype=current.dtype) + new_current[...] = np.nan + + start_voltage = voltage[0] + stop_voltage = start_voltage + voltage_step_size + + ii = 0 + while start_voltage <= voltage[-1]: + mask1 = voltage >= start_voltage + mask2 = voltage < stop_voltage + mask = np.logical_and(mask1, mask2) + + if np.count_nonzero(mask) > 0: + new_voltage[ii] = ( + start_voltage + 0.5 * voltage_step_size if force_regular_grid + else np.average(voltage[mask]) + ) + new_current[ii] = np.average(current[mask]) + + ii += 1 + + start_voltage = stop_voltage + stop_voltage = start_voltage + voltage_step_size + + # filter out NaN values + new_voltage = new_voltage[:ii] + new_current = new_current[:ii] + + # force regular spacing + if force_regular_grid: + # Need to fill array with NaN values to force the regular spacing + ... + + if not voltage_ascending: + voltage, current = sort_sweep_arrays(voltage, current, voltage_order="descending") + new_voltage, new_current = sort_sweep_arrays( + new_voltage, new_current, voltage_order="descending" + ) + else: + new_voltage, new_current = sort_sweep_arrays( + new_voltage, new_current, voltage_order="ascending" + ) + + return new_voltage, new_current From 626dedb63def14fdfd0fad5c5d852ec3633cf836 Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 12 Jun 2025 11:30:29 -0700 Subject: [PATCH 285/521] too much to explain --- .../analysis/swept_langmuir/helpers.py | 188 ++++++++++++++---- 1 file changed, 145 insertions(+), 43 deletions(-) diff --git a/src/plasmapy/analysis/swept_langmuir/helpers.py b/src/plasmapy/analysis/swept_langmuir/helpers.py index 53da0e631d..cc33b71eb2 100644 --- a/src/plasmapy/analysis/swept_langmuir/helpers.py +++ b/src/plasmapy/analysis/swept_langmuir/helpers.py @@ -236,61 +236,164 @@ def sort_sweep_arrays( return voltage, current -def merge_voltage_clusters( +def _nan_stuff_regular_grid( voltage: np.ndarray, current: np.ndarray, - voltage_step_size: float = None, - force_regular_grid: bool = False, -): - # step_size = 0 (only merge identical voltages) - # None : calculate steps size as average of array step sizes + voltage_step_size: float, +) -> tuple[np.ndarray, np.ndarray]: + size = int(np.round((voltage[-1] - voltage[0]) / voltage_step_size)) + 1 + reg_voltage = np.linspace(voltage[0], voltage[-1], num=size, dtype=voltage.dtype) - voltage, current = check_sweep(voltage, current) + _, reg_indices, new_indices = np.intersect1d( + np.round(reg_voltage, decimals=5), + np.round(voltage, decimals=5), + return_indices=True, + ) + mask = np.ones_like(reg_voltage, dtype=bool) + mask[reg_indices] = False + reg_voltage[mask] = np.nan + + reg_current = np.full(size, np.nan, dtype=current.dtype) + reg_current[np.logical_not(mask)] = current[...] - if not isinstance(force_regular_grid, bool): + return reg_voltage, reg_current + + +def merge_voltage_clusters( + voltage: np.ndarray, + current: np.ndarray, + voltage_step_size: float = None, + force_regular_spacing: bool = False, +) -> tuple[np.ndarray, np.ndarray]: + # condition force_regular_grid + if not isinstance(force_regular_spacing, bool): raise TypeError( - "Expected 'force_regular_grid' to be a bool, but got type " - f"{type(force_regular_grid)}." + "Expected 'force_regular_spacing' to be a bool, but got type " + f"{type(force_regular_spacing)}." ) - if voltage_step_size is None: - voltage_step_size = np.abs(np.average(np.diff(voltage))) - elif voltage_step_size == 0: - voltage_step_size = 0.0 - elif not isinstance(voltage_step_size, float): + # condition voltage_step_size + if ( + voltage_step_size is not None + and not isinstance(voltage_step_size, (float, np.floating, int, np.integer)) + ): raise TypeError( "Expected 'voltage_step_size' to be a float or None, got type " f"{type(voltage_step_size)}." ) + elif isinstance(voltage_step_size, (int, np.integer)): + voltage_step_size = float(voltage_step_size) + + voltage, current = check_sweep(voltage, current) + + # check if grid is regularly spaced + voltage_diff = np.diff(voltage) + mask_zero_diff = np.isclose(voltage_diff, 0.0) + if np.count_nonzero(mask_zero_diff) > 0: + is_regular_grid = False + elif np.allclose(voltage_diff, voltage_diff[0]): + # grid is already regularly spaced + is_regular_grid = True + elif np.allclose( + np.rint(voltage_diff / np.min(voltage_diff)) + - voltage_diff / np.min(voltage_diff), + 0, + ): + # grid has a common dV, but at times jumps N * dV times + if force_regular_spacing and (voltage_step_size is None or voltage_step_size == 0): + # need to stuff with NaN values + voltage, current = _nan_stuff_regular_grid( + voltage=voltage, + current=current, + voltage_step_size=np.min(voltage_diff), + ) + is_regular_grid = True + else: + is_regular_grid = False + + # return if voltage is already regularly spaced and no voltage merging is + # requested + if is_regular_grid and (voltage_step_size is None or voltage_step_size == 0): + return voltage.copy(), current.copy() + + # condition voltage_step_size ... Round 2 + if voltage_step_size is None: + voltage_step_size = np.abs( + np.average(voltage_diff[np.logical_not(mask_zero_diff)]) + ) + elif voltage_step_size == 0: + voltage_step_size = 0.0 elif voltage_step_size < 0: voltage_step_size = -voltage_step_size - voltage_ascending = bool(np.all(np.diff(voltage) >= 0)) + # ensure voltage is ascending for calculation + voltage_ascending = bool(np.all(voltage_diff >= 0)) if not voltage_ascending: voltage, current = sort_sweep_arrays(voltage, current, voltage_order="ascending") # now merge clusters - new_voltage = np.unique(voltage) - if voltage_step_size == 0 and new_voltage.size == voltage.size: + voltage_diff = np.diff(voltage) + if voltage_step_size != 0 and np.all(voltage_diff >= voltage_step_size): + new_voltage = voltage.copy() new_current = current.copy() + + if force_regular_spacing: + size = int( + np.round((new_voltage[-1] - new_voltage[0]) / voltage_step_size) + ) + 1 + reg_voltage = np.linspace( + new_voltage[0], new_voltage[-1], num=size, dtype=new_voltage.dtype + ) + reg_current = np.interp(reg_voltage, new_voltage, new_current) + + new_voltage = reg_voltage + new_current = reg_current elif voltage_step_size == 0: - new_current = np.empty_like(new_voltage, dtype=current.dtype) + voltage_diff = np.diff(voltage) + mask_zero_diff = np.isclose(voltage_diff, 0.0) + mask_zero_diff = np.append(mask_zero_diff, [mask_zero_diff[-1]]) + + new_voltage = np.full(voltage.shape, np.nan, dtype=voltage.dtype) + new_current = np.full(current.shape, np.nan, dtype=current.dtype) + + mask = np.logical_not(mask_zero_diff) + new_voltage[mask] = voltage[mask] + new_current[mask] = current[mask] + + while np.any(mask_zero_diff): + volt = voltage[mask_zero_diff][0] + index = np.where(new_voltage == volt)[0] + if len(index) == 0: + index = np.where(mask_zero_diff)[0] + + index = index[0] + volt_mask = np.isclose(voltage, volt) + + new_voltage[index] = volt + new_current[index] = np.average(current[volt_mask]) + + mask_zero_diff[volt_mask] = False + + # remove nan entries + mask = np.logical_not(np.isnan(new_voltage)) + new_voltage = new_voltage[mask] + new_current = new_current[mask] + + if force_regular_spacing: + new_voltage, new_current = merge_voltage_clusters( + voltage=new_voltage, + current=new_current, + voltage_step_size=voltage_step_size, + ) - for ii in range(new_voltage.size): - mask = voltage == new_voltage[ii] - if np.count_nonzero(mask) == 1: - new_current[ii] = current[mask] - else: - new_current[ii] = np.average(current[mask]) else: - new_voltage = np.empty_like(voltage, dtype=voltage.dtype) - new_voltage[...] = np.nan - new_current = np.empty_like(current, dtype=current.dtype) - new_current[...] = np.nan + new_voltage = np.full(voltage.shape, np.nan, dtype=voltage.dtype) + new_current = np.full(current.shape, np.nan, dtype=current.dtype) start_voltage = voltage[0] stop_voltage = start_voltage + voltage_step_size + # populate ii = 0 while start_voltage <= voltage[-1]: mask1 = voltage >= start_voltage @@ -299,7 +402,7 @@ def merge_voltage_clusters( if np.count_nonzero(mask) > 0: new_voltage[ii] = ( - start_voltage + 0.5 * voltage_step_size if force_regular_grid + start_voltage + 0.5 * voltage_step_size if force_regular_spacing else np.average(voltage[mask]) ) new_current[ii] = np.average(current[mask]) @@ -307,25 +410,24 @@ def merge_voltage_clusters( ii += 1 start_voltage = stop_voltage - stop_voltage = start_voltage + voltage_step_size + stop_voltage += voltage_step_size - # filter out NaN values + # crop new arrays new_voltage = new_voltage[:ii] new_current = new_current[:ii] - # force regular spacing - if force_regular_grid: + if force_regular_spacing: # Need to fill array with NaN values to force the regular spacing - ... + new_voltage, new_current = _nan_stuff_regular_grid( + voltage=new_voltage, + current=new_current, + voltage_step_size=voltage_step_size, + ) if not voltage_ascending: - voltage, current = sort_sweep_arrays(voltage, current, voltage_order="descending") - new_voltage, new_current = sort_sweep_arrays( - new_voltage, new_current, voltage_order="descending" - ) - else: - new_voltage, new_current = sort_sweep_arrays( - new_voltage, new_current, voltage_order="ascending" - ) + voltage = voltage[::-1] + current = current[::-1] + new_voltage = new_voltage[::-1] + new_current = new_current[::-1] return new_voltage, new_current From 1c5271a6ff18f961c12eba7874086418ff6acded Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 13 Jun 2025 19:00:36 -0700 Subject: [PATCH 286/521] rename _nan_stuff_regular_grid -> _force_regular_spacing --- src/plasmapy/analysis/swept_langmuir/helpers.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/plasmapy/analysis/swept_langmuir/helpers.py b/src/plasmapy/analysis/swept_langmuir/helpers.py index cc33b71eb2..14be3ed40b 100644 --- a/src/plasmapy/analysis/swept_langmuir/helpers.py +++ b/src/plasmapy/analysis/swept_langmuir/helpers.py @@ -236,7 +236,7 @@ def sort_sweep_arrays( return voltage, current -def _nan_stuff_regular_grid( +def _force_regular_spacing( voltage: np.ndarray, current: np.ndarray, voltage_step_size: float, @@ -302,7 +302,7 @@ def merge_voltage_clusters( # grid has a common dV, but at times jumps N * dV times if force_regular_spacing and (voltage_step_size is None or voltage_step_size == 0): # need to stuff with NaN values - voltage, current = _nan_stuff_regular_grid( + voltage, current = _force_regular_spacing( voltage=voltage, current=current, voltage_step_size=np.min(voltage_diff), @@ -418,7 +418,7 @@ def merge_voltage_clusters( if force_regular_spacing: # Need to fill array with NaN values to force the regular spacing - new_voltage, new_current = _nan_stuff_regular_grid( + new_voltage, new_current = _force_regular_spacing( voltage=new_voltage, current=new_current, voltage_step_size=voltage_step_size, From 03309ac8abf7be4ce0c82c2852d0d9fd2a6586e4 Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 13 Jun 2025 19:01:00 -0700 Subject: [PATCH 287/521] add docstring to _force_regular_spacing --- .../analysis/swept_langmuir/helpers.py | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/src/plasmapy/analysis/swept_langmuir/helpers.py b/src/plasmapy/analysis/swept_langmuir/helpers.py index 14be3ed40b..aac22ea2ad 100644 --- a/src/plasmapy/analysis/swept_langmuir/helpers.py +++ b/src/plasmapy/analysis/swept_langmuir/helpers.py @@ -241,6 +241,41 @@ def _force_regular_spacing( current: np.ndarray, voltage_step_size: float, ) -> tuple[np.ndarray, np.ndarray]: + """ + Take a ``voltage`` array that already has voltage steps at some + integer spacing of ``voltage_step_size`` and its paired ``current`` + array to generate a voltage array with a fixed step size + ``voltage_step_size`` along with an appropriately `~numpy.nan` + stuffed ``current`` array. + + Parameters + ---------- + voltage: `numpy.ndarray` + 1D `numpy.ndarray` representing the voltage of the swept + Langmuir trace. *No units are assumed or checked, but values + should be in volts.* + + current: `numpy.ndarray` + 1D `numpy.ndarray` representing the current of the swept + Langmuir trace. Values should start from a negative + ion-saturation current and increase to a positive + electron-saturation current. *No units are assumed or checked, + but values should be in amperes.* + + voltage_step_size: `float` + A non-zero, positive step size for the ``voltage`` array + spacing. + + Returns + ------- + voltage : `numpy.ndarray` + An array with step size ``voltage_step_size`` spanning the same + voltages given in the input ``voltage`` array. + + current : `numpy.ndarray` + A `~numpy.nan` stuffed copy of the input ``current`` array to + match the size of the returned ``voltage`` array. + """ size = int(np.round((voltage[-1] - voltage[0]) / voltage_step_size)) + 1 reg_voltage = np.linspace(voltage[0], voltage[-1], num=size, dtype=voltage.dtype) From 71b46b589eab3b5d22e49dc07804b133abdcab07 Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 13 Jun 2025 19:01:26 -0700 Subject: [PATCH 288/521] _force_regular_spacing: only nan stuff the current array --- src/plasmapy/analysis/swept_langmuir/helpers.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/plasmapy/analysis/swept_langmuir/helpers.py b/src/plasmapy/analysis/swept_langmuir/helpers.py index aac22ea2ad..304a4528fb 100644 --- a/src/plasmapy/analysis/swept_langmuir/helpers.py +++ b/src/plasmapy/analysis/swept_langmuir/helpers.py @@ -284,12 +284,12 @@ def _force_regular_spacing( np.round(voltage, decimals=5), return_indices=True, ) - mask = np.ones_like(reg_voltage, dtype=bool) - mask[reg_indices] = False - reg_voltage[mask] = np.nan + + mask = np.zeros_like(reg_voltage, dtype=bool) + mask[reg_indices] = True reg_current = np.full(size, np.nan, dtype=current.dtype) - reg_current[np.logical_not(mask)] = current[...] + reg_current[mask] = current[...] return reg_voltage, reg_current From 3feaa67f778a2af3c74283cc1f3b95ae4874418e Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 13 Jun 2025 19:08:07 -0700 Subject: [PATCH 289/521] appease grumpy ruff --- src/plasmapy/analysis/swept_langmuir/helpers.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/plasmapy/analysis/swept_langmuir/helpers.py b/src/plasmapy/analysis/swept_langmuir/helpers.py index 304a4528fb..725f041dc4 100644 --- a/src/plasmapy/analysis/swept_langmuir/helpers.py +++ b/src/plasmapy/analysis/swept_langmuir/helpers.py @@ -294,10 +294,10 @@ def _force_regular_spacing( return reg_voltage, reg_current -def merge_voltage_clusters( +def merge_voltage_clusters( # noqa: C901, PLR0912, PLR9015 voltage: np.ndarray, current: np.ndarray, - voltage_step_size: float = None, + voltage_step_size: float | None = None, force_regular_spacing: bool = False, ) -> tuple[np.ndarray, np.ndarray]: # condition force_regular_grid @@ -310,13 +310,13 @@ def merge_voltage_clusters( # condition voltage_step_size if ( voltage_step_size is not None - and not isinstance(voltage_step_size, (float, np.floating, int, np.integer)) + and not isinstance(voltage_step_size, float | np.floating | int | np.integer) ): raise TypeError( "Expected 'voltage_step_size' to be a float or None, got type " f"{type(voltage_step_size)}." ) - elif isinstance(voltage_step_size, (int, np.integer)): + elif isinstance(voltage_step_size, int | np.integer): voltage_step_size = float(voltage_step_size) voltage, current = check_sweep(voltage, current) From ae1e72e36f6be635c87dec6ebf0a568383e74c0e Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 13 Jun 2025 19:53:33 -0700 Subject: [PATCH 290/521] fix invalid ruff rule in noqa --- src/plasmapy/analysis/swept_langmuir/helpers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plasmapy/analysis/swept_langmuir/helpers.py b/src/plasmapy/analysis/swept_langmuir/helpers.py index 725f041dc4..973812cc9b 100644 --- a/src/plasmapy/analysis/swept_langmuir/helpers.py +++ b/src/plasmapy/analysis/swept_langmuir/helpers.py @@ -294,7 +294,7 @@ def _force_regular_spacing( return reg_voltage, reg_current -def merge_voltage_clusters( # noqa: C901, PLR0912, PLR9015 +def merge_voltage_clusters( # noqa: C901, PLR0912, PLR0915 voltage: np.ndarray, current: np.ndarray, voltage_step_size: float | None = None, From 7d1a207d2f57b39bc133bd8f3938dfb7b211ebff Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 13 Jun 2025 20:01:42 -0700 Subject: [PATCH 291/521] appease ruff formatter --- .../analysis/swept_langmuir/helpers.py | 23 +++++++++++-------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/src/plasmapy/analysis/swept_langmuir/helpers.py b/src/plasmapy/analysis/swept_langmuir/helpers.py index 973812cc9b..e6f46b33a7 100644 --- a/src/plasmapy/analysis/swept_langmuir/helpers.py +++ b/src/plasmapy/analysis/swept_langmuir/helpers.py @@ -308,9 +308,8 @@ def merge_voltage_clusters( # noqa: C901, PLR0912, PLR0915 ) # condition voltage_step_size - if ( - voltage_step_size is not None - and not isinstance(voltage_step_size, float | np.floating | int | np.integer) + if voltage_step_size is not None and not isinstance( + voltage_step_size, float | np.floating | int | np.integer ): raise TypeError( "Expected 'voltage_step_size' to be a float or None, got type " @@ -335,7 +334,9 @@ def merge_voltage_clusters( # noqa: C901, PLR0912, PLR0915 0, ): # grid has a common dV, but at times jumps N * dV times - if force_regular_spacing and (voltage_step_size is None or voltage_step_size == 0): + if force_regular_spacing and ( + voltage_step_size is None or voltage_step_size == 0 + ): # need to stuff with NaN values voltage, current = _force_regular_spacing( voltage=voltage, @@ -364,7 +365,9 @@ def merge_voltage_clusters( # noqa: C901, PLR0912, PLR0915 # ensure voltage is ascending for calculation voltage_ascending = bool(np.all(voltage_diff >= 0)) if not voltage_ascending: - voltage, current = sort_sweep_arrays(voltage, current, voltage_order="ascending") + voltage, current = sort_sweep_arrays( + voltage, current, voltage_order="ascending" + ) # now merge clusters voltage_diff = np.diff(voltage) @@ -373,9 +376,10 @@ def merge_voltage_clusters( # noqa: C901, PLR0912, PLR0915 new_current = current.copy() if force_regular_spacing: - size = int( - np.round((new_voltage[-1] - new_voltage[0]) / voltage_step_size) - ) + 1 + size = ( + int(np.round((new_voltage[-1] - new_voltage[0]) / voltage_step_size)) + + 1 + ) reg_voltage = np.linspace( new_voltage[0], new_voltage[-1], num=size, dtype=new_voltage.dtype ) @@ -437,7 +441,8 @@ def merge_voltage_clusters( # noqa: C901, PLR0912, PLR0915 if np.count_nonzero(mask) > 0: new_voltage[ii] = ( - start_voltage + 0.5 * voltage_step_size if force_regular_spacing + start_voltage + 0.5 * voltage_step_size + if force_regular_spacing else np.average(voltage[mask]) ) new_current[ii] = np.average(current[mask]) From f2896846b9b96c87b75654e298c29009db0df102 Mon Sep 17 00:00:00 2001 From: "plasmapy-requirements-bot[bot]" <134649236+plasmapy-requirements-bot[bot]@users.noreply.github.com> Date: Mon, 16 Jun 2025 13:42:55 -0400 Subject: [PATCH 292/521] Update requirements with 'nox -s requirements' (#3038) Co-authored-by: namurphy <8931994+namurphy@users.noreply.github.com> --- uv.lock | 275 +++++++++++++++++++++++++++----------------------------- 1 file changed, 132 insertions(+), 143 deletions(-) diff --git a/uv.lock b/uv.lock index 4bda236cd3..19e5436373 100644 --- a/uv.lock +++ b/uv.lock @@ -140,11 +140,11 @@ wheels = [ [[package]] name = "astropy-iers-data" -version = "0.2025.6.9.0.39.3" +version = "0.2025.6.16.0.38.47" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/3d/33/fedbe8157e47ca0f85b752f5cd8285fba15498999c807074342bcbc6486a/astropy_iers_data-0.2025.6.9.0.39.3.tar.gz", hash = "sha256:4f8d0b0325187700a8bb5a8adaeae3570303fdb070537580936a08272e6d2d8d", size = 1903806, upload-time = "2025-06-09T00:39:46.998Z" } +sdist = { url = "https://files.pythonhosted.org/packages/63/ae/efd931d47653f474afb1154d9181f885bf3f82854dcdd979a9e2838470c5/astropy_iers_data-0.2025.6.16.0.38.47.tar.gz", hash = "sha256:58c984976506b8a5c1c969aafe8744b286111d98c8623e66aecc45db9e777121", size = 1899704, upload-time = "2025-06-16T00:39:20.529Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/39/18/83a74b38e1cfd2291f43daf0cf9ea59cd8dd8ded912c2e56141e6224d708/astropy_iers_data-0.2025.6.9.0.39.3-py3-none-any.whl", hash = "sha256:76855f5572707b8d25f77a0ede2b330b7ef9863bc963e3eda86321e4e32df802", size = 1956961, upload-time = "2025-06-09T00:39:45.072Z" }, + { url = "https://files.pythonhosted.org/packages/3c/35/e4b67e87d7ff182b59047db09dce11c7154273eee428c98fe0828adbf3d7/astropy_iers_data-0.2025.6.16.0.38.47-py3-none-any.whl", hash = "sha256:c8c2c999bb9fa987c89c737bc7e71d83f8a6c8fd874ef03b0adc196c1432e20e", size = 1955135, upload-time = "2025-06-16T00:39:18.731Z" }, ] [[package]] @@ -206,11 +206,11 @@ css = [ [[package]] name = "certifi" -version = "2025.4.26" +version = "2025.6.15" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e8/9e/c05b3920a3b7d20d3d3310465f50348e5b3694f4f88c6daf736eef3024c4/certifi-2025.4.26.tar.gz", hash = "sha256:0a816057ea3cdefcef70270d2c515e4506bbc954f417fa5ade2021213bb8f0c6", size = 160705, upload-time = "2025-04-26T02:12:29.51Z" } +sdist = { url = "https://files.pythonhosted.org/packages/73/f7/f14b46d4bcd21092d7d3ccef689615220d8a08fb25e564b65d20738e672e/certifi-2025.6.15.tar.gz", hash = "sha256:d747aa5a8b9bbbb1bb8c22bb13e22bd1f18e9796defa16bab421f7f7a317323b", size = 158753, upload-time = "2025-06-15T02:45:51.329Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/4a/7e/3db2bd1b1f9e95f7cddca6d6e75e2f2bd9f51b1246e546d88addca0106bd/certifi-2025.4.26-py3-none-any.whl", hash = "sha256:30350364dfe371162649852c63336a15c70c6510c2ad5015b21c2345311805f3", size = 159618, upload-time = "2025-04-26T02:12:27.662Z" }, + { url = "https://files.pythonhosted.org/packages/84/ae/320161bd181fc06471eed047ecce67b693fd7515b16d495d8932db763426/certifi-2025.6.15-py3-none-any.whl", hash = "sha256:2e0c7ce7cb5d8f8634ca55d2ba7e6ec2689a2fd6537d8dec1296a477a4910057", size = 157650, upload-time = "2025-06-15T02:45:49.977Z" }, ] [[package]] @@ -407,56 +407,56 @@ wheels = [ [[package]] name = "coverage" -version = "7.8.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/ba/07/998afa4a0ecdf9b1981ae05415dad2d4e7716e1b1f00abbd91691ac09ac9/coverage-7.8.2.tar.gz", hash = "sha256:a886d531373a1f6ff9fad2a2ba4a045b68467b779ae729ee0b3b10ac20033b27", size = 812759, upload-time = "2025-05-23T11:39:57.856Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/6a/4d/1ff618ee9f134d0de5cc1661582c21a65e06823f41caf801aadf18811a8e/coverage-7.8.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b99058eef42e6a8dcd135afb068b3d53aff3921ce699e127602efff9956457a9", size = 211692, upload-time = "2025-05-23T11:38:08.485Z" }, - { url = "https://files.pythonhosted.org/packages/96/fa/c3c1b476de96f2bc7a8ca01a9f1fcb51c01c6b60a9d2c3e66194b2bdb4af/coverage-7.8.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5feb7f2c3e6ea94d3b877def0270dff0947b8d8c04cfa34a17be0a4dc1836879", size = 212115, upload-time = "2025-05-23T11:38:09.989Z" }, - { url = "https://files.pythonhosted.org/packages/f7/c2/5414c5a1b286c0f3881ae5adb49be1854ac5b7e99011501f81c8c1453065/coverage-7.8.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:670a13249b957bb9050fab12d86acef7bf8f6a879b9d1a883799276e0d4c674a", size = 244740, upload-time = "2025-05-23T11:38:11.947Z" }, - { url = "https://files.pythonhosted.org/packages/cd/46/1ae01912dfb06a642ef3dd9cf38ed4996fda8fe884dab8952da616f81a2b/coverage-7.8.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0bdc8bf760459a4a4187b452213e04d039990211f98644c7292adf1e471162b5", size = 242429, upload-time = "2025-05-23T11:38:13.955Z" }, - { url = "https://files.pythonhosted.org/packages/06/58/38c676aec594bfe2a87c7683942e5a30224791d8df99bcc8439fde140377/coverage-7.8.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:07a989c867986c2a75f158f03fdb413128aad29aca9d4dbce5fc755672d96f11", size = 244218, upload-time = "2025-05-23T11:38:15.631Z" }, - { url = "https://files.pythonhosted.org/packages/80/0c/95b1023e881ce45006d9abc250f76c6cdab7134a1c182d9713878dfefcb2/coverage-7.8.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:2db10dedeb619a771ef0e2949ccba7b75e33905de959c2643a4607bef2f3fb3a", size = 243865, upload-time = "2025-05-23T11:38:17.622Z" }, - { url = "https://files.pythonhosted.org/packages/57/37/0ae95989285a39e0839c959fe854a3ae46c06610439350d1ab860bf020ac/coverage-7.8.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e6ea7dba4e92926b7b5f0990634b78ea02f208d04af520c73a7c876d5a8d36cb", size = 242038, upload-time = "2025-05-23T11:38:19.966Z" }, - { url = "https://files.pythonhosted.org/packages/4d/82/40e55f7c0eb5e97cc62cbd9d0746fd24e8caf57be5a408b87529416e0c70/coverage-7.8.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ef2f22795a7aca99fc3c84393a55a53dd18ab8c93fb431004e4d8f0774150f54", size = 242567, upload-time = "2025-05-23T11:38:21.912Z" }, - { url = "https://files.pythonhosted.org/packages/f9/35/66a51adc273433a253989f0d9cc7aa6bcdb4855382cf0858200afe578861/coverage-7.8.2-cp311-cp311-win32.whl", hash = "sha256:641988828bc18a6368fe72355df5f1703e44411adbe49bba5644b941ce6f2e3a", size = 214194, upload-time = "2025-05-23T11:38:23.571Z" }, - { url = "https://files.pythonhosted.org/packages/f6/8f/a543121f9f5f150eae092b08428cb4e6b6d2d134152c3357b77659d2a605/coverage-7.8.2-cp311-cp311-win_amd64.whl", hash = "sha256:8ab4a51cb39dc1933ba627e0875046d150e88478dbe22ce145a68393e9652975", size = 215109, upload-time = "2025-05-23T11:38:25.137Z" }, - { url = "https://files.pythonhosted.org/packages/77/65/6cc84b68d4f35186463cd7ab1da1169e9abb59870c0f6a57ea6aba95f861/coverage-7.8.2-cp311-cp311-win_arm64.whl", hash = "sha256:8966a821e2083c74d88cca5b7dcccc0a3a888a596a04c0b9668a891de3a0cc53", size = 213521, upload-time = "2025-05-23T11:38:27.123Z" }, - { url = "https://files.pythonhosted.org/packages/8d/2a/1da1ada2e3044fcd4a3254fb3576e160b8fe5b36d705c8a31f793423f763/coverage-7.8.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:e2f6fe3654468d061942591aef56686131335b7a8325684eda85dacdf311356c", size = 211876, upload-time = "2025-05-23T11:38:29.01Z" }, - { url = "https://files.pythonhosted.org/packages/70/e9/3d715ffd5b6b17a8be80cd14a8917a002530a99943cc1939ad5bb2aa74b9/coverage-7.8.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:76090fab50610798cc05241bf83b603477c40ee87acd358b66196ab0ca44ffa1", size = 212130, upload-time = "2025-05-23T11:38:30.675Z" }, - { url = "https://files.pythonhosted.org/packages/a0/02/fdce62bb3c21649abfd91fbdcf041fb99be0d728ff00f3f9d54d97ed683e/coverage-7.8.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2bd0a0a5054be160777a7920b731a0570284db5142abaaf81bcbb282b8d99279", size = 246176, upload-time = "2025-05-23T11:38:32.395Z" }, - { url = "https://files.pythonhosted.org/packages/a7/52/decbbed61e03b6ffe85cd0fea360a5e04a5a98a7423f292aae62423b8557/coverage-7.8.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:da23ce9a3d356d0affe9c7036030b5c8f14556bd970c9b224f9c8205505e3b99", size = 243068, upload-time = "2025-05-23T11:38:33.989Z" }, - { url = "https://files.pythonhosted.org/packages/38/6c/d0e9c0cce18faef79a52778219a3c6ee8e336437da8eddd4ab3dbd8fadff/coverage-7.8.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c9392773cffeb8d7e042a7b15b82a414011e9d2b5fdbbd3f7e6a6b17d5e21b20", size = 245328, upload-time = "2025-05-23T11:38:35.568Z" }, - { url = "https://files.pythonhosted.org/packages/f0/70/f703b553a2f6b6c70568c7e398ed0789d47f953d67fbba36a327714a7bca/coverage-7.8.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:876cbfd0b09ce09d81585d266c07a32657beb3eaec896f39484b631555be0fe2", size = 245099, upload-time = "2025-05-23T11:38:37.627Z" }, - { url = "https://files.pythonhosted.org/packages/ec/fb/4cbb370dedae78460c3aacbdad9d249e853f3bc4ce5ff0e02b1983d03044/coverage-7.8.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:3da9b771c98977a13fbc3830f6caa85cae6c9c83911d24cb2d218e9394259c57", size = 243314, upload-time = "2025-05-23T11:38:39.238Z" }, - { url = "https://files.pythonhosted.org/packages/39/9f/1afbb2cb9c8699b8bc38afdce00a3b4644904e6a38c7bf9005386c9305ec/coverage-7.8.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:9a990f6510b3292686713bfef26d0049cd63b9c7bb17e0864f133cbfd2e6167f", size = 244489, upload-time = "2025-05-23T11:38:40.845Z" }, - { url = "https://files.pythonhosted.org/packages/79/fa/f3e7ec7d220bff14aba7a4786ae47043770cbdceeea1803083059c878837/coverage-7.8.2-cp312-cp312-win32.whl", hash = "sha256:bf8111cddd0f2b54d34e96613e7fbdd59a673f0cf5574b61134ae75b6f5a33b8", size = 214366, upload-time = "2025-05-23T11:38:43.551Z" }, - { url = "https://files.pythonhosted.org/packages/54/aa/9cbeade19b7e8e853e7ffc261df885d66bf3a782c71cba06c17df271f9e6/coverage-7.8.2-cp312-cp312-win_amd64.whl", hash = "sha256:86a323a275e9e44cdf228af9b71c5030861d4d2610886ab920d9945672a81223", size = 215165, upload-time = "2025-05-23T11:38:45.148Z" }, - { url = "https://files.pythonhosted.org/packages/c4/73/e2528bf1237d2448f882bbebaec5c3500ef07301816c5c63464b9da4d88a/coverage-7.8.2-cp312-cp312-win_arm64.whl", hash = "sha256:820157de3a589e992689ffcda8639fbabb313b323d26388d02e154164c57b07f", size = 213548, upload-time = "2025-05-23T11:38:46.74Z" }, - { url = "https://files.pythonhosted.org/packages/1a/93/eb6400a745ad3b265bac36e8077fdffcf0268bdbbb6c02b7220b624c9b31/coverage-7.8.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ea561010914ec1c26ab4188aef8b1567272ef6de096312716f90e5baa79ef8ca", size = 211898, upload-time = "2025-05-23T11:38:49.066Z" }, - { url = "https://files.pythonhosted.org/packages/1b/7c/bdbf113f92683024406a1cd226a199e4200a2001fc85d6a6e7e299e60253/coverage-7.8.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:cb86337a4fcdd0e598ff2caeb513ac604d2f3da6d53df2c8e368e07ee38e277d", size = 212171, upload-time = "2025-05-23T11:38:51.207Z" }, - { url = "https://files.pythonhosted.org/packages/91/22/594513f9541a6b88eb0dba4d5da7d71596dadef6b17a12dc2c0e859818a9/coverage-7.8.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:26a4636ddb666971345541b59899e969f3b301143dd86b0ddbb570bd591f1e85", size = 245564, upload-time = "2025-05-23T11:38:52.857Z" }, - { url = "https://files.pythonhosted.org/packages/1f/f4/2860fd6abeebd9f2efcfe0fd376226938f22afc80c1943f363cd3c28421f/coverage-7.8.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5040536cf9b13fb033f76bcb5e1e5cb3b57c4807fef37db9e0ed129c6a094257", size = 242719, upload-time = "2025-05-23T11:38:54.529Z" }, - { url = "https://files.pythonhosted.org/packages/89/60/f5f50f61b6332451520e6cdc2401700c48310c64bc2dd34027a47d6ab4ca/coverage-7.8.2-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dc67994df9bcd7e0150a47ef41278b9e0a0ea187caba72414b71dc590b99a108", size = 244634, upload-time = "2025-05-23T11:38:57.326Z" }, - { url = "https://files.pythonhosted.org/packages/3b/70/7f4e919039ab7d944276c446b603eea84da29ebcf20984fb1fdf6e602028/coverage-7.8.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:6e6c86888fd076d9e0fe848af0a2142bf606044dc5ceee0aa9eddb56e26895a0", size = 244824, upload-time = "2025-05-23T11:38:59.421Z" }, - { url = "https://files.pythonhosted.org/packages/26/45/36297a4c0cea4de2b2c442fe32f60c3991056c59cdc3cdd5346fbb995c97/coverage-7.8.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:684ca9f58119b8e26bef860db33524ae0365601492e86ba0b71d513f525e7050", size = 242872, upload-time = "2025-05-23T11:39:01.049Z" }, - { url = "https://files.pythonhosted.org/packages/a4/71/e041f1b9420f7b786b1367fa2a375703889ef376e0d48de9f5723fb35f11/coverage-7.8.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8165584ddedb49204c4e18da083913bdf6a982bfb558632a79bdaadcdafd0d48", size = 244179, upload-time = "2025-05-23T11:39:02.709Z" }, - { url = "https://files.pythonhosted.org/packages/bd/db/3c2bf49bdc9de76acf2491fc03130c4ffc51469ce2f6889d2640eb563d77/coverage-7.8.2-cp313-cp313-win32.whl", hash = "sha256:34759ee2c65362163699cc917bdb2a54114dd06d19bab860725f94ef45a3d9b7", size = 214393, upload-time = "2025-05-23T11:39:05.457Z" }, - { url = "https://files.pythonhosted.org/packages/c6/dc/947e75d47ebbb4b02d8babb1fad4ad381410d5bc9da7cfca80b7565ef401/coverage-7.8.2-cp313-cp313-win_amd64.whl", hash = "sha256:2f9bc608fbafaee40eb60a9a53dbfb90f53cc66d3d32c2849dc27cf5638a21e3", size = 215194, upload-time = "2025-05-23T11:39:07.171Z" }, - { url = "https://files.pythonhosted.org/packages/90/31/a980f7df8a37eaf0dc60f932507fda9656b3a03f0abf188474a0ea188d6d/coverage-7.8.2-cp313-cp313-win_arm64.whl", hash = "sha256:9fe449ee461a3b0c7105690419d0b0aba1232f4ff6d120a9e241e58a556733f7", size = 213580, upload-time = "2025-05-23T11:39:08.862Z" }, - { url = "https://files.pythonhosted.org/packages/8a/6a/25a37dd90f6c95f59355629417ebcb74e1c34e38bb1eddf6ca9b38b0fc53/coverage-7.8.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:8369a7c8ef66bded2b6484053749ff220dbf83cba84f3398c84c51a6f748a008", size = 212734, upload-time = "2025-05-23T11:39:11.109Z" }, - { url = "https://files.pythonhosted.org/packages/36/8b/3a728b3118988725f40950931abb09cd7f43b3c740f4640a59f1db60e372/coverage-7.8.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:159b81df53a5fcbc7d45dae3adad554fdbde9829a994e15227b3f9d816d00b36", size = 212959, upload-time = "2025-05-23T11:39:12.751Z" }, - { url = "https://files.pythonhosted.org/packages/53/3c/212d94e6add3a3c3f412d664aee452045ca17a066def8b9421673e9482c4/coverage-7.8.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e6fcbbd35a96192d042c691c9e0c49ef54bd7ed865846a3c9d624c30bb67ce46", size = 257024, upload-time = "2025-05-23T11:39:15.569Z" }, - { url = "https://files.pythonhosted.org/packages/a4/40/afc03f0883b1e51bbe804707aae62e29c4e8c8bbc365c75e3e4ddeee9ead/coverage-7.8.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:05364b9cc82f138cc86128dc4e2e1251c2981a2218bfcd556fe6b0fbaa3501be", size = 252867, upload-time = "2025-05-23T11:39:17.64Z" }, - { url = "https://files.pythonhosted.org/packages/18/a2/3699190e927b9439c6ded4998941a3c1d6fa99e14cb28d8536729537e307/coverage-7.8.2-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:46d532db4e5ff3979ce47d18e2fe8ecad283eeb7367726da0e5ef88e4fe64740", size = 255096, upload-time = "2025-05-23T11:39:19.328Z" }, - { url = "https://files.pythonhosted.org/packages/b4/06/16e3598b9466456b718eb3e789457d1a5b8bfb22e23b6e8bbc307df5daf0/coverage-7.8.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:4000a31c34932e7e4fa0381a3d6deb43dc0c8f458e3e7ea6502e6238e10be625", size = 256276, upload-time = "2025-05-23T11:39:21.077Z" }, - { url = "https://files.pythonhosted.org/packages/a7/d5/4b5a120d5d0223050a53d2783c049c311eea1709fa9de12d1c358e18b707/coverage-7.8.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:43ff5033d657cd51f83015c3b7a443287250dc14e69910577c3e03bd2e06f27b", size = 254478, upload-time = "2025-05-23T11:39:22.838Z" }, - { url = "https://files.pythonhosted.org/packages/ba/85/f9ecdb910ecdb282b121bfcaa32fa8ee8cbd7699f83330ee13ff9bbf1a85/coverage-7.8.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:94316e13f0981cbbba132c1f9f365cac1d26716aaac130866ca812006f662199", size = 255255, upload-time = "2025-05-23T11:39:24.644Z" }, - { url = "https://files.pythonhosted.org/packages/50/63/2d624ac7d7ccd4ebbd3c6a9eba9d7fc4491a1226071360d59dd84928ccb2/coverage-7.8.2-cp313-cp313t-win32.whl", hash = "sha256:3f5673888d3676d0a745c3d0e16da338c5eea300cb1f4ada9c872981265e76d8", size = 215109, upload-time = "2025-05-23T11:39:26.722Z" }, - { url = "https://files.pythonhosted.org/packages/22/5e/7053b71462e970e869111c1853afd642212568a350eba796deefdfbd0770/coverage-7.8.2-cp313-cp313t-win_amd64.whl", hash = "sha256:2c08b05ee8d7861e45dc5a2cc4195c8c66dca5ac613144eb6ebeaff2d502e73d", size = 216268, upload-time = "2025-05-23T11:39:28.429Z" }, - { url = "https://files.pythonhosted.org/packages/07/69/afa41aa34147655543dbe96994f8a246daf94b361ccf5edfd5df62ce066a/coverage-7.8.2-cp313-cp313t-win_arm64.whl", hash = "sha256:1e1448bb72b387755e1ff3ef1268a06617afd94188164960dba8d0245a46004b", size = 214071, upload-time = "2025-05-23T11:39:30.55Z" }, - { url = "https://files.pythonhosted.org/packages/69/2f/572b29496d8234e4a7773200dd835a0d32d9e171f2d974f3fe04a9dbc271/coverage-7.8.2-pp39.pp310.pp311-none-any.whl", hash = "sha256:ec455eedf3ba0bbdf8f5a570012617eb305c63cb9f03428d39bf544cb2b94837", size = 203636, upload-time = "2025-05-23T11:39:52.002Z" }, - { url = "https://files.pythonhosted.org/packages/a0/1a/0b9c32220ad694d66062f571cc5cedfa9997b64a591e8a500bb63de1bd40/coverage-7.8.2-py3-none-any.whl", hash = "sha256:726f32ee3713f7359696331a18daf0c3b3a70bb0ae71141b9d3c52be7c595e32", size = 203623, upload-time = "2025-05-23T11:39:53.846Z" }, +version = "7.9.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e7/e0/98670a80884f64578f0c22cd70c5e81a6e07b08167721c7487b4d70a7ca0/coverage-7.9.1.tar.gz", hash = "sha256:6cf43c78c4282708a28e466316935ec7489a9c487518a77fa68f716c67909cec", size = 813650, upload-time = "2025-06-13T13:02:28.627Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/60/34/fa69372a07d0903a78ac103422ad34db72281c9fc625eba94ac1185da66f/coverage-7.9.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:95c765060e65c692da2d2f51a9499c5e9f5cf5453aeaf1420e3fc847cc060582", size = 212146, upload-time = "2025-06-13T13:00:48.496Z" }, + { url = "https://files.pythonhosted.org/packages/27/f0/da1894915d2767f093f081c42afeba18e760f12fdd7a2f4acbe00564d767/coverage-7.9.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ba383dc6afd5ec5b7a0d0c23d38895db0e15bcba7fb0fa8901f245267ac30d86", size = 212536, upload-time = "2025-06-13T13:00:51.535Z" }, + { url = "https://files.pythonhosted.org/packages/10/d5/3fc33b06e41e390f88eef111226a24e4504d216ab8e5d1a7089aa5a3c87a/coverage-7.9.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:37ae0383f13cbdcf1e5e7014489b0d71cc0106458878ccde52e8a12ced4298ed", size = 245092, upload-time = "2025-06-13T13:00:52.883Z" }, + { url = "https://files.pythonhosted.org/packages/0a/39/7aa901c14977aba637b78e95800edf77f29f5a380d29768c5b66f258305b/coverage-7.9.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:69aa417a030bf11ec46149636314c24c8d60fadb12fc0ee8f10fda0d918c879d", size = 242806, upload-time = "2025-06-13T13:00:54.571Z" }, + { url = "https://files.pythonhosted.org/packages/43/fc/30e5cfeaf560b1fc1989227adedc11019ce4bb7cce59d65db34fe0c2d963/coverage-7.9.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0a4be2a28656afe279b34d4f91c3e26eccf2f85500d4a4ff0b1f8b54bf807338", size = 244610, upload-time = "2025-06-13T13:00:56.932Z" }, + { url = "https://files.pythonhosted.org/packages/bf/15/cca62b13f39650bc87b2b92bb03bce7f0e79dd0bf2c7529e9fc7393e4d60/coverage-7.9.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:382e7ddd5289f140259b610e5f5c58f713d025cb2f66d0eb17e68d0a94278875", size = 244257, upload-time = "2025-06-13T13:00:58.545Z" }, + { url = "https://files.pythonhosted.org/packages/cd/1a/c0f2abe92c29e1464dbd0ff9d56cb6c88ae2b9e21becdb38bea31fcb2f6c/coverage-7.9.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e5532482344186c543c37bfad0ee6069e8ae4fc38d073b8bc836fc8f03c9e250", size = 242309, upload-time = "2025-06-13T13:00:59.836Z" }, + { url = "https://files.pythonhosted.org/packages/57/8d/c6fd70848bd9bf88fa90df2af5636589a8126d2170f3aade21ed53f2b67a/coverage-7.9.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a39d18b3f50cc121d0ce3838d32d58bd1d15dab89c910358ebefc3665712256c", size = 242898, upload-time = "2025-06-13T13:01:02.506Z" }, + { url = "https://files.pythonhosted.org/packages/c2/9e/6ca46c7bff4675f09a66fe2797cd1ad6a24f14c9c7c3b3ebe0470a6e30b8/coverage-7.9.1-cp311-cp311-win32.whl", hash = "sha256:dd24bd8d77c98557880def750782df77ab2b6885a18483dc8588792247174b32", size = 214561, upload-time = "2025-06-13T13:01:04.012Z" }, + { url = "https://files.pythonhosted.org/packages/a1/30/166978c6302010742dabcdc425fa0f938fa5a800908e39aff37a7a876a13/coverage-7.9.1-cp311-cp311-win_amd64.whl", hash = "sha256:6b55ad10a35a21b8015eabddc9ba31eb590f54adc9cd39bcf09ff5349fd52125", size = 215493, upload-time = "2025-06-13T13:01:05.702Z" }, + { url = "https://files.pythonhosted.org/packages/60/07/a6d2342cd80a5be9f0eeab115bc5ebb3917b4a64c2953534273cf9bc7ae6/coverage-7.9.1-cp311-cp311-win_arm64.whl", hash = "sha256:6ad935f0016be24c0e97fc8c40c465f9c4b85cbbe6eac48934c0dc4d2568321e", size = 213869, upload-time = "2025-06-13T13:01:09.345Z" }, + { url = "https://files.pythonhosted.org/packages/68/d9/7f66eb0a8f2fce222de7bdc2046ec41cb31fe33fb55a330037833fb88afc/coverage-7.9.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:a8de12b4b87c20de895f10567639c0797b621b22897b0af3ce4b4e204a743626", size = 212336, upload-time = "2025-06-13T13:01:10.909Z" }, + { url = "https://files.pythonhosted.org/packages/20/20/e07cb920ef3addf20f052ee3d54906e57407b6aeee3227a9c91eea38a665/coverage-7.9.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5add197315a054e92cee1b5f686a2bcba60c4c3e66ee3de77ace6c867bdee7cb", size = 212571, upload-time = "2025-06-13T13:01:12.518Z" }, + { url = "https://files.pythonhosted.org/packages/78/f8/96f155de7e9e248ca9c8ff1a40a521d944ba48bec65352da9be2463745bf/coverage-7.9.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:600a1d4106fe66f41e5d0136dfbc68fe7200a5cbe85610ddf094f8f22e1b0300", size = 246377, upload-time = "2025-06-13T13:01:14.87Z" }, + { url = "https://files.pythonhosted.org/packages/3e/cf/1d783bd05b7bca5c10ded5f946068909372e94615a4416afadfe3f63492d/coverage-7.9.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2a876e4c3e5a2a1715a6608906aa5a2e0475b9c0f68343c2ada98110512ab1d8", size = 243394, upload-time = "2025-06-13T13:01:16.23Z" }, + { url = "https://files.pythonhosted.org/packages/02/dd/e7b20afd35b0a1abea09fb3998e1abc9f9bd953bee548f235aebd2b11401/coverage-7.9.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:81f34346dd63010453922c8e628a52ea2d2ccd73cb2487f7700ac531b247c8a5", size = 245586, upload-time = "2025-06-13T13:01:17.532Z" }, + { url = "https://files.pythonhosted.org/packages/4e/38/b30b0006fea9d617d1cb8e43b1bc9a96af11eff42b87eb8c716cf4d37469/coverage-7.9.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:888f8eee13f2377ce86d44f338968eedec3291876b0b8a7289247ba52cb984cd", size = 245396, upload-time = "2025-06-13T13:01:19.164Z" }, + { url = "https://files.pythonhosted.org/packages/31/e4/4d8ec1dc826e16791f3daf1b50943e8e7e1eb70e8efa7abb03936ff48418/coverage-7.9.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:9969ef1e69b8c8e1e70d591f91bbc37fc9a3621e447525d1602801a24ceda898", size = 243577, upload-time = "2025-06-13T13:01:22.433Z" }, + { url = "https://files.pythonhosted.org/packages/25/f4/b0e96c5c38e6e40ef465c4bc7f138863e2909c00e54a331da335faf0d81a/coverage-7.9.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:60c458224331ee3f1a5b472773e4a085cc27a86a0b48205409d364272d67140d", size = 244809, upload-time = "2025-06-13T13:01:24.143Z" }, + { url = "https://files.pythonhosted.org/packages/8a/65/27e0a1fa5e2e5079bdca4521be2f5dabf516f94e29a0defed35ac2382eb2/coverage-7.9.1-cp312-cp312-win32.whl", hash = "sha256:5f646a99a8c2b3ff4c6a6e081f78fad0dde275cd59f8f49dc4eab2e394332e74", size = 214724, upload-time = "2025-06-13T13:01:25.435Z" }, + { url = "https://files.pythonhosted.org/packages/9b/a8/d5b128633fd1a5e0401a4160d02fa15986209a9e47717174f99dc2f7166d/coverage-7.9.1-cp312-cp312-win_amd64.whl", hash = "sha256:30f445f85c353090b83e552dcbbdad3ec84c7967e108c3ae54556ca69955563e", size = 215535, upload-time = "2025-06-13T13:01:27.861Z" }, + { url = "https://files.pythonhosted.org/packages/a3/37/84bba9d2afabc3611f3e4325ee2c6a47cd449b580d4a606b240ce5a6f9bf/coverage-7.9.1-cp312-cp312-win_arm64.whl", hash = "sha256:af41da5dca398d3474129c58cb2b106a5d93bbb196be0d307ac82311ca234342", size = 213904, upload-time = "2025-06-13T13:01:29.202Z" }, + { url = "https://files.pythonhosted.org/packages/d0/a7/a027970c991ca90f24e968999f7d509332daf6b8c3533d68633930aaebac/coverage-7.9.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:31324f18d5969feef7344a932c32428a2d1a3e50b15a6404e97cba1cc9b2c631", size = 212358, upload-time = "2025-06-13T13:01:30.909Z" }, + { url = "https://files.pythonhosted.org/packages/f2/48/6aaed3651ae83b231556750280682528fea8ac7f1232834573472d83e459/coverage-7.9.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0c804506d624e8a20fb3108764c52e0eef664e29d21692afa375e0dd98dc384f", size = 212620, upload-time = "2025-06-13T13:01:32.256Z" }, + { url = "https://files.pythonhosted.org/packages/6c/2a/f4b613f3b44d8b9f144847c89151992b2b6b79cbc506dee89ad0c35f209d/coverage-7.9.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ef64c27bc40189f36fcc50c3fb8f16ccda73b6a0b80d9bd6e6ce4cffcd810bbd", size = 245788, upload-time = "2025-06-13T13:01:33.948Z" }, + { url = "https://files.pythonhosted.org/packages/04/d2/de4fdc03af5e4e035ef420ed26a703c6ad3d7a07aff2e959eb84e3b19ca8/coverage-7.9.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d4fe2348cc6ec372e25adec0219ee2334a68d2f5222e0cba9c0d613394e12d86", size = 243001, upload-time = "2025-06-13T13:01:35.285Z" }, + { url = "https://files.pythonhosted.org/packages/f5/e8/eed18aa5583b0423ab7f04e34659e51101135c41cd1dcb33ac1d7013a6d6/coverage-7.9.1-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:34ed2186fe52fcc24d4561041979a0dec69adae7bce2ae8d1c49eace13e55c43", size = 244985, upload-time = "2025-06-13T13:01:36.712Z" }, + { url = "https://files.pythonhosted.org/packages/17/f8/ae9e5cce8885728c934eaa58ebfa8281d488ef2afa81c3dbc8ee9e6d80db/coverage-7.9.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:25308bd3d00d5eedd5ae7d4357161f4df743e3c0240fa773ee1b0f75e6c7c0f1", size = 245152, upload-time = "2025-06-13T13:01:39.303Z" }, + { url = "https://files.pythonhosted.org/packages/5a/c8/272c01ae792bb3af9b30fac14d71d63371db227980682836ec388e2c57c0/coverage-7.9.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:73e9439310f65d55a5a1e0564b48e34f5369bee943d72c88378f2d576f5a5751", size = 243123, upload-time = "2025-06-13T13:01:40.727Z" }, + { url = "https://files.pythonhosted.org/packages/8c/d0/2819a1e3086143c094ab446e3bdf07138527a7b88cb235c488e78150ba7a/coverage-7.9.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:37ab6be0859141b53aa89412a82454b482c81cf750de4f29223d52268a86de67", size = 244506, upload-time = "2025-06-13T13:01:42.184Z" }, + { url = "https://files.pythonhosted.org/packages/8b/4e/9f6117b89152df7b6112f65c7a4ed1f2f5ec8e60c4be8f351d91e7acc848/coverage-7.9.1-cp313-cp313-win32.whl", hash = "sha256:64bdd969456e2d02a8b08aa047a92d269c7ac1f47e0c977675d550c9a0863643", size = 214766, upload-time = "2025-06-13T13:01:44.482Z" }, + { url = "https://files.pythonhosted.org/packages/27/0f/4b59f7c93b52c2c4ce7387c5a4e135e49891bb3b7408dcc98fe44033bbe0/coverage-7.9.1-cp313-cp313-win_amd64.whl", hash = "sha256:be9e3f68ca9edb897c2184ad0eee815c635565dbe7a0e7e814dc1f7cbab92c0a", size = 215568, upload-time = "2025-06-13T13:01:45.772Z" }, + { url = "https://files.pythonhosted.org/packages/09/1e/9679826336f8c67b9c39a359352882b24a8a7aee48d4c9cad08d38d7510f/coverage-7.9.1-cp313-cp313-win_arm64.whl", hash = "sha256:1c503289ffef1d5105d91bbb4d62cbe4b14bec4d13ca225f9c73cde9bb46207d", size = 213939, upload-time = "2025-06-13T13:01:47.087Z" }, + { url = "https://files.pythonhosted.org/packages/bb/5b/5c6b4e7a407359a2e3b27bf9c8a7b658127975def62077d441b93a30dbe8/coverage-7.9.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:0b3496922cb5f4215bf5caaef4cf12364a26b0be82e9ed6d050f3352cf2d7ef0", size = 213079, upload-time = "2025-06-13T13:01:48.554Z" }, + { url = "https://files.pythonhosted.org/packages/a2/22/1e2e07279fd2fd97ae26c01cc2186e2258850e9ec125ae87184225662e89/coverage-7.9.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:9565c3ab1c93310569ec0d86b017f128f027cab0b622b7af288696d7ed43a16d", size = 213299, upload-time = "2025-06-13T13:01:49.997Z" }, + { url = "https://files.pythonhosted.org/packages/14/c0/4c5125a4b69d66b8c85986d3321520f628756cf524af810baab0790c7647/coverage-7.9.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2241ad5dbf79ae1d9c08fe52b36d03ca122fb9ac6bca0f34439e99f8327ac89f", size = 256535, upload-time = "2025-06-13T13:01:51.314Z" }, + { url = "https://files.pythonhosted.org/packages/81/8b/e36a04889dda9960be4263e95e777e7b46f1bb4fc32202612c130a20c4da/coverage-7.9.1-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3bb5838701ca68b10ebc0937dbd0eb81974bac54447c55cd58dea5bca8451029", size = 252756, upload-time = "2025-06-13T13:01:54.403Z" }, + { url = "https://files.pythonhosted.org/packages/98/82/be04eff8083a09a4622ecd0e1f31a2c563dbea3ed848069e7b0445043a70/coverage-7.9.1-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b30a25f814591a8c0c5372c11ac8967f669b97444c47fd794926e175c4047ece", size = 254912, upload-time = "2025-06-13T13:01:56.769Z" }, + { url = "https://files.pythonhosted.org/packages/0f/25/c26610a2c7f018508a5ab958e5b3202d900422cf7cdca7670b6b8ca4e8df/coverage-7.9.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:2d04b16a6062516df97969f1ae7efd0de9c31eb6ebdceaa0d213b21c0ca1a683", size = 256144, upload-time = "2025-06-13T13:01:58.19Z" }, + { url = "https://files.pythonhosted.org/packages/c5/8b/fb9425c4684066c79e863f1e6e7ecebb49e3a64d9f7f7860ef1688c56f4a/coverage-7.9.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:7931b9e249edefb07cd6ae10c702788546341d5fe44db5b6108a25da4dca513f", size = 254257, upload-time = "2025-06-13T13:01:59.645Z" }, + { url = "https://files.pythonhosted.org/packages/93/df/27b882f54157fc1131e0e215b0da3b8d608d9b8ef79a045280118a8f98fe/coverage-7.9.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:52e92b01041151bf607ee858e5a56c62d4b70f4dac85b8c8cb7fb8a351ab2c10", size = 255094, upload-time = "2025-06-13T13:02:01.37Z" }, + { url = "https://files.pythonhosted.org/packages/41/5f/cad1c3dbed8b3ee9e16fa832afe365b4e3eeab1fb6edb65ebbf745eabc92/coverage-7.9.1-cp313-cp313t-win32.whl", hash = "sha256:684e2110ed84fd1ca5f40e89aa44adf1729dc85444004111aa01866507adf363", size = 215437, upload-time = "2025-06-13T13:02:02.905Z" }, + { url = "https://files.pythonhosted.org/packages/99/4d/fad293bf081c0e43331ca745ff63673badc20afea2104b431cdd8c278b4c/coverage-7.9.1-cp313-cp313t-win_amd64.whl", hash = "sha256:437c576979e4db840539674e68c84b3cda82bc824dd138d56bead1435f1cb5d7", size = 216605, upload-time = "2025-06-13T13:02:05.638Z" }, + { url = "https://files.pythonhosted.org/packages/1f/56/4ee027d5965fc7fc126d7ec1187529cc30cc7d740846e1ecb5e92d31b224/coverage-7.9.1-cp313-cp313t-win_arm64.whl", hash = "sha256:18a0912944d70aaf5f399e350445738a1a20b50fbea788f640751c2ed9208b6c", size = 214392, upload-time = "2025-06-13T13:02:07.642Z" }, + { url = "https://files.pythonhosted.org/packages/3e/e5/c723545c3fd3204ebde3b4cc4b927dce709d3b6dc577754bb57f63ca4a4a/coverage-7.9.1-pp39.pp310.pp311-none-any.whl", hash = "sha256:db0f04118d1db74db6c9e1cb1898532c7dcc220f1d2718f058601f7c3f499514", size = 204009, upload-time = "2025-06-13T13:02:25.787Z" }, + { url = "https://files.pythonhosted.org/packages/08/b8/7ddd1e8ba9701dea08ce22029917140e6f66a859427406579fd8d0ca7274/coverage-7.9.1-py3-none-any.whl", hash = "sha256:66b974b145aa189516b6bf2d8423e888b742517d37872f6ee4c5be0073bd9a3c", size = 204000, upload-time = "2025-06-13T13:02:27.173Z" }, ] [package.optional-dependencies] @@ -589,35 +589,35 @@ wheels = [ [[package]] name = "fonttools" -version = "4.58.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/b6/a9/3319c6ae07fd9dde51064ddc6d82a2b707efad8ed407d700a01091121bbc/fonttools-4.58.2.tar.gz", hash = "sha256:4b491ddbfd50b856e84b0648b5f7941af918f6d32f938f18e62b58426a8d50e2", size = 3524285, upload-time = "2025-06-06T14:50:58.643Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/63/d0/335d12ee943b8d67847864bba98478fedf3503d8b168eeeefadd8660256a/fonttools-4.58.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:024faaf20811296fd2f83ebdac7682276362e726ed5fea4062480dd36aff2fd9", size = 2755885, upload-time = "2025-06-06T14:49:52.459Z" }, - { url = "https://files.pythonhosted.org/packages/66/c2/d8ceb8b91e3847786a19d4b93749b1d804833482b5f79bee35b68327609e/fonttools-4.58.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2faec6e7f2abd80cd9f2392dfa28c02cfd5b1125be966ea6eddd6ca684deaa40", size = 2317804, upload-time = "2025-06-06T14:49:54.581Z" }, - { url = "https://files.pythonhosted.org/packages/7c/93/865c8d50b3a1f50ebdc02227f28bb81817df88cee75bc6f2652469e754b1/fonttools-4.58.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:520792629a938c14dd7fe185794b156cfc159c609d07b31bbb5f51af8dc7918a", size = 4916900, upload-time = "2025-06-06T14:49:56.366Z" }, - { url = "https://files.pythonhosted.org/packages/60/d1/301aec4f02995958b7af6728f838b2e5cc9296bec7eae350722dec31f685/fonttools-4.58.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:12fbc6e0bf0c75ce475ef170f2c065be6abc9e06ad19a13b56b02ec2acf02427", size = 4937358, upload-time = "2025-06-06T14:49:58.392Z" }, - { url = "https://files.pythonhosted.org/packages/15/22/75dc23a4c7200b8feb90baa82c518684a601a3a03be25f7cc3dde1525e37/fonttools-4.58.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:44a39cf856d52109127d55576c7ec010206a8ba510161a7705021f70d1649831", size = 4980151, upload-time = "2025-06-06T14:50:00.778Z" }, - { url = "https://files.pythonhosted.org/packages/14/51/5d402f65c4b0c89ce0cdbffe86646f3996da209f7bc93f1f4a13a7211ee0/fonttools-4.58.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:5390a67c55a835ad5a420da15b3d88b75412cbbd74450cb78c4916b0bd7f0a34", size = 5091255, upload-time = "2025-06-06T14:50:02.588Z" }, - { url = "https://files.pythonhosted.org/packages/c7/5e/dee28700276129db1a0ee8ab0d5574d255a1d72df7f6df58a9d26ddef687/fonttools-4.58.2-cp311-cp311-win32.whl", hash = "sha256:f7e10f4e7160bcf6a240d7560e9e299e8cb585baed96f6a616cef51180bf56cb", size = 2190095, upload-time = "2025-06-06T14:50:04.932Z" }, - { url = "https://files.pythonhosted.org/packages/bd/60/b90fda549942808b68c1c5bada4b369f4f55d4c28a7012f7537670438f82/fonttools-4.58.2-cp311-cp311-win_amd64.whl", hash = "sha256:29bdf52bfafdae362570d3f0d3119a3b10982e1ef8cb3a9d3ebb72da81cb8d5e", size = 2238013, upload-time = "2025-06-06T14:50:06.605Z" }, - { url = "https://files.pythonhosted.org/packages/eb/68/7ec64584dc592faf944d540307c3562cd893256c48bb028c90de489e4750/fonttools-4.58.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:c6eeaed9c54c1d33c1db928eb92b4e180c7cb93b50b1ee3e79b2395cb01f25e9", size = 2741645, upload-time = "2025-06-06T14:50:08.706Z" }, - { url = "https://files.pythonhosted.org/packages/8f/0c/b327838f63baa7ebdd6db3ffdf5aff638e883f9236d928be4f32c692e1bd/fonttools-4.58.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:bbe1d9c72b7f981bed5c2a61443d5e3127c1b3aca28ca76386d1ad93268a803f", size = 2311100, upload-time = "2025-06-06T14:50:10.401Z" }, - { url = "https://files.pythonhosted.org/packages/ae/c7/dec024a1c873c79a4db98fe0104755fa62ec2b4518e09d6fda28246c3c9b/fonttools-4.58.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:85babe5b3ce2cbe57fc0d09c0ee92bbd4d594fd7ea46a65eb43510a74a4ce773", size = 4815841, upload-time = "2025-06-06T14:50:12.496Z" }, - { url = "https://files.pythonhosted.org/packages/94/33/57c81abad641d6ec9c8b06c99cd28d687cb4849efb6168625b5c6b8f9fa4/fonttools-4.58.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:918a2854537fcdc662938057ad58b633bc9e0698f04a2f4894258213283a7932", size = 4882659, upload-time = "2025-06-06T14:50:14.361Z" }, - { url = "https://files.pythonhosted.org/packages/a5/37/2f8faa2bf8bd1ba016ea86a94c72a5e8ef8ea1c52ec64dada617191f0515/fonttools-4.58.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3b379cf05bf776c336a0205632596b1c7d7ab5f7135e3935f2ca2a0596d2d092", size = 4876128, upload-time = "2025-06-06T14:50:16.653Z" }, - { url = "https://files.pythonhosted.org/packages/a0/ca/f1caac24ae7028a33f2a95e66c640571ff0ce5cb06c4c9ca1f632e98e22c/fonttools-4.58.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:99ab3547a15a5d168c265e139e21756bbae1de04782ac9445c9ef61b8c0a32ce", size = 5027843, upload-time = "2025-06-06T14:50:18.582Z" }, - { url = "https://files.pythonhosted.org/packages/52/6e/3200fa2bafeed748a3017e4e6594751fd50cce544270919265451b21b75c/fonttools-4.58.2-cp312-cp312-win32.whl", hash = "sha256:6764e7a3188ce36eea37b477cdeca602ae62e63ae9fc768ebc176518072deb04", size = 2177374, upload-time = "2025-06-06T14:50:20.454Z" }, - { url = "https://files.pythonhosted.org/packages/55/ab/8f3e726f3f3ef3062ce9bbb615727c55beb11eea96d1f443f79cafca93ee/fonttools-4.58.2-cp312-cp312-win_amd64.whl", hash = "sha256:41f02182a1d41b79bae93c1551855146868b04ec3e7f9c57d6fef41a124e6b29", size = 2226685, upload-time = "2025-06-06T14:50:22.087Z" }, - { url = "https://files.pythonhosted.org/packages/ac/01/29f81970a508408af20b434ff5136cd1c7ef92198957eb8ddadfbb9ef177/fonttools-4.58.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:829048ef29dbefec35d95cc6811014720371c95bdc6ceb0afd2f8e407c41697c", size = 2732398, upload-time = "2025-06-06T14:50:23.821Z" }, - { url = "https://files.pythonhosted.org/packages/0c/f1/095f2338359333adb2f1c51b8b2ad94bf9a2fa17e5fcbdf8a7b8e3672d2d/fonttools-4.58.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:64998c5993431e45b474ed5f579f18555f45309dd1cf8008b594d2fe0a94be59", size = 2306390, upload-time = "2025-06-06T14:50:25.942Z" }, - { url = "https://files.pythonhosted.org/packages/bf/d4/9eba134c7666a26668c28945355cd86e5d57828b6b8d952a5489fe45d7e2/fonttools-4.58.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b887a1cf9fbcb920980460ee4a489c8aba7e81341f6cdaeefa08c0ab6529591c", size = 4795100, upload-time = "2025-06-06T14:50:27.653Z" }, - { url = "https://files.pythonhosted.org/packages/2a/34/345f153a24c1340daa62340c3be2d1e5ee6c1ee57e13f6d15613209e688b/fonttools-4.58.2-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:27d74b9f6970cefbcda33609a3bee1618e5e57176c8b972134c4e22461b9c791", size = 4864585, upload-time = "2025-06-06T14:50:29.915Z" }, - { url = "https://files.pythonhosted.org/packages/01/5f/091979a25c9a6c4ba064716cfdfe9431f78ed6ffba4bd05ae01eee3532e9/fonttools-4.58.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ec26784610056a770e15a60f9920cee26ae10d44d1e43271ea652dadf4e7a236", size = 4866191, upload-time = "2025-06-06T14:50:32.188Z" }, - { url = "https://files.pythonhosted.org/packages/9d/09/3944d0ece4a39560918cba37c2e0453a5f826b665a6db0b43abbd9dbe7e1/fonttools-4.58.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ed0a71d57dd427c0fb89febd08cac9b925284d2a8888e982a6c04714b82698d7", size = 5003867, upload-time = "2025-06-06T14:50:34.323Z" }, - { url = "https://files.pythonhosted.org/packages/68/97/190b8f9ba22f8b7d07df2faa9fd7087b453776d0705d3cb5b0cbd89b8ef0/fonttools-4.58.2-cp313-cp313-win32.whl", hash = "sha256:994e362b01460aa863ef0cb41a29880bc1a498c546952df465deff7abf75587a", size = 2175688, upload-time = "2025-06-06T14:50:36.211Z" }, - { url = "https://files.pythonhosted.org/packages/94/ea/0e6d4a39528dbb6e0f908c2ad219975be0a506ed440fddf5453b90f76981/fonttools-4.58.2-cp313-cp313-win_amd64.whl", hash = "sha256:f95dec862d7c395f2d4efe0535d9bdaf1e3811e51b86432fa2a77e73f8195756", size = 2226464, upload-time = "2025-06-06T14:50:38.862Z" }, - { url = "https://files.pythonhosted.org/packages/e8/e5/c1cb8ebabb80be76d4d28995da9416816653f8f572920ab5e3d2e3ac8285/fonttools-4.58.2-py3-none-any.whl", hash = "sha256:84f4b0bcfa046254a65ee7117094b4907e22dc98097a220ef108030eb3c15596", size = 1114597, upload-time = "2025-06-06T14:50:56.619Z" }, +version = "4.58.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/2e/5a/1124b2c8cb3a8015faf552e92714040bcdbc145dfa29928891b02d147a18/fonttools-4.58.4.tar.gz", hash = "sha256:928a8009b9884ed3aae17724b960987575155ca23c6f0b8146e400cc9e0d44ba", size = 3525026, upload-time = "2025-06-13T17:25:15.426Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/17/7b/cc6e9bb41bab223bd2dc70ba0b21386b85f604e27f4c3206b4205085a2ab/fonttools-4.58.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:a3841991c9ee2dc0562eb7f23d333d34ce81e8e27c903846f0487da21e0028eb", size = 2768901, upload-time = "2025-06-13T17:24:05.901Z" }, + { url = "https://files.pythonhosted.org/packages/3d/15/98d75df9f2b4e7605f3260359ad6e18e027c11fa549f74fce567270ac891/fonttools-4.58.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3c98f91b6a9604e7ffb5ece6ea346fa617f967c2c0944228801246ed56084664", size = 2328696, upload-time = "2025-06-13T17:24:09.18Z" }, + { url = "https://files.pythonhosted.org/packages/a8/c8/dc92b80f5452c9c40164e01b3f78f04b835a00e673bd9355ca257008ff61/fonttools-4.58.4-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ab9f891eb687ddf6a4e5f82901e00f992e18012ca97ab7acd15f13632acd14c1", size = 5018830, upload-time = "2025-06-13T17:24:11.282Z" }, + { url = "https://files.pythonhosted.org/packages/19/48/8322cf177680505d6b0b6062e204f01860cb573466a88077a9b795cb70e8/fonttools-4.58.4-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:891c5771e8f0094b7c0dc90eda8fc75e72930b32581418f2c285a9feedfd9a68", size = 4960922, upload-time = "2025-06-13T17:24:14.9Z" }, + { url = "https://files.pythonhosted.org/packages/14/e0/2aff149ed7eb0916de36da513d473c6fff574a7146891ce42de914899395/fonttools-4.58.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:43ba4d9646045c375d22e3473b7d82b18b31ee2ac715cd94220ffab7bc2d5c1d", size = 4997135, upload-time = "2025-06-13T17:24:16.959Z" }, + { url = "https://files.pythonhosted.org/packages/e6/6f/4d9829b29a64a2e63a121cb11ecb1b6a9524086eef3e35470949837a1692/fonttools-4.58.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:33d19f16e6d2ffd6669bda574a6589941f6c99a8d5cfb9f464038244c71555de", size = 5108701, upload-time = "2025-06-13T17:24:18.849Z" }, + { url = "https://files.pythonhosted.org/packages/6f/1e/2d656ddd1b0cd0d222f44b2d008052c2689e66b702b9af1cd8903ddce319/fonttools-4.58.4-cp311-cp311-win32.whl", hash = "sha256:b59e5109b907da19dc9df1287454821a34a75f2632a491dd406e46ff432c2a24", size = 2200177, upload-time = "2025-06-13T17:24:20.823Z" }, + { url = "https://files.pythonhosted.org/packages/fb/83/ba71ad053fddf4157cb0697c8da8eff6718d059f2a22986fa5f312b49c92/fonttools-4.58.4-cp311-cp311-win_amd64.whl", hash = "sha256:3d471a5b567a0d1648f2e148c9a8bcf00d9ac76eb89e976d9976582044cc2509", size = 2247892, upload-time = "2025-06-13T17:24:22.927Z" }, + { url = "https://files.pythonhosted.org/packages/04/3c/1d1792bfe91ef46f22a3d23b4deb514c325e73c17d4f196b385b5e2faf1c/fonttools-4.58.4-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:462211c0f37a278494e74267a994f6be9a2023d0557aaa9ecbcbfce0f403b5a6", size = 2754082, upload-time = "2025-06-13T17:24:24.862Z" }, + { url = "https://files.pythonhosted.org/packages/2a/1f/2b261689c901a1c3bc57a6690b0b9fc21a9a93a8b0c83aae911d3149f34e/fonttools-4.58.4-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:0c7a12fb6f769165547f00fcaa8d0df9517603ae7e04b625e5acb8639809b82d", size = 2321677, upload-time = "2025-06-13T17:24:26.815Z" }, + { url = "https://files.pythonhosted.org/packages/fe/6b/4607add1755a1e6581ae1fc0c9a640648e0d9cdd6591cc2d581c2e07b8c3/fonttools-4.58.4-cp312-cp312-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:2d42c63020a922154add0a326388a60a55504629edc3274bc273cd3806b4659f", size = 4896354, upload-time = "2025-06-13T17:24:28.428Z" }, + { url = "https://files.pythonhosted.org/packages/cd/95/34b4f483643d0cb11a1f830b72c03fdd18dbd3792d77a2eb2e130a96fada/fonttools-4.58.4-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8f2b4e6fd45edc6805f5f2c355590b092ffc7e10a945bd6a569fc66c1d2ae7aa", size = 4941633, upload-time = "2025-06-13T17:24:30.568Z" }, + { url = "https://files.pythonhosted.org/packages/81/ac/9bafbdb7694059c960de523e643fa5a61dd2f698f3f72c0ca18ae99257c7/fonttools-4.58.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:f155b927f6efb1213a79334e4cb9904d1e18973376ffc17a0d7cd43d31981f1e", size = 4886170, upload-time = "2025-06-13T17:24:32.724Z" }, + { url = "https://files.pythonhosted.org/packages/ae/44/a3a3b70d5709405f7525bb7cb497b4e46151e0c02e3c8a0e40e5e9fe030b/fonttools-4.58.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e38f687d5de97c7fb7da3e58169fb5ba349e464e141f83c3c2e2beb91d317816", size = 5037851, upload-time = "2025-06-13T17:24:35.034Z" }, + { url = "https://files.pythonhosted.org/packages/21/cb/e8923d197c78969454eb876a4a55a07b59c9c4c46598f02b02411dc3b45c/fonttools-4.58.4-cp312-cp312-win32.whl", hash = "sha256:636c073b4da9db053aa683db99580cac0f7c213a953b678f69acbca3443c12cc", size = 2187428, upload-time = "2025-06-13T17:24:36.996Z" }, + { url = "https://files.pythonhosted.org/packages/46/e6/fe50183b1a0e1018e7487ee740fa8bb127b9f5075a41e20d017201e8ab14/fonttools-4.58.4-cp312-cp312-win_amd64.whl", hash = "sha256:82e8470535743409b30913ba2822e20077acf9ea70acec40b10fcf5671dceb58", size = 2236649, upload-time = "2025-06-13T17:24:38.985Z" }, + { url = "https://files.pythonhosted.org/packages/d4/4f/c05cab5fc1a4293e6bc535c6cb272607155a0517700f5418a4165b7f9ec8/fonttools-4.58.4-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:5f4a64846495c543796fa59b90b7a7a9dff6839bd852741ab35a71994d685c6d", size = 2745197, upload-time = "2025-06-13T17:24:40.645Z" }, + { url = "https://files.pythonhosted.org/packages/3e/d3/49211b1f96ae49308f4f78ca7664742377a6867f00f704cdb31b57e4b432/fonttools-4.58.4-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e80661793a5d4d7ad132a2aa1eae2e160fbdbb50831a0edf37c7c63b2ed36574", size = 2317272, upload-time = "2025-06-13T17:24:43.428Z" }, + { url = "https://files.pythonhosted.org/packages/b2/11/c9972e46a6abd752a40a46960e431c795ad1f306775fc1f9e8c3081a1274/fonttools-4.58.4-cp313-cp313-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:fe5807fc64e4ba5130f1974c045a6e8d795f3b7fb6debfa511d1773290dbb76b", size = 4877184, upload-time = "2025-06-13T17:24:45.527Z" }, + { url = "https://files.pythonhosted.org/packages/ea/24/5017c01c9ef8df572cc9eaf9f12be83ad8ed722ff6dc67991d3d752956e4/fonttools-4.58.4-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b610b9bef841cb8f4b50472494158b1e347d15cad56eac414c722eda695a6cfd", size = 4939445, upload-time = "2025-06-13T17:24:47.647Z" }, + { url = "https://files.pythonhosted.org/packages/79/b0/538cc4d0284b5a8826b4abed93a69db52e358525d4b55c47c8cef3669767/fonttools-4.58.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:2daa7f0e213c38f05f054eb5e1730bd0424aebddbeac094489ea1585807dd187", size = 4878800, upload-time = "2025-06-13T17:24:49.766Z" }, + { url = "https://files.pythonhosted.org/packages/5a/9b/a891446b7a8250e65bffceb248508587958a94db467ffd33972723ab86c9/fonttools-4.58.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:66cccb6c0b944496b7f26450e9a66e997739c513ffaac728d24930df2fd9d35b", size = 5021259, upload-time = "2025-06-13T17:24:51.754Z" }, + { url = "https://files.pythonhosted.org/packages/17/b2/c4d2872cff3ace3ddd1388bf15b76a1d8d5313f0a61f234e9aed287e674d/fonttools-4.58.4-cp313-cp313-win32.whl", hash = "sha256:94d2aebb5ca59a5107825520fde596e344652c1f18170ef01dacbe48fa60c889", size = 2185824, upload-time = "2025-06-13T17:24:54.324Z" }, + { url = "https://files.pythonhosted.org/packages/98/57/cddf8bcc911d4f47dfca1956c1e3aeeb9f7c9b8e88b2a312fe8c22714e0b/fonttools-4.58.4-cp313-cp313-win_amd64.whl", hash = "sha256:b554bd6e80bba582fd326ddab296e563c20c64dca816d5e30489760e0c41529f", size = 2236382, upload-time = "2025-06-13T17:24:56.291Z" }, + { url = "https://files.pythonhosted.org/packages/0b/2f/c536b5b9bb3c071e91d536a4d11f969e911dbb6b227939f4c5b0bca090df/fonttools-4.58.4-py3-none-any.whl", hash = "sha256:a10ce13a13f26cbb9f37512a4346bb437ad7e002ff6fa966a7ce7ff5ac3528bd", size = 1114660, upload-time = "2025-06-13T17:25:13.321Z" }, ] [[package]] @@ -657,15 +657,15 @@ wheels = [ [[package]] name = "hypothesis" -version = "6.135.4" +version = "6.135.10" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "attrs" }, { name = "sortedcontainers" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/ae/59/7022ef95715701cd90ac0cf04582e3507492ab200f370fd7ef12d80dda75/hypothesis-6.135.4.tar.gz", hash = "sha256:c63f6fc56840558c5c5e2441dd91fad1709da60bde756b816d4b89944e50a52f", size = 451895, upload-time = "2025-06-09T02:31:38.766Z" } +sdist = { url = "https://files.pythonhosted.org/packages/c8/8e/6176e9b3e51fbab6dab1e572116605dbc54eadda0c60dd45927f601d3c60/hypothesis-6.135.10.tar.gz", hash = "sha256:ce224e310012e40b8e3aa6edba226c032c57bbcbdccad41212ab6d2d74b602cf", size = 452518, upload-time = "2025-06-15T06:02:07.517Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/31/d4/25b3a9f35199eb1904967ca3e6db4afd636911fa39695760b0afac84f38a/hypothesis-6.135.4-py3-none-any.whl", hash = "sha256:6a3b13ce35d43e14aaf6a6ca4cc411e5342be5d05b77977499d07cf6a61e6e71", size = 517950, upload-time = "2025-06-09T02:31:34.463Z" }, + { url = "https://files.pythonhosted.org/packages/a9/e5/8c62bd37d2815f37a2886be6b9d5e037d14cc3f6adc377711f323617b113/hypothesis-6.135.10-py3-none-any.whl", hash = "sha256:275012ee9a7a1a64fd38745c2b7a07e838fc9f738d49c97a881d235b53fe28c1", size = 518624, upload-time = "2025-06-15T06:02:04.227Z" }, ] [[package]] @@ -1869,15 +1869,16 @@ wheels = [ [[package]] name = "pytest-cov" -version = "6.1.1" +version = "6.2.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "coverage", extra = ["toml"] }, + { name = "pluggy" }, { name = "pytest" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/25/69/5f1e57f6c5a39f81411b550027bf72842c4567ff5fd572bed1edc9e4b5d9/pytest_cov-6.1.1.tar.gz", hash = "sha256:46935f7aaefba760e716c2ebfbe1c216240b9592966e7da99ea8292d4d3e2a0a", size = 66857, upload-time = "2025-04-05T14:07:51.592Z" } +sdist = { url = "https://files.pythonhosted.org/packages/18/99/668cade231f434aaa59bbfbf49469068d2ddd945000621d3d165d2e7dd7b/pytest_cov-6.2.1.tar.gz", hash = "sha256:25cc6cc0a5358204b8108ecedc51a9b57b34cc6b8c967cc2c01a4e00d8a67da2", size = 69432, upload-time = "2025-06-12T10:47:47.684Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/28/d0/def53b4a790cfb21483016430ed828f64830dd981ebe1089971cd10cab25/pytest_cov-6.1.1-py3-none-any.whl", hash = "sha256:bddf29ed2d0ab6f4df17b4c55b0a657287db8684af9c42ea546b21b1041b3dde", size = 23841, upload-time = "2025-04-05T14:07:49.641Z" }, + { url = "https://files.pythonhosted.org/packages/bc/16/4ea354101abb1287856baa4af2732be351c7bee728065aed451b678153fd/pytest_cov-6.2.1-py3-none-any.whl", hash = "sha256:f5bc4c23f42f1cdd23c70b1dab1bbaef4fc505ba950d53e0081d0730dd7e86d5", size = 24644, upload-time = "2025-06-12T10:47:45.932Z" }, ] [[package]] @@ -2040,59 +2041,47 @@ wheels = [ [[package]] name = "pyzmq" -version = "26.4.0" +version = "27.0.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "cffi", marker = "implementation_name == 'pypy'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/b1/11/b9213d25230ac18a71b39b3723494e57adebe36e066397b961657b3b41c1/pyzmq-26.4.0.tar.gz", hash = "sha256:4bd13f85f80962f91a651a7356fe0472791a5f7a92f227822b5acf44795c626d", size = 278293, upload-time = "2025-04-04T12:05:44.049Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/32/6d/234e3b0aa82fd0290b1896e9992f56bdddf1f97266110be54d0177a9d2d9/pyzmq-26.4.0-cp311-cp311-macosx_10_15_universal2.whl", hash = "sha256:bfcf82644c9b45ddd7cd2a041f3ff8dce4a0904429b74d73a439e8cab1bd9e54", size = 1339723, upload-time = "2025-04-04T12:03:24.358Z" }, - { url = "https://files.pythonhosted.org/packages/4f/11/6d561efe29ad83f7149a7cd48e498e539ed09019c6cd7ecc73f4cc725028/pyzmq-26.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e9bcae3979b2654d5289d3490742378b2f3ce804b0b5fd42036074e2bf35b030", size = 672645, upload-time = "2025-04-04T12:03:25.693Z" }, - { url = "https://files.pythonhosted.org/packages/19/fd/81bfe3e23f418644660bad1a90f0d22f0b3eebe33dd65a79385530bceb3d/pyzmq-26.4.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ccdff8ac4246b6fb60dcf3982dfaeeff5dd04f36051fe0632748fc0aa0679c01", size = 910133, upload-time = "2025-04-04T12:03:27.625Z" }, - { url = "https://files.pythonhosted.org/packages/97/68/321b9c775595ea3df832a9516252b653fe32818db66fdc8fa31c9b9fce37/pyzmq-26.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4550af385b442dc2d55ab7717837812799d3674cb12f9a3aa897611839c18e9e", size = 867428, upload-time = "2025-04-04T12:03:29.004Z" }, - { url = "https://files.pythonhosted.org/packages/4e/6e/159cbf2055ef36aa2aa297e01b24523176e5b48ead283c23a94179fb2ba2/pyzmq-26.4.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:2f9f7ffe9db1187a253fca95191854b3fda24696f086e8789d1d449308a34b88", size = 862409, upload-time = "2025-04-04T12:03:31.032Z" }, - { url = "https://files.pythonhosted.org/packages/05/1c/45fb8db7be5a7d0cadea1070a9cbded5199a2d578de2208197e592f219bd/pyzmq-26.4.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:3709c9ff7ba61589b7372923fd82b99a81932b592a5c7f1a24147c91da9a68d6", size = 1205007, upload-time = "2025-04-04T12:03:32.687Z" }, - { url = "https://files.pythonhosted.org/packages/f8/fa/658c7f583af6498b463f2fa600f34e298e1b330886f82f1feba0dc2dd6c3/pyzmq-26.4.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:f8f3c30fb2d26ae5ce36b59768ba60fb72507ea9efc72f8f69fa088450cff1df", size = 1514599, upload-time = "2025-04-04T12:03:34.084Z" }, - { url = "https://files.pythonhosted.org/packages/4d/d7/44d641522353ce0a2bbd150379cb5ec32f7120944e6bfba4846586945658/pyzmq-26.4.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:382a4a48c8080e273427fc692037e3f7d2851959ffe40864f2db32646eeb3cef", size = 1414546, upload-time = "2025-04-04T12:03:35.478Z" }, - { url = "https://files.pythonhosted.org/packages/72/76/c8ed7263218b3d1e9bce07b9058502024188bd52cc0b0a267a9513b431fc/pyzmq-26.4.0-cp311-cp311-win32.whl", hash = "sha256:d56aad0517d4c09e3b4f15adebba8f6372c5102c27742a5bdbfc74a7dceb8fca", size = 579247, upload-time = "2025-04-04T12:03:36.846Z" }, - { url = "https://files.pythonhosted.org/packages/c3/d0/2d9abfa2571a0b1a67c0ada79a8aa1ba1cce57992d80f771abcdf99bb32c/pyzmq-26.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:963977ac8baed7058c1e126014f3fe58b3773f45c78cce7af5c26c09b6823896", size = 644727, upload-time = "2025-04-04T12:03:38.578Z" }, - { url = "https://files.pythonhosted.org/packages/0d/d1/c8ad82393be6ccedfc3c9f3adb07f8f3976e3c4802640fe3f71441941e70/pyzmq-26.4.0-cp311-cp311-win_arm64.whl", hash = "sha256:c0c8e8cadc81e44cc5088fcd53b9b3b4ce9344815f6c4a03aec653509296fae3", size = 559942, upload-time = "2025-04-04T12:03:40.143Z" }, - { url = "https://files.pythonhosted.org/packages/10/44/a778555ebfdf6c7fc00816aad12d185d10a74d975800341b1bc36bad1187/pyzmq-26.4.0-cp312-cp312-macosx_10_15_universal2.whl", hash = "sha256:5227cb8da4b6f68acfd48d20c588197fd67745c278827d5238c707daf579227b", size = 1341586, upload-time = "2025-04-04T12:03:41.954Z" }, - { url = "https://files.pythonhosted.org/packages/9c/4f/f3a58dc69ac757e5103be3bd41fb78721a5e17da7cc617ddb56d973a365c/pyzmq-26.4.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e1c07a7fa7f7ba86554a2b1bef198c9fed570c08ee062fd2fd6a4dcacd45f905", size = 665880, upload-time = "2025-04-04T12:03:43.45Z" }, - { url = "https://files.pythonhosted.org/packages/fe/45/50230bcfb3ae5cb98bee683b6edeba1919f2565d7cc1851d3c38e2260795/pyzmq-26.4.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae775fa83f52f52de73183f7ef5395186f7105d5ed65b1ae65ba27cb1260de2b", size = 902216, upload-time = "2025-04-04T12:03:45.572Z" }, - { url = "https://files.pythonhosted.org/packages/41/59/56bbdc5689be5e13727491ad2ba5efd7cd564365750514f9bc8f212eef82/pyzmq-26.4.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:66c760d0226ebd52f1e6b644a9e839b5db1e107a23f2fcd46ec0569a4fdd4e63", size = 859814, upload-time = "2025-04-04T12:03:47.188Z" }, - { url = "https://files.pythonhosted.org/packages/81/b1/57db58cfc8af592ce94f40649bd1804369c05b2190e4cbc0a2dad572baeb/pyzmq-26.4.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:ef8c6ecc1d520debc147173eaa3765d53f06cd8dbe7bd377064cdbc53ab456f5", size = 855889, upload-time = "2025-04-04T12:03:49.223Z" }, - { url = "https://files.pythonhosted.org/packages/e8/92/47542e629cbac8f221c230a6d0f38dd3d9cff9f6f589ed45fdf572ffd726/pyzmq-26.4.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:3150ef4084e163dec29ae667b10d96aad309b668fac6810c9e8c27cf543d6e0b", size = 1197153, upload-time = "2025-04-04T12:03:50.591Z" }, - { url = "https://files.pythonhosted.org/packages/07/e5/b10a979d1d565d54410afc87499b16c96b4a181af46e7645ab4831b1088c/pyzmq-26.4.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:4448c9e55bf8329fa1dcedd32f661bf611214fa70c8e02fee4347bc589d39a84", size = 1507352, upload-time = "2025-04-04T12:03:52.473Z" }, - { url = "https://files.pythonhosted.org/packages/ab/58/5a23db84507ab9c01c04b1232a7a763be66e992aa2e66498521bbbc72a71/pyzmq-26.4.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:e07dde3647afb084d985310d067a3efa6efad0621ee10826f2cb2f9a31b89d2f", size = 1406834, upload-time = "2025-04-04T12:03:54Z" }, - { url = "https://files.pythonhosted.org/packages/22/74/aaa837b331580c13b79ac39396601fb361454ee184ca85e8861914769b99/pyzmq-26.4.0-cp312-cp312-win32.whl", hash = "sha256:ba034a32ecf9af72adfa5ee383ad0fd4f4e38cdb62b13624278ef768fe5b5b44", size = 577992, upload-time = "2025-04-04T12:03:55.815Z" }, - { url = "https://files.pythonhosted.org/packages/30/0f/55f8c02c182856743b82dde46b2dc3e314edda7f1098c12a8227eeda0833/pyzmq-26.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:056a97aab4064f526ecb32f4343917a4022a5d9efb6b9df990ff72e1879e40be", size = 640466, upload-time = "2025-04-04T12:03:57.231Z" }, - { url = "https://files.pythonhosted.org/packages/e4/29/073779afc3ef6f830b8de95026ef20b2d1ec22d0324d767748d806e57379/pyzmq-26.4.0-cp312-cp312-win_arm64.whl", hash = "sha256:2f23c750e485ce1eb639dbd576d27d168595908aa2d60b149e2d9e34c9df40e0", size = 556342, upload-time = "2025-04-04T12:03:59.218Z" }, - { url = "https://files.pythonhosted.org/packages/d7/20/fb2c92542488db70f833b92893769a569458311a76474bda89dc4264bd18/pyzmq-26.4.0-cp313-cp313-macosx_10_15_universal2.whl", hash = "sha256:c43fac689880f5174d6fc864857d1247fe5cfa22b09ed058a344ca92bf5301e3", size = 1339484, upload-time = "2025-04-04T12:04:00.671Z" }, - { url = "https://files.pythonhosted.org/packages/58/29/2f06b9cabda3a6ea2c10f43e67ded3e47fc25c54822e2506dfb8325155d4/pyzmq-26.4.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:902aca7eba477657c5fb81c808318460328758e8367ecdd1964b6330c73cae43", size = 666106, upload-time = "2025-04-04T12:04:02.366Z" }, - { url = "https://files.pythonhosted.org/packages/77/e4/dcf62bd29e5e190bd21bfccaa4f3386e01bf40d948c239239c2f1e726729/pyzmq-26.4.0-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e5e48a830bfd152fe17fbdeaf99ac5271aa4122521bf0d275b6b24e52ef35eb6", size = 902056, upload-time = "2025-04-04T12:04:03.919Z" }, - { url = "https://files.pythonhosted.org/packages/1a/cf/b36b3d7aea236087d20189bec1a87eeb2b66009731d7055e5c65f845cdba/pyzmq-26.4.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:31be2b6de98c824c06f5574331f805707c667dc8f60cb18580b7de078479891e", size = 860148, upload-time = "2025-04-04T12:04:05.581Z" }, - { url = "https://files.pythonhosted.org/packages/18/a6/f048826bc87528c208e90604c3bf573801e54bd91e390cbd2dfa860e82dc/pyzmq-26.4.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:6332452034be001bbf3206ac59c0d2a7713de5f25bb38b06519fc6967b7cf771", size = 855983, upload-time = "2025-04-04T12:04:07.096Z" }, - { url = "https://files.pythonhosted.org/packages/0a/27/454d34ab6a1d9772a36add22f17f6b85baf7c16e14325fa29e7202ca8ee8/pyzmq-26.4.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:da8c0f5dd352136853e6a09b1b986ee5278dfddfebd30515e16eae425c872b30", size = 1197274, upload-time = "2025-04-04T12:04:08.523Z" }, - { url = "https://files.pythonhosted.org/packages/f4/3d/7abfeab6b83ad38aa34cbd57c6fc29752c391e3954fd12848bd8d2ec0df6/pyzmq-26.4.0-cp313-cp313-musllinux_1_1_i686.whl", hash = "sha256:f4ccc1a0a2c9806dda2a2dd118a3b7b681e448f3bb354056cad44a65169f6d86", size = 1507120, upload-time = "2025-04-04T12:04:10.58Z" }, - { url = "https://files.pythonhosted.org/packages/13/ff/bc8d21dbb9bc8705126e875438a1969c4f77e03fc8565d6901c7933a3d01/pyzmq-26.4.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:1c0b5fceadbab461578daf8d1dcc918ebe7ddd2952f748cf30c7cf2de5d51101", size = 1406738, upload-time = "2025-04-04T12:04:12.509Z" }, - { url = "https://files.pythonhosted.org/packages/f5/5d/d4cd85b24de71d84d81229e3bbb13392b2698432cf8fdcea5afda253d587/pyzmq-26.4.0-cp313-cp313-win32.whl", hash = "sha256:28e2b0ff5ba4b3dd11062d905682bad33385cfa3cc03e81abd7f0822263e6637", size = 577826, upload-time = "2025-04-04T12:04:14.289Z" }, - { url = "https://files.pythonhosted.org/packages/c6/6c/f289c1789d7bb6e5a3b3bef7b2a55089b8561d17132be7d960d3ff33b14e/pyzmq-26.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:23ecc9d241004c10e8b4f49d12ac064cd7000e1643343944a10df98e57bc544b", size = 640406, upload-time = "2025-04-04T12:04:15.757Z" }, - { url = "https://files.pythonhosted.org/packages/b3/99/676b8851cb955eb5236a0c1e9ec679ea5ede092bf8bf2c8a68d7e965cac3/pyzmq-26.4.0-cp313-cp313-win_arm64.whl", hash = "sha256:1edb0385c7f025045d6e0f759d4d3afe43c17a3d898914ec6582e6f464203c08", size = 556216, upload-time = "2025-04-04T12:04:17.212Z" }, - { url = "https://files.pythonhosted.org/packages/65/c2/1fac340de9d7df71efc59d9c50fc7a635a77b103392d1842898dd023afcb/pyzmq-26.4.0-cp313-cp313t-macosx_10_15_universal2.whl", hash = "sha256:93a29e882b2ba1db86ba5dd5e88e18e0ac6b627026c5cfbec9983422011b82d4", size = 1333769, upload-time = "2025-04-04T12:04:18.665Z" }, - { url = "https://files.pythonhosted.org/packages/5c/c7/6c03637e8d742c3b00bec4f5e4cd9d1c01b2f3694c6f140742e93ca637ed/pyzmq-26.4.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb45684f276f57110bb89e4300c00f1233ca631f08f5f42528a5c408a79efc4a", size = 658826, upload-time = "2025-04-04T12:04:20.405Z" }, - { url = "https://files.pythonhosted.org/packages/a5/97/a8dca65913c0f78e0545af2bb5078aebfc142ca7d91cdaffa1fbc73e5dbd/pyzmq-26.4.0-cp313-cp313t-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f72073e75260cb301aad4258ad6150fa7f57c719b3f498cb91e31df16784d89b", size = 891650, upload-time = "2025-04-04T12:04:22.413Z" }, - { url = "https://files.pythonhosted.org/packages/7d/7e/f63af1031eb060bf02d033732b910fe48548dcfdbe9c785e9f74a6cc6ae4/pyzmq-26.4.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:be37e24b13026cfedd233bcbbccd8c0bcd2fdd186216094d095f60076201538d", size = 849776, upload-time = "2025-04-04T12:04:23.959Z" }, - { url = "https://files.pythonhosted.org/packages/f6/fa/1a009ce582802a895c0d5fe9413f029c940a0a8ee828657a3bb0acffd88b/pyzmq-26.4.0-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:237b283044934d26f1eeff4075f751b05d2f3ed42a257fc44386d00df6a270cf", size = 842516, upload-time = "2025-04-04T12:04:25.449Z" }, - { url = "https://files.pythonhosted.org/packages/6e/bc/f88b0bad0f7a7f500547d71e99f10336f2314e525d4ebf576a1ea4a1d903/pyzmq-26.4.0-cp313-cp313t-musllinux_1_1_aarch64.whl", hash = "sha256:b30f862f6768b17040929a68432c8a8be77780317f45a353cb17e423127d250c", size = 1189183, upload-time = "2025-04-04T12:04:27.035Z" }, - { url = "https://files.pythonhosted.org/packages/d9/8c/db446a3dd9cf894406dec2e61eeffaa3c07c3abb783deaebb9812c4af6a5/pyzmq-26.4.0-cp313-cp313t-musllinux_1_1_i686.whl", hash = "sha256:c80fcd3504232f13617c6ab501124d373e4895424e65de8b72042333316f64a8", size = 1495501, upload-time = "2025-04-04T12:04:28.833Z" }, - { url = "https://files.pythonhosted.org/packages/05/4c/bf3cad0d64c3214ac881299c4562b815f05d503bccc513e3fd4fdc6f67e4/pyzmq-26.4.0-cp313-cp313t-musllinux_1_1_x86_64.whl", hash = "sha256:26a2a7451606b87f67cdeca2c2789d86f605da08b4bd616b1a9981605ca3a364", size = 1395540, upload-time = "2025-04-04T12:04:30.562Z" }, - { url = "https://files.pythonhosted.org/packages/04/52/a70fcd5592715702248306d8e1729c10742c2eac44529984413b05c68658/pyzmq-26.4.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:4478b14cb54a805088299c25a79f27eaf530564a7a4f72bf432a040042b554eb", size = 834405, upload-time = "2025-04-04T12:05:13.3Z" }, - { url = "https://files.pythonhosted.org/packages/25/f9/1a03f1accff16b3af1a6fa22cbf7ced074776abbf688b2e9cb4629700c62/pyzmq-26.4.0-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8a28ac29c60e4ba84b5f58605ace8ad495414a724fe7aceb7cf06cd0598d04e1", size = 569578, upload-time = "2025-04-04T12:05:15.36Z" }, - { url = "https://files.pythonhosted.org/packages/76/0c/3a633acd762aa6655fcb71fa841907eae0ab1e8582ff494b137266de341d/pyzmq-26.4.0-pp311-pypy311_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:43b03c1ceea27c6520124f4fb2ba9c647409b9abdf9a62388117148a90419494", size = 798248, upload-time = "2025-04-04T12:05:17.376Z" }, - { url = "https://files.pythonhosted.org/packages/cd/cc/6c99c84aa60ac1cc56747bed6be8ce6305b9b861d7475772e7a25ce019d3/pyzmq-26.4.0-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7731abd23a782851426d4e37deb2057bf9410848a4459b5ede4fe89342e687a9", size = 756757, upload-time = "2025-04-04T12:05:19.19Z" }, - { url = "https://files.pythonhosted.org/packages/13/9c/d8073bd898eb896e94c679abe82e47506e2b750eb261cf6010ced869797c/pyzmq-26.4.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:a222ad02fbe80166b0526c038776e8042cd4e5f0dec1489a006a1df47e9040e0", size = 555371, upload-time = "2025-04-04T12:05:20.702Z" }, +sdist = { url = "https://files.pythonhosted.org/packages/f1/06/50a4e9648b3e8b992bef8eb632e457307553a89d294103213cfd47b3da69/pyzmq-27.0.0.tar.gz", hash = "sha256:b1f08eeb9ce1510e6939b6e5dcd46a17765e2333daae78ecf4606808442e52cf", size = 280478, upload-time = "2025-06-13T14:09:07.087Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/44/df/84c630654106d9bd9339cdb564aa941ed41b023a0264251d6743766bb50e/pyzmq-27.0.0-cp311-cp311-macosx_10_15_universal2.whl", hash = "sha256:21457825249b2a53834fa969c69713f8b5a79583689387a5e7aed880963ac564", size = 1332718, upload-time = "2025-06-13T14:07:16.555Z" }, + { url = "https://files.pythonhosted.org/packages/c1/8e/f6a5461a07654d9840d256476434ae0ff08340bba562a455f231969772cb/pyzmq-27.0.0-cp311-cp311-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:1958947983fef513e6e98eff9cb487b60bf14f588dc0e6bf35fa13751d2c8251", size = 908248, upload-time = "2025-06-13T14:07:18.033Z" }, + { url = "https://files.pythonhosted.org/packages/7c/93/82863e8d695a9a3ae424b63662733ae204a295a2627d52af2f62c2cd8af9/pyzmq-27.0.0-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c0dc628b5493f9a8cd9844b8bee9732ef587ab00002157c9329e4fc0ef4d3afa", size = 668647, upload-time = "2025-06-13T14:07:19.378Z" }, + { url = "https://files.pythonhosted.org/packages/f3/85/15278769b348121eacdbfcbd8c4d40f1102f32fa6af5be1ffc032ed684be/pyzmq-27.0.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f7bbe9e1ed2c8d3da736a15694d87c12493e54cc9dc9790796f0321794bbc91f", size = 856600, upload-time = "2025-06-13T14:07:20.906Z" }, + { url = "https://files.pythonhosted.org/packages/d4/af/1c469b3d479bd095edb28e27f12eee10b8f00b356acbefa6aeb14dd295d1/pyzmq-27.0.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:dc1091f59143b471d19eb64f54bae4f54bcf2a466ffb66fe45d94d8d734eb495", size = 1657748, upload-time = "2025-06-13T14:07:22.549Z" }, + { url = "https://files.pythonhosted.org/packages/8c/f4/17f965d0ee6380b1d6326da842a50e4b8b9699745161207945f3745e8cb5/pyzmq-27.0.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:7011ade88c8e535cf140f8d1a59428676fbbce7c6e54fefce58bf117aefb6667", size = 2034311, upload-time = "2025-06-13T14:07:23.966Z" }, + { url = "https://files.pythonhosted.org/packages/e0/6e/7c391d81fa3149fd759de45d298003de6cfab343fb03e92c099821c448db/pyzmq-27.0.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:2c386339d7e3f064213aede5d03d054b237937fbca6dd2197ac8cf3b25a6b14e", size = 1893630, upload-time = "2025-06-13T14:07:25.899Z" }, + { url = "https://files.pythonhosted.org/packages/0e/e0/eaffe7a86f60e556399e224229e7769b717f72fec0706b70ab2c03aa04cb/pyzmq-27.0.0-cp311-cp311-win32.whl", hash = "sha256:0546a720c1f407b2172cb04b6b094a78773491497e3644863cf5c96c42df8cff", size = 567706, upload-time = "2025-06-13T14:07:27.595Z" }, + { url = "https://files.pythonhosted.org/packages/c9/05/89354a8cffdcce6e547d48adaaf7be17007fc75572123ff4ca90a4ca04fc/pyzmq-27.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:15f39d50bd6c9091c67315ceb878a4f531957b121d2a05ebd077eb35ddc5efed", size = 630322, upload-time = "2025-06-13T14:07:28.938Z" }, + { url = "https://files.pythonhosted.org/packages/fa/07/4ab976d5e1e63976719389cc4f3bfd248a7f5f2bb2ebe727542363c61b5f/pyzmq-27.0.0-cp311-cp311-win_arm64.whl", hash = "sha256:c5817641eebb391a2268c27fecd4162448e03538387093cdbd8bf3510c316b38", size = 558435, upload-time = "2025-06-13T14:07:30.256Z" }, + { url = "https://files.pythonhosted.org/packages/93/a7/9ad68f55b8834ede477842214feba6a4c786d936c022a67625497aacf61d/pyzmq-27.0.0-cp312-abi3-macosx_10_15_universal2.whl", hash = "sha256:cbabc59dcfaac66655c040dfcb8118f133fb5dde185e5fc152628354c1598e52", size = 1305438, upload-time = "2025-06-13T14:07:31.676Z" }, + { url = "https://files.pythonhosted.org/packages/ba/ee/26aa0f98665a22bc90ebe12dced1de5f3eaca05363b717f6fb229b3421b3/pyzmq-27.0.0-cp312-abi3-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:cb0ac5179cba4b2f94f1aa208fbb77b62c4c9bf24dd446278b8b602cf85fcda3", size = 895095, upload-time = "2025-06-13T14:07:33.104Z" }, + { url = "https://files.pythonhosted.org/packages/cf/85/c57e7ab216ecd8aa4cc7e3b83b06cc4e9cf45c87b0afc095f10cd5ce87c1/pyzmq-27.0.0-cp312-abi3-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:53a48f0228eab6cbf69fde3aa3c03cbe04e50e623ef92ae395fce47ef8a76152", size = 651826, upload-time = "2025-06-13T14:07:34.831Z" }, + { url = "https://files.pythonhosted.org/packages/69/9a/9ea7e230feda9400fb0ae0d61d7d6ddda635e718d941c44eeab22a179d34/pyzmq-27.0.0-cp312-abi3-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:111db5f395e09f7e775f759d598f43cb815fc58e0147623c4816486e1a39dc22", size = 839750, upload-time = "2025-06-13T14:07:36.553Z" }, + { url = "https://files.pythonhosted.org/packages/08/66/4cebfbe71f3dfbd417011daca267539f62ed0fbc68105357b68bbb1a25b7/pyzmq-27.0.0-cp312-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:c8878011653dcdc27cc2c57e04ff96f0471e797f5c19ac3d7813a245bcb24371", size = 1641357, upload-time = "2025-06-13T14:07:38.21Z" }, + { url = "https://files.pythonhosted.org/packages/ac/f6/b0f62578c08d2471c791287149cb8c2aaea414ae98c6e995c7dbe008adfb/pyzmq-27.0.0-cp312-abi3-musllinux_1_2_i686.whl", hash = "sha256:c0ed2c1f335ba55b5fdc964622254917d6b782311c50e138863eda409fbb3b6d", size = 2020281, upload-time = "2025-06-13T14:07:39.599Z" }, + { url = "https://files.pythonhosted.org/packages/37/b9/4f670b15c7498495da9159edc374ec09c88a86d9cd5a47d892f69df23450/pyzmq-27.0.0-cp312-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:e918d70862d4cfd4b1c187310015646a14e1f5917922ab45b29f28f345eeb6be", size = 1877110, upload-time = "2025-06-13T14:07:41.027Z" }, + { url = "https://files.pythonhosted.org/packages/66/31/9dee25c226295b740609f0d46db2fe972b23b6f5cf786360980524a3ba92/pyzmq-27.0.0-cp312-abi3-win32.whl", hash = "sha256:88b4e43cab04c3c0f0d55df3b1eef62df2b629a1a369b5289a58f6fa8b07c4f4", size = 559297, upload-time = "2025-06-13T14:07:42.533Z" }, + { url = "https://files.pythonhosted.org/packages/9b/12/52da5509800f7ff2d287b2f2b4e636e7ea0f001181cba6964ff6c1537778/pyzmq-27.0.0-cp312-abi3-win_amd64.whl", hash = "sha256:dce4199bf5f648a902ce37e7b3afa286f305cd2ef7a8b6ec907470ccb6c8b371", size = 619203, upload-time = "2025-06-13T14:07:43.843Z" }, + { url = "https://files.pythonhosted.org/packages/93/6d/7f2e53b19d1edb1eb4f09ec7c3a1f945ca0aac272099eab757d15699202b/pyzmq-27.0.0-cp312-abi3-win_arm64.whl", hash = "sha256:56e46bbb85d52c1072b3f809cc1ce77251d560bc036d3a312b96db1afe76db2e", size = 551927, upload-time = "2025-06-13T14:07:45.51Z" }, + { url = "https://files.pythonhosted.org/packages/19/62/876b27c4ff777db4ceba1c69ea90d3c825bb4f8d5e7cd987ce5802e33c55/pyzmq-27.0.0-cp313-cp313t-macosx_10_15_universal2.whl", hash = "sha256:c36ad534c0c29b4afa088dc53543c525b23c0797e01b69fef59b1a9c0e38b688", size = 1340826, upload-time = "2025-06-13T14:07:46.881Z" }, + { url = "https://files.pythonhosted.org/packages/43/69/58ef8f4f59d3bcd505260c73bee87b008850f45edca40ddaba54273c35f4/pyzmq-27.0.0-cp313-cp313t-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:67855c14173aec36395d7777aaba3cc527b393821f30143fd20b98e1ff31fd38", size = 897283, upload-time = "2025-06-13T14:07:49.562Z" }, + { url = "https://files.pythonhosted.org/packages/43/15/93a0d0396700a60475ad3c5d42c5f1c308d3570bc94626b86c71ef9953e0/pyzmq-27.0.0-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8617c7d43cd8ccdb62aebe984bfed77ca8f036e6c3e46dd3dddda64b10f0ab7a", size = 660567, upload-time = "2025-06-13T14:07:51.364Z" }, + { url = "https://files.pythonhosted.org/packages/0e/b3/fe055513e498ca32f64509abae19b9c9eb4d7c829e02bd8997dd51b029eb/pyzmq-27.0.0-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:67bfbcbd0a04c575e8103a6061d03e393d9f80ffdb9beb3189261e9e9bc5d5e9", size = 847681, upload-time = "2025-06-13T14:07:52.77Z" }, + { url = "https://files.pythonhosted.org/packages/b6/4f/ff15300b00b5b602191f3df06bbc8dd4164e805fdd65bb77ffbb9c5facdc/pyzmq-27.0.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:5cd11d46d7b7e5958121b3eaf4cd8638eff3a720ec527692132f05a57f14341d", size = 1650148, upload-time = "2025-06-13T14:07:54.178Z" }, + { url = "https://files.pythonhosted.org/packages/c4/6f/84bdfff2a224a6f26a24249a342e5906993c50b0761e311e81b39aef52a7/pyzmq-27.0.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:b801c2e40c5aa6072c2f4876de8dccd100af6d9918d4d0d7aa54a1d982fd4f44", size = 2023768, upload-time = "2025-06-13T14:07:55.714Z" }, + { url = "https://files.pythonhosted.org/packages/64/39/dc2db178c26a42228c5ac94a9cc595030458aa64c8d796a7727947afbf55/pyzmq-27.0.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:20d5cb29e8c5f76a127c75b6e7a77e846bc4b655c373baa098c26a61b7ecd0ef", size = 1885199, upload-time = "2025-06-13T14:07:57.166Z" }, + { url = "https://files.pythonhosted.org/packages/c7/21/dae7b06a1f8cdee5d8e7a63d99c5d129c401acc40410bef2cbf42025e26f/pyzmq-27.0.0-cp313-cp313t-win32.whl", hash = "sha256:a20528da85c7ac7a19b7384e8c3f8fa707841fd85afc4ed56eda59d93e3d98ad", size = 575439, upload-time = "2025-06-13T14:07:58.959Z" }, + { url = "https://files.pythonhosted.org/packages/eb/bc/1709dc55f0970cf4cb8259e435e6773f9946f41a045c2cb90e870b7072da/pyzmq-27.0.0-cp313-cp313t-win_amd64.whl", hash = "sha256:d8229f2efece6a660ee211d74d91dbc2a76b95544d46c74c615e491900dc107f", size = 639933, upload-time = "2025-06-13T14:08:00.777Z" }, + { url = "https://files.pythonhosted.org/packages/98/a6/92394373b8dbc1edc9d53c951e8d3989d518185174ee54492ec27711779d/pyzmq-27.0.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:cd1dc59763effd1576f8368047c9c31468fce0af89d76b5067641137506792ae", size = 835948, upload-time = "2025-06-13T14:08:43.516Z" }, + { url = "https://files.pythonhosted.org/packages/56/f3/4dc38d75d9995bfc18773df3e41f2a2ca9b740b06f1a15dbf404077e7588/pyzmq-27.0.0-pp311-pypy311_pp73-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:60e8cc82d968174650c1860d7b716366caab9973787a1c060cf8043130f7d0f7", size = 799874, upload-time = "2025-06-13T14:08:45.017Z" }, + { url = "https://files.pythonhosted.org/packages/ab/ba/64af397e0f421453dc68e31d5e0784d554bf39013a2de0872056e96e58af/pyzmq-27.0.0-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:14fe7aaac86e4e93ea779a821967360c781d7ac5115b3f1a171ced77065a0174", size = 567400, upload-time = "2025-06-13T14:08:46.855Z" }, + { url = "https://files.pythonhosted.org/packages/63/87/ec956cbe98809270b59a22891d5758edae147a258e658bf3024a8254c855/pyzmq-27.0.0-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6ad0562d4e6abb785be3e4dd68599c41be821b521da38c402bc9ab2a8e7ebc7e", size = 747031, upload-time = "2025-06-13T14:08:48.419Z" }, + { url = "https://files.pythonhosted.org/packages/be/8a/4a3764a68abc02e2fbb0668d225b6fda5cd39586dd099cee8b2ed6ab0452/pyzmq-27.0.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:9df43a2459cd3a3563404c1456b2c4c69564daa7dbaf15724c09821a3329ce46", size = 544726, upload-time = "2025-06-13T14:08:49.903Z" }, ] [[package]] @@ -2111,7 +2100,7 @@ wheels = [ [[package]] name = "requests" -version = "2.32.3" +version = "2.32.4" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "certifi" }, @@ -2119,9 +2108,9 @@ dependencies = [ { name = "idna" }, { name = "urllib3" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/63/70/2bf7780ad2d390a8d301ad0b550f1581eadbd9a20f896afe06353c2a2913/requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760", size = 131218, upload-time = "2024-05-29T15:37:49.536Z" } +sdist = { url = "https://files.pythonhosted.org/packages/e1/0a/929373653770d8a0d7ea76c37de6e41f11eb07559b103b1c02cafb3f7cf8/requests-2.32.4.tar.gz", hash = "sha256:27d0316682c8a29834d3264820024b62a36942083d52caf2f14c0591336d3422", size = 135258, upload-time = "2025-06-09T16:43:07.34Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/f9/9b/335f9764261e915ed497fcdeb11df5dfd6f7bf257d4a6a2a686d80da4d54/requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6", size = 64928, upload-time = "2024-05-29T15:37:47.027Z" }, + { url = "https://files.pythonhosted.org/packages/7c/e4/56027c4a6b4ae70ca9de302488c5ca95ad4a39e190093d6c1a8ace08341b/requests-2.32.4-py3-none-any.whl", hash = "sha256:27babd3cda2a6d50b30443204ee89830707d396671944c998b5975b031ac2b2c", size = 64847, upload-time = "2025-06-09T16:43:05.728Z" }, ] [[package]] From fce421437a152e86d5c976d14ea2594c20faecdd Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 16 Jun 2025 12:19:14 -0700 Subject: [PATCH 293/521] move grid regularity checking into separate func _is_voltage_regularly_spaced() --- .../analysis/swept_langmuir/helpers.py | 45 +++++++++---------- 1 file changed, 22 insertions(+), 23 deletions(-) diff --git a/src/plasmapy/analysis/swept_langmuir/helpers.py b/src/plasmapy/analysis/swept_langmuir/helpers.py index e6f46b33a7..7ff064ea4d 100644 --- a/src/plasmapy/analysis/swept_langmuir/helpers.py +++ b/src/plasmapy/analysis/swept_langmuir/helpers.py @@ -294,6 +294,27 @@ def _force_regular_spacing( return reg_voltage, reg_current +def _is_voltage_regularly_spaced( + voltage_diff: np.ndarray, mask_zero_diff: np.ndarray, +) -> bool: + is_regular_grid = False + if np.count_nonzero(mask_zero_diff) > 0: + # is_regular_grid = False + pass + elif np.allclose(voltage_diff, voltage_diff[0]): + # grid is already regularly spaced + is_regular_grid = True + elif np.allclose( + np.rint(voltage_diff / np.min(voltage_diff)) + - voltage_diff / np.min(voltage_diff), + 0, + ): + # grid has a common dV, but at times jumps N * dV times + is_regular_grid = True + + return is_regular_grid + + def merge_voltage_clusters( # noqa: C901, PLR0912, PLR0915 voltage: np.ndarray, current: np.ndarray, @@ -323,29 +344,7 @@ def merge_voltage_clusters( # noqa: C901, PLR0912, PLR0915 # check if grid is regularly spaced voltage_diff = np.diff(voltage) mask_zero_diff = np.isclose(voltage_diff, 0.0) - if np.count_nonzero(mask_zero_diff) > 0: - is_regular_grid = False - elif np.allclose(voltage_diff, voltage_diff[0]): - # grid is already regularly spaced - is_regular_grid = True - elif np.allclose( - np.rint(voltage_diff / np.min(voltage_diff)) - - voltage_diff / np.min(voltage_diff), - 0, - ): - # grid has a common dV, but at times jumps N * dV times - if force_regular_spacing and ( - voltage_step_size is None or voltage_step_size == 0 - ): - # need to stuff with NaN values - voltage, current = _force_regular_spacing( - voltage=voltage, - current=current, - voltage_step_size=np.min(voltage_diff), - ) - is_regular_grid = True - else: - is_regular_grid = False + is_regular_grid = _is_voltage_regularly_spaced(voltage_diff, mask_zero_diff) # return if voltage is already regularly spaced and no voltage merging is # requested From 0ab23b979d6f206a68b5cc9afe054e38c9663038 Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 16 Jun 2025 12:19:34 -0700 Subject: [PATCH 294/521] rough out docstring for merge_voltage_clusters() --- .../analysis/swept_langmuir/helpers.py | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/src/plasmapy/analysis/swept_langmuir/helpers.py b/src/plasmapy/analysis/swept_langmuir/helpers.py index 7ff064ea4d..5cb04d74f4 100644 --- a/src/plasmapy/analysis/swept_langmuir/helpers.py +++ b/src/plasmapy/analysis/swept_langmuir/helpers.py @@ -321,6 +321,56 @@ def merge_voltage_clusters( # noqa: C901, PLR0912, PLR0915 voltage_step_size: float | None = None, force_regular_spacing: bool = False, ) -> tuple[np.ndarray, np.ndarray]: + """ + Search the ``voltage`` array for closely spaced voltage clusters + based on the ``voltage_step_size`` parameter and merge cluster, and + associated ``current`` values, into a single point. + + Parameters + ---------- + voltage: `numpy.ndarray` + 1D `numpy.ndarray` representing the voltage of the swept + Langmuir trace. *No units are assumed or checked, but values + should be in volts.* + + current: `numpy.ndarray` + 1D `numpy.ndarray` representing the current of the swept + Langmuir trace. Values should start from a negative + ion-saturation current and increase to a positive + electron-saturation current. *No units are assumed or checked, + but values should be in amperes.* + + voltage_step_size: `float` or `None` + A non-zero, positive step size for the ``voltage`` array + cluster identification. A value of ``0`` will merge only + duplicate voltage values. A value of `None` will default to the + average step size of the ``voltage`` array. (DEFAULT:`None`) + + force_regular_spacing: `bool` + If `False`, then the new voltage value of a cluster is the + average of the contained points. If `True`, then the new + ``voltage`` array will be regularly spaced with a delta of + ``voltage_step_size``. (DEFAULT: `False`) + + Returns + ------- + voltage : `numpy.ndarray` + The new ``voltage`` array. + + current : `numpy.ndarray` + The new ``current`` array. + + Notes + ----- + ``voltage_step_size = 0`` : + blah + + ``voltage_step_size > 0`` or `None` + blah + + ``force_regular_spacing = True`` + blah + """ # condition force_regular_grid if not isinstance(force_regular_spacing, bool): raise TypeError( From f6e0852aeeec69118618680105e7edd27c31c2d0 Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 16 Jun 2025 12:21:01 -0700 Subject: [PATCH 295/521] _force_regular_spacing() only NaN stuff if steps of multiples (>1) of voltage_step_size --- src/plasmapy/analysis/swept_langmuir/helpers.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/plasmapy/analysis/swept_langmuir/helpers.py b/src/plasmapy/analysis/swept_langmuir/helpers.py index 5cb04d74f4..a33207b52b 100644 --- a/src/plasmapy/analysis/swept_langmuir/helpers.py +++ b/src/plasmapy/analysis/swept_langmuir/helpers.py @@ -277,6 +277,11 @@ def _force_regular_spacing( match the size of the returned ``voltage`` array. """ size = int(np.round((voltage[-1] - voltage[0]) / voltage_step_size)) + 1 + + if voltage.size == size: + # all voltages steps are already equal + return voltage, current + reg_voltage = np.linspace(voltage[0], voltage[-1], num=size, dtype=voltage.dtype) _, reg_indices, new_indices = np.intersect1d( From 66e1af48f020d5ccfca006b314f3c6945332f603 Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 16 Jun 2025 12:21:32 -0700 Subject: [PATCH 296/521] merge_voltage_clusters(): return quickly if already regularly spaced --- .../analysis/swept_langmuir/helpers.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/plasmapy/analysis/swept_langmuir/helpers.py b/src/plasmapy/analysis/swept_langmuir/helpers.py index a33207b52b..325b656ddd 100644 --- a/src/plasmapy/analysis/swept_langmuir/helpers.py +++ b/src/plasmapy/analysis/swept_langmuir/helpers.py @@ -3,10 +3,13 @@ __all__ = ["check_sweep", "merge_voltage_clusters", "sort_sweep_arrays"] from typing import Literal +import warnings import astropy.units as u import numpy as np +from plasmapy.utils.exceptions import PlasmaPyWarning + def check_sweep( # noqa: C901, PLR0912 voltage: np.ndarray, @@ -404,6 +407,22 @@ def merge_voltage_clusters( # noqa: C901, PLR0912, PLR0915 # return if voltage is already regularly spaced and no voltage merging is # requested if is_regular_grid and (voltage_step_size is None or voltage_step_size == 0): + if voltage_step_size is None: + warnings.warn( + "The supplied ``voltage`` array is already regularly spaced. If " + "you want to re-bin the arrays to a different voltage_step_size, " + "the use something like numpy.interp.", + PlasmaPyWarning + ) + + if force_regular_spacing: + # need to stuff with NaN values + voltage, current = _force_regular_spacing( + voltage=voltage, + current=current, + voltage_step_size=np.min(voltage_diff), + ) + return voltage.copy(), current.copy() # condition voltage_step_size ... Round 2 From f5878436758f4a3bf169f05e046df4bce0e1b3be Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 16 Jun 2025 18:21:12 -0700 Subject: [PATCH 297/521] add docstring to _is_voltage_regularly_spaced() --- src/plasmapy/analysis/swept_langmuir/helpers.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/plasmapy/analysis/swept_langmuir/helpers.py b/src/plasmapy/analysis/swept_langmuir/helpers.py index 325b656ddd..a9fad5b27b 100644 --- a/src/plasmapy/analysis/swept_langmuir/helpers.py +++ b/src/plasmapy/analysis/swept_langmuir/helpers.py @@ -305,6 +305,11 @@ def _force_regular_spacing( def _is_voltage_regularly_spaced( voltage_diff: np.ndarray, mask_zero_diff: np.ndarray, ) -> bool: + """ + Determine if the voltage difference array ``voltage_diff`` is + regularly spaced. That is the differences are all equal or some + integer multiple of the smallest difference. + """ is_regular_grid = False if np.count_nonzero(mask_zero_diff) > 0: # is_regular_grid = False From d9ad84827f828d70289593120ce20a6dd05604ea Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 16 Jun 2025 19:17:00 -0700 Subject: [PATCH 298/521] create _interpolate_sweep() --- .../analysis/swept_langmuir/helpers.py | 36 +++++++++++++------ 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/src/plasmapy/analysis/swept_langmuir/helpers.py b/src/plasmapy/analysis/swept_langmuir/helpers.py index a9fad5b27b..798189b865 100644 --- a/src/plasmapy/analysis/swept_langmuir/helpers.py +++ b/src/plasmapy/analysis/swept_langmuir/helpers.py @@ -328,6 +328,29 @@ def _is_voltage_regularly_spaced( return is_regular_grid +def _interpolate_sweep( + voltage: np.ndarray, + current: np.ndarray, + voltage_step_size: float, +): + """ + Interpolate the ``voltage`` and ``current`` arrays associated with + a langmuir trace onto a new regularly spaced voltage array. The + new voltage array will be spaced by ``voltage_step_size`` and span + the same range as the original ``voltage`` array. + """ + size = ( + int(np.round((voltage[-1] - voltage[0]) / voltage_step_size)) + + 1 + ) + reg_voltage = np.linspace( + voltage[0], voltage[-1], num=size, dtype=voltage.dtype + ) + reg_current = np.interp(reg_voltage, voltage, current) + + return reg_voltage, reg_current + + def merge_voltage_clusters( # noqa: C901, PLR0912, PLR0915 voltage: np.ndarray, current: np.ndarray, @@ -450,21 +473,12 @@ def merge_voltage_clusters( # noqa: C901, PLR0912, PLR0915 # now merge clusters voltage_diff = np.diff(voltage) if voltage_step_size != 0 and np.all(voltage_diff >= voltage_step_size): - new_voltage = voltage.copy() - new_current = current.copy() if force_regular_spacing: - size = ( - int(np.round((new_voltage[-1] - new_voltage[0]) / voltage_step_size)) - + 1 - ) - reg_voltage = np.linspace( - new_voltage[0], new_voltage[-1], num=size, dtype=new_voltage.dtype + new_voltage, new_current = _interpolate_sweep( + voltage, current, voltage_step_size ) - reg_current = np.interp(reg_voltage, new_voltage, new_current) - new_voltage = reg_voltage - new_current = reg_current elif voltage_step_size == 0: voltage_diff = np.diff(voltage) mask_zero_diff = np.isclose(voltage_diff, 0.0) From b05d76a10396c6dddf7c1614b80f70ec4ead4012 Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 16 Jun 2025 19:26:41 -0700 Subject: [PATCH 299/521] create _merge_zero_diff_voltage_clusters() --- .../analysis/swept_langmuir/helpers.py | 75 +++++++++++-------- 1 file changed, 45 insertions(+), 30 deletions(-) diff --git a/src/plasmapy/analysis/swept_langmuir/helpers.py b/src/plasmapy/analysis/swept_langmuir/helpers.py index 798189b865..60f7038768 100644 --- a/src/plasmapy/analysis/swept_langmuir/helpers.py +++ b/src/plasmapy/analysis/swept_langmuir/helpers.py @@ -351,6 +351,50 @@ def _interpolate_sweep( return reg_voltage, reg_current +def _merge_zero_diff_voltage_clusters( + voltage: np.ndarray, current: np.ndarray +) -> tuple[np.ndarray, np.ndarray]: + """ + Take the ``voltage`` and ``current`` arrays associated with a + langmuir trace and average together clusters of identical voltage + values. + """ + # generate boolean mask for zero diff locations + voltage_diff = np.diff(voltage) + mask_zero_diff = np.isclose(voltage_diff, 0.0) + mask_zero_diff = np.append(mask_zero_diff, [mask_zero_diff[-1]]) + + # initialize new voltage and current arrays + new_voltage = np.full(voltage.shape, np.nan, dtype=voltage.dtype) + new_current = np.full(current.shape, np.nan, dtype=current.dtype) + + mask = np.logical_not(mask_zero_diff) + new_voltage[mask] = voltage[mask] + new_current[mask] = current[mask] + + # merge zero diff clusters + while np.any(mask_zero_diff): + volt = voltage[mask_zero_diff][0] + index = np.where(new_voltage == volt)[0] + if len(index) == 0: + index = np.where(mask_zero_diff)[0] + + index = index[0] + volt_mask = np.isclose(voltage, volt) + + new_voltage[index] = volt + new_current[index] = np.average(current[volt_mask]) + + mask_zero_diff[volt_mask] = False + + # remove nan entries + mask = np.logical_not(np.isnan(new_voltage)) + new_voltage = new_voltage[mask] + new_current = new_current[mask] + + return new_voltage, new_current + + def merge_voltage_clusters( # noqa: C901, PLR0912, PLR0915 voltage: np.ndarray, current: np.ndarray, @@ -471,7 +515,6 @@ def merge_voltage_clusters( # noqa: C901, PLR0912, PLR0915 ) # now merge clusters - voltage_diff = np.diff(voltage) if voltage_step_size != 0 and np.all(voltage_diff >= voltage_step_size): if force_regular_spacing: @@ -480,35 +523,7 @@ def merge_voltage_clusters( # noqa: C901, PLR0912, PLR0915 ) elif voltage_step_size == 0: - voltage_diff = np.diff(voltage) - mask_zero_diff = np.isclose(voltage_diff, 0.0) - mask_zero_diff = np.append(mask_zero_diff, [mask_zero_diff[-1]]) - - new_voltage = np.full(voltage.shape, np.nan, dtype=voltage.dtype) - new_current = np.full(current.shape, np.nan, dtype=current.dtype) - - mask = np.logical_not(mask_zero_diff) - new_voltage[mask] = voltage[mask] - new_current[mask] = current[mask] - - while np.any(mask_zero_diff): - volt = voltage[mask_zero_diff][0] - index = np.where(new_voltage == volt)[0] - if len(index) == 0: - index = np.where(mask_zero_diff)[0] - - index = index[0] - volt_mask = np.isclose(voltage, volt) - - new_voltage[index] = volt - new_current[index] = np.average(current[volt_mask]) - - mask_zero_diff[volt_mask] = False - - # remove nan entries - mask = np.logical_not(np.isnan(new_voltage)) - new_voltage = new_voltage[mask] - new_current = new_current[mask] + new_voltage, new_current = _merge_zero_diff_voltage_clusters(voltage, current) if force_regular_spacing: new_voltage, new_current = merge_voltage_clusters( From 1be80d8a7dc580947ce17f57b10a0abaa6922026 Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 16 Jun 2025 19:27:04 -0700 Subject: [PATCH 300/521] add return annotations to _interpolate_sweep() --- src/plasmapy/analysis/swept_langmuir/helpers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plasmapy/analysis/swept_langmuir/helpers.py b/src/plasmapy/analysis/swept_langmuir/helpers.py index 60f7038768..2ce0f6ad16 100644 --- a/src/plasmapy/analysis/swept_langmuir/helpers.py +++ b/src/plasmapy/analysis/swept_langmuir/helpers.py @@ -332,7 +332,7 @@ def _interpolate_sweep( voltage: np.ndarray, current: np.ndarray, voltage_step_size: float, -): +) -> tuple[np.ndarray, np.ndarray]: """ Interpolate the ``voltage`` and ``current`` arrays associated with a langmuir trace onto a new regularly spaced voltage array. The From 06e2fc3537cbbe75d31d4db4e5198a83b0d9913b Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 16 Jun 2025 19:28:00 -0700 Subject: [PATCH 301/521] appease grumpy ruff --- src/plasmapy/analysis/swept_langmuir/helpers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plasmapy/analysis/swept_langmuir/helpers.py b/src/plasmapy/analysis/swept_langmuir/helpers.py index 2ce0f6ad16..e3e0d14bb5 100644 --- a/src/plasmapy/analysis/swept_langmuir/helpers.py +++ b/src/plasmapy/analysis/swept_langmuir/helpers.py @@ -2,8 +2,8 @@ __all__ = ["check_sweep", "merge_voltage_clusters", "sort_sweep_arrays"] -from typing import Literal import warnings +from typing import Literal import astropy.units as u import numpy as np From 295d5b871ccf2118d10b56350a1e341814ff6cc8 Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 16 Jun 2025 19:29:00 -0700 Subject: [PATCH 302/521] appease grumpy ruff formatter --- .../analysis/swept_langmuir/helpers.py | 21 +++++++------------ 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/src/plasmapy/analysis/swept_langmuir/helpers.py b/src/plasmapy/analysis/swept_langmuir/helpers.py index e3e0d14bb5..1309219d93 100644 --- a/src/plasmapy/analysis/swept_langmuir/helpers.py +++ b/src/plasmapy/analysis/swept_langmuir/helpers.py @@ -303,7 +303,8 @@ def _force_regular_spacing( def _is_voltage_regularly_spaced( - voltage_diff: np.ndarray, mask_zero_diff: np.ndarray, + voltage_diff: np.ndarray, + mask_zero_diff: np.ndarray, ) -> bool: """ Determine if the voltage difference array ``voltage_diff`` is @@ -318,9 +319,9 @@ def _is_voltage_regularly_spaced( # grid is already regularly spaced is_regular_grid = True elif np.allclose( - np.rint(voltage_diff / np.min(voltage_diff)) - - voltage_diff / np.min(voltage_diff), - 0, + np.rint(voltage_diff / np.min(voltage_diff)) + - voltage_diff / np.min(voltage_diff), + 0, ): # grid has a common dV, but at times jumps N * dV times is_regular_grid = True @@ -339,13 +340,8 @@ def _interpolate_sweep( new voltage array will be spaced by ``voltage_step_size`` and span the same range as the original ``voltage`` array. """ - size = ( - int(np.round((voltage[-1] - voltage[0]) / voltage_step_size)) - + 1 - ) - reg_voltage = np.linspace( - voltage[0], voltage[-1], num=size, dtype=voltage.dtype - ) + size = int(np.round((voltage[-1] - voltage[0]) / voltage_step_size)) + 1 + reg_voltage = np.linspace(voltage[0], voltage[-1], num=size, dtype=voltage.dtype) reg_current = np.interp(reg_voltage, voltage, current) return reg_voltage, reg_current @@ -484,7 +480,7 @@ def merge_voltage_clusters( # noqa: C901, PLR0912, PLR0915 "The supplied ``voltage`` array is already regularly spaced. If " "you want to re-bin the arrays to a different voltage_step_size, " "the use something like numpy.interp.", - PlasmaPyWarning + PlasmaPyWarning, ) if force_regular_spacing: @@ -516,7 +512,6 @@ def merge_voltage_clusters( # noqa: C901, PLR0912, PLR0915 # now merge clusters if voltage_step_size != 0 and np.all(voltage_diff >= voltage_step_size): - if force_regular_spacing: new_voltage, new_current = _interpolate_sweep( voltage, current, voltage_step_size From ccea90d0f27e154285861a8fcbeddae22fc1764c Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 16 Jun 2025 19:30:49 -0700 Subject: [PATCH 303/521] add else case so new_voltage and new_current are always defined --- src/plasmapy/analysis/swept_langmuir/helpers.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/plasmapy/analysis/swept_langmuir/helpers.py b/src/plasmapy/analysis/swept_langmuir/helpers.py index 1309219d93..f71dc472fd 100644 --- a/src/plasmapy/analysis/swept_langmuir/helpers.py +++ b/src/plasmapy/analysis/swept_langmuir/helpers.py @@ -516,6 +516,9 @@ def merge_voltage_clusters( # noqa: C901, PLR0912, PLR0915 new_voltage, new_current = _interpolate_sweep( voltage, current, voltage_step_size ) + else: + new_voltage = voltage.copy() + new_current = current.copy() elif voltage_step_size == 0: new_voltage, new_current = _merge_zero_diff_voltage_clusters(voltage, current) From 54843470181996147658c312be2a96dc26915079 Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 16 Jun 2025 19:35:47 -0700 Subject: [PATCH 304/521] create _merge_voltage_clusters() --- .../analysis/swept_langmuir/helpers.py | 77 ++++++++++++------- 1 file changed, 48 insertions(+), 29 deletions(-) diff --git a/src/plasmapy/analysis/swept_langmuir/helpers.py b/src/plasmapy/analysis/swept_langmuir/helpers.py index f71dc472fd..edaaa3578d 100644 --- a/src/plasmapy/analysis/swept_langmuir/helpers.py +++ b/src/plasmapy/analysis/swept_langmuir/helpers.py @@ -391,6 +391,51 @@ def _merge_zero_diff_voltage_clusters( return new_voltage, new_current +def _merge_voltage_clusters( + voltage: np.ndarray, + current: np.ndarray, + voltage_step_size: float, + force_regular_spacing: bool, +) -> tuple[np.ndarray, np.ndarray]: + """ + Take the ``voltage`` and ``current`` arrays associated with a + langmuir trace and average together clusters voltage values within + step size ``voltage_step_size``. + """ + # initialize new voltage anc current arrays + new_voltage = np.full(voltage.shape, np.nan, dtype=voltage.dtype) + new_current = np.full(current.shape, np.nan, dtype=current.dtype) + + start_voltage = voltage[0] + stop_voltage = start_voltage + voltage_step_size + + # populate + ii = 0 + while start_voltage <= voltage[-1]: + mask1 = voltage >= start_voltage + mask2 = voltage < stop_voltage + mask = np.logical_and(mask1, mask2) + + if np.count_nonzero(mask) > 0: + new_voltage[ii] = ( + start_voltage + 0.5 * voltage_step_size + if force_regular_spacing + else np.average(voltage[mask]) + ) + new_current[ii] = np.average(current[mask]) + + ii += 1 + + start_voltage = stop_voltage + stop_voltage += voltage_step_size + + # crop new arrays + new_voltage = new_voltage[:ii] + new_current = new_current[:ii] + + return new_voltage, new_current + + def merge_voltage_clusters( # noqa: C901, PLR0912, PLR0915 voltage: np.ndarray, current: np.ndarray, @@ -531,35 +576,9 @@ def merge_voltage_clusters( # noqa: C901, PLR0912, PLR0915 ) else: - new_voltage = np.full(voltage.shape, np.nan, dtype=voltage.dtype) - new_current = np.full(current.shape, np.nan, dtype=current.dtype) - - start_voltage = voltage[0] - stop_voltage = start_voltage + voltage_step_size - - # populate - ii = 0 - while start_voltage <= voltage[-1]: - mask1 = voltage >= start_voltage - mask2 = voltage < stop_voltage - mask = np.logical_and(mask1, mask2) - - if np.count_nonzero(mask) > 0: - new_voltage[ii] = ( - start_voltage + 0.5 * voltage_step_size - if force_regular_spacing - else np.average(voltage[mask]) - ) - new_current[ii] = np.average(current[mask]) - - ii += 1 - - start_voltage = stop_voltage - stop_voltage += voltage_step_size - - # crop new arrays - new_voltage = new_voltage[:ii] - new_current = new_current[:ii] + new_voltage, new_current = _merge_voltage_clusters( + voltage, current, voltage_step_size, force_regular_spacing + ) if force_regular_spacing: # Need to fill array with NaN values to force the regular spacing From d978467703b60c6158d5b40bd57fd80969179334 Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 16 Jun 2025 19:36:36 -0700 Subject: [PATCH 305/521] remove noqa from merge_voltage_clusters() --- src/plasmapy/analysis/swept_langmuir/helpers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plasmapy/analysis/swept_langmuir/helpers.py b/src/plasmapy/analysis/swept_langmuir/helpers.py index edaaa3578d..e59101307b 100644 --- a/src/plasmapy/analysis/swept_langmuir/helpers.py +++ b/src/plasmapy/analysis/swept_langmuir/helpers.py @@ -436,7 +436,7 @@ def _merge_voltage_clusters( return new_voltage, new_current -def merge_voltage_clusters( # noqa: C901, PLR0912, PLR0915 +def merge_voltage_clusters( voltage: np.ndarray, current: np.ndarray, voltage_step_size: float | None = None, From 66518b9f338bc1e856cfb48405e4cf76cc15daff Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 16 Jun 2025 19:38:35 -0700 Subject: [PATCH 306/521] put back noqa C901 and PLR0912 --- src/plasmapy/analysis/swept_langmuir/helpers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plasmapy/analysis/swept_langmuir/helpers.py b/src/plasmapy/analysis/swept_langmuir/helpers.py index e59101307b..e5ff0d7a3e 100644 --- a/src/plasmapy/analysis/swept_langmuir/helpers.py +++ b/src/plasmapy/analysis/swept_langmuir/helpers.py @@ -436,7 +436,7 @@ def _merge_voltage_clusters( return new_voltage, new_current -def merge_voltage_clusters( +def merge_voltage_clusters( # noqa: C901, PLR0912 voltage: np.ndarray, current: np.ndarray, voltage_step_size: float | None = None, From e7c075ed65eade69780f0096c6ca3d1b62c4bdbd Mon Sep 17 00:00:00 2001 From: Erik Date: Wed, 18 Jun 2025 13:52:02 -0700 Subject: [PATCH 307/521] fix typo --- src/plasmapy/analysis/swept_langmuir/helpers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plasmapy/analysis/swept_langmuir/helpers.py b/src/plasmapy/analysis/swept_langmuir/helpers.py index e5ff0d7a3e..a609326eaf 100644 --- a/src/plasmapy/analysis/swept_langmuir/helpers.py +++ b/src/plasmapy/analysis/swept_langmuir/helpers.py @@ -402,7 +402,7 @@ def _merge_voltage_clusters( langmuir trace and average together clusters voltage values within step size ``voltage_step_size``. """ - # initialize new voltage anc current arrays + # initialize new voltage and current arrays new_voltage = np.full(voltage.shape, np.nan, dtype=voltage.dtype) new_current = np.full(current.shape, np.nan, dtype=current.dtype) From 701128f79c0e40b7011945c3d0ac0049c1c6963d Mon Sep 17 00:00:00 2001 From: Peter Heuer Date: Thu, 19 Jun 2025 19:35:21 -0400 Subject: [PATCH 308/521] Reduce CPR test time (#3039) * Delete duplicate test_multiple_grids, reduce nparticles * Refactor add_wire tests, reduce number of particles * Changelog, pre-commit * Fix type issue for ruff --- changelog/3039.internal.rst | 1 + .../test_synthetic_radiography.py | 126 +++++++----------- 2 files changed, 47 insertions(+), 80 deletions(-) create mode 100644 changelog/3039.internal.rst diff --git a/changelog/3039.internal.rst b/changelog/3039.internal.rst new file mode 100644 index 0000000000..5c777113e7 --- /dev/null +++ b/changelog/3039.internal.rst @@ -0,0 +1 @@ +Refactored tests for the `~plasmapy.diagnostics.charged_particle_radiography` module to reduce test runtime. diff --git a/tests/diagnostics/charged_particle_radiography/test_synthetic_radiography.py b/tests/diagnostics/charged_particle_radiography/test_synthetic_radiography.py index ec9810fe57..6353ccb36f 100644 --- a/tests/diagnostics/charged_particle_radiography/test_synthetic_radiography.py +++ b/tests/diagnostics/charged_particle_radiography/test_synthetic_radiography.py @@ -148,8 +148,8 @@ def test_multiple_grids() -> None: solution?? """ - grid1 = _test_grid("constant_bz", L=3 * u.cm, num=50, B0=0.7 * u.T) - grid2 = _test_grid("electrostatic_gaussian_sphere", L=1 * u.mm, num=50) + grid1 = _test_grid("constant_bz", L=3 * u.cm, num=20, B0=0.7 * u.T) + grid2 = _test_grid("electrostatic_gaussian_sphere", L=1 * u.mm, num=20) grids = [grid1, grid2] source = (0 * u.mm, -10 * u.mm, 0 * u.mm) @@ -159,7 +159,7 @@ def test_multiple_grids() -> None: grids, source, detector, field_weighting="nearest neighbor", verbose=True ) - sim.create_particles(1e5, 15 * u.MeV, max_theta=8 * u.deg, random_seed=42) + sim.create_particles(1e2, 15 * u.MeV, max_theta=8 * u.deg, random_seed=42) sim.run() @@ -167,13 +167,6 @@ def test_multiple_grids() -> None: bins = [100, 100] hax, vax, values = cpr.synthetic_radiograph(sim, size=size, bins=bins) - """ - import matplotlib.pyplot as plt - fig, ax = plt.subplots() - ax.set_aspect('equal') - ax.pcolormesh(hax.to(u.cm).value, vax.to(u.cm).value, values.T) - """ - def run_1D_example(name: str): """ @@ -215,7 +208,7 @@ def run_mesh_example( wire_diameter=20 * u.um, mesh_hdir=None, mesh_vdir=None, - nparticles: int = 10000, + nparticles: int = 1000, problem: str = "electrostatic_gaussian_sphere", ) -> cpr.Tracker: """ @@ -812,51 +805,60 @@ def test_gaussian_sphere_analytical_comparison() -> None: assert np.isclose(max_deflection, sim.max_deflection.to(u.rad).value, atol=1e-3) +@pytest.mark.parametrize( + "kwargs", + [ + # Test a circular mesh + ({"extent": 1 * u.mm}), + # Test providing hdir + ({"mesh_hdir": np.array([0.5, 0, 0.5])}), + # Test providing hdir and vdir + ({"mesh_hdir": np.array([0.5, 0, 0.5]), "mesh_vdir": np.array([0, 0.1, 1])}), + ], +) @pytest.mark.slow -def test_add_wire_mesh() -> None: - # ************************************************************ - # Test various input configurations - # ************************************************************ - - # Test a circular mesh - run_mesh_example(extent=1 * u.mm) +def test_add_wire_mesh_inputs(kwargs) -> None: + run_mesh_example(**kwargs) - # Test providing hdir - run_mesh_example(mesh_hdir=np.array([0.5, 0, 0.5])) - # Test providing hdir and vdir - run_mesh_example(mesh_hdir=np.array([0.5, 0, 0.5]), mesh_vdir=np.array([0, 0.1, 1])) - - # ************************************************************ - # Test invalid inputs - # ************************************************************ +@pytest.mark.parametrize( + ("kwargs", "exception"), + [ + # Test invalid extent (too many elements) + ({"extent": (1 * u.mm, 2 * u.mm, 3 * u.mm)}, ValueError), + # Test wire mesh completely blocks all particles (in this case because + # the wire diameter is absurdly large) + ({"wire_diameter": 5 * u.mm}, ValueError), + # Test if wire mesh is not between the source and object + ({"location": np.array([0, 3, 0]) * u.mm}, ValueError), + ], +) +@pytest.mark.slow +def test_add_wire_mesh_invalid_inputs(kwargs, exception) -> None: + with pytest.raises(exception): + run_mesh_example(**kwargs) - # Test invalid extent (too many elements) - with pytest.raises(ValueError): - run_mesh_example(extent=(1 * u.mm, 2 * u.mm, 3 * u.mm)) - # Test wire mesh completely blocks all particles (in this case because - # the wire diameter is absurdly large) - with pytest.raises(ValueError): - run_mesh_example(wire_diameter=5 * u.mm) +@pytest.mark.slow +def test_add_wire_mesh_accuracy() -> None: + """ + Test that a mesh is imaged correctly in the detector plane. - # Test if wire mesh is not between the source and object - with pytest.raises(ValueError): - run_mesh_example(location=np.array([0, 3, 0]) * u.mm) - - # ************************************************************ - # Test that mesh is the right size in the detector plane, and that - # the wire spacing images correctly. - # This is actually a good overall test of the whole proton radiography - # particle tracing algorithm. - # ************************************************************ + Test that mesh is the right size in the detector plane, and that + the wire spacing images correctly. + This is actually a good overall test of the whole proton radiography + particle tracing algorithm. + """ loc = np.array([0, -2, 0]) * u.mm extent = (1 * u.mm, 1 * u.mm) wire_diameter = 30 * u.um nwires = 9 + + # A large number of particles is needed to get a good image + # of the mesh, so this is a slow test sim = run_mesh_example( problem="empty", - nparticles=100000, + nparticles=10000, location=loc, extent=extent, wire_diameter=wire_diameter, @@ -924,42 +926,6 @@ def test_add_wire_mesh() -> None: assert np.isclose(measured_spacing, true_spacing, 0.5) -@pytest.mark.slow -@pytest.mark.filterwarnings("ignore::RuntimeWarning") -def test_multiple_grids2() -> None: - """ - Test that a case with two grids runs. - TODO: automate test by including two fields with some obvious analytical - solution?? - """ - - grid1 = _test_grid("constant_bz", L=3 * u.cm, num=50, B0=0.7 * u.T) - grid2 = _test_grid("electrostatic_gaussian_sphere", L=1 * u.mm, num=50) - grids = [grid1, grid2] - - source = (0 * u.mm, -10 * u.mm, 0 * u.mm) - detector = (0 * u.mm, 200 * u.mm, 0 * u.mm) - - sim = cpr.Tracker( - grids, source, detector, field_weighting="nearest neighbor", verbose=True - ) - - sim.create_particles(1e5, 15 * u.MeV, max_theta=8 * u.deg, random_seed=42) - - sim.run() - - size = np.array([[-1, 1], [-1, 1]]) * 5 * u.cm - bins = [100, 100] - hax, vax, values = cpr.synthetic_radiograph(sim, size=size, bins=bins) - - """ - import matplotlib.pyplot as plt - fig, ax = plt.subplots() - ax.set_aspect('equal') - ax.pcolormesh(hax.to(u.cm).value, vax.to(u.cm).value, values.T) - """ - - def test_radiography_disk_save_routine(tmp_path) -> None: grid = _test_grid("electrostatic_gaussian_sphere", L=1 * u.mm, num=50) From 2663ab5a069f5525aa5046cc93fedbfe362aced5 Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 23 Jun 2025 10:05:15 -0700 Subject: [PATCH 309/521] _force_regular_spacing: fix docstring wording --- src/plasmapy/analysis/swept_langmuir/helpers.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/plasmapy/analysis/swept_langmuir/helpers.py b/src/plasmapy/analysis/swept_langmuir/helpers.py index a609326eaf..4bc5d48853 100644 --- a/src/plasmapy/analysis/swept_langmuir/helpers.py +++ b/src/plasmapy/analysis/swept_langmuir/helpers.py @@ -245,11 +245,16 @@ def _force_regular_spacing( voltage_step_size: float, ) -> tuple[np.ndarray, np.ndarray]: """ - Take a ``voltage`` array that already has voltage steps at some - integer spacing of ``voltage_step_size`` and its paired ``current`` - array to generate a voltage array with a fixed step size - ``voltage_step_size`` along with an appropriately `~numpy.nan` - stuffed ``current`` array. + Generated a regularly spaced voltage array and associated + `~numpy.nan` stuffed current array from the given ``voltage`` + and ``current`` langmuir trace arrays. The generated voltage + array will span the same range as the input ``voltage`` array with + a regular spacing of ``voltage_step_size``. + + It is assumed the input ``voltage`` array is already spaced at + some integer multiple of ``voltage_step_size``. This integer + multiple does NOT need to be fixed for every point pair in + ``voltage``. Parameters ---------- From 19b83deaffe95560c57c4444785feb01f23fb679 Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 23 Jun 2025 10:37:29 -0700 Subject: [PATCH 310/521] _is_voltage_regularly_spaced: fix docstring wording --- src/plasmapy/analysis/swept_langmuir/helpers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plasmapy/analysis/swept_langmuir/helpers.py b/src/plasmapy/analysis/swept_langmuir/helpers.py index 4bc5d48853..50e1e00b21 100644 --- a/src/plasmapy/analysis/swept_langmuir/helpers.py +++ b/src/plasmapy/analysis/swept_langmuir/helpers.py @@ -313,7 +313,7 @@ def _is_voltage_regularly_spaced( ) -> bool: """ Determine if the voltage difference array ``voltage_diff`` is - regularly spaced. That is the differences are all equal or some + regularly spaced; that is the differences are all equal or some integer multiple of the smallest difference. """ is_regular_grid = False From 45bc39eee7d7d8c7507cc1e28297e7ff2f052186 Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 23 Jun 2025 10:38:05 -0700 Subject: [PATCH 311/521] _interpolate_sweep: fix docstring wording --- src/plasmapy/analysis/swept_langmuir/helpers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plasmapy/analysis/swept_langmuir/helpers.py b/src/plasmapy/analysis/swept_langmuir/helpers.py index 50e1e00b21..d90807a3a4 100644 --- a/src/plasmapy/analysis/swept_langmuir/helpers.py +++ b/src/plasmapy/analysis/swept_langmuir/helpers.py @@ -341,7 +341,7 @@ def _interpolate_sweep( ) -> tuple[np.ndarray, np.ndarray]: """ Interpolate the ``voltage`` and ``current`` arrays associated with - a langmuir trace onto a new regularly spaced voltage array. The + a langmuir trace onto a new regularly spaced voltage array. The new voltage array will be spaced by ``voltage_step_size`` and span the same range as the original ``voltage`` array. """ From 09d807bf11df820622f0f0210558d85b705be51c Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 23 Jun 2025 10:39:05 -0700 Subject: [PATCH 312/521] _merge_zero_diff_voltage_clusters: fix docstring wording --- src/plasmapy/analysis/swept_langmuir/helpers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plasmapy/analysis/swept_langmuir/helpers.py b/src/plasmapy/analysis/swept_langmuir/helpers.py index d90807a3a4..02b4cedc82 100644 --- a/src/plasmapy/analysis/swept_langmuir/helpers.py +++ b/src/plasmapy/analysis/swept_langmuir/helpers.py @@ -356,7 +356,7 @@ def _merge_zero_diff_voltage_clusters( voltage: np.ndarray, current: np.ndarray ) -> tuple[np.ndarray, np.ndarray]: """ - Take the ``voltage`` and ``current`` arrays associated with a + Take the ``voltage`` and ``current`` arrays associated with a swept langmuir trace and average together clusters of identical voltage values. """ From e9e77b21dbb432db362b72223a2778160a87d62b Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 23 Jun 2025 10:39:55 -0700 Subject: [PATCH 313/521] _merge_voltage_clusters: fix docstring wording --- src/plasmapy/analysis/swept_langmuir/helpers.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/plasmapy/analysis/swept_langmuir/helpers.py b/src/plasmapy/analysis/swept_langmuir/helpers.py index 02b4cedc82..982ef95b4f 100644 --- a/src/plasmapy/analysis/swept_langmuir/helpers.py +++ b/src/plasmapy/analysis/swept_langmuir/helpers.py @@ -403,9 +403,9 @@ def _merge_voltage_clusters( force_regular_spacing: bool, ) -> tuple[np.ndarray, np.ndarray]: """ - Take the ``voltage`` and ``current`` arrays associated with a - langmuir trace and average together clusters voltage values within - step size ``voltage_step_size``. + Take the ``voltage`` and ``current`` arrays associated with a swept + langmuir trace and average together clusters of voltage values + within step size ``voltage_step_size``. """ # initialize new voltage and current arrays new_voltage = np.full(voltage.shape, np.nan, dtype=voltage.dtype) From 0d1a63a6ce9804e99a0f8944886f2652f726d7ad Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 23 Jun 2025 10:42:24 -0700 Subject: [PATCH 314/521] rename _merge_voltage_clusters -> _merge_voltage_clusters__within_dv --- src/plasmapy/analysis/swept_langmuir/helpers.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plasmapy/analysis/swept_langmuir/helpers.py b/src/plasmapy/analysis/swept_langmuir/helpers.py index 982ef95b4f..e9d556cf84 100644 --- a/src/plasmapy/analysis/swept_langmuir/helpers.py +++ b/src/plasmapy/analysis/swept_langmuir/helpers.py @@ -396,7 +396,7 @@ def _merge_zero_diff_voltage_clusters( return new_voltage, new_current -def _merge_voltage_clusters( +def _merge_voltage_clusters__within_dv( voltage: np.ndarray, current: np.ndarray, voltage_step_size: float, @@ -581,7 +581,7 @@ def merge_voltage_clusters( # noqa: C901, PLR0912 ) else: - new_voltage, new_current = _merge_voltage_clusters( + new_voltage, new_current = _merge_voltage_clusters__within_dv( voltage, current, voltage_step_size, force_regular_spacing ) From 2b997ecbba8ef94a335f5b851f8370ea43525c28 Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 23 Jun 2025 10:43:30 -0700 Subject: [PATCH 315/521] rename _merge_zero_diff_voltage_clusters -> _merge_voltage_clusters__zero_diff_neighbors --- src/plasmapy/analysis/swept_langmuir/helpers.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plasmapy/analysis/swept_langmuir/helpers.py b/src/plasmapy/analysis/swept_langmuir/helpers.py index e9d556cf84..e4aeaff53d 100644 --- a/src/plasmapy/analysis/swept_langmuir/helpers.py +++ b/src/plasmapy/analysis/swept_langmuir/helpers.py @@ -352,7 +352,7 @@ def _interpolate_sweep( return reg_voltage, reg_current -def _merge_zero_diff_voltage_clusters( +def _merge_voltage_clusters__zero_diff_neighbors( voltage: np.ndarray, current: np.ndarray ) -> tuple[np.ndarray, np.ndarray]: """ @@ -571,7 +571,7 @@ def merge_voltage_clusters( # noqa: C901, PLR0912 new_current = current.copy() elif voltage_step_size == 0: - new_voltage, new_current = _merge_zero_diff_voltage_clusters(voltage, current) + new_voltage, new_current = _merge_voltage_clusters__zero_diff_neighbors(voltage, current) if force_regular_spacing: new_voltage, new_current = merge_voltage_clusters( From a0b4af7f5077f7d7d8ea2d3b2650553698b0722a Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 23 Jun 2025 10:44:29 -0700 Subject: [PATCH 316/521] rename _interpolate_sweep -> _merge_voltage_clusters__interpolate_sweep --- src/plasmapy/analysis/swept_langmuir/helpers.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plasmapy/analysis/swept_langmuir/helpers.py b/src/plasmapy/analysis/swept_langmuir/helpers.py index e4aeaff53d..b622404d14 100644 --- a/src/plasmapy/analysis/swept_langmuir/helpers.py +++ b/src/plasmapy/analysis/swept_langmuir/helpers.py @@ -334,7 +334,7 @@ def _is_voltage_regularly_spaced( return is_regular_grid -def _interpolate_sweep( +def _merge_voltage_clusters__interpolate_sweep( voltage: np.ndarray, current: np.ndarray, voltage_step_size: float, @@ -563,7 +563,7 @@ def merge_voltage_clusters( # noqa: C901, PLR0912 # now merge clusters if voltage_step_size != 0 and np.all(voltage_diff >= voltage_step_size): if force_regular_spacing: - new_voltage, new_current = _interpolate_sweep( + new_voltage, new_current = _merge_voltage_clusters__interpolate_sweep( voltage, current, voltage_step_size ) else: From ccbc7cfa908fc3ea6c0dedb699444190caeba2ac Mon Sep 17 00:00:00 2001 From: "plasmapy-requirements-bot[bot]" <134649236+plasmapy-requirements-bot[bot]@users.noreply.github.com> Date: Mon, 23 Jun 2025 13:47:47 -0400 Subject: [PATCH 317/521] Update requirements with 'nox -s requirements' (#3040) Co-authored-by: namurphy <8931994+namurphy@users.noreply.github.com> --- uv.lock | 275 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 137 insertions(+), 138 deletions(-) diff --git a/uv.lock b/uv.lock index 19e5436373..b2adf35eac 100644 --- a/uv.lock +++ b/uv.lock @@ -140,11 +140,11 @@ wheels = [ [[package]] name = "astropy-iers-data" -version = "0.2025.6.16.0.38.47" +version = "0.2025.6.23.0.39.50" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/63/ae/efd931d47653f474afb1154d9181f885bf3f82854dcdd979a9e2838470c5/astropy_iers_data-0.2025.6.16.0.38.47.tar.gz", hash = "sha256:58c984976506b8a5c1c969aafe8744b286111d98c8623e66aecc45db9e777121", size = 1899704, upload-time = "2025-06-16T00:39:20.529Z" } +sdist = { url = "https://files.pythonhosted.org/packages/33/3a/cf170b5a55cd849d0543b929588b4cec326a5e6dde42e41ee7e43c2cff7f/astropy_iers_data-0.2025.6.23.0.39.50.tar.gz", hash = "sha256:3dd7cbf82408837ad21fb15db0c35d0bff19b1552f6b13de48542a246215a754", size = 1900117, upload-time = "2025-06-23T00:40:29.864Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/3c/35/e4b67e87d7ff182b59047db09dce11c7154273eee428c98fe0828adbf3d7/astropy_iers_data-0.2025.6.16.0.38.47-py3-none-any.whl", hash = "sha256:c8c2c999bb9fa987c89c737bc7e71d83f8a6c8fd874ef03b0adc196c1432e20e", size = 1955135, upload-time = "2025-06-16T00:39:18.731Z" }, + { url = "https://files.pythonhosted.org/packages/f1/07/3e936628ee19d2eb3e453f30df2f4f038dfff76423c8361001fb075d570d/astropy_iers_data-0.2025.6.23.0.39.50-py3-none-any.whl", hash = "sha256:52f7ed57cdbfcdfe410c78e766caaae84ce75aeabc86df9ed7785b0a52dd274b", size = 1955596, upload-time = "2025-06-23T00:40:28.407Z" }, ] [[package]] @@ -657,15 +657,15 @@ wheels = [ [[package]] name = "hypothesis" -version = "6.135.10" +version = "6.135.14" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "attrs" }, { name = "sortedcontainers" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/c8/8e/6176e9b3e51fbab6dab1e572116605dbc54eadda0c60dd45927f601d3c60/hypothesis-6.135.10.tar.gz", hash = "sha256:ce224e310012e40b8e3aa6edba226c032c57bbcbdccad41212ab6d2d74b602cf", size = 452518, upload-time = "2025-06-15T06:02:07.517Z" } +sdist = { url = "https://files.pythonhosted.org/packages/70/a5/d4f74ba61bbe5dd001c998ae8b85f9bfdc6cd29e6c5693d1116847b64251/hypothesis-6.135.14.tar.gz", hash = "sha256:2666df50b3cc40ea08b161a5389d6a1cd5aa3cab0dd8fde0ae339389714a4f67", size = 452884, upload-time = "2025-06-20T19:16:38.199Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/a9/e5/8c62bd37d2815f37a2886be6b9d5e037d14cc3f6adc377711f323617b113/hypothesis-6.135.10-py3-none-any.whl", hash = "sha256:275012ee9a7a1a64fd38745c2b7a07e838fc9f738d49c97a881d235b53fe28c1", size = 518624, upload-time = "2025-06-15T06:02:04.227Z" }, + { url = "https://files.pythonhosted.org/packages/ce/cf/491a487229b04a2ad56175c74700cfb79635dfce2d942becc6ab10c0ceb9/hypothesis-6.135.14-py3-none-any.whl", hash = "sha256:0dd5b8095e36bd288367c631f864a16c30500b01b17943dcea681233f7421860", size = 519115, upload-time = "2025-06-20T19:16:34.539Z" }, ] [[package]] @@ -1058,11 +1058,11 @@ wheels = [ [[package]] name = "latexcodec" -version = "3.0.0" +version = "3.0.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/98/e7/ed339caf3662976949e4fdbfdf4a6db818b8d2aa1cf2b5f73af89e936bba/latexcodec-3.0.0.tar.gz", hash = "sha256:917dc5fe242762cc19d963e6548b42d63a118028cdd3361d62397e3b638b6bc5", size = 31023, upload-time = "2024-03-06T14:51:39.283Z" } +sdist = { url = "https://files.pythonhosted.org/packages/27/dd/4270b2c5e2ee49316c3859e62293bd2ea8e382339d63ab7bbe9f39c0ec3b/latexcodec-3.0.1.tar.gz", hash = "sha256:e78a6911cd72f9dec35031c6ec23584de6842bfbc4610a9678868d14cdfb0357", size = 31222, upload-time = "2025-06-17T18:47:34.051Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/b0/bf/ea8887e9f31a8f93ca306699d11909c6140151393a4216f0d9f85a004077/latexcodec-3.0.0-py3-none-any.whl", hash = "sha256:6f3477ad5e61a0a99bd31a6a370c34e88733a6bad9c921a3ffcfacada12f41a7", size = 18150, upload-time = "2024-03-06T14:51:37.872Z" }, + { url = "https://files.pythonhosted.org/packages/b5/40/23569737873cc9637fd488606347e9dd92b9fa37ba4fcda1f98ee5219a97/latexcodec-3.0.1-py3-none-any.whl", hash = "sha256:a9eb8200bff693f0437a69581f7579eb6bca25c4193515c09900ce76451e452e", size = 18532, upload-time = "2025-06-17T18:47:30.726Z" }, ] [[package]] @@ -1204,34 +1204,34 @@ wheels = [ [[package]] name = "mypy" -version = "1.16.0" +version = "1.16.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "mypy-extensions" }, { name = "pathspec" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/d4/38/13c2f1abae94d5ea0354e146b95a1be9b2137a0d506728e0da037c4276f6/mypy-1.16.0.tar.gz", hash = "sha256:84b94283f817e2aa6350a14b4a8fb2a35a53c286f97c9d30f53b63620e7af8ab", size = 3323139, upload-time = "2025-05-29T13:46:12.532Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/24/c4/ff2f79db7075c274fe85b5fff8797d29c6b61b8854c39e3b7feb556aa377/mypy-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:9f826aaa7ff8443bac6a494cf743f591488ea940dd360e7dd330e30dd772a5ab", size = 10884498, upload-time = "2025-05-29T13:18:54.066Z" }, - { url = "https://files.pythonhosted.org/packages/02/07/12198e83006235f10f6a7808917376b5d6240a2fd5dce740fe5d2ebf3247/mypy-1.16.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:82d056e6faa508501af333a6af192c700b33e15865bda49611e3d7d8358ebea2", size = 10011755, upload-time = "2025-05-29T13:34:00.851Z" }, - { url = "https://files.pythonhosted.org/packages/f1/9b/5fd5801a72b5d6fb6ec0105ea1d0e01ab2d4971893076e558d4b6d6b5f80/mypy-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:089bedc02307c2548eb51f426e085546db1fa7dd87fbb7c9fa561575cf6eb1ff", size = 11800138, upload-time = "2025-05-29T13:32:55.082Z" }, - { url = "https://files.pythonhosted.org/packages/2e/81/a117441ea5dfc3746431e51d78a4aca569c677aa225bca2cc05a7c239b61/mypy-1.16.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6a2322896003ba66bbd1318c10d3afdfe24e78ef12ea10e2acd985e9d684a666", size = 12533156, upload-time = "2025-05-29T13:19:12.963Z" }, - { url = "https://files.pythonhosted.org/packages/3f/38/88ec57c6c86014d3f06251e00f397b5a7daa6888884d0abf187e4f5f587f/mypy-1.16.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:021a68568082c5b36e977d54e8f1de978baf401a33884ffcea09bd8e88a98f4c", size = 12742426, upload-time = "2025-05-29T13:20:22.72Z" }, - { url = "https://files.pythonhosted.org/packages/bd/53/7e9d528433d56e6f6f77ccf24af6ce570986c2d98a5839e4c2009ef47283/mypy-1.16.0-cp311-cp311-win_amd64.whl", hash = "sha256:54066fed302d83bf5128632d05b4ec68412e1f03ef2c300434057d66866cea4b", size = 9478319, upload-time = "2025-05-29T13:21:17.582Z" }, - { url = "https://files.pythonhosted.org/packages/70/cf/158e5055e60ca2be23aec54a3010f89dcffd788732634b344fc9cb1e85a0/mypy-1.16.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:c5436d11e89a3ad16ce8afe752f0f373ae9620841c50883dc96f8b8805620b13", size = 11062927, upload-time = "2025-05-29T13:35:52.328Z" }, - { url = "https://files.pythonhosted.org/packages/94/34/cfff7a56be1609f5d10ef386342ce3494158e4d506516890142007e6472c/mypy-1.16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f2622af30bf01d8fc36466231bdd203d120d7a599a6d88fb22bdcb9dbff84090", size = 10083082, upload-time = "2025-05-29T13:35:33.378Z" }, - { url = "https://files.pythonhosted.org/packages/b3/7f/7242062ec6288c33d8ad89574df87c3903d394870e5e6ba1699317a65075/mypy-1.16.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d045d33c284e10a038f5e29faca055b90eee87da3fc63b8889085744ebabb5a1", size = 11828306, upload-time = "2025-05-29T13:21:02.164Z" }, - { url = "https://files.pythonhosted.org/packages/6f/5f/b392f7b4f659f5b619ce5994c5c43caab3d80df2296ae54fa888b3d17f5a/mypy-1.16.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b4968f14f44c62e2ec4a038c8797a87315be8df7740dc3ee8d3bfe1c6bf5dba8", size = 12702764, upload-time = "2025-05-29T13:20:42.826Z" }, - { url = "https://files.pythonhosted.org/packages/9b/c0/7646ef3a00fa39ac9bc0938626d9ff29d19d733011be929cfea59d82d136/mypy-1.16.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:eb14a4a871bb8efb1e4a50360d4e3c8d6c601e7a31028a2c79f9bb659b63d730", size = 12896233, upload-time = "2025-05-29T13:18:37.446Z" }, - { url = "https://files.pythonhosted.org/packages/6d/38/52f4b808b3fef7f0ef840ee8ff6ce5b5d77381e65425758d515cdd4f5bb5/mypy-1.16.0-cp312-cp312-win_amd64.whl", hash = "sha256:bd4e1ebe126152a7bbaa4daedd781c90c8f9643c79b9748caa270ad542f12bec", size = 9565547, upload-time = "2025-05-29T13:20:02.836Z" }, - { url = "https://files.pythonhosted.org/packages/97/9c/ca03bdbefbaa03b264b9318a98950a9c683e06472226b55472f96ebbc53d/mypy-1.16.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:a9e056237c89f1587a3be1a3a70a06a698d25e2479b9a2f57325ddaaffc3567b", size = 11059753, upload-time = "2025-05-29T13:18:18.167Z" }, - { url = "https://files.pythonhosted.org/packages/36/92/79a969b8302cfe316027c88f7dc6fee70129490a370b3f6eb11d777749d0/mypy-1.16.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0b07e107affb9ee6ce1f342c07f51552d126c32cd62955f59a7db94a51ad12c0", size = 10073338, upload-time = "2025-05-29T13:19:48.079Z" }, - { url = "https://files.pythonhosted.org/packages/14/9b/a943f09319167da0552d5cd722104096a9c99270719b1afeea60d11610aa/mypy-1.16.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c6fb60cbd85dc65d4d63d37cb5c86f4e3a301ec605f606ae3a9173e5cf34997b", size = 11827764, upload-time = "2025-05-29T13:46:04.47Z" }, - { url = "https://files.pythonhosted.org/packages/ec/64/ff75e71c65a0cb6ee737287c7913ea155845a556c64144c65b811afdb9c7/mypy-1.16.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a7e32297a437cc915599e0578fa6bc68ae6a8dc059c9e009c628e1c47f91495d", size = 12701356, upload-time = "2025-05-29T13:35:13.553Z" }, - { url = "https://files.pythonhosted.org/packages/0a/ad/0e93c18987a1182c350f7a5fab70550852f9fabe30ecb63bfbe51b602074/mypy-1.16.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:afe420c9380ccec31e744e8baff0d406c846683681025db3531b32db56962d52", size = 12900745, upload-time = "2025-05-29T13:17:24.409Z" }, - { url = "https://files.pythonhosted.org/packages/28/5d/036c278d7a013e97e33f08c047fe5583ab4f1fc47c9a49f985f1cdd2a2d7/mypy-1.16.0-cp313-cp313-win_amd64.whl", hash = "sha256:55f9076c6ce55dd3f8cd0c6fff26a008ca8e5131b89d5ba6d86bd3f47e736eeb", size = 9572200, upload-time = "2025-05-29T13:33:44.92Z" }, - { url = "https://files.pythonhosted.org/packages/99/a3/6ed10530dec8e0fdc890d81361260c9ef1f5e5c217ad8c9b21ecb2b8366b/mypy-1.16.0-py3-none-any.whl", hash = "sha256:29e1499864a3888bca5c1542f2d7232c6e586295183320caa95758fc84034031", size = 2265773, upload-time = "2025-05-29T13:35:18.762Z" }, +sdist = { url = "https://files.pythonhosted.org/packages/81/69/92c7fa98112e4d9eb075a239caa4ef4649ad7d441545ccffbd5e34607cbb/mypy-1.16.1.tar.gz", hash = "sha256:6bd00a0a2094841c5e47e7374bb42b83d64c527a502e3334e1173a0c24437bab", size = 3324747, upload-time = "2025-06-16T16:51:35.145Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9a/61/ec1245aa1c325cb7a6c0f8570a2eee3bfc40fa90d19b1267f8e50b5c8645/mypy-1.16.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:472e4e4c100062488ec643f6162dd0d5208e33e2f34544e1fc931372e806c0cc", size = 10890557, upload-time = "2025-06-16T16:37:21.421Z" }, + { url = "https://files.pythonhosted.org/packages/6b/bb/6eccc0ba0aa0c7a87df24e73f0ad34170514abd8162eb0c75fd7128171fb/mypy-1.16.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ea16e2a7d2714277e349e24d19a782a663a34ed60864006e8585db08f8ad1782", size = 10012921, upload-time = "2025-06-16T16:51:28.659Z" }, + { url = "https://files.pythonhosted.org/packages/5f/80/b337a12e2006715f99f529e732c5f6a8c143bb58c92bb142d5ab380963a5/mypy-1.16.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:08e850ea22adc4d8a4014651575567b0318ede51e8e9fe7a68f25391af699507", size = 11802887, upload-time = "2025-06-16T16:50:53.627Z" }, + { url = "https://files.pythonhosted.org/packages/d9/59/f7af072d09793d581a745a25737c7c0a945760036b16aeb620f658a017af/mypy-1.16.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:22d76a63a42619bfb90122889b903519149879ddbf2ba4251834727944c8baca", size = 12531658, upload-time = "2025-06-16T16:33:55.002Z" }, + { url = "https://files.pythonhosted.org/packages/82/c4/607672f2d6c0254b94a646cfc45ad589dd71b04aa1f3d642b840f7cce06c/mypy-1.16.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:2c7ce0662b6b9dc8f4ed86eb7a5d505ee3298c04b40ec13b30e572c0e5ae17c4", size = 12732486, upload-time = "2025-06-16T16:37:03.301Z" }, + { url = "https://files.pythonhosted.org/packages/b6/5e/136555ec1d80df877a707cebf9081bd3a9f397dedc1ab9750518d87489ec/mypy-1.16.1-cp311-cp311-win_amd64.whl", hash = "sha256:211287e98e05352a2e1d4e8759c5490925a7c784ddc84207f4714822f8cf99b6", size = 9479482, upload-time = "2025-06-16T16:47:37.48Z" }, + { url = "https://files.pythonhosted.org/packages/b4/d6/39482e5fcc724c15bf6280ff5806548c7185e0c090712a3736ed4d07e8b7/mypy-1.16.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:af4792433f09575d9eeca5c63d7d90ca4aeceda9d8355e136f80f8967639183d", size = 11066493, upload-time = "2025-06-16T16:47:01.683Z" }, + { url = "https://files.pythonhosted.org/packages/e6/e5/26c347890efc6b757f4d5bb83f4a0cf5958b8cf49c938ac99b8b72b420a6/mypy-1.16.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:66df38405fd8466ce3517eda1f6640611a0b8e70895e2a9462d1d4323c5eb4b9", size = 10081687, upload-time = "2025-06-16T16:48:19.367Z" }, + { url = "https://files.pythonhosted.org/packages/44/c7/b5cb264c97b86914487d6a24bd8688c0172e37ec0f43e93b9691cae9468b/mypy-1.16.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:44e7acddb3c48bd2713994d098729494117803616e116032af192871aed80b79", size = 11839723, upload-time = "2025-06-16T16:49:20.912Z" }, + { url = "https://files.pythonhosted.org/packages/15/f8/491997a9b8a554204f834ed4816bda813aefda31cf873bb099deee3c9a99/mypy-1.16.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0ab5eca37b50188163fa7c1b73c685ac66c4e9bdee4a85c9adac0e91d8895e15", size = 12722980, upload-time = "2025-06-16T16:37:40.929Z" }, + { url = "https://files.pythonhosted.org/packages/df/f0/2bd41e174b5fd93bc9de9a28e4fb673113633b8a7f3a607fa4a73595e468/mypy-1.16.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:dedb6229b2c9086247e21a83c309754b9058b438704ad2f6807f0d8227f6ebdd", size = 12903328, upload-time = "2025-06-16T16:34:35.099Z" }, + { url = "https://files.pythonhosted.org/packages/61/81/5572108a7bec2c46b8aff7e9b524f371fe6ab5efb534d38d6b37b5490da8/mypy-1.16.1-cp312-cp312-win_amd64.whl", hash = "sha256:1f0435cf920e287ff68af3d10a118a73f212deb2ce087619eb4e648116d1fe9b", size = 9562321, upload-time = "2025-06-16T16:48:58.823Z" }, + { url = "https://files.pythonhosted.org/packages/28/e3/96964af4a75a949e67df4b95318fe2b7427ac8189bbc3ef28f92a1c5bc56/mypy-1.16.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ddc91eb318c8751c69ddb200a5937f1232ee8efb4e64e9f4bc475a33719de438", size = 11063480, upload-time = "2025-06-16T16:47:56.205Z" }, + { url = "https://files.pythonhosted.org/packages/f5/4d/cd1a42b8e5be278fab7010fb289d9307a63e07153f0ae1510a3d7b703193/mypy-1.16.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:87ff2c13d58bdc4bbe7dc0dedfe622c0f04e2cb2a492269f3b418df2de05c536", size = 10090538, upload-time = "2025-06-16T16:46:43.92Z" }, + { url = "https://files.pythonhosted.org/packages/c9/4f/c3c6b4b66374b5f68bab07c8cabd63a049ff69796b844bc759a0ca99bb2a/mypy-1.16.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0a7cfb0fe29fe5a9841b7c8ee6dffb52382c45acdf68f032145b75620acfbd6f", size = 11836839, upload-time = "2025-06-16T16:36:28.039Z" }, + { url = "https://files.pythonhosted.org/packages/b4/7e/81ca3b074021ad9775e5cb97ebe0089c0f13684b066a750b7dc208438403/mypy-1.16.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:051e1677689c9d9578b9c7f4d206d763f9bbd95723cd1416fad50db49d52f359", size = 12715634, upload-time = "2025-06-16T16:50:34.441Z" }, + { url = "https://files.pythonhosted.org/packages/e9/95/bdd40c8be346fa4c70edb4081d727a54d0a05382d84966869738cfa8a497/mypy-1.16.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:d5d2309511cc56c021b4b4e462907c2b12f669b2dbeb68300110ec27723971be", size = 12895584, upload-time = "2025-06-16T16:34:54.857Z" }, + { url = "https://files.pythonhosted.org/packages/5a/fd/d486a0827a1c597b3b48b1bdef47228a6e9ee8102ab8c28f944cb83b65dc/mypy-1.16.1-cp313-cp313-win_amd64.whl", hash = "sha256:4f58ac32771341e38a853c5d0ec0dfe27e18e27da9cdb8bbc882d2249c71a3ee", size = 9573886, upload-time = "2025-06-16T16:36:43.589Z" }, + { url = "https://files.pythonhosted.org/packages/cf/d3/53e684e78e07c1a2bf7105715e5edd09ce951fc3f47cf9ed095ec1b7a037/mypy-1.16.1-py3-none-any.whl", hash = "sha256:5fc2ac4027d0ef28d6ba69a0343737a23c4d1b83672bf38d1fe237bdc0643b37", size = 2265923, upload-time = "2025-06-16T16:48:02.366Z" }, ] [[package]] @@ -1343,60 +1343,60 @@ wheels = [ [[package]] name = "numpy" -version = "2.3.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f3/db/8e12381333aea300890829a0a36bfa738cac95475d88982d538725143fd9/numpy-2.3.0.tar.gz", hash = "sha256:581f87f9e9e9db2cba2141400e160e9dd644ee248788d6f90636eeb8fd9260a6", size = 20382813, upload-time = "2025-06-07T14:54:32.608Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/fd/5f/df67435257d827eb3b8af66f585223dc2c3f2eb7ad0b50cb1dae2f35f494/numpy-2.3.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c3c9fdde0fa18afa1099d6257eb82890ea4f3102847e692193b54e00312a9ae9", size = 21199688, upload-time = "2025-06-07T14:36:52.067Z" }, - { url = "https://files.pythonhosted.org/packages/e5/ce/aad219575055d6c9ef29c8c540c81e1c38815d3be1fe09cdbe53d48ee838/numpy-2.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:46d16f72c2192da7b83984aa5455baee640e33a9f1e61e656f29adf55e406c2b", size = 14359277, upload-time = "2025-06-07T14:37:15.325Z" }, - { url = "https://files.pythonhosted.org/packages/29/6b/2d31da8e6d2ec99bed54c185337a87f8fbeccc1cd9804e38217e92f3f5e2/numpy-2.3.0-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:a0be278be9307c4ab06b788f2a077f05e180aea817b3e41cebbd5aaf7bd85ed3", size = 5376069, upload-time = "2025-06-07T14:37:25.636Z" }, - { url = "https://files.pythonhosted.org/packages/7d/2a/6c59a062397553ec7045c53d5fcdad44e4536e54972faa2ba44153bca984/numpy-2.3.0-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:99224862d1412d2562248d4710126355d3a8db7672170a39d6909ac47687a8a4", size = 6913057, upload-time = "2025-06-07T14:37:37.215Z" }, - { url = "https://files.pythonhosted.org/packages/d5/5a/8df16f258d28d033e4f359e29d3aeb54663243ac7b71504e89deeb813202/numpy-2.3.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:2393a914db64b0ead0ab80c962e42d09d5f385802006a6c87835acb1f58adb96", size = 14568083, upload-time = "2025-06-07T14:37:59.337Z" }, - { url = "https://files.pythonhosted.org/packages/0a/92/0528a563dfc2cdccdcb208c0e241a4bb500d7cde218651ffb834e8febc50/numpy-2.3.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:7729c8008d55e80784bd113787ce876ca117185c579c0d626f59b87d433ea779", size = 16929402, upload-time = "2025-06-07T14:38:24.343Z" }, - { url = "https://files.pythonhosted.org/packages/e4/2f/e7a8c8d4a2212c527568d84f31587012cf5497a7271ea1f23332142f634e/numpy-2.3.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:06d4fb37a8d383b769281714897420c5cc3545c79dc427df57fc9b852ee0bf58", size = 15879193, upload-time = "2025-06-07T14:38:48.007Z" }, - { url = "https://files.pythonhosted.org/packages/e2/c3/dada3f005953847fe35f42ac0fe746f6e1ea90b4c6775e4be605dcd7b578/numpy-2.3.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:c39ec392b5db5088259c68250e342612db82dc80ce044cf16496cf14cf6bc6f8", size = 18665318, upload-time = "2025-06-07T14:39:15.794Z" }, - { url = "https://files.pythonhosted.org/packages/3b/ae/3f448517dedefc8dd64d803f9d51a8904a48df730e00a3c5fb1e75a60620/numpy-2.3.0-cp311-cp311-win32.whl", hash = "sha256:ee9d3ee70d62827bc91f3ea5eee33153212c41f639918550ac0475e3588da59f", size = 6601108, upload-time = "2025-06-07T14:39:27.176Z" }, - { url = "https://files.pythonhosted.org/packages/8c/4a/556406d2bb2b9874c8cbc840c962683ac28f21efbc9b01177d78f0199ca1/numpy-2.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:43c55b6a860b0eb44d42341438b03513cf3879cb3617afb749ad49307e164edd", size = 13021525, upload-time = "2025-06-07T14:39:46.637Z" }, - { url = "https://files.pythonhosted.org/packages/ed/ee/bf54278aef30335ffa9a189f869ea09e1a195b3f4b93062164a3b02678a7/numpy-2.3.0-cp311-cp311-win_arm64.whl", hash = "sha256:2e6a1409eee0cb0316cb64640a49a49ca44deb1a537e6b1121dc7c458a1299a8", size = 10170327, upload-time = "2025-06-07T14:40:02.703Z" }, - { url = "https://files.pythonhosted.org/packages/89/59/9df493df81ac6f76e9f05cdbe013cdb0c9a37b434f6e594f5bd25e278908/numpy-2.3.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:389b85335838155a9076e9ad7f8fdba0827496ec2d2dc32ce69ce7898bde03ba", size = 20897025, upload-time = "2025-06-07T14:40:33.558Z" }, - { url = "https://files.pythonhosted.org/packages/2f/86/4ff04335901d6cf3a6bb9c748b0097546ae5af35e455ae9b962ebff4ecd7/numpy-2.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9498f60cd6bb8238d8eaf468a3d5bb031d34cd12556af53510f05fcf581c1b7e", size = 14129882, upload-time = "2025-06-07T14:40:55.034Z" }, - { url = "https://files.pythonhosted.org/packages/71/8d/a942cd4f959de7f08a79ab0c7e6cecb7431d5403dce78959a726f0f57aa1/numpy-2.3.0-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:622a65d40d8eb427d8e722fd410ac3ad4958002f109230bc714fa551044ebae2", size = 5110181, upload-time = "2025-06-07T14:41:04.4Z" }, - { url = "https://files.pythonhosted.org/packages/86/5d/45850982efc7b2c839c5626fb67fbbc520d5b0d7c1ba1ae3651f2f74c296/numpy-2.3.0-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:b9446d9d8505aadadb686d51d838f2b6688c9e85636a0c3abaeb55ed54756459", size = 6647581, upload-time = "2025-06-07T14:41:14.695Z" }, - { url = "https://files.pythonhosted.org/packages/1a/c0/c871d4a83f93b00373d3eebe4b01525eee8ef10b623a335ec262b58f4dc1/numpy-2.3.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:50080245365d75137a2bf46151e975de63146ae6d79f7e6bd5c0e85c9931d06a", size = 14262317, upload-time = "2025-06-07T14:41:35.862Z" }, - { url = "https://files.pythonhosted.org/packages/b7/f6/bc47f5fa666d5ff4145254f9e618d56e6a4ef9b874654ca74c19113bb538/numpy-2.3.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:c24bb4113c66936eeaa0dc1e47c74770453d34f46ee07ae4efd853a2ed1ad10a", size = 16633919, upload-time = "2025-06-07T14:42:00.622Z" }, - { url = "https://files.pythonhosted.org/packages/f5/b4/65f48009ca0c9b76df5f404fccdea5a985a1bb2e34e97f21a17d9ad1a4ba/numpy-2.3.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:4d8d294287fdf685281e671886c6dcdf0291a7c19db3e5cb4178d07ccf6ecc67", size = 15567651, upload-time = "2025-06-07T14:42:24.429Z" }, - { url = "https://files.pythonhosted.org/packages/f1/62/5367855a2018578e9334ed08252ef67cc302e53edc869666f71641cad40b/numpy-2.3.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:6295f81f093b7f5769d1728a6bd8bf7466de2adfa771ede944ce6711382b89dc", size = 18361723, upload-time = "2025-06-07T14:42:51.167Z" }, - { url = "https://files.pythonhosted.org/packages/d4/75/5baed8cd867eabee8aad1e74d7197d73971d6a3d40c821f1848b8fab8b84/numpy-2.3.0-cp312-cp312-win32.whl", hash = "sha256:e6648078bdd974ef5d15cecc31b0c410e2e24178a6e10bf511e0557eed0f2570", size = 6318285, upload-time = "2025-06-07T14:43:02.052Z" }, - { url = "https://files.pythonhosted.org/packages/bc/49/d5781eaa1a15acb3b3a3f49dc9e2ff18d92d0ce5c2976f4ab5c0a7360250/numpy-2.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:0898c67a58cdaaf29994bc0e2c65230fd4de0ac40afaf1584ed0b02cd74c6fdd", size = 12732594, upload-time = "2025-06-07T14:43:21.071Z" }, - { url = "https://files.pythonhosted.org/packages/c2/1c/6d343e030815c7c97a1f9fbad00211b47717c7fe446834c224bd5311e6f1/numpy-2.3.0-cp312-cp312-win_arm64.whl", hash = "sha256:bd8df082b6c4695753ad6193018c05aac465d634834dca47a3ae06d4bb22d9ea", size = 9891498, upload-time = "2025-06-07T14:43:36.332Z" }, - { url = "https://files.pythonhosted.org/packages/73/fc/1d67f751fd4dbafc5780244fe699bc4084268bad44b7c5deb0492473127b/numpy-2.3.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5754ab5595bfa2c2387d241296e0381c21f44a4b90a776c3c1d39eede13a746a", size = 20889633, upload-time = "2025-06-07T14:44:06.839Z" }, - { url = "https://files.pythonhosted.org/packages/e8/95/73ffdb69e5c3f19ec4530f8924c4386e7ba097efc94b9c0aff607178ad94/numpy-2.3.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d11fa02f77752d8099573d64e5fe33de3229b6632036ec08f7080f46b6649959", size = 14151683, upload-time = "2025-06-07T14:44:28.847Z" }, - { url = "https://files.pythonhosted.org/packages/64/d5/06d4bb31bb65a1d9c419eb5676173a2f90fd8da3c59f816cc54c640ce265/numpy-2.3.0-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:aba48d17e87688a765ab1cd557882052f238e2f36545dfa8e29e6a91aef77afe", size = 5102683, upload-time = "2025-06-07T14:44:38.417Z" }, - { url = "https://files.pythonhosted.org/packages/12/8b/6c2cef44f8ccdc231f6b56013dff1d71138c48124334aded36b1a1b30c5a/numpy-2.3.0-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:4dc58865623023b63b10d52f18abaac3729346a7a46a778381e0e3af4b7f3beb", size = 6640253, upload-time = "2025-06-07T14:44:49.359Z" }, - { url = "https://files.pythonhosted.org/packages/62/aa/fca4bf8de3396ddb59544df9b75ffe5b73096174de97a9492d426f5cd4aa/numpy-2.3.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:df470d376f54e052c76517393fa443758fefcdd634645bc9c1f84eafc67087f0", size = 14258658, upload-time = "2025-06-07T14:45:10.156Z" }, - { url = "https://files.pythonhosted.org/packages/1c/12/734dce1087eed1875f2297f687e671cfe53a091b6f2f55f0c7241aad041b/numpy-2.3.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:87717eb24d4a8a64683b7a4e91ace04e2f5c7c77872f823f02a94feee186168f", size = 16628765, upload-time = "2025-06-07T14:45:35.076Z" }, - { url = "https://files.pythonhosted.org/packages/48/03/ffa41ade0e825cbcd5606a5669962419528212a16082763fc051a7247d76/numpy-2.3.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d8fa264d56882b59dcb5ea4d6ab6f31d0c58a57b41aec605848b6eb2ef4a43e8", size = 15564335, upload-time = "2025-06-07T14:45:58.797Z" }, - { url = "https://files.pythonhosted.org/packages/07/58/869398a11863310aee0ff85a3e13b4c12f20d032b90c4b3ee93c3b728393/numpy-2.3.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e651756066a0eaf900916497e20e02fe1ae544187cb0fe88de981671ee7f6270", size = 18360608, upload-time = "2025-06-07T14:46:25.687Z" }, - { url = "https://files.pythonhosted.org/packages/2f/8a/5756935752ad278c17e8a061eb2127c9a3edf4ba2c31779548b336f23c8d/numpy-2.3.0-cp313-cp313-win32.whl", hash = "sha256:e43c3cce3b6ae5f94696669ff2a6eafd9a6b9332008bafa4117af70f4b88be6f", size = 6310005, upload-time = "2025-06-07T14:50:13.138Z" }, - { url = "https://files.pythonhosted.org/packages/08/60/61d60cf0dfc0bf15381eaef46366ebc0c1a787856d1db0c80b006092af84/numpy-2.3.0-cp313-cp313-win_amd64.whl", hash = "sha256:81ae0bf2564cf475f94be4a27ef7bcf8af0c3e28da46770fc904da9abd5279b5", size = 12729093, upload-time = "2025-06-07T14:50:31.82Z" }, - { url = "https://files.pythonhosted.org/packages/66/31/2f2f2d2b3e3c32d5753d01437240feaa32220b73258c9eef2e42a0832866/numpy-2.3.0-cp313-cp313-win_arm64.whl", hash = "sha256:c8738baa52505fa6e82778580b23f945e3578412554d937093eac9205e845e6e", size = 9885689, upload-time = "2025-06-07T14:50:47.888Z" }, - { url = "https://files.pythonhosted.org/packages/f1/89/c7828f23cc50f607ceb912774bb4cff225ccae7131c431398ad8400e2c98/numpy-2.3.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:39b27d8b38942a647f048b675f134dd5a567f95bfff481f9109ec308515c51d8", size = 20986612, upload-time = "2025-06-07T14:46:56.077Z" }, - { url = "https://files.pythonhosted.org/packages/dd/46/79ecf47da34c4c50eedec7511e53d57ffdfd31c742c00be7dc1d5ffdb917/numpy-2.3.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:0eba4a1ea88f9a6f30f56fdafdeb8da3774349eacddab9581a21234b8535d3d3", size = 14298953, upload-time = "2025-06-07T14:47:18.053Z" }, - { url = "https://files.pythonhosted.org/packages/59/44/f6caf50713d6ff4480640bccb2a534ce1d8e6e0960c8f864947439f0ee95/numpy-2.3.0-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:b0f1f11d0a1da54927436505a5a7670b154eac27f5672afc389661013dfe3d4f", size = 5225806, upload-time = "2025-06-07T14:47:27.524Z" }, - { url = "https://files.pythonhosted.org/packages/a6/43/e1fd1aca7c97e234dd05e66de4ab7a5be54548257efcdd1bc33637e72102/numpy-2.3.0-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:690d0a5b60a47e1f9dcec7b77750a4854c0d690e9058b7bef3106e3ae9117808", size = 6735169, upload-time = "2025-06-07T14:47:38.057Z" }, - { url = "https://files.pythonhosted.org/packages/84/89/f76f93b06a03177c0faa7ca94d0856c4e5c4bcaf3c5f77640c9ed0303e1c/numpy-2.3.0-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:8b51ead2b258284458e570942137155978583e407babc22e3d0ed7af33ce06f8", size = 14330701, upload-time = "2025-06-07T14:47:59.113Z" }, - { url = "https://files.pythonhosted.org/packages/aa/f5/4858c3e9ff7a7d64561b20580cf7cc5d085794bd465a19604945d6501f6c/numpy-2.3.0-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:aaf81c7b82c73bd9b45e79cfb9476cb9c29e937494bfe9092c26aece812818ad", size = 16692983, upload-time = "2025-06-07T14:48:24.196Z" }, - { url = "https://files.pythonhosted.org/packages/08/17/0e3b4182e691a10e9483bcc62b4bb8693dbf9ea5dc9ba0b77a60435074bb/numpy-2.3.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:f420033a20b4f6a2a11f585f93c843ac40686a7c3fa514060a97d9de93e5e72b", size = 15641435, upload-time = "2025-06-07T14:48:47.712Z" }, - { url = "https://files.pythonhosted.org/packages/4e/d5/463279fda028d3c1efa74e7e8d507605ae87f33dbd0543cf4c4527c8b882/numpy-2.3.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:d344ca32ab482bcf8735d8f95091ad081f97120546f3d250240868430ce52555", size = 18433798, upload-time = "2025-06-07T14:49:14.866Z" }, - { url = "https://files.pythonhosted.org/packages/0e/1e/7a9d98c886d4c39a2b4d3a7c026bffcf8fbcaf518782132d12a301cfc47a/numpy-2.3.0-cp313-cp313t-win32.whl", hash = "sha256:48a2e8eaf76364c32a1feaa60d6925eaf32ed7a040183b807e02674305beef61", size = 6438632, upload-time = "2025-06-07T14:49:25.67Z" }, - { url = "https://files.pythonhosted.org/packages/fe/ab/66fc909931d5eb230107d016861824f335ae2c0533f422e654e5ff556784/numpy-2.3.0-cp313-cp313t-win_amd64.whl", hash = "sha256:ba17f93a94e503551f154de210e4d50c5e3ee20f7e7a1b5f6ce3f22d419b93bb", size = 12868491, upload-time = "2025-06-07T14:49:44.898Z" }, - { url = "https://files.pythonhosted.org/packages/ee/e8/2c8a1c9e34d6f6d600c83d5ce5b71646c32a13f34ca5c518cc060639841c/numpy-2.3.0-cp313-cp313t-win_arm64.whl", hash = "sha256:f14e016d9409680959691c109be98c436c6249eaf7f118b424679793607b5944", size = 9935345, upload-time = "2025-06-07T14:50:02.311Z" }, - { url = "https://files.pythonhosted.org/packages/6a/a2/f8c1133f90eaa1c11bbbec1dc28a42054d0ce74bc2c9838c5437ba5d4980/numpy-2.3.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:80b46117c7359de8167cc00a2c7d823bdd505e8c7727ae0871025a86d668283b", size = 21070759, upload-time = "2025-06-07T14:51:18.241Z" }, - { url = "https://files.pythonhosted.org/packages/6c/e0/4c05fc44ba28463096eee5ae2a12832c8d2759cc5bcec34ae33386d3ff83/numpy-2.3.0-pp311-pypy311_pp73-macosx_14_0_arm64.whl", hash = "sha256:5814a0f43e70c061f47abd5857d120179609ddc32a613138cbb6c4e9e2dbdda5", size = 5301054, upload-time = "2025-06-07T14:51:27.413Z" }, - { url = "https://files.pythonhosted.org/packages/8a/3b/6c06cdebe922bbc2a466fe2105f50f661238ea223972a69c7deb823821e7/numpy-2.3.0-pp311-pypy311_pp73-macosx_14_0_x86_64.whl", hash = "sha256:ef6c1e88fd6b81ac6d215ed71dc8cd027e54d4bf1d2682d362449097156267a2", size = 6817520, upload-time = "2025-06-07T14:51:38.015Z" }, - { url = "https://files.pythonhosted.org/packages/9d/a3/1e536797fd10eb3c5dbd2e376671667c9af19e241843548575267242ea02/numpy-2.3.0-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:33a5a12a45bb82d9997e2c0b12adae97507ad7c347546190a18ff14c28bbca12", size = 14398078, upload-time = "2025-06-07T14:52:00.122Z" }, - { url = "https://files.pythonhosted.org/packages/7c/61/9d574b10d9368ecb1a0c923952aa593510a20df4940aa615b3a71337c8db/numpy-2.3.0-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:54dfc8681c1906d239e95ab1508d0a533c4a9505e52ee2d71a5472b04437ef97", size = 16751324, upload-time = "2025-06-07T14:52:25.077Z" }, - { url = "https://files.pythonhosted.org/packages/39/de/bcad52ce972dc26232629ca3a99721fd4b22c1d2bda84d5db6541913ef9c/numpy-2.3.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:e017a8a251ff4d18d71f139e28bdc7c31edba7a507f72b1414ed902cbe48c74d", size = 12924237, upload-time = "2025-06-07T14:52:44.713Z" }, +version = "2.3.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/2e/19/d7c972dfe90a353dbd3efbbe1d14a5951de80c99c9dc1b93cd998d51dc0f/numpy-2.3.1.tar.gz", hash = "sha256:1ec9ae20a4226da374362cca3c62cd753faf2f951440b0e3b98e93c235441d2b", size = 20390372, upload-time = "2025-06-21T12:28:33.469Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b0/c7/87c64d7ab426156530676000c94784ef55676df2f13b2796f97722464124/numpy-2.3.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6ea9e48336a402551f52cd8f593343699003d2353daa4b72ce8d34f66b722070", size = 21199346, upload-time = "2025-06-21T11:47:47.57Z" }, + { url = "https://files.pythonhosted.org/packages/58/0e/0966c2f44beeac12af8d836e5b5f826a407cf34c45cb73ddcdfce9f5960b/numpy-2.3.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5ccb7336eaf0e77c1635b232c141846493a588ec9ea777a7c24d7166bb8533ae", size = 14361143, upload-time = "2025-06-21T11:48:10.766Z" }, + { url = "https://files.pythonhosted.org/packages/7d/31/6e35a247acb1bfc19226791dfc7d4c30002cd4e620e11e58b0ddf836fe52/numpy-2.3.1-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:0bb3a4a61e1d327e035275d2a993c96fa786e4913aa089843e6a2d9dd205c66a", size = 5378989, upload-time = "2025-06-21T11:48:19.998Z" }, + { url = "https://files.pythonhosted.org/packages/b0/25/93b621219bb6f5a2d4e713a824522c69ab1f06a57cd571cda70e2e31af44/numpy-2.3.1-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:e344eb79dab01f1e838ebb67aab09965fb271d6da6b00adda26328ac27d4a66e", size = 6912890, upload-time = "2025-06-21T11:48:31.376Z" }, + { url = "https://files.pythonhosted.org/packages/ef/60/6b06ed98d11fb32e27fb59468b42383f3877146d3ee639f733776b6ac596/numpy-2.3.1-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:467db865b392168ceb1ef1ffa6f5a86e62468c43e0cfb4ab6da667ede10e58db", size = 14569032, upload-time = "2025-06-21T11:48:52.563Z" }, + { url = "https://files.pythonhosted.org/packages/75/c9/9bec03675192077467a9c7c2bdd1f2e922bd01d3a69b15c3a0fdcd8548f6/numpy-2.3.1-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:afed2ce4a84f6b0fc6c1ce734ff368cbf5a5e24e8954a338f3bdffa0718adffb", size = 16930354, upload-time = "2025-06-21T11:49:17.473Z" }, + { url = "https://files.pythonhosted.org/packages/6a/e2/5756a00cabcf50a3f527a0c968b2b4881c62b1379223931853114fa04cda/numpy-2.3.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0025048b3c1557a20bc80d06fdeb8cc7fc193721484cca82b2cfa072fec71a93", size = 15879605, upload-time = "2025-06-21T11:49:41.161Z" }, + { url = "https://files.pythonhosted.org/packages/ff/86/a471f65f0a86f1ca62dcc90b9fa46174dd48f50214e5446bc16a775646c5/numpy-2.3.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a5ee121b60aa509679b682819c602579e1df14a5b07fe95671c8849aad8f2115", size = 18666994, upload-time = "2025-06-21T11:50:08.516Z" }, + { url = "https://files.pythonhosted.org/packages/43/a6/482a53e469b32be6500aaf61cfafd1de7a0b0d484babf679209c3298852e/numpy-2.3.1-cp311-cp311-win32.whl", hash = "sha256:a8b740f5579ae4585831b3cf0e3b0425c667274f82a484866d2adf9570539369", size = 6603672, upload-time = "2025-06-21T11:50:19.584Z" }, + { url = "https://files.pythonhosted.org/packages/6b/fb/bb613f4122c310a13ec67585c70e14b03bfc7ebabd24f4d5138b97371d7c/numpy-2.3.1-cp311-cp311-win_amd64.whl", hash = "sha256:d4580adadc53311b163444f877e0789f1c8861e2698f6b2a4ca852fda154f3ff", size = 13024015, upload-time = "2025-06-21T11:50:39.139Z" }, + { url = "https://files.pythonhosted.org/packages/51/58/2d842825af9a0c041aca246dc92eb725e1bc5e1c9ac89712625db0c4e11c/numpy-2.3.1-cp311-cp311-win_arm64.whl", hash = "sha256:ec0bdafa906f95adc9a0c6f26a4871fa753f25caaa0e032578a30457bff0af6a", size = 10456989, upload-time = "2025-06-21T11:50:55.616Z" }, + { url = "https://files.pythonhosted.org/packages/c6/56/71ad5022e2f63cfe0ca93559403d0edef14aea70a841d640bd13cdba578e/numpy-2.3.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:2959d8f268f3d8ee402b04a9ec4bb7604555aeacf78b360dc4ec27f1d508177d", size = 20896664, upload-time = "2025-06-21T12:15:30.845Z" }, + { url = "https://files.pythonhosted.org/packages/25/65/2db52ba049813670f7f987cc5db6dac9be7cd95e923cc6832b3d32d87cef/numpy-2.3.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:762e0c0c6b56bdedfef9a8e1d4538556438288c4276901ea008ae44091954e29", size = 14131078, upload-time = "2025-06-21T12:15:52.23Z" }, + { url = "https://files.pythonhosted.org/packages/57/dd/28fa3c17b0e751047ac928c1e1b6990238faad76e9b147e585b573d9d1bd/numpy-2.3.1-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:867ef172a0976aaa1f1d1b63cf2090de8b636a7674607d514505fb7276ab08fc", size = 5112554, upload-time = "2025-06-21T12:16:01.434Z" }, + { url = "https://files.pythonhosted.org/packages/c9/fc/84ea0cba8e760c4644b708b6819d91784c290288c27aca916115e3311d17/numpy-2.3.1-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:4e602e1b8682c2b833af89ba641ad4176053aaa50f5cacda1a27004352dde943", size = 6646560, upload-time = "2025-06-21T12:16:11.895Z" }, + { url = "https://files.pythonhosted.org/packages/61/b2/512b0c2ddec985ad1e496b0bd853eeb572315c0f07cd6997473ced8f15e2/numpy-2.3.1-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:8e333040d069eba1652fb08962ec5b76af7f2c7bce1df7e1418c8055cf776f25", size = 14260638, upload-time = "2025-06-21T12:16:32.611Z" }, + { url = "https://files.pythonhosted.org/packages/6e/45/c51cb248e679a6c6ab14b7a8e3ead3f4a3fe7425fc7a6f98b3f147bec532/numpy-2.3.1-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:e7cbf5a5eafd8d230a3ce356d892512185230e4781a361229bd902ff403bc660", size = 16632729, upload-time = "2025-06-21T12:16:57.439Z" }, + { url = "https://files.pythonhosted.org/packages/e4/ff/feb4be2e5c09a3da161b412019caf47183099cbea1132fd98061808c2df2/numpy-2.3.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5f1b8f26d1086835f442286c1d9b64bb3974b0b1e41bb105358fd07d20872952", size = 15565330, upload-time = "2025-06-21T12:17:20.638Z" }, + { url = "https://files.pythonhosted.org/packages/bc/6d/ceafe87587101e9ab0d370e4f6e5f3f3a85b9a697f2318738e5e7e176ce3/numpy-2.3.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ee8340cb48c9b7a5899d1149eece41ca535513a9698098edbade2a8e7a84da77", size = 18361734, upload-time = "2025-06-21T12:17:47.938Z" }, + { url = "https://files.pythonhosted.org/packages/2b/19/0fb49a3ea088be691f040c9bf1817e4669a339d6e98579f91859b902c636/numpy-2.3.1-cp312-cp312-win32.whl", hash = "sha256:e772dda20a6002ef7061713dc1e2585bc1b534e7909b2030b5a46dae8ff077ab", size = 6320411, upload-time = "2025-06-21T12:17:58.475Z" }, + { url = "https://files.pythonhosted.org/packages/b1/3e/e28f4c1dd9e042eb57a3eb652f200225e311b608632bc727ae378623d4f8/numpy-2.3.1-cp312-cp312-win_amd64.whl", hash = "sha256:cfecc7822543abdea6de08758091da655ea2210b8ffa1faf116b940693d3df76", size = 12734973, upload-time = "2025-06-21T12:18:17.601Z" }, + { url = "https://files.pythonhosted.org/packages/04/a8/8a5e9079dc722acf53522b8f8842e79541ea81835e9b5483388701421073/numpy-2.3.1-cp312-cp312-win_arm64.whl", hash = "sha256:7be91b2239af2658653c5bb6f1b8bccafaf08226a258caf78ce44710a0160d30", size = 10191491, upload-time = "2025-06-21T12:18:33.585Z" }, + { url = "https://files.pythonhosted.org/packages/d4/bd/35ad97006d8abff8631293f8ea6adf07b0108ce6fec68da3c3fcca1197f2/numpy-2.3.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:25a1992b0a3fdcdaec9f552ef10d8103186f5397ab45e2d25f8ac51b1a6b97e8", size = 20889381, upload-time = "2025-06-21T12:19:04.103Z" }, + { url = "https://files.pythonhosted.org/packages/f1/4f/df5923874d8095b6062495b39729178eef4a922119cee32a12ee1bd4664c/numpy-2.3.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:7dea630156d39b02a63c18f508f85010230409db5b2927ba59c8ba4ab3e8272e", size = 14152726, upload-time = "2025-06-21T12:19:25.599Z" }, + { url = "https://files.pythonhosted.org/packages/8c/0f/a1f269b125806212a876f7efb049b06c6f8772cf0121139f97774cd95626/numpy-2.3.1-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:bada6058dd886061f10ea15f230ccf7dfff40572e99fef440a4a857c8728c9c0", size = 5105145, upload-time = "2025-06-21T12:19:34.782Z" }, + { url = "https://files.pythonhosted.org/packages/6d/63/a7f7fd5f375b0361682f6ffbf686787e82b7bbd561268e4f30afad2bb3c0/numpy-2.3.1-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:a894f3816eb17b29e4783e5873f92faf55b710c2519e5c351767c51f79d8526d", size = 6639409, upload-time = "2025-06-21T12:19:45.228Z" }, + { url = "https://files.pythonhosted.org/packages/bf/0d/1854a4121af895aab383f4aa233748f1df4671ef331d898e32426756a8a6/numpy-2.3.1-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:18703df6c4a4fee55fd3d6e5a253d01c5d33a295409b03fda0c86b3ca2ff41a1", size = 14257630, upload-time = "2025-06-21T12:20:06.544Z" }, + { url = "https://files.pythonhosted.org/packages/50/30/af1b277b443f2fb08acf1c55ce9d68ee540043f158630d62cef012750f9f/numpy-2.3.1-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:5902660491bd7a48b2ec16c23ccb9124b8abfd9583c5fdfa123fe6b421e03de1", size = 16627546, upload-time = "2025-06-21T12:20:31.002Z" }, + { url = "https://files.pythonhosted.org/packages/6e/ec/3b68220c277e463095342d254c61be8144c31208db18d3fd8ef02712bcd6/numpy-2.3.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:36890eb9e9d2081137bd78d29050ba63b8dab95dff7912eadf1185e80074b2a0", size = 15562538, upload-time = "2025-06-21T12:20:54.322Z" }, + { url = "https://files.pythonhosted.org/packages/77/2b/4014f2bcc4404484021c74d4c5ee8eb3de7e3f7ac75f06672f8dcf85140a/numpy-2.3.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a780033466159c2270531e2b8ac063704592a0bc62ec4a1b991c7c40705eb0e8", size = 18360327, upload-time = "2025-06-21T12:21:21.053Z" }, + { url = "https://files.pythonhosted.org/packages/40/8d/2ddd6c9b30fcf920837b8672f6c65590c7d92e43084c25fc65edc22e93ca/numpy-2.3.1-cp313-cp313-win32.whl", hash = "sha256:39bff12c076812595c3a306f22bfe49919c5513aa1e0e70fac756a0be7c2a2b8", size = 6312330, upload-time = "2025-06-21T12:25:07.447Z" }, + { url = "https://files.pythonhosted.org/packages/dd/c8/beaba449925988d415efccb45bf977ff8327a02f655090627318f6398c7b/numpy-2.3.1-cp313-cp313-win_amd64.whl", hash = "sha256:8d5ee6eec45f08ce507a6570e06f2f879b374a552087a4179ea7838edbcbfa42", size = 12731565, upload-time = "2025-06-21T12:25:26.444Z" }, + { url = "https://files.pythonhosted.org/packages/0b/c3/5c0c575d7ec78c1126998071f58facfc124006635da75b090805e642c62e/numpy-2.3.1-cp313-cp313-win_arm64.whl", hash = "sha256:0c4d9e0a8368db90f93bd192bfa771ace63137c3488d198ee21dfb8e7771916e", size = 10190262, upload-time = "2025-06-21T12:25:42.196Z" }, + { url = "https://files.pythonhosted.org/packages/ea/19/a029cd335cf72f79d2644dcfc22d90f09caa86265cbbde3b5702ccef6890/numpy-2.3.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:b0b5397374f32ec0649dd98c652a1798192042e715df918c20672c62fb52d4b8", size = 20987593, upload-time = "2025-06-21T12:21:51.664Z" }, + { url = "https://files.pythonhosted.org/packages/25/91/8ea8894406209107d9ce19b66314194675d31761fe2cb3c84fe2eeae2f37/numpy-2.3.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:c5bdf2015ccfcee8253fb8be695516ac4457c743473a43290fd36eba6a1777eb", size = 14300523, upload-time = "2025-06-21T12:22:13.583Z" }, + { url = "https://files.pythonhosted.org/packages/a6/7f/06187b0066eefc9e7ce77d5f2ddb4e314a55220ad62dd0bfc9f2c44bac14/numpy-2.3.1-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:d70f20df7f08b90a2062c1f07737dd340adccf2068d0f1b9b3d56e2038979fee", size = 5227993, upload-time = "2025-06-21T12:22:22.53Z" }, + { url = "https://files.pythonhosted.org/packages/e8/ec/a926c293c605fa75e9cfb09f1e4840098ed46d2edaa6e2152ee35dc01ed3/numpy-2.3.1-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:2fb86b7e58f9ac50e1e9dd1290154107e47d1eef23a0ae9145ded06ea606f992", size = 6736652, upload-time = "2025-06-21T12:22:33.629Z" }, + { url = "https://files.pythonhosted.org/packages/e3/62/d68e52fb6fde5586650d4c0ce0b05ff3a48ad4df4ffd1b8866479d1d671d/numpy-2.3.1-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:23ab05b2d241f76cb883ce8b9a93a680752fbfcbd51c50eff0b88b979e471d8c", size = 14331561, upload-time = "2025-06-21T12:22:55.056Z" }, + { url = "https://files.pythonhosted.org/packages/fc/ec/b74d3f2430960044bdad6900d9f5edc2dc0fb8bf5a0be0f65287bf2cbe27/numpy-2.3.1-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:ce2ce9e5de4703a673e705183f64fd5da5bf36e7beddcb63a25ee2286e71ca48", size = 16693349, upload-time = "2025-06-21T12:23:20.53Z" }, + { url = "https://files.pythonhosted.org/packages/0d/15/def96774b9d7eb198ddadfcbd20281b20ebb510580419197e225f5c55c3e/numpy-2.3.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:c4913079974eeb5c16ccfd2b1f09354b8fed7e0d6f2cab933104a09a6419b1ee", size = 15642053, upload-time = "2025-06-21T12:23:43.697Z" }, + { url = "https://files.pythonhosted.org/packages/2b/57/c3203974762a759540c6ae71d0ea2341c1fa41d84e4971a8e76d7141678a/numpy-2.3.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:010ce9b4f00d5c036053ca684c77441f2f2c934fd23bee058b4d6f196efd8280", size = 18434184, upload-time = "2025-06-21T12:24:10.708Z" }, + { url = "https://files.pythonhosted.org/packages/22/8a/ccdf201457ed8ac6245187850aff4ca56a79edbea4829f4e9f14d46fa9a5/numpy-2.3.1-cp313-cp313t-win32.whl", hash = "sha256:6269b9edfe32912584ec496d91b00b6d34282ca1d07eb10e82dfc780907d6c2e", size = 6440678, upload-time = "2025-06-21T12:24:21.596Z" }, + { url = "https://files.pythonhosted.org/packages/f1/7e/7f431d8bd8eb7e03d79294aed238b1b0b174b3148570d03a8a8a8f6a0da9/numpy-2.3.1-cp313-cp313t-win_amd64.whl", hash = "sha256:2a809637460e88a113e186e87f228d74ae2852a2e0c44de275263376f17b5bdc", size = 12870697, upload-time = "2025-06-21T12:24:40.644Z" }, + { url = "https://files.pythonhosted.org/packages/d4/ca/af82bf0fad4c3e573c6930ed743b5308492ff19917c7caaf2f9b6f9e2e98/numpy-2.3.1-cp313-cp313t-win_arm64.whl", hash = "sha256:eccb9a159db9aed60800187bc47a6d3451553f0e1b08b068d8b277ddfbb9b244", size = 10260376, upload-time = "2025-06-21T12:24:56.884Z" }, + { url = "https://files.pythonhosted.org/packages/e8/34/facc13b9b42ddca30498fc51f7f73c3d0f2be179943a4b4da8686e259740/numpy-2.3.1-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:ad506d4b09e684394c42c966ec1527f6ebc25da7f4da4b1b056606ffe446b8a3", size = 21070637, upload-time = "2025-06-21T12:26:12.518Z" }, + { url = "https://files.pythonhosted.org/packages/65/b6/41b705d9dbae04649b529fc9bd3387664c3281c7cd78b404a4efe73dcc45/numpy-2.3.1-pp311-pypy311_pp73-macosx_14_0_arm64.whl", hash = "sha256:ebb8603d45bc86bbd5edb0d63e52c5fd9e7945d3a503b77e486bd88dde67a19b", size = 5304087, upload-time = "2025-06-21T12:26:22.294Z" }, + { url = "https://files.pythonhosted.org/packages/7a/b4/fe3ac1902bff7a4934a22d49e1c9d71a623204d654d4cc43c6e8fe337fcb/numpy-2.3.1-pp311-pypy311_pp73-macosx_14_0_x86_64.whl", hash = "sha256:15aa4c392ac396e2ad3d0a2680c0f0dee420f9fed14eef09bdb9450ee6dcb7b7", size = 6817588, upload-time = "2025-06-21T12:26:32.939Z" }, + { url = "https://files.pythonhosted.org/packages/ae/ee/89bedf69c36ace1ac8f59e97811c1f5031e179a37e4821c3a230bf750142/numpy-2.3.1-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:c6e0bf9d1a2f50d2b65a7cf56db37c095af17b59f6c132396f7c6d5dd76484df", size = 14399010, upload-time = "2025-06-21T12:26:54.086Z" }, + { url = "https://files.pythonhosted.org/packages/15/08/e00e7070ede29b2b176165eba18d6f9784d5349be3c0c1218338e79c27fd/numpy-2.3.1-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:eabd7e8740d494ce2b4ea0ff05afa1b7b291e978c0ae075487c51e8bd93c0c68", size = 16752042, upload-time = "2025-06-21T12:27:19.018Z" }, + { url = "https://files.pythonhosted.org/packages/48/6b/1c6b515a83d5564b1698a61efa245727c8feecf308f4091f565988519d20/numpy-2.3.1-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:e610832418a2bc09d974cc9fecebfa51e9532d6190223bc5ef6a7402ebf3b5cb", size = 12927246, upload-time = "2025-06-21T12:27:38.618Z" }, ] [[package]] @@ -1781,16 +1781,15 @@ wheels = [ [[package]] name = "pybtex" -version = "0.24.0" +version = "0.25.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "latexcodec" }, { name = "pyyaml" }, - { name = "six" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/46/9b/fd39836a6397fb363446d83075a7b9c2cc562f4c449292e039ed36084376/pybtex-0.24.0.tar.gz", hash = "sha256:818eae35b61733e5c007c3fcd2cfb75ed1bc8b4173c1f70b56cc4c0802d34755", size = 402879, upload-time = "2021-01-17T20:02:27.328Z" } +sdist = { url = "https://files.pythonhosted.org/packages/05/9b/1c5b913cb9121aac0a2f2990ee002b77efc70d969d5d5b179e19564389fe/pybtex-0.25.0.tar.gz", hash = "sha256:10684ffb05af33b041b06dabe15868078fd75847b24e1dffd8dd91348bbb3a4b", size = 358178, upload-time = "2025-06-21T12:03:27.236Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ad/5f/40d8e90f985a05133a8895fc454c6127ecec3de8b095dd35bba91382f803/pybtex-0.24.0-py2.py3-none-any.whl", hash = "sha256:e1e0c8c69998452fea90e9179aa2a98ab103f3eed894405b7264e517cc2fcc0f", size = 561354, upload-time = "2021-01-17T20:02:23.696Z" }, + { url = "https://files.pythonhosted.org/packages/b6/1d/9979b520b655657cea19523c1340c21f3cbbbe30c1dd03311833fbbad06d/pybtex-0.25.0-py2.py3-none-any.whl", hash = "sha256:bbc211abd458b42c5256d50185ea4f80000f43351959e1d5a3e86cd567a07a6d", size = 127434, upload-time = "2025-06-21T12:03:28.865Z" }, ] [[package]] @@ -1853,7 +1852,7 @@ wheels = [ [[package]] name = "pytest" -version = "8.4.0" +version = "8.4.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "colorama", marker = "sys_platform == 'win32'" }, @@ -1862,9 +1861,9 @@ dependencies = [ { name = "pluggy" }, { name = "pygments" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/fb/aa/405082ce2749be5398045152251ac69c0f3578c7077efc53431303af97ce/pytest-8.4.0.tar.gz", hash = "sha256:14d920b48472ea0dbf68e45b96cd1ffda4705f33307dcc86c676c1b5104838a6", size = 1515232, upload-time = "2025-06-02T17:36:30.03Z" } +sdist = { url = "https://files.pythonhosted.org/packages/08/ba/45911d754e8eba3d5a841a5ce61a65a685ff1798421ac054f85aa8747dfb/pytest-8.4.1.tar.gz", hash = "sha256:7c67fd69174877359ed9371ec3af8a3d2b04741818c51e5e99cc1742251fa93c", size = 1517714, upload-time = "2025-06-18T05:48:06.109Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/2f/de/afa024cbe022b1b318a3d224125aa24939e99b4ff6f22e0ba639a2eaee47/pytest-8.4.0-py3-none-any.whl", hash = "sha256:f40f825768ad76c0977cbacdf1fd37c6f7a468e460ea6a0636078f8972d4517e", size = 363797, upload-time = "2025-06-02T17:36:27.859Z" }, + { url = "https://files.pythonhosted.org/packages/29/16/c8a903f4c4dffe7a12843191437d7cd8e32751d5de349d45d3fe69544e87/pytest-8.4.1-py3-none-any.whl", hash = "sha256:539c70ba6fcead8e78eebbf1115e8b589e7565830d7d006a8723f19ac8a0afb7", size = 365474, upload-time = "2025-06-18T05:48:03.955Z" }, ] [[package]] @@ -2219,49 +2218,49 @@ wheels = [ [[package]] name = "scipy" -version = "1.15.3" +version = "1.16.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "numpy" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/0f/37/6964b830433e654ec7485e45a00fc9a27cf868d622838f6b6d9c5ec0d532/scipy-1.15.3.tar.gz", hash = "sha256:eae3cf522bc7df64b42cad3925c876e1b0b6c35c1337c93e12c0f366f55b0eaf", size = 59419214, upload-time = "2025-05-08T16:13:05.955Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/96/ab/5cc9f80f28f6a7dff646c5756e559823614a42b1939d86dd0ed550470210/scipy-1.15.3-cp311-cp311-macosx_10_13_x86_64.whl", hash = "sha256:993439ce220d25e3696d1b23b233dd010169b62f6456488567e830654ee37a6b", size = 38714255, upload-time = "2025-05-08T16:05:14.596Z" }, - { url = "https://files.pythonhosted.org/packages/4a/4a/66ba30abe5ad1a3ad15bfb0b59d22174012e8056ff448cb1644deccbfed2/scipy-1.15.3-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:34716e281f181a02341ddeaad584205bd2fd3c242063bd3423d61ac259ca7eba", size = 30111035, upload-time = "2025-05-08T16:05:20.152Z" }, - { url = "https://files.pythonhosted.org/packages/4b/fa/a7e5b95afd80d24313307f03624acc65801846fa75599034f8ceb9e2cbf6/scipy-1.15.3-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:3b0334816afb8b91dab859281b1b9786934392aa3d527cd847e41bb6f45bee65", size = 22384499, upload-time = "2025-05-08T16:05:24.494Z" }, - { url = "https://files.pythonhosted.org/packages/17/99/f3aaddccf3588bb4aea70ba35328c204cadd89517a1612ecfda5b2dd9d7a/scipy-1.15.3-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:6db907c7368e3092e24919b5e31c76998b0ce1684d51a90943cb0ed1b4ffd6c1", size = 25152602, upload-time = "2025-05-08T16:05:29.313Z" }, - { url = "https://files.pythonhosted.org/packages/56/c5/1032cdb565f146109212153339f9cb8b993701e9fe56b1c97699eee12586/scipy-1.15.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:721d6b4ef5dc82ca8968c25b111e307083d7ca9091bc38163fb89243e85e3889", size = 35503415, upload-time = "2025-05-08T16:05:34.699Z" }, - { url = "https://files.pythonhosted.org/packages/bd/37/89f19c8c05505d0601ed5650156e50eb881ae3918786c8fd7262b4ee66d3/scipy-1.15.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:39cb9c62e471b1bb3750066ecc3a3f3052b37751c7c3dfd0fd7e48900ed52982", size = 37652622, upload-time = "2025-05-08T16:05:40.762Z" }, - { url = "https://files.pythonhosted.org/packages/7e/31/be59513aa9695519b18e1851bb9e487de66f2d31f835201f1b42f5d4d475/scipy-1.15.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:795c46999bae845966368a3c013e0e00947932d68e235702b5c3f6ea799aa8c9", size = 37244796, upload-time = "2025-05-08T16:05:48.119Z" }, - { url = "https://files.pythonhosted.org/packages/10/c0/4f5f3eeccc235632aab79b27a74a9130c6c35df358129f7ac8b29f562ac7/scipy-1.15.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:18aaacb735ab38b38db42cb01f6b92a2d0d4b6aabefeb07f02849e47f8fb3594", size = 40047684, upload-time = "2025-05-08T16:05:54.22Z" }, - { url = "https://files.pythonhosted.org/packages/ab/a7/0ddaf514ce8a8714f6ed243a2b391b41dbb65251affe21ee3077ec45ea9a/scipy-1.15.3-cp311-cp311-win_amd64.whl", hash = "sha256:ae48a786a28412d744c62fd7816a4118ef97e5be0bee968ce8f0a2fba7acf3bb", size = 41246504, upload-time = "2025-05-08T16:06:00.437Z" }, - { url = "https://files.pythonhosted.org/packages/37/4b/683aa044c4162e10ed7a7ea30527f2cbd92e6999c10a8ed8edb253836e9c/scipy-1.15.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:6ac6310fdbfb7aa6612408bd2f07295bcbd3fda00d2d702178434751fe48e019", size = 38766735, upload-time = "2025-05-08T16:06:06.471Z" }, - { url = "https://files.pythonhosted.org/packages/7b/7e/f30be3d03de07f25dc0ec926d1681fed5c732d759ac8f51079708c79e680/scipy-1.15.3-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:185cd3d6d05ca4b44a8f1595af87f9c372bb6acf9c808e99aa3e9aa03bd98cf6", size = 30173284, upload-time = "2025-05-08T16:06:11.686Z" }, - { url = "https://files.pythonhosted.org/packages/07/9c/0ddb0d0abdabe0d181c1793db51f02cd59e4901da6f9f7848e1f96759f0d/scipy-1.15.3-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:05dc6abcd105e1a29f95eada46d4a3f251743cfd7d3ae8ddb4088047f24ea477", size = 22446958, upload-time = "2025-05-08T16:06:15.97Z" }, - { url = "https://files.pythonhosted.org/packages/af/43/0bce905a965f36c58ff80d8bea33f1f9351b05fad4beaad4eae34699b7a1/scipy-1.15.3-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:06efcba926324df1696931a57a176c80848ccd67ce6ad020c810736bfd58eb1c", size = 25242454, upload-time = "2025-05-08T16:06:20.394Z" }, - { url = "https://files.pythonhosted.org/packages/56/30/a6f08f84ee5b7b28b4c597aca4cbe545535c39fe911845a96414700b64ba/scipy-1.15.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c05045d8b9bfd807ee1b9f38761993297b10b245f012b11b13b91ba8945f7e45", size = 35210199, upload-time = "2025-05-08T16:06:26.159Z" }, - { url = "https://files.pythonhosted.org/packages/0b/1f/03f52c282437a168ee2c7c14a1a0d0781a9a4a8962d84ac05c06b4c5b555/scipy-1.15.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:271e3713e645149ea5ea3e97b57fdab61ce61333f97cfae392c28ba786f9bb49", size = 37309455, upload-time = "2025-05-08T16:06:32.778Z" }, - { url = "https://files.pythonhosted.org/packages/89/b1/fbb53137f42c4bf630b1ffdfc2151a62d1d1b903b249f030d2b1c0280af8/scipy-1.15.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6cfd56fc1a8e53f6e89ba3a7a7251f7396412d655bca2aa5611c8ec9a6784a1e", size = 36885140, upload-time = "2025-05-08T16:06:39.249Z" }, - { url = "https://files.pythonhosted.org/packages/2e/2e/025e39e339f5090df1ff266d021892694dbb7e63568edcfe43f892fa381d/scipy-1.15.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:0ff17c0bb1cb32952c09217d8d1eed9b53d1463e5f1dd6052c7857f83127d539", size = 39710549, upload-time = "2025-05-08T16:06:45.729Z" }, - { url = "https://files.pythonhosted.org/packages/e6/eb/3bf6ea8ab7f1503dca3a10df2e4b9c3f6b3316df07f6c0ded94b281c7101/scipy-1.15.3-cp312-cp312-win_amd64.whl", hash = "sha256:52092bc0472cfd17df49ff17e70624345efece4e1a12b23783a1ac59a1b728ed", size = 40966184, upload-time = "2025-05-08T16:06:52.623Z" }, - { url = "https://files.pythonhosted.org/packages/73/18/ec27848c9baae6e0d6573eda6e01a602e5649ee72c27c3a8aad673ebecfd/scipy-1.15.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:2c620736bcc334782e24d173c0fdbb7590a0a436d2fdf39310a8902505008759", size = 38728256, upload-time = "2025-05-08T16:06:58.696Z" }, - { url = "https://files.pythonhosted.org/packages/74/cd/1aef2184948728b4b6e21267d53b3339762c285a46a274ebb7863c9e4742/scipy-1.15.3-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:7e11270a000969409d37ed399585ee530b9ef6aa99d50c019de4cb01e8e54e62", size = 30109540, upload-time = "2025-05-08T16:07:04.209Z" }, - { url = "https://files.pythonhosted.org/packages/5b/d8/59e452c0a255ec352bd0a833537a3bc1bfb679944c4938ab375b0a6b3a3e/scipy-1.15.3-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:8c9ed3ba2c8a2ce098163a9bdb26f891746d02136995df25227a20e71c396ebb", size = 22383115, upload-time = "2025-05-08T16:07:08.998Z" }, - { url = "https://files.pythonhosted.org/packages/08/f5/456f56bbbfccf696263b47095291040655e3cbaf05d063bdc7c7517f32ac/scipy-1.15.3-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:0bdd905264c0c9cfa74a4772cdb2070171790381a5c4d312c973382fc6eaf730", size = 25163884, upload-time = "2025-05-08T16:07:14.091Z" }, - { url = "https://files.pythonhosted.org/packages/a2/66/a9618b6a435a0f0c0b8a6d0a2efb32d4ec5a85f023c2b79d39512040355b/scipy-1.15.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:79167bba085c31f38603e11a267d862957cbb3ce018d8b38f79ac043bc92d825", size = 35174018, upload-time = "2025-05-08T16:07:19.427Z" }, - { url = "https://files.pythonhosted.org/packages/b5/09/c5b6734a50ad4882432b6bb7c02baf757f5b2f256041da5df242e2d7e6b6/scipy-1.15.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c9deabd6d547aee2c9a81dee6cc96c6d7e9a9b1953f74850c179f91fdc729cb7", size = 37269716, upload-time = "2025-05-08T16:07:25.712Z" }, - { url = "https://files.pythonhosted.org/packages/77/0a/eac00ff741f23bcabd352731ed9b8995a0a60ef57f5fd788d611d43d69a1/scipy-1.15.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:dde4fc32993071ac0c7dd2d82569e544f0bdaff66269cb475e0f369adad13f11", size = 36872342, upload-time = "2025-05-08T16:07:31.468Z" }, - { url = "https://files.pythonhosted.org/packages/fe/54/4379be86dd74b6ad81551689107360d9a3e18f24d20767a2d5b9253a3f0a/scipy-1.15.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:f77f853d584e72e874d87357ad70f44b437331507d1c311457bed8ed2b956126", size = 39670869, upload-time = "2025-05-08T16:07:38.002Z" }, - { url = "https://files.pythonhosted.org/packages/87/2e/892ad2862ba54f084ffe8cc4a22667eaf9c2bcec6d2bff1d15713c6c0703/scipy-1.15.3-cp313-cp313-win_amd64.whl", hash = "sha256:b90ab29d0c37ec9bf55424c064312930ca5f4bde15ee8619ee44e69319aab163", size = 40988851, upload-time = "2025-05-08T16:08:33.671Z" }, - { url = "https://files.pythonhosted.org/packages/1b/e9/7a879c137f7e55b30d75d90ce3eb468197646bc7b443ac036ae3fe109055/scipy-1.15.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:3ac07623267feb3ae308487c260ac684b32ea35fd81e12845039952f558047b8", size = 38863011, upload-time = "2025-05-08T16:07:44.039Z" }, - { url = "https://files.pythonhosted.org/packages/51/d1/226a806bbd69f62ce5ef5f3ffadc35286e9fbc802f606a07eb83bf2359de/scipy-1.15.3-cp313-cp313t-macosx_12_0_arm64.whl", hash = "sha256:6487aa99c2a3d509a5227d9a5e889ff05830a06b2ce08ec30df6d79db5fcd5c5", size = 30266407, upload-time = "2025-05-08T16:07:49.891Z" }, - { url = "https://files.pythonhosted.org/packages/e5/9b/f32d1d6093ab9eeabbd839b0f7619c62e46cc4b7b6dbf05b6e615bbd4400/scipy-1.15.3-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:50f9e62461c95d933d5c5ef4a1f2ebf9a2b4e83b0db374cb3f1de104d935922e", size = 22540030, upload-time = "2025-05-08T16:07:54.121Z" }, - { url = "https://files.pythonhosted.org/packages/e7/29/c278f699b095c1a884f29fda126340fcc201461ee8bfea5c8bdb1c7c958b/scipy-1.15.3-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:14ed70039d182f411ffc74789a16df3835e05dc469b898233a245cdfd7f162cb", size = 25218709, upload-time = "2025-05-08T16:07:58.506Z" }, - { url = "https://files.pythonhosted.org/packages/24/18/9e5374b617aba742a990581373cd6b68a2945d65cc588482749ef2e64467/scipy-1.15.3-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a769105537aa07a69468a0eefcd121be52006db61cdd8cac8a0e68980bbb723", size = 34809045, upload-time = "2025-05-08T16:08:03.929Z" }, - { url = "https://files.pythonhosted.org/packages/e1/fe/9c4361e7ba2927074360856db6135ef4904d505e9b3afbbcb073c4008328/scipy-1.15.3-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9db984639887e3dffb3928d118145ffe40eff2fa40cb241a306ec57c219ebbbb", size = 36703062, upload-time = "2025-05-08T16:08:09.558Z" }, - { url = "https://files.pythonhosted.org/packages/b7/8e/038ccfe29d272b30086b25a4960f757f97122cb2ec42e62b460d02fe98e9/scipy-1.15.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:40e54d5c7e7ebf1aa596c374c49fa3135f04648a0caabcb66c52884b943f02b4", size = 36393132, upload-time = "2025-05-08T16:08:15.34Z" }, - { url = "https://files.pythonhosted.org/packages/10/7e/5c12285452970be5bdbe8352c619250b97ebf7917d7a9a9e96b8a8140f17/scipy-1.15.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:5e721fed53187e71d0ccf382b6bf977644c533e506c4d33c3fb24de89f5c3ed5", size = 38979503, upload-time = "2025-05-08T16:08:21.513Z" }, - { url = "https://files.pythonhosted.org/packages/81/06/0a5e5349474e1cbc5757975b21bd4fad0e72ebf138c5592f191646154e06/scipy-1.15.3-cp313-cp313t-win_amd64.whl", hash = "sha256:76ad1fb5f8752eabf0fa02e4cc0336b4e8f021e2d5f061ed37d6d264db35e3ca", size = 40308097, upload-time = "2025-05-08T16:08:27.627Z" }, +sdist = { url = "https://files.pythonhosted.org/packages/81/18/b06a83f0c5ee8cddbde5e3f3d0bb9b702abfa5136ef6d4620ff67df7eee5/scipy-1.16.0.tar.gz", hash = "sha256:b5ef54021e832869c8cfb03bc3bf20366cbcd426e02a58e8a58d7584dfbb8f62", size = 30581216, upload-time = "2025-06-22T16:27:55.782Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d9/f8/53fc4884df6b88afd5f5f00240bdc49fee2999c7eff3acf5953eb15bc6f8/scipy-1.16.0-cp311-cp311-macosx_10_14_x86_64.whl", hash = "sha256:deec06d831b8f6b5fb0b652433be6a09db29e996368ce5911faf673e78d20085", size = 36447362, upload-time = "2025-06-22T16:18:17.817Z" }, + { url = "https://files.pythonhosted.org/packages/c9/25/fad8aa228fa828705142a275fc593d701b1817c98361a2d6b526167d07bc/scipy-1.16.0-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:d30c0fe579bb901c61ab4bb7f3eeb7281f0d4c4a7b52dbf563c89da4fd2949be", size = 28547120, upload-time = "2025-06-22T16:18:24.117Z" }, + { url = "https://files.pythonhosted.org/packages/8d/be/d324ddf6b89fd1c32fecc307f04d095ce84abb52d2e88fab29d0cd8dc7a8/scipy-1.16.0-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:b2243561b45257f7391d0f49972fca90d46b79b8dbcb9b2cb0f9df928d370ad4", size = 20818922, upload-time = "2025-06-22T16:18:28.035Z" }, + { url = "https://files.pythonhosted.org/packages/cd/e0/cf3f39e399ac83fd0f3ba81ccc5438baba7cfe02176be0da55ff3396f126/scipy-1.16.0-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:e6d7dfc148135e9712d87c5f7e4f2ddc1304d1582cb3a7d698bbadedb61c7afd", size = 23409695, upload-time = "2025-06-22T16:18:32.497Z" }, + { url = "https://files.pythonhosted.org/packages/5b/61/d92714489c511d3ffd6830ac0eb7f74f243679119eed8b9048e56b9525a1/scipy-1.16.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:90452f6a9f3fe5a2cf3748e7be14f9cc7d9b124dce19667b54f5b429d680d539", size = 33444586, upload-time = "2025-06-22T16:18:37.992Z" }, + { url = "https://files.pythonhosted.org/packages/af/2c/40108915fd340c830aee332bb85a9160f99e90893e58008b659b9f3dddc0/scipy-1.16.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:a2f0bf2f58031c8701a8b601df41701d2a7be17c7ffac0a4816aeba89c4cdac8", size = 35284126, upload-time = "2025-06-22T16:18:43.605Z" }, + { url = "https://files.pythonhosted.org/packages/d3/30/e9eb0ad3d0858df35d6c703cba0a7e16a18a56a9e6b211d861fc6f261c5f/scipy-1.16.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:6c4abb4c11fc0b857474241b812ce69ffa6464b4bd8f4ecb786cf240367a36a7", size = 35608257, upload-time = "2025-06-22T16:18:49.09Z" }, + { url = "https://files.pythonhosted.org/packages/c8/ff/950ee3e0d612b375110d8cda211c1f787764b4c75e418a4b71f4a5b1e07f/scipy-1.16.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b370f8f6ac6ef99815b0d5c9f02e7ade77b33007d74802efc8316c8db98fd11e", size = 38040541, upload-time = "2025-06-22T16:18:55.077Z" }, + { url = "https://files.pythonhosted.org/packages/8b/c9/750d34788288d64ffbc94fdb4562f40f609d3f5ef27ab4f3a4ad00c9033e/scipy-1.16.0-cp311-cp311-win_amd64.whl", hash = "sha256:a16ba90847249bedce8aa404a83fb8334b825ec4a8e742ce6012a7a5e639f95c", size = 38570814, upload-time = "2025-06-22T16:19:00.912Z" }, + { url = "https://files.pythonhosted.org/packages/01/c0/c943bc8d2bbd28123ad0f4f1eef62525fa1723e84d136b32965dcb6bad3a/scipy-1.16.0-cp312-cp312-macosx_10_14_x86_64.whl", hash = "sha256:7eb6bd33cef4afb9fa5f1fb25df8feeb1e52d94f21a44f1d17805b41b1da3180", size = 36459071, upload-time = "2025-06-22T16:19:06.605Z" }, + { url = "https://files.pythonhosted.org/packages/99/0d/270e2e9f1a4db6ffbf84c9a0b648499842046e4e0d9b2275d150711b3aba/scipy-1.16.0-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:1dbc8fdba23e4d80394ddfab7a56808e3e6489176d559c6c71935b11a2d59db1", size = 28490500, upload-time = "2025-06-22T16:19:11.775Z" }, + { url = "https://files.pythonhosted.org/packages/1c/22/01d7ddb07cff937d4326198ec8d10831367a708c3da72dfd9b7ceaf13028/scipy-1.16.0-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:7dcf42c380e1e3737b343dec21095c9a9ad3f9cbe06f9c05830b44b1786c9e90", size = 20762345, upload-time = "2025-06-22T16:19:15.813Z" }, + { url = "https://files.pythonhosted.org/packages/34/7f/87fd69856569ccdd2a5873fe5d7b5bbf2ad9289d7311d6a3605ebde3a94b/scipy-1.16.0-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:26ec28675f4a9d41587266084c626b02899db373717d9312fa96ab17ca1ae94d", size = 23418563, upload-time = "2025-06-22T16:19:20.746Z" }, + { url = "https://files.pythonhosted.org/packages/f6/f1/e4f4324fef7f54160ab749efbab6a4bf43678a9eb2e9817ed71a0a2fd8de/scipy-1.16.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:952358b7e58bd3197cfbd2f2f2ba829f258404bdf5db59514b515a8fe7a36c52", size = 33203951, upload-time = "2025-06-22T16:19:25.813Z" }, + { url = "https://files.pythonhosted.org/packages/6d/f0/b6ac354a956384fd8abee2debbb624648125b298f2c4a7b4f0d6248048a5/scipy-1.16.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:03931b4e870c6fef5b5c0970d52c9f6ddd8c8d3e934a98f09308377eba6f3824", size = 35070225, upload-time = "2025-06-22T16:19:31.416Z" }, + { url = "https://files.pythonhosted.org/packages/e5/73/5cbe4a3fd4bc3e2d67ffad02c88b83edc88f381b73ab982f48f3df1a7790/scipy-1.16.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:512c4f4f85912767c351a0306824ccca6fd91307a9f4318efe8fdbd9d30562ef", size = 35389070, upload-time = "2025-06-22T16:19:37.387Z" }, + { url = "https://files.pythonhosted.org/packages/86/e8/a60da80ab9ed68b31ea5a9c6dfd3c2f199347429f229bf7f939a90d96383/scipy-1.16.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e69f798847e9add03d512eaf5081a9a5c9a98757d12e52e6186ed9681247a1ac", size = 37825287, upload-time = "2025-06-22T16:19:43.375Z" }, + { url = "https://files.pythonhosted.org/packages/ea/b5/29fece1a74c6a94247f8a6fb93f5b28b533338e9c34fdcc9cfe7a939a767/scipy-1.16.0-cp312-cp312-win_amd64.whl", hash = "sha256:adf9b1999323ba335adc5d1dc7add4781cb5a4b0ef1e98b79768c05c796c4e49", size = 38431929, upload-time = "2025-06-22T16:19:49.385Z" }, + { url = "https://files.pythonhosted.org/packages/46/95/0746417bc24be0c2a7b7563946d61f670a3b491b76adede420e9d173841f/scipy-1.16.0-cp313-cp313-macosx_10_14_x86_64.whl", hash = "sha256:e9f414cbe9ca289a73e0cc92e33a6a791469b6619c240aa32ee18abdce8ab451", size = 36418162, upload-time = "2025-06-22T16:19:56.3Z" }, + { url = "https://files.pythonhosted.org/packages/19/5a/914355a74481b8e4bbccf67259bbde171348a3f160b67b4945fbc5f5c1e5/scipy-1.16.0-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:bbba55fb97ba3cdef9b1ee973f06b09d518c0c7c66a009c729c7d1592be1935e", size = 28465985, upload-time = "2025-06-22T16:20:01.238Z" }, + { url = "https://files.pythonhosted.org/packages/58/46/63477fc1246063855969cbefdcee8c648ba4b17f67370bd542ba56368d0b/scipy-1.16.0-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:58e0d4354eacb6004e7aa1cd350e5514bd0270acaa8d5b36c0627bb3bb486974", size = 20737961, upload-time = "2025-06-22T16:20:05.913Z" }, + { url = "https://files.pythonhosted.org/packages/93/86/0fbb5588b73555e40f9d3d6dde24ee6fac7d8e301a27f6f0cab9d8f66ff2/scipy-1.16.0-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:75b2094ec975c80efc273567436e16bb794660509c12c6a31eb5c195cbf4b6dc", size = 23377941, upload-time = "2025-06-22T16:20:10.668Z" }, + { url = "https://files.pythonhosted.org/packages/ca/80/a561f2bf4c2da89fa631b3cbf31d120e21ea95db71fd9ec00cb0247c7a93/scipy-1.16.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:6b65d232157a380fdd11a560e7e21cde34fdb69d65c09cb87f6cc024ee376351", size = 33196703, upload-time = "2025-06-22T16:20:16.097Z" }, + { url = "https://files.pythonhosted.org/packages/11/6b/3443abcd0707d52e48eb315e33cc669a95e29fc102229919646f5a501171/scipy-1.16.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:1d8747f7736accd39289943f7fe53a8333be7f15a82eea08e4afe47d79568c32", size = 35083410, upload-time = "2025-06-22T16:20:21.734Z" }, + { url = "https://files.pythonhosted.org/packages/20/ab/eb0fc00e1e48961f1bd69b7ad7e7266896fe5bad4ead91b5fc6b3561bba4/scipy-1.16.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:eb9f147a1b8529bb7fec2a85cf4cf42bdfadf9e83535c309a11fdae598c88e8b", size = 35387829, upload-time = "2025-06-22T16:20:27.548Z" }, + { url = "https://files.pythonhosted.org/packages/57/9e/d6fc64e41fad5d481c029ee5a49eefc17f0b8071d636a02ceee44d4a0de2/scipy-1.16.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:d2b83c37edbfa837a8923d19c749c1935ad3d41cf196006a24ed44dba2ec4358", size = 37841356, upload-time = "2025-06-22T16:20:35.112Z" }, + { url = "https://files.pythonhosted.org/packages/7c/a7/4c94bbe91f12126b8bf6709b2471900577b7373a4fd1f431f28ba6f81115/scipy-1.16.0-cp313-cp313-win_amd64.whl", hash = "sha256:79a3c13d43c95aa80b87328a46031cf52508cf5f4df2767602c984ed1d3c6bbe", size = 38403710, upload-time = "2025-06-22T16:21:54.473Z" }, + { url = "https://files.pythonhosted.org/packages/47/20/965da8497f6226e8fa90ad3447b82ed0e28d942532e92dd8b91b43f100d4/scipy-1.16.0-cp313-cp313t-macosx_10_14_x86_64.whl", hash = "sha256:f91b87e1689f0370690e8470916fe1b2308e5b2061317ff76977c8f836452a47", size = 36813833, upload-time = "2025-06-22T16:20:43.925Z" }, + { url = "https://files.pythonhosted.org/packages/28/f4/197580c3dac2d234e948806e164601c2df6f0078ed9f5ad4a62685b7c331/scipy-1.16.0-cp313-cp313t-macosx_12_0_arm64.whl", hash = "sha256:88a6ca658fb94640079e7a50b2ad3b67e33ef0f40e70bdb7dc22017dae73ac08", size = 28974431, upload-time = "2025-06-22T16:20:51.302Z" }, + { url = "https://files.pythonhosted.org/packages/8a/fc/e18b8550048d9224426e76906694c60028dbdb65d28b1372b5503914b89d/scipy-1.16.0-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:ae902626972f1bd7e4e86f58fd72322d7f4ec7b0cfc17b15d4b7006efc385176", size = 21246454, upload-time = "2025-06-22T16:20:57.276Z" }, + { url = "https://files.pythonhosted.org/packages/8c/48/07b97d167e0d6a324bfd7484cd0c209cc27338b67e5deadae578cf48e809/scipy-1.16.0-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:8cb824c1fc75ef29893bc32b3ddd7b11cf9ab13c1127fe26413a05953b8c32ed", size = 23772979, upload-time = "2025-06-22T16:21:03.363Z" }, + { url = "https://files.pythonhosted.org/packages/4c/4f/9efbd3f70baf9582edf271db3002b7882c875ddd37dc97f0f675ad68679f/scipy-1.16.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:de2db7250ff6514366a9709c2cba35cb6d08498e961cba20d7cff98a7ee88938", size = 33341972, upload-time = "2025-06-22T16:21:11.14Z" }, + { url = "https://files.pythonhosted.org/packages/3f/dc/9e496a3c5dbe24e76ee24525155ab7f659c20180bab058ef2c5fa7d9119c/scipy-1.16.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:e85800274edf4db8dd2e4e93034f92d1b05c9421220e7ded9988b16976f849c1", size = 35185476, upload-time = "2025-06-22T16:21:19.156Z" }, + { url = "https://files.pythonhosted.org/packages/ce/b3/21001cff985a122ba434c33f2c9d7d1dc3b669827e94f4fc4e1fe8b9dfd8/scipy-1.16.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:4f720300a3024c237ace1cb11f9a84c38beb19616ba7c4cdcd771047a10a1706", size = 35570990, upload-time = "2025-06-22T16:21:27.797Z" }, + { url = "https://files.pythonhosted.org/packages/e5/d3/7ba42647d6709251cdf97043d0c107e0317e152fa2f76873b656b509ff55/scipy-1.16.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:aad603e9339ddb676409b104c48a027e9916ce0d2838830691f39552b38a352e", size = 37950262, upload-time = "2025-06-22T16:21:36.976Z" }, + { url = "https://files.pythonhosted.org/packages/eb/c4/231cac7a8385394ebbbb4f1ca662203e9d8c332825ab4f36ffc3ead09a42/scipy-1.16.0-cp313-cp313t-win_amd64.whl", hash = "sha256:f56296fefca67ba605fd74d12f7bd23636267731a72cb3947963e76b8c0a25db", size = 38515076, upload-time = "2025-06-22T16:21:45.694Z" }, ] [[package]] @@ -2506,18 +2505,18 @@ wheels = [ [[package]] name = "sphinxcontrib-bibtex" -version = "2.6.3" +version = "2.6.4" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "docutils" }, { name = "pybtex" }, { name = "pybtex-docutils" }, - { name = "setuptools", marker = "python_full_version >= '3.12'" }, + { name = "setuptools" }, { name = "sphinx" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/c1/ce/054a8ec04063f9a27772fea7188f796edbfa382e656d3b76428323861f0e/sphinxcontrib_bibtex-2.6.3.tar.gz", hash = "sha256:7c790347ef1cb0edf30de55fc324d9782d085e89c52c2b8faafa082e08e23946", size = 117177, upload-time = "2024-09-12T14:23:44.662Z" } +sdist = { url = "https://files.pythonhosted.org/packages/96/10/237737925e667e79b18ccd81f4a768306b80847fa24b86786f042484b439/sphinxcontrib_bibtex-2.6.4.tar.gz", hash = "sha256:aad018b730d324201f09777f6c25c4a2ff7ac1d5e66af187f21fc21840768760", size = 118453, upload-time = "2025-06-17T06:41:51.22Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/8e/49/c23f9493c0a5d5881fb7ed3002e87708454fef860aa96a48e755d27bf6f0/sphinxcontrib_bibtex-2.6.3-py3-none-any.whl", hash = "sha256:ff016b738fcc867df0f75c29e139b3b2158d26a2c802db27963cb128be3b75fb", size = 40340, upload-time = "2024-09-12T14:23:43.593Z" }, + { url = "https://files.pythonhosted.org/packages/c5/29/9d6fbbd52d7dc6c3cc958187a05cb5d2bf891ee65ac7e8e690b9159103b4/sphinxcontrib_bibtex-2.6.4-py3-none-any.whl", hash = "sha256:bfd34d36322ba0ef0624a1bbee44adcedde86e0fa0ce5b2310304a3e68263f6f", size = 40422, upload-time = "2025-06-17T06:41:49.943Z" }, ] [[package]] @@ -2798,11 +2797,11 @@ wheels = [ [[package]] name = "urllib3" -version = "2.4.0" +version = "2.5.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/8a/78/16493d9c386d8e60e442a35feac5e00f0913c0f4b7c217c11e8ec2ff53e0/urllib3-2.4.0.tar.gz", hash = "sha256:414bc6535b787febd7567804cc015fee39daab8ad86268f1310a9250697de466", size = 390672, upload-time = "2025-04-10T15:23:39.232Z" } +sdist = { url = "https://files.pythonhosted.org/packages/15/22/9ee70a2574a4f4599c47dd506532914ce044817c7752a79b6a51286319bc/urllib3-2.5.0.tar.gz", hash = "sha256:3fc47733c7e419d4bc3f6b3dc2b4f890bb743906a30d56ba4a5bfa4bbff92760", size = 393185, upload-time = "2025-06-18T14:07:41.644Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/6b/11/cc635220681e93a0183390e26485430ca2c7b5f9d33b15c74c2861cb8091/urllib3-2.4.0-py3-none-any.whl", hash = "sha256:4e16665048960a0900c702d4a66415956a584919c03361cac9f1df5c5dd7e813", size = 128680, upload-time = "2025-04-10T15:23:37.377Z" }, + { url = "https://files.pythonhosted.org/packages/a7/c2/fe1e52489ae3122415c51f387e221dd0773709bad6c6cdaa599e8a2c5185/urllib3-2.5.0-py3-none-any.whl", hash = "sha256:e6b01673c0fa6a13e374b50871808eb3bf7046c4b125b216f6bf1cc604cff0dc", size = 129795, upload-time = "2025-06-18T14:07:40.39Z" }, ] [[package]] From a2382aa227025d78b347162d7c13cbbd01ed8630 Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 23 Jun 2025 12:25:59 -0700 Subject: [PATCH 318/521] avoid possible infinite loop when voltage_step_size = 0 --- .../analysis/swept_langmuir/helpers.py | 27 ++++++++++++++----- 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/src/plasmapy/analysis/swept_langmuir/helpers.py b/src/plasmapy/analysis/swept_langmuir/helpers.py index b622404d14..e641f0808b 100644 --- a/src/plasmapy/analysis/swept_langmuir/helpers.py +++ b/src/plasmapy/analysis/swept_langmuir/helpers.py @@ -571,14 +571,29 @@ def merge_voltage_clusters( # noqa: C901, PLR0912 new_current = current.copy() elif voltage_step_size == 0: - new_voltage, new_current = _merge_voltage_clusters__zero_diff_neighbors(voltage, current) + new_voltage, new_current = _merge_voltage_clusters__zero_diff_neighbors( + voltage, current + ) if force_regular_spacing: - new_voltage, new_current = merge_voltage_clusters( - voltage=new_voltage, - current=new_current, - voltage_step_size=voltage_step_size, - ) + voltage_diff = np.diff(new_voltage) + mask_zero_diff = np.isclose(voltage_diff, 0.0) + is_regular_grid = _is_voltage_regularly_spaced(voltage_diff, mask_zero_diff) + + if is_regular_grid: + new_voltage, new_current = _force_regular_spacing( + voltage=new_voltage, + current=new_current, + voltage_step_size=np.min(voltage_diff), + ) + else: + warnings.warn( + "Can not enforce regular spacing for the voltage array " + "if argument 'voltage_step_size' is set to 0 and the " + "voltage array is NOT already regularly spaced. " + "Returning voltage and current arrays WITHOUT enforce " + "regular spacing.", + ) else: new_voltage, new_current = _merge_voltage_clusters__within_dv( From 31d696994216bf7c95f59a83878ddb2b0d0977cd Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 23 Jun 2025 12:49:40 -0700 Subject: [PATCH 319/521] expand merge_voltage_clusters docstring --- .../analysis/swept_langmuir/helpers.py | 42 ++++++++++++++----- 1 file changed, 32 insertions(+), 10 deletions(-) diff --git a/src/plasmapy/analysis/swept_langmuir/helpers.py b/src/plasmapy/analysis/swept_langmuir/helpers.py index e641f0808b..9f44ff71da 100644 --- a/src/plasmapy/analysis/swept_langmuir/helpers.py +++ b/src/plasmapy/analysis/swept_langmuir/helpers.py @@ -449,8 +449,8 @@ def merge_voltage_clusters( # noqa: C901, PLR0912 ) -> tuple[np.ndarray, np.ndarray]: """ Search the ``voltage`` array for closely spaced voltage clusters - based on the ``voltage_step_size`` parameter and merge cluster, and - associated ``current`` values, into a single point. + based on the ``voltage_step_size`` parameter and merge those + clusters, and associated ``current`` values, into a single point. Parameters ---------- @@ -488,14 +488,36 @@ def merge_voltage_clusters( # noqa: C901, PLR0912 Notes ----- - ``voltage_step_size = 0`` : - blah - - ``voltage_step_size > 0`` or `None` - blah - - ``force_regular_spacing = True`` - blah + - ``voltage_step_size = 0`` + - Only merge clusters that have the same voltage values. + - ``force_regular_spacing = True`` is ignored if the spacing is + not already regularly spaced. If the voltage is already + regularly spaced, then the current array will be `numpy.nan` + stuffed for missing voltage entries. + + - ``voltage_step_size is None`` + - If the ``voltage`` array is already regularly spaced, then a + copy of the original arrays will be returned. + - If the ``voltage`` array is NOT regularly spaced, then the + step size will be the average voltage step of the ``voltage`` + array. + + - ``voltage_step_size > 0`` or `None` + - If the ``voltage`` array is already regularly spaced, then + `numpy.interp` will be used interpolate the ``voltage`` and + ``current`` arrays onto the new grid spacing + ``voltage_step_size``. + - If ``force_regular_spacing = False``, then, starting at the + lowest voltage, clusters within ``voltage_step_size`` will be + merged together with the new voltage value being the average of + the points in the cluster and the new current value being the + average of the points in the cluster. + - If ``force_regular_spacing = True``, then, starting at the + lowest voltage, clusters within ``voltage_step_size`` will be + merged together with the new current value being the average of + the points in the cluster and the new voltage value being + ``voltage_min + 0.5 * N * voltage_step_size``, where ``N`` is + the Nth point in the voltage array. """ # condition force_regular_grid if not isinstance(force_regular_spacing, bool): From e4a6c78964ad4d141218710084408106ab4cb5e8 Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 23 Jun 2025 15:27:34 -0700 Subject: [PATCH 320/521] start test_merge_voltage_clusters() --- .../test_helpers__merge_voltage_clusters.py | 110 ++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 tests/analysis/swept_langmuir/test_helpers__merge_voltage_clusters.py diff --git a/tests/analysis/swept_langmuir/test_helpers__merge_voltage_clusters.py b/tests/analysis/swept_langmuir/test_helpers__merge_voltage_clusters.py new file mode 100644 index 0000000000..c9de34b354 --- /dev/null +++ b/tests/analysis/swept_langmuir/test_helpers__merge_voltage_clusters.py @@ -0,0 +1,110 @@ +""" +Tests for helper function `merge_voltage_clusters` contained in +`plasmapy.analysis.swept_langmuir.helpers`. +""" + +from contextlib import nullcontext as does_not_raise +from unittest import mock + +import astropy.units as u +import numpy as np +import pytest + +from plasmapy.analysis.swept_langmuir.helpers import check_sweep, merge_voltage_clusters + + +@pytest.mark.parametrize( + ("voltage", "current", "kwargs", "with_context", "expected"), + [ + # raises + ( + np.linspace(-40.0, 40, 100), + np.linspace(-10.0, 30, 100), + {"force_regular_spacing": None}, # not a bool + pytest.raises(TypeError), + None, + ), + ( + np.linspace(-40.0, 40, 100), + np.linspace(-10.0, 30, 100), + {"voltage_step_size": "wrong type"}, + pytest.raises(TypeError), + None, + ), + # values + # ( + # np.linspace(-40.0, 40, 100), + # np.linspace(-10.0, 30, 100), + # {"voltage_order": "ascending"}, + # does_not_raise(), + # None, + # ), + # ( + # np.linspace(-40.0, 40, 100), + # np.linspace(-10.0, 30, 100), + # {"voltage_order": "descending"}, + # does_not_raise(), + # (np.linspace(40.0, -40, 100), np.linspace(30.0, -10, 100)), + # ), + # ( + # np.linspace(40.0, -40, 100), + # np.linspace(-10.0, 30, 100), + # {"voltage_order": "descending"}, + # does_not_raise(), + # None, + # ), + # ( + # np.linspace(40.0, -40, 100), + # np.linspace(-10.0, 30, 100), + # {"voltage_order": "ascending"}, + # does_not_raise(), + # (np.linspace(-40.0, 40, 100), np.linspace(30.0, -10, 100)), + # ), + # ( + # np.array([-40.0, 20.0, -22.0, 40.0]), + # np.array([-10.0, 10.0, -5.0, 30.0]), + # {"voltage_order": "ascending"}, + # does_not_raise(), + # (np.array([-40.0, -22.0, 20.0, 40.0]), np.array([-10.0, -5.0, 10.0, 30.0])), + # ), + # ( + # np.array([-40.0, 20.0, -22.0, 40.0]), + # np.array([-10.0, 10.0, -5.0, 30.0]), + # {"voltage_order": "descending"}, + # does_not_raise(), + # (np.array([40.0, 20.0, -22.0, -40.0]), np.array([30.0, 10.0, -5.0, -10.0])), + # ), + ], +) +def test_merge_voltage_clusters( + voltage, current, kwargs, with_context, expected +) -> None: + with ( + with_context, + mock.patch( + "plasmapy.analysis.swept_langmuir.helpers.merge_voltage_clusters", + wraps=merge_voltage_clusters, + ) as mock_merge, + mock.patch( + "plasmapy.analysis.swept_langmuir.helpers.check_sweep", + wraps=check_sweep, + ) as mock_sweep, + ): + rtn_voltage, rtn_current = merge_voltage_clusters( + voltage=voltage, + current=current, + **kwargs, + ) + + if expected is not None: + assert np.allclose(rtn_voltage, expected[0]) + assert np.allclose(rtn_current, expected[1]) + else: + assert np.allclose(rtn_voltage, voltage) + assert np.allclose(rtn_current, current) + + # mock_merge.assert_called_once() + # mock_merge.reset_mock() + + mock_sweep.assert_called_once() + mock_sweep.reset_mock() From a0c545d1baf589b1888ac510220eec329e7a8f38 Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 23 Jun 2025 18:25:31 -0700 Subject: [PATCH 321/521] add cases to the tests --- .../test_helpers__merge_voltage_clusters.py | 76 ++++++++----------- 1 file changed, 33 insertions(+), 43 deletions(-) diff --git a/tests/analysis/swept_langmuir/test_helpers__merge_voltage_clusters.py b/tests/analysis/swept_langmuir/test_helpers__merge_voltage_clusters.py index c9de34b354..2cfd7b33c5 100644 --- a/tests/analysis/swept_langmuir/test_helpers__merge_voltage_clusters.py +++ b/tests/analysis/swept_langmuir/test_helpers__merge_voltage_clusters.py @@ -11,6 +11,7 @@ import pytest from plasmapy.analysis.swept_langmuir.helpers import check_sweep, merge_voltage_clusters +from plasmapy.utils.exceptions import PlasmaPyWarning @pytest.mark.parametrize( @@ -32,48 +33,30 @@ None, ), # values - # ( - # np.linspace(-40.0, 40, 100), - # np.linspace(-10.0, 30, 100), - # {"voltage_order": "ascending"}, - # does_not_raise(), - # None, - # ), - # ( - # np.linspace(-40.0, 40, 100), - # np.linspace(-10.0, 30, 100), - # {"voltage_order": "descending"}, - # does_not_raise(), - # (np.linspace(40.0, -40, 100), np.linspace(30.0, -10, 100)), - # ), - # ( - # np.linspace(40.0, -40, 100), - # np.linspace(-10.0, 30, 100), - # {"voltage_order": "descending"}, - # does_not_raise(), - # None, - # ), - # ( - # np.linspace(40.0, -40, 100), - # np.linspace(-10.0, 30, 100), - # {"voltage_order": "ascending"}, - # does_not_raise(), - # (np.linspace(-40.0, 40, 100), np.linspace(30.0, -10, 100)), - # ), - # ( - # np.array([-40.0, 20.0, -22.0, 40.0]), - # np.array([-10.0, 10.0, -5.0, 30.0]), - # {"voltage_order": "ascending"}, - # does_not_raise(), - # (np.array([-40.0, -22.0, 20.0, 40.0]), np.array([-10.0, -5.0, 10.0, 30.0])), - # ), - # ( - # np.array([-40.0, 20.0, -22.0, 40.0]), - # np.array([-10.0, 10.0, -5.0, 30.0]), - # {"voltage_order": "descending"}, - # does_not_raise(), - # (np.array([40.0, 20.0, -22.0, -40.0]), np.array([30.0, 10.0, -5.0, -10.0])), - # ), + ( + np.linspace(-40.0, 40, 100), + np.linspace(-10.0, 30, 100), + {"voltage_step_size": None}, + pytest.warns(PlasmaPyWarning), + None, # same as inputs + ), + ( + np.linspace(-40.0, 40, 100), + np.linspace(-10.0, 30, 100), + {"voltage_step_size": 0.0}, + does_not_raise(), + None, # same as inputs + ), + ( + np.array([1, 2, 4, 6], dtype=float), + np.array([-5, -2, 0, 5], dtype=float), + {"voltage_step_size": 0.0, "force_regular_spacing": True}, + does_not_raise(), + ( + np.array([1, 2, 3, 4, 5, 6], dtype=float), + np.array([-5, -2, np.nan, 0, np.nan, 5], dtype=float), + ), # same as inputs + ), ], ) def test_merge_voltage_clusters( @@ -98,7 +81,14 @@ def test_merge_voltage_clusters( if expected is not None: assert np.allclose(rtn_voltage, expected[0]) - assert np.allclose(rtn_current, expected[1]) + + rtn_nan_mask = np.isnan(rtn_current) + expected_nan_mask = np.isnan(expected[1]) + assert np.array_equal(rtn_nan_mask, expected_nan_mask) + assert np.allclose( + rtn_current[np.logical_not(rtn_nan_mask)], + expected[1][np.logical_not(expected_nan_mask)], + ) else: assert np.allclose(rtn_voltage, voltage) assert np.allclose(rtn_current, current) From 16fbee2d1a6096214aa5f5795d61d96df2e5ad47 Mon Sep 17 00:00:00 2001 From: Nick Murphy Date: Tue, 24 Jun 2025 14:32:24 -0400 Subject: [PATCH 322/521] Update time to update lockfiles (#3041) --- .github/workflows/update-pinned-reqs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/update-pinned-reqs.yml b/.github/workflows/update-pinned-reqs.yml index 29702ae6be..bf142406c4 100644 --- a/.github/workflows/update-pinned-reqs.yml +++ b/.github/workflows/update-pinned-reqs.yml @@ -2,7 +2,7 @@ name: Update pinned requirements on: schedule: - - cron: 0 12 * * 1 + - cron: 37 11 * * 5 workflow_dispatch: jobs: From c87c163dbac137e437386fe9124223df713ac88b Mon Sep 17 00:00:00 2001 From: Nick Murphy Date: Tue, 24 Jun 2025 14:44:02 -0400 Subject: [PATCH 323/521] Remove `sphinx-hoverxref` as an extension to the documentation build (#3024) * Remove sphinx-hoverxref from docs requirements * Remove sphinx-hoverxref from docs/conf.py * Remove sphinx-hoverxref discussion in doc guide * Unlink to sphinx-hoverxref in old changelog * Edit changelog: .doc.rst * Rename changelog file to include PR number * Put back links to sphinx-hoverxref Co-authored-by: Erik Everson * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Underscore * Add spaces --------- Co-authored-by: Erik Everson Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- changelog/3024.doc.rst | 1 + docs/changelog/0.8.1.rst | 3 +-- docs/conf.py | 40 --------------------------------- docs/contributing/doc_guide.rst | 5 ----- pyproject.toml | 1 - uv.lock | 31 +++---------------------- 6 files changed, 5 insertions(+), 76 deletions(-) create mode 100644 changelog/3024.doc.rst diff --git a/changelog/3024.doc.rst b/changelog/3024.doc.rst new file mode 100644 index 0000000000..189678920b --- /dev/null +++ b/changelog/3024.doc.rst @@ -0,0 +1 @@ +Removed the `sphinx-hoverxref `_ |Sphinx| extension, since it has been deprecated in favor of the Read the Docs addon `Link Previews `_\ . diff --git a/docs/changelog/0.8.1.rst b/docs/changelog/0.8.1.rst index 524d0e85e0..36ac4f062d 100644 --- a/docs/changelog/0.8.1.rst +++ b/docs/changelog/0.8.1.rst @@ -371,8 +371,7 @@ Improved Documentation :file:`README.md`. (`#1327 `__) - Enabled the `sphinx-hoverxref - `_ extension to - |Sphinx|. (`#1353 + `__ extension to |Sphinx|. (`#1353 `__) - Added bullet points on module level docstrings and ``__all__`` to the documentation guide. (`#1359 diff --git a/docs/conf.py b/docs/conf.py index e43a570a92..3ce914c994 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -85,7 +85,6 @@ "plasmapy_sphinx.ext.autodoc", "plasmapy_sphinx.ext.directives", # other 3rd party extensions - "hoverxref.extension", "IPython.sphinxext.ipython_console_highlighting", "nbsphinx", "notfound.extension", @@ -270,45 +269,6 @@ ), } -# hoverxref - -hoverxref_intersphinx = list(intersphinx_mapping.keys()) - -hoverxref_auto_ref = True -hoverxref_domains = ["py", "cite"] -hoverxref_mathjax = True -hoverxref_roles = ["confval", "term"] -hoverxref_sphinxtabs = True -hoverxref_tooltip_maxwidth = 600 # RTD main window is 696px - -hoverxref_role_types = { - # roles with cite domain - "p": "tooltip", - "t": "tooltip", - # roles with py domain - "attr": "tooltip", - "class": "tooltip", - "const": "tooltip", - "data": "tooltip", - "exc": "tooltip", - "func": "tooltip", - "meth": "tooltip", - "mod": "tooltip", - "obj": "tooltip", - # roles with std domain - "confval": "tooltip", - "hoverxref": "tooltip", - "ref": "tooltip", - "term": "tooltip", -} - -if building_on_readthedocs := os.environ.get("READTHEDOCS"): - # Using the proxied API endpoint is a Read the Docs strategy to - # avoid a cross-site request forgery block for docs using a custom - # domain. See conf.py for sphinx-hoverxref. - use_proxied_api_endpoint = os.environ.get("PROXIED_API_ENDPOINT") - hoverxref_api_host = "/_" if use_proxied_api_endpoint else "https://readthedocs.org" - # sphinx-issues issues_github_path = "PlasmaPy/PlasmaPy" diff --git a/docs/contributing/doc_guide.rst b/docs/contributing/doc_guide.rst index a134016dd3..a17d6c17b7 100644 --- a/docs/contributing/doc_guide.rst +++ b/docs/contributing/doc_guide.rst @@ -1066,8 +1066,6 @@ extensions: * |IPython.sphinxext.ipython_console_highlighting|_. * |sphinx_changelog|_ for rendering |towncrier| changelogs. * |sphinx-tabs|_ for creating tabbed content. -* |sphinx-hoverxref|_ for showing floating windows on cross references - of the documentation. * |sphinx-notfound-page|_ to add a :wikipedia:`404 ` page for the documentation. * |sphinx-issues|_ to add roles for linking to GitHub (:rst:role:`commit`, @@ -1698,9 +1696,6 @@ example Jupyter notebooks, the tables of contents are in .. _`sphinx-reredirects`: https://documatt.gitlab.io/sphinx-reredirects .. |sphinx-reredirects| replace:: `sphinx-reredirects` -.. _`sphinx-hoverxref`: https://sphinx-hoverxref.readthedocs.io -.. |sphinx-hoverxref| replace:: `sphinx-hoverxref` - .. _`sphinx-issues`: https://github.com/sloria/sphinx-issues .. |sphinx-issues| replace:: `sphinx-issues` diff --git a/pyproject.toml b/pyproject.toml index 77843ccda4..dedf522b32 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -96,7 +96,6 @@ optional-dependencies.docs = [ "sphinx-collapse>=0.1.3", "sphinx-copybutton>=0.5.2", "sphinx-gallery>=0.16", - "sphinx-hoverxref>=1.4", "sphinx-issues>=4.1", "sphinx-notfound-page>=1.0.2", "sphinx-reredirects>=0.1.5", diff --git a/uv.lock b/uv.lock index b2adf35eac..40cea164b7 100644 --- a/uv.lock +++ b/uv.lock @@ -1401,15 +1401,14 @@ wheels = [ [[package]] name = "numpydoc" -version = "1.8.0" +version = "1.9.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "sphinx" }, - { name = "tabulate" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/ee/59/5d1d1afb0b9598e21e7cda477935188e39ef845bcf59cb65ac20845bfd45/numpydoc-1.8.0.tar.gz", hash = "sha256:022390ab7464a44f8737f79f8b31ce1d3cfa4b4af79ccaa1aac5e8368db587fb", size = 90445, upload-time = "2024-08-09T15:52:38.679Z" } +sdist = { url = "https://files.pythonhosted.org/packages/2f/19/7721093e25804cc82c7c1cdab0cce6b9343451828fc2ce249cee10646db5/numpydoc-1.9.0.tar.gz", hash = "sha256:5fec64908fe041acc4b3afc2a32c49aab1540cf581876f5563d68bb129e27c5b", size = 91451, upload-time = "2025-06-24T12:22:55.283Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/6c/45/56d99ba9366476cd8548527667f01869279cedb9e66b28eb4dfb27701679/numpydoc-1.8.0-py3-none-any.whl", hash = "sha256:72024c7fd5e17375dec3608a27c03303e8ad00c81292667955c6fea7a3ccf541", size = 64003, upload-time = "2024-08-09T15:52:37.276Z" }, + { url = "https://files.pythonhosted.org/packages/26/62/5783d8924fca72529defb2c7dbe2070d49224d2dba03a85b20b37adb24d8/numpydoc-1.9.0-py3-none-any.whl", hash = "sha256:8a2983b2d62bfd0a8c470c7caa25e7e0c3d163875cdec12a8a1034020a9d1135", size = 64871, upload-time = "2025-06-24T12:22:53.701Z" }, ] [[package]] @@ -1608,7 +1607,6 @@ docs = [ { name = "sphinx-collapse" }, { name = "sphinx-copybutton" }, { name = "sphinx-gallery" }, - { name = "sphinx-hoverxref" }, { name = "sphinx-issues" }, { name = "sphinx-notfound-page" }, { name = "sphinx-reredirects" }, @@ -1671,7 +1669,6 @@ requires-dist = [ { name = "sphinx-collapse", marker = "extra == 'docs'", specifier = ">=0.1.3" }, { name = "sphinx-copybutton", marker = "extra == 'docs'", specifier = ">=0.5.2" }, { name = "sphinx-gallery", marker = "extra == 'docs'", specifier = ">=0.16" }, - { name = "sphinx-hoverxref", marker = "extra == 'docs'", specifier = ">=1.4" }, { name = "sphinx-issues", marker = "extra == 'docs'", specifier = ">=4.1" }, { name = "sphinx-notfound-page", marker = "extra == 'docs'", specifier = ">=1.0.2" }, { name = "sphinx-reredirects", marker = "extra == 'docs'", specifier = ">=0.1.5" }, @@ -2417,19 +2414,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/77/c7/52b48aec16b26c52aba854d03a3a31e0681150301dac1bea2243645a69e7/sphinx_gallery-0.19.0-py3-none-any.whl", hash = "sha256:4c28751973f81769d5bbbf5e4ebaa0dc49dff8c48eb7f11131eb5f6e4aa25f0e", size = 455923, upload-time = "2025-02-13T03:24:47.697Z" }, ] -[[package]] -name = "sphinx-hoverxref" -version = "1.4.2" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "sphinx" }, - { name = "sphinxcontrib-jquery" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/d6/6d/89764d3c719ed172d94778a74661cca647b2475165ae6cde1f73c9524d63/sphinx_hoverxref-1.4.2.tar.gz", hash = "sha256:74fab961b1b8c0e9c2cf22fa195c0e783d635e78686d39dd06ff157c196ca0c9", size = 1715764, upload-time = "2024-11-18T18:01:34.965Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/19/3b/d981175d7b9bbbcf6894faf640d15198394efc7dedd6182332c4a791a5a6/sphinx_hoverxref-1.4.2-py2.py3-none-any.whl", hash = "sha256:4fc2e283e908d9df61ea9196589934944a7e2e6e3cb753a420b938cd6d14e220", size = 32198, upload-time = "2024-11-18T18:01:31.473Z" }, -] - [[package]] name = "sphinx-issues" version = "5.0.1" @@ -2614,15 +2598,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/f1/7b/ce1eafaf1a76852e2ec9b22edecf1daa58175c090266e9f6c64afcd81d91/stack_data-0.6.3-py3-none-any.whl", hash = "sha256:d5558e0c25a4cb0853cddad3d77da9891a08cb85dd9f9f91b9f8cd66e511e695", size = 24521, upload-time = "2023-09-30T13:58:03.53Z" }, ] -[[package]] -name = "tabulate" -version = "0.9.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/ec/fe/802052aecb21e3797b8f7902564ab6ea0d60ff8ca23952079064155d1ae1/tabulate-0.9.0.tar.gz", hash = "sha256:0095b12bf5966de529c0feb1fa08671671b3368eec77d7ef7ab114be2c068b3c", size = 81090, upload-time = "2022-10-06T17:21:48.54Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/40/44/4a5f08c96eb108af5cb50b41f76142f0afa346dfa99d5296fe7202a11854/tabulate-0.9.0-py3-none-any.whl", hash = "sha256:024ca478df22e9340661486f85298cff5f6dcdba14f3813e8830015b9ed1948f", size = 35252, upload-time = "2022-10-06T17:21:44.262Z" }, -] - [[package]] name = "terminado" version = "0.18.1" From 0d70ea23daf27cac923d95e1a5628d7fb9b030a6 Mon Sep 17 00:00:00 2001 From: Erik Date: Tue, 24 Jun 2025 13:55:12 -0700 Subject: [PATCH 324/521] use np.arange to generate reg_voltage instead of np.linspace --- src/plasmapy/analysis/swept_langmuir/helpers.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plasmapy/analysis/swept_langmuir/helpers.py b/src/plasmapy/analysis/swept_langmuir/helpers.py index 9f44ff71da..693823d12e 100644 --- a/src/plasmapy/analysis/swept_langmuir/helpers.py +++ b/src/plasmapy/analysis/swept_langmuir/helpers.py @@ -345,8 +345,8 @@ def _merge_voltage_clusters__interpolate_sweep( new voltage array will be spaced by ``voltage_step_size`` and span the same range as the original ``voltage`` array. """ - size = int(np.round((voltage[-1] - voltage[0]) / voltage_step_size)) + 1 - reg_voltage = np.linspace(voltage[0], voltage[-1], num=size, dtype=voltage.dtype) + size = int(np.floor((voltage[-1] - voltage[0]) / voltage_step_size)) + 1 + reg_voltage = voltage_step_size * np.arange(size, dtype=voltage.dtype) + voltage[0] reg_current = np.interp(reg_voltage, voltage, current) return reg_voltage, reg_current From 5febd1066c1721282c6abc6ebfbe1aabd2d0fb8d Mon Sep 17 00:00:00 2001 From: Erik Date: Tue, 24 Jun 2025 13:57:36 -0700 Subject: [PATCH 325/521] replace UserWarning with PlasmaPyWarning --- src/plasmapy/analysis/swept_langmuir/helpers.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/plasmapy/analysis/swept_langmuir/helpers.py b/src/plasmapy/analysis/swept_langmuir/helpers.py index 693823d12e..a44eeb6af6 100644 --- a/src/plasmapy/analysis/swept_langmuir/helpers.py +++ b/src/plasmapy/analysis/swept_langmuir/helpers.py @@ -615,6 +615,7 @@ def merge_voltage_clusters( # noqa: C901, PLR0912 "voltage array is NOT already regularly spaced. " "Returning voltage and current arrays WITHOUT enforce " "regular spacing.", + PlasmaPyWarning, ) else: From dab2bfab824eff41539615a2de79cf9c9fef7848 Mon Sep 17 00:00:00 2001 From: Erik Date: Tue, 24 Jun 2025 13:57:51 -0700 Subject: [PATCH 326/521] add more test scenarios --- .../test_helpers__merge_voltage_clusters.py | 57 ++++++++++++++++++- 1 file changed, 56 insertions(+), 1 deletion(-) diff --git a/tests/analysis/swept_langmuir/test_helpers__merge_voltage_clusters.py b/tests/analysis/swept_langmuir/test_helpers__merge_voltage_clusters.py index 2cfd7b33c5..51ca726a4f 100644 --- a/tests/analysis/swept_langmuir/test_helpers__merge_voltage_clusters.py +++ b/tests/analysis/swept_langmuir/test_helpers__merge_voltage_clusters.py @@ -55,7 +55,62 @@ ( np.array([1, 2, 3, 4, 5, 6], dtype=float), np.array([-5, -2, np.nan, 0, np.nan, 5], dtype=float), - ), # same as inputs + ), + ), + ( + np.array([1, 2, 2, 4, 6, 6], dtype=float), + np.array([-5, -2, -2.1, 0, 5, 4.9], dtype=float), + {"voltage_step_size": 0.0}, + does_not_raise(), + ( + np.array([1, 2, 4, 6], dtype=float), + np.array([-5, -2.05, 0, 4.95], dtype=float), + ), + ), + ( + np.array([1, 2, 2, 4, 6, 6], dtype=float), + np.array([-5, -2, -2.1, 0, 5, 4.9], dtype=float), + {"voltage_step_size": 0, "force_regular_spacing": True}, + does_not_raise(), + ( + np.array([1, 2, 3, 4, 5, 6], dtype=float), + np.array([-5, -2.05, np.nan, 0, np.nan, 4.95], dtype=float), + ), + ), + # voltage_step_size < all actual diffs + ( + np.array([1, 1.5, 2.1, 4, 5.5, 6], dtype=float), + np.array([-5, -2, -2, 0, 5, 5], dtype=float), + {"voltage_step_size": 0.2, "force_regular_spacing": False}, + does_not_raise(), + None, + ), + ( + np.array([1, 1.5, 2.1, 4, 5.5, 6], dtype=float), + np.array([-5, -2, -2, 0, 5, 5], dtype=float), + {"voltage_step_size": 0.4, "force_regular_spacing": True}, + does_not_raise(), + ( + 0.4 * np.arange(13, dtype=float) + 1.0, + np.array( + [ + -5, + -2.6, + -2, + -1.894736, + -1.473684, + -1.052631, + -0.631578, + -0.210526, + 0.666667, + 2.0, + 3.333333, + 4.666667, + 5.0, + ], + dtype=float, + ), # generated using np.interp + ), ), ], ) From 96a78d7cecfc16a43a108f258af61be9127b6bc4 Mon Sep 17 00:00:00 2001 From: Erik Date: Tue, 24 Jun 2025 15:40:32 -0700 Subject: [PATCH 327/521] add another scenario for the PlasmaPyWarning --- .../test_helpers__merge_voltage_clusters.py | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/tests/analysis/swept_langmuir/test_helpers__merge_voltage_clusters.py b/tests/analysis/swept_langmuir/test_helpers__merge_voltage_clusters.py index 51ca726a4f..0f49261cfc 100644 --- a/tests/analysis/swept_langmuir/test_helpers__merge_voltage_clusters.py +++ b/tests/analysis/swept_langmuir/test_helpers__merge_voltage_clusters.py @@ -32,14 +32,25 @@ pytest.raises(TypeError), None, ), - # values - ( + # warnings (and values) + ( # voltage spacing is regular and not step size given np.linspace(-40.0, 40, 100), np.linspace(-10.0, 30, 100), {"voltage_step_size": None}, pytest.warns(PlasmaPyWarning), None, # same as inputs ), + ( # voltage_step_size = 0 and spacing is irregular + np.array([1.1, 1.1, 2, 3.8, 6.1, 6.1], dtype=float), + np.array([-5, -5.2, -2, 0, 4.2, 5], dtype=float), + {"voltage_step_size": 0, "force_regular_spacing": True}, + pytest.warns(PlasmaPyWarning), + ( + np.array([1.1, 2, 3.8, 6.1], dtype=float), + np.array([-5.1, -2, 0, 4.6], dtype=float), + ), + ), + # values ( np.linspace(-40.0, 40, 100), np.linspace(-10.0, 30, 100), From b1359c3de4297d0a2893283752b894403ab8712e Mon Sep 17 00:00:00 2001 From: Erik Date: Tue, 24 Jun 2025 15:49:48 -0700 Subject: [PATCH 328/521] disable untyped mypy error for tests --- mypy.ini | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mypy.ini b/mypy.ini index a6b8fd8ae4..c093717935 100644 --- a/mypy.ini +++ b/mypy.ini @@ -331,6 +331,9 @@ disable_error_code = arg-type,no-untyped-def,union-attr [mypy-tests.analysis.swept_langmuir.test_swept_langmuir_helpers] disable_error_code = no-untyped-def +[mypy-tests.analysis.swept_langmuir.test_helpers__merge_voltage_clusters] +disable_error_code = no-untyped-def + [mypy-tests.analysis.test_fit_functions] disable_error_code = assignment,index,no-any-return,no-untyped-call,no-untyped-def,override,type-arg From 115835f2c30ddf2fa371257349d9571853e3f050 Mon Sep 17 00:00:00 2001 From: Erik Date: Tue, 24 Jun 2025 16:44:45 -0700 Subject: [PATCH 329/521] update docstring --- src/plasmapy/analysis/swept_langmuir/helpers.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/plasmapy/analysis/swept_langmuir/helpers.py b/src/plasmapy/analysis/swept_langmuir/helpers.py index a44eeb6af6..632a30f9bf 100644 --- a/src/plasmapy/analysis/swept_langmuir/helpers.py +++ b/src/plasmapy/analysis/swept_langmuir/helpers.py @@ -489,6 +489,7 @@ def merge_voltage_clusters( # noqa: C901, PLR0912 Notes ----- - ``voltage_step_size = 0`` + - Only merge clusters that have the same voltage values. - ``force_regular_spacing = True`` is ignored if the spacing is not already regularly spaced. If the voltage is already @@ -496,6 +497,7 @@ def merge_voltage_clusters( # noqa: C901, PLR0912 stuffed for missing voltage entries. - ``voltage_step_size is None`` + - If the ``voltage`` array is already regularly spaced, then a copy of the original arrays will be returned. - If the ``voltage`` array is NOT regularly spaced, then the @@ -503,6 +505,7 @@ def merge_voltage_clusters( # noqa: C901, PLR0912 array. - ``voltage_step_size > 0`` or `None` + - If the ``voltage`` array is already regularly spaced, then `numpy.interp` will be used interpolate the ``voltage`` and ``current`` arrays onto the new grid spacing @@ -517,7 +520,7 @@ def merge_voltage_clusters( # noqa: C901, PLR0912 merged together with the new current value being the average of the points in the cluster and the new voltage value being ``voltage_min + 0.5 * N * voltage_step_size``, where ``N`` is - the Nth point in the voltage array. + the N-th point in the voltage array. """ # condition force_regular_grid if not isinstance(force_regular_spacing, bool): From a4144d4cb60f244e8336fbd7d86341e4da1408e7 Mon Sep 17 00:00:00 2001 From: Erik Date: Wed, 25 Jun 2025 09:41:44 -0700 Subject: [PATCH 330/521] removed unnecessary mock --- .../swept_langmuir/test_helpers__merge_voltage_clusters.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/tests/analysis/swept_langmuir/test_helpers__merge_voltage_clusters.py b/tests/analysis/swept_langmuir/test_helpers__merge_voltage_clusters.py index 0f49261cfc..a3e0fa717b 100644 --- a/tests/analysis/swept_langmuir/test_helpers__merge_voltage_clusters.py +++ b/tests/analysis/swept_langmuir/test_helpers__merge_voltage_clusters.py @@ -130,10 +130,6 @@ def test_merge_voltage_clusters( ) -> None: with ( with_context, - mock.patch( - "plasmapy.analysis.swept_langmuir.helpers.merge_voltage_clusters", - wraps=merge_voltage_clusters, - ) as mock_merge, mock.patch( "plasmapy.analysis.swept_langmuir.helpers.check_sweep", wraps=check_sweep, @@ -159,8 +155,5 @@ def test_merge_voltage_clusters( assert np.allclose(rtn_voltage, voltage) assert np.allclose(rtn_current, current) - # mock_merge.assert_called_once() - # mock_merge.reset_mock() - mock_sweep.assert_called_once() mock_sweep.reset_mock() From 1638c5e251a730fd85a51a08107bd0015af5e019 Mon Sep 17 00:00:00 2001 From: Erik Date: Wed, 25 Jun 2025 15:50:22 -0700 Subject: [PATCH 331/521] rework _merge_voltage_clusters__within_dv so clusters are identified and then merged --- .../analysis/swept_langmuir/helpers.py | 81 +++++++++++++------ 1 file changed, 56 insertions(+), 25 deletions(-) diff --git a/src/plasmapy/analysis/swept_langmuir/helpers.py b/src/plasmapy/analysis/swept_langmuir/helpers.py index 632a30f9bf..de348ac327 100644 --- a/src/plasmapy/analysis/swept_langmuir/helpers.py +++ b/src/plasmapy/analysis/swept_langmuir/helpers.py @@ -408,35 +408,66 @@ def _merge_voltage_clusters__within_dv( within step size ``voltage_step_size``. """ # initialize new voltage and current arrays - new_voltage = np.full(voltage.shape, np.nan, dtype=voltage.dtype) - new_current = np.full(current.shape, np.nan, dtype=current.dtype) + new_voltage = voltage.copy() + new_current = current.copy() - start_voltage = voltage[0] - stop_voltage = start_voltage + voltage_step_size - - # populate - ii = 0 - while start_voltage <= voltage[-1]: - mask1 = voltage >= start_voltage - mask2 = voltage < stop_voltage - mask = np.logical_and(mask1, mask2) - - if np.count_nonzero(mask) > 0: - new_voltage[ii] = ( - start_voltage + 0.5 * voltage_step_size - if force_regular_spacing - else np.average(voltage[mask]) - ) - new_current[ii] = np.average(current[mask]) + voltage_diff = np.diff(voltage) - ii += 1 + # generate global cluster mask + cluster_mask = voltage_diff <= voltage_step_size + cluster_mask = np.append(cluster_mask, [cluster_mask[-1]]) + cluster_mask[1:] = np.logical_or(cluster_mask[1:], np.roll(cluster_mask, 1)[1:]) - start_voltage = stop_voltage - stop_voltage += voltage_step_size + # determine cluster locations + indices = np.where(np.diff(cluster_mask))[0] + if cluster_mask[0]: + # 1st element in voltage is in a cluster + indices = np.append([0], indices) + else: + indices[0] = indices[0] + 1 + if indices.size > 1: + indices[2::2] = indices[2::2] + 1 + if cluster_mask[-1] and indices[-1] != voltage.size-1: + # last element in voltage is in a cluster + indices = np.append(indices, [voltage.size-1]) + indices = np.reshape(indices, shape=(int(indices.size/2), 2)) - # crop new arrays - new_voltage = new_voltage[:ii] - new_current = new_current[:ii] + # populate + for ii in range(indices.shape[0]): + start_index = indices[ii][0] + stop_index = indices[ii][1] + 1 + + new_voltage[start_index:stop_index] = np.nan + new_current[start_index:stop_index] = np.nan + + sub_voltage = voltage[start_index:stop_index] + sub_current = current[start_index:stop_index] + + if sub_voltage[-1] - sub_voltage[0] <= voltage_step_size: + new_voltage[start_index] = np.average(sub_voltage) + new_current[start_index] = np.average(sub_current) + continue + + start_voltage = sub_voltage[0] + stop_voltage = start_voltage + voltage_step_size + jj = 0 + while start_voltage <= sub_voltage[-1]: + mask1 = sub_voltage >= start_voltage + mask2 = sub_voltage < stop_voltage + mask = np.logical_and(mask1, mask2) + + if np.count_nonzero(mask) > 0: + new_voltage[start_index + jj] = np.average(sub_voltage[mask]) + new_current[start_index + jj] = np.average(sub_current[mask]) + jj += 1 + + start_voltage = stop_voltage + stop_voltage += voltage_step_size + + # filter out NaN values + nan_mask = np.logical_not(np.isnan(new_voltage)) + new_voltage = new_voltage[nan_mask] + new_current = new_current[nan_mask] return new_voltage, new_current From 6e1838b9cd02d9f291b14bd25bd2b8bf07cd5259 Mon Sep 17 00:00:00 2001 From: Erik Date: Wed, 25 Jun 2025 15:55:21 -0700 Subject: [PATCH 332/521] remove force_regular_spacing --- .../analysis/swept_langmuir/helpers.py | 63 +------------------ 1 file changed, 3 insertions(+), 60 deletions(-) diff --git a/src/plasmapy/analysis/swept_langmuir/helpers.py b/src/plasmapy/analysis/swept_langmuir/helpers.py index de348ac327..25cc0763e8 100644 --- a/src/plasmapy/analysis/swept_langmuir/helpers.py +++ b/src/plasmapy/analysis/swept_langmuir/helpers.py @@ -400,7 +400,6 @@ def _merge_voltage_clusters__within_dv( voltage: np.ndarray, current: np.ndarray, voltage_step_size: float, - force_regular_spacing: bool, ) -> tuple[np.ndarray, np.ndarray]: """ Take the ``voltage`` and ``current`` arrays associated with a swept @@ -476,7 +475,6 @@ def merge_voltage_clusters( # noqa: C901, PLR0912 voltage: np.ndarray, current: np.ndarray, voltage_step_size: float | None = None, - force_regular_spacing: bool = False, ) -> tuple[np.ndarray, np.ndarray]: """ Search the ``voltage`` array for closely spaced voltage clusters @@ -503,12 +501,6 @@ def merge_voltage_clusters( # noqa: C901, PLR0912 duplicate voltage values. A value of `None` will default to the average step size of the ``voltage`` array. (DEFAULT:`None`) - force_regular_spacing: `bool` - If `False`, then the new voltage value of a cluster is the - average of the contained points. If `True`, then the new - ``voltage`` array will be regularly spaced with a delta of - ``voltage_step_size``. (DEFAULT: `False`) - Returns ------- voltage : `numpy.ndarray` @@ -553,13 +545,6 @@ def merge_voltage_clusters( # noqa: C901, PLR0912 ``voltage_min + 0.5 * N * voltage_step_size``, where ``N`` is the N-th point in the voltage array. """ - # condition force_regular_grid - if not isinstance(force_regular_spacing, bool): - raise TypeError( - "Expected 'force_regular_spacing' to be a bool, but got type " - f"{type(force_regular_spacing)}." - ) - # condition voltage_step_size if voltage_step_size is not None and not isinstance( voltage_step_size, float | np.floating | int | np.integer @@ -589,14 +574,6 @@ def merge_voltage_clusters( # noqa: C901, PLR0912 PlasmaPyWarning, ) - if force_regular_spacing: - # need to stuff with NaN values - voltage, current = _force_regular_spacing( - voltage=voltage, - current=current, - voltage_step_size=np.min(voltage_diff), - ) - return voltage.copy(), current.copy() # condition voltage_step_size ... Round 2 @@ -618,53 +595,19 @@ def merge_voltage_clusters( # noqa: C901, PLR0912 # now merge clusters if voltage_step_size != 0 and np.all(voltage_diff >= voltage_step_size): - if force_regular_spacing: - new_voltage, new_current = _merge_voltage_clusters__interpolate_sweep( - voltage, current, voltage_step_size - ) - else: - new_voltage = voltage.copy() - new_current = current.copy() + new_voltage = voltage.copy() + new_current = current.copy() elif voltage_step_size == 0: new_voltage, new_current = _merge_voltage_clusters__zero_diff_neighbors( voltage, current ) - if force_regular_spacing: - voltage_diff = np.diff(new_voltage) - mask_zero_diff = np.isclose(voltage_diff, 0.0) - is_regular_grid = _is_voltage_regularly_spaced(voltage_diff, mask_zero_diff) - - if is_regular_grid: - new_voltage, new_current = _force_regular_spacing( - voltage=new_voltage, - current=new_current, - voltage_step_size=np.min(voltage_diff), - ) - else: - warnings.warn( - "Can not enforce regular spacing for the voltage array " - "if argument 'voltage_step_size' is set to 0 and the " - "voltage array is NOT already regularly spaced. " - "Returning voltage and current arrays WITHOUT enforce " - "regular spacing.", - PlasmaPyWarning, - ) - else: new_voltage, new_current = _merge_voltage_clusters__within_dv( - voltage, current, voltage_step_size, force_regular_spacing + voltage, current, voltage_step_size ) - if force_regular_spacing: - # Need to fill array with NaN values to force the regular spacing - new_voltage, new_current = _force_regular_spacing( - voltage=new_voltage, - current=new_current, - voltage_step_size=voltage_step_size, - ) - if not voltage_ascending: voltage = voltage[::-1] current = current[::-1] From 50e7364388f2a78f90cb2a9b08b26ff6a6e65674 Mon Sep 17 00:00:00 2001 From: Erik Date: Wed, 25 Jun 2025 16:38:23 -0700 Subject: [PATCH 333/521] update warning messages --- .../analysis/swept_langmuir/helpers.py | 32 +++++++++++-------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/src/plasmapy/analysis/swept_langmuir/helpers.py b/src/plasmapy/analysis/swept_langmuir/helpers.py index 25cc0763e8..4d0b8230de 100644 --- a/src/plasmapy/analysis/swept_langmuir/helpers.py +++ b/src/plasmapy/analysis/swept_langmuir/helpers.py @@ -565,14 +565,13 @@ def merge_voltage_clusters( # noqa: C901, PLR0912 # return if voltage is already regularly spaced and no voltage merging is # requested - if is_regular_grid and (voltage_step_size is None or voltage_step_size == 0): - if voltage_step_size is None: - warnings.warn( - "The supplied ``voltage`` array is already regularly spaced. If " - "you want to re-bin the arrays to a different voltage_step_size, " - "the use something like numpy.interp.", - PlasmaPyWarning, - ) + if is_regular_grid and voltage_step_size is None: + warnings.warn( + "The supplied ``voltage`` array is already regularly spaced. If " + "you want to re-bin the arrays to a different voltage_step_size, " + "then use something like numpy.interp. No merging performed.", + PlasmaPyWarning, + ) return voltage.copy(), current.copy() @@ -586,6 +585,17 @@ def merge_voltage_clusters( # noqa: C901, PLR0912 elif voltage_step_size < 0: voltage_step_size = -voltage_step_size + if np.all(voltage_step_size <= np.abs(voltage_diff)) and voltage_step_size != 0: + warnings.warn( + f"The supplied voltage_step_size ({voltage_step_size}) is smaller than " + f"any of the voltage steps in the voltage array. Supply a step size " + f"greater than the smallest voltage step ({np.min(voltage_diff)}). " + f"No merging performed.", + PlasmaPyWarning, + ) + + return voltage.copy(), current.copy() + # ensure voltage is ascending for calculation voltage_ascending = bool(np.all(voltage_diff >= 0)) if not voltage_ascending: @@ -594,11 +604,7 @@ def merge_voltage_clusters( # noqa: C901, PLR0912 ) # now merge clusters - if voltage_step_size != 0 and np.all(voltage_diff >= voltage_step_size): - new_voltage = voltage.copy() - new_current = current.copy() - - elif voltage_step_size == 0: + if voltage_step_size == 0: new_voltage, new_current = _merge_voltage_clusters__zero_diff_neighbors( voltage, current ) From 30daae3210fd81139930c4b22d8ead375d4978c9 Mon Sep 17 00:00:00 2001 From: Erik Date: Wed, 25 Jun 2025 16:39:47 -0700 Subject: [PATCH 334/521] remove _force_regular_spacing() --- .../analysis/swept_langmuir/helpers.py | 68 ------------------- 1 file changed, 68 deletions(-) diff --git a/src/plasmapy/analysis/swept_langmuir/helpers.py b/src/plasmapy/analysis/swept_langmuir/helpers.py index 4d0b8230de..a987e1e2f1 100644 --- a/src/plasmapy/analysis/swept_langmuir/helpers.py +++ b/src/plasmapy/analysis/swept_langmuir/helpers.py @@ -239,74 +239,6 @@ def sort_sweep_arrays( return voltage, current -def _force_regular_spacing( - voltage: np.ndarray, - current: np.ndarray, - voltage_step_size: float, -) -> tuple[np.ndarray, np.ndarray]: - """ - Generated a regularly spaced voltage array and associated - `~numpy.nan` stuffed current array from the given ``voltage`` - and ``current`` langmuir trace arrays. The generated voltage - array will span the same range as the input ``voltage`` array with - a regular spacing of ``voltage_step_size``. - - It is assumed the input ``voltage`` array is already spaced at - some integer multiple of ``voltage_step_size``. This integer - multiple does NOT need to be fixed for every point pair in - ``voltage``. - - Parameters - ---------- - voltage: `numpy.ndarray` - 1D `numpy.ndarray` representing the voltage of the swept - Langmuir trace. *No units are assumed or checked, but values - should be in volts.* - - current: `numpy.ndarray` - 1D `numpy.ndarray` representing the current of the swept - Langmuir trace. Values should start from a negative - ion-saturation current and increase to a positive - electron-saturation current. *No units are assumed or checked, - but values should be in amperes.* - - voltage_step_size: `float` - A non-zero, positive step size for the ``voltage`` array - spacing. - - Returns - ------- - voltage : `numpy.ndarray` - An array with step size ``voltage_step_size`` spanning the same - voltages given in the input ``voltage`` array. - - current : `numpy.ndarray` - A `~numpy.nan` stuffed copy of the input ``current`` array to - match the size of the returned ``voltage`` array. - """ - size = int(np.round((voltage[-1] - voltage[0]) / voltage_step_size)) + 1 - - if voltage.size == size: - # all voltages steps are already equal - return voltage, current - - reg_voltage = np.linspace(voltage[0], voltage[-1], num=size, dtype=voltage.dtype) - - _, reg_indices, new_indices = np.intersect1d( - np.round(reg_voltage, decimals=5), - np.round(voltage, decimals=5), - return_indices=True, - ) - - mask = np.zeros_like(reg_voltage, dtype=bool) - mask[reg_indices] = True - - reg_current = np.full(size, np.nan, dtype=current.dtype) - reg_current[mask] = current[...] - - return reg_voltage, reg_current - - def _is_voltage_regularly_spaced( voltage_diff: np.ndarray, mask_zero_diff: np.ndarray, From a1df942ae7f013327f8cca83f7d880866fd18fc3 Mon Sep 17 00:00:00 2001 From: Erik Date: Wed, 25 Jun 2025 17:49:33 -0700 Subject: [PATCH 335/521] if voltage cluster spans a distance larger than voltage_step_size then bin the cluster for averaging --- .../analysis/swept_langmuir/helpers.py | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/plasmapy/analysis/swept_langmuir/helpers.py b/src/plasmapy/analysis/swept_langmuir/helpers.py index a987e1e2f1..5b1d6773bb 100644 --- a/src/plasmapy/analysis/swept_langmuir/helpers.py +++ b/src/plasmapy/analysis/swept_langmuir/helpers.py @@ -374,26 +374,30 @@ def _merge_voltage_clusters__within_dv( sub_voltage = voltage[start_index:stop_index] sub_current = current[start_index:stop_index] - if sub_voltage[-1] - sub_voltage[0] <= voltage_step_size: + nbins = int(np.floor((sub_voltage[-1] - sub_voltage[0]) / voltage_step_size)) + if nbins == 0: + nbins = 1 + + if nbins == 1: new_voltage[start_index] = np.average(sub_voltage) new_current[start_index] = np.average(sub_current) continue - start_voltage = sub_voltage[0] - stop_voltage = start_voltage + voltage_step_size - jj = 0 - while start_voltage <= sub_voltage[-1]: + range_array = np.linspace(sub_voltage[0], sub_voltage[-1], nbins+1) + for jj in range(nbins): + start_voltage = range_array[jj] + start_current = range_array[jj+1] + mask1 = sub_voltage >= start_voltage - mask2 = sub_voltage < stop_voltage + if jj == nbins - 1: + mask2 = sub_voltage <= stop_voltage + else: + mask2 = sub_voltage < stop_voltage mask = np.logical_and(mask1, mask2) if np.count_nonzero(mask) > 0: new_voltage[start_index + jj] = np.average(sub_voltage[mask]) new_current[start_index + jj] = np.average(sub_current[mask]) - jj += 1 - - start_voltage = stop_voltage - stop_voltage += voltage_step_size # filter out NaN values nan_mask = np.logical_not(np.isnan(new_voltage)) From 51071e83536ff613afd170b0f856c77fc094fde8 Mon Sep 17 00:00:00 2001 From: Erik Date: Wed, 25 Jun 2025 17:49:50 -0700 Subject: [PATCH 336/521] improve docstring --- src/plasmapy/analysis/swept_langmuir/helpers.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/plasmapy/analysis/swept_langmuir/helpers.py b/src/plasmapy/analysis/swept_langmuir/helpers.py index 5b1d6773bb..81fe584e3e 100644 --- a/src/plasmapy/analysis/swept_langmuir/helpers.py +++ b/src/plasmapy/analysis/swept_langmuir/helpers.py @@ -435,7 +435,8 @@ def merge_voltage_clusters( # noqa: C901, PLR0912 A non-zero, positive step size for the ``voltage`` array cluster identification. A value of ``0`` will merge only duplicate voltage values. A value of `None` will default to the - average step size of the ``voltage`` array. (DEFAULT:`None`) + average step size of the ``voltage`` array (only counting + duplicate voltages once). (DEFAULT:`None`) Returns ------- From 641126a30d776e08fb6e09a02a56cc241cdd349d Mon Sep 17 00:00:00 2001 From: Erik Date: Wed, 25 Jun 2025 18:07:23 -0700 Subject: [PATCH 337/521] update docstring --- .../analysis/swept_langmuir/helpers.py | 47 +++++-------------- 1 file changed, 13 insertions(+), 34 deletions(-) diff --git a/src/plasmapy/analysis/swept_langmuir/helpers.py b/src/plasmapy/analysis/swept_langmuir/helpers.py index 81fe584e3e..7daa8a0d02 100644 --- a/src/plasmapy/analysis/swept_langmuir/helpers.py +++ b/src/plasmapy/analysis/swept_langmuir/helpers.py @@ -412,7 +412,7 @@ def merge_voltage_clusters( # noqa: C901, PLR0912 current: np.ndarray, voltage_step_size: float | None = None, ) -> tuple[np.ndarray, np.ndarray]: - """ + r""" Search the ``voltage`` array for closely spaced voltage clusters based on the ``voltage_step_size`` parameter and merge those clusters, and associated ``current`` values, into a single point. @@ -448,39 +448,18 @@ def merge_voltage_clusters( # noqa: C901, PLR0912 Notes ----- - - ``voltage_step_size = 0`` - - - Only merge clusters that have the same voltage values. - - ``force_regular_spacing = True`` is ignored if the spacing is - not already regularly spaced. If the voltage is already - regularly spaced, then the current array will be `numpy.nan` - stuffed for missing voltage entries. - - - ``voltage_step_size is None`` - - - If the ``voltage`` array is already regularly spaced, then a - copy of the original arrays will be returned. - - If the ``voltage`` array is NOT regularly spaced, then the - step size will be the average voltage step of the ``voltage`` - array. - - - ``voltage_step_size > 0`` or `None` - - - If the ``voltage`` array is already regularly spaced, then - `numpy.interp` will be used interpolate the ``voltage`` and - ``current`` arrays onto the new grid spacing - ``voltage_step_size``. - - If ``force_regular_spacing = False``, then, starting at the - lowest voltage, clusters within ``voltage_step_size`` will be - merged together with the new voltage value being the average of - the points in the cluster and the new current value being the - average of the points in the cluster. - - If ``force_regular_spacing = True``, then, starting at the - lowest voltage, clusters within ``voltage_step_size`` will be - merged together with the new current value being the average of - the points in the cluster and the new voltage value being - ``voltage_min + 0.5 * N * voltage_step_size``, where ``N`` is - the N-th point in the voltage array. + + An identified voltage cluster can span a voltage range larger than + ``voltage_step_size`` and still have every voltage step being + smaller than ``voltage_step_size``. In this scenario, the voltage + cluster will be divided up into :math:`N`-sections for averaging, + where :math:`N` is given by + + .. math:: + + N = \texttt{floor}\left( + \frac{V_{cluster,max} - V_{cluster,min}}{\texttt{voltage_step_size}} + \right) """ # condition voltage_step_size if voltage_step_size is not None and not isinstance( From 786dcfc8189af829b4fe9c9fab917608a9409b84 Mon Sep 17 00:00:00 2001 From: Erik Date: Wed, 25 Jun 2025 18:17:34 -0700 Subject: [PATCH 338/521] update test for removal of kwarg force_regular_spacing --- .../test_helpers__merge_voltage_clusters.py | 78 +++++-------------- 1 file changed, 20 insertions(+), 58 deletions(-) diff --git a/tests/analysis/swept_langmuir/test_helpers__merge_voltage_clusters.py b/tests/analysis/swept_langmuir/test_helpers__merge_voltage_clusters.py index a3e0fa717b..9bdf2defcd 100644 --- a/tests/analysis/swept_langmuir/test_helpers__merge_voltage_clusters.py +++ b/tests/analysis/swept_langmuir/test_helpers__merge_voltage_clusters.py @@ -18,13 +18,6 @@ ("voltage", "current", "kwargs", "with_context", "expected"), [ # raises - ( - np.linspace(-40.0, 40, 100), - np.linspace(-10.0, 30, 100), - {"force_regular_spacing": None}, # not a bool - pytest.raises(TypeError), - None, - ), ( np.linspace(-40.0, 40, 100), np.linspace(-10.0, 30, 100), @@ -40,15 +33,19 @@ pytest.warns(PlasmaPyWarning), None, # same as inputs ), - ( # voltage_step_size = 0 and spacing is irregular - np.array([1.1, 1.1, 2, 3.8, 6.1, 6.1], dtype=float), + ( # non-zero voltage_step_size < any step size + np.array([1.1, 1.5, 2, 3.8, 6.0, 6.2], dtype=float), np.array([-5, -5.2, -2, 0, 4.2, 5], dtype=float), - {"voltage_step_size": 0, "force_regular_spacing": True}, + {"voltage_step_size": 0.1}, pytest.warns(PlasmaPyWarning), - ( - np.array([1.1, 2, 3.8, 6.1], dtype=float), - np.array([-5.1, -2, 0, 4.6], dtype=float), - ), + None, + ), + ( + np.array([1, 1.5, 2.1, 4, 5.5, 6], dtype=float), + np.array([-5, -2, -2, 0, 5, 5], dtype=float), + {"voltage_step_size": 0.2}, + pytest.warns(PlasmaPyWarning), + None, ), # values ( @@ -58,16 +55,6 @@ does_not_raise(), None, # same as inputs ), - ( - np.array([1, 2, 4, 6], dtype=float), - np.array([-5, -2, 0, 5], dtype=float), - {"voltage_step_size": 0.0, "force_regular_spacing": True}, - does_not_raise(), - ( - np.array([1, 2, 3, 4, 5, 6], dtype=float), - np.array([-5, -2, np.nan, 0, np.nan, 5], dtype=float), - ), - ), ( np.array([1, 2, 2, 4, 6, 6], dtype=float), np.array([-5, -2, -2.1, 0, 5, 4.9], dtype=float), @@ -81,46 +68,21 @@ ( np.array([1, 2, 2, 4, 6, 6], dtype=float), np.array([-5, -2, -2.1, 0, 5, 4.9], dtype=float), - {"voltage_step_size": 0, "force_regular_spacing": True}, + {"voltage_step_size": 0}, # integer value does_not_raise(), ( - np.array([1, 2, 3, 4, 5, 6], dtype=float), - np.array([-5, -2.05, np.nan, 0, np.nan, 4.95], dtype=float), + np.array([1, 2, 4, 6], dtype=float), + np.array([-5, -2.05, 0, 4.95], dtype=float), ), ), - # voltage_step_size < all actual diffs - ( - np.array([1, 1.5, 2.1, 4, 5.5, 6], dtype=float), - np.array([-5, -2, -2, 0, 5, 5], dtype=float), - {"voltage_step_size": 0.2, "force_regular_spacing": False}, - does_not_raise(), - None, - ), - ( - np.array([1, 1.5, 2.1, 4, 5.5, 6], dtype=float), - np.array([-5, -2, -2, 0, 5, 5], dtype=float), - {"voltage_step_size": 0.4, "force_regular_spacing": True}, + ( # voltage_step_size is negative + np.array([1, 1.5, 1.56, 2.1, 4, 5.5, 5.52], dtype=float), + np.array([-5, -2, -2.1, 0, 5, 7, 7.1], dtype=float), + {"voltage_step_size": -0.1}, does_not_raise(), ( - 0.4 * np.arange(13, dtype=float) + 1.0, - np.array( - [ - -5, - -2.6, - -2, - -1.894736, - -1.473684, - -1.052631, - -0.631578, - -0.210526, - 0.666667, - 2.0, - 3.333333, - 4.666667, - 5.0, - ], - dtype=float, - ), # generated using np.interp + np.array([1, 1.53, 2.1, 4, 5.51], dtype=float), + np.array([-5, -2.05, 0, 5, 7.05], dtype=float), ), ), ], From 5d9fda3b3ffe17dcd3f1dc857a399cbfc31a6a2c Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 26 Jun 2025 12:00:55 -0700 Subject: [PATCH 339/521] use newshape kwarg --- src/plasmapy/analysis/swept_langmuir/helpers.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/plasmapy/analysis/swept_langmuir/helpers.py b/src/plasmapy/analysis/swept_langmuir/helpers.py index 7daa8a0d02..9ba7fa1c17 100644 --- a/src/plasmapy/analysis/swept_langmuir/helpers.py +++ b/src/plasmapy/analysis/swept_langmuir/helpers.py @@ -361,7 +361,9 @@ def _merge_voltage_clusters__within_dv( if cluster_mask[-1] and indices[-1] != voltage.size-1: # last element in voltage is in a cluster indices = np.append(indices, [voltage.size-1]) - indices = np.reshape(indices, shape=(int(indices.size/2), 2)) + indices = np.reshape(indices, newshape=(int(indices.size/2), 2)) + # ^ using newshape kwarg for backwards compatability, newshape kwarg + # has been deprecated since numpy v2.1 # populate for ii in range(indices.shape[0]): From 337b7da120ec96b417fd419994cb283bfa8bb6c3 Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 26 Jun 2025 12:02:49 -0700 Subject: [PATCH 340/521] fix variable start_current was supposed to be stop_voltage --- src/plasmapy/analysis/swept_langmuir/helpers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plasmapy/analysis/swept_langmuir/helpers.py b/src/plasmapy/analysis/swept_langmuir/helpers.py index 9ba7fa1c17..2683aae054 100644 --- a/src/plasmapy/analysis/swept_langmuir/helpers.py +++ b/src/plasmapy/analysis/swept_langmuir/helpers.py @@ -388,7 +388,7 @@ def _merge_voltage_clusters__within_dv( range_array = np.linspace(sub_voltage[0], sub_voltage[-1], nbins+1) for jj in range(nbins): start_voltage = range_array[jj] - start_current = range_array[jj+1] + stop_voltage = range_array[jj+1] mask1 = sub_voltage >= start_voltage if jj == nbins - 1: From ab5969428b609349816997077fed22d9bd593447 Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 26 Jun 2025 12:25:26 -0700 Subject: [PATCH 341/521] add newshape to _typos.toml --- _typos.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/_typos.toml b/_typos.toml index e9f704263a..ac0c24c496 100644 --- a/_typos.toml +++ b/_typos.toml @@ -10,3 +10,4 @@ hax = "hax" iy = "iy" nd = "nd" rety = "rety" +newshape = "newshape" From fd7b674313ebacc82ede53ae26a134a39ee73167 Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 26 Jun 2025 12:25:47 -0700 Subject: [PATCH 342/521] add test cases --- .../test_helpers__merge_voltage_clusters.py | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/tests/analysis/swept_langmuir/test_helpers__merge_voltage_clusters.py b/tests/analysis/swept_langmuir/test_helpers__merge_voltage_clusters.py index 9bdf2defcd..043704aec8 100644 --- a/tests/analysis/swept_langmuir/test_helpers__merge_voltage_clusters.py +++ b/tests/analysis/swept_langmuir/test_helpers__merge_voltage_clusters.py @@ -85,6 +85,26 @@ np.array([-5, -2.05, 0, 5, 7.05], dtype=float), ), ), + ( # voltage array starts with a cluster + np.array([1, 1.1, 1.2, 1.5, 2, 4, 5.5], dtype=float), + np.array([-5, -5.1, -4.9, -4, 0, 5, 7], dtype=float), + {"voltage_step_size": 0.1}, + does_not_raise(), + ( + np.array([1., 1.15, 1.5, 2, 4, 5.5], dtype=float), + np.array([-5., -5, -4, 0, 5, 7], dtype=float), + ), + ), + ( # voltage array starts with a cluster, spans < 2 * voltage_step_size + np.array([1, 1.1, 1.2, 1.5, 2, 4, 5.5], dtype=float), + np.array([-5, -5.1, -4.9, -4, 0, 5, 7], dtype=float), + {"voltage_step_size": 0.12}, + does_not_raise(), + ( + np.array([1.1, 1.5, 2, 4, 5.5], dtype=float), + np.array([-5., -4, 0, 5, 7], dtype=float), + ), + ), ], ) def test_merge_voltage_clusters( From 2e88fca9bbc5370b4693464f2e92586fa5d129aa Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 26 Jun 2025 12:26:11 -0700 Subject: [PATCH 343/521] remove nan mask test (not needed after removing force_regular_spacing) --- .../test_helpers__merge_voltage_clusters.py | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/tests/analysis/swept_langmuir/test_helpers__merge_voltage_clusters.py b/tests/analysis/swept_langmuir/test_helpers__merge_voltage_clusters.py index 043704aec8..b59835ed87 100644 --- a/tests/analysis/swept_langmuir/test_helpers__merge_voltage_clusters.py +++ b/tests/analysis/swept_langmuir/test_helpers__merge_voltage_clusters.py @@ -125,14 +125,7 @@ def test_merge_voltage_clusters( if expected is not None: assert np.allclose(rtn_voltage, expected[0]) - - rtn_nan_mask = np.isnan(rtn_current) - expected_nan_mask = np.isnan(expected[1]) - assert np.array_equal(rtn_nan_mask, expected_nan_mask) - assert np.allclose( - rtn_current[np.logical_not(rtn_nan_mask)], - expected[1][np.logical_not(expected_nan_mask)], - ) + assert np.allclose(rtn_current, expected[1]) else: assert np.allclose(rtn_voltage, voltage) assert np.allclose(rtn_current, current) From c995db827b328d440ec04563e265d5c55cb775a4 Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 26 Jun 2025 12:26:26 -0700 Subject: [PATCH 344/521] add clarifying comments about test scenarios --- .../swept_langmuir/test_helpers__merge_voltage_clusters.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/analysis/swept_langmuir/test_helpers__merge_voltage_clusters.py b/tests/analysis/swept_langmuir/test_helpers__merge_voltage_clusters.py index b59835ed87..3bc6aba06d 100644 --- a/tests/analysis/swept_langmuir/test_helpers__merge_voltage_clusters.py +++ b/tests/analysis/swept_langmuir/test_helpers__merge_voltage_clusters.py @@ -48,14 +48,14 @@ None, ), # values - ( + ( # no merging needed np.linspace(-40.0, 40, 100), np.linspace(-10.0, 30, 100), {"voltage_step_size": 0.0}, does_not_raise(), None, # same as inputs ), - ( + ( # merge identical voltages np.array([1, 2, 2, 4, 6, 6], dtype=float), np.array([-5, -2, -2.1, 0, 5, 4.9], dtype=float), {"voltage_step_size": 0.0}, @@ -65,7 +65,7 @@ np.array([-5, -2.05, 0, 4.95], dtype=float), ), ), - ( + ( # step size given as an integer np.array([1, 2, 2, 4, 6, 6], dtype=float), np.array([-5, -2, -2.1, 0, 5, 4.9], dtype=float), {"voltage_step_size": 0}, # integer value From 8d12c144d28120246bad38a411f15782566ee86d Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 26 Jun 2025 12:53:05 -0700 Subject: [PATCH 345/521] remove _merge_voltage_clusters__interpolate_sweep() --- .../analysis/swept_langmuir/helpers.py | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/src/plasmapy/analysis/swept_langmuir/helpers.py b/src/plasmapy/analysis/swept_langmuir/helpers.py index 2683aae054..eaf149acd7 100644 --- a/src/plasmapy/analysis/swept_langmuir/helpers.py +++ b/src/plasmapy/analysis/swept_langmuir/helpers.py @@ -266,24 +266,6 @@ def _is_voltage_regularly_spaced( return is_regular_grid -def _merge_voltage_clusters__interpolate_sweep( - voltage: np.ndarray, - current: np.ndarray, - voltage_step_size: float, -) -> tuple[np.ndarray, np.ndarray]: - """ - Interpolate the ``voltage`` and ``current`` arrays associated with - a langmuir trace onto a new regularly spaced voltage array. The - new voltage array will be spaced by ``voltage_step_size`` and span - the same range as the original ``voltage`` array. - """ - size = int(np.floor((voltage[-1] - voltage[0]) / voltage_step_size)) + 1 - reg_voltage = voltage_step_size * np.arange(size, dtype=voltage.dtype) + voltage[0] - reg_current = np.interp(reg_voltage, voltage, current) - - return reg_voltage, reg_current - - def _merge_voltage_clusters__zero_diff_neighbors( voltage: np.ndarray, current: np.ndarray ) -> tuple[np.ndarray, np.ndarray]: From 963d63b25f10b9b6dfe0eb6b2bbb714dc870966d Mon Sep 17 00:00:00 2001 From: Mahlet Getahun <212391704+Getahun-yw-Mahl@users.noreply.github.com> Date: Thu, 26 Jun 2025 17:20:22 -0400 Subject: [PATCH 346/521] Added functions to laser formulary for Gaussian beams (#3036) * Added functions to laser formulary initial commit * fix syntax * fix syntax * fix syntax * fix formatting * fix formatting * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * fix doctest and unit conversion * documentation formatting * fix reference * add a0_ alias * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * add changelog entry * fix syntax and documentation * add tests for new laser functions * fix formatting and syntax * fix typo * fixed syntax in test * Update src/plasmapy/formulary/laser.py Co-authored-by: Joseph Smith <11745431+josephrhsmith@users.noreply.github.com> * Update src/plasmapy/formulary/laser.py Co-authored-by: Joseph Smith <11745431+josephrhsmith@users.noreply.github.com> * fix documentation * fix test labels * fix import * fix typo in function name * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * fix syntax * fix syntax * add more test cases * fix syntax * fix syntax * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * fix formatting and syntax * fix documentation * fix function name * fix parameter name * add more digits to test cases * fix test cases * Update src/plasmapy/formulary/laser.py Co-authored-by: Nick Murphy * Update src/plasmapy/formulary/laser.py Co-authored-by: Nick Murphy * descriptive function names and reduced aliases * making function name consistent * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * fix function name * change function name * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * edited documentation * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * edit funtion name * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * fix typo in references to functions * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Make normalized_vector_array return a float or ndarray ...since the return value is dimensionless. * Update tests for normalized_vector_potential --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Joseph Smith <11745431+josephrhsmith@users.noreply.github.com> Co-authored-by: Nick Murphy Co-authored-by: Nick Murphy --- changelog/3036.feature.rst | 1 + docs/bibliography.bib | 9 + src/plasmapy/formulary/laser.py | 367 +++++++++++++++++++++++++++++++- tests/formulary/test_laser.py | 367 +++++++++++++++++++++++++++++++- 4 files changed, 741 insertions(+), 3 deletions(-) create mode 100644 changelog/3036.feature.rst diff --git a/changelog/3036.feature.rst b/changelog/3036.feature.rst new file mode 100644 index 0000000000..26ccc29a04 --- /dev/null +++ b/changelog/3036.feature.rst @@ -0,0 +1 @@ +Added functions for calculating `~plasmapy.formulary.laser.em_wavelength` from `~plasmapy.formulary.laser.em_angular_frequency` and vice versa, `~plasmapy.formulary.laser.Gaussian_beam_waist_radius` from `~plasmapy.formulary.laser.Gaussian_spot_size_FWHM` and vice versa, `~plasmapy.formulary.laser.Gaussian_power`, `~plasmapy.formulary.laser.Gaussian_Rayleigh_length`, and `~plasmapy.formulary.laser.normalized_vector_potential` to `plasmapy.formulary.laser`. diff --git a/docs/bibliography.bib b/docs/bibliography.bib index 5b4e6dff12..39f3cc4ec6 100644 --- a/docs/bibliography.bib +++ b/docs/bibliography.bib @@ -195,6 +195,15 @@ @article{gericke:2002 pages = 036418, doi = {10.1103/PhysRevE.65.036418} } +@inproceedings{gibbon:2016, + title = {{Introduction to Plasma Physics}}, + author = {P. Gibbons}, + year = 2016, + booktitle = {Proceedings of the 2014 CAS-CERN Accelerator School: Plasma Wake Acceleration}, + publisher = {CERN}, + pages = {51 - 65}, + doi = {10.5170/CERN-2016-001.51}, +} @article{hasegawa:1982, title = {{Alfven wave. DOE Critical Review Series}}, author = {A. Hasegawa and C. Uberoi}, diff --git a/src/plasmapy/formulary/laser.py b/src/plasmapy/formulary/laser.py index 40fe7c14be..bbd6927aea 100644 --- a/src/plasmapy/formulary/laser.py +++ b/src/plasmapy/formulary/laser.py @@ -7,14 +7,27 @@ """ __all__ = [ + "em_angular_frequency", "electric_field_amplitude", "intensity", + "normalized_vector_potential", + "Gaussian_beam_waist_radius", + "Gaussian_power", + "Gaussian_Rayleigh_length", + "Gaussian_spot_size_FWHM", + "em_wavelength", +] +__aliases__ = [ + "a0_", + "omega_", + "E0_", + "I_", + "w0_", ] -__aliases__ = ["E0_", "I_"] import astropy.units as u import numpy as np -from astropy.constants.si import c, eps0 +from astropy.constants.si import c, e, eps0, m_e from plasmapy.utils.decorators import validate_quantities @@ -119,3 +132,353 @@ def intensity( I_ = intensity """Alias to `~plasmapy.formulary.laser.intensity`.""" + + +@validate_quantities( + angular_frequency={"can_be_negative": False}, +) +def em_wavelength(angular_frequency: u.Quantity[u.rad / u.s]) -> u.Quantity[u.m]: + r""" + Calculate the wavelength of a laser :math:`\lambda` given the + the angular frequency :math:`\omega`. + + The wavelength of an electromagnetic wave :math:`\lambda` + is calculated using: + + .. math:: + \lambda = \frac{2\pi c}{\omega}, + + where :math:`\omega` is the angular frequency of the beam. + + Parameters + ---------- + angular_frequency : `~astropy.units.Quantity` + angular frequency of the laser beam (convertible to rad / s). + + Returns + ------- + wavelength : `~astropy.units.Quantity` + The wavelength of a laser with a given angular frequency. + + Notes + ----- + For details, see :cite:t:`ling:2016`\ . + + Examples + -------- + >>> import astropy.units as u + >>> em_wavelength(2.354307546e15 * u.rad / u.s) + + """ + return (2 * np.pi * c / angular_frequency).to( + u.m, equivalencies=u.dimensionless_angles() + ) + + +@validate_quantities( + wavelength={"can_be_negative": False}, +) +def em_angular_frequency(wavelength: u.Quantity[u.m]) -> u.Quantity[u.rad / u.s]: + r""" + Calculate the angular frequency :math:`\omega` of a laser given the + the wavelength of the beam :math:`\lambda`. + + The angular frequency of a wave :math:`\omega` + can be calculated using: + + .. math:: + \omega = \frac{2\pi c}{\lambda}, + + where :math:`\lambda` is the wavelength of the beam and :math:`c` is the speed of light. + + **Aliases:** `omega_` + + Parameters + ---------- + wavelength : `~astropy.units.Quantity` + Wavelength of the laser beam (convertible to m). + + Returns + ------- + omega_0 : `~astropy.units.Quantity` + The angular frequency of a laser with a given wavelength. + + Notes + ----- + For details, see :cite:t:`ling:2016`\ . + + Examples + -------- + >>> import astropy.units as u + >>> em_angular_frequency(800 * u.nm) + + """ + return ((c / wavelength) * 2 * np.pi).to( + u.rad / u.s, equivalencies=u.dimensionless_angles() + ) + + +omega_ = em_angular_frequency +"""Alias to `~plasmapy.formulary.laser.em_angular_frequency`.""" + + +@validate_quantities( + intensity={"can_be_negative": False}, + wavelength={"can_be_negative": False}, +) +def normalized_vector_potential( + intensity: u.Quantity[u.watt / u.m**2], + wavelength: u.Quantity[u.m], +) -> float | np.ndarray: + r""" + Calculate the normalized vector potential :math:`a_0` from the intensity :math:`I` + and the wavelength :math:`\lambda`. + + The normalized vector potential is also known as a dimensionless oscillation amplitude, + quiver velocity, or normalized quiver momentum of an electron. + + The normalized vector potential of a laser + is calculated using: + + .. math:: + a_0= \frac{e E_0}{m_e \omega c}=\frac{e \lambda}{m_e \pi} \sqrt{\frac{I} {2 \epsilon_0 c^5}}, + + where :math:`e` is the fudamental charge, + :math:`E_0` is the electric field amplitude, + :math:`m_e` is the mass of an electron, + :math:`\omega` is the angular frequency of the electromagnetic wave, + :math:`c` is the speed of light, + :math:`\lambda` is the wavelength, + :math:`I` is the intensity of the elecromagnetic wave, and + :math:`\epsilon_0` is the permitivity of free space. + + **Aliases:** `a0_` + + Parameters + ---------- + intensity : `~astropy.units.Quantity` + Intensity of the laser pulse (convertible to W / m\ :sup:`2`). + + wavelength : `~astropy.units.Quantity` + Wavelength of the laser (convertible to m). + + Returns + ------- + a_0 : float | numpy.ndarray + The normalized vector potential of a plasma given the intensity and wavelength of + a laser. + + Notes + ----- + For details, see :cite:t:`gibbon:2016`\ . + + Examples + -------- + >>> import astropy.units as u + >>> normalized_vector_potential(1e18 * u.watt / u.cm**2, 1 * u.um) + np.float64(0.8549297...) + """ + + a0 = (e * wavelength * np.sqrt(intensity / (2 * eps0 * c**5))) / (m_e * np.pi) + return a0.to(u.dimensionless_unscaled).value # type: ignore[no-any-return] + + +a0_ = normalized_vector_potential +"""Alias to `~plasmapy.formulary.laser.normalized_vector_potential`.""" + + +@validate_quantities( + intensity={"can_be_negative": False}, + beam_waist_radius={"can_be_negative": False}, +) +def Gaussian_power( + intensity: u.Quantity[u.watt / u.m**2], + beam_waist_radius: u.Quantity[u.m], +) -> u.Quantity[u.Watt]: + r""" + Calculate the total power of a Gaussian beam :math:`P_0` from the intensity :math:`I` + and the beam waist radius :math:`w_0`. + + The total power of a Gaussian beam + is calculated using: + + .. math:: + P_0=\frac{1}{2}I_0 \pi w_0^2, + + where :math:`w_0` is the beam waist radius and + :math:`I_0` is the intensity of the beam. + + Parameters + ---------- + intensity : `~astropy.units.Quantity` + Intensity of the laser pulse (convertible to W / m\ :sup:`2`). + beam_waist_radius : `~astropy.units.Quantity` + Beam waist of the laser pulse (convertible to m). + + Returns + ------- + P_0 : `~astropy.units.Quantity` + The total power of the Gaussian beam for the given intensity + and spot size. + + Notes + ----- + For details, see :wikipedia:`Gaussian beam`\ . + + Examples + -------- + >>> import astropy.units as u + >>> Gaussian_power(1e18 * u.watt / u.cm**2, 1 * u.um) # Total beam power + + """ + + return (1 / 2) * intensity * np.pi * beam_waist_radius**2 + + +@validate_quantities( + spot_size_FWHM={"can_be_negative": False}, +) +def Gaussian_beam_waist_radius(spot_size_FWHM: u.Quantity[u.m]) -> u.Quantity[u.m]: + r""" + Calculate the beam waist radius :math:`w_0` for the intensity profile + of a Gaussian beam given the Full Width at Half Maximum spot size :math:`FWHM`. + + At focus, :math:`w_0` is the transverse distance from the center of the beam + to where the intensity drops by a factor of :math:`1/e^2`. + + The beam waist radius of a Gaussian beam + is calculated using: + + .. math:: + w_0=\frac{FWHM}{\sqrt{2 \ln {2}}}, + + where :math:`FWHM` is the full width at half maximum spot size of the beam. + + **Aliases:** `w0_` + + Parameters + ---------- + spot_size_FWHM : `~astropy.units.Quantity` + Full Width at Half Maximum spot size of the Gaussian beam (convertible to m). + + Returns + ------- + w_0 : `~astropy.units.Quantity` + The beam waist radius of the Gaussian beam for the given FWHM spot size. + + See Also + -------- + Gaussian_spot_size_FWHM + + Notes + ----- + For details, see :wikipedia:`Gaussian beam`\ . + + Examples + -------- + >>> import astropy.units as u + >>> Gaussian_beam_waist_radius(8.242 * u.um) + + """ + return spot_size_FWHM / np.sqrt(2 * np.log(2)) + + +w0_ = Gaussian_beam_waist_radius +"""Alias to `~plasmapy.formulary.laser.Gaussian_beam_waist_radius`.""" + + +@validate_quantities( + beam_waist_radius={"can_be_negative": False}, +) +def Gaussian_spot_size_FWHM(beam_waist_radius: u.Quantity[u.m]) -> u.Quantity[u.m]: + r""" + Calculate the Full Width at Half Maximum spot size :math:`FWHM` at focus given the + beam waist radius of a Gaussian beam :math:`w_0`. + + The FWHM spot size of a Gaussian beam + is calculated using: + + .. math:: + FWHM = w_0 \sqrt{2 \ln {2}}, + + where :math:`w_0` is the beam waist radius of the beam. + + Parameters + ---------- + beam_waist_radius : `~astropy.units.Quantity` + beam waist radius of the Gaussian beam (convertible to nm). + + Returns + ------- + FWHM : `~astropy.units.Quantity` + The FWHM spot size of the Gaussian beam for the given beam waist. + + See Also + -------- + Gaussian_beam_waist_radius + + Notes + ----- + For details, see :wikipedia:`Gaussian beam`\ . + + Examples + -------- + >>> import astropy.units as u + >>> Gaussian_spot_size_FWHM(7 * u.um) + + """ + return beam_waist_radius * np.sqrt(2 * np.log(2)) + + +# use kwargs +@validate_quantities( + wavelength={"can_be_negative": False}, + beam_waist_radius={"can_be_negative": False}, +) +def Gaussian_Rayleigh_length( + wavelength: u.Quantity[u.m], + beam_waist_radius: u.Quantity[u.m], +) -> u.Quantity[u.m]: + r""" + Calculate the Rayleigh length :math:`z_R` from the beam waist radius :math:`w_0` + and the wavelength :math:`\lambda`. + + The Rayleigh length of a Gaussian beam + is calculated using: + + .. math:: + z_R=\frac{\pi w_0 ^2}{\lambda}, + + where :math:`w_0` is the beam waist and + :math:`\lambda` is the wavelength of the beam. + + Parameters + ---------- + wavelength : `~astropy.units.Quantity` + Wavelength of the laser pulse (convertible to m). + beam_waist_radius : `~astropy.units.Quantity` + Beam waist of the laser pulse (convertible to m). + + Returns + ------- + z_R : `~astropy.units.Quantity` + The Rayleigh length of the Gaussian beam for the given wavelength + and beam waist. + + See Also + -------- + Gaussian_beam_waist_radius + Gaussian_spot_size_FWHM + + Notes + ----- + For details, see :wikipedia:`Rayleigh Length`\ . + + Examples + -------- + >>> import astropy.units as u + >>> Gaussian_Rayleigh_length(800 * u.nm, 1 * u.um) + + """ + + return (np.pi * beam_waist_radius**2) / wavelength diff --git a/tests/formulary/test_laser.py b/tests/formulary/test_laser.py index 9abf970a19..05fc7af3b5 100644 --- a/tests/formulary/test_laser.py +++ b/tests/formulary/test_laser.py @@ -5,7 +5,22 @@ import pytest from astropy.tests.helper import assert_quantity_allclose -from plasmapy.formulary.laser import E0_, I_, electric_field_amplitude, intensity +from plasmapy.formulary.laser import ( + E0_, + I_, + Gaussian_beam_waist_radius, + Gaussian_power, + Gaussian_Rayleigh_length, + Gaussian_spot_size_FWHM, + a0_, + electric_field_amplitude, + em_angular_frequency, + em_wavelength, + intensity, + normalized_vector_potential, + omega_, + w0_, +) @pytest.mark.parametrize( @@ -51,6 +66,9 @@ def test_electric_field_amplitude_warnings(intensity, expected_warning) -> None: [ (E0_, electric_field_amplitude), (I_, intensity), + (w0_, Gaussian_beam_waist_radius), + (omega_, em_angular_frequency), + (a0_, normalized_vector_potential), ], ) def test_aliases(alias, parent) -> None: @@ -94,3 +112,350 @@ def test_intensity_errors(electric_field_amplitude, expected) -> None: def test_intensity_warnings(electric_field_amplitude, expected_warning) -> None: with pytest.warns(expected_warning): intensity(electric_field_amplitude=electric_field_amplitude) + + +@pytest.mark.parametrize( + ("intensity", "beam_waist_radius", "expected"), + [ + (1e-3 * u.watt / u.m**2, 1e-6 * u.m, 1.5707963267948967e-15 * u.Watt), + ( + [1, 1e21] * u.milliWatt / u.m**2, + [1, 1] * u.um, + [1.5707963267948967e-15, 1570796.3267948967] * u.Watt, + ), + ( + [1, 1] * u.milliWatt / u.m**2, + [1, 10] * u.um, + [1.5707963267948967e-15, 1.5707963267948967e-13] * u.Watt, + ), + ( + 1 * u.milliWatt / u.m**2, + [1, 10] * u.um, + [1.5707963267948967e-15, 1.5707963267948967e-13] * u.Watt, + ), + ( + [1, 1e21] * u.milliWatt / u.m**2, + 1 * u.um, + [1.5707963267948967e-15, 1570796.3267948967] * u.Watt, + ), + (0 * u.watt / u.m**2, 1e-6 * u.m, 0 * u.Watt), + (1e-3 * u.watt / u.m**2, 0 * u.m, 0 * u.Watt), + (np.nan * u.watt / u.m**2, np.nan * u.m, np.nan * u.Watt), + ], +) +@pytest.mark.filterwarnings("ignore::astropy.units.UnitsWarning") +def test_Gaussian_power(intensity, beam_waist_radius, expected) -> None: + result = Gaussian_power(intensity=intensity, beam_waist_radius=beam_waist_radius) + assert_quantity_allclose(result, expected, rtol=1e-6, equal_nan=True, verbose=True) + assert result.unit == u.Watt + + +@pytest.mark.parametrize( + ("intensity", "beam_waist_radius", "expected"), + [ + (-5e4 * u.Watt / u.m**2, 2 * u.m, ValueError), + (5e4 * u.Watt / u.m**2, -2 * u.m, ValueError), + (1 * u.kg, 3 * u.s, u.UnitTypeError), + ], +) +def test_Gaussian_power_errors(intensity, beam_waist_radius, expected) -> None: + with pytest.raises(expected): + Gaussian_power(intensity=intensity, beam_waist_radius=beam_waist_radius) + + +@pytest.mark.parametrize( + ("intensity", "beam_waist_radius", "expected_warning"), + [(5, 2 * u.um, u.UnitsWarning), (5 * u.Watt / u.m**2, 2, u.UnitsWarning)], +) +def test_Gaussian_power_errors_warnings( + intensity, beam_waist_radius, expected_warning +) -> None: + with pytest.warns(expected_warning): + Gaussian_power(intensity=intensity, beam_waist_radius=beam_waist_radius) + + +@pytest.mark.parametrize( + ("spot_size_FWHM", "expected"), + [ + (8.242e-6 * u.m, 7.00011e-6 * u.m), + ([8.242, 0] * u.um, [7.00011e-6, 0] * u.m), + (np.nan * u.m, np.nan * u.m), + ], +) +@pytest.mark.filterwarnings("ignore::astropy.units.UnitsWarning") +def test_Gaussian_beam_waist_radius(spot_size_FWHM, expected) -> None: + result = Gaussian_beam_waist_radius(spot_size_FWHM=spot_size_FWHM) + assert_quantity_allclose(result, expected, rtol=1e-6, equal_nan=True, verbose=True) + assert result.unit == u.m + + +@pytest.mark.parametrize( + ("spot_size_FWHM", "expected"), + [ + (-5e4 * u.m, ValueError), + (1 * u.kg, u.UnitTypeError), + ], +) +def test_Gaussian_beam_waist_radius_errors(spot_size_FWHM, expected) -> None: + with pytest.raises(expected): + Gaussian_beam_waist_radius(spot_size_FWHM=spot_size_FWHM) + + +@pytest.mark.parametrize( + ("spot_size_FWHM", "expected_warning"), + [ + (5, u.UnitsWarning), + ], +) +def test_Gaussian_beam_waist_radius_warnings(spot_size_FWHM, expected_warning) -> None: + with pytest.warns(expected_warning): + Gaussian_beam_waist_radius(spot_size_FWHM=spot_size_FWHM) + + +@pytest.mark.parametrize( + ("beam_waist_radius", "expected"), + [ + (7e-6 * u.m, 8.24187e-6 * u.m), + ([7, 0] * u.um, [8.24187e-6, 0] * u.m), + (np.nan * u.m, np.nan * u.m), + ], +) +@pytest.mark.filterwarnings("ignore::astropy.units.UnitsWarning") +def test_Gaussian_spot_size_FWHM(beam_waist_radius, expected) -> None: + result = Gaussian_spot_size_FWHM(beam_waist_radius=beam_waist_radius) + assert_quantity_allclose(result, expected, rtol=1e-6, equal_nan=True, verbose=True) + assert result.unit == u.m + + +@pytest.mark.parametrize( + ("beam_waist_radius", "expected"), + [ + (-5e4 * u.m, ValueError), + (1 * u.kg, u.UnitTypeError), + ], +) +def test_Gaussian_spot_size_FWHM_errors(beam_waist_radius, expected) -> None: + with pytest.raises(expected): + Gaussian_spot_size_FWHM(beam_waist_radius=beam_waist_radius) + + +@pytest.mark.parametrize( + ("beam_waist_radius", "expected_warning"), + [ + (5, u.UnitsWarning), + ], +) +def test_Gaussian_spot_size_FWHM_warnings(beam_waist_radius, expected_warning) -> None: + with pytest.warns(expected_warning): + Gaussian_spot_size_FWHM(beam_waist_radius=beam_waist_radius) + + +@pytest.mark.parametrize( + ("angular_frequency", "expected"), + [ + (2.354307546e15 * u.rad / u.s, 800.0873e-9 * u.m), + ([2.354307546, 0] * u.Prad / u.s, [800.0873e-9, np.inf] * u.m), + (np.nan * u.rad / u.s, np.nan * u.m), + ], +) +@pytest.mark.filterwarnings("ignore::astropy.units.UnitsWarning") +def test_em_wavelength(angular_frequency, expected) -> None: + result = em_wavelength(angular_frequency=angular_frequency) + assert_quantity_allclose(result, expected, rtol=1e-6, equal_nan=True, verbose=True) + assert result.unit == u.m + + +@pytest.mark.parametrize( + ("angular_frequency", "expected"), + [ + (-5e4 * u.rad / u.s, ValueError), + (1 * u.kg, u.UnitTypeError), + ], +) +def test_em_wavelength_errors(angular_frequency, expected) -> None: + with pytest.raises(expected): + em_wavelength(angular_frequency=angular_frequency) + + +@pytest.mark.parametrize( + ("angular_frequency", "expected_warning"), + [ + (5, u.UnitsWarning), + ], +) +def test_em_wavelength_warnings(angular_frequency, expected_warning) -> None: + with pytest.warns(expected_warning): + em_wavelength(angular_frequency=angular_frequency) + + +@pytest.mark.parametrize( + ("wavelength", "expected"), + [ + (800e-9 * u.m, 2.354564e15 * u.rad / u.s), + ([800, 0] * u.nm, [2.354564e15, np.inf] * u.rad / u.s), + (np.nan * u.m, np.nan * u.rad / u.s), + ], +) +@pytest.mark.filterwarnings("ignore::astropy.units.UnitsWarning") +def test_em_angular_frequency(wavelength, expected) -> None: + result = em_angular_frequency(wavelength=wavelength) + assert_quantity_allclose(result, expected, rtol=1e-6, equal_nan=True, verbose=True) + assert result.unit == u.rad / u.s + + +@pytest.mark.parametrize( + ("wavelength", "expected"), + [ + (-5e4 * u.m, ValueError), + (1 * u.kg, u.UnitTypeError), + ], +) +def test_em_angular_frequency_errors(wavelength, expected) -> None: + with pytest.raises(expected): + em_angular_frequency(wavelength=wavelength) + + +@pytest.mark.parametrize( + ("wavelength", "expected_warning"), + [ + (5, u.UnitsWarning), + ], +) +def test_em_angular_frequency_warning(wavelength, expected_warning) -> None: + with pytest.warns(expected_warning): + em_angular_frequency(wavelength=wavelength) + + +@pytest.mark.parametrize( + ("intensity", "wavelength", "expected"), + [ + (1e-3 * u.watt / u.m**2, 800e-9 * u.m, 2.162820076644342e-13), + ( + [1, 1e-3] * u.milliWatt / u.m**2, + [800, 800] * u.nm, + [2.162820076644342e-13, 6.839437611336064e-15], + ), + ( + [1, 1] * u.milliWatt / u.m**2, + [800, 650] * u.nm, + [2.162820076644342e-13, 1.7572913122735275e-13], + ), + ( + [1, 1e-3] * u.milliWatt / u.m**2, + 800 * u.nm, + [2.162820076644342e-13, 6.839437611336064e-15], + ), + ( + 1 * u.milliWatt / u.m**2, + [800, 650] * u.nm, + [2.162820076644342e-13, 1.7572913122735275e-13], + ), + (0 * u.watt / u.m**2, 800e-9 * u.m, 0), + (1e-3 * u.watt / u.m**2, 0 * u.m, 0), + (np.nan * u.Watt / u.m**2, np.nan * u.m, np.nan), + ], +) +@pytest.mark.filterwarnings("ignore::astropy.units.UnitsWarning") +def test_normalized_vector_potential(intensity, wavelength, expected) -> None: + result = normalized_vector_potential(intensity=intensity, wavelength=wavelength) + assert_quantity_allclose(result, expected, rtol=1e-6, equal_nan=True, verbose=True) + + +# assert result.unit == u.dimensionless_unscaled + + +@pytest.mark.parametrize( + ("intensity", "wavelength", "expected"), + [ + (-5e-3 * u.Watt / u.m**2, 5e4 * u.m, ValueError), + (5e-3 * u.Watt / u.m**2, -5e4 * u.m, ValueError), + (7 * u.s, 1 * u.kg, u.UnitTypeError), + ], +) +def test_normalized_vector_potential_errors(intensity, wavelength, expected) -> None: + with pytest.raises(expected): + normalized_vector_potential(intensity=intensity, wavelength=wavelength) + + +@pytest.mark.parametrize( + ("intensity", "wavelength", "expected_warning"), + [ + (3, 5, u.UnitsWarning), + ], +) +def test_normalized_vector_potential_warning( + intensity, wavelength, expected_warning +) -> None: + with pytest.warns(expected_warning): + normalized_vector_potential(intensity=intensity, wavelength=wavelength) + + +@pytest.mark.parametrize( + ("wavelength", "beam_waist_radius", "expected"), + [ + (800e-9 * u.m, 1e-6 * u.m, 3.926990816987241e-06 * u.m), + ( + [800, 650] * u.nm, + [1, 1] * u.um, + [3.926990816987241e-06, 4.8332194670612195e-06] * u.m, + ), + ( + [800, 800] * u.nm, + [1, 20] * u.um, + [3.926990816987241e-06, 0.0015707963267948962] * u.m, + ), + ( + [800, 650] * u.nm, + 1 * u.um, + [3.926990816987241e-06, 4.8332194670612195e-06] * u.m, + ), + ( + 800 * u.nm, + [1, 20] * u.um, + [3.926990816987241e-06, 0.0015707963267948962] * u.m, + ), + (800e-9 * u.m, 0 * u.m, 0 * u.m), + (0 * u.m, 1e-6 * u.m, np.inf * u.m), + (np.nan * u.m, np.nan * u.m, np.nan * u.m), + ], +) +@pytest.mark.filterwarnings("ignore::astropy.units.UnitsWarning") +def test_Gaussian_Rayleigh_length(wavelength, beam_waist_radius, expected) -> None: + result = Gaussian_Rayleigh_length( + wavelength=wavelength, beam_waist_radius=beam_waist_radius + ) + assert_quantity_allclose(result, expected, rtol=1e-6, equal_nan=True, verbose=True) + assert result.unit == u.m + + +@pytest.mark.parametrize( + ("wavelength", "beam_waist_radius", "expected"), + [ + (-5e4 * u.m, 2 * u.m, ValueError), + (5e4 * u.m, -2 * u.m, ValueError), + (1 * u.kg, 3 * u.s, u.UnitTypeError), + ], +) +def test_Gaussian_Rayleigh_length_errors( + wavelength, beam_waist_radius, expected +) -> None: + with pytest.raises(expected): + Gaussian_Rayleigh_length( + wavelength=wavelength, beam_waist_radius=beam_waist_radius + ) + + +@pytest.mark.parametrize( + ("wavelength", "beam_waist_radius", "expected_warning"), + [ + (5 * u.m, 2, u.UnitsWarning), + (5, 2 * u.m, u.UnitsWarning), + ], +) +def test_Rayleigh_length_warnings_warnings( + wavelength, beam_waist_radius, expected_warning +) -> None: + with pytest.warns(expected_warning): + Gaussian_Rayleigh_length( + wavelength=wavelength, beam_waist_radius=beam_waist_radius + ) From 35c5442cd8ceb3d3fb15b83bfc210547b8cd04be Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 26 Jun 2025 16:27:12 -0700 Subject: [PATCH 347/521] use np.isclose to identify voltage steps near voltage_step_size --- src/plasmapy/analysis/swept_langmuir/helpers.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/plasmapy/analysis/swept_langmuir/helpers.py b/src/plasmapy/analysis/swept_langmuir/helpers.py index eaf149acd7..ad0196f86d 100644 --- a/src/plasmapy/analysis/swept_langmuir/helpers.py +++ b/src/plasmapy/analysis/swept_langmuir/helpers.py @@ -327,7 +327,9 @@ def _merge_voltage_clusters__within_dv( voltage_diff = np.diff(voltage) # generate global cluster mask - cluster_mask = voltage_diff <= voltage_step_size + mask1 = voltage_diff < voltage_step_size + mask2 = np.isclose(voltage_diff, voltage_step_size) + cluster_mask = np.logical_or(mask1, mask2) cluster_mask = np.append(cluster_mask, [cluster_mask[-1]]) cluster_mask[1:] = np.logical_or(cluster_mask[1:], np.roll(cluster_mask, 1)[1:]) From ebd10461e4fb8de2b526a15a85a7009ce07c3c7f Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 26 Jun 2025 16:27:48 -0700 Subject: [PATCH 348/521] if voltage_steps_size is None default to 95% of average step size --- src/plasmapy/analysis/swept_langmuir/helpers.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/plasmapy/analysis/swept_langmuir/helpers.py b/src/plasmapy/analysis/swept_langmuir/helpers.py index ad0196f86d..907afb9e15 100644 --- a/src/plasmapy/analysis/swept_langmuir/helpers.py +++ b/src/plasmapy/analysis/swept_langmuir/helpers.py @@ -420,9 +420,9 @@ def merge_voltage_clusters( # noqa: C901, PLR0912 voltage_step_size: `float` or `None` A non-zero, positive step size for the ``voltage`` array cluster identification. A value of ``0`` will merge only - duplicate voltage values. A value of `None` will default to the - average step size of the ``voltage`` array (only counting - duplicate voltages once). (DEFAULT:`None`) + duplicate voltage values. A value of `None` will default to + 95% of the average step size of the ``voltage`` array (only + counting duplicate voltages once). (DEFAULT:`None`) Returns ------- @@ -479,7 +479,7 @@ def merge_voltage_clusters( # noqa: C901, PLR0912 # condition voltage_step_size ... Round 2 if voltage_step_size is None: - voltage_step_size = np.abs( + voltage_step_size = 0.95 * np.abs( np.average(voltage_diff[np.logical_not(mask_zero_diff)]) ) elif voltage_step_size == 0: From cf8e7c687dbf30286a579fccfa172470278d71fc Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 26 Jun 2025 16:28:57 -0700 Subject: [PATCH 349/521] modify cluster binning to accounts for clusters sizes that are close to integer multiples of voltage_step_size --- src/plasmapy/analysis/swept_langmuir/helpers.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/plasmapy/analysis/swept_langmuir/helpers.py b/src/plasmapy/analysis/swept_langmuir/helpers.py index 907afb9e15..1704e7df36 100644 --- a/src/plasmapy/analysis/swept_langmuir/helpers.py +++ b/src/plasmapy/analysis/swept_langmuir/helpers.py @@ -360,7 +360,11 @@ def _merge_voltage_clusters__within_dv( sub_voltage = voltage[start_index:stop_index] sub_current = current[start_index:stop_index] - nbins = int(np.floor((sub_voltage[-1] - sub_voltage[0]) / voltage_step_size)) + v_range = sub_voltage[-1] - sub_voltage[0] + nbins = int(np.rint(v_range / voltage_step_size)) + if not np.isclose(nbins - (v_range / voltage_step_size), 0): + nbins = int(np.floor((sub_voltage[-1] - sub_voltage[0]) / voltage_step_size)) + if nbins == 0: nbins = 1 From adaea82857b142a5f5498ba77cf1bc8d8ec1c9f7 Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 26 Jun 2025 16:29:36 -0700 Subject: [PATCH 350/521] only consider voltage regularly spaced if the largest step is less than 10x the smallest step --- src/plasmapy/analysis/swept_langmuir/helpers.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/plasmapy/analysis/swept_langmuir/helpers.py b/src/plasmapy/analysis/swept_langmuir/helpers.py index 1704e7df36..93b4a5c9e3 100644 --- a/src/plasmapy/analysis/swept_langmuir/helpers.py +++ b/src/plasmapy/analysis/swept_langmuir/helpers.py @@ -261,7 +261,10 @@ def _is_voltage_regularly_spaced( 0, ): # grid has a common dV, but at times jumps N * dV times - is_regular_grid = True + min_dV = np.min(voltage_diff) + ndV = np.rint(voltage_diff / min_dV) + + is_regular_grid = False if np.any(ndV > 10) else True return is_regular_grid From 49ffb543647f455fdecfc239efe292c535c45515 Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 26 Jun 2025 16:29:46 -0700 Subject: [PATCH 351/521] add test cases --- .../test_helpers__merge_voltage_clusters.py | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/tests/analysis/swept_langmuir/test_helpers__merge_voltage_clusters.py b/tests/analysis/swept_langmuir/test_helpers__merge_voltage_clusters.py index 3bc6aba06d..d772ee96d6 100644 --- a/tests/analysis/swept_langmuir/test_helpers__merge_voltage_clusters.py +++ b/tests/analysis/swept_langmuir/test_helpers__merge_voltage_clusters.py @@ -105,6 +105,38 @@ np.array([-5., -4, 0, 5, 7], dtype=float), ), ), + ( # multiple voltage clusters, including at beginning and end + np.array( + [1, 1.01, 1.05, 1.5, 2, 3.88, 3.9, 3.92, 4.8, 5.5, 5.55], + dtype=float, + ), + np.array( + [-5, -5.1, -4.9, -4, -3, 0, 0.1, -0.1, 5, 7, 6.9], + dtype=float, + ), + {"voltage_step_size": 0.1}, + does_not_raise(), + ( + np.array([1.02, 1.5, 2, 3.9, 4.8, 5.525], dtype=float), + np.array([-5., -4, -3, 0, 5, 6.95], dtype=float), + ), + ), + ( # self determine voltage_step_size + np.array( + [1, 1.01, 1.05, 1.5, 2, 3.88, 3.9, 3.92, 4.8, 5.5, 5.55], + dtype=float, + ), + np.array( + [-5, -5.1, -4.9, -4, -3, 0, 0.1, -0.1, 5, 7, 6.9], + dtype=float, + ), + {"voltage_step_size": None}, + does_not_raise(), + ( + np.array([1.02, 1.5, 2, 3.9, 4.8, 5.525], dtype=float), + np.array([-5., -4, -3, 0, 5, 6.95], dtype=float), + ), + ), ], ) def test_merge_voltage_clusters( From 6a4eb395eaff606218cad79c4b13de2391a5f278 Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 26 Jun 2025 16:38:36 -0700 Subject: [PATCH 352/521] enforce the voltage array needs to be monotonically ascending --- .../analysis/swept_langmuir/helpers.py | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/src/plasmapy/analysis/swept_langmuir/helpers.py b/src/plasmapy/analysis/swept_langmuir/helpers.py index 93b4a5c9e3..d1603e602a 100644 --- a/src/plasmapy/analysis/swept_langmuir/helpers.py +++ b/src/plasmapy/analysis/swept_langmuir/helpers.py @@ -414,8 +414,9 @@ def merge_voltage_clusters( # noqa: C901, PLR0912 ---------- voltage: `numpy.ndarray` 1D `numpy.ndarray` representing the voltage of the swept - Langmuir trace. *No units are assumed or checked, but values - should be in volts.* + Langmuir trace. Voltage needs to be monotonically ascending. + *No units are assumed or checked, but values should be in + volts.* current: `numpy.ndarray` 1D `numpy.ndarray` representing the current of the swept @@ -505,13 +506,6 @@ def merge_voltage_clusters( # noqa: C901, PLR0912 return voltage.copy(), current.copy() - # ensure voltage is ascending for calculation - voltage_ascending = bool(np.all(voltage_diff >= 0)) - if not voltage_ascending: - voltage, current = sort_sweep_arrays( - voltage, current, voltage_order="ascending" - ) - # now merge clusters if voltage_step_size == 0: new_voltage, new_current = _merge_voltage_clusters__zero_diff_neighbors( @@ -523,10 +517,4 @@ def merge_voltage_clusters( # noqa: C901, PLR0912 voltage, current, voltage_step_size ) - if not voltage_ascending: - voltage = voltage[::-1] - current = current[::-1] - new_voltage = new_voltage[::-1] - new_current = new_current[::-1] - return new_voltage, new_current From 02e5b79245ecf51284d42240de6d9c4068452a91 Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 26 Jun 2025 16:48:25 -0700 Subject: [PATCH 353/521] add texttt and nbins to _typos.toml --- _typos.toml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/_typos.toml b/_typos.toml index ac0c24c496..22c2e5515f 100644 --- a/_typos.toml +++ b/_typos.toml @@ -11,3 +11,5 @@ iy = "iy" nd = "nd" rety = "rety" newshape = "newshape" +texttt = "texttt" +nbins = "nbins" From d14ada61b4ddb6c1451b4a276fb4e56714fc4d0a Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 26 Jun 2025 16:50:11 -0700 Subject: [PATCH 354/521] appease grumpy ruff --- src/plasmapy/analysis/swept_langmuir/helpers.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/plasmapy/analysis/swept_langmuir/helpers.py b/src/plasmapy/analysis/swept_langmuir/helpers.py index d1603e602a..6790577ec5 100644 --- a/src/plasmapy/analysis/swept_langmuir/helpers.py +++ b/src/plasmapy/analysis/swept_langmuir/helpers.py @@ -400,7 +400,7 @@ def _merge_voltage_clusters__within_dv( return new_voltage, new_current -def merge_voltage_clusters( # noqa: C901, PLR0912 +def merge_voltage_clusters( voltage: np.ndarray, current: np.ndarray, voltage_step_size: float | None = None, @@ -442,7 +442,6 @@ def merge_voltage_clusters( # noqa: C901, PLR0912 Notes ----- - An identified voltage cluster can span a voltage range larger than ``voltage_step_size`` and still have every voltage step being smaller than ``voltage_step_size``. In this scenario, the voltage From b2dbec44605d6ae311229916190181c839403090 Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 26 Jun 2025 16:51:46 -0700 Subject: [PATCH 355/521] simplify conditional --- src/plasmapy/analysis/swept_langmuir/helpers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plasmapy/analysis/swept_langmuir/helpers.py b/src/plasmapy/analysis/swept_langmuir/helpers.py index 6790577ec5..7caa5f4a1b 100644 --- a/src/plasmapy/analysis/swept_langmuir/helpers.py +++ b/src/plasmapy/analysis/swept_langmuir/helpers.py @@ -264,7 +264,7 @@ def _is_voltage_regularly_spaced( min_dV = np.min(voltage_diff) ndV = np.rint(voltage_diff / min_dV) - is_regular_grid = False if np.any(ndV > 10) else True + is_regular_grid = not np.any(ndV > 10) return is_regular_grid From 15c386baec427d210ca641ec3025e37a83377b14 Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 26 Jun 2025 16:52:31 -0700 Subject: [PATCH 356/521] add noqa --- src/plasmapy/analysis/swept_langmuir/helpers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plasmapy/analysis/swept_langmuir/helpers.py b/src/plasmapy/analysis/swept_langmuir/helpers.py index 7caa5f4a1b..e037696c46 100644 --- a/src/plasmapy/analysis/swept_langmuir/helpers.py +++ b/src/plasmapy/analysis/swept_langmuir/helpers.py @@ -313,7 +313,7 @@ def _merge_voltage_clusters__zero_diff_neighbors( return new_voltage, new_current -def _merge_voltage_clusters__within_dv( +def _merge_voltage_clusters__within_dv( # noqa: C901 voltage: np.ndarray, current: np.ndarray, voltage_step_size: float, From e7091f9643860fd9be3af03160563a649d2aca9c Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 26 Jun 2025 16:54:37 -0700 Subject: [PATCH 357/521] add changelog entry --- changelog/3037.feature.rst | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 changelog/3037.feature.rst diff --git a/changelog/3037.feature.rst b/changelog/3037.feature.rst new file mode 100644 index 0000000000..0b4bbb42aa --- /dev/null +++ b/changelog/3037.feature.rst @@ -0,0 +1,4 @@ +.. currentmodule:: plasmapy.analysis.swept_langmuir + +Added helper function `~helpers.merge_voltage_clusters` to the +`~plasmapy.analysis.swept_langmuir` analysis module. From b4fcb7f307c4af2682d98ecd4dd2b7dcccb86f04 Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 26 Jun 2025 17:01:22 -0700 Subject: [PATCH 358/521] remove unused import --- .../swept_langmuir/test_helpers__merge_voltage_clusters.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/analysis/swept_langmuir/test_helpers__merge_voltage_clusters.py b/tests/analysis/swept_langmuir/test_helpers__merge_voltage_clusters.py index d772ee96d6..f1030fc0dc 100644 --- a/tests/analysis/swept_langmuir/test_helpers__merge_voltage_clusters.py +++ b/tests/analysis/swept_langmuir/test_helpers__merge_voltage_clusters.py @@ -6,7 +6,6 @@ from contextlib import nullcontext as does_not_raise from unittest import mock -import astropy.units as u import numpy as np import pytest From 278c2734d8204ab4d80784376992d4d7fc1c2407 Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 26 Jun 2025 19:16:34 -0700 Subject: [PATCH 359/521] appease grump ruff format --- src/plasmapy/analysis/swept_langmuir/helpers.py | 14 ++++++++------ .../test_helpers__merge_voltage_clusters.py | 16 ++++++++-------- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/src/plasmapy/analysis/swept_langmuir/helpers.py b/src/plasmapy/analysis/swept_langmuir/helpers.py index e037696c46..388801921e 100644 --- a/src/plasmapy/analysis/swept_langmuir/helpers.py +++ b/src/plasmapy/analysis/swept_langmuir/helpers.py @@ -345,10 +345,10 @@ def _merge_voltage_clusters__within_dv( # noqa: C901 indices[0] = indices[0] + 1 if indices.size > 1: indices[2::2] = indices[2::2] + 1 - if cluster_mask[-1] and indices[-1] != voltage.size-1: + if cluster_mask[-1] and indices[-1] != voltage.size - 1: # last element in voltage is in a cluster - indices = np.append(indices, [voltage.size-1]) - indices = np.reshape(indices, newshape=(int(indices.size/2), 2)) + indices = np.append(indices, [voltage.size - 1]) + indices = np.reshape(indices, newshape=(int(indices.size / 2), 2)) # ^ using newshape kwarg for backwards compatability, newshape kwarg # has been deprecated since numpy v2.1 @@ -366,7 +366,9 @@ def _merge_voltage_clusters__within_dv( # noqa: C901 v_range = sub_voltage[-1] - sub_voltage[0] nbins = int(np.rint(v_range / voltage_step_size)) if not np.isclose(nbins - (v_range / voltage_step_size), 0): - nbins = int(np.floor((sub_voltage[-1] - sub_voltage[0]) / voltage_step_size)) + nbins = int( + np.floor((sub_voltage[-1] - sub_voltage[0]) / voltage_step_size) + ) if nbins == 0: nbins = 1 @@ -376,10 +378,10 @@ def _merge_voltage_clusters__within_dv( # noqa: C901 new_current[start_index] = np.average(sub_current) continue - range_array = np.linspace(sub_voltage[0], sub_voltage[-1], nbins+1) + range_array = np.linspace(sub_voltage[0], sub_voltage[-1], nbins + 1) for jj in range(nbins): start_voltage = range_array[jj] - stop_voltage = range_array[jj+1] + stop_voltage = range_array[jj + 1] mask1 = sub_voltage >= start_voltage if jj == nbins - 1: diff --git a/tests/analysis/swept_langmuir/test_helpers__merge_voltage_clusters.py b/tests/analysis/swept_langmuir/test_helpers__merge_voltage_clusters.py index f1030fc0dc..6288f5878f 100644 --- a/tests/analysis/swept_langmuir/test_helpers__merge_voltage_clusters.py +++ b/tests/analysis/swept_langmuir/test_helpers__merge_voltage_clusters.py @@ -33,7 +33,7 @@ None, # same as inputs ), ( # non-zero voltage_step_size < any step size - np.array([1.1, 1.5, 2, 3.8, 6.0, 6.2], dtype=float), + np.array([1.1, 1.5, 2, 3.8, 6.0, 6.2], dtype=float), np.array([-5, -5.2, -2, 0, 4.2, 5], dtype=float), {"voltage_step_size": 0.1}, pytest.warns(PlasmaPyWarning), @@ -90,8 +90,8 @@ {"voltage_step_size": 0.1}, does_not_raise(), ( - np.array([1., 1.15, 1.5, 2, 4, 5.5], dtype=float), - np.array([-5., -5, -4, 0, 5, 7], dtype=float), + np.array([1.0, 1.15, 1.5, 2, 4, 5.5], dtype=float), + np.array([-5.0, -5, -4, 0, 5, 7], dtype=float), ), ), ( # voltage array starts with a cluster, spans < 2 * voltage_step_size @@ -101,12 +101,12 @@ does_not_raise(), ( np.array([1.1, 1.5, 2, 4, 5.5], dtype=float), - np.array([-5., -4, 0, 5, 7], dtype=float), + np.array([-5.0, -4, 0, 5, 7], dtype=float), ), ), ( # multiple voltage clusters, including at beginning and end np.array( - [1, 1.01, 1.05, 1.5, 2, 3.88, 3.9, 3.92, 4.8, 5.5, 5.55], + [1, 1.01, 1.05, 1.5, 2, 3.88, 3.9, 3.92, 4.8, 5.5, 5.55], dtype=float, ), np.array( @@ -117,12 +117,12 @@ does_not_raise(), ( np.array([1.02, 1.5, 2, 3.9, 4.8, 5.525], dtype=float), - np.array([-5., -4, -3, 0, 5, 6.95], dtype=float), + np.array([-5.0, -4, -3, 0, 5, 6.95], dtype=float), ), ), ( # self determine voltage_step_size np.array( - [1, 1.01, 1.05, 1.5, 2, 3.88, 3.9, 3.92, 4.8, 5.5, 5.55], + [1, 1.01, 1.05, 1.5, 2, 3.88, 3.9, 3.92, 4.8, 5.5, 5.55], dtype=float, ), np.array( @@ -133,7 +133,7 @@ does_not_raise(), ( np.array([1.02, 1.5, 2, 3.9, 4.8, 5.525], dtype=float), - np.array([-5., -4, -3, 0, 5, 6.95], dtype=float), + np.array([-5.0, -4, -3, 0, 5, 6.95], dtype=float), ), ), ], From c2b0d76f15950a11a750b21efe5047f05f87e216 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 27 Jun 2025 02:21:25 +0000 Subject: [PATCH 360/521] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- src/plasmapy/analysis/swept_langmuir/helpers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plasmapy/analysis/swept_langmuir/helpers.py b/src/plasmapy/analysis/swept_langmuir/helpers.py index 388801921e..69b35c009b 100644 --- a/src/plasmapy/analysis/swept_langmuir/helpers.py +++ b/src/plasmapy/analysis/swept_langmuir/helpers.py @@ -349,7 +349,7 @@ def _merge_voltage_clusters__within_dv( # noqa: C901 # last element in voltage is in a cluster indices = np.append(indices, [voltage.size - 1]) indices = np.reshape(indices, newshape=(int(indices.size / 2), 2)) - # ^ using newshape kwarg for backwards compatability, newshape kwarg + # ^ using newshape kwarg for backwards compatibility, newshape kwarg # has been deprecated since numpy v2.1 # populate From 91b65432060de002d592bdd3b65c65a2cb2f8be9 Mon Sep 17 00:00:00 2001 From: "plasmapy-requirements-bot[bot]" <134649236+plasmapy-requirements-bot[bot]@users.noreply.github.com> Date: Fri, 27 Jun 2025 13:13:19 -0400 Subject: [PATCH 361/521] Update requirements with 'nox -s requirements' (#3043) Co-authored-by: namurphy <8931994+namurphy@users.noreply.github.com> --- uv.lock | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/uv.lock b/uv.lock index 40cea164b7..e38c97e5b2 100644 --- a/uv.lock +++ b/uv.lock @@ -657,15 +657,15 @@ wheels = [ [[package]] name = "hypothesis" -version = "6.135.14" +version = "6.135.16" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "attrs" }, { name = "sortedcontainers" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/70/a5/d4f74ba61bbe5dd001c998ae8b85f9bfdc6cd29e6c5693d1116847b64251/hypothesis-6.135.14.tar.gz", hash = "sha256:2666df50b3cc40ea08b161a5389d6a1cd5aa3cab0dd8fde0ae339389714a4f67", size = 452884, upload-time = "2025-06-20T19:16:38.199Z" } +sdist = { url = "https://files.pythonhosted.org/packages/3f/91/c8d9af23d6a2a0feb7490ab10a3d78e6ac35ae75887c7fe442d14ad6d6f9/hypothesis-6.135.16.tar.gz", hash = "sha256:6131ea0b698e69bad62aae915988b8d00a6ac974351d0830db74c5fffc68c418", size = 452900, upload-time = "2025-06-26T03:36:33.624Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ce/cf/491a487229b04a2ad56175c74700cfb79635dfce2d942becc6ab10c0ceb9/hypothesis-6.135.14-py3-none-any.whl", hash = "sha256:0dd5b8095e36bd288367c631f864a16c30500b01b17943dcea681233f7421860", size = 519115, upload-time = "2025-06-20T19:16:34.539Z" }, + { url = "https://files.pythonhosted.org/packages/73/e1/196cd69190ba95f2538d577417ac6383a10cb1fabc06917b54e1e437dcaa/hypothesis-6.135.16-py3-none-any.whl", hash = "sha256:0a64697ef0afa4532535209a9bcd99919d59093ff894622e8a001fb773b59d8a", size = 519164, upload-time = "2025-06-26T03:36:30.12Z" }, ] [[package]] @@ -1778,15 +1778,15 @@ wheels = [ [[package]] name = "pybtex" -version = "0.25.0" +version = "0.25.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "latexcodec" }, { name = "pyyaml" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/05/9b/1c5b913cb9121aac0a2f2990ee002b77efc70d969d5d5b179e19564389fe/pybtex-0.25.0.tar.gz", hash = "sha256:10684ffb05af33b041b06dabe15868078fd75847b24e1dffd8dd91348bbb3a4b", size = 358178, upload-time = "2025-06-21T12:03:27.236Z" } +sdist = { url = "https://files.pythonhosted.org/packages/5f/bc/c2be05ca72f8c103670e983df8be26d1e288bc6556f487fa8cccaa27779f/pybtex-0.25.1.tar.gz", hash = "sha256:9eaf90267c7e83e225af89fea65c370afbf65f458220d3946a9e3049e1eca491", size = 406157, upload-time = "2025-06-26T13:27:41.903Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/b6/1d/9979b520b655657cea19523c1340c21f3cbbbe30c1dd03311833fbbad06d/pybtex-0.25.0-py2.py3-none-any.whl", hash = "sha256:bbc211abd458b42c5256d50185ea4f80000f43351959e1d5a3e86cd567a07a6d", size = 127434, upload-time = "2025-06-21T12:03:28.865Z" }, + { url = "https://files.pythonhosted.org/packages/25/68/ceb5d6679baa326261f5d3e5113d9cfed6efef2810afd9f18bffb8ed312b/pybtex-0.25.1-py2.py3-none-any.whl", hash = "sha256:9053b0d619409a0a83f38abad5d9921de5f7b3ede00742beafcd9f10ad0d8c5c", size = 127437, upload-time = "2025-06-26T13:27:43.585Z" }, ] [[package]] @@ -2489,18 +2489,17 @@ wheels = [ [[package]] name = "sphinxcontrib-bibtex" -version = "2.6.4" +version = "2.6.5" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "docutils" }, { name = "pybtex" }, { name = "pybtex-docutils" }, - { name = "setuptools" }, { name = "sphinx" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/96/10/237737925e667e79b18ccd81f4a768306b80847fa24b86786f042484b439/sphinxcontrib_bibtex-2.6.4.tar.gz", hash = "sha256:aad018b730d324201f09777f6c25c4a2ff7ac1d5e66af187f21fc21840768760", size = 118453, upload-time = "2025-06-17T06:41:51.22Z" } +sdist = { url = "https://files.pythonhosted.org/packages/de/83/1488c9879f2fa3c2cbd6f666c7a3a42a1fa9e08462bec73281fa6c092cba/sphinxcontrib_bibtex-2.6.5.tar.gz", hash = "sha256:9b3224dd6fece9268ebd8c905dc0a83ff2f6c54148a9235fe70e9d1e9ff149c0", size = 118462, upload-time = "2025-06-27T10:40:14.061Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/c5/29/9d6fbbd52d7dc6c3cc958187a05cb5d2bf891ee65ac7e8e690b9159103b4/sphinxcontrib_bibtex-2.6.4-py3-none-any.whl", hash = "sha256:bfd34d36322ba0ef0624a1bbee44adcedde86e0fa0ce5b2310304a3e68263f6f", size = 40422, upload-time = "2025-06-17T06:41:49.943Z" }, + { url = "https://files.pythonhosted.org/packages/9e/a0/3a612da94f828f26cabb247817393e79472c32b12c49222bf85fb6d7b6c8/sphinxcontrib_bibtex-2.6.5-py3-none-any.whl", hash = "sha256:455ea4509642ea0b28ede3721550273626f85af65af01f161bfd8e19dc1edd7d", size = 40410, upload-time = "2025-06-27T10:40:12.274Z" }, ] [[package]] From 8e3b5d062b374405b7348cc536c76167fa09513c Mon Sep 17 00:00:00 2001 From: "plasmapy-requirements-bot[bot]" <134649236+plasmapy-requirements-bot[bot]@users.noreply.github.com> Date: Sat, 5 Jul 2025 10:27:22 -0400 Subject: [PATCH 362/521] =?UTF-8?q?Update=20pinned=20requirements=20?= =?UTF-8?q?=F0=9F=93=8D=20(#3049)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update requirements with 'nox -s requirements' * Fix Friday -> Thursday --------- Co-authored-by: namurphy <8931994+namurphy@users.noreply.github.com> Co-authored-by: Nick Murphy --- .github/workflows/update-pinned-reqs.yml | 2 +- uv.lock | 484 +++++++++++++---------- 2 files changed, 269 insertions(+), 217 deletions(-) diff --git a/.github/workflows/update-pinned-reqs.yml b/.github/workflows/update-pinned-reqs.yml index bf142406c4..d4118cca81 100644 --- a/.github/workflows/update-pinned-reqs.yml +++ b/.github/workflows/update-pinned-reqs.yml @@ -2,7 +2,7 @@ name: Update pinned requirements on: schedule: - - cron: 37 11 * * 5 + - cron: 37 11 * * 4 workflow_dispatch: jobs: diff --git a/uv.lock b/uv.lock index e38c97e5b2..df79684e62 100644 --- a/uv.lock +++ b/uv.lock @@ -140,11 +140,11 @@ wheels = [ [[package]] name = "astropy-iers-data" -version = "0.2025.6.23.0.39.50" +version = "0.2025.6.30.0.39.40" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/33/3a/cf170b5a55cd849d0543b929588b4cec326a5e6dde42e41ee7e43c2cff7f/astropy_iers_data-0.2025.6.23.0.39.50.tar.gz", hash = "sha256:3dd7cbf82408837ad21fb15db0c35d0bff19b1552f6b13de48542a246215a754", size = 1900117, upload-time = "2025-06-23T00:40:29.864Z" } +sdist = { url = "https://files.pythonhosted.org/packages/7e/90/52b0ef79e60942b6d241f4fd7bda1203612a21904175a0842797ccac218b/astropy_iers_data-0.2025.6.30.0.39.40.tar.gz", hash = "sha256:511a1bb0185b5eef28dc05d8aecd7d5a7201156370d7bb9bbf439e76ffc33b00", size = 1900718, upload-time = "2025-06-30T00:40:12.067Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/f1/07/3e936628ee19d2eb3e453f30df2f4f038dfff76423c8361001fb075d570d/astropy_iers_data-0.2025.6.23.0.39.50-py3-none-any.whl", hash = "sha256:52f7ed57cdbfcdfe410c78e766caaae84ce75aeabc86df9ed7785b0a52dd274b", size = 1955596, upload-time = "2025-06-23T00:40:28.407Z" }, + { url = "https://files.pythonhosted.org/packages/ac/00/5837d03a5c03c0a3a57b0b37fde73363fe42e7a6d0eca663ec3ab59b8d2c/astropy_iers_data-0.2025.6.30.0.39.40-py3-none-any.whl", hash = "sha256:dea5e1a1d4125246efcb7a58322569f9174371f0ad4d48963a5c3d8ded0dcc3e", size = 1956086, upload-time = "2025-06-30T00:40:10.425Z" }, ] [[package]] @@ -407,56 +407,56 @@ wheels = [ [[package]] name = "coverage" -version = "7.9.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e7/e0/98670a80884f64578f0c22cd70c5e81a6e07b08167721c7487b4d70a7ca0/coverage-7.9.1.tar.gz", hash = "sha256:6cf43c78c4282708a28e466316935ec7489a9c487518a77fa68f716c67909cec", size = 813650, upload-time = "2025-06-13T13:02:28.627Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/60/34/fa69372a07d0903a78ac103422ad34db72281c9fc625eba94ac1185da66f/coverage-7.9.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:95c765060e65c692da2d2f51a9499c5e9f5cf5453aeaf1420e3fc847cc060582", size = 212146, upload-time = "2025-06-13T13:00:48.496Z" }, - { url = "https://files.pythonhosted.org/packages/27/f0/da1894915d2767f093f081c42afeba18e760f12fdd7a2f4acbe00564d767/coverage-7.9.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ba383dc6afd5ec5b7a0d0c23d38895db0e15bcba7fb0fa8901f245267ac30d86", size = 212536, upload-time = "2025-06-13T13:00:51.535Z" }, - { url = "https://files.pythonhosted.org/packages/10/d5/3fc33b06e41e390f88eef111226a24e4504d216ab8e5d1a7089aa5a3c87a/coverage-7.9.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:37ae0383f13cbdcf1e5e7014489b0d71cc0106458878ccde52e8a12ced4298ed", size = 245092, upload-time = "2025-06-13T13:00:52.883Z" }, - { url = "https://files.pythonhosted.org/packages/0a/39/7aa901c14977aba637b78e95800edf77f29f5a380d29768c5b66f258305b/coverage-7.9.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:69aa417a030bf11ec46149636314c24c8d60fadb12fc0ee8f10fda0d918c879d", size = 242806, upload-time = "2025-06-13T13:00:54.571Z" }, - { url = "https://files.pythonhosted.org/packages/43/fc/30e5cfeaf560b1fc1989227adedc11019ce4bb7cce59d65db34fe0c2d963/coverage-7.9.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0a4be2a28656afe279b34d4f91c3e26eccf2f85500d4a4ff0b1f8b54bf807338", size = 244610, upload-time = "2025-06-13T13:00:56.932Z" }, - { url = "https://files.pythonhosted.org/packages/bf/15/cca62b13f39650bc87b2b92bb03bce7f0e79dd0bf2c7529e9fc7393e4d60/coverage-7.9.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:382e7ddd5289f140259b610e5f5c58f713d025cb2f66d0eb17e68d0a94278875", size = 244257, upload-time = "2025-06-13T13:00:58.545Z" }, - { url = "https://files.pythonhosted.org/packages/cd/1a/c0f2abe92c29e1464dbd0ff9d56cb6c88ae2b9e21becdb38bea31fcb2f6c/coverage-7.9.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e5532482344186c543c37bfad0ee6069e8ae4fc38d073b8bc836fc8f03c9e250", size = 242309, upload-time = "2025-06-13T13:00:59.836Z" }, - { url = "https://files.pythonhosted.org/packages/57/8d/c6fd70848bd9bf88fa90df2af5636589a8126d2170f3aade21ed53f2b67a/coverage-7.9.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a39d18b3f50cc121d0ce3838d32d58bd1d15dab89c910358ebefc3665712256c", size = 242898, upload-time = "2025-06-13T13:01:02.506Z" }, - { url = "https://files.pythonhosted.org/packages/c2/9e/6ca46c7bff4675f09a66fe2797cd1ad6a24f14c9c7c3b3ebe0470a6e30b8/coverage-7.9.1-cp311-cp311-win32.whl", hash = "sha256:dd24bd8d77c98557880def750782df77ab2b6885a18483dc8588792247174b32", size = 214561, upload-time = "2025-06-13T13:01:04.012Z" }, - { url = "https://files.pythonhosted.org/packages/a1/30/166978c6302010742dabcdc425fa0f938fa5a800908e39aff37a7a876a13/coverage-7.9.1-cp311-cp311-win_amd64.whl", hash = "sha256:6b55ad10a35a21b8015eabddc9ba31eb590f54adc9cd39bcf09ff5349fd52125", size = 215493, upload-time = "2025-06-13T13:01:05.702Z" }, - { url = "https://files.pythonhosted.org/packages/60/07/a6d2342cd80a5be9f0eeab115bc5ebb3917b4a64c2953534273cf9bc7ae6/coverage-7.9.1-cp311-cp311-win_arm64.whl", hash = "sha256:6ad935f0016be24c0e97fc8c40c465f9c4b85cbbe6eac48934c0dc4d2568321e", size = 213869, upload-time = "2025-06-13T13:01:09.345Z" }, - { url = "https://files.pythonhosted.org/packages/68/d9/7f66eb0a8f2fce222de7bdc2046ec41cb31fe33fb55a330037833fb88afc/coverage-7.9.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:a8de12b4b87c20de895f10567639c0797b621b22897b0af3ce4b4e204a743626", size = 212336, upload-time = "2025-06-13T13:01:10.909Z" }, - { url = "https://files.pythonhosted.org/packages/20/20/e07cb920ef3addf20f052ee3d54906e57407b6aeee3227a9c91eea38a665/coverage-7.9.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5add197315a054e92cee1b5f686a2bcba60c4c3e66ee3de77ace6c867bdee7cb", size = 212571, upload-time = "2025-06-13T13:01:12.518Z" }, - { url = "https://files.pythonhosted.org/packages/78/f8/96f155de7e9e248ca9c8ff1a40a521d944ba48bec65352da9be2463745bf/coverage-7.9.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:600a1d4106fe66f41e5d0136dfbc68fe7200a5cbe85610ddf094f8f22e1b0300", size = 246377, upload-time = "2025-06-13T13:01:14.87Z" }, - { url = "https://files.pythonhosted.org/packages/3e/cf/1d783bd05b7bca5c10ded5f946068909372e94615a4416afadfe3f63492d/coverage-7.9.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2a876e4c3e5a2a1715a6608906aa5a2e0475b9c0f68343c2ada98110512ab1d8", size = 243394, upload-time = "2025-06-13T13:01:16.23Z" }, - { url = "https://files.pythonhosted.org/packages/02/dd/e7b20afd35b0a1abea09fb3998e1abc9f9bd953bee548f235aebd2b11401/coverage-7.9.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:81f34346dd63010453922c8e628a52ea2d2ccd73cb2487f7700ac531b247c8a5", size = 245586, upload-time = "2025-06-13T13:01:17.532Z" }, - { url = "https://files.pythonhosted.org/packages/4e/38/b30b0006fea9d617d1cb8e43b1bc9a96af11eff42b87eb8c716cf4d37469/coverage-7.9.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:888f8eee13f2377ce86d44f338968eedec3291876b0b8a7289247ba52cb984cd", size = 245396, upload-time = "2025-06-13T13:01:19.164Z" }, - { url = "https://files.pythonhosted.org/packages/31/e4/4d8ec1dc826e16791f3daf1b50943e8e7e1eb70e8efa7abb03936ff48418/coverage-7.9.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:9969ef1e69b8c8e1e70d591f91bbc37fc9a3621e447525d1602801a24ceda898", size = 243577, upload-time = "2025-06-13T13:01:22.433Z" }, - { url = "https://files.pythonhosted.org/packages/25/f4/b0e96c5c38e6e40ef465c4bc7f138863e2909c00e54a331da335faf0d81a/coverage-7.9.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:60c458224331ee3f1a5b472773e4a085cc27a86a0b48205409d364272d67140d", size = 244809, upload-time = "2025-06-13T13:01:24.143Z" }, - { url = "https://files.pythonhosted.org/packages/8a/65/27e0a1fa5e2e5079bdca4521be2f5dabf516f94e29a0defed35ac2382eb2/coverage-7.9.1-cp312-cp312-win32.whl", hash = "sha256:5f646a99a8c2b3ff4c6a6e081f78fad0dde275cd59f8f49dc4eab2e394332e74", size = 214724, upload-time = "2025-06-13T13:01:25.435Z" }, - { url = "https://files.pythonhosted.org/packages/9b/a8/d5b128633fd1a5e0401a4160d02fa15986209a9e47717174f99dc2f7166d/coverage-7.9.1-cp312-cp312-win_amd64.whl", hash = "sha256:30f445f85c353090b83e552dcbbdad3ec84c7967e108c3ae54556ca69955563e", size = 215535, upload-time = "2025-06-13T13:01:27.861Z" }, - { url = "https://files.pythonhosted.org/packages/a3/37/84bba9d2afabc3611f3e4325ee2c6a47cd449b580d4a606b240ce5a6f9bf/coverage-7.9.1-cp312-cp312-win_arm64.whl", hash = "sha256:af41da5dca398d3474129c58cb2b106a5d93bbb196be0d307ac82311ca234342", size = 213904, upload-time = "2025-06-13T13:01:29.202Z" }, - { url = "https://files.pythonhosted.org/packages/d0/a7/a027970c991ca90f24e968999f7d509332daf6b8c3533d68633930aaebac/coverage-7.9.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:31324f18d5969feef7344a932c32428a2d1a3e50b15a6404e97cba1cc9b2c631", size = 212358, upload-time = "2025-06-13T13:01:30.909Z" }, - { url = "https://files.pythonhosted.org/packages/f2/48/6aaed3651ae83b231556750280682528fea8ac7f1232834573472d83e459/coverage-7.9.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0c804506d624e8a20fb3108764c52e0eef664e29d21692afa375e0dd98dc384f", size = 212620, upload-time = "2025-06-13T13:01:32.256Z" }, - { url = "https://files.pythonhosted.org/packages/6c/2a/f4b613f3b44d8b9f144847c89151992b2b6b79cbc506dee89ad0c35f209d/coverage-7.9.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ef64c27bc40189f36fcc50c3fb8f16ccda73b6a0b80d9bd6e6ce4cffcd810bbd", size = 245788, upload-time = "2025-06-13T13:01:33.948Z" }, - { url = "https://files.pythonhosted.org/packages/04/d2/de4fdc03af5e4e035ef420ed26a703c6ad3d7a07aff2e959eb84e3b19ca8/coverage-7.9.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d4fe2348cc6ec372e25adec0219ee2334a68d2f5222e0cba9c0d613394e12d86", size = 243001, upload-time = "2025-06-13T13:01:35.285Z" }, - { url = "https://files.pythonhosted.org/packages/f5/e8/eed18aa5583b0423ab7f04e34659e51101135c41cd1dcb33ac1d7013a6d6/coverage-7.9.1-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:34ed2186fe52fcc24d4561041979a0dec69adae7bce2ae8d1c49eace13e55c43", size = 244985, upload-time = "2025-06-13T13:01:36.712Z" }, - { url = "https://files.pythonhosted.org/packages/17/f8/ae9e5cce8885728c934eaa58ebfa8281d488ef2afa81c3dbc8ee9e6d80db/coverage-7.9.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:25308bd3d00d5eedd5ae7d4357161f4df743e3c0240fa773ee1b0f75e6c7c0f1", size = 245152, upload-time = "2025-06-13T13:01:39.303Z" }, - { url = "https://files.pythonhosted.org/packages/5a/c8/272c01ae792bb3af9b30fac14d71d63371db227980682836ec388e2c57c0/coverage-7.9.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:73e9439310f65d55a5a1e0564b48e34f5369bee943d72c88378f2d576f5a5751", size = 243123, upload-time = "2025-06-13T13:01:40.727Z" }, - { url = "https://files.pythonhosted.org/packages/8c/d0/2819a1e3086143c094ab446e3bdf07138527a7b88cb235c488e78150ba7a/coverage-7.9.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:37ab6be0859141b53aa89412a82454b482c81cf750de4f29223d52268a86de67", size = 244506, upload-time = "2025-06-13T13:01:42.184Z" }, - { url = "https://files.pythonhosted.org/packages/8b/4e/9f6117b89152df7b6112f65c7a4ed1f2f5ec8e60c4be8f351d91e7acc848/coverage-7.9.1-cp313-cp313-win32.whl", hash = "sha256:64bdd969456e2d02a8b08aa047a92d269c7ac1f47e0c977675d550c9a0863643", size = 214766, upload-time = "2025-06-13T13:01:44.482Z" }, - { url = "https://files.pythonhosted.org/packages/27/0f/4b59f7c93b52c2c4ce7387c5a4e135e49891bb3b7408dcc98fe44033bbe0/coverage-7.9.1-cp313-cp313-win_amd64.whl", hash = "sha256:be9e3f68ca9edb897c2184ad0eee815c635565dbe7a0e7e814dc1f7cbab92c0a", size = 215568, upload-time = "2025-06-13T13:01:45.772Z" }, - { url = "https://files.pythonhosted.org/packages/09/1e/9679826336f8c67b9c39a359352882b24a8a7aee48d4c9cad08d38d7510f/coverage-7.9.1-cp313-cp313-win_arm64.whl", hash = "sha256:1c503289ffef1d5105d91bbb4d62cbe4b14bec4d13ca225f9c73cde9bb46207d", size = 213939, upload-time = "2025-06-13T13:01:47.087Z" }, - { url = "https://files.pythonhosted.org/packages/bb/5b/5c6b4e7a407359a2e3b27bf9c8a7b658127975def62077d441b93a30dbe8/coverage-7.9.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:0b3496922cb5f4215bf5caaef4cf12364a26b0be82e9ed6d050f3352cf2d7ef0", size = 213079, upload-time = "2025-06-13T13:01:48.554Z" }, - { url = "https://files.pythonhosted.org/packages/a2/22/1e2e07279fd2fd97ae26c01cc2186e2258850e9ec125ae87184225662e89/coverage-7.9.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:9565c3ab1c93310569ec0d86b017f128f027cab0b622b7af288696d7ed43a16d", size = 213299, upload-time = "2025-06-13T13:01:49.997Z" }, - { url = "https://files.pythonhosted.org/packages/14/c0/4c5125a4b69d66b8c85986d3321520f628756cf524af810baab0790c7647/coverage-7.9.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2241ad5dbf79ae1d9c08fe52b36d03ca122fb9ac6bca0f34439e99f8327ac89f", size = 256535, upload-time = "2025-06-13T13:01:51.314Z" }, - { url = "https://files.pythonhosted.org/packages/81/8b/e36a04889dda9960be4263e95e777e7b46f1bb4fc32202612c130a20c4da/coverage-7.9.1-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3bb5838701ca68b10ebc0937dbd0eb81974bac54447c55cd58dea5bca8451029", size = 252756, upload-time = "2025-06-13T13:01:54.403Z" }, - { url = "https://files.pythonhosted.org/packages/98/82/be04eff8083a09a4622ecd0e1f31a2c563dbea3ed848069e7b0445043a70/coverage-7.9.1-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b30a25f814591a8c0c5372c11ac8967f669b97444c47fd794926e175c4047ece", size = 254912, upload-time = "2025-06-13T13:01:56.769Z" }, - { url = "https://files.pythonhosted.org/packages/0f/25/c26610a2c7f018508a5ab958e5b3202d900422cf7cdca7670b6b8ca4e8df/coverage-7.9.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:2d04b16a6062516df97969f1ae7efd0de9c31eb6ebdceaa0d213b21c0ca1a683", size = 256144, upload-time = "2025-06-13T13:01:58.19Z" }, - { url = "https://files.pythonhosted.org/packages/c5/8b/fb9425c4684066c79e863f1e6e7ecebb49e3a64d9f7f7860ef1688c56f4a/coverage-7.9.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:7931b9e249edefb07cd6ae10c702788546341d5fe44db5b6108a25da4dca513f", size = 254257, upload-time = "2025-06-13T13:01:59.645Z" }, - { url = "https://files.pythonhosted.org/packages/93/df/27b882f54157fc1131e0e215b0da3b8d608d9b8ef79a045280118a8f98fe/coverage-7.9.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:52e92b01041151bf607ee858e5a56c62d4b70f4dac85b8c8cb7fb8a351ab2c10", size = 255094, upload-time = "2025-06-13T13:02:01.37Z" }, - { url = "https://files.pythonhosted.org/packages/41/5f/cad1c3dbed8b3ee9e16fa832afe365b4e3eeab1fb6edb65ebbf745eabc92/coverage-7.9.1-cp313-cp313t-win32.whl", hash = "sha256:684e2110ed84fd1ca5f40e89aa44adf1729dc85444004111aa01866507adf363", size = 215437, upload-time = "2025-06-13T13:02:02.905Z" }, - { url = "https://files.pythonhosted.org/packages/99/4d/fad293bf081c0e43331ca745ff63673badc20afea2104b431cdd8c278b4c/coverage-7.9.1-cp313-cp313t-win_amd64.whl", hash = "sha256:437c576979e4db840539674e68c84b3cda82bc824dd138d56bead1435f1cb5d7", size = 216605, upload-time = "2025-06-13T13:02:05.638Z" }, - { url = "https://files.pythonhosted.org/packages/1f/56/4ee027d5965fc7fc126d7ec1187529cc30cc7d740846e1ecb5e92d31b224/coverage-7.9.1-cp313-cp313t-win_arm64.whl", hash = "sha256:18a0912944d70aaf5f399e350445738a1a20b50fbea788f640751c2ed9208b6c", size = 214392, upload-time = "2025-06-13T13:02:07.642Z" }, - { url = "https://files.pythonhosted.org/packages/3e/e5/c723545c3fd3204ebde3b4cc4b927dce709d3b6dc577754bb57f63ca4a4a/coverage-7.9.1-pp39.pp310.pp311-none-any.whl", hash = "sha256:db0f04118d1db74db6c9e1cb1898532c7dcc220f1d2718f058601f7c3f499514", size = 204009, upload-time = "2025-06-13T13:02:25.787Z" }, - { url = "https://files.pythonhosted.org/packages/08/b8/7ddd1e8ba9701dea08ce22029917140e6f66a859427406579fd8d0ca7274/coverage-7.9.1-py3-none-any.whl", hash = "sha256:66b974b145aa189516b6bf2d8423e888b742517d37872f6ee4c5be0073bd9a3c", size = 204000, upload-time = "2025-06-13T13:02:27.173Z" }, +version = "7.9.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/04/b7/c0465ca253df10a9e8dae0692a4ae6e9726d245390aaef92360e1d6d3832/coverage-7.9.2.tar.gz", hash = "sha256:997024fa51e3290264ffd7492ec97d0690293ccd2b45a6cd7d82d945a4a80c8b", size = 813556, upload-time = "2025-07-03T10:54:15.101Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/39/40/916786453bcfafa4c788abee4ccd6f592b5b5eca0cd61a32a4e5a7ef6e02/coverage-7.9.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a7a56a2964a9687b6aba5b5ced6971af308ef6f79a91043c05dd4ee3ebc3e9ba", size = 212152, upload-time = "2025-07-03T10:52:53.562Z" }, + { url = "https://files.pythonhosted.org/packages/9f/66/cc13bae303284b546a030762957322bbbff1ee6b6cb8dc70a40f8a78512f/coverage-7.9.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:123d589f32c11d9be7fe2e66d823a236fe759b0096f5db3fb1b75b2fa414a4fa", size = 212540, upload-time = "2025-07-03T10:52:55.196Z" }, + { url = "https://files.pythonhosted.org/packages/0f/3c/d56a764b2e5a3d43257c36af4a62c379df44636817bb5f89265de4bf8bd7/coverage-7.9.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:333b2e0ca576a7dbd66e85ab402e35c03b0b22f525eed82681c4b866e2e2653a", size = 245097, upload-time = "2025-07-03T10:52:56.509Z" }, + { url = "https://files.pythonhosted.org/packages/b1/46/bd064ea8b3c94eb4ca5d90e34d15b806cba091ffb2b8e89a0d7066c45791/coverage-7.9.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:326802760da234baf9f2f85a39e4a4b5861b94f6c8d95251f699e4f73b1835dc", size = 242812, upload-time = "2025-07-03T10:52:57.842Z" }, + { url = "https://files.pythonhosted.org/packages/43/02/d91992c2b29bc7afb729463bc918ebe5f361be7f1daae93375a5759d1e28/coverage-7.9.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:19e7be4cfec248df38ce40968c95d3952fbffd57b400d4b9bb580f28179556d2", size = 244617, upload-time = "2025-07-03T10:52:59.239Z" }, + { url = "https://files.pythonhosted.org/packages/b7/4f/8fadff6bf56595a16d2d6e33415841b0163ac660873ed9a4e9046194f779/coverage-7.9.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0b4a4cb73b9f2b891c1788711408ef9707666501ba23684387277ededab1097c", size = 244263, upload-time = "2025-07-03T10:53:00.601Z" }, + { url = "https://files.pythonhosted.org/packages/9b/d2/e0be7446a2bba11739edb9f9ba4eff30b30d8257370e237418eb44a14d11/coverage-7.9.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:2c8937fa16c8c9fbbd9f118588756e7bcdc7e16a470766a9aef912dd3f117dbd", size = 242314, upload-time = "2025-07-03T10:53:01.932Z" }, + { url = "https://files.pythonhosted.org/packages/9d/7d/dcbac9345000121b8b57a3094c2dfcf1ccc52d8a14a40c1d4bc89f936f80/coverage-7.9.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:42da2280c4d30c57a9b578bafd1d4494fa6c056d4c419d9689e66d775539be74", size = 242904, upload-time = "2025-07-03T10:53:03.478Z" }, + { url = "https://files.pythonhosted.org/packages/41/58/11e8db0a0c0510cf31bbbdc8caf5d74a358b696302a45948d7c768dfd1cf/coverage-7.9.2-cp311-cp311-win32.whl", hash = "sha256:14fa8d3da147f5fdf9d298cacc18791818f3f1a9f542c8958b80c228320e90c6", size = 214553, upload-time = "2025-07-03T10:53:05.174Z" }, + { url = "https://files.pythonhosted.org/packages/3a/7d/751794ec8907a15e257136e48dc1021b1f671220ecccfd6c4eaf30802714/coverage-7.9.2-cp311-cp311-win_amd64.whl", hash = "sha256:549cab4892fc82004f9739963163fd3aac7a7b0df430669b75b86d293d2df2a7", size = 215441, upload-time = "2025-07-03T10:53:06.472Z" }, + { url = "https://files.pythonhosted.org/packages/62/5b/34abcedf7b946c1c9e15b44f326cb5b0da852885312b30e916f674913428/coverage-7.9.2-cp311-cp311-win_arm64.whl", hash = "sha256:c2667a2b913e307f06aa4e5677f01a9746cd08e4b35e14ebcde6420a9ebb4c62", size = 213873, upload-time = "2025-07-03T10:53:07.699Z" }, + { url = "https://files.pythonhosted.org/packages/53/d7/7deefc6fd4f0f1d4c58051f4004e366afc9e7ab60217ac393f247a1de70a/coverage-7.9.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:ae9eb07f1cfacd9cfe8eaee6f4ff4b8a289a668c39c165cd0c8548484920ffc0", size = 212344, upload-time = "2025-07-03T10:53:09.3Z" }, + { url = "https://files.pythonhosted.org/packages/95/0c/ee03c95d32be4d519e6a02e601267769ce2e9a91fc8faa1b540e3626c680/coverage-7.9.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9ce85551f9a1119f02adc46d3014b5ee3f765deac166acf20dbb851ceb79b6f3", size = 212580, upload-time = "2025-07-03T10:53:11.52Z" }, + { url = "https://files.pythonhosted.org/packages/8b/9f/826fa4b544b27620086211b87a52ca67592622e1f3af9e0a62c87aea153a/coverage-7.9.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f8f6389ac977c5fb322e0e38885fbbf901743f79d47f50db706e7644dcdcb6e1", size = 246383, upload-time = "2025-07-03T10:53:13.134Z" }, + { url = "https://files.pythonhosted.org/packages/7f/b3/4477aafe2a546427b58b9c540665feff874f4db651f4d3cb21b308b3a6d2/coverage-7.9.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ff0d9eae8cdfcd58fe7893b88993723583a6ce4dfbfd9f29e001922544f95615", size = 243400, upload-time = "2025-07-03T10:53:14.614Z" }, + { url = "https://files.pythonhosted.org/packages/f8/c2/efffa43778490c226d9d434827702f2dfbc8041d79101a795f11cbb2cf1e/coverage-7.9.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fae939811e14e53ed8a9818dad51d434a41ee09df9305663735f2e2d2d7d959b", size = 245591, upload-time = "2025-07-03T10:53:15.872Z" }, + { url = "https://files.pythonhosted.org/packages/c6/e7/a59888e882c9a5f0192d8627a30ae57910d5d449c80229b55e7643c078c4/coverage-7.9.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:31991156251ec202c798501e0a42bbdf2169dcb0f137b1f5c0f4267f3fc68ef9", size = 245402, upload-time = "2025-07-03T10:53:17.124Z" }, + { url = "https://files.pythonhosted.org/packages/92/a5/72fcd653ae3d214927edc100ce67440ed8a0a1e3576b8d5e6d066ed239db/coverage-7.9.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:d0d67963f9cbfc7c7f96d4ac74ed60ecbebd2ea6eeb51887af0f8dce205e545f", size = 243583, upload-time = "2025-07-03T10:53:18.781Z" }, + { url = "https://files.pythonhosted.org/packages/5c/f5/84e70e4df28f4a131d580d7d510aa1ffd95037293da66fd20d446090a13b/coverage-7.9.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:49b752a2858b10580969ec6af6f090a9a440a64a301ac1528d7ca5f7ed497f4d", size = 244815, upload-time = "2025-07-03T10:53:20.168Z" }, + { url = "https://files.pythonhosted.org/packages/39/e7/d73d7cbdbd09fdcf4642655ae843ad403d9cbda55d725721965f3580a314/coverage-7.9.2-cp312-cp312-win32.whl", hash = "sha256:88d7598b8ee130f32f8a43198ee02edd16d7f77692fa056cb779616bbea1b355", size = 214719, upload-time = "2025-07-03T10:53:21.521Z" }, + { url = "https://files.pythonhosted.org/packages/9f/d6/7486dcc3474e2e6ad26a2af2db7e7c162ccd889c4c68fa14ea8ec189c9e9/coverage-7.9.2-cp312-cp312-win_amd64.whl", hash = "sha256:9dfb070f830739ee49d7c83e4941cc767e503e4394fdecb3b54bfdac1d7662c0", size = 215509, upload-time = "2025-07-03T10:53:22.853Z" }, + { url = "https://files.pythonhosted.org/packages/b7/34/0439f1ae2593b0346164d907cdf96a529b40b7721a45fdcf8b03c95fcd90/coverage-7.9.2-cp312-cp312-win_arm64.whl", hash = "sha256:4e2c058aef613e79df00e86b6d42a641c877211384ce5bd07585ed7ba71ab31b", size = 213910, upload-time = "2025-07-03T10:53:24.472Z" }, + { url = "https://files.pythonhosted.org/packages/94/9d/7a8edf7acbcaa5e5c489a646226bed9591ee1c5e6a84733c0140e9ce1ae1/coverage-7.9.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:985abe7f242e0d7bba228ab01070fde1d6c8fa12f142e43debe9ed1dde686038", size = 212367, upload-time = "2025-07-03T10:53:25.811Z" }, + { url = "https://files.pythonhosted.org/packages/e8/9e/5cd6f130150712301f7e40fb5865c1bc27b97689ec57297e568d972eec3c/coverage-7.9.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:82c3939264a76d44fde7f213924021ed31f55ef28111a19649fec90c0f109e6d", size = 212632, upload-time = "2025-07-03T10:53:27.075Z" }, + { url = "https://files.pythonhosted.org/packages/a8/de/6287a2c2036f9fd991c61cefa8c64e57390e30c894ad3aa52fac4c1e14a8/coverage-7.9.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ae5d563e970dbe04382f736ec214ef48103d1b875967c89d83c6e3f21706d5b3", size = 245793, upload-time = "2025-07-03T10:53:28.408Z" }, + { url = "https://files.pythonhosted.org/packages/06/cc/9b5a9961d8160e3cb0b558c71f8051fe08aa2dd4b502ee937225da564ed1/coverage-7.9.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bdd612e59baed2a93c8843c9a7cb902260f181370f1d772f4842987535071d14", size = 243006, upload-time = "2025-07-03T10:53:29.754Z" }, + { url = "https://files.pythonhosted.org/packages/49/d9/4616b787d9f597d6443f5588619c1c9f659e1f5fc9eebf63699eb6d34b78/coverage-7.9.2-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:256ea87cb2a1ed992bcdfc349d8042dcea1b80436f4ddf6e246d6bee4b5d73b6", size = 244990, upload-time = "2025-07-03T10:53:31.098Z" }, + { url = "https://files.pythonhosted.org/packages/48/83/801cdc10f137b2d02b005a761661649ffa60eb173dcdaeb77f571e4dc192/coverage-7.9.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f44ae036b63c8ea432f610534a2668b0c3aee810e7037ab9d8ff6883de480f5b", size = 245157, upload-time = "2025-07-03T10:53:32.717Z" }, + { url = "https://files.pythonhosted.org/packages/c8/a4/41911ed7e9d3ceb0ffb019e7635468df7499f5cc3edca5f7dfc078e9c5ec/coverage-7.9.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:82d76ad87c932935417a19b10cfe7abb15fd3f923cfe47dbdaa74ef4e503752d", size = 243128, upload-time = "2025-07-03T10:53:34.009Z" }, + { url = "https://files.pythonhosted.org/packages/10/41/344543b71d31ac9cb00a664d5d0c9ef134a0fe87cb7d8430003b20fa0b7d/coverage-7.9.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:619317bb86de4193debc712b9e59d5cffd91dc1d178627ab2a77b9870deb2868", size = 244511, upload-time = "2025-07-03T10:53:35.434Z" }, + { url = "https://files.pythonhosted.org/packages/d5/81/3b68c77e4812105e2a060f6946ba9e6f898ddcdc0d2bfc8b4b152a9ae522/coverage-7.9.2-cp313-cp313-win32.whl", hash = "sha256:0a07757de9feb1dfafd16ab651e0f628fd7ce551604d1bf23e47e1ddca93f08a", size = 214765, upload-time = "2025-07-03T10:53:36.787Z" }, + { url = "https://files.pythonhosted.org/packages/06/a2/7fac400f6a346bb1a4004eb2a76fbff0e242cd48926a2ce37a22a6a1d917/coverage-7.9.2-cp313-cp313-win_amd64.whl", hash = "sha256:115db3d1f4d3f35f5bb021e270edd85011934ff97c8797216b62f461dd69374b", size = 215536, upload-time = "2025-07-03T10:53:38.188Z" }, + { url = "https://files.pythonhosted.org/packages/08/47/2c6c215452b4f90d87017e61ea0fd9e0486bb734cb515e3de56e2c32075f/coverage-7.9.2-cp313-cp313-win_arm64.whl", hash = "sha256:48f82f889c80af8b2a7bb6e158d95a3fbec6a3453a1004d04e4f3b5945a02694", size = 213943, upload-time = "2025-07-03T10:53:39.492Z" }, + { url = "https://files.pythonhosted.org/packages/a3/46/e211e942b22d6af5e0f323faa8a9bc7c447a1cf1923b64c47523f36ed488/coverage-7.9.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:55a28954545f9d2f96870b40f6c3386a59ba8ed50caf2d949676dac3ecab99f5", size = 213088, upload-time = "2025-07-03T10:53:40.874Z" }, + { url = "https://files.pythonhosted.org/packages/d2/2f/762551f97e124442eccd907bf8b0de54348635b8866a73567eb4e6417acf/coverage-7.9.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:cdef6504637731a63c133bb2e6f0f0214e2748495ec15fe42d1e219d1b133f0b", size = 213298, upload-time = "2025-07-03T10:53:42.218Z" }, + { url = "https://files.pythonhosted.org/packages/7a/b7/76d2d132b7baf7360ed69be0bcab968f151fa31abe6d067f0384439d9edb/coverage-7.9.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bcd5ebe66c7a97273d5d2ddd4ad0ed2e706b39630ed4b53e713d360626c3dbb3", size = 256541, upload-time = "2025-07-03T10:53:43.823Z" }, + { url = "https://files.pythonhosted.org/packages/a0/17/392b219837d7ad47d8e5974ce5f8dc3deb9f99a53b3bd4d123602f960c81/coverage-7.9.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9303aed20872d7a3c9cb39c5d2b9bdbe44e3a9a1aecb52920f7e7495410dfab8", size = 252761, upload-time = "2025-07-03T10:53:45.19Z" }, + { url = "https://files.pythonhosted.org/packages/d5/77/4256d3577fe1b0daa8d3836a1ebe68eaa07dd2cbaf20cf5ab1115d6949d4/coverage-7.9.2-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc18ea9e417a04d1920a9a76fe9ebd2f43ca505b81994598482f938d5c315f46", size = 254917, upload-time = "2025-07-03T10:53:46.931Z" }, + { url = "https://files.pythonhosted.org/packages/53/99/fc1a008eef1805e1ddb123cf17af864743354479ea5129a8f838c433cc2c/coverage-7.9.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:6406cff19880aaaadc932152242523e892faff224da29e241ce2fca329866584", size = 256147, upload-time = "2025-07-03T10:53:48.289Z" }, + { url = "https://files.pythonhosted.org/packages/92/c0/f63bf667e18b7f88c2bdb3160870e277c4874ced87e21426128d70aa741f/coverage-7.9.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:2d0d4f6ecdf37fcc19c88fec3e2277d5dee740fb51ffdd69b9579b8c31e4232e", size = 254261, upload-time = "2025-07-03T10:53:49.99Z" }, + { url = "https://files.pythonhosted.org/packages/8c/32/37dd1c42ce3016ff8ec9e4b607650d2e34845c0585d3518b2a93b4830c1a/coverage-7.9.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:c33624f50cf8de418ab2b4d6ca9eda96dc45b2c4231336bac91454520e8d1fac", size = 255099, upload-time = "2025-07-03T10:53:51.354Z" }, + { url = "https://files.pythonhosted.org/packages/da/2e/af6b86f7c95441ce82f035b3affe1cd147f727bbd92f563be35e2d585683/coverage-7.9.2-cp313-cp313t-win32.whl", hash = "sha256:1df6b76e737c6a92210eebcb2390af59a141f9e9430210595251fbaf02d46926", size = 215440, upload-time = "2025-07-03T10:53:52.808Z" }, + { url = "https://files.pythonhosted.org/packages/4d/bb/8a785d91b308867f6b2e36e41c569b367c00b70c17f54b13ac29bcd2d8c8/coverage-7.9.2-cp313-cp313t-win_amd64.whl", hash = "sha256:f5fd54310b92741ebe00d9c0d1d7b2b27463952c022da6d47c175d246a98d1bd", size = 216537, upload-time = "2025-07-03T10:53:54.273Z" }, + { url = "https://files.pythonhosted.org/packages/1d/a0/a6bffb5e0f41a47279fd45a8f3155bf193f77990ae1c30f9c224b61cacb0/coverage-7.9.2-cp313-cp313t-win_arm64.whl", hash = "sha256:c48c2375287108c887ee87d13b4070a381c6537d30e8487b24ec721bf2a781cb", size = 214398, upload-time = "2025-07-03T10:53:56.715Z" }, + { url = "https://files.pythonhosted.org/packages/d7/85/f8bbefac27d286386961c25515431482a425967e23d3698b75a250872924/coverage-7.9.2-pp39.pp310.pp311-none-any.whl", hash = "sha256:8a1166db2fb62473285bcb092f586e081e92656c7dfa8e9f62b4d39d7e6b5050", size = 204013, upload-time = "2025-07-03T10:54:12.084Z" }, + { url = "https://files.pythonhosted.org/packages/3c/38/bbe2e63902847cf79036ecc75550d0698af31c91c7575352eb25190d0fb3/coverage-7.9.2-py3-none-any.whl", hash = "sha256:e425cd5b00f6fc0ed7cdbd766c70be8baab4b7839e4d4fe5fac48581dd968ea4", size = 204005, upload-time = "2025-07-03T10:54:13.491Z" }, ] [package.optional-dependencies] @@ -589,35 +589,35 @@ wheels = [ [[package]] name = "fonttools" -version = "4.58.4" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/2e/5a/1124b2c8cb3a8015faf552e92714040bcdbc145dfa29928891b02d147a18/fonttools-4.58.4.tar.gz", hash = "sha256:928a8009b9884ed3aae17724b960987575155ca23c6f0b8146e400cc9e0d44ba", size = 3525026, upload-time = "2025-06-13T17:25:15.426Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/17/7b/cc6e9bb41bab223bd2dc70ba0b21386b85f604e27f4c3206b4205085a2ab/fonttools-4.58.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:a3841991c9ee2dc0562eb7f23d333d34ce81e8e27c903846f0487da21e0028eb", size = 2768901, upload-time = "2025-06-13T17:24:05.901Z" }, - { url = "https://files.pythonhosted.org/packages/3d/15/98d75df9f2b4e7605f3260359ad6e18e027c11fa549f74fce567270ac891/fonttools-4.58.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3c98f91b6a9604e7ffb5ece6ea346fa617f967c2c0944228801246ed56084664", size = 2328696, upload-time = "2025-06-13T17:24:09.18Z" }, - { url = "https://files.pythonhosted.org/packages/a8/c8/dc92b80f5452c9c40164e01b3f78f04b835a00e673bd9355ca257008ff61/fonttools-4.58.4-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ab9f891eb687ddf6a4e5f82901e00f992e18012ca97ab7acd15f13632acd14c1", size = 5018830, upload-time = "2025-06-13T17:24:11.282Z" }, - { url = "https://files.pythonhosted.org/packages/19/48/8322cf177680505d6b0b6062e204f01860cb573466a88077a9b795cb70e8/fonttools-4.58.4-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:891c5771e8f0094b7c0dc90eda8fc75e72930b32581418f2c285a9feedfd9a68", size = 4960922, upload-time = "2025-06-13T17:24:14.9Z" }, - { url = "https://files.pythonhosted.org/packages/14/e0/2aff149ed7eb0916de36da513d473c6fff574a7146891ce42de914899395/fonttools-4.58.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:43ba4d9646045c375d22e3473b7d82b18b31ee2ac715cd94220ffab7bc2d5c1d", size = 4997135, upload-time = "2025-06-13T17:24:16.959Z" }, - { url = "https://files.pythonhosted.org/packages/e6/6f/4d9829b29a64a2e63a121cb11ecb1b6a9524086eef3e35470949837a1692/fonttools-4.58.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:33d19f16e6d2ffd6669bda574a6589941f6c99a8d5cfb9f464038244c71555de", size = 5108701, upload-time = "2025-06-13T17:24:18.849Z" }, - { url = "https://files.pythonhosted.org/packages/6f/1e/2d656ddd1b0cd0d222f44b2d008052c2689e66b702b9af1cd8903ddce319/fonttools-4.58.4-cp311-cp311-win32.whl", hash = "sha256:b59e5109b907da19dc9df1287454821a34a75f2632a491dd406e46ff432c2a24", size = 2200177, upload-time = "2025-06-13T17:24:20.823Z" }, - { url = "https://files.pythonhosted.org/packages/fb/83/ba71ad053fddf4157cb0697c8da8eff6718d059f2a22986fa5f312b49c92/fonttools-4.58.4-cp311-cp311-win_amd64.whl", hash = "sha256:3d471a5b567a0d1648f2e148c9a8bcf00d9ac76eb89e976d9976582044cc2509", size = 2247892, upload-time = "2025-06-13T17:24:22.927Z" }, - { url = "https://files.pythonhosted.org/packages/04/3c/1d1792bfe91ef46f22a3d23b4deb514c325e73c17d4f196b385b5e2faf1c/fonttools-4.58.4-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:462211c0f37a278494e74267a994f6be9a2023d0557aaa9ecbcbfce0f403b5a6", size = 2754082, upload-time = "2025-06-13T17:24:24.862Z" }, - { url = "https://files.pythonhosted.org/packages/2a/1f/2b261689c901a1c3bc57a6690b0b9fc21a9a93a8b0c83aae911d3149f34e/fonttools-4.58.4-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:0c7a12fb6f769165547f00fcaa8d0df9517603ae7e04b625e5acb8639809b82d", size = 2321677, upload-time = "2025-06-13T17:24:26.815Z" }, - { url = "https://files.pythonhosted.org/packages/fe/6b/4607add1755a1e6581ae1fc0c9a640648e0d9cdd6591cc2d581c2e07b8c3/fonttools-4.58.4-cp312-cp312-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:2d42c63020a922154add0a326388a60a55504629edc3274bc273cd3806b4659f", size = 4896354, upload-time = "2025-06-13T17:24:28.428Z" }, - { url = "https://files.pythonhosted.org/packages/cd/95/34b4f483643d0cb11a1f830b72c03fdd18dbd3792d77a2eb2e130a96fada/fonttools-4.58.4-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8f2b4e6fd45edc6805f5f2c355590b092ffc7e10a945bd6a569fc66c1d2ae7aa", size = 4941633, upload-time = "2025-06-13T17:24:30.568Z" }, - { url = "https://files.pythonhosted.org/packages/81/ac/9bafbdb7694059c960de523e643fa5a61dd2f698f3f72c0ca18ae99257c7/fonttools-4.58.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:f155b927f6efb1213a79334e4cb9904d1e18973376ffc17a0d7cd43d31981f1e", size = 4886170, upload-time = "2025-06-13T17:24:32.724Z" }, - { url = "https://files.pythonhosted.org/packages/ae/44/a3a3b70d5709405f7525bb7cb497b4e46151e0c02e3c8a0e40e5e9fe030b/fonttools-4.58.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e38f687d5de97c7fb7da3e58169fb5ba349e464e141f83c3c2e2beb91d317816", size = 5037851, upload-time = "2025-06-13T17:24:35.034Z" }, - { url = "https://files.pythonhosted.org/packages/21/cb/e8923d197c78969454eb876a4a55a07b59c9c4c46598f02b02411dc3b45c/fonttools-4.58.4-cp312-cp312-win32.whl", hash = "sha256:636c073b4da9db053aa683db99580cac0f7c213a953b678f69acbca3443c12cc", size = 2187428, upload-time = "2025-06-13T17:24:36.996Z" }, - { url = "https://files.pythonhosted.org/packages/46/e6/fe50183b1a0e1018e7487ee740fa8bb127b9f5075a41e20d017201e8ab14/fonttools-4.58.4-cp312-cp312-win_amd64.whl", hash = "sha256:82e8470535743409b30913ba2822e20077acf9ea70acec40b10fcf5671dceb58", size = 2236649, upload-time = "2025-06-13T17:24:38.985Z" }, - { url = "https://files.pythonhosted.org/packages/d4/4f/c05cab5fc1a4293e6bc535c6cb272607155a0517700f5418a4165b7f9ec8/fonttools-4.58.4-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:5f4a64846495c543796fa59b90b7a7a9dff6839bd852741ab35a71994d685c6d", size = 2745197, upload-time = "2025-06-13T17:24:40.645Z" }, - { url = "https://files.pythonhosted.org/packages/3e/d3/49211b1f96ae49308f4f78ca7664742377a6867f00f704cdb31b57e4b432/fonttools-4.58.4-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e80661793a5d4d7ad132a2aa1eae2e160fbdbb50831a0edf37c7c63b2ed36574", size = 2317272, upload-time = "2025-06-13T17:24:43.428Z" }, - { url = "https://files.pythonhosted.org/packages/b2/11/c9972e46a6abd752a40a46960e431c795ad1f306775fc1f9e8c3081a1274/fonttools-4.58.4-cp313-cp313-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:fe5807fc64e4ba5130f1974c045a6e8d795f3b7fb6debfa511d1773290dbb76b", size = 4877184, upload-time = "2025-06-13T17:24:45.527Z" }, - { url = "https://files.pythonhosted.org/packages/ea/24/5017c01c9ef8df572cc9eaf9f12be83ad8ed722ff6dc67991d3d752956e4/fonttools-4.58.4-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b610b9bef841cb8f4b50472494158b1e347d15cad56eac414c722eda695a6cfd", size = 4939445, upload-time = "2025-06-13T17:24:47.647Z" }, - { url = "https://files.pythonhosted.org/packages/79/b0/538cc4d0284b5a8826b4abed93a69db52e358525d4b55c47c8cef3669767/fonttools-4.58.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:2daa7f0e213c38f05f054eb5e1730bd0424aebddbeac094489ea1585807dd187", size = 4878800, upload-time = "2025-06-13T17:24:49.766Z" }, - { url = "https://files.pythonhosted.org/packages/5a/9b/a891446b7a8250e65bffceb248508587958a94db467ffd33972723ab86c9/fonttools-4.58.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:66cccb6c0b944496b7f26450e9a66e997739c513ffaac728d24930df2fd9d35b", size = 5021259, upload-time = "2025-06-13T17:24:51.754Z" }, - { url = "https://files.pythonhosted.org/packages/17/b2/c4d2872cff3ace3ddd1388bf15b76a1d8d5313f0a61f234e9aed287e674d/fonttools-4.58.4-cp313-cp313-win32.whl", hash = "sha256:94d2aebb5ca59a5107825520fde596e344652c1f18170ef01dacbe48fa60c889", size = 2185824, upload-time = "2025-06-13T17:24:54.324Z" }, - { url = "https://files.pythonhosted.org/packages/98/57/cddf8bcc911d4f47dfca1956c1e3aeeb9f7c9b8e88b2a312fe8c22714e0b/fonttools-4.58.4-cp313-cp313-win_amd64.whl", hash = "sha256:b554bd6e80bba582fd326ddab296e563c20c64dca816d5e30489760e0c41529f", size = 2236382, upload-time = "2025-06-13T17:24:56.291Z" }, - { url = "https://files.pythonhosted.org/packages/0b/2f/c536b5b9bb3c071e91d536a4d11f969e911dbb6b227939f4c5b0bca090df/fonttools-4.58.4-py3-none-any.whl", hash = "sha256:a10ce13a13f26cbb9f37512a4346bb437ad7e002ff6fa966a7ce7ff5ac3528bd", size = 1114660, upload-time = "2025-06-13T17:25:13.321Z" }, +version = "4.58.5" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/52/97/5735503e58d3816b0989955ef9b2df07e4c99b246469bd8b3823a14095da/fonttools-4.58.5.tar.gz", hash = "sha256:b2a35b0a19f1837284b3a23dd64fd7761b8911d50911ecd2bdbaf5b2d1b5df9c", size = 3526243, upload-time = "2025-07-03T14:04:47.736Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/14/50/26c683bf6f30dcbde6955c8e07ec6af23764aab86ff06b36383654ab6739/fonttools-4.58.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:cda226253bf14c559bc5a17c570d46abd70315c9a687d91c0e01147f87736182", size = 2769557, upload-time = "2025-07-03T14:03:35.383Z" }, + { url = "https://files.pythonhosted.org/packages/b1/00/c3c75fb6196b9ff9988e6a82319ae23f4ae7098e1c01e2408e58d2e7d9c7/fonttools-4.58.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:83a96e4a4e65efd6c098da549ec34f328f08963acd2d7bc910ceba01d2dc73e6", size = 2329367, upload-time = "2025-07-03T14:03:37.322Z" }, + { url = "https://files.pythonhosted.org/packages/59/e9/6946366c8e88650c199da9b284559de5d47a6e66ed6d175a166953347959/fonttools-4.58.5-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2d172b92dff59ef8929b4452d5a7b19b8e92081aa87bfb2d82b03b1ff14fc667", size = 5019491, upload-time = "2025-07-03T14:03:39.759Z" }, + { url = "https://files.pythonhosted.org/packages/76/12/2f3f7d09bba7a93bd48dcb54b170fba665f0b7e80e959ac831b907d40785/fonttools-4.58.5-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0bfddfd09aafbbfb3bd98ae67415fbe51eccd614c17db0c8844fe724fbc5d43d", size = 4961579, upload-time = "2025-07-03T14:03:41.611Z" }, + { url = "https://files.pythonhosted.org/packages/2c/95/87e84071189e51c714074646dfac8275b2e9c6b2b118600529cc74f7451e/fonttools-4.58.5-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:cfde5045f1bc92ad11b4b7551807564045a1b38cb037eb3c2bc4e737cd3a8d0f", size = 4997792, upload-time = "2025-07-03T14:03:44.529Z" }, + { url = "https://files.pythonhosted.org/packages/73/47/5c4df7473ecbeb8aa4e01373e4f614ca33f53227fe13ae673c6d5ca99be7/fonttools-4.58.5-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:3515ac47a9a5ac025d2899d195198314023d89492340ba86e4ba79451f7518a8", size = 5109361, upload-time = "2025-07-03T14:03:46.693Z" }, + { url = "https://files.pythonhosted.org/packages/06/00/31406853c570210232b845e08e5a566e15495910790381566ffdbdc7f9a2/fonttools-4.58.5-cp311-cp311-win32.whl", hash = "sha256:9f7e2ab9c10b6811b4f12a0768661325a48e664ec0a0530232c1605896a598db", size = 2201369, upload-time = "2025-07-03T14:03:48.885Z" }, + { url = "https://files.pythonhosted.org/packages/c5/90/ac0facb57962cef53a5734d0be5d2f2936e55aa5c62647c38ca3497263d8/fonttools-4.58.5-cp311-cp311-win_amd64.whl", hash = "sha256:126c16ec4a672c9cb5c1c255dc438d15436b470afc8e9cac25a2d39dd2dc26eb", size = 2249021, upload-time = "2025-07-03T14:03:51.232Z" }, + { url = "https://files.pythonhosted.org/packages/d6/68/66b498ee66f3e7e92fd68476c2509508082b7f57d68c0cdb4b8573f44331/fonttools-4.58.5-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:c3af3fefaafb570a03051a0d6899b8374dcf8e6a4560e42575843aef33bdbad6", size = 2754751, upload-time = "2025-07-03T14:03:52.976Z" }, + { url = "https://files.pythonhosted.org/packages/f1/1e/edbc14b79290980c3944a1f43098624bc8965f534964aa03d52041f24cb4/fonttools-4.58.5-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:688137789dbd44e8757ad77b49a771539d8069195ffa9a8bcf18176e90bbd86d", size = 2322342, upload-time = "2025-07-03T14:03:54.957Z" }, + { url = "https://files.pythonhosted.org/packages/c1/d7/3c87cf147185d91c2e946460a5cf68c236427b4a23ab96793ccb7d8017c9/fonttools-4.58.5-cp312-cp312-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:2af65836cf84cd7cb882d0b353bdc73643a497ce23b7414c26499bb8128ca1af", size = 4897011, upload-time = "2025-07-03T14:03:56.829Z" }, + { url = "https://files.pythonhosted.org/packages/a0/d6/fbb44cc85d4195fe54356658bd9f934328b4f74ae14addd90b4b5558b5c9/fonttools-4.58.5-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d2d79cfeb456bf438cb9fb87437634d4d6f228f27572ca5c5355e58472d5519d", size = 4942291, upload-time = "2025-07-03T14:03:59.204Z" }, + { url = "https://files.pythonhosted.org/packages/4d/c8/453f82e21aedf25cdc2ae619c03a73512398cec9bd8b6c3b1c571e0b6632/fonttools-4.58.5-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:0feac9dda9a48a7a342a593f35d50a5cee2dbd27a03a4c4a5192834a4853b204", size = 4886824, upload-time = "2025-07-03T14:04:01.517Z" }, + { url = "https://files.pythonhosted.org/packages/40/54/e9190001b8e22d123f78925b2f508c866d9d18531694b979277ad45d59b0/fonttools-4.58.5-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:36555230e168511e83ad8637232268649634b8dfff6ef58f46e1ebc057a041ad", size = 5038510, upload-time = "2025-07-03T14:04:03.917Z" }, + { url = "https://files.pythonhosted.org/packages/cf/9c/07cdad4774841a6304aabae939f8cbb9538cb1d8e97f5016b334da98e73a/fonttools-4.58.5-cp312-cp312-win32.whl", hash = "sha256:26ec05319353842d127bd02516eacb25b97ca83966e40e9ad6fab85cab0576f4", size = 2188459, upload-time = "2025-07-03T14:04:06.103Z" }, + { url = "https://files.pythonhosted.org/packages/0e/4d/1eaaad22781d55f49d1b184563842172aeb6a4fe53c029e503be81114314/fonttools-4.58.5-cp312-cp312-win_amd64.whl", hash = "sha256:778a632e538f82c1920579c0c01566a8f83dc24470c96efbf2fbac698907f569", size = 2236565, upload-time = "2025-07-03T14:04:08.27Z" }, + { url = "https://files.pythonhosted.org/packages/3a/ee/764dd8b99891f815241f449345863cfed9e546923d9cef463f37fd1d7168/fonttools-4.58.5-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:f4b6f1360da13cecc88c0d60716145b31e1015fbe6a59e32f73a4404e2ea92cf", size = 2745867, upload-time = "2025-07-03T14:04:10.586Z" }, + { url = "https://files.pythonhosted.org/packages/e2/23/8fef484c02fef55e226dfeac4339a015c5480b6a496064058491759ac71e/fonttools-4.58.5-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:4a036822e915692aa2c03e2decc60f49a8190f8111b639c947a4f4e5774d0d7a", size = 2317933, upload-time = "2025-07-03T14:04:12.335Z" }, + { url = "https://files.pythonhosted.org/packages/ab/47/f92b135864fa777e11ad68420bf89446c91a572fe2782745586f8e6aac0c/fonttools-4.58.5-cp313-cp313-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:a6d7709fcf4577b0f294ee6327088884ca95046e1eccde87c53bbba4d5008541", size = 4877844, upload-time = "2025-07-03T14:04:14.58Z" }, + { url = "https://files.pythonhosted.org/packages/3e/65/6c1a83511d8ac32411930495645edb3f8dfabebcb78f08cf6009ba2585ec/fonttools-4.58.5-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b9b5099ca99b79d6d67162778b1b1616fc0e1de02c1a178248a0da8d78a33852", size = 4940106, upload-time = "2025-07-03T14:04:16.563Z" }, + { url = "https://files.pythonhosted.org/packages/fa/90/df8eb77d6cf266cbbba01866a1349a3e9121e0a63002cf8d6754e994f755/fonttools-4.58.5-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:3f2c05a8d82a4d15aebfdb3506e90793aea16e0302cec385134dd960647a36c0", size = 4879458, upload-time = "2025-07-03T14:04:19.584Z" }, + { url = "https://files.pythonhosted.org/packages/26/b1/e32f8de51b7afcfea6ad62780da2fa73212c43a32cd8cafcc852189d7949/fonttools-4.58.5-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:79f0c4b1cc63839b61deeac646d8dba46f8ed40332c2ac1b9997281462c2e4ba", size = 5021917, upload-time = "2025-07-03T14:04:21.736Z" }, + { url = "https://files.pythonhosted.org/packages/89/72/578aa7fe32918dd763c62f447aaed672d665ee10e3eeb1725f4d6493fe96/fonttools-4.58.5-cp313-cp313-win32.whl", hash = "sha256:a1a9a2c462760976882131cbab7d63407813413a2d32cd699e86a1ff22bf7aa5", size = 2186827, upload-time = "2025-07-03T14:04:24.237Z" }, + { url = "https://files.pythonhosted.org/packages/71/a3/21e921b16cb9c029d3308e0cb79c9a937e9ff1fc1ee28c2419f0957b9e7c/fonttools-4.58.5-cp313-cp313-win_amd64.whl", hash = "sha256:bca61b14031a4b7dc87e14bf6ca34c275f8e4b9f7a37bc2fe746b532a924cf30", size = 2235706, upload-time = "2025-07-03T14:04:26.082Z" }, + { url = "https://files.pythonhosted.org/packages/d7/d4/1d85a1996b6188cd2713230e002d79a6f3a289bb17cef600cba385848b72/fonttools-4.58.5-py3-none-any.whl", hash = "sha256:e48a487ed24d9b611c5c4b25db1e50e69e9854ca2670e39a3486ffcd98863ec4", size = 1115318, upload-time = "2025-07-03T14:04:45.378Z" }, ] [[package]] @@ -657,15 +657,15 @@ wheels = [ [[package]] name = "hypothesis" -version = "6.135.16" +version = "6.135.24" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "attrs" }, { name = "sortedcontainers" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/3f/91/c8d9af23d6a2a0feb7490ab10a3d78e6ac35ae75887c7fe442d14ad6d6f9/hypothesis-6.135.16.tar.gz", hash = "sha256:6131ea0b698e69bad62aae915988b8d00a6ac974351d0830db74c5fffc68c418", size = 452900, upload-time = "2025-06-26T03:36:33.624Z" } +sdist = { url = "https://files.pythonhosted.org/packages/cf/ae/f846b67ce9fc80cf51cece6b7adaa3fe2de4251242d142e241ce5d4aa26f/hypothesis-6.135.24.tar.gz", hash = "sha256:e301aeb2691ec0a1f62bfc405eaa966055d603e328cd854c1ed59e1728e35ab6", size = 454011, upload-time = "2025-07-03T02:46:51.776Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/73/e1/196cd69190ba95f2538d577417ac6383a10cb1fabc06917b54e1e437dcaa/hypothesis-6.135.16-py3-none-any.whl", hash = "sha256:0a64697ef0afa4532535209a9bcd99919d59093ff894622e8a001fb773b59d8a", size = 519164, upload-time = "2025-06-26T03:36:30.12Z" }, + { url = "https://files.pythonhosted.org/packages/ed/cb/c38acf27826a96712302229622f32dd356b9c4fbe52a3e9f615706027af8/hypothesis-6.135.24-py3-none-any.whl", hash = "sha256:88ed21fbfa481ca9851a9080841b3caca14cd4ed51a165dfae8006325775ee72", size = 520920, upload-time = "2025-07-03T02:46:48.286Z" }, ] [[package]] @@ -721,7 +721,7 @@ wheels = [ [[package]] name = "ipython" -version = "9.3.0" +version = "9.4.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "colorama", marker = "sys_platform == 'win32'" }, @@ -736,9 +736,9 @@ dependencies = [ { name = "traitlets" }, { name = "typing-extensions", marker = "python_full_version < '3.12'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/dc/09/4c7e06b96fbd203e06567b60fb41b06db606b6a82db6db7b2c85bb72a15c/ipython-9.3.0.tar.gz", hash = "sha256:79eb896f9f23f50ad16c3bc205f686f6e030ad246cc309c6279a242b14afe9d8", size = 4426460, upload-time = "2025-05-31T16:34:55.678Z" } +sdist = { url = "https://files.pythonhosted.org/packages/54/80/406f9e3bde1c1fd9bf5a0be9d090f8ae623e401b7670d8f6fdf2ab679891/ipython-9.4.0.tar.gz", hash = "sha256:c033c6d4e7914c3d9768aabe76bbe87ba1dc66a92a05db6bfa1125d81f2ee270", size = 4385338, upload-time = "2025-07-01T11:11:30.606Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/3c/99/9ed3d52d00f1846679e3aa12e2326ac7044b5e7f90dc822b60115fa533ca/ipython-9.3.0-py3-none-any.whl", hash = "sha256:1a0b6dd9221a1f5dddf725b57ac0cb6fddc7b5f470576231ae9162b9b3455a04", size = 605320, upload-time = "2025-05-31T16:34:52.154Z" }, + { url = "https://files.pythonhosted.org/packages/63/f8/0031ee2b906a15a33d6bfc12dd09c3dfa966b3cb5b284ecfb7549e6ac3c4/ipython-9.4.0-py3-none-any.whl", hash = "sha256:25850f025a446d9b359e8d296ba175a36aedd32e83ca9b5060430fe16801f066", size = 611021, upload-time = "2025-07-01T11:11:27.85Z" }, ] [[package]] @@ -1511,61 +1511,86 @@ wheels = [ [[package]] name = "pillow" -version = "11.2.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/af/cb/bb5c01fcd2a69335b86c22142b2bccfc3464087efb7fd382eee5ffc7fdf7/pillow-11.2.1.tar.gz", hash = "sha256:a64dd61998416367b7ef979b73d3a85853ba9bec4c2925f74e588879a58716b6", size = 47026707, upload-time = "2025-04-12T17:50:03.289Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/68/08/3fbf4b98924c73037a8e8b4c2c774784805e0fb4ebca6c5bb60795c40125/pillow-11.2.1-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:35ca289f712ccfc699508c4658a1d14652e8033e9b69839edf83cbdd0ba39e70", size = 3198450, upload-time = "2025-04-12T17:47:37.135Z" }, - { url = "https://files.pythonhosted.org/packages/84/92/6505b1af3d2849d5e714fc75ba9e69b7255c05ee42383a35a4d58f576b16/pillow-11.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e0409af9f829f87a2dfb7e259f78f317a5351f2045158be321fd135973fff7bf", size = 3030550, upload-time = "2025-04-12T17:47:39.345Z" }, - { url = "https://files.pythonhosted.org/packages/3c/8c/ac2f99d2a70ff966bc7eb13dacacfaab57c0549b2ffb351b6537c7840b12/pillow-11.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d4e5c5edee874dce4f653dbe59db7c73a600119fbea8d31f53423586ee2aafd7", size = 4415018, upload-time = "2025-04-12T17:47:41.128Z" }, - { url = "https://files.pythonhosted.org/packages/1f/e3/0a58b5d838687f40891fff9cbaf8669f90c96b64dc8f91f87894413856c6/pillow-11.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b93a07e76d13bff9444f1a029e0af2964e654bfc2e2c2d46bfd080df5ad5f3d8", size = 4498006, upload-time = "2025-04-12T17:47:42.912Z" }, - { url = "https://files.pythonhosted.org/packages/21/f5/6ba14718135f08fbfa33308efe027dd02b781d3f1d5c471444a395933aac/pillow-11.2.1-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:e6def7eed9e7fa90fde255afaf08060dc4b343bbe524a8f69bdd2a2f0018f600", size = 4517773, upload-time = "2025-04-12T17:47:44.611Z" }, - { url = "https://files.pythonhosted.org/packages/20/f2/805ad600fc59ebe4f1ba6129cd3a75fb0da126975c8579b8f57abeb61e80/pillow-11.2.1-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:8f4f3724c068be008c08257207210c138d5f3731af6c155a81c2b09a9eb3a788", size = 4607069, upload-time = "2025-04-12T17:47:46.46Z" }, - { url = "https://files.pythonhosted.org/packages/71/6b/4ef8a288b4bb2e0180cba13ca0a519fa27aa982875882392b65131401099/pillow-11.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:a0a6709b47019dff32e678bc12c63008311b82b9327613f534e496dacaefb71e", size = 4583460, upload-time = "2025-04-12T17:47:49.255Z" }, - { url = "https://files.pythonhosted.org/packages/62/ae/f29c705a09cbc9e2a456590816e5c234382ae5d32584f451c3eb41a62062/pillow-11.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f6b0c664ccb879109ee3ca702a9272d877f4fcd21e5eb63c26422fd6e415365e", size = 4661304, upload-time = "2025-04-12T17:47:51.067Z" }, - { url = "https://files.pythonhosted.org/packages/6e/1a/c8217b6f2f73794a5e219fbad087701f412337ae6dbb956db37d69a9bc43/pillow-11.2.1-cp311-cp311-win32.whl", hash = "sha256:cc5d875d56e49f112b6def6813c4e3d3036d269c008bf8aef72cd08d20ca6df6", size = 2331809, upload-time = "2025-04-12T17:47:54.425Z" }, - { url = "https://files.pythonhosted.org/packages/e2/72/25a8f40170dc262e86e90f37cb72cb3de5e307f75bf4b02535a61afcd519/pillow-11.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:0f5c7eda47bf8e3c8a283762cab94e496ba977a420868cb819159980b6709193", size = 2676338, upload-time = "2025-04-12T17:47:56.535Z" }, - { url = "https://files.pythonhosted.org/packages/06/9e/76825e39efee61efea258b479391ca77d64dbd9e5804e4ad0fa453b4ba55/pillow-11.2.1-cp311-cp311-win_arm64.whl", hash = "sha256:4d375eb838755f2528ac8cbc926c3e31cc49ca4ad0cf79cff48b20e30634a4a7", size = 2414918, upload-time = "2025-04-12T17:47:58.217Z" }, - { url = "https://files.pythonhosted.org/packages/c7/40/052610b15a1b8961f52537cc8326ca6a881408bc2bdad0d852edeb6ed33b/pillow-11.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:78afba22027b4accef10dbd5eed84425930ba41b3ea0a86fa8d20baaf19d807f", size = 3190185, upload-time = "2025-04-12T17:48:00.417Z" }, - { url = "https://files.pythonhosted.org/packages/e5/7e/b86dbd35a5f938632093dc40d1682874c33dcfe832558fc80ca56bfcb774/pillow-11.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:78092232a4ab376a35d68c4e6d5e00dfd73454bd12b230420025fbe178ee3b0b", size = 3030306, upload-time = "2025-04-12T17:48:02.391Z" }, - { url = "https://files.pythonhosted.org/packages/a4/5c/467a161f9ed53e5eab51a42923c33051bf8d1a2af4626ac04f5166e58e0c/pillow-11.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:25a5f306095c6780c52e6bbb6109624b95c5b18e40aab1c3041da3e9e0cd3e2d", size = 4416121, upload-time = "2025-04-12T17:48:04.554Z" }, - { url = "https://files.pythonhosted.org/packages/62/73/972b7742e38ae0e2ac76ab137ca6005dcf877480da0d9d61d93b613065b4/pillow-11.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c7b29dbd4281923a2bfe562acb734cee96bbb129e96e6972d315ed9f232bef4", size = 4501707, upload-time = "2025-04-12T17:48:06.831Z" }, - { url = "https://files.pythonhosted.org/packages/e4/3a/427e4cb0b9e177efbc1a84798ed20498c4f233abde003c06d2650a6d60cb/pillow-11.2.1-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:3e645b020f3209a0181a418bffe7b4a93171eef6c4ef6cc20980b30bebf17b7d", size = 4522921, upload-time = "2025-04-12T17:48:09.229Z" }, - { url = "https://files.pythonhosted.org/packages/fe/7c/d8b1330458e4d2f3f45d9508796d7caf0c0d3764c00c823d10f6f1a3b76d/pillow-11.2.1-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:b2dbea1012ccb784a65349f57bbc93730b96e85b42e9bf7b01ef40443db720b4", size = 4612523, upload-time = "2025-04-12T17:48:11.631Z" }, - { url = "https://files.pythonhosted.org/packages/b3/2f/65738384e0b1acf451de5a573d8153fe84103772d139e1e0bdf1596be2ea/pillow-11.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:da3104c57bbd72948d75f6a9389e6727d2ab6333c3617f0a89d72d4940aa0443", size = 4587836, upload-time = "2025-04-12T17:48:13.592Z" }, - { url = "https://files.pythonhosted.org/packages/6a/c5/e795c9f2ddf3debb2dedd0df889f2fe4b053308bb59a3cc02a0cd144d641/pillow-11.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:598174aef4589af795f66f9caab87ba4ff860ce08cd5bb447c6fc553ffee603c", size = 4669390, upload-time = "2025-04-12T17:48:15.938Z" }, - { url = "https://files.pythonhosted.org/packages/96/ae/ca0099a3995976a9fce2f423166f7bff9b12244afdc7520f6ed38911539a/pillow-11.2.1-cp312-cp312-win32.whl", hash = "sha256:1d535df14716e7f8776b9e7fee118576d65572b4aad3ed639be9e4fa88a1cad3", size = 2332309, upload-time = "2025-04-12T17:48:17.885Z" }, - { url = "https://files.pythonhosted.org/packages/7c/18/24bff2ad716257fc03da964c5e8f05d9790a779a8895d6566e493ccf0189/pillow-11.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:14e33b28bf17c7a38eede290f77db7c664e4eb01f7869e37fa98a5aa95978941", size = 2676768, upload-time = "2025-04-12T17:48:19.655Z" }, - { url = "https://files.pythonhosted.org/packages/da/bb/e8d656c9543276517ee40184aaa39dcb41e683bca121022f9323ae11b39d/pillow-11.2.1-cp312-cp312-win_arm64.whl", hash = "sha256:21e1470ac9e5739ff880c211fc3af01e3ae505859392bf65458c224d0bf283eb", size = 2415087, upload-time = "2025-04-12T17:48:21.991Z" }, - { url = "https://files.pythonhosted.org/packages/36/9c/447528ee3776e7ab8897fe33697a7ff3f0475bb490c5ac1456a03dc57956/pillow-11.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:fdec757fea0b793056419bca3e9932eb2b0ceec90ef4813ea4c1e072c389eb28", size = 3190098, upload-time = "2025-04-12T17:48:23.915Z" }, - { url = "https://files.pythonhosted.org/packages/b5/09/29d5cd052f7566a63e5b506fac9c60526e9ecc553825551333e1e18a4858/pillow-11.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:b0e130705d568e2f43a17bcbe74d90958e8a16263868a12c3e0d9c8162690830", size = 3030166, upload-time = "2025-04-12T17:48:25.738Z" }, - { url = "https://files.pythonhosted.org/packages/71/5d/446ee132ad35e7600652133f9c2840b4799bbd8e4adba881284860da0a36/pillow-11.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7bdb5e09068332578214cadd9c05e3d64d99e0e87591be22a324bdbc18925be0", size = 4408674, upload-time = "2025-04-12T17:48:27.908Z" }, - { url = "https://files.pythonhosted.org/packages/69/5f/cbe509c0ddf91cc3a03bbacf40e5c2339c4912d16458fcb797bb47bcb269/pillow-11.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d189ba1bebfbc0c0e529159631ec72bb9e9bc041f01ec6d3233d6d82eb823bc1", size = 4496005, upload-time = "2025-04-12T17:48:29.888Z" }, - { url = "https://files.pythonhosted.org/packages/f9/b3/dd4338d8fb8a5f312021f2977fb8198a1184893f9b00b02b75d565c33b51/pillow-11.2.1-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:191955c55d8a712fab8934a42bfefbf99dd0b5875078240943f913bb66d46d9f", size = 4518707, upload-time = "2025-04-12T17:48:31.874Z" }, - { url = "https://files.pythonhosted.org/packages/13/eb/2552ecebc0b887f539111c2cd241f538b8ff5891b8903dfe672e997529be/pillow-11.2.1-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:ad275964d52e2243430472fc5d2c2334b4fc3ff9c16cb0a19254e25efa03a155", size = 4610008, upload-time = "2025-04-12T17:48:34.422Z" }, - { url = "https://files.pythonhosted.org/packages/72/d1/924ce51bea494cb6e7959522d69d7b1c7e74f6821d84c63c3dc430cbbf3b/pillow-11.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:750f96efe0597382660d8b53e90dd1dd44568a8edb51cb7f9d5d918b80d4de14", size = 4585420, upload-time = "2025-04-12T17:48:37.641Z" }, - { url = "https://files.pythonhosted.org/packages/43/ab/8f81312d255d713b99ca37479a4cb4b0f48195e530cdc1611990eb8fd04b/pillow-11.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:fe15238d3798788d00716637b3d4e7bb6bde18b26e5d08335a96e88564a36b6b", size = 4667655, upload-time = "2025-04-12T17:48:39.652Z" }, - { url = "https://files.pythonhosted.org/packages/94/86/8f2e9d2dc3d308dfd137a07fe1cc478df0a23d42a6c4093b087e738e4827/pillow-11.2.1-cp313-cp313-win32.whl", hash = "sha256:3fe735ced9a607fee4f481423a9c36701a39719252a9bb251679635f99d0f7d2", size = 2332329, upload-time = "2025-04-12T17:48:41.765Z" }, - { url = "https://files.pythonhosted.org/packages/6d/ec/1179083b8d6067a613e4d595359b5fdea65d0a3b7ad623fee906e1b3c4d2/pillow-11.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:74ee3d7ecb3f3c05459ba95eed5efa28d6092d751ce9bf20e3e253a4e497e691", size = 2676388, upload-time = "2025-04-12T17:48:43.625Z" }, - { url = "https://files.pythonhosted.org/packages/23/f1/2fc1e1e294de897df39fa8622d829b8828ddad938b0eaea256d65b84dd72/pillow-11.2.1-cp313-cp313-win_arm64.whl", hash = "sha256:5119225c622403afb4b44bad4c1ca6c1f98eed79db8d3bc6e4e160fc6339d66c", size = 2414950, upload-time = "2025-04-12T17:48:45.475Z" }, - { url = "https://files.pythonhosted.org/packages/c4/3e/c328c48b3f0ead7bab765a84b4977acb29f101d10e4ef57a5e3400447c03/pillow-11.2.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:8ce2e8411c7aaef53e6bb29fe98f28cd4fbd9a1d9be2eeea434331aac0536b22", size = 3192759, upload-time = "2025-04-12T17:48:47.866Z" }, - { url = "https://files.pythonhosted.org/packages/18/0e/1c68532d833fc8b9f404d3a642991441d9058eccd5606eab31617f29b6d4/pillow-11.2.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:9ee66787e095127116d91dea2143db65c7bb1e232f617aa5957c0d9d2a3f23a7", size = 3033284, upload-time = "2025-04-12T17:48:50.189Z" }, - { url = "https://files.pythonhosted.org/packages/b7/cb/6faf3fb1e7705fd2db74e070f3bf6f88693601b0ed8e81049a8266de4754/pillow-11.2.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9622e3b6c1d8b551b6e6f21873bdcc55762b4b2126633014cea1803368a9aa16", size = 4445826, upload-time = "2025-04-12T17:48:52.346Z" }, - { url = "https://files.pythonhosted.org/packages/07/94/8be03d50b70ca47fb434a358919d6a8d6580f282bbb7af7e4aa40103461d/pillow-11.2.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:63b5dff3a68f371ea06025a1a6966c9a1e1ee452fc8020c2cd0ea41b83e9037b", size = 4527329, upload-time = "2025-04-12T17:48:54.403Z" }, - { url = "https://files.pythonhosted.org/packages/fd/a4/bfe78777076dc405e3bd2080bc32da5ab3945b5a25dc5d8acaa9de64a162/pillow-11.2.1-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:31df6e2d3d8fc99f993fd253e97fae451a8db2e7207acf97859732273e108406", size = 4549049, upload-time = "2025-04-12T17:48:56.383Z" }, - { url = "https://files.pythonhosted.org/packages/65/4d/eaf9068dc687c24979e977ce5677e253624bd8b616b286f543f0c1b91662/pillow-11.2.1-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:062b7a42d672c45a70fa1f8b43d1d38ff76b63421cbbe7f88146b39e8a558d91", size = 4635408, upload-time = "2025-04-12T17:48:58.782Z" }, - { url = "https://files.pythonhosted.org/packages/1d/26/0fd443365d9c63bc79feb219f97d935cd4b93af28353cba78d8e77b61719/pillow-11.2.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:4eb92eca2711ef8be42fd3f67533765d9fd043b8c80db204f16c8ea62ee1a751", size = 4614863, upload-time = "2025-04-12T17:49:00.709Z" }, - { url = "https://files.pythonhosted.org/packages/49/65/dca4d2506be482c2c6641cacdba5c602bc76d8ceb618fd37de855653a419/pillow-11.2.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:f91ebf30830a48c825590aede79376cb40f110b387c17ee9bd59932c961044f9", size = 4692938, upload-time = "2025-04-12T17:49:02.946Z" }, - { url = "https://files.pythonhosted.org/packages/b3/92/1ca0c3f09233bd7decf8f7105a1c4e3162fb9142128c74adad0fb361b7eb/pillow-11.2.1-cp313-cp313t-win32.whl", hash = "sha256:e0b55f27f584ed623221cfe995c912c61606be8513bfa0e07d2c674b4516d9dd", size = 2335774, upload-time = "2025-04-12T17:49:04.889Z" }, - { url = "https://files.pythonhosted.org/packages/a5/ac/77525347cb43b83ae905ffe257bbe2cc6fd23acb9796639a1f56aa59d191/pillow-11.2.1-cp313-cp313t-win_amd64.whl", hash = "sha256:36d6b82164c39ce5482f649b437382c0fb2395eabc1e2b1702a6deb8ad647d6e", size = 2681895, upload-time = "2025-04-12T17:49:06.635Z" }, - { url = "https://files.pythonhosted.org/packages/67/32/32dc030cfa91ca0fc52baebbba2e009bb001122a1daa8b6a79ad830b38d3/pillow-11.2.1-cp313-cp313t-win_arm64.whl", hash = "sha256:225c832a13326e34f212d2072982bb1adb210e0cc0b153e688743018c94a2681", size = 2417234, upload-time = "2025-04-12T17:49:08.399Z" }, - { url = "https://files.pythonhosted.org/packages/a4/ad/2613c04633c7257d9481ab21d6b5364b59fc5d75faafd7cb8693523945a3/pillow-11.2.1-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:80f1df8dbe9572b4b7abdfa17eb5d78dd620b1d55d9e25f834efdbee872d3aed", size = 3181734, upload-time = "2025-04-12T17:49:46.789Z" }, - { url = "https://files.pythonhosted.org/packages/a4/fd/dcdda4471ed667de57bb5405bb42d751e6cfdd4011a12c248b455c778e03/pillow-11.2.1-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:ea926cfbc3957090becbcbbb65ad177161a2ff2ad578b5a6ec9bb1e1cd78753c", size = 2999841, upload-time = "2025-04-12T17:49:48.812Z" }, - { url = "https://files.pythonhosted.org/packages/ac/89/8a2536e95e77432833f0db6fd72a8d310c8e4272a04461fb833eb021bf94/pillow-11.2.1-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:738db0e0941ca0376804d4de6a782c005245264edaa253ffce24e5a15cbdc7bd", size = 3437470, upload-time = "2025-04-12T17:49:50.831Z" }, - { url = "https://files.pythonhosted.org/packages/9d/8f/abd47b73c60712f88e9eda32baced7bfc3e9bd6a7619bb64b93acff28c3e/pillow-11.2.1-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9db98ab6565c69082ec9b0d4e40dd9f6181dab0dd236d26f7a50b8b9bfbd5076", size = 3460013, upload-time = "2025-04-12T17:49:53.278Z" }, - { url = "https://files.pythonhosted.org/packages/f6/20/5c0a0aa83b213b7a07ec01e71a3d6ea2cf4ad1d2c686cc0168173b6089e7/pillow-11.2.1-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:036e53f4170e270ddb8797d4c590e6dd14d28e15c7da375c18978045f7e6c37b", size = 3527165, upload-time = "2025-04-12T17:49:55.164Z" }, - { url = "https://files.pythonhosted.org/packages/58/0e/2abab98a72202d91146abc839e10c14f7cf36166f12838ea0c4db3ca6ecb/pillow-11.2.1-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:14f73f7c291279bd65fda51ee87affd7c1e097709f7fdd0188957a16c264601f", size = 3571586, upload-time = "2025-04-12T17:49:57.171Z" }, - { url = "https://files.pythonhosted.org/packages/21/2c/5e05f58658cf49b6667762cca03d6e7d85cededde2caf2ab37b81f80e574/pillow-11.2.1-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:208653868d5c9ecc2b327f9b9ef34e0e42a4cdd172c2988fd81d62d2bc9bc044", size = 2674751, upload-time = "2025-04-12T17:49:59.628Z" }, +version = "11.3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f3/0d/d0d6dea55cd152ce3d6767bb38a8fc10e33796ba4ba210cbab9354b6d238/pillow-11.3.0.tar.gz", hash = "sha256:3828ee7586cd0b2091b6209e5ad53e20d0649bbe87164a459d0676e035e8f523", size = 47113069, upload-time = "2025-07-01T09:16:30.666Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/db/26/77f8ed17ca4ffd60e1dcd220a6ec6d71210ba398cfa33a13a1cd614c5613/pillow-11.3.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:1cd110edf822773368b396281a2293aeb91c90a2db00d78ea43e7e861631b722", size = 5316531, upload-time = "2025-07-01T09:13:59.203Z" }, + { url = "https://files.pythonhosted.org/packages/cb/39/ee475903197ce709322a17a866892efb560f57900d9af2e55f86db51b0a5/pillow-11.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9c412fddd1b77a75aa904615ebaa6001f169b26fd467b4be93aded278266b288", size = 4686560, upload-time = "2025-07-01T09:14:01.101Z" }, + { url = "https://files.pythonhosted.org/packages/d5/90/442068a160fd179938ba55ec8c97050a612426fae5ec0a764e345839f76d/pillow-11.3.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:7d1aa4de119a0ecac0a34a9c8bde33f34022e2e8f99104e47a3ca392fd60e37d", size = 5870978, upload-time = "2025-07-03T13:09:55.638Z" }, + { url = "https://files.pythonhosted.org/packages/13/92/dcdd147ab02daf405387f0218dcf792dc6dd5b14d2573d40b4caeef01059/pillow-11.3.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:91da1d88226663594e3f6b4b8c3c8d85bd504117d043740a8e0ec449087cc494", size = 7641168, upload-time = "2025-07-03T13:10:00.37Z" }, + { url = "https://files.pythonhosted.org/packages/6e/db/839d6ba7fd38b51af641aa904e2960e7a5644d60ec754c046b7d2aee00e5/pillow-11.3.0-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:643f189248837533073c405ec2f0bb250ba54598cf80e8c1e043381a60632f58", size = 5973053, upload-time = "2025-07-01T09:14:04.491Z" }, + { url = "https://files.pythonhosted.org/packages/f2/2f/d7675ecae6c43e9f12aa8d58b6012683b20b6edfbdac7abcb4e6af7a3784/pillow-11.3.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:106064daa23a745510dabce1d84f29137a37224831d88eb4ce94bb187b1d7e5f", size = 6640273, upload-time = "2025-07-01T09:14:06.235Z" }, + { url = "https://files.pythonhosted.org/packages/45/ad/931694675ede172e15b2ff03c8144a0ddaea1d87adb72bb07655eaffb654/pillow-11.3.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:cd8ff254faf15591e724dc7c4ddb6bf4793efcbe13802a4ae3e863cd300b493e", size = 6082043, upload-time = "2025-07-01T09:14:07.978Z" }, + { url = "https://files.pythonhosted.org/packages/3a/04/ba8f2b11fc80d2dd462d7abec16351b45ec99cbbaea4387648a44190351a/pillow-11.3.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:932c754c2d51ad2b2271fd01c3d121daaa35e27efae2a616f77bf164bc0b3e94", size = 6715516, upload-time = "2025-07-01T09:14:10.233Z" }, + { url = "https://files.pythonhosted.org/packages/48/59/8cd06d7f3944cc7d892e8533c56b0acb68399f640786313275faec1e3b6f/pillow-11.3.0-cp311-cp311-win32.whl", hash = "sha256:b4b8f3efc8d530a1544e5962bd6b403d5f7fe8b9e08227c6b255f98ad82b4ba0", size = 6274768, upload-time = "2025-07-01T09:14:11.921Z" }, + { url = "https://files.pythonhosted.org/packages/f1/cc/29c0f5d64ab8eae20f3232da8f8571660aa0ab4b8f1331da5c2f5f9a938e/pillow-11.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:1a992e86b0dd7aeb1f053cd506508c0999d710a8f07b4c791c63843fc6a807ac", size = 6986055, upload-time = "2025-07-01T09:14:13.623Z" }, + { url = "https://files.pythonhosted.org/packages/c6/df/90bd886fabd544c25addd63e5ca6932c86f2b701d5da6c7839387a076b4a/pillow-11.3.0-cp311-cp311-win_arm64.whl", hash = "sha256:30807c931ff7c095620fe04448e2c2fc673fcbb1ffe2a7da3fb39613489b1ddd", size = 2423079, upload-time = "2025-07-01T09:14:15.268Z" }, + { url = "https://files.pythonhosted.org/packages/40/fe/1bc9b3ee13f68487a99ac9529968035cca2f0a51ec36892060edcc51d06a/pillow-11.3.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:fdae223722da47b024b867c1ea0be64e0df702c5e0a60e27daad39bf960dd1e4", size = 5278800, upload-time = "2025-07-01T09:14:17.648Z" }, + { url = "https://files.pythonhosted.org/packages/2c/32/7e2ac19b5713657384cec55f89065fb306b06af008cfd87e572035b27119/pillow-11.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:921bd305b10e82b4d1f5e802b6850677f965d8394203d182f078873851dada69", size = 4686296, upload-time = "2025-07-01T09:14:19.828Z" }, + { url = "https://files.pythonhosted.org/packages/8e/1e/b9e12bbe6e4c2220effebc09ea0923a07a6da1e1f1bfbc8d7d29a01ce32b/pillow-11.3.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:eb76541cba2f958032d79d143b98a3a6b3ea87f0959bbe256c0b5e416599fd5d", size = 5871726, upload-time = "2025-07-03T13:10:04.448Z" }, + { url = "https://files.pythonhosted.org/packages/8d/33/e9200d2bd7ba00dc3ddb78df1198a6e80d7669cce6c2bdbeb2530a74ec58/pillow-11.3.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:67172f2944ebba3d4a7b54f2e95c786a3a50c21b88456329314caaa28cda70f6", size = 7644652, upload-time = "2025-07-03T13:10:10.391Z" }, + { url = "https://files.pythonhosted.org/packages/41/f1/6f2427a26fc683e00d985bc391bdd76d8dd4e92fac33d841127eb8fb2313/pillow-11.3.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:97f07ed9f56a3b9b5f49d3661dc9607484e85c67e27f3e8be2c7d28ca032fec7", size = 5977787, upload-time = "2025-07-01T09:14:21.63Z" }, + { url = "https://files.pythonhosted.org/packages/e4/c9/06dd4a38974e24f932ff5f98ea3c546ce3f8c995d3f0985f8e5ba48bba19/pillow-11.3.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:676b2815362456b5b3216b4fd5bd89d362100dc6f4945154ff172e206a22c024", size = 6645236, upload-time = "2025-07-01T09:14:23.321Z" }, + { url = "https://files.pythonhosted.org/packages/40/e7/848f69fb79843b3d91241bad658e9c14f39a32f71a301bcd1d139416d1be/pillow-11.3.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3e184b2f26ff146363dd07bde8b711833d7b0202e27d13540bfe2e35a323a809", size = 6086950, upload-time = "2025-07-01T09:14:25.237Z" }, + { url = "https://files.pythonhosted.org/packages/0b/1a/7cff92e695a2a29ac1958c2a0fe4c0b2393b60aac13b04a4fe2735cad52d/pillow-11.3.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:6be31e3fc9a621e071bc17bb7de63b85cbe0bfae91bb0363c893cbe67247780d", size = 6723358, upload-time = "2025-07-01T09:14:27.053Z" }, + { url = "https://files.pythonhosted.org/packages/26/7d/73699ad77895f69edff76b0f332acc3d497f22f5d75e5360f78cbcaff248/pillow-11.3.0-cp312-cp312-win32.whl", hash = "sha256:7b161756381f0918e05e7cb8a371fff367e807770f8fe92ecb20d905d0e1c149", size = 6275079, upload-time = "2025-07-01T09:14:30.104Z" }, + { url = "https://files.pythonhosted.org/packages/8c/ce/e7dfc873bdd9828f3b6e5c2bbb74e47a98ec23cc5c74fc4e54462f0d9204/pillow-11.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:a6444696fce635783440b7f7a9fc24b3ad10a9ea3f0ab66c5905be1c19ccf17d", size = 6986324, upload-time = "2025-07-01T09:14:31.899Z" }, + { url = "https://files.pythonhosted.org/packages/16/8f/b13447d1bf0b1f7467ce7d86f6e6edf66c0ad7cf44cf5c87a37f9bed9936/pillow-11.3.0-cp312-cp312-win_arm64.whl", hash = "sha256:2aceea54f957dd4448264f9bf40875da0415c83eb85f55069d89c0ed436e3542", size = 2423067, upload-time = "2025-07-01T09:14:33.709Z" }, + { url = "https://files.pythonhosted.org/packages/1e/93/0952f2ed8db3a5a4c7a11f91965d6184ebc8cd7cbb7941a260d5f018cd2d/pillow-11.3.0-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:1c627742b539bba4309df89171356fcb3cc5a9178355b2727d1b74a6cf155fbd", size = 2128328, upload-time = "2025-07-01T09:14:35.276Z" }, + { url = "https://files.pythonhosted.org/packages/4b/e8/100c3d114b1a0bf4042f27e0f87d2f25e857e838034e98ca98fe7b8c0a9c/pillow-11.3.0-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:30b7c02f3899d10f13d7a48163c8969e4e653f8b43416d23d13d1bbfdc93b9f8", size = 2170652, upload-time = "2025-07-01T09:14:37.203Z" }, + { url = "https://files.pythonhosted.org/packages/aa/86/3f758a28a6e381758545f7cdb4942e1cb79abd271bea932998fc0db93cb6/pillow-11.3.0-cp313-cp313-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:7859a4cc7c9295f5838015d8cc0a9c215b77e43d07a25e460f35cf516df8626f", size = 2227443, upload-time = "2025-07-01T09:14:39.344Z" }, + { url = "https://files.pythonhosted.org/packages/01/f4/91d5b3ffa718df2f53b0dc109877993e511f4fd055d7e9508682e8aba092/pillow-11.3.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ec1ee50470b0d050984394423d96325b744d55c701a439d2bd66089bff963d3c", size = 5278474, upload-time = "2025-07-01T09:14:41.843Z" }, + { url = "https://files.pythonhosted.org/packages/f9/0e/37d7d3eca6c879fbd9dba21268427dffda1ab00d4eb05b32923d4fbe3b12/pillow-11.3.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:7db51d222548ccfd274e4572fdbf3e810a5e66b00608862f947b163e613b67dd", size = 4686038, upload-time = "2025-07-01T09:14:44.008Z" }, + { url = "https://files.pythonhosted.org/packages/ff/b0/3426e5c7f6565e752d81221af9d3676fdbb4f352317ceafd42899aaf5d8a/pillow-11.3.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:2d6fcc902a24ac74495df63faad1884282239265c6839a0a6416d33faedfae7e", size = 5864407, upload-time = "2025-07-03T13:10:15.628Z" }, + { url = "https://files.pythonhosted.org/packages/fc/c1/c6c423134229f2a221ee53f838d4be9d82bab86f7e2f8e75e47b6bf6cd77/pillow-11.3.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:f0f5d8f4a08090c6d6d578351a2b91acf519a54986c055af27e7a93feae6d3f1", size = 7639094, upload-time = "2025-07-03T13:10:21.857Z" }, + { url = "https://files.pythonhosted.org/packages/ba/c9/09e6746630fe6372c67c648ff9deae52a2bc20897d51fa293571977ceb5d/pillow-11.3.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c37d8ba9411d6003bba9e518db0db0c58a680ab9fe5179f040b0463644bc9805", size = 5973503, upload-time = "2025-07-01T09:14:45.698Z" }, + { url = "https://files.pythonhosted.org/packages/d5/1c/a2a29649c0b1983d3ef57ee87a66487fdeb45132df66ab30dd37f7dbe162/pillow-11.3.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:13f87d581e71d9189ab21fe0efb5a23e9f28552d5be6979e84001d3b8505abe8", size = 6642574, upload-time = "2025-07-01T09:14:47.415Z" }, + { url = "https://files.pythonhosted.org/packages/36/de/d5cc31cc4b055b6c6fd990e3e7f0f8aaf36229a2698501bcb0cdf67c7146/pillow-11.3.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:023f6d2d11784a465f09fd09a34b150ea4672e85fb3d05931d89f373ab14abb2", size = 6084060, upload-time = "2025-07-01T09:14:49.636Z" }, + { url = "https://files.pythonhosted.org/packages/d5/ea/502d938cbaeec836ac28a9b730193716f0114c41325db428e6b280513f09/pillow-11.3.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:45dfc51ac5975b938e9809451c51734124e73b04d0f0ac621649821a63852e7b", size = 6721407, upload-time = "2025-07-01T09:14:51.962Z" }, + { url = "https://files.pythonhosted.org/packages/45/9c/9c5e2a73f125f6cbc59cc7087c8f2d649a7ae453f83bd0362ff7c9e2aee2/pillow-11.3.0-cp313-cp313-win32.whl", hash = "sha256:a4d336baed65d50d37b88ca5b60c0fa9d81e3a87d4a7930d3880d1624d5b31f3", size = 6273841, upload-time = "2025-07-01T09:14:54.142Z" }, + { url = "https://files.pythonhosted.org/packages/23/85/397c73524e0cd212067e0c969aa245b01d50183439550d24d9f55781b776/pillow-11.3.0-cp313-cp313-win_amd64.whl", hash = "sha256:0bce5c4fd0921f99d2e858dc4d4d64193407e1b99478bc5cacecba2311abde51", size = 6978450, upload-time = "2025-07-01T09:14:56.436Z" }, + { url = "https://files.pythonhosted.org/packages/17/d2/622f4547f69cd173955194b78e4d19ca4935a1b0f03a302d655c9f6aae65/pillow-11.3.0-cp313-cp313-win_arm64.whl", hash = "sha256:1904e1264881f682f02b7f8167935cce37bc97db457f8e7849dc3a6a52b99580", size = 2423055, upload-time = "2025-07-01T09:14:58.072Z" }, + { url = "https://files.pythonhosted.org/packages/dd/80/a8a2ac21dda2e82480852978416cfacd439a4b490a501a288ecf4fe2532d/pillow-11.3.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:4c834a3921375c48ee6b9624061076bc0a32a60b5532b322cc0ea64e639dd50e", size = 5281110, upload-time = "2025-07-01T09:14:59.79Z" }, + { url = "https://files.pythonhosted.org/packages/44/d6/b79754ca790f315918732e18f82a8146d33bcd7f4494380457ea89eb883d/pillow-11.3.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:5e05688ccef30ea69b9317a9ead994b93975104a677a36a8ed8106be9260aa6d", size = 4689547, upload-time = "2025-07-01T09:15:01.648Z" }, + { url = "https://files.pythonhosted.org/packages/49/20/716b8717d331150cb00f7fdd78169c01e8e0c219732a78b0e59b6bdb2fd6/pillow-11.3.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:1019b04af07fc0163e2810167918cb5add8d74674b6267616021ab558dc98ced", size = 5901554, upload-time = "2025-07-03T13:10:27.018Z" }, + { url = "https://files.pythonhosted.org/packages/74/cf/a9f3a2514a65bb071075063a96f0a5cf949c2f2fce683c15ccc83b1c1cab/pillow-11.3.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:f944255db153ebb2b19c51fe85dd99ef0ce494123f21b9db4877ffdfc5590c7c", size = 7669132, upload-time = "2025-07-03T13:10:33.01Z" }, + { url = "https://files.pythonhosted.org/packages/98/3c/da78805cbdbee9cb43efe8261dd7cc0b4b93f2ac79b676c03159e9db2187/pillow-11.3.0-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1f85acb69adf2aaee8b7da124efebbdb959a104db34d3a2cb0f3793dbae422a8", size = 6005001, upload-time = "2025-07-01T09:15:03.365Z" }, + { url = "https://files.pythonhosted.org/packages/6c/fa/ce044b91faecf30e635321351bba32bab5a7e034c60187fe9698191aef4f/pillow-11.3.0-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:05f6ecbeff5005399bb48d198f098a9b4b6bdf27b8487c7f38ca16eeb070cd59", size = 6668814, upload-time = "2025-07-01T09:15:05.655Z" }, + { url = "https://files.pythonhosted.org/packages/7b/51/90f9291406d09bf93686434f9183aba27b831c10c87746ff49f127ee80cb/pillow-11.3.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:a7bc6e6fd0395bc052f16b1a8670859964dbd7003bd0af2ff08342eb6e442cfe", size = 6113124, upload-time = "2025-07-01T09:15:07.358Z" }, + { url = "https://files.pythonhosted.org/packages/cd/5a/6fec59b1dfb619234f7636d4157d11fb4e196caeee220232a8d2ec48488d/pillow-11.3.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:83e1b0161c9d148125083a35c1c5a89db5b7054834fd4387499e06552035236c", size = 6747186, upload-time = "2025-07-01T09:15:09.317Z" }, + { url = "https://files.pythonhosted.org/packages/49/6b/00187a044f98255225f172de653941e61da37104a9ea60e4f6887717e2b5/pillow-11.3.0-cp313-cp313t-win32.whl", hash = "sha256:2a3117c06b8fb646639dce83694f2f9eac405472713fcb1ae887469c0d4f6788", size = 6277546, upload-time = "2025-07-01T09:15:11.311Z" }, + { url = "https://files.pythonhosted.org/packages/e8/5c/6caaba7e261c0d75bab23be79f1d06b5ad2a2ae49f028ccec801b0e853d6/pillow-11.3.0-cp313-cp313t-win_amd64.whl", hash = "sha256:857844335c95bea93fb39e0fa2726b4d9d758850b34075a7e3ff4f4fa3aa3b31", size = 6985102, upload-time = "2025-07-01T09:15:13.164Z" }, + { url = "https://files.pythonhosted.org/packages/f3/7e/b623008460c09a0cb38263c93b828c666493caee2eb34ff67f778b87e58c/pillow-11.3.0-cp313-cp313t-win_arm64.whl", hash = "sha256:8797edc41f3e8536ae4b10897ee2f637235c94f27404cac7297f7b607dd0716e", size = 2424803, upload-time = "2025-07-01T09:15:15.695Z" }, + { url = "https://files.pythonhosted.org/packages/73/f4/04905af42837292ed86cb1b1dabe03dce1edc008ef14c473c5c7e1443c5d/pillow-11.3.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:d9da3df5f9ea2a89b81bb6087177fb1f4d1c7146d583a3fe5c672c0d94e55e12", size = 5278520, upload-time = "2025-07-01T09:15:17.429Z" }, + { url = "https://files.pythonhosted.org/packages/41/b0/33d79e377a336247df6348a54e6d2a2b85d644ca202555e3faa0cf811ecc/pillow-11.3.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:0b275ff9b04df7b640c59ec5a3cb113eefd3795a8df80bac69646ef699c6981a", size = 4686116, upload-time = "2025-07-01T09:15:19.423Z" }, + { url = "https://files.pythonhosted.org/packages/49/2d/ed8bc0ab219ae8768f529597d9509d184fe8a6c4741a6864fea334d25f3f/pillow-11.3.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:0743841cabd3dba6a83f38a92672cccbd69af56e3e91777b0ee7f4dba4385632", size = 5864597, upload-time = "2025-07-03T13:10:38.404Z" }, + { url = "https://files.pythonhosted.org/packages/b5/3d/b932bb4225c80b58dfadaca9d42d08d0b7064d2d1791b6a237f87f661834/pillow-11.3.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:2465a69cf967b8b49ee1b96d76718cd98c4e925414ead59fdf75cf0fd07df673", size = 7638246, upload-time = "2025-07-03T13:10:44.987Z" }, + { url = "https://files.pythonhosted.org/packages/09/b5/0487044b7c096f1b48f0d7ad416472c02e0e4bf6919541b111efd3cae690/pillow-11.3.0-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:41742638139424703b4d01665b807c6468e23e699e8e90cffefe291c5832b027", size = 5973336, upload-time = "2025-07-01T09:15:21.237Z" }, + { url = "https://files.pythonhosted.org/packages/a8/2d/524f9318f6cbfcc79fbc004801ea6b607ec3f843977652fdee4857a7568b/pillow-11.3.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:93efb0b4de7e340d99057415c749175e24c8864302369e05914682ba642e5d77", size = 6642699, upload-time = "2025-07-01T09:15:23.186Z" }, + { url = "https://files.pythonhosted.org/packages/6f/d2/a9a4f280c6aefedce1e8f615baaa5474e0701d86dd6f1dede66726462bbd/pillow-11.3.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7966e38dcd0fa11ca390aed7c6f20454443581d758242023cf36fcb319b1a874", size = 6083789, upload-time = "2025-07-01T09:15:25.1Z" }, + { url = "https://files.pythonhosted.org/packages/fe/54/86b0cd9dbb683a9d5e960b66c7379e821a19be4ac5810e2e5a715c09a0c0/pillow-11.3.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:98a9afa7b9007c67ed84c57c9e0ad86a6000da96eaa638e4f8abe5b65ff83f0a", size = 6720386, upload-time = "2025-07-01T09:15:27.378Z" }, + { url = "https://files.pythonhosted.org/packages/e7/95/88efcaf384c3588e24259c4203b909cbe3e3c2d887af9e938c2022c9dd48/pillow-11.3.0-cp314-cp314-win32.whl", hash = "sha256:02a723e6bf909e7cea0dac1b0e0310be9d7650cd66222a5f1c571455c0a45214", size = 6370911, upload-time = "2025-07-01T09:15:29.294Z" }, + { url = "https://files.pythonhosted.org/packages/2e/cc/934e5820850ec5eb107e7b1a72dd278140731c669f396110ebc326f2a503/pillow-11.3.0-cp314-cp314-win_amd64.whl", hash = "sha256:a418486160228f64dd9e9efcd132679b7a02a5f22c982c78b6fc7dab3fefb635", size = 7117383, upload-time = "2025-07-01T09:15:31.128Z" }, + { url = "https://files.pythonhosted.org/packages/d6/e9/9c0a616a71da2a5d163aa37405e8aced9a906d574b4a214bede134e731bc/pillow-11.3.0-cp314-cp314-win_arm64.whl", hash = "sha256:155658efb5e044669c08896c0c44231c5e9abcaadbc5cd3648df2f7c0b96b9a6", size = 2511385, upload-time = "2025-07-01T09:15:33.328Z" }, + { url = "https://files.pythonhosted.org/packages/1a/33/c88376898aff369658b225262cd4f2659b13e8178e7534df9e6e1fa289f6/pillow-11.3.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:59a03cdf019efbfeeed910bf79c7c93255c3d54bc45898ac2a4140071b02b4ae", size = 5281129, upload-time = "2025-07-01T09:15:35.194Z" }, + { url = "https://files.pythonhosted.org/packages/1f/70/d376247fb36f1844b42910911c83a02d5544ebd2a8bad9efcc0f707ea774/pillow-11.3.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:f8a5827f84d973d8636e9dc5764af4f0cf2318d26744b3d902931701b0d46653", size = 4689580, upload-time = "2025-07-01T09:15:37.114Z" }, + { url = "https://files.pythonhosted.org/packages/eb/1c/537e930496149fbac69efd2fc4329035bbe2e5475b4165439e3be9cb183b/pillow-11.3.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ee92f2fd10f4adc4b43d07ec5e779932b4eb3dbfbc34790ada5a6669bc095aa6", size = 5902860, upload-time = "2025-07-03T13:10:50.248Z" }, + { url = "https://files.pythonhosted.org/packages/bd/57/80f53264954dcefeebcf9dae6e3eb1daea1b488f0be8b8fef12f79a3eb10/pillow-11.3.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c96d333dcf42d01f47b37e0979b6bd73ec91eae18614864622d9b87bbd5bbf36", size = 7670694, upload-time = "2025-07-03T13:10:56.432Z" }, + { url = "https://files.pythonhosted.org/packages/70/ff/4727d3b71a8578b4587d9c276e90efad2d6fe0335fd76742a6da08132e8c/pillow-11.3.0-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4c96f993ab8c98460cd0c001447bff6194403e8b1d7e149ade5f00594918128b", size = 6005888, upload-time = "2025-07-01T09:15:39.436Z" }, + { url = "https://files.pythonhosted.org/packages/05/ae/716592277934f85d3be51d7256f3636672d7b1abfafdc42cf3f8cbd4b4c8/pillow-11.3.0-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:41342b64afeba938edb034d122b2dda5db2139b9a4af999729ba8818e0056477", size = 6670330, upload-time = "2025-07-01T09:15:41.269Z" }, + { url = "https://files.pythonhosted.org/packages/e7/bb/7fe6cddcc8827b01b1a9766f5fdeb7418680744f9082035bdbabecf1d57f/pillow-11.3.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:068d9c39a2d1b358eb9f245ce7ab1b5c3246c7c8c7d9ba58cfa5b43146c06e50", size = 6114089, upload-time = "2025-07-01T09:15:43.13Z" }, + { url = "https://files.pythonhosted.org/packages/8b/f5/06bfaa444c8e80f1a8e4bff98da9c83b37b5be3b1deaa43d27a0db37ef84/pillow-11.3.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:a1bc6ba083b145187f648b667e05a2534ecc4b9f2784c2cbe3089e44868f2b9b", size = 6748206, upload-time = "2025-07-01T09:15:44.937Z" }, + { url = "https://files.pythonhosted.org/packages/f0/77/bc6f92a3e8e6e46c0ca78abfffec0037845800ea38c73483760362804c41/pillow-11.3.0-cp314-cp314t-win32.whl", hash = "sha256:118ca10c0d60b06d006be10a501fd6bbdfef559251ed31b794668ed569c87e12", size = 6377370, upload-time = "2025-07-01T09:15:46.673Z" }, + { url = "https://files.pythonhosted.org/packages/4a/82/3a721f7d69dca802befb8af08b7c79ebcab461007ce1c18bd91a5d5896f9/pillow-11.3.0-cp314-cp314t-win_amd64.whl", hash = "sha256:8924748b688aa210d79883357d102cd64690e56b923a186f35a82cbc10f997db", size = 7121500, upload-time = "2025-07-01T09:15:48.512Z" }, + { url = "https://files.pythonhosted.org/packages/89/c7/5572fa4a3f45740eaab6ae86fcdf7195b55beac1371ac8c619d880cfe948/pillow-11.3.0-cp314-cp314t-win_arm64.whl", hash = "sha256:79ea0d14d3ebad43ec77ad5272e6ff9bba5b679ef73375ea760261207fa8e0aa", size = 2512835, upload-time = "2025-07-01T09:15:50.399Z" }, + { url = "https://files.pythonhosted.org/packages/9e/e3/6fa84033758276fb31da12e5fb66ad747ae83b93c67af17f8c6ff4cc8f34/pillow-11.3.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:7c8ec7a017ad1bd562f93dbd8505763e688d388cde6e4a010ae1486916e713e6", size = 5270566, upload-time = "2025-07-01T09:16:19.801Z" }, + { url = "https://files.pythonhosted.org/packages/5b/ee/e8d2e1ab4892970b561e1ba96cbd59c0d28cf66737fc44abb2aec3795a4e/pillow-11.3.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:9ab6ae226de48019caa8074894544af5b53a117ccb9d3b3dcb2871464c829438", size = 4654618, upload-time = "2025-07-01T09:16:21.818Z" }, + { url = "https://files.pythonhosted.org/packages/f2/6d/17f80f4e1f0761f02160fc433abd4109fa1548dcfdca46cfdadaf9efa565/pillow-11.3.0-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:fe27fb049cdcca11f11a7bfda64043c37b30e6b91f10cb5bab275806c32f6ab3", size = 4874248, upload-time = "2025-07-03T13:11:20.738Z" }, + { url = "https://files.pythonhosted.org/packages/de/5f/c22340acd61cef960130585bbe2120e2fd8434c214802f07e8c03596b17e/pillow-11.3.0-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:465b9e8844e3c3519a983d58b80be3f668e2a7a5db97f2784e7079fbc9f9822c", size = 6583963, upload-time = "2025-07-03T13:11:26.283Z" }, + { url = "https://files.pythonhosted.org/packages/31/5e/03966aedfbfcbb4d5f8aa042452d3361f325b963ebbadddac05b122e47dd/pillow-11.3.0-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5418b53c0d59b3824d05e029669efa023bbef0f3e92e75ec8428f3799487f361", size = 4957170, upload-time = "2025-07-01T09:16:23.762Z" }, + { url = "https://files.pythonhosted.org/packages/cc/2d/e082982aacc927fc2cab48e1e731bdb1643a1406acace8bed0900a61464e/pillow-11.3.0-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:504b6f59505f08ae014f724b6207ff6222662aab5cc9542577fb084ed0676ac7", size = 5581505, upload-time = "2025-07-01T09:16:25.593Z" }, + { url = "https://files.pythonhosted.org/packages/34/e7/ae39f538fd6844e982063c3a5e4598b8ced43b9633baa3a85ef33af8c05c/pillow-11.3.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:c84d689db21a1c397d001aa08241044aa2069e7587b398c8cc63020390b1c1b8", size = 6984598, upload-time = "2025-07-01T09:16:27.732Z" }, ] [[package]] @@ -1931,15 +1956,15 @@ wheels = [ [[package]] name = "pytest-xdist" -version = "3.7.0" +version = "3.8.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "execnet" }, { name = "pytest" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/49/dc/865845cfe987b21658e871d16e0a24e871e00884c545f246dd8f6f69edda/pytest_xdist-3.7.0.tar.gz", hash = "sha256:f9248c99a7c15b7d2f90715df93610353a485827bc06eefb6566d23f6400f126", size = 87550, upload-time = "2025-05-26T21:18:20.251Z" } +sdist = { url = "https://files.pythonhosted.org/packages/78/b4/439b179d1ff526791eb921115fca8e44e596a13efeda518b9d845a619450/pytest_xdist-3.8.0.tar.gz", hash = "sha256:7e578125ec9bc6050861aa93f2d59f1d8d085595d6551c2c90b6f4fad8d3a9f1", size = 88069, upload-time = "2025-07-01T13:30:59.346Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/0d/b2/0e802fde6f1c5b2f7ae7e9ad42b83fd4ecebac18a8a8c2f2f14e39dce6e1/pytest_xdist-3.7.0-py3-none-any.whl", hash = "sha256:7d3fbd255998265052435eb9daa4e99b62e6fb9cfb6efd1f858d4d8c0c7f0ca0", size = 46142, upload-time = "2025-05-26T21:18:18.759Z" }, + { url = "https://files.pythonhosted.org/packages/ca/31/d4e37e9e550c2b92a9cbc2e4d0b7420a27224968580b5a447f420847c975/pytest_xdist-3.8.0-py3-none-any.whl", hash = "sha256:202ca578cfeb7370784a8c33d6d05bc6e13b4f25b5053c30a152269fd10f0b88", size = 46396, upload-time = "2025-07-01T13:30:56.632Z" }, ] [[package]] @@ -2141,76 +2166,103 @@ wheels = [ [[package]] name = "rpds-py" -version = "0.25.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/8c/a6/60184b7fc00dd3ca80ac635dd5b8577d444c57e8e8742cecabfacb829921/rpds_py-0.25.1.tar.gz", hash = "sha256:8960b6dac09b62dac26e75d7e2c4a22efb835d827a7278c34f72b2b84fa160e3", size = 27304, upload-time = "2025-05-21T12:46:12.502Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/95/e1/df13fe3ddbbea43567e07437f097863b20c99318ae1f58a0fe389f763738/rpds_py-0.25.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:5f048bbf18b1f9120685c6d6bb70cc1a52c8cc11bdd04e643d28d3be0baf666d", size = 373341, upload-time = "2025-05-21T12:43:02.978Z" }, - { url = "https://files.pythonhosted.org/packages/7a/58/deef4d30fcbcbfef3b6d82d17c64490d5c94585a2310544ce8e2d3024f83/rpds_py-0.25.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4fbb0dbba559959fcb5d0735a0f87cdbca9e95dac87982e9b95c0f8f7ad10255", size = 359111, upload-time = "2025-05-21T12:43:05.128Z" }, - { url = "https://files.pythonhosted.org/packages/bb/7e/39f1f4431b03e96ebaf159e29a0f82a77259d8f38b2dd474721eb3a8ac9b/rpds_py-0.25.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d4ca54b9cf9d80b4016a67a0193ebe0bcf29f6b0a96f09db942087e294d3d4c2", size = 386112, upload-time = "2025-05-21T12:43:07.13Z" }, - { url = "https://files.pythonhosted.org/packages/db/e7/847068a48d63aec2ae695a1646089620b3b03f8ccf9f02c122ebaf778f3c/rpds_py-0.25.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1ee3e26eb83d39b886d2cb6e06ea701bba82ef30a0de044d34626ede51ec98b0", size = 400362, upload-time = "2025-05-21T12:43:08.693Z" }, - { url = "https://files.pythonhosted.org/packages/3b/3d/9441d5db4343d0cee759a7ab4d67420a476cebb032081763de934719727b/rpds_py-0.25.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:89706d0683c73a26f76a5315d893c051324d771196ae8b13e6ffa1ffaf5e574f", size = 522214, upload-time = "2025-05-21T12:43:10.694Z" }, - { url = "https://files.pythonhosted.org/packages/a2/ec/2cc5b30d95f9f1a432c79c7a2f65d85e52812a8f6cbf8768724571710786/rpds_py-0.25.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c2013ee878c76269c7b557a9a9c042335d732e89d482606990b70a839635feb7", size = 411491, upload-time = "2025-05-21T12:43:12.739Z" }, - { url = "https://files.pythonhosted.org/packages/dc/6c/44695c1f035077a017dd472b6a3253553780837af2fac9b6ac25f6a5cb4d/rpds_py-0.25.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45e484db65e5380804afbec784522de84fa95e6bb92ef1bd3325d33d13efaebd", size = 386978, upload-time = "2025-05-21T12:43:14.25Z" }, - { url = "https://files.pythonhosted.org/packages/b1/74/b4357090bb1096db5392157b4e7ed8bb2417dc7799200fcbaee633a032c9/rpds_py-0.25.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:48d64155d02127c249695abb87d39f0faf410733428d499867606be138161d65", size = 420662, upload-time = "2025-05-21T12:43:15.8Z" }, - { url = "https://files.pythonhosted.org/packages/26/dd/8cadbebf47b96e59dfe8b35868e5c38a42272699324e95ed522da09d3a40/rpds_py-0.25.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:048893e902132fd6548a2e661fb38bf4896a89eea95ac5816cf443524a85556f", size = 563385, upload-time = "2025-05-21T12:43:17.78Z" }, - { url = "https://files.pythonhosted.org/packages/c3/ea/92960bb7f0e7a57a5ab233662f12152085c7dc0d5468534c65991a3d48c9/rpds_py-0.25.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:0317177b1e8691ab5879f4f33f4b6dc55ad3b344399e23df2e499de7b10a548d", size = 592047, upload-time = "2025-05-21T12:43:19.457Z" }, - { url = "https://files.pythonhosted.org/packages/61/ad/71aabc93df0d05dabcb4b0c749277881f8e74548582d96aa1bf24379493a/rpds_py-0.25.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:bffcf57826d77a4151962bf1701374e0fc87f536e56ec46f1abdd6a903354042", size = 557863, upload-time = "2025-05-21T12:43:21.69Z" }, - { url = "https://files.pythonhosted.org/packages/93/0f/89df0067c41f122b90b76f3660028a466eb287cbe38efec3ea70e637ca78/rpds_py-0.25.1-cp311-cp311-win32.whl", hash = "sha256:cda776f1967cb304816173b30994faaf2fd5bcb37e73118a47964a02c348e1bc", size = 219627, upload-time = "2025-05-21T12:43:23.311Z" }, - { url = "https://files.pythonhosted.org/packages/7c/8d/93b1a4c1baa903d0229374d9e7aa3466d751f1d65e268c52e6039c6e338e/rpds_py-0.25.1-cp311-cp311-win_amd64.whl", hash = "sha256:dc3c1ff0abc91444cd20ec643d0f805df9a3661fcacf9c95000329f3ddf268a4", size = 231603, upload-time = "2025-05-21T12:43:25.145Z" }, - { url = "https://files.pythonhosted.org/packages/cb/11/392605e5247bead2f23e6888e77229fbd714ac241ebbebb39a1e822c8815/rpds_py-0.25.1-cp311-cp311-win_arm64.whl", hash = "sha256:5a3ddb74b0985c4387719fc536faced33cadf2172769540c62e2a94b7b9be1c4", size = 223967, upload-time = "2025-05-21T12:43:26.566Z" }, - { url = "https://files.pythonhosted.org/packages/7f/81/28ab0408391b1dc57393653b6a0cf2014cc282cc2909e4615e63e58262be/rpds_py-0.25.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:b5ffe453cde61f73fea9430223c81d29e2fbf412a6073951102146c84e19e34c", size = 364647, upload-time = "2025-05-21T12:43:28.559Z" }, - { url = "https://files.pythonhosted.org/packages/2c/9a/7797f04cad0d5e56310e1238434f71fc6939d0bc517192a18bb99a72a95f/rpds_py-0.25.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:115874ae5e2fdcfc16b2aedc95b5eef4aebe91b28e7e21951eda8a5dc0d3461b", size = 350454, upload-time = "2025-05-21T12:43:30.615Z" }, - { url = "https://files.pythonhosted.org/packages/69/3c/93d2ef941b04898011e5d6eaa56a1acf46a3b4c9f4b3ad1bbcbafa0bee1f/rpds_py-0.25.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a714bf6e5e81b0e570d01f56e0c89c6375101b8463999ead3a93a5d2a4af91fa", size = 389665, upload-time = "2025-05-21T12:43:32.629Z" }, - { url = "https://files.pythonhosted.org/packages/c1/57/ad0e31e928751dde8903a11102559628d24173428a0f85e25e187defb2c1/rpds_py-0.25.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:35634369325906bcd01577da4c19e3b9541a15e99f31e91a02d010816b49bfda", size = 403873, upload-time = "2025-05-21T12:43:34.576Z" }, - { url = "https://files.pythonhosted.org/packages/16/ad/c0c652fa9bba778b4f54980a02962748479dc09632e1fd34e5282cf2556c/rpds_py-0.25.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d4cb2b3ddc16710548801c6fcc0cfcdeeff9dafbc983f77265877793f2660309", size = 525866, upload-time = "2025-05-21T12:43:36.123Z" }, - { url = "https://files.pythonhosted.org/packages/2a/39/3e1839bc527e6fcf48d5fec4770070f872cdee6c6fbc9b259932f4e88a38/rpds_py-0.25.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9ceca1cf097ed77e1a51f1dbc8d174d10cb5931c188a4505ff9f3e119dfe519b", size = 416886, upload-time = "2025-05-21T12:43:38.034Z" }, - { url = "https://files.pythonhosted.org/packages/7a/95/dd6b91cd4560da41df9d7030a038298a67d24f8ca38e150562644c829c48/rpds_py-0.25.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2c2cd1a4b0c2b8c5e31ffff50d09f39906fe351389ba143c195566056c13a7ea", size = 390666, upload-time = "2025-05-21T12:43:40.065Z" }, - { url = "https://files.pythonhosted.org/packages/64/48/1be88a820e7494ce0a15c2d390ccb7c52212370badabf128e6a7bb4cb802/rpds_py-0.25.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1de336a4b164c9188cb23f3703adb74a7623ab32d20090d0e9bf499a2203ad65", size = 425109, upload-time = "2025-05-21T12:43:42.263Z" }, - { url = "https://files.pythonhosted.org/packages/cf/07/3e2a17927ef6d7720b9949ec1b37d1e963b829ad0387f7af18d923d5cfa5/rpds_py-0.25.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:9fca84a15333e925dd59ce01da0ffe2ffe0d6e5d29a9eeba2148916d1824948c", size = 567244, upload-time = "2025-05-21T12:43:43.846Z" }, - { url = "https://files.pythonhosted.org/packages/d2/e5/76cf010998deccc4f95305d827847e2eae9c568099c06b405cf96384762b/rpds_py-0.25.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:88ec04afe0c59fa64e2f6ea0dd9657e04fc83e38de90f6de201954b4d4eb59bd", size = 596023, upload-time = "2025-05-21T12:43:45.932Z" }, - { url = "https://files.pythonhosted.org/packages/52/9a/df55efd84403736ba37a5a6377b70aad0fd1cb469a9109ee8a1e21299a1c/rpds_py-0.25.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a8bd2f19e312ce3e1d2c635618e8a8d8132892bb746a7cf74780a489f0f6cdcb", size = 561634, upload-time = "2025-05-21T12:43:48.263Z" }, - { url = "https://files.pythonhosted.org/packages/ab/aa/dc3620dd8db84454aaf9374bd318f1aa02578bba5e567f5bf6b79492aca4/rpds_py-0.25.1-cp312-cp312-win32.whl", hash = "sha256:e5e2f7280d8d0d3ef06f3ec1b4fd598d386cc6f0721e54f09109a8132182fbfe", size = 222713, upload-time = "2025-05-21T12:43:49.897Z" }, - { url = "https://files.pythonhosted.org/packages/a3/7f/7cef485269a50ed5b4e9bae145f512d2a111ca638ae70cc101f661b4defd/rpds_py-0.25.1-cp312-cp312-win_amd64.whl", hash = "sha256:db58483f71c5db67d643857404da360dce3573031586034b7d59f245144cc192", size = 235280, upload-time = "2025-05-21T12:43:51.893Z" }, - { url = "https://files.pythonhosted.org/packages/99/f2/c2d64f6564f32af913bf5f3f7ae41c7c263c5ae4c4e8f1a17af8af66cd46/rpds_py-0.25.1-cp312-cp312-win_arm64.whl", hash = "sha256:6d50841c425d16faf3206ddbba44c21aa3310a0cebc3c1cdfc3e3f4f9f6f5728", size = 225399, upload-time = "2025-05-21T12:43:53.351Z" }, - { url = "https://files.pythonhosted.org/packages/2b/da/323848a2b62abe6a0fec16ebe199dc6889c5d0a332458da8985b2980dffe/rpds_py-0.25.1-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:659d87430a8c8c704d52d094f5ba6fa72ef13b4d385b7e542a08fc240cb4a559", size = 364498, upload-time = "2025-05-21T12:43:54.841Z" }, - { url = "https://files.pythonhosted.org/packages/1f/b4/4d3820f731c80fd0cd823b3e95b9963fec681ae45ba35b5281a42382c67d/rpds_py-0.25.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:68f6f060f0bbdfb0245267da014d3a6da9be127fe3e8cc4a68c6f833f8a23bb1", size = 350083, upload-time = "2025-05-21T12:43:56.428Z" }, - { url = "https://files.pythonhosted.org/packages/d5/b1/3a8ee1c9d480e8493619a437dec685d005f706b69253286f50f498cbdbcf/rpds_py-0.25.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:083a9513a33e0b92cf6e7a6366036c6bb43ea595332c1ab5c8ae329e4bcc0a9c", size = 389023, upload-time = "2025-05-21T12:43:57.995Z" }, - { url = "https://files.pythonhosted.org/packages/3b/31/17293edcfc934dc62c3bf74a0cb449ecd549531f956b72287203e6880b87/rpds_py-0.25.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:816568614ecb22b18a010c7a12559c19f6fe993526af88e95a76d5a60b8b75fb", size = 403283, upload-time = "2025-05-21T12:43:59.546Z" }, - { url = "https://files.pythonhosted.org/packages/d1/ca/e0f0bc1a75a8925024f343258c8ecbd8828f8997ea2ac71e02f67b6f5299/rpds_py-0.25.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3c6564c0947a7f52e4792983f8e6cf9bac140438ebf81f527a21d944f2fd0a40", size = 524634, upload-time = "2025-05-21T12:44:01.087Z" }, - { url = "https://files.pythonhosted.org/packages/3e/03/5d0be919037178fff33a6672ffc0afa04ea1cfcb61afd4119d1b5280ff0f/rpds_py-0.25.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5c4a128527fe415d73cf1f70a9a688d06130d5810be69f3b553bf7b45e8acf79", size = 416233, upload-time = "2025-05-21T12:44:02.604Z" }, - { url = "https://files.pythonhosted.org/packages/05/7c/8abb70f9017a231c6c961a8941403ed6557664c0913e1bf413cbdc039e75/rpds_py-0.25.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a49e1d7a4978ed554f095430b89ecc23f42014a50ac385eb0c4d163ce213c325", size = 390375, upload-time = "2025-05-21T12:44:04.162Z" }, - { url = "https://files.pythonhosted.org/packages/7a/ac/a87f339f0e066b9535074a9f403b9313fd3892d4a164d5d5f5875ac9f29f/rpds_py-0.25.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d74ec9bc0e2feb81d3f16946b005748119c0f52a153f6db6a29e8cd68636f295", size = 424537, upload-time = "2025-05-21T12:44:06.175Z" }, - { url = "https://files.pythonhosted.org/packages/1f/8f/8d5c1567eaf8c8afe98a838dd24de5013ce6e8f53a01bd47fe8bb06b5533/rpds_py-0.25.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:3af5b4cc10fa41e5bc64e5c198a1b2d2864337f8fcbb9a67e747e34002ce812b", size = 566425, upload-time = "2025-05-21T12:44:08.242Z" }, - { url = "https://files.pythonhosted.org/packages/95/33/03016a6be5663b389c8ab0bbbcca68d9e96af14faeff0a04affcb587e776/rpds_py-0.25.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:79dc317a5f1c51fd9c6a0c4f48209c6b8526d0524a6904fc1076476e79b00f98", size = 595197, upload-time = "2025-05-21T12:44:10.449Z" }, - { url = "https://files.pythonhosted.org/packages/33/8d/da9f4d3e208c82fda311bff0cf0a19579afceb77cf456e46c559a1c075ba/rpds_py-0.25.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:1521031351865e0181bc585147624d66b3b00a84109b57fcb7a779c3ec3772cd", size = 561244, upload-time = "2025-05-21T12:44:12.387Z" }, - { url = "https://files.pythonhosted.org/packages/e2/b3/39d5dcf7c5f742ecd6dbc88f6f84ae54184b92f5f387a4053be2107b17f1/rpds_py-0.25.1-cp313-cp313-win32.whl", hash = "sha256:5d473be2b13600b93a5675d78f59e63b51b1ba2d0476893415dfbb5477e65b31", size = 222254, upload-time = "2025-05-21T12:44:14.261Z" }, - { url = "https://files.pythonhosted.org/packages/5f/19/2d6772c8eeb8302c5f834e6d0dfd83935a884e7c5ce16340c7eaf89ce925/rpds_py-0.25.1-cp313-cp313-win_amd64.whl", hash = "sha256:a7b74e92a3b212390bdce1d93da9f6488c3878c1d434c5e751cbc202c5e09500", size = 234741, upload-time = "2025-05-21T12:44:16.236Z" }, - { url = "https://files.pythonhosted.org/packages/5b/5a/145ada26cfaf86018d0eb304fe55eafdd4f0b6b84530246bb4a7c4fb5c4b/rpds_py-0.25.1-cp313-cp313-win_arm64.whl", hash = "sha256:dd326a81afe332ede08eb39ab75b301d5676802cdffd3a8f287a5f0b694dc3f5", size = 224830, upload-time = "2025-05-21T12:44:17.749Z" }, - { url = "https://files.pythonhosted.org/packages/4b/ca/d435844829c384fd2c22754ff65889c5c556a675d2ed9eb0e148435c6690/rpds_py-0.25.1-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:a58d1ed49a94d4183483a3ce0af22f20318d4a1434acee255d683ad90bf78129", size = 359668, upload-time = "2025-05-21T12:44:19.322Z" }, - { url = "https://files.pythonhosted.org/packages/1f/01/b056f21db3a09f89410d493d2f6614d87bb162499f98b649d1dbd2a81988/rpds_py-0.25.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:f251bf23deb8332823aef1da169d5d89fa84c89f67bdfb566c49dea1fccfd50d", size = 345649, upload-time = "2025-05-21T12:44:20.962Z" }, - { url = "https://files.pythonhosted.org/packages/e0/0f/e0d00dc991e3d40e03ca36383b44995126c36b3eafa0ccbbd19664709c88/rpds_py-0.25.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8dbd586bfa270c1103ece2109314dd423df1fa3d9719928b5d09e4840cec0d72", size = 384776, upload-time = "2025-05-21T12:44:22.516Z" }, - { url = "https://files.pythonhosted.org/packages/9f/a2/59374837f105f2ca79bde3c3cd1065b2f8c01678900924949f6392eab66d/rpds_py-0.25.1-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6d273f136e912aa101a9274c3145dcbddbe4bac560e77e6d5b3c9f6e0ed06d34", size = 395131, upload-time = "2025-05-21T12:44:24.147Z" }, - { url = "https://files.pythonhosted.org/packages/9c/dc/48e8d84887627a0fe0bac53f0b4631e90976fd5d35fff8be66b8e4f3916b/rpds_py-0.25.1-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:666fa7b1bd0a3810a7f18f6d3a25ccd8866291fbbc3c9b912b917a6715874bb9", size = 520942, upload-time = "2025-05-21T12:44:25.915Z" }, - { url = "https://files.pythonhosted.org/packages/7c/f5/ee056966aeae401913d37befeeab57a4a43a4f00099e0a20297f17b8f00c/rpds_py-0.25.1-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:921954d7fbf3fccc7de8f717799304b14b6d9a45bbeec5a8d7408ccbf531faf5", size = 411330, upload-time = "2025-05-21T12:44:27.638Z" }, - { url = "https://files.pythonhosted.org/packages/ab/74/b2cffb46a097cefe5d17f94ede7a174184b9d158a0aeb195f39f2c0361e8/rpds_py-0.25.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f3d86373ff19ca0441ebeb696ef64cb58b8b5cbacffcda5a0ec2f3911732a194", size = 387339, upload-time = "2025-05-21T12:44:29.292Z" }, - { url = "https://files.pythonhosted.org/packages/7f/9a/0ff0b375dcb5161c2b7054e7d0b7575f1680127505945f5cabaac890bc07/rpds_py-0.25.1-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c8980cde3bb8575e7c956a530f2c217c1d6aac453474bf3ea0f9c89868b531b6", size = 418077, upload-time = "2025-05-21T12:44:30.877Z" }, - { url = "https://files.pythonhosted.org/packages/0d/a1/fda629bf20d6b698ae84c7c840cfb0e9e4200f664fc96e1f456f00e4ad6e/rpds_py-0.25.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:8eb8c84ecea987a2523e057c0d950bcb3f789696c0499290b8d7b3107a719d78", size = 562441, upload-time = "2025-05-21T12:44:32.541Z" }, - { url = "https://files.pythonhosted.org/packages/20/15/ce4b5257f654132f326f4acd87268e1006cc071e2c59794c5bdf4bebbb51/rpds_py-0.25.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:e43a005671a9ed5a650f3bc39e4dbccd6d4326b24fb5ea8be5f3a43a6f576c72", size = 590750, upload-time = "2025-05-21T12:44:34.557Z" }, - { url = "https://files.pythonhosted.org/packages/fb/ab/e04bf58a8d375aeedb5268edcc835c6a660ebf79d4384d8e0889439448b0/rpds_py-0.25.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:58f77c60956501a4a627749a6dcb78dac522f249dd96b5c9f1c6af29bfacfb66", size = 558891, upload-time = "2025-05-21T12:44:37.358Z" }, - { url = "https://files.pythonhosted.org/packages/90/82/cb8c6028a6ef6cd2b7991e2e4ced01c854b6236ecf51e81b64b569c43d73/rpds_py-0.25.1-cp313-cp313t-win32.whl", hash = "sha256:2cb9e5b5e26fc02c8a4345048cd9998c2aca7c2712bd1b36da0c72ee969a3523", size = 218718, upload-time = "2025-05-21T12:44:38.969Z" }, - { url = "https://files.pythonhosted.org/packages/b6/97/5a4b59697111c89477d20ba8a44df9ca16b41e737fa569d5ae8bff99e650/rpds_py-0.25.1-cp313-cp313t-win_amd64.whl", hash = "sha256:401ca1c4a20cc0510d3435d89c069fe0a9ae2ee6495135ac46bdd49ec0495763", size = 232218, upload-time = "2025-05-21T12:44:40.512Z" }, - { url = "https://files.pythonhosted.org/packages/49/74/48f3df0715a585cbf5d34919c9c757a4c92c1a9eba059f2d334e72471f70/rpds_py-0.25.1-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:ee86d81551ec68a5c25373c5643d343150cc54672b5e9a0cafc93c1870a53954", size = 374208, upload-time = "2025-05-21T12:45:26.306Z" }, - { url = "https://files.pythonhosted.org/packages/55/b0/9b01bb11ce01ec03d05e627249cc2c06039d6aa24ea5a22a39c312167c10/rpds_py-0.25.1-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:89c24300cd4a8e4a51e55c31a8ff3918e6651b241ee8876a42cc2b2a078533ba", size = 359262, upload-time = "2025-05-21T12:45:28.322Z" }, - { url = "https://files.pythonhosted.org/packages/a9/eb/5395621618f723ebd5116c53282052943a726dba111b49cd2071f785b665/rpds_py-0.25.1-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:771c16060ff4e79584dc48902a91ba79fd93eade3aa3a12d6d2a4aadaf7d542b", size = 387366, upload-time = "2025-05-21T12:45:30.42Z" }, - { url = "https://files.pythonhosted.org/packages/68/73/3d51442bdb246db619d75039a50ea1cf8b5b4ee250c3e5cd5c3af5981cd4/rpds_py-0.25.1-pp311-pypy311_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:785ffacd0ee61c3e60bdfde93baa6d7c10d86f15655bd706c89da08068dc5038", size = 400759, upload-time = "2025-05-21T12:45:32.516Z" }, - { url = "https://files.pythonhosted.org/packages/b7/4c/3a32d5955d7e6cb117314597bc0f2224efc798428318b13073efe306512a/rpds_py-0.25.1-pp311-pypy311_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2a40046a529cc15cef88ac5ab589f83f739e2d332cb4d7399072242400ed68c9", size = 523128, upload-time = "2025-05-21T12:45:34.396Z" }, - { url = "https://files.pythonhosted.org/packages/be/95/1ffccd3b0bb901ae60b1dd4b1be2ab98bb4eb834cd9b15199888f5702f7b/rpds_py-0.25.1-pp311-pypy311_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:85fc223d9c76cabe5d0bff82214459189720dc135db45f9f66aa7cffbf9ff6c1", size = 411597, upload-time = "2025-05-21T12:45:36.164Z" }, - { url = "https://files.pythonhosted.org/packages/ef/6d/6e6cd310180689db8b0d2de7f7d1eabf3fb013f239e156ae0d5a1a85c27f/rpds_py-0.25.1-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b0be9965f93c222fb9b4cc254235b3b2b215796c03ef5ee64f995b1b69af0762", size = 388053, upload-time = "2025-05-21T12:45:38.45Z" }, - { url = "https://files.pythonhosted.org/packages/4a/87/ec4186b1fe6365ced6fa470960e68fc7804bafbe7c0cf5a36237aa240efa/rpds_py-0.25.1-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8378fa4a940f3fb509c081e06cb7f7f2adae8cf46ef258b0e0ed7519facd573e", size = 421821, upload-time = "2025-05-21T12:45:40.732Z" }, - { url = "https://files.pythonhosted.org/packages/7a/60/84f821f6bf4e0e710acc5039d91f8f594fae0d93fc368704920d8971680d/rpds_py-0.25.1-pp311-pypy311_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:33358883a4490287e67a2c391dfaea4d9359860281db3292b6886bf0be3d8692", size = 564534, upload-time = "2025-05-21T12:45:42.672Z" }, - { url = "https://files.pythonhosted.org/packages/41/3a/bc654eb15d3b38f9330fe0f545016ba154d89cdabc6177b0295910cd0ebe/rpds_py-0.25.1-pp311-pypy311_pp73-musllinux_1_2_i686.whl", hash = "sha256:1d1fadd539298e70cac2f2cb36f5b8a65f742b9b9f1014dd4ea1f7785e2470bf", size = 592674, upload-time = "2025-05-21T12:45:44.533Z" }, - { url = "https://files.pythonhosted.org/packages/2e/ba/31239736f29e4dfc7a58a45955c5db852864c306131fd6320aea214d5437/rpds_py-0.25.1-pp311-pypy311_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:9a46c2fb2545e21181445515960006e85d22025bd2fe6db23e76daec6eb689fe", size = 558781, upload-time = "2025-05-21T12:45:46.281Z" }, +version = "0.26.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a5/aa/4456d84bbb54adc6a916fb10c9b374f78ac840337644e4a5eda229c81275/rpds_py-0.26.0.tar.gz", hash = "sha256:20dae58a859b0906f0685642e591056f1e787f3a8b39c8e8749a45dc7d26bdb0", size = 27385, upload-time = "2025-07-01T15:57:13.958Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/09/4c/4ee8f7e512030ff79fda1df3243c88d70fc874634e2dbe5df13ba4210078/rpds_py-0.26.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:9e8cb77286025bdb21be2941d64ac6ca016130bfdcd228739e8ab137eb4406ed", size = 372610, upload-time = "2025-07-01T15:53:58.844Z" }, + { url = "https://files.pythonhosted.org/packages/fa/9d/3dc16be00f14fc1f03c71b1d67c8df98263ab2710a2fbd65a6193214a527/rpds_py-0.26.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5e09330b21d98adc8ccb2dbb9fc6cb434e8908d4c119aeaa772cb1caab5440a0", size = 358032, upload-time = "2025-07-01T15:53:59.985Z" }, + { url = "https://files.pythonhosted.org/packages/e7/5a/7f1bf8f045da2866324a08ae80af63e64e7bfaf83bd31f865a7b91a58601/rpds_py-0.26.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2c9c1b92b774b2e68d11193dc39620d62fd8ab33f0a3c77ecdabe19c179cdbc1", size = 381525, upload-time = "2025-07-01T15:54:01.162Z" }, + { url = "https://files.pythonhosted.org/packages/45/8a/04479398c755a066ace10e3d158866beb600867cacae194c50ffa783abd0/rpds_py-0.26.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:824e6d3503ab990d7090768e4dfd9e840837bae057f212ff9f4f05ec6d1975e7", size = 397089, upload-time = "2025-07-01T15:54:02.319Z" }, + { url = "https://files.pythonhosted.org/packages/72/88/9203f47268db488a1b6d469d69c12201ede776bb728b9d9f29dbfd7df406/rpds_py-0.26.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8ad7fd2258228bf288f2331f0a6148ad0186b2e3643055ed0db30990e59817a6", size = 514255, upload-time = "2025-07-01T15:54:03.38Z" }, + { url = "https://files.pythonhosted.org/packages/f5/b4/01ce5d1e853ddf81fbbd4311ab1eff0b3cf162d559288d10fd127e2588b5/rpds_py-0.26.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0dc23bbb3e06ec1ea72d515fb572c1fea59695aefbffb106501138762e1e915e", size = 402283, upload-time = "2025-07-01T15:54:04.923Z" }, + { url = "https://files.pythonhosted.org/packages/34/a2/004c99936997bfc644d590a9defd9e9c93f8286568f9c16cdaf3e14429a7/rpds_py-0.26.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d80bf832ac7b1920ee29a426cdca335f96a2b5caa839811803e999b41ba9030d", size = 383881, upload-time = "2025-07-01T15:54:06.482Z" }, + { url = "https://files.pythonhosted.org/packages/05/1b/ef5fba4a8f81ce04c427bfd96223f92f05e6cd72291ce9d7523db3b03a6c/rpds_py-0.26.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0919f38f5542c0a87e7b4afcafab6fd2c15386632d249e9a087498571250abe3", size = 415822, upload-time = "2025-07-01T15:54:07.605Z" }, + { url = "https://files.pythonhosted.org/packages/16/80/5c54195aec456b292f7bd8aa61741c8232964063fd8a75fdde9c1e982328/rpds_py-0.26.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d422b945683e409000c888e384546dbab9009bb92f7c0b456e217988cf316107", size = 558347, upload-time = "2025-07-01T15:54:08.591Z" }, + { url = "https://files.pythonhosted.org/packages/f2/1c/1845c1b1fd6d827187c43afe1841d91678d7241cbdb5420a4c6de180a538/rpds_py-0.26.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:77a7711fa562ba2da1aa757e11024ad6d93bad6ad7ede5afb9af144623e5f76a", size = 587956, upload-time = "2025-07-01T15:54:09.963Z" }, + { url = "https://files.pythonhosted.org/packages/2e/ff/9e979329dd131aa73a438c077252ddabd7df6d1a7ad7b9aacf6261f10faa/rpds_py-0.26.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:238e8c8610cb7c29460e37184f6799547f7e09e6a9bdbdab4e8edb90986a2318", size = 554363, upload-time = "2025-07-01T15:54:11.073Z" }, + { url = "https://files.pythonhosted.org/packages/00/8b/d78cfe034b71ffbe72873a136e71acc7a831a03e37771cfe59f33f6de8a2/rpds_py-0.26.0-cp311-cp311-win32.whl", hash = "sha256:893b022bfbdf26d7bedb083efeea624e8550ca6eb98bf7fea30211ce95b9201a", size = 220123, upload-time = "2025-07-01T15:54:12.382Z" }, + { url = "https://files.pythonhosted.org/packages/94/c1/3c8c94c7dd3905dbfde768381ce98778500a80db9924731d87ddcdb117e9/rpds_py-0.26.0-cp311-cp311-win_amd64.whl", hash = "sha256:87a5531de9f71aceb8af041d72fc4cab4943648d91875ed56d2e629bef6d4c03", size = 231732, upload-time = "2025-07-01T15:54:13.434Z" }, + { url = "https://files.pythonhosted.org/packages/67/93/e936fbed1b734eabf36ccb5d93c6a2e9246fbb13c1da011624b7286fae3e/rpds_py-0.26.0-cp311-cp311-win_arm64.whl", hash = "sha256:de2713f48c1ad57f89ac25b3cb7daed2156d8e822cf0eca9b96a6f990718cc41", size = 221917, upload-time = "2025-07-01T15:54:14.559Z" }, + { url = "https://files.pythonhosted.org/packages/ea/86/90eb87c6f87085868bd077c7a9938006eb1ce19ed4d06944a90d3560fce2/rpds_py-0.26.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:894514d47e012e794f1350f076c427d2347ebf82f9b958d554d12819849a369d", size = 363933, upload-time = "2025-07-01T15:54:15.734Z" }, + { url = "https://files.pythonhosted.org/packages/63/78/4469f24d34636242c924626082b9586f064ada0b5dbb1e9d096ee7a8e0c6/rpds_py-0.26.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:fc921b96fa95a097add244da36a1d9e4f3039160d1d30f1b35837bf108c21136", size = 350447, upload-time = "2025-07-01T15:54:16.922Z" }, + { url = "https://files.pythonhosted.org/packages/ad/91/c448ed45efdfdade82348d5e7995e15612754826ea640afc20915119734f/rpds_py-0.26.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e1157659470aa42a75448b6e943c895be8c70531c43cb78b9ba990778955582", size = 384711, upload-time = "2025-07-01T15:54:18.101Z" }, + { url = "https://files.pythonhosted.org/packages/ec/43/e5c86fef4be7f49828bdd4ecc8931f0287b1152c0bb0163049b3218740e7/rpds_py-0.26.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:521ccf56f45bb3a791182dc6b88ae5f8fa079dd705ee42138c76deb1238e554e", size = 400865, upload-time = "2025-07-01T15:54:19.295Z" }, + { url = "https://files.pythonhosted.org/packages/55/34/e00f726a4d44f22d5c5fe2e5ddd3ac3d7fd3f74a175607781fbdd06fe375/rpds_py-0.26.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9def736773fd56b305c0eef698be5192c77bfa30d55a0e5885f80126c4831a15", size = 517763, upload-time = "2025-07-01T15:54:20.858Z" }, + { url = "https://files.pythonhosted.org/packages/52/1c/52dc20c31b147af724b16104500fba13e60123ea0334beba7b40e33354b4/rpds_py-0.26.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cdad4ea3b4513b475e027be79e5a0ceac8ee1c113a1a11e5edc3c30c29f964d8", size = 406651, upload-time = "2025-07-01T15:54:22.508Z" }, + { url = "https://files.pythonhosted.org/packages/2e/77/87d7bfabfc4e821caa35481a2ff6ae0b73e6a391bb6b343db2c91c2b9844/rpds_py-0.26.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:82b165b07f416bdccf5c84546a484cc8f15137ca38325403864bfdf2b5b72f6a", size = 386079, upload-time = "2025-07-01T15:54:23.987Z" }, + { url = "https://files.pythonhosted.org/packages/e3/d4/7f2200c2d3ee145b65b3cddc4310d51f7da6a26634f3ac87125fd789152a/rpds_py-0.26.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d04cab0a54b9dba4d278fe955a1390da3cf71f57feb78ddc7cb67cbe0bd30323", size = 421379, upload-time = "2025-07-01T15:54:25.073Z" }, + { url = "https://files.pythonhosted.org/packages/ae/13/9fdd428b9c820869924ab62236b8688b122baa22d23efdd1c566938a39ba/rpds_py-0.26.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:79061ba1a11b6a12743a2b0f72a46aa2758613d454aa6ba4f5a265cc48850158", size = 562033, upload-time = "2025-07-01T15:54:26.225Z" }, + { url = "https://files.pythonhosted.org/packages/f3/e1/b69686c3bcbe775abac3a4c1c30a164a2076d28df7926041f6c0eb5e8d28/rpds_py-0.26.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:f405c93675d8d4c5ac87364bb38d06c988e11028a64b52a47158a355079661f3", size = 591639, upload-time = "2025-07-01T15:54:27.424Z" }, + { url = "https://files.pythonhosted.org/packages/5c/c9/1e3d8c8863c84a90197ac577bbc3d796a92502124c27092413426f670990/rpds_py-0.26.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:dafd4c44b74aa4bed4b250f1aed165b8ef5de743bcca3b88fc9619b6087093d2", size = 557105, upload-time = "2025-07-01T15:54:29.93Z" }, + { url = "https://files.pythonhosted.org/packages/9f/c5/90c569649057622959f6dcc40f7b516539608a414dfd54b8d77e3b201ac0/rpds_py-0.26.0-cp312-cp312-win32.whl", hash = "sha256:3da5852aad63fa0c6f836f3359647870e21ea96cf433eb393ffa45263a170d44", size = 223272, upload-time = "2025-07-01T15:54:31.128Z" }, + { url = "https://files.pythonhosted.org/packages/7d/16/19f5d9f2a556cfed454eebe4d354c38d51c20f3db69e7b4ce6cff904905d/rpds_py-0.26.0-cp312-cp312-win_amd64.whl", hash = "sha256:cf47cfdabc2194a669dcf7a8dbba62e37a04c5041d2125fae0233b720da6f05c", size = 234995, upload-time = "2025-07-01T15:54:32.195Z" }, + { url = "https://files.pythonhosted.org/packages/83/f0/7935e40b529c0e752dfaa7880224771b51175fce08b41ab4a92eb2fbdc7f/rpds_py-0.26.0-cp312-cp312-win_arm64.whl", hash = "sha256:20ab1ae4fa534f73647aad289003f1104092890849e0266271351922ed5574f8", size = 223198, upload-time = "2025-07-01T15:54:33.271Z" }, + { url = "https://files.pythonhosted.org/packages/6a/67/bb62d0109493b12b1c6ab00de7a5566aa84c0e44217c2d94bee1bd370da9/rpds_py-0.26.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:696764a5be111b036256c0b18cd29783fab22154690fc698062fc1b0084b511d", size = 363917, upload-time = "2025-07-01T15:54:34.755Z" }, + { url = "https://files.pythonhosted.org/packages/4b/f3/34e6ae1925a5706c0f002a8d2d7f172373b855768149796af87bd65dcdb9/rpds_py-0.26.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1e6c15d2080a63aaed876e228efe4f814bc7889c63b1e112ad46fdc8b368b9e1", size = 350073, upload-time = "2025-07-01T15:54:36.292Z" }, + { url = "https://files.pythonhosted.org/packages/75/83/1953a9d4f4e4de7fd0533733e041c28135f3c21485faaef56a8aadbd96b5/rpds_py-0.26.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:390e3170babf42462739a93321e657444f0862c6d722a291accc46f9d21ed04e", size = 384214, upload-time = "2025-07-01T15:54:37.469Z" }, + { url = "https://files.pythonhosted.org/packages/48/0e/983ed1b792b3322ea1d065e67f4b230f3b96025f5ce3878cc40af09b7533/rpds_py-0.26.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7da84c2c74c0f5bc97d853d9e17bb83e2dcafcff0dc48286916001cc114379a1", size = 400113, upload-time = "2025-07-01T15:54:38.954Z" }, + { url = "https://files.pythonhosted.org/packages/69/7f/36c0925fff6f660a80be259c5b4f5e53a16851f946eb080351d057698528/rpds_py-0.26.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4c5fe114a6dd480a510b6d3661d09d67d1622c4bf20660a474507aaee7eeeee9", size = 515189, upload-time = "2025-07-01T15:54:40.57Z" }, + { url = "https://files.pythonhosted.org/packages/13/45/cbf07fc03ba7a9b54662c9badb58294ecfb24f828b9732970bd1a431ed5c/rpds_py-0.26.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3100b3090269f3a7ea727b06a6080d4eb7439dca4c0e91a07c5d133bb1727ea7", size = 406998, upload-time = "2025-07-01T15:54:43.025Z" }, + { url = "https://files.pythonhosted.org/packages/6c/b0/8fa5e36e58657997873fd6a1cf621285ca822ca75b4b3434ead047daa307/rpds_py-0.26.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2c03c9b0c64afd0320ae57de4c982801271c0c211aa2d37f3003ff5feb75bb04", size = 385903, upload-time = "2025-07-01T15:54:44.752Z" }, + { url = "https://files.pythonhosted.org/packages/4b/f7/b25437772f9f57d7a9fbd73ed86d0dcd76b4c7c6998348c070d90f23e315/rpds_py-0.26.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5963b72ccd199ade6ee493723d18a3f21ba7d5b957017607f815788cef50eaf1", size = 419785, upload-time = "2025-07-01T15:54:46.043Z" }, + { url = "https://files.pythonhosted.org/packages/a7/6b/63ffa55743dfcb4baf2e9e77a0b11f7f97ed96a54558fcb5717a4b2cd732/rpds_py-0.26.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:9da4e873860ad5bab3291438525cae80169daecbfafe5657f7f5fb4d6b3f96b9", size = 561329, upload-time = "2025-07-01T15:54:47.64Z" }, + { url = "https://files.pythonhosted.org/packages/2f/07/1f4f5e2886c480a2346b1e6759c00278b8a69e697ae952d82ae2e6ee5db0/rpds_py-0.26.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:5afaddaa8e8c7f1f7b4c5c725c0070b6eed0228f705b90a1732a48e84350f4e9", size = 590875, upload-time = "2025-07-01T15:54:48.9Z" }, + { url = "https://files.pythonhosted.org/packages/cc/bc/e6639f1b91c3a55f8c41b47d73e6307051b6e246254a827ede730624c0f8/rpds_py-0.26.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4916dc96489616a6f9667e7526af8fa693c0fdb4f3acb0e5d9f4400eb06a47ba", size = 556636, upload-time = "2025-07-01T15:54:50.619Z" }, + { url = "https://files.pythonhosted.org/packages/05/4c/b3917c45566f9f9a209d38d9b54a1833f2bb1032a3e04c66f75726f28876/rpds_py-0.26.0-cp313-cp313-win32.whl", hash = "sha256:2a343f91b17097c546b93f7999976fd6c9d5900617aa848c81d794e062ab302b", size = 222663, upload-time = "2025-07-01T15:54:52.023Z" }, + { url = "https://files.pythonhosted.org/packages/e0/0b/0851bdd6025775aaa2365bb8de0697ee2558184c800bfef8d7aef5ccde58/rpds_py-0.26.0-cp313-cp313-win_amd64.whl", hash = "sha256:0a0b60701f2300c81b2ac88a5fb893ccfa408e1c4a555a77f908a2596eb875a5", size = 234428, upload-time = "2025-07-01T15:54:53.692Z" }, + { url = "https://files.pythonhosted.org/packages/ed/e8/a47c64ed53149c75fb581e14a237b7b7cd18217e969c30d474d335105622/rpds_py-0.26.0-cp313-cp313-win_arm64.whl", hash = "sha256:257d011919f133a4746958257f2c75238e3ff54255acd5e3e11f3ff41fd14256", size = 222571, upload-time = "2025-07-01T15:54:54.822Z" }, + { url = "https://files.pythonhosted.org/packages/89/bf/3d970ba2e2bcd17d2912cb42874107390f72873e38e79267224110de5e61/rpds_py-0.26.0-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:529c8156d7506fba5740e05da8795688f87119cce330c244519cf706a4a3d618", size = 360475, upload-time = "2025-07-01T15:54:56.228Z" }, + { url = "https://files.pythonhosted.org/packages/82/9f/283e7e2979fc4ec2d8ecee506d5a3675fce5ed9b4b7cb387ea5d37c2f18d/rpds_py-0.26.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:f53ec51f9d24e9638a40cabb95078ade8c99251945dad8d57bf4aabe86ecee35", size = 346692, upload-time = "2025-07-01T15:54:58.561Z" }, + { url = "https://files.pythonhosted.org/packages/e3/03/7e50423c04d78daf391da3cc4330bdb97042fc192a58b186f2d5deb7befd/rpds_py-0.26.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7ab504c4d654e4a29558eaa5bb8cea5fdc1703ea60a8099ffd9c758472cf913f", size = 379415, upload-time = "2025-07-01T15:54:59.751Z" }, + { url = "https://files.pythonhosted.org/packages/57/00/d11ee60d4d3b16808432417951c63df803afb0e0fc672b5e8d07e9edaaae/rpds_py-0.26.0-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fd0641abca296bc1a00183fe44f7fced8807ed49d501f188faa642d0e4975b83", size = 391783, upload-time = "2025-07-01T15:55:00.898Z" }, + { url = "https://files.pythonhosted.org/packages/08/b3/1069c394d9c0d6d23c5b522e1f6546b65793a22950f6e0210adcc6f97c3e/rpds_py-0.26.0-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:69b312fecc1d017b5327afa81d4da1480f51c68810963a7336d92203dbb3d4f1", size = 512844, upload-time = "2025-07-01T15:55:02.201Z" }, + { url = "https://files.pythonhosted.org/packages/08/3b/c4fbf0926800ed70b2c245ceca99c49f066456755f5d6eb8863c2c51e6d0/rpds_py-0.26.0-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c741107203954f6fc34d3066d213d0a0c40f7bb5aafd698fb39888af277c70d8", size = 402105, upload-time = "2025-07-01T15:55:03.698Z" }, + { url = "https://files.pythonhosted.org/packages/1c/b0/db69b52ca07413e568dae9dc674627a22297abb144c4d6022c6d78f1e5cc/rpds_py-0.26.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc3e55a7db08dc9a6ed5fb7103019d2c1a38a349ac41901f9f66d7f95750942f", size = 383440, upload-time = "2025-07-01T15:55:05.398Z" }, + { url = "https://files.pythonhosted.org/packages/4c/e1/c65255ad5b63903e56b3bb3ff9dcc3f4f5c3badde5d08c741ee03903e951/rpds_py-0.26.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9e851920caab2dbcae311fd28f4313c6953993893eb5c1bb367ec69d9a39e7ed", size = 412759, upload-time = "2025-07-01T15:55:08.316Z" }, + { url = "https://files.pythonhosted.org/packages/e4/22/bb731077872377a93c6e93b8a9487d0406c70208985831034ccdeed39c8e/rpds_py-0.26.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:dfbf280da5f876d0b00c81f26bedce274e72a678c28845453885a9b3c22ae632", size = 556032, upload-time = "2025-07-01T15:55:09.52Z" }, + { url = "https://files.pythonhosted.org/packages/e0/8b/393322ce7bac5c4530fb96fc79cc9ea2f83e968ff5f6e873f905c493e1c4/rpds_py-0.26.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:1cc81d14ddfa53d7f3906694d35d54d9d3f850ef8e4e99ee68bc0d1e5fed9a9c", size = 585416, upload-time = "2025-07-01T15:55:11.216Z" }, + { url = "https://files.pythonhosted.org/packages/49/ae/769dc372211835bf759319a7aae70525c6eb523e3371842c65b7ef41c9c6/rpds_py-0.26.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:dca83c498b4650a91efcf7b88d669b170256bf8017a5db6f3e06c2bf031f57e0", size = 554049, upload-time = "2025-07-01T15:55:13.004Z" }, + { url = "https://files.pythonhosted.org/packages/6b/f9/4c43f9cc203d6ba44ce3146246cdc38619d92c7bd7bad4946a3491bd5b70/rpds_py-0.26.0-cp313-cp313t-win32.whl", hash = "sha256:4d11382bcaf12f80b51d790dee295c56a159633a8e81e6323b16e55d81ae37e9", size = 218428, upload-time = "2025-07-01T15:55:14.486Z" }, + { url = "https://files.pythonhosted.org/packages/7e/8b/9286b7e822036a4a977f2f1e851c7345c20528dbd56b687bb67ed68a8ede/rpds_py-0.26.0-cp313-cp313t-win_amd64.whl", hash = "sha256:ff110acded3c22c033e637dd8896e411c7d3a11289b2edf041f86663dbc791e9", size = 231524, upload-time = "2025-07-01T15:55:15.745Z" }, + { url = "https://files.pythonhosted.org/packages/55/07/029b7c45db910c74e182de626dfdae0ad489a949d84a468465cd0ca36355/rpds_py-0.26.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:da619979df60a940cd434084355c514c25cf8eb4cf9a508510682f6c851a4f7a", size = 364292, upload-time = "2025-07-01T15:55:17.001Z" }, + { url = "https://files.pythonhosted.org/packages/13/d1/9b3d3f986216b4d1f584878dca15ce4797aaf5d372d738974ba737bf68d6/rpds_py-0.26.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:ea89a2458a1a75f87caabefe789c87539ea4e43b40f18cff526052e35bbb4fdf", size = 350334, upload-time = "2025-07-01T15:55:18.922Z" }, + { url = "https://files.pythonhosted.org/packages/18/98/16d5e7bc9ec715fa9668731d0cf97f6b032724e61696e2db3d47aeb89214/rpds_py-0.26.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:feac1045b3327a45944e7dcbeb57530339f6b17baff154df51ef8b0da34c8c12", size = 384875, upload-time = "2025-07-01T15:55:20.399Z" }, + { url = "https://files.pythonhosted.org/packages/f9/13/aa5e2b1ec5ab0e86a5c464d53514c0467bec6ba2507027d35fc81818358e/rpds_py-0.26.0-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b818a592bd69bfe437ee8368603d4a2d928c34cffcdf77c2e761a759ffd17d20", size = 399993, upload-time = "2025-07-01T15:55:21.729Z" }, + { url = "https://files.pythonhosted.org/packages/17/03/8021810b0e97923abdbab6474c8b77c69bcb4b2c58330777df9ff69dc559/rpds_py-0.26.0-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1a8b0dd8648709b62d9372fc00a57466f5fdeefed666afe3fea5a6c9539a0331", size = 516683, upload-time = "2025-07-01T15:55:22.918Z" }, + { url = "https://files.pythonhosted.org/packages/dc/b1/da8e61c87c2f3d836954239fdbbfb477bb7b54d74974d8f6fcb34342d166/rpds_py-0.26.0-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6d3498ad0df07d81112aa6ec6c95a7e7b1ae00929fb73e7ebee0f3faaeabad2f", size = 408825, upload-time = "2025-07-01T15:55:24.207Z" }, + { url = "https://files.pythonhosted.org/packages/38/bc/1fc173edaaa0e52c94b02a655db20697cb5fa954ad5a8e15a2c784c5cbdd/rpds_py-0.26.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:24a4146ccb15be237fdef10f331c568e1b0e505f8c8c9ed5d67759dac58ac246", size = 387292, upload-time = "2025-07-01T15:55:25.554Z" }, + { url = "https://files.pythonhosted.org/packages/7c/eb/3a9bb4bd90867d21916f253caf4f0d0be7098671b6715ad1cead9fe7bab9/rpds_py-0.26.0-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a9a63785467b2d73635957d32a4f6e73d5e4df497a16a6392fa066b753e87387", size = 420435, upload-time = "2025-07-01T15:55:27.798Z" }, + { url = "https://files.pythonhosted.org/packages/cd/16/e066dcdb56f5632713445271a3f8d3d0b426d51ae9c0cca387799df58b02/rpds_py-0.26.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:de4ed93a8c91debfd5a047be327b7cc8b0cc6afe32a716bbbc4aedca9e2a83af", size = 562410, upload-time = "2025-07-01T15:55:29.057Z" }, + { url = "https://files.pythonhosted.org/packages/60/22/ddbdec7eb82a0dc2e455be44c97c71c232983e21349836ce9f272e8a3c29/rpds_py-0.26.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:caf51943715b12af827696ec395bfa68f090a4c1a1d2509eb4e2cb69abbbdb33", size = 590724, upload-time = "2025-07-01T15:55:30.719Z" }, + { url = "https://files.pythonhosted.org/packages/2c/b4/95744085e65b7187d83f2fcb0bef70716a1ea0a9e5d8f7f39a86e5d83424/rpds_py-0.26.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:4a59e5bc386de021f56337f757301b337d7ab58baa40174fb150accd480bc953", size = 558285, upload-time = "2025-07-01T15:55:31.981Z" }, + { url = "https://files.pythonhosted.org/packages/37/37/6309a75e464d1da2559446f9c811aa4d16343cebe3dbb73701e63f760caa/rpds_py-0.26.0-cp314-cp314-win32.whl", hash = "sha256:92c8db839367ef16a662478f0a2fe13e15f2227da3c1430a782ad0f6ee009ec9", size = 223459, upload-time = "2025-07-01T15:55:33.312Z" }, + { url = "https://files.pythonhosted.org/packages/d9/6f/8e9c11214c46098b1d1391b7e02b70bb689ab963db3b19540cba17315291/rpds_py-0.26.0-cp314-cp314-win_amd64.whl", hash = "sha256:b0afb8cdd034150d4d9f53926226ed27ad15b7f465e93d7468caaf5eafae0d37", size = 236083, upload-time = "2025-07-01T15:55:34.933Z" }, + { url = "https://files.pythonhosted.org/packages/47/af/9c4638994dd623d51c39892edd9d08e8be8220a4b7e874fa02c2d6e91955/rpds_py-0.26.0-cp314-cp314-win_arm64.whl", hash = "sha256:ca3f059f4ba485d90c8dc75cb5ca897e15325e4e609812ce57f896607c1c0867", size = 223291, upload-time = "2025-07-01T15:55:36.202Z" }, + { url = "https://files.pythonhosted.org/packages/4d/db/669a241144460474aab03e254326b32c42def83eb23458a10d163cb9b5ce/rpds_py-0.26.0-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:5afea17ab3a126006dc2f293b14ffc7ef3c85336cf451564a0515ed7648033da", size = 361445, upload-time = "2025-07-01T15:55:37.483Z" }, + { url = "https://files.pythonhosted.org/packages/3b/2d/133f61cc5807c6c2fd086a46df0eb8f63a23f5df8306ff9f6d0fd168fecc/rpds_py-0.26.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:69f0c0a3df7fd3a7eec50a00396104bb9a843ea6d45fcc31c2d5243446ffd7a7", size = 347206, upload-time = "2025-07-01T15:55:38.828Z" }, + { url = "https://files.pythonhosted.org/packages/05/bf/0e8fb4c05f70273469eecf82f6ccf37248558526a45321644826555db31b/rpds_py-0.26.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:801a71f70f9813e82d2513c9a96532551fce1e278ec0c64610992c49c04c2dad", size = 380330, upload-time = "2025-07-01T15:55:40.175Z" }, + { url = "https://files.pythonhosted.org/packages/d4/a8/060d24185d8b24d3923322f8d0ede16df4ade226a74e747b8c7c978e3dd3/rpds_py-0.26.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:df52098cde6d5e02fa75c1f6244f07971773adb4a26625edd5c18fee906fa84d", size = 392254, upload-time = "2025-07-01T15:55:42.015Z" }, + { url = "https://files.pythonhosted.org/packages/b9/7b/7c2e8a9ee3e6bc0bae26bf29f5219955ca2fbb761dca996a83f5d2f773fe/rpds_py-0.26.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9bc596b30f86dc6f0929499c9e574601679d0341a0108c25b9b358a042f51bca", size = 516094, upload-time = "2025-07-01T15:55:43.603Z" }, + { url = "https://files.pythonhosted.org/packages/75/d6/f61cafbed8ba1499b9af9f1777a2a199cd888f74a96133d8833ce5eaa9c5/rpds_py-0.26.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9dfbe56b299cf5875b68eb6f0ebaadc9cac520a1989cac0db0765abfb3709c19", size = 402889, upload-time = "2025-07-01T15:55:45.275Z" }, + { url = "https://files.pythonhosted.org/packages/92/19/c8ac0a8a8df2dd30cdec27f69298a5c13e9029500d6d76718130f5e5be10/rpds_py-0.26.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ac64f4b2bdb4ea622175c9ab7cf09444e412e22c0e02e906978b3b488af5fde8", size = 384301, upload-time = "2025-07-01T15:55:47.098Z" }, + { url = "https://files.pythonhosted.org/packages/41/e1/6b1859898bc292a9ce5776016c7312b672da00e25cec74d7beced1027286/rpds_py-0.26.0-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:181ef9b6bbf9845a264f9aa45c31836e9f3c1f13be565d0d010e964c661d1e2b", size = 412891, upload-time = "2025-07-01T15:55:48.412Z" }, + { url = "https://files.pythonhosted.org/packages/ef/b9/ceb39af29913c07966a61367b3c08b4f71fad841e32c6b59a129d5974698/rpds_py-0.26.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:49028aa684c144ea502a8e847d23aed5e4c2ef7cadfa7d5eaafcb40864844b7a", size = 557044, upload-time = "2025-07-01T15:55:49.816Z" }, + { url = "https://files.pythonhosted.org/packages/2f/27/35637b98380731a521f8ec4f3fd94e477964f04f6b2f8f7af8a2d889a4af/rpds_py-0.26.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:e5d524d68a474a9688336045bbf76cb0def88549c1b2ad9dbfec1fb7cfbe9170", size = 585774, upload-time = "2025-07-01T15:55:51.192Z" }, + { url = "https://files.pythonhosted.org/packages/52/d9/3f0f105420fecd18551b678c9a6ce60bd23986098b252a56d35781b3e7e9/rpds_py-0.26.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:c1851f429b822831bd2edcbe0cfd12ee9ea77868f8d3daf267b189371671c80e", size = 554886, upload-time = "2025-07-01T15:55:52.541Z" }, + { url = "https://files.pythonhosted.org/packages/6b/c5/347c056a90dc8dd9bc240a08c527315008e1b5042e7a4cf4ac027be9d38a/rpds_py-0.26.0-cp314-cp314t-win32.whl", hash = "sha256:7bdb17009696214c3b66bb3590c6d62e14ac5935e53e929bcdbc5a495987a84f", size = 219027, upload-time = "2025-07-01T15:55:53.874Z" }, + { url = "https://files.pythonhosted.org/packages/75/04/5302cea1aa26d886d34cadbf2dc77d90d7737e576c0065f357b96dc7a1a6/rpds_py-0.26.0-cp314-cp314t-win_amd64.whl", hash = "sha256:f14440b9573a6f76b4ee4770c13f0b5921f71dde3b6fcb8dabbefd13b7fe05d7", size = 232821, upload-time = "2025-07-01T15:55:55.167Z" }, + { url = "https://files.pythonhosted.org/packages/51/f2/b5c85b758a00c513bb0389f8fc8e61eb5423050c91c958cdd21843faa3e6/rpds_py-0.26.0-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:f61a9326f80ca59214d1cceb0a09bb2ece5b2563d4e0cd37bfd5515c28510674", size = 373505, upload-time = "2025-07-01T15:56:34.716Z" }, + { url = "https://files.pythonhosted.org/packages/23/e0/25db45e391251118e915e541995bb5f5ac5691a3b98fb233020ba53afc9b/rpds_py-0.26.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:183f857a53bcf4b1b42ef0f57ca553ab56bdd170e49d8091e96c51c3d69ca696", size = 359468, upload-time = "2025-07-01T15:56:36.219Z" }, + { url = "https://files.pythonhosted.org/packages/0b/73/dd5ee6075bb6491be3a646b301dfd814f9486d924137a5098e61f0487e16/rpds_py-0.26.0-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:941c1cfdf4799d623cf3aa1d326a6b4fdb7a5799ee2687f3516738216d2262fb", size = 382680, upload-time = "2025-07-01T15:56:37.644Z" }, + { url = "https://files.pythonhosted.org/packages/2f/10/84b522ff58763a5c443f5bcedc1820240e454ce4e620e88520f04589e2ea/rpds_py-0.26.0-pp311-pypy311_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:72a8d9564a717ee291f554eeb4bfeafe2309d5ec0aa6c475170bdab0f9ee8e88", size = 397035, upload-time = "2025-07-01T15:56:39.241Z" }, + { url = "https://files.pythonhosted.org/packages/06/ea/8667604229a10a520fcbf78b30ccc278977dcc0627beb7ea2c96b3becef0/rpds_py-0.26.0-pp311-pypy311_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:511d15193cbe013619dd05414c35a7dedf2088fcee93c6bbb7c77859765bd4e8", size = 514922, upload-time = "2025-07-01T15:56:40.645Z" }, + { url = "https://files.pythonhosted.org/packages/24/e6/9ed5b625c0661c4882fc8cdf302bf8e96c73c40de99c31e0b95ed37d508c/rpds_py-0.26.0-pp311-pypy311_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:aea1f9741b603a8d8fedb0ed5502c2bc0accbc51f43e2ad1337fe7259c2b77a5", size = 402822, upload-time = "2025-07-01T15:56:42.137Z" }, + { url = "https://files.pythonhosted.org/packages/8a/58/212c7b6fd51946047fb45d3733da27e2fa8f7384a13457c874186af691b1/rpds_py-0.26.0-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4019a9d473c708cf2f16415688ef0b4639e07abaa569d72f74745bbeffafa2c7", size = 384336, upload-time = "2025-07-01T15:56:44.239Z" }, + { url = "https://files.pythonhosted.org/packages/aa/f5/a40ba78748ae8ebf4934d4b88e77b98497378bc2c24ba55ebe87a4e87057/rpds_py-0.26.0-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:093d63b4b0f52d98ebae33b8c50900d3d67e0666094b1be7a12fffd7f65de74b", size = 416871, upload-time = "2025-07-01T15:56:46.284Z" }, + { url = "https://files.pythonhosted.org/packages/d5/a6/33b1fc0c9f7dcfcfc4a4353daa6308b3ece22496ceece348b3e7a7559a09/rpds_py-0.26.0-pp311-pypy311_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:2abe21d8ba64cded53a2a677e149ceb76dcf44284202d737178afe7ba540c1eb", size = 559439, upload-time = "2025-07-01T15:56:48.549Z" }, + { url = "https://files.pythonhosted.org/packages/71/2d/ceb3f9c12f8cfa56d34995097f6cd99da1325642c60d1b6680dd9df03ed8/rpds_py-0.26.0-pp311-pypy311_pp73-musllinux_1_2_i686.whl", hash = "sha256:4feb7511c29f8442cbbc28149a92093d32e815a28aa2c50d333826ad2a20fdf0", size = 588380, upload-time = "2025-07-01T15:56:50.086Z" }, + { url = "https://files.pythonhosted.org/packages/c8/ed/9de62c2150ca8e2e5858acf3f4f4d0d180a38feef9fdab4078bea63d8dba/rpds_py-0.26.0-pp311-pypy311_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:e99685fc95d386da368013e7fb4269dd39c30d99f812a8372d62f244f662709c", size = 555334, upload-time = "2025-07-01T15:56:51.703Z" }, ] [[package]] From 8ca2dfd49ee889dd8e2f0c91ee83d324d67ef0dc Mon Sep 17 00:00:00 2001 From: Erik Everson Date: Wed, 9 Jul 2025 10:52:57 -0700 Subject: [PATCH 363/521] initial rough out of find_plasma_potential_via_didv_peak --- .../swept_langmuir/plasma_potential.py | 84 +++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 src/plasmapy/analysis/swept_langmuir/plasma_potential.py diff --git a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py new file mode 100644 index 0000000000..21dccab9fa --- /dev/null +++ b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py @@ -0,0 +1,84 @@ +""" +Functionality for determining the plasma potential of a Langmuir sweep. +""" + +__all__ = ["find_plasma_potential_via_didv_peak"] + +import numpy as np + +from scipy import signal + +from plasmapy.analysis.swept_langmuir.helpers import check_sweep, merge_voltage_clusters + + +def find_plasma_potential_via_didv_peak( + voltage: np.ndarray, + current: np.ndarray, + # *, + floating_potential: float | None = None, + smooth_fractions=None, +): + # check voltage and current arrays + voltage, current = check_sweep(voltage, current, strip_units=True) + voltage, current = merge_voltage_clusters(voltage, current, voltage_step_size=0) + + # condition floating potential + if floating_potential is None: + pass + elif not isinstance(floating_potential, float | int | np.floating | np.integer): + raise TypeError( + f"Expected None or float for floating_potential, got type " + f"{type(floating_potential)}." + ) + elif not (np.min(voltage) <= floating_potential <= np.max(voltage)): + raise ValueError( + f"Given floating_potential ({floating_potential}) is outside range " + f"[{np.min(voltage)}, {np.max(voltage)}]." + ) + + # determine data window + first_index = 0 + if floating_potential is not None: + mask = voltage > floating_potential + if np.count_nonzero(mask) > 0: + first_index = np.where(mask)[0][0] + data_size = voltage.size - first_index + + # define smooth_fractions + # TODO: add better description + if smooth_fractions is None: + smooth_fractions = np.linspace(0.01, 0.25, num=25) + + # create bin sizes (smooth_windows) for the savgol_filter + smooth_windows = np.unique(np.rint(smooth_fractions * data_size, dtype=int)) + mask = smooth_windows > 2 + smooth_windows = smooth_windows[mask] + mask = smooth_windows % 2 == 0 + if np.count_nonzero(mask) > 0: + smooth_windows[mask] = smooth_windows[mask] + 1 + smooth_windows = np.unique(smooth_windows) + + voltage_slice = voltage[first_index:] + current_slice = current[first_index:] + plasma_potentials = [] + for _window in smooth_windows: + v_smooth = signal.savgol_filter(voltage_slice, _window, 1) + c_smooth = signal.savgol_filter(current_slice, _window, 1) + + didv = np.gradient(c_smooth, v_smooth) + imax = np.argmax(didv) + if imax.size > 1: + ... + else: + vp = voltage_slice[imax[0]] + + plasma_potentials.append(vp) + + + + +find_vp_ = find_plasma_potential_via_didv_peak +""" +Alias to +:func:`~plasmapy.analysis.swept_langmuir.plasma_potential.find_plasma_potential_via_didv_peak`. +""" From acf0d5943f200b5b84646e0a1f234ea07c57fb24 Mon Sep 17 00:00:00 2001 From: "plasmapy-requirements-bot[bot]" <134649236+plasmapy-requirements-bot[bot]@users.noreply.github.com> Date: Thu, 10 Jul 2025 13:40:24 -0400 Subject: [PATCH 364/521] Update requirements with 'nox -s requirements' (#3051) Co-authored-by: namurphy <8931994+namurphy@users.noreply.github.com> --- uv.lock | 96 ++++++++++++++++++++++++++++----------------------------- 1 file changed, 48 insertions(+), 48 deletions(-) diff --git a/uv.lock b/uv.lock index df79684e62..0b2c2f4a4e 100644 --- a/uv.lock +++ b/uv.lock @@ -140,11 +140,11 @@ wheels = [ [[package]] name = "astropy-iers-data" -version = "0.2025.6.30.0.39.40" +version = "0.2025.7.7.0.39.39" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/7e/90/52b0ef79e60942b6d241f4fd7bda1203612a21904175a0842797ccac218b/astropy_iers_data-0.2025.6.30.0.39.40.tar.gz", hash = "sha256:511a1bb0185b5eef28dc05d8aecd7d5a7201156370d7bb9bbf439e76ffc33b00", size = 1900718, upload-time = "2025-06-30T00:40:12.067Z" } +sdist = { url = "https://files.pythonhosted.org/packages/e8/88/ab5663cd28e9b9958a9e0c1ff0f755603b3ed1c8230818f9f1cbb19cf354/astropy_iers_data-0.2025.7.7.0.39.39.tar.gz", hash = "sha256:e29bf3e16816a92282a39edd587150296047b7b08ac6b8048b429a7d1ef1c386", size = 1901264, upload-time = "2025-07-07T00:40:21.053Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ac/00/5837d03a5c03c0a3a57b0b37fde73363fe42e7a6d0eca663ec3ab59b8d2c/astropy_iers_data-0.2025.6.30.0.39.40-py3-none-any.whl", hash = "sha256:dea5e1a1d4125246efcb7a58322569f9174371f0ad4d48963a5c3d8ded0dcc3e", size = 1956086, upload-time = "2025-06-30T00:40:10.425Z" }, + { url = "https://files.pythonhosted.org/packages/09/7f/ba056c9d42d8c495c36f33ec72a893de9df860ecfcba3e7640db874a7411/astropy_iers_data-0.2025.7.7.0.39.39-py3-none-any.whl", hash = "sha256:770221844e56c4cafba8c65659438bde5c96041d246dc4eb13cbc63890e33299", size = 1956686, upload-time = "2025-07-07T00:40:19.368Z" }, ] [[package]] @@ -206,11 +206,11 @@ css = [ [[package]] name = "certifi" -version = "2025.6.15" +version = "2025.7.9" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/73/f7/f14b46d4bcd21092d7d3ccef689615220d8a08fb25e564b65d20738e672e/certifi-2025.6.15.tar.gz", hash = "sha256:d747aa5a8b9bbbb1bb8c22bb13e22bd1f18e9796defa16bab421f7f7a317323b", size = 158753, upload-time = "2025-06-15T02:45:51.329Z" } +sdist = { url = "https://files.pythonhosted.org/packages/de/8a/c729b6b60c66a38f590c4e774decc4b2ec7b0576be8f1aa984a53ffa812a/certifi-2025.7.9.tar.gz", hash = "sha256:c1d2ec05395148ee10cf672ffc28cd37ea0ab0d99f9cc74c43e588cbd111b079", size = 160386, upload-time = "2025-07-09T02:13:58.874Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/84/ae/320161bd181fc06471eed047ecce67b693fd7515b16d495d8932db763426/certifi-2025.6.15-py3-none-any.whl", hash = "sha256:2e0c7ce7cb5d8f8634ca55d2ba7e6ec2689a2fd6537d8dec1296a477a4910057", size = 157650, upload-time = "2025-06-15T02:45:49.977Z" }, + { url = "https://files.pythonhosted.org/packages/66/f3/80a3f974c8b535d394ff960a11ac20368e06b736da395b551a49ce950cce/certifi-2025.7.9-py3-none-any.whl", hash = "sha256:d842783a14f8fdd646895ac26f719a061408834473cfc10203f6a575beb15d39", size = 159230, upload-time = "2025-07-09T02:13:57.007Z" }, ] [[package]] @@ -657,15 +657,15 @@ wheels = [ [[package]] name = "hypothesis" -version = "6.135.24" +version = "6.135.26" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "attrs" }, { name = "sortedcontainers" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/cf/ae/f846b67ce9fc80cf51cece6b7adaa3fe2de4251242d142e241ce5d4aa26f/hypothesis-6.135.24.tar.gz", hash = "sha256:e301aeb2691ec0a1f62bfc405eaa966055d603e328cd854c1ed59e1728e35ab6", size = 454011, upload-time = "2025-07-03T02:46:51.776Z" } +sdist = { url = "https://files.pythonhosted.org/packages/da/83/15c4e30561a0d8c8d076c88cb159187823d877118f34c851ada3b9b02a7b/hypothesis-6.135.26.tar.gz", hash = "sha256:73af0e46cd5039c6806f514fed6a3c185d91ef88b5a1577477099ddbd1a2e300", size = 454523, upload-time = "2025-07-05T04:59:45.443Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ed/cb/c38acf27826a96712302229622f32dd356b9c4fbe52a3e9f615706027af8/hypothesis-6.135.24-py3-none-any.whl", hash = "sha256:88ed21fbfa481ca9851a9080841b3caca14cd4ed51a165dfae8006325775ee72", size = 520920, upload-time = "2025-07-03T02:46:48.286Z" }, + { url = "https://files.pythonhosted.org/packages/3c/78/db4fdc464219455f8dde90074660c3faf8429101b2d1299cac7d219e3176/hypothesis-6.135.26-py3-none-any.whl", hash = "sha256:fa237cbe2ae2c31d65f7230dcb866139ace635dcfec6c30dddf25974dd8ff4b9", size = 521517, upload-time = "2025-07-05T04:59:42.061Z" }, ] [[package]] @@ -1431,7 +1431,7 @@ wheels = [ [[package]] name = "pandas" -version = "2.3.0" +version = "2.3.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "numpy" }, @@ -1439,35 +1439,35 @@ dependencies = [ { name = "pytz" }, { name = "tzdata" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/72/51/48f713c4c728d7c55ef7444ba5ea027c26998d96d1a40953b346438602fc/pandas-2.3.0.tar.gz", hash = "sha256:34600ab34ebf1131a7613a260a61dbe8b62c188ec0ea4c296da7c9a06b004133", size = 4484490, upload-time = "2025-06-05T03:27:54.133Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/96/1e/ba313812a699fe37bf62e6194265a4621be11833f5fce46d9eae22acb5d7/pandas-2.3.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:8adff9f138fc614347ff33812046787f7d43b3cef7c0f0171b3340cae333f6ca", size = 11551836, upload-time = "2025-06-05T03:26:22.784Z" }, - { url = "https://files.pythonhosted.org/packages/1b/cc/0af9c07f8d714ea563b12383a7e5bde9479cf32413ee2f346a9c5a801f22/pandas-2.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e5f08eb9a445d07720776df6e641975665c9ea12c9d8a331e0f6890f2dcd76ef", size = 10807977, upload-time = "2025-06-05T16:50:11.109Z" }, - { url = "https://files.pythonhosted.org/packages/ee/3e/8c0fb7e2cf4a55198466ced1ca6a9054ae3b7e7630df7757031df10001fd/pandas-2.3.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fa35c266c8cd1a67d75971a1912b185b492d257092bdd2709bbdebe574ed228d", size = 11788230, upload-time = "2025-06-05T03:26:27.417Z" }, - { url = "https://files.pythonhosted.org/packages/14/22/b493ec614582307faf3f94989be0f7f0a71932ed6f56c9a80c0bb4a3b51e/pandas-2.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:14a0cc77b0f089d2d2ffe3007db58f170dae9b9f54e569b299db871a3ab5bf46", size = 12370423, upload-time = "2025-06-05T03:26:34.142Z" }, - { url = "https://files.pythonhosted.org/packages/9f/74/b012addb34cda5ce855218a37b258c4e056a0b9b334d116e518d72638737/pandas-2.3.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c06f6f144ad0a1bf84699aeea7eff6068ca5c63ceb404798198af7eb86082e33", size = 12990594, upload-time = "2025-06-06T00:00:13.934Z" }, - { url = "https://files.pythonhosted.org/packages/95/81/b310e60d033ab64b08e66c635b94076488f0b6ce6a674379dd5b224fc51c/pandas-2.3.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ed16339bc354a73e0a609df36d256672c7d296f3f767ac07257801aa064ff73c", size = 13745952, upload-time = "2025-06-05T03:26:39.475Z" }, - { url = "https://files.pythonhosted.org/packages/25/ac/f6ee5250a8881b55bd3aecde9b8cfddea2f2b43e3588bca68a4e9aaf46c8/pandas-2.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:fa07e138b3f6c04addfeaf56cc7fdb96c3b68a3fe5e5401251f231fce40a0d7a", size = 11094534, upload-time = "2025-06-05T03:26:43.23Z" }, - { url = "https://files.pythonhosted.org/packages/94/46/24192607058dd607dbfacdd060a2370f6afb19c2ccb617406469b9aeb8e7/pandas-2.3.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:2eb4728a18dcd2908c7fccf74a982e241b467d178724545a48d0caf534b38ebf", size = 11573865, upload-time = "2025-06-05T03:26:46.774Z" }, - { url = "https://files.pythonhosted.org/packages/9f/cc/ae8ea3b800757a70c9fdccc68b67dc0280a6e814efcf74e4211fd5dea1ca/pandas-2.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b9d8c3187be7479ea5c3d30c32a5d73d62a621166675063b2edd21bc47614027", size = 10702154, upload-time = "2025-06-05T16:50:14.439Z" }, - { url = "https://files.pythonhosted.org/packages/d8/ba/a7883d7aab3d24c6540a2768f679e7414582cc389876d469b40ec749d78b/pandas-2.3.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9ff730713d4c4f2f1c860e36c005c7cefc1c7c80c21c0688fd605aa43c9fcf09", size = 11262180, upload-time = "2025-06-05T16:50:17.453Z" }, - { url = "https://files.pythonhosted.org/packages/01/a5/931fc3ad333d9d87b10107d948d757d67ebcfc33b1988d5faccc39c6845c/pandas-2.3.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba24af48643b12ffe49b27065d3babd52702d95ab70f50e1b34f71ca703e2c0d", size = 11991493, upload-time = "2025-06-05T03:26:51.813Z" }, - { url = "https://files.pythonhosted.org/packages/d7/bf/0213986830a92d44d55153c1d69b509431a972eb73f204242988c4e66e86/pandas-2.3.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:404d681c698e3c8a40a61d0cd9412cc7364ab9a9cc6e144ae2992e11a2e77a20", size = 12470733, upload-time = "2025-06-06T00:00:18.651Z" }, - { url = "https://files.pythonhosted.org/packages/a4/0e/21eb48a3a34a7d4bac982afc2c4eb5ab09f2d988bdf29d92ba9ae8e90a79/pandas-2.3.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:6021910b086b3ca756755e86ddc64e0ddafd5e58e076c72cb1585162e5ad259b", size = 13212406, upload-time = "2025-06-05T03:26:55.992Z" }, - { url = "https://files.pythonhosted.org/packages/1f/d9/74017c4eec7a28892d8d6e31ae9de3baef71f5a5286e74e6b7aad7f8c837/pandas-2.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:094e271a15b579650ebf4c5155c05dcd2a14fd4fdd72cf4854b2f7ad31ea30be", size = 10976199, upload-time = "2025-06-05T03:26:59.594Z" }, - { url = "https://files.pythonhosted.org/packages/d3/57/5cb75a56a4842bbd0511c3d1c79186d8315b82dac802118322b2de1194fe/pandas-2.3.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:2c7e2fc25f89a49a11599ec1e76821322439d90820108309bf42130d2f36c983", size = 11518913, upload-time = "2025-06-05T03:27:02.757Z" }, - { url = "https://files.pythonhosted.org/packages/05/01/0c8785610e465e4948a01a059562176e4c8088aa257e2e074db868f86d4e/pandas-2.3.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:c6da97aeb6a6d233fb6b17986234cc723b396b50a3c6804776351994f2a658fd", size = 10655249, upload-time = "2025-06-05T16:50:20.17Z" }, - { url = "https://files.pythonhosted.org/packages/e8/6a/47fd7517cd8abe72a58706aab2b99e9438360d36dcdb052cf917b7bf3bdc/pandas-2.3.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb32dc743b52467d488e7a7c8039b821da2826a9ba4f85b89ea95274f863280f", size = 11328359, upload-time = "2025-06-05T03:27:06.431Z" }, - { url = "https://files.pythonhosted.org/packages/2a/b3/463bfe819ed60fb7e7ddffb4ae2ee04b887b3444feee6c19437b8f834837/pandas-2.3.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:213cd63c43263dbb522c1f8a7c9d072e25900f6975596f883f4bebd77295d4f3", size = 12024789, upload-time = "2025-06-05T03:27:09.875Z" }, - { url = "https://files.pythonhosted.org/packages/04/0c/e0704ccdb0ac40aeb3434d1c641c43d05f75c92e67525df39575ace35468/pandas-2.3.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:1d2b33e68d0ce64e26a4acc2e72d747292084f4e8db4c847c6f5f6cbe56ed6d8", size = 12480734, upload-time = "2025-06-06T00:00:22.246Z" }, - { url = "https://files.pythonhosted.org/packages/e9/df/815d6583967001153bb27f5cf075653d69d51ad887ebbf4cfe1173a1ac58/pandas-2.3.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:430a63bae10b5086995db1b02694996336e5a8ac9a96b4200572b413dfdfccb9", size = 13223381, upload-time = "2025-06-05T03:27:15.641Z" }, - { url = "https://files.pythonhosted.org/packages/79/88/ca5973ed07b7f484c493e941dbff990861ca55291ff7ac67c815ce347395/pandas-2.3.0-cp313-cp313-win_amd64.whl", hash = "sha256:4930255e28ff5545e2ca404637bcc56f031893142773b3468dc021c6c32a1390", size = 10970135, upload-time = "2025-06-05T03:27:24.131Z" }, - { url = "https://files.pythonhosted.org/packages/24/fb/0994c14d1f7909ce83f0b1fb27958135513c4f3f2528bde216180aa73bfc/pandas-2.3.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:f925f1ef673b4bd0271b1809b72b3270384f2b7d9d14a189b12b7fc02574d575", size = 12141356, upload-time = "2025-06-05T03:27:34.547Z" }, - { url = "https://files.pythonhosted.org/packages/9d/a2/9b903e5962134497ac4f8a96f862ee3081cb2506f69f8e4778ce3d9c9d82/pandas-2.3.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:e78ad363ddb873a631e92a3c063ade1ecfb34cae71e9a2be6ad100f875ac1042", size = 11474674, upload-time = "2025-06-05T03:27:39.448Z" }, - { url = "https://files.pythonhosted.org/packages/81/3a/3806d041bce032f8de44380f866059437fb79e36d6b22c82c187e65f765b/pandas-2.3.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:951805d146922aed8357e4cc5671b8b0b9be1027f0619cea132a9f3f65f2f09c", size = 11439876, upload-time = "2025-06-05T03:27:43.652Z" }, - { url = "https://files.pythonhosted.org/packages/15/aa/3fc3181d12b95da71f5c2537c3e3b3af6ab3a8c392ab41ebb766e0929bc6/pandas-2.3.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1a881bc1309f3fce34696d07b00f13335c41f5f5a8770a33b09ebe23261cfc67", size = 11966182, upload-time = "2025-06-05T03:27:47.652Z" }, - { url = "https://files.pythonhosted.org/packages/37/e7/e12f2d9b0a2c4a2cc86e2aabff7ccfd24f03e597d770abfa2acd313ee46b/pandas-2.3.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:e1991bbb96f4050b09b5f811253c4f3cf05ee89a589379aa36cd623f21a31d6f", size = 12547686, upload-time = "2025-06-06T00:00:26.142Z" }, - { url = "https://files.pythonhosted.org/packages/39/c2/646d2e93e0af70f4e5359d870a63584dacbc324b54d73e6b3267920ff117/pandas-2.3.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:bb3be958022198531eb7ec2008cfc78c5b1eed51af8600c6c5d9160d89d8d249", size = 13231847, upload-time = "2025-06-05T03:27:51.465Z" }, +sdist = { url = "https://files.pythonhosted.org/packages/d1/6f/75aa71f8a14267117adeeed5d21b204770189c0a0025acbdc03c337b28fc/pandas-2.3.1.tar.gz", hash = "sha256:0a95b9ac964fe83ce317827f80304d37388ea77616b1425f0ae41c9d2d0d7bb2", size = 4487493, upload-time = "2025-07-07T19:20:04.079Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/76/1c/ccf70029e927e473a4476c00e0d5b32e623bff27f0402d0a92b7fc29bb9f/pandas-2.3.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2b0540963d83431f5ce8870ea02a7430adca100cec8a050f0811f8e31035541b", size = 11566608, upload-time = "2025-07-07T19:18:33.86Z" }, + { url = "https://files.pythonhosted.org/packages/ec/d3/3c37cb724d76a841f14b8f5fe57e5e3645207cc67370e4f84717e8bb7657/pandas-2.3.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fe7317f578c6a153912bd2292f02e40c1d8f253e93c599e82620c7f69755c74f", size = 10823181, upload-time = "2025-07-07T19:18:36.151Z" }, + { url = "https://files.pythonhosted.org/packages/8a/4c/367c98854a1251940edf54a4df0826dcacfb987f9068abf3e3064081a382/pandas-2.3.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e6723a27ad7b244c0c79d8e7007092d7c8f0f11305770e2f4cd778b3ad5f9f85", size = 11793570, upload-time = "2025-07-07T19:18:38.385Z" }, + { url = "https://files.pythonhosted.org/packages/07/5f/63760ff107bcf5146eee41b38b3985f9055e710a72fdd637b791dea3495c/pandas-2.3.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3462c3735fe19f2638f2c3a40bd94ec2dc5ba13abbb032dd2fa1f540a075509d", size = 12378887, upload-time = "2025-07-07T19:18:41.284Z" }, + { url = "https://files.pythonhosted.org/packages/15/53/f31a9b4dfe73fe4711c3a609bd8e60238022f48eacedc257cd13ae9327a7/pandas-2.3.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:98bcc8b5bf7afed22cc753a28bc4d9e26e078e777066bc53fac7904ddef9a678", size = 13230957, upload-time = "2025-07-07T19:18:44.187Z" }, + { url = "https://files.pythonhosted.org/packages/e0/94/6fce6bf85b5056d065e0a7933cba2616dcb48596f7ba3c6341ec4bcc529d/pandas-2.3.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:4d544806b485ddf29e52d75b1f559142514e60ef58a832f74fb38e48d757b299", size = 13883883, upload-time = "2025-07-07T19:18:46.498Z" }, + { url = "https://files.pythonhosted.org/packages/c8/7b/bdcb1ed8fccb63d04bdb7635161d0ec26596d92c9d7a6cce964e7876b6c1/pandas-2.3.1-cp311-cp311-win_amd64.whl", hash = "sha256:b3cd4273d3cb3707b6fffd217204c52ed92859533e31dc03b7c5008aa933aaab", size = 11340212, upload-time = "2025-07-07T19:18:49.293Z" }, + { url = "https://files.pythonhosted.org/packages/46/de/b8445e0f5d217a99fe0eeb2f4988070908979bec3587c0633e5428ab596c/pandas-2.3.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:689968e841136f9e542020698ee1c4fbe9caa2ed2213ae2388dc7b81721510d3", size = 11588172, upload-time = "2025-07-07T19:18:52.054Z" }, + { url = "https://files.pythonhosted.org/packages/1e/e0/801cdb3564e65a5ac041ab99ea6f1d802a6c325bb6e58c79c06a3f1cd010/pandas-2.3.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:025e92411c16cbe5bb2a4abc99732a6b132f439b8aab23a59fa593eb00704232", size = 10717365, upload-time = "2025-07-07T19:18:54.785Z" }, + { url = "https://files.pythonhosted.org/packages/51/a5/c76a8311833c24ae61a376dbf360eb1b1c9247a5d9c1e8b356563b31b80c/pandas-2.3.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9b7ff55f31c4fcb3e316e8f7fa194566b286d6ac430afec0d461163312c5841e", size = 11280411, upload-time = "2025-07-07T19:18:57.045Z" }, + { url = "https://files.pythonhosted.org/packages/da/01/e383018feba0a1ead6cf5fe8728e5d767fee02f06a3d800e82c489e5daaf/pandas-2.3.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7dcb79bf373a47d2a40cf7232928eb7540155abbc460925c2c96d2d30b006eb4", size = 11988013, upload-time = "2025-07-07T19:18:59.771Z" }, + { url = "https://files.pythonhosted.org/packages/5b/14/cec7760d7c9507f11c97d64f29022e12a6cc4fc03ac694535e89f88ad2ec/pandas-2.3.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:56a342b231e8862c96bdb6ab97170e203ce511f4d0429589c8ede1ee8ece48b8", size = 12767210, upload-time = "2025-07-07T19:19:02.944Z" }, + { url = "https://files.pythonhosted.org/packages/50/b9/6e2d2c6728ed29fb3d4d4d302504fb66f1a543e37eb2e43f352a86365cdf/pandas-2.3.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ca7ed14832bce68baef331f4d7f294411bed8efd032f8109d690df45e00c4679", size = 13440571, upload-time = "2025-07-07T19:19:06.82Z" }, + { url = "https://files.pythonhosted.org/packages/80/a5/3a92893e7399a691bad7664d977cb5e7c81cf666c81f89ea76ba2bff483d/pandas-2.3.1-cp312-cp312-win_amd64.whl", hash = "sha256:ac942bfd0aca577bef61f2bc8da8147c4ef6879965ef883d8e8d5d2dc3e744b8", size = 10987601, upload-time = "2025-07-07T19:19:09.589Z" }, + { url = "https://files.pythonhosted.org/packages/32/ed/ff0a67a2c5505e1854e6715586ac6693dd860fbf52ef9f81edee200266e7/pandas-2.3.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:9026bd4a80108fac2239294a15ef9003c4ee191a0f64b90f170b40cfb7cf2d22", size = 11531393, upload-time = "2025-07-07T19:19:12.245Z" }, + { url = "https://files.pythonhosted.org/packages/c7/db/d8f24a7cc9fb0972adab0cc80b6817e8bef888cfd0024eeb5a21c0bb5c4a/pandas-2.3.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:6de8547d4fdb12421e2d047a2c446c623ff4c11f47fddb6b9169eb98ffba485a", size = 10668750, upload-time = "2025-07-07T19:19:14.612Z" }, + { url = "https://files.pythonhosted.org/packages/0f/b0/80f6ec783313f1e2356b28b4fd8d2148c378370045da918c73145e6aab50/pandas-2.3.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:782647ddc63c83133b2506912cc6b108140a38a37292102aaa19c81c83db2928", size = 11342004, upload-time = "2025-07-07T19:19:16.857Z" }, + { url = "https://files.pythonhosted.org/packages/e9/e2/20a317688435470872885e7fc8f95109ae9683dec7c50be29b56911515a5/pandas-2.3.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2ba6aff74075311fc88504b1db890187a3cd0f887a5b10f5525f8e2ef55bfdb9", size = 12050869, upload-time = "2025-07-07T19:19:19.265Z" }, + { url = "https://files.pythonhosted.org/packages/55/79/20d746b0a96c67203a5bee5fb4e00ac49c3e8009a39e1f78de264ecc5729/pandas-2.3.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:e5635178b387bd2ba4ac040f82bc2ef6e6b500483975c4ebacd34bec945fda12", size = 12750218, upload-time = "2025-07-07T19:19:21.547Z" }, + { url = "https://files.pythonhosted.org/packages/7c/0f/145c8b41e48dbf03dd18fdd7f24f8ba95b8254a97a3379048378f33e7838/pandas-2.3.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6f3bf5ec947526106399a9e1d26d40ee2b259c66422efdf4de63c848492d91bb", size = 13416763, upload-time = "2025-07-07T19:19:23.939Z" }, + { url = "https://files.pythonhosted.org/packages/b2/c0/54415af59db5cdd86a3d3bf79863e8cc3fa9ed265f0745254061ac09d5f2/pandas-2.3.1-cp313-cp313-win_amd64.whl", hash = "sha256:1c78cf43c8fde236342a1cb2c34bcff89564a7bfed7e474ed2fffa6aed03a956", size = 10987482, upload-time = "2025-07-07T19:19:42.699Z" }, + { url = "https://files.pythonhosted.org/packages/48/64/2fd2e400073a1230e13b8cd604c9bc95d9e3b962e5d44088ead2e8f0cfec/pandas-2.3.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:8dfc17328e8da77be3cf9f47509e5637ba8f137148ed0e9b5241e1baf526e20a", size = 12029159, upload-time = "2025-07-07T19:19:26.362Z" }, + { url = "https://files.pythonhosted.org/packages/d8/0a/d84fd79b0293b7ef88c760d7dca69828d867c89b6d9bc52d6a27e4d87316/pandas-2.3.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:ec6c851509364c59a5344458ab935e6451b31b818be467eb24b0fe89bd05b6b9", size = 11393287, upload-time = "2025-07-07T19:19:29.157Z" }, + { url = "https://files.pythonhosted.org/packages/50/ae/ff885d2b6e88f3c7520bb74ba319268b42f05d7e583b5dded9837da2723f/pandas-2.3.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:911580460fc4884d9b05254b38a6bfadddfcc6aaef856fb5859e7ca202e45275", size = 11309381, upload-time = "2025-07-07T19:19:31.436Z" }, + { url = "https://files.pythonhosted.org/packages/85/86/1fa345fc17caf5d7780d2699985c03dbe186c68fee00b526813939062bb0/pandas-2.3.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2f4d6feeba91744872a600e6edbbd5b033005b431d5ae8379abee5bcfa479fab", size = 11883998, upload-time = "2025-07-07T19:19:34.267Z" }, + { url = "https://files.pythonhosted.org/packages/81/aa/e58541a49b5e6310d89474333e994ee57fea97c8aaa8fc7f00b873059bbf/pandas-2.3.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:fe37e757f462d31a9cd7580236a82f353f5713a80e059a29753cf938c6775d96", size = 12704705, upload-time = "2025-07-07T19:19:36.856Z" }, + { url = "https://files.pythonhosted.org/packages/d5/f9/07086f5b0f2a19872554abeea7658200824f5835c58a106fa8f2ae96a46c/pandas-2.3.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:5db9637dbc24b631ff3707269ae4559bce4b7fd75c1c4d7e13f40edc42df4444", size = 13189044, upload-time = "2025-07-07T19:19:39.999Z" }, ] [[package]] @@ -1929,16 +1929,16 @@ wheels = [ [[package]] name = "pytest-regressions" -version = "2.8.0" +version = "2.8.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pytest" }, { name = "pytest-datadir" }, { name = "pyyaml" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/c5/ef/48083b093c1291fac24d0556b8ddb88310977c5b7d6c7abe73cc87647901/pytest_regressions-2.8.0.tar.gz", hash = "sha256:775044e17117f5427df2caad3ab1c66889abe770a0ce2bc3f24fdeac99af76fe", size = 116454, upload-time = "2025-05-30T17:46:21.498Z" } +sdist = { url = "https://files.pythonhosted.org/packages/c9/20/f861ea5b5db791ba1f778032b294b0a454eff2f6c2b3f8a88d36d61c0a63/pytest_regressions-2.8.1.tar.gz", hash = "sha256:20080d44cf46b40407956af5e44a7f932cbc3159018de81fb51e62b97e96a5fb", size = 116486, upload-time = "2025-07-04T12:54:36.473Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/7f/6a/cf0a9929a94912e7123dd3ab23658fce5c3bdef12cb270da84348282feda/pytest_regressions-2.8.0-py3-none-any.whl", hash = "sha256:2926f37efa5fd6793806b10352e274c5284a5469a845aeab6243e86f9214766f", size = 24859, upload-time = "2025-05-30T17:46:19.722Z" }, + { url = "https://files.pythonhosted.org/packages/46/6e/416d44b81b42482c2b7b553606c79d7f3e32e686d42f3f24b04a7f8cf56f/pytest_regressions-2.8.1-py3-none-any.whl", hash = "sha256:bcae249df5214225bbe4bd77c146d8f331f19b0b26805486533b1e49680950a5", size = 24861, upload-time = "2025-07-04T12:54:35.051Z" }, ] [[package]] @@ -2769,20 +2769,20 @@ wheels = [ [[package]] name = "types-python-dateutil" -version = "2.9.0.20250516" +version = "2.9.0.20250708" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/ef/88/d65ed807393285204ab6e2801e5d11fbbea811adcaa979a2ed3b67a5ef41/types_python_dateutil-2.9.0.20250516.tar.gz", hash = "sha256:13e80d6c9c47df23ad773d54b2826bd52dbbb41be87c3f339381c1700ad21ee5", size = 13943, upload-time = "2025-05-16T03:06:58.385Z" } +sdist = { url = "https://files.pythonhosted.org/packages/c9/95/6bdde7607da2e1e99ec1c1672a759d42f26644bbacf939916e086db34870/types_python_dateutil-2.9.0.20250708.tar.gz", hash = "sha256:ccdbd75dab2d6c9696c350579f34cffe2c281e4c5f27a585b2a2438dd1d5c8ab", size = 15834, upload-time = "2025-07-08T03:14:03.382Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/c5/3f/b0e8db149896005adc938a1e7f371d6d7e9eca4053a29b108978ed15e0c2/types_python_dateutil-2.9.0.20250516-py3-none-any.whl", hash = "sha256:2b2b3f57f9c6a61fba26a9c0ffb9ea5681c9b83e69cd897c6b5f668d9c0cab93", size = 14356, upload-time = "2025-05-16T03:06:57.249Z" }, + { url = "https://files.pythonhosted.org/packages/72/52/43e70a8e57fefb172c22a21000b03ebcc15e47e97f5cb8495b9c2832efb4/types_python_dateutil-2.9.0.20250708-py3-none-any.whl", hash = "sha256:4d6d0cc1cc4d24a2dc3816024e502564094497b713f7befda4d5bc7a8e3fd21f", size = 17724, upload-time = "2025-07-08T03:14:02.593Z" }, ] [[package]] name = "typing-extensions" -version = "4.14.0" +version = "4.14.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/d1/bc/51647cd02527e87d05cb083ccc402f93e441606ff1f01739a62c8ad09ba5/typing_extensions-4.14.0.tar.gz", hash = "sha256:8676b788e32f02ab42d9e7c61324048ae4c6d844a399eebace3d4979d75ceef4", size = 107423, upload-time = "2025-06-02T14:52:11.399Z" } +sdist = { url = "https://files.pythonhosted.org/packages/98/5a/da40306b885cc8c09109dc2e1abd358d5684b1425678151cdaed4731c822/typing_extensions-4.14.1.tar.gz", hash = "sha256:38b39f4aeeab64884ce9f74c94263ef78f3c22467c8724005483154c26648d36", size = 107673, upload-time = "2025-07-04T13:28:34.16Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/69/e0/552843e0d356fbb5256d21449fa957fa4eff3bbc135a74a691ee70c7c5da/typing_extensions-4.14.0-py3-none-any.whl", hash = "sha256:a1514509136dd0b477638fc68d6a91497af5076466ad0fa6c338e44e359944af", size = 43839, upload-time = "2025-06-02T14:52:10.026Z" }, + { url = "https://files.pythonhosted.org/packages/b5/00/d631e67a838026495268c2f6884f3711a15a9a2a96cd244fdaea53b823fb/typing_extensions-4.14.1-py3-none-any.whl", hash = "sha256:d1e1e3b58374dc93031d6eda2420a48ea44a36c2b4766a4fdeb3710755731d76", size = 43906, upload-time = "2025-07-04T13:28:32.743Z" }, ] [[package]] From 6c2766e799892e993f7bd78b4c1ddfb50dd186f4 Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 10 Jul 2025 10:58:09 -0700 Subject: [PATCH 365/521] expose find_plasma_potential to the swept_langmuir namespace --- src/plasmapy/analysis/swept_langmuir/__init__.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/plasmapy/analysis/swept_langmuir/__init__.py b/src/plasmapy/analysis/swept_langmuir/__init__.py index 3da6d9bacb..8677651059 100644 --- a/src/plasmapy/analysis/swept_langmuir/__init__.py +++ b/src/plasmapy/analysis/swept_langmuir/__init__.py @@ -7,12 +7,13 @@ "check_sweep", "find_floating_potential", "find_ion_saturation_current", + "find_plasma_potential_via_didv_peak", "merge_voltage_clusters", "sort_sweep_arrays", "ISatExtras", "VFExtras", ] -__aliases__ = ["find_isat_", "find_vf_"] +__aliases__ = ["find_isat_", "find_vf_", "find_vp_"] __all__ += __aliases__ from plasmapy.analysis.swept_langmuir.floating_potential import ( @@ -30,3 +31,7 @@ find_ion_saturation_current, find_isat_, ) +from plasmapy.analysis.swept_langmuir.plasma_potential import ( + find_plasma_potential_via_didv_peak, + find_vp_, +) From b314f62b65bc7fc5f50813c84fa1a9c28dec6d12 Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 10 Jul 2025 10:58:38 -0700 Subject: [PATCH 366/521] add alias find_vp_ --- src/plasmapy/analysis/swept_langmuir/plasma_potential.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py index 21dccab9fa..a1632940d7 100644 --- a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py +++ b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py @@ -3,6 +3,9 @@ """ __all__ = ["find_plasma_potential_via_didv_peak"] +__aliases__ = ["find_vp_"] + +__all__ += __aliases__ import numpy as np From 3a935a21ce3d7b6c16433e41d60aac790bc455e5 Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 10 Jul 2025 10:59:00 -0700 Subject: [PATCH 367/521] create namedtuple VpExtras --- .../analysis/swept_langmuir/plasma_potential.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py index a1632940d7..2c9a683c43 100644 --- a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py +++ b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py @@ -5,6 +5,8 @@ __all__ = ["find_plasma_potential_via_didv_peak"] __aliases__ = ["find_vp_"] +from typing import NamedTuple + __all__ += __aliases__ import numpy as np @@ -14,6 +16,14 @@ from plasmapy.analysis.swept_langmuir.helpers import check_sweep, merge_voltage_clusters +class VpExtras(NamedTuple): + vp_std: float | None + data_slice: slice | None + savgol_windows: list[int] | None + computed_plasma_potentials: list[float] | None + method: str | None + + def find_plasma_potential_via_didv_peak( voltage: np.ndarray, current: np.ndarray, From a3eff3974c8ab502b9266c9af0615811d735663f Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 10 Jul 2025 10:59:50 -0700 Subject: [PATCH 368/521] incorporate VpExtras into find_plasma_potential --- .../analysis/swept_langmuir/plasma_potential.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py index 2c9a683c43..8374bffea3 100644 --- a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py +++ b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py @@ -31,6 +31,14 @@ def find_plasma_potential_via_didv_peak( floating_potential: float | None = None, smooth_fractions=None, ): + rtn_extras = VpExtras( + vp_std=None, + data_slice=None, + savgol_windows=None, + computed_plasma_potentials=None, + method="didv_peak", + )._asdict() + # check voltage and current arrays voltage, current = check_sweep(voltage, current, strip_units=True) voltage, current = merge_voltage_clusters(voltage, current, voltage_step_size=0) @@ -56,6 +64,7 @@ def find_plasma_potential_via_didv_peak( if np.count_nonzero(mask) > 0: first_index = np.where(mask)[0][0] data_size = voltage.size - first_index + rtn_extras["data_slice"] = slice(int(first_index), None, 1) # define smooth_fractions # TODO: add better description @@ -74,6 +83,7 @@ def find_plasma_potential_via_didv_peak( voltage_slice = voltage[first_index:] current_slice = current[first_index:] plasma_potentials = [] + rtn_extras["savgol_windows"] = [] for _window in smooth_windows: v_smooth = signal.savgol_filter(voltage_slice, _window, 1) c_smooth = signal.savgol_filter(current_slice, _window, 1) @@ -86,8 +96,13 @@ def find_plasma_potential_via_didv_peak( vp = voltage_slice[imax[0]] plasma_potentials.append(vp) + rtn_extras["savgol_windows"].append(int(_window)) + rtn_extras["computed_plasma_potentials"] = plasma_potentials + rtn_extras["vp_std"] = float(np.std(plasma_potentials)) + vp = float(np.average(plasma_potentials)) + return vp, VpExtras(**rtn_extras) find_vp_ = find_plasma_potential_via_didv_peak From 7b94e1d652af19cf2eddd3dcd514ef90064d4c4d Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 10 Jul 2025 11:09:00 -0700 Subject: [PATCH 369/521] calc vp when imax is not singular --- src/plasmapy/analysis/swept_langmuir/plasma_potential.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py index 8374bffea3..6d7c997cb6 100644 --- a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py +++ b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py @@ -91,7 +91,12 @@ def find_plasma_potential_via_didv_peak( didv = np.gradient(c_smooth, v_smooth) imax = np.argmax(didv) if imax.size > 1: - ... + if np.all(np.diff(imax) == 1): + vp = np.average(voltage_slice[imax]) + else: + continue + elif np.isscalar(imax): + vp = voltage_slice[imax] else: vp = voltage_slice[imax[0]] From 2e9d3216139b064004457b88f0fa478986af01e3 Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 10 Jul 2025 11:09:47 -0700 Subject: [PATCH 370/521] up smooth_fractions count --- src/plasmapy/analysis/swept_langmuir/plasma_potential.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py index 6d7c997cb6..b195f99210 100644 --- a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py +++ b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py @@ -69,7 +69,7 @@ def find_plasma_potential_via_didv_peak( # define smooth_fractions # TODO: add better description if smooth_fractions is None: - smooth_fractions = np.linspace(0.01, 0.25, num=25) + smooth_fractions = np.linspace(0.01, 0.25, num=30) # create bin sizes (smooth_windows) for the savgol_filter smooth_windows = np.unique(np.rint(smooth_fractions * data_size, dtype=int)) From 1a399ae0189f96b3e208858955a19d69b9a737cf Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 10 Jul 2025 11:10:06 -0700 Subject: [PATCH 371/521] force int and float types --- src/plasmapy/analysis/swept_langmuir/plasma_potential.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py index b195f99210..0564710d4f 100644 --- a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py +++ b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py @@ -72,7 +72,7 @@ def find_plasma_potential_via_didv_peak( smooth_fractions = np.linspace(0.01, 0.25, num=30) # create bin sizes (smooth_windows) for the savgol_filter - smooth_windows = np.unique(np.rint(smooth_fractions * data_size, dtype=int)) + smooth_windows = np.unique(np.rint(smooth_fractions * data_size).astype(int)) mask = smooth_windows > 2 smooth_windows = smooth_windows[mask] mask = smooth_windows % 2 == 0 @@ -100,7 +100,7 @@ def find_plasma_potential_via_didv_peak( else: vp = voltage_slice[imax[0]] - plasma_potentials.append(vp) + plasma_potentials.append(float(vp)) rtn_extras["savgol_windows"].append(int(_window)) rtn_extras["computed_plasma_potentials"] = plasma_potentials From 9d1388285e82c76c89cafe0871e9927799ac1762 Mon Sep 17 00:00:00 2001 From: Erik Everson Date: Thu, 10 Jul 2025 11:44:29 -0700 Subject: [PATCH 372/521] [SLA] Add helper function `sort_sweep_arrays` (#3034) * add argument allow_unsorted to check_sweep * rough out helper function sort_sweep_arrays * add a lint E402 ignore for swept_langmuir/__init__.py * move full construction of the __all__ dunder to the top of the file * fix error string * add messages to raised errors * appease grumpy ruff * add docstring * add test case for allow_unsort == True * use np.diff to decide if we can manually reorder arrays or need to use argsort * add value test cases for sort_sweep_arrays * remove unused code * use the newer numpy.random.Generator * add change log * reformat with statement * fix references * Apply suggestions from code review Co-authored-by: Nick Murphy * fix docstring line lengths --------- Co-authored-by: Erik Everson Co-authored-by: Nick Murphy --- changelog/3034.feature.rst | 4 + pyproject.toml | 1 + .../analysis/swept_langmuir/__init__.py | 9 +- .../analysis/swept_langmuir/helpers.py | 144 ++++++++++++++---- .../test_swept_langmuir_helpers.py | 99 +++++++++++- 5 files changed, 226 insertions(+), 31 deletions(-) create mode 100644 changelog/3034.feature.rst diff --git a/changelog/3034.feature.rst b/changelog/3034.feature.rst new file mode 100644 index 0000000000..38f150ade6 --- /dev/null +++ b/changelog/3034.feature.rst @@ -0,0 +1,4 @@ +.. currentmodule:: plasmapy.analysis.swept_langmuir + +Added helper function `~helpers.sort_sweep_arrays` to the +`~plasmapy.analysis.swept_langmuir` module. diff --git a/pyproject.toml b/pyproject.toml index dedf522b32..b2d9a9a368 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -325,6 +325,7 @@ lint.per-file-ignores."docs/notebooks/plasma/grids_nonuniform.ipynb" = [ "NPY002 lint.per-file-ignores."setup.py" = [ "D100" ] lint.per-file-ignores."src/plasmapy/analysis/fit_functions.py" = [ "D301" ] +lint.per-file-ignores."src/plasmapy/analysis/swept_langmuir/__init__.py" = [ "E402" ] lint.per-file-ignores."src/plasmapy/formulary/braginskii.py" = [ "C901", "RET503", "RET504" ] lint.per-file-ignores."src/plasmapy/plasma/sources/*.py" = [ "D102" ] lint.per-file-ignores."src/plasmapy/utils/_pytest_helpers/pytest_helpers.py" = [ "BLE001", "PLR", "SLF001" ] diff --git a/src/plasmapy/analysis/swept_langmuir/__init__.py b/src/plasmapy/analysis/swept_langmuir/__init__.py index 2c65d8359e..387fd40008 100644 --- a/src/plasmapy/analysis/swept_langmuir/__init__.py +++ b/src/plasmapy/analysis/swept_langmuir/__init__.py @@ -7,21 +7,24 @@ "check_sweep", "find_floating_potential", "find_ion_saturation_current", + "sort_sweep_arrays", "ISatExtras", "VFExtras", ] __aliases__ = ["find_isat_", "find_vf_"] +__all__ += __aliases__ from plasmapy.analysis.swept_langmuir.floating_potential import ( VFExtras, find_floating_potential, find_vf_, ) -from plasmapy.analysis.swept_langmuir.helpers import check_sweep +from plasmapy.analysis.swept_langmuir.helpers import ( + check_sweep, + sort_sweep_arrays, +) from plasmapy.analysis.swept_langmuir.ion_saturation_current import ( ISatExtras, find_ion_saturation_current, find_isat_, ) - -__all__ += __aliases__ diff --git a/src/plasmapy/analysis/swept_langmuir/helpers.py b/src/plasmapy/analysis/swept_langmuir/helpers.py index 54f5edf46d..ed739bd613 100644 --- a/src/plasmapy/analysis/swept_langmuir/helpers.py +++ b/src/plasmapy/analysis/swept_langmuir/helpers.py @@ -1,6 +1,8 @@ """Helper functions for analyzing swept Langmuir traces.""" -__all__ = ["check_sweep"] +__all__ = ["check_sweep", "sort_sweep_arrays"] + +from typing import Literal import astropy.units as u import numpy as np @@ -10,44 +12,52 @@ def check_sweep( # noqa: C901, PLR0912 voltage: np.ndarray, current: np.ndarray, strip_units: bool = True, + allow_unsorted: bool = False, ) -> tuple[np.ndarray, np.ndarray]: """ - Function for checking that the voltage and current arrays are properly - formatted for analysis by `plasmapy.analysis.swept_langmuir`. + Check that the voltage and current arrays are + properly formatted for analysis by + `plasmapy.analysis.swept_langmuir`. Parameters ---------- voltage: `numpy.ndarray` - 1D `numpy.ndarray` representing the voltage of the swept Langmuir trace. - Voltage should be monotonically increasing. *No units are assumed or - checked, but values should be in volts.* + 1D `numpy.ndarray` representing the voltage of the swept + Langmuir trace. Voltage should be monotonically increasing. + *No units are assumed or checked, but values should be in + volts.* current: `numpy.ndarray` - 1D `numpy.ndarray` representing the current of the swept Langmuir trace. - Values should start from a negative ion-saturation current and increase - to a positive electron-saturation current. *No units are assumed or - checked, but values should be in amperes.* - - strip_units: `bool` - (Default: `True`) If `True`, then the units on ``voltage`` and/or - ``current`` will be stripped if either are passed in as an Astropy + 1D `numpy.ndarray` representing the current of the swept + Langmuir trace. Values should start from a negative + ion-saturation current and increase to a positive + electron-saturation current. *No units are assumed or checked, + but values should be in amperes.* + + strip_units: `bool`, default: `True` + If `True`, then the units on ``voltage`` and/or ``current`` + will be stripped if either are passed in as an Astropy `~astropy.units.Quantity`. + allow_unsorted: `bool`, default: `False` + If `True`, then the supplied ``voltage`` + array must be monotonically increasing. + Returns ------- voltage : `numpy.ndarray` - Input argument ``voltage`` after it goes through all of its checks - and conditioning. + Input argument ``voltage`` after it goes through all of its + checks and conditioning. current : `numpy.ndarray` - Input argument ``current`` after it goes through all of its checks - and conditioning. + Input argument ``current`` after it goes through all of its + checks and conditioning. Raises ------ `TypeError` - If either the ``voltage`` or ``current`` arrays are not instances of a - `numpy.ndarray`. + If either the ``voltage`` or ``current`` arrays are not + instances of a `numpy.ndarray`. `ValueError`: If either the ``voltage`` or ``current`` arrays are not 1D. @@ -56,12 +66,13 @@ def check_sweep( # noqa: C901, PLR0912 If the ``voltage`` array is not monotonically increasing. `ValueError` - If the ``current`` array never crosses zero (i.e. has no floating - potential). + If the ``current`` array never crosses zero (i.e. has no + floating potential). `ValueError` - If the ``current`` array does not start form a negative ion-saturation - current and increases to a positive electron-saturation current. + If the ``current`` array does not start form a negative + ion-saturation current and increases to a positive + electron-saturation current. `ValueError` If either the ``voltage`` or ``current`` array does not have a @@ -93,7 +104,7 @@ def check_sweep( # noqa: C901, PLR0912 f"Expected 1D numpy array for voltage, but got array with " f"{voltage.ndim} dimensions.", ) - elif not np.all(np.diff(voltage) >= 0): + elif not np.all(np.diff(voltage) >= 0) and not allow_unsorted: raise ValueError("The voltage array is not monotonically increasing.") if isinstance(voltage, u.Quantity) and strip_units: @@ -131,8 +142,8 @@ def check_sweep( # noqa: C901, PLR0912 ) elif current[0] > 0.0 or current[-1] < 0.0: raise ValueError( - "The current array needs to start from a negative ion-saturation current" - " to a positive electron-saturation current." + "The current array needs to start from a negative ion-saturation " + "current to a positive electron-saturation current." ) if voltage.size != current.size: @@ -145,3 +156,82 @@ def check_sweep( # noqa: C901, PLR0912 current = current.value return voltage, current + + +def sort_sweep_arrays( + voltage: np.ndarray, + current: np.ndarray, + voltage_order: Literal["ascending", "descending"] = "ascending", +) -> tuple[np.ndarray, np.ndarray]: + """ + Sort the swept langmuir ``voltage`` and ``current`` traces to + ensure the ``voltage`` array is either monotonically increasing or + decreasing. + + Parameters + ---------- + voltage: `numpy.ndarray` + 1D `numpy.ndarray` representing the voltage of the swept + Langmuir trace. *No units are assumed or checked, but values + should be in volts.* + + current: `numpy.ndarray` + 1D `numpy.ndarray` representing the current of the swept + Langmuir trace. Values should start from a negative + ion-saturation current and increase to a positive + electron-saturation current. *No units are assumed or checked, + but values should be in amperes.* + + voltage_order: `str` + Either ``'ascending'`` or ``'descending'`` to indicate how the + ``voltage`` array should be sorted. (DEFAULT: ``'ascending'``) + + Returns + ------- + voltage : `numpy.ndarray` + Sorted ``voltage`` array. + + current : `numpy.ndarray` + Matched ``current`` array to the sorted ``voltage`` array. + """ + if not isinstance(voltage_order, str): + raise TypeError( + "Expected 'voltage_order' to be a string equal to 'ascending' " + f"or 'descending', but got type {type(voltage_order)}." + ) + elif voltage_order not in ["ascending", "descending"]: + raise ValueError( + "Expected 'voltage_order' to be a string equal to 'ascending' " + f"or 'descending', but got '{voltage_order}'." + ) + + voltage, current = check_sweep( + voltage, current, strip_units=True, allow_unsorted=True + ) + + # determine order + voltage_diff = np.diff(voltage) + if np.all(voltage_diff >= 0): + _order = "ascending" + elif np.all(voltage_diff <= 0): + _order = "descending" + else: + _order = None + + if _order == voltage_order: + # already ordered + return voltage, current + + # perform sorting + if _order is None: + index_sort = np.argsort(voltage) + if voltage_order == "descending": + index_sort = index_sort[::-1] + + voltage = voltage[index_sort] + current = current[index_sort] + else: + voltage = voltage[::-1] + current = current[::-1] + + return voltage, current diff --git a/tests/analysis/swept_langmuir/test_swept_langmuir_helpers.py b/tests/analysis/swept_langmuir/test_swept_langmuir_helpers.py index fb34917fff..daab228c7b 100644 --- a/tests/analysis/swept_langmuir/test_swept_langmuir_helpers.py +++ b/tests/analysis/swept_langmuir/test_swept_langmuir_helpers.py @@ -1,12 +1,13 @@ """Tests for `plasmapy.analysis.swept_langmuir.helpers`.""" from contextlib import nullcontext as does_not_raise +from unittest import mock import astropy.units as u import numpy as np import pytest -from plasmapy.analysis.swept_langmuir.helpers import check_sweep +from plasmapy.analysis.swept_langmuir.helpers import check_sweep, sort_sweep_arrays @pytest.mark.parametrize( @@ -163,6 +164,14 @@ does_not_raise(), (np.linspace(-40.0, 40, 100), np.linspace(-10.0, 30, 100)), ), + # -- allow_unsorted == True -- + ( + 30.0 * np.random.default_rng().random(100) - 20.0, + np.linspace(-10.0, 30, 100), + {"allow_unsorted": True}, + does_not_raise(), + "expected same as inputs", + ), ], ) def test_check_sweep(voltage, current, kwargs, with_context, expected) -> None: @@ -180,3 +189,91 @@ def test_check_sweep(voltage, current, kwargs, with_context, expected) -> None: else: assert np.allclose(rtn_voltage, expected[0]) assert np.allclose(rtn_current, expected[1]) + + +@pytest.mark.parametrize( + ("voltage", "current", "kwargs", "with_context", "expected"), + [ + # raises + ( + np.linspace(-40.0, 40, 100), + np.linspace(-10.0, 30, 100), + {"voltage_order": 5.0}, # not a string + pytest.raises(TypeError), + None, + ), + ( + np.linspace(-40.0, 40, 100), + np.linspace(-10.0, 30, 100), + {"voltage_order": "wrong string"}, + pytest.raises(ValueError), + None, + ), + # values + ( + np.linspace(-40.0, 40, 100), + np.linspace(-10.0, 30, 100), + {"voltage_order": "ascending"}, + does_not_raise(), + None, + ), + ( + np.linspace(-40.0, 40, 100), + np.linspace(-10.0, 30, 100), + {"voltage_order": "descending"}, + does_not_raise(), + (np.linspace(40.0, -40, 100), np.linspace(30.0, -10, 100)), + ), + ( + np.linspace(40.0, -40, 100), + np.linspace(-10.0, 30, 100), + {"voltage_order": "descending"}, + does_not_raise(), + None, + ), + ( + np.linspace(40.0, -40, 100), + np.linspace(-10.0, 30, 100), + {"voltage_order": "ascending"}, + does_not_raise(), + (np.linspace(-40.0, 40, 100), np.linspace(30.0, -10, 100)), + ), + ( + np.array([-40.0, 20.0, -22.0, 40.0]), + np.array([-10.0, 10.0, -5.0, 30.0]), + {"voltage_order": "ascending"}, + does_not_raise(), + (np.array([-40.0, -22.0, 20.0, 40.0]), np.array([-10.0, -5.0, 10.0, 30.0])), + ), + ( + np.array([-40.0, 20.0, -22.0, 40.0]), + np.array([-10.0, 10.0, -5.0, 30.0]), + {"voltage_order": "descending"}, + does_not_raise(), + (np.array([40.0, 20.0, -22.0, -40.0]), np.array([30.0, 10.0, -5.0, -10.0])), + ), + ], +) +def test_sort_sweep_arrays(voltage, current, kwargs, with_context, expected) -> None: + with ( + with_context, + mock.patch( + "plasmapy.analysis.swept_langmuir.helpers.check_sweep", + wraps=check_sweep, + ) as mock_check_sweep, + ): + rtn_voltage, rtn_current = sort_sweep_arrays( + voltage=voltage, + current=current, + **kwargs, + ) + + if expected is not None: + assert np.allclose(rtn_voltage, expected[0]) + assert np.allclose(rtn_current, expected[1]) + else: + assert np.allclose(rtn_voltage, voltage) + assert np.allclose(rtn_current, current) + + mock_check_sweep.assert_called_once() + mock_check_sweep.reset_mock() From 34d64c77c9b43944165dbc559915e24e3b099a82 Mon Sep 17 00:00:00 2001 From: "plasmapy-requirements-bot[bot]" <134649236+plasmapy-requirements-bot[bot]@users.noreply.github.com> Date: Tue, 15 Jul 2025 19:34:16 -0400 Subject: [PATCH 373/521] Update requirements with 'nox -s requirements' (#3052) Co-authored-by: namurphy <8931994+namurphy@users.noreply.github.com> --- uv.lock | 119 +++++++++++++++++++++++++++++--------------------------- 1 file changed, 61 insertions(+), 58 deletions(-) diff --git a/uv.lock b/uv.lock index 0b2c2f4a4e..4463d5c009 100644 --- a/uv.lock +++ b/uv.lock @@ -140,11 +140,11 @@ wheels = [ [[package]] name = "astropy-iers-data" -version = "0.2025.7.7.0.39.39" +version = "0.2025.7.14.0.40.29" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e8/88/ab5663cd28e9b9958a9e0c1ff0f755603b3ed1c8230818f9f1cbb19cf354/astropy_iers_data-0.2025.7.7.0.39.39.tar.gz", hash = "sha256:e29bf3e16816a92282a39edd587150296047b7b08ac6b8048b429a7d1ef1c386", size = 1901264, upload-time = "2025-07-07T00:40:21.053Z" } +sdist = { url = "https://files.pythonhosted.org/packages/83/08/7e0be27f3748240e88ec86c7a01717163d5c92ef0bbbdf2f781903745bd8/astropy_iers_data-0.2025.7.14.0.40.29.tar.gz", hash = "sha256:2d2446eda1bb26a92b9235b67cee584f86e02afec27ad7a0edfc296e891dd820", size = 1902390, upload-time = "2025-07-14T00:41:11.052Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/09/7f/ba056c9d42d8c495c36f33ec72a893de9df860ecfcba3e7640db874a7411/astropy_iers_data-0.2025.7.7.0.39.39-py3-none-any.whl", hash = "sha256:770221844e56c4cafba8c65659438bde5c96041d246dc4eb13cbc63890e33299", size = 1956686, upload-time = "2025-07-07T00:40:19.368Z" }, + { url = "https://files.pythonhosted.org/packages/7b/82/6d548466803b15511841e473e9fed7a29cfbba98ffe653fd454fd46a878d/astropy_iers_data-0.2025.7.14.0.40.29-py3-none-any.whl", hash = "sha256:f5080ce17297328946deb11974a4eb0afdcba098764e622164f1acb9a796700a", size = 1957818, upload-time = "2025-07-14T00:41:09.431Z" }, ] [[package]] @@ -206,11 +206,11 @@ css = [ [[package]] name = "certifi" -version = "2025.7.9" +version = "2025.7.14" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/de/8a/c729b6b60c66a38f590c4e774decc4b2ec7b0576be8f1aa984a53ffa812a/certifi-2025.7.9.tar.gz", hash = "sha256:c1d2ec05395148ee10cf672ffc28cd37ea0ab0d99f9cc74c43e588cbd111b079", size = 160386, upload-time = "2025-07-09T02:13:58.874Z" } +sdist = { url = "https://files.pythonhosted.org/packages/b3/76/52c535bcebe74590f296d6c77c86dabf761c41980e1347a2422e4aa2ae41/certifi-2025.7.14.tar.gz", hash = "sha256:8ea99dbdfaaf2ba2f9bac77b9249ef62ec5218e7c2b2e903378ed5fccf765995", size = 163981, upload-time = "2025-07-14T03:29:28.449Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/66/f3/80a3f974c8b535d394ff960a11ac20368e06b736da395b551a49ce950cce/certifi-2025.7.9-py3-none-any.whl", hash = "sha256:d842783a14f8fdd646895ac26f719a061408834473cfc10203f6a575beb15d39", size = 159230, upload-time = "2025-07-09T02:13:57.007Z" }, + { url = "https://files.pythonhosted.org/packages/4f/52/34c6cf5bb9285074dc3531c437b3919e825d976fde097a7a73f79e726d03/certifi-2025.7.14-py3-none-any.whl", hash = "sha256:6b31f564a415d79ee77df69d757bb49a5bb53bd9f756cbbe24394ffd6fc1f4b2", size = 162722, upload-time = "2025-07-14T03:29:26.863Z" }, ] [[package]] @@ -475,23 +475,23 @@ wheels = [ [[package]] name = "debugpy" -version = "1.8.14" +version = "1.8.15" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/bd/75/087fe07d40f490a78782ff3b0a30e3968936854105487decdb33446d4b0e/debugpy-1.8.14.tar.gz", hash = "sha256:7cd287184318416850aa8b60ac90105837bb1e59531898c07569d197d2ed5322", size = 1641444, upload-time = "2025-04-10T19:46:10.981Z" } +sdist = { url = "https://files.pythonhosted.org/packages/8c/8b/3a9a28ddb750a76eaec445c7f4d3147ea2c579a97dbd9e25d39001b92b21/debugpy-1.8.15.tar.gz", hash = "sha256:58d7a20b7773ab5ee6bdfb2e6cf622fdf1e40c9d5aef2857d85391526719ac00", size = 1643279, upload-time = "2025-07-15T16:43:29.135Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/67/e8/57fe0c86915671fd6a3d2d8746e40485fd55e8d9e682388fbb3a3d42b86f/debugpy-1.8.14-cp311-cp311-macosx_14_0_universal2.whl", hash = "sha256:1b2ac8c13b2645e0b1eaf30e816404990fbdb168e193322be8f545e8c01644a9", size = 2175064, upload-time = "2025-04-10T19:46:19.486Z" }, - { url = "https://files.pythonhosted.org/packages/3b/97/2b2fd1b1c9569c6764ccdb650a6f752e4ac31be465049563c9eb127a8487/debugpy-1.8.14-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cf431c343a99384ac7eab2f763980724834f933a271e90496944195318c619e2", size = 3132359, upload-time = "2025-04-10T19:46:21.192Z" }, - { url = "https://files.pythonhosted.org/packages/c0/ee/b825c87ed06256ee2a7ed8bab8fb3bb5851293bf9465409fdffc6261c426/debugpy-1.8.14-cp311-cp311-win32.whl", hash = "sha256:c99295c76161ad8d507b413cd33422d7c542889fbb73035889420ac1fad354f2", size = 5133269, upload-time = "2025-04-10T19:46:23.047Z" }, - { url = "https://files.pythonhosted.org/packages/d5/a6/6c70cd15afa43d37839d60f324213843174c1d1e6bb616bd89f7c1341bac/debugpy-1.8.14-cp311-cp311-win_amd64.whl", hash = "sha256:7816acea4a46d7e4e50ad8d09d963a680ecc814ae31cdef3622eb05ccacf7b01", size = 5158156, upload-time = "2025-04-10T19:46:24.521Z" }, - { url = "https://files.pythonhosted.org/packages/d9/2a/ac2df0eda4898f29c46eb6713a5148e6f8b2b389c8ec9e425a4a1d67bf07/debugpy-1.8.14-cp312-cp312-macosx_14_0_universal2.whl", hash = "sha256:8899c17920d089cfa23e6005ad9f22582fd86f144b23acb9feeda59e84405b84", size = 2501268, upload-time = "2025-04-10T19:46:26.044Z" }, - { url = "https://files.pythonhosted.org/packages/10/53/0a0cb5d79dd9f7039169f8bf94a144ad3efa52cc519940b3b7dde23bcb89/debugpy-1.8.14-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f6bb5c0dcf80ad5dbc7b7d6eac484e2af34bdacdf81df09b6a3e62792b722826", size = 4221077, upload-time = "2025-04-10T19:46:27.464Z" }, - { url = "https://files.pythonhosted.org/packages/f8/d5/84e01821f362327bf4828728aa31e907a2eca7c78cd7c6ec062780d249f8/debugpy-1.8.14-cp312-cp312-win32.whl", hash = "sha256:281d44d248a0e1791ad0eafdbbd2912ff0de9eec48022a5bfbc332957487ed3f", size = 5255127, upload-time = "2025-04-10T19:46:29.467Z" }, - { url = "https://files.pythonhosted.org/packages/33/16/1ed929d812c758295cac7f9cf3dab5c73439c83d9091f2d91871e648093e/debugpy-1.8.14-cp312-cp312-win_amd64.whl", hash = "sha256:5aa56ef8538893e4502a7d79047fe39b1dae08d9ae257074c6464a7b290b806f", size = 5297249, upload-time = "2025-04-10T19:46:31.538Z" }, - { url = "https://files.pythonhosted.org/packages/4d/e4/395c792b243f2367d84202dc33689aa3d910fb9826a7491ba20fc9e261f5/debugpy-1.8.14-cp313-cp313-macosx_14_0_universal2.whl", hash = "sha256:329a15d0660ee09fec6786acdb6e0443d595f64f5d096fc3e3ccf09a4259033f", size = 2485676, upload-time = "2025-04-10T19:46:32.96Z" }, - { url = "https://files.pythonhosted.org/packages/ba/f1/6f2ee3f991327ad9e4c2f8b82611a467052a0fb0e247390192580e89f7ff/debugpy-1.8.14-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0f920c7f9af409d90f5fd26e313e119d908b0dd2952c2393cd3247a462331f15", size = 4217514, upload-time = "2025-04-10T19:46:34.336Z" }, - { url = "https://files.pythonhosted.org/packages/79/28/b9d146f8f2dc535c236ee09ad3e5ac899adb39d7a19b49f03ac95d216beb/debugpy-1.8.14-cp313-cp313-win32.whl", hash = "sha256:3784ec6e8600c66cbdd4ca2726c72d8ca781e94bce2f396cc606d458146f8f4e", size = 5254756, upload-time = "2025-04-10T19:46:36.199Z" }, - { url = "https://files.pythonhosted.org/packages/e0/62/a7b4a57013eac4ccaef6977966e6bec5c63906dd25a86e35f155952e29a1/debugpy-1.8.14-cp313-cp313-win_amd64.whl", hash = "sha256:684eaf43c95a3ec39a96f1f5195a7ff3d4144e4a18d69bb66beeb1a6de605d6e", size = 5297119, upload-time = "2025-04-10T19:46:38.141Z" }, - { url = "https://files.pythonhosted.org/packages/97/1a/481f33c37ee3ac8040d3d51fc4c4e4e7e61cb08b8bc8971d6032acc2279f/debugpy-1.8.14-py2.py3-none-any.whl", hash = "sha256:5cd9a579d553b6cb9759a7908a41988ee6280b961f24f63336835d9418216a20", size = 5256230, upload-time = "2025-04-10T19:46:54.077Z" }, + { url = "https://files.pythonhosted.org/packages/d2/b3/1c44a2ed311199ab11c2299c9474a6c7cd80d19278defd333aeb7c287995/debugpy-1.8.15-cp311-cp311-macosx_14_0_universal2.whl", hash = "sha256:babc4fb1962dd6a37e94d611280e3d0d11a1f5e6c72ac9b3d87a08212c4b6dd3", size = 2183442, upload-time = "2025-07-15T16:43:36.733Z" }, + { url = "https://files.pythonhosted.org/packages/f6/69/e2dcb721491e1c294d348681227c9b44fb95218f379aa88e12a19d85528d/debugpy-1.8.15-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f778e68f2986a58479d0ac4f643e0b8c82fdd97c2e200d4d61e7c2d13838eb53", size = 3134215, upload-time = "2025-07-15T16:43:38.116Z" }, + { url = "https://files.pythonhosted.org/packages/17/76/4ce63b95d8294dcf2fd1820860b300a420d077df4e93afcaa25a984c2ca7/debugpy-1.8.15-cp311-cp311-win32.whl", hash = "sha256:f9d1b5abd75cd965e2deabb1a06b0e93a1546f31f9f621d2705e78104377c702", size = 5154037, upload-time = "2025-07-15T16:43:39.471Z" }, + { url = "https://files.pythonhosted.org/packages/c2/a7/e5a7c784465eb9c976d84408873d597dc7ce74a0fc69ed009548a1a94813/debugpy-1.8.15-cp311-cp311-win_amd64.whl", hash = "sha256:62954fb904bec463e2b5a415777f6d1926c97febb08ef1694da0e5d1463c5c3b", size = 5178133, upload-time = "2025-07-15T16:43:40.969Z" }, + { url = "https://files.pythonhosted.org/packages/ab/4a/4508d256e52897f5cdfee6a6d7580974811e911c6d01321df3264508a5ac/debugpy-1.8.15-cp312-cp312-macosx_14_0_universal2.whl", hash = "sha256:3dcc7225cb317469721ab5136cda9ff9c8b6e6fb43e87c9e15d5b108b99d01ba", size = 2511197, upload-time = "2025-07-15T16:43:42.343Z" }, + { url = "https://files.pythonhosted.org/packages/99/8d/7f6ef1097e7fecf26b4ef72338d08e41644a41b7ee958a19f494ffcffc29/debugpy-1.8.15-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:047a493ca93c85ccede1dbbaf4e66816794bdc214213dde41a9a61e42d27f8fc", size = 4229517, upload-time = "2025-07-15T16:43:44.14Z" }, + { url = "https://files.pythonhosted.org/packages/3f/e8/e8c6a9aa33a9c9c6dacbf31747384f6ed2adde4de2e9693c766bdf323aa3/debugpy-1.8.15-cp312-cp312-win32.whl", hash = "sha256:b08e9b0bc260cf324c890626961dad4ffd973f7568fbf57feb3c3a65ab6b6327", size = 5276132, upload-time = "2025-07-15T16:43:45.529Z" }, + { url = "https://files.pythonhosted.org/packages/e9/ad/231050c6177b3476b85fcea01e565dac83607b5233d003ff067e2ee44d8f/debugpy-1.8.15-cp312-cp312-win_amd64.whl", hash = "sha256:e2a4fe357c92334272eb2845fcfcdbec3ef9f22c16cf613c388ac0887aed15fa", size = 5317645, upload-time = "2025-07-15T16:43:46.968Z" }, + { url = "https://files.pythonhosted.org/packages/28/70/2928aad2310726d5920b18ed9f54b9f06df5aa4c10cf9b45fa18ff0ab7e8/debugpy-1.8.15-cp313-cp313-macosx_14_0_universal2.whl", hash = "sha256:f5e01291ad7d6649aed5773256c5bba7a1a556196300232de1474c3c372592bf", size = 2495538, upload-time = "2025-07-15T16:43:48.927Z" }, + { url = "https://files.pythonhosted.org/packages/9e/c6/9b8ffb4ca91fac8b2877eef63c9cc0e87dd2570b1120054c272815ec4cd0/debugpy-1.8.15-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:94dc0f0d00e528d915e0ce1c78e771475b2335b376c49afcc7382ee0b146bab6", size = 4221874, upload-time = "2025-07-15T16:43:50.282Z" }, + { url = "https://files.pythonhosted.org/packages/55/8a/9b8d59674b4bf489318c7c46a1aab58e606e583651438084b7e029bf3c43/debugpy-1.8.15-cp313-cp313-win32.whl", hash = "sha256:fcf0748d4f6e25f89dc5e013d1129ca6f26ad4da405e0723a4f704583896a709", size = 5275949, upload-time = "2025-07-15T16:43:52.079Z" }, + { url = "https://files.pythonhosted.org/packages/72/83/9e58e6fdfa8710a5e6ec06c2401241b9ad48b71c0a7eb99570a1f1edb1d3/debugpy-1.8.15-cp313-cp313-win_amd64.whl", hash = "sha256:73c943776cb83e36baf95e8f7f8da765896fd94b05991e7bc162456d25500683", size = 5317720, upload-time = "2025-07-15T16:43:53.703Z" }, + { url = "https://files.pythonhosted.org/packages/07/d5/98748d9860e767a1248b5e31ffa7ce8cb7006e97bf8abbf3d891d0a8ba4e/debugpy-1.8.15-py2.py3-none-any.whl", hash = "sha256:bce2e6c5ff4f2e00b98d45e7e01a49c7b489ff6df5f12d881c67d2f1ac635f3d", size = 5282697, upload-time = "2025-07-15T16:44:07.996Z" }, ] [[package]] @@ -657,15 +657,15 @@ wheels = [ [[package]] name = "hypothesis" -version = "6.135.26" +version = "6.135.31" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "attrs" }, { name = "sortedcontainers" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/da/83/15c4e30561a0d8c8d076c88cb159187823d877118f34c851ada3b9b02a7b/hypothesis-6.135.26.tar.gz", hash = "sha256:73af0e46cd5039c6806f514fed6a3c185d91ef88b5a1577477099ddbd1a2e300", size = 454523, upload-time = "2025-07-05T04:59:45.443Z" } +sdist = { url = "https://files.pythonhosted.org/packages/22/2c/988c75a27f805ce53ef5a3feaf96add76fe93aede509e16126408c426a0d/hypothesis-6.135.31.tar.gz", hash = "sha256:a759a6010a43424b66b634383a04717a30ed05f553cc51e3b3fe3931faace53a", size = 455774, upload-time = "2025-07-15T02:04:18.988Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/3c/78/db4fdc464219455f8dde90074660c3faf8429101b2d1299cac7d219e3176/hypothesis-6.135.26-py3-none-any.whl", hash = "sha256:fa237cbe2ae2c31d65f7230dcb866139ace635dcfec6c30dddf25974dd8ff4b9", size = 521517, upload-time = "2025-07-05T04:59:42.061Z" }, + { url = "https://files.pythonhosted.org/packages/08/f6/3a9ad54d87c3bc5d4fe4925b0eb5d93c5e3090cf6fe8472176651ce04eea/hypothesis-6.135.31-py3-none-any.whl", hash = "sha256:12f1cf4aa961884b71021ef8770d81045f66c0b3f4295abc956e4f84d862f321", size = 522768, upload-time = "2025-07-15T02:04:15.919Z" }, ] [[package]] @@ -1204,34 +1204,34 @@ wheels = [ [[package]] name = "mypy" -version = "1.16.1" +version = "1.17.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "mypy-extensions" }, { name = "pathspec" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/81/69/92c7fa98112e4d9eb075a239caa4ef4649ad7d441545ccffbd5e34607cbb/mypy-1.16.1.tar.gz", hash = "sha256:6bd00a0a2094841c5e47e7374bb42b83d64c527a502e3334e1173a0c24437bab", size = 3324747, upload-time = "2025-06-16T16:51:35.145Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/9a/61/ec1245aa1c325cb7a6c0f8570a2eee3bfc40fa90d19b1267f8e50b5c8645/mypy-1.16.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:472e4e4c100062488ec643f6162dd0d5208e33e2f34544e1fc931372e806c0cc", size = 10890557, upload-time = "2025-06-16T16:37:21.421Z" }, - { url = "https://files.pythonhosted.org/packages/6b/bb/6eccc0ba0aa0c7a87df24e73f0ad34170514abd8162eb0c75fd7128171fb/mypy-1.16.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ea16e2a7d2714277e349e24d19a782a663a34ed60864006e8585db08f8ad1782", size = 10012921, upload-time = "2025-06-16T16:51:28.659Z" }, - { url = "https://files.pythonhosted.org/packages/5f/80/b337a12e2006715f99f529e732c5f6a8c143bb58c92bb142d5ab380963a5/mypy-1.16.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:08e850ea22adc4d8a4014651575567b0318ede51e8e9fe7a68f25391af699507", size = 11802887, upload-time = "2025-06-16T16:50:53.627Z" }, - { url = "https://files.pythonhosted.org/packages/d9/59/f7af072d09793d581a745a25737c7c0a945760036b16aeb620f658a017af/mypy-1.16.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:22d76a63a42619bfb90122889b903519149879ddbf2ba4251834727944c8baca", size = 12531658, upload-time = "2025-06-16T16:33:55.002Z" }, - { url = "https://files.pythonhosted.org/packages/82/c4/607672f2d6c0254b94a646cfc45ad589dd71b04aa1f3d642b840f7cce06c/mypy-1.16.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:2c7ce0662b6b9dc8f4ed86eb7a5d505ee3298c04b40ec13b30e572c0e5ae17c4", size = 12732486, upload-time = "2025-06-16T16:37:03.301Z" }, - { url = "https://files.pythonhosted.org/packages/b6/5e/136555ec1d80df877a707cebf9081bd3a9f397dedc1ab9750518d87489ec/mypy-1.16.1-cp311-cp311-win_amd64.whl", hash = "sha256:211287e98e05352a2e1d4e8759c5490925a7c784ddc84207f4714822f8cf99b6", size = 9479482, upload-time = "2025-06-16T16:47:37.48Z" }, - { url = "https://files.pythonhosted.org/packages/b4/d6/39482e5fcc724c15bf6280ff5806548c7185e0c090712a3736ed4d07e8b7/mypy-1.16.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:af4792433f09575d9eeca5c63d7d90ca4aeceda9d8355e136f80f8967639183d", size = 11066493, upload-time = "2025-06-16T16:47:01.683Z" }, - { url = "https://files.pythonhosted.org/packages/e6/e5/26c347890efc6b757f4d5bb83f4a0cf5958b8cf49c938ac99b8b72b420a6/mypy-1.16.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:66df38405fd8466ce3517eda1f6640611a0b8e70895e2a9462d1d4323c5eb4b9", size = 10081687, upload-time = "2025-06-16T16:48:19.367Z" }, - { url = "https://files.pythonhosted.org/packages/44/c7/b5cb264c97b86914487d6a24bd8688c0172e37ec0f43e93b9691cae9468b/mypy-1.16.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:44e7acddb3c48bd2713994d098729494117803616e116032af192871aed80b79", size = 11839723, upload-time = "2025-06-16T16:49:20.912Z" }, - { url = "https://files.pythonhosted.org/packages/15/f8/491997a9b8a554204f834ed4816bda813aefda31cf873bb099deee3c9a99/mypy-1.16.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0ab5eca37b50188163fa7c1b73c685ac66c4e9bdee4a85c9adac0e91d8895e15", size = 12722980, upload-time = "2025-06-16T16:37:40.929Z" }, - { url = "https://files.pythonhosted.org/packages/df/f0/2bd41e174b5fd93bc9de9a28e4fb673113633b8a7f3a607fa4a73595e468/mypy-1.16.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:dedb6229b2c9086247e21a83c309754b9058b438704ad2f6807f0d8227f6ebdd", size = 12903328, upload-time = "2025-06-16T16:34:35.099Z" }, - { url = "https://files.pythonhosted.org/packages/61/81/5572108a7bec2c46b8aff7e9b524f371fe6ab5efb534d38d6b37b5490da8/mypy-1.16.1-cp312-cp312-win_amd64.whl", hash = "sha256:1f0435cf920e287ff68af3d10a118a73f212deb2ce087619eb4e648116d1fe9b", size = 9562321, upload-time = "2025-06-16T16:48:58.823Z" }, - { url = "https://files.pythonhosted.org/packages/28/e3/96964af4a75a949e67df4b95318fe2b7427ac8189bbc3ef28f92a1c5bc56/mypy-1.16.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ddc91eb318c8751c69ddb200a5937f1232ee8efb4e64e9f4bc475a33719de438", size = 11063480, upload-time = "2025-06-16T16:47:56.205Z" }, - { url = "https://files.pythonhosted.org/packages/f5/4d/cd1a42b8e5be278fab7010fb289d9307a63e07153f0ae1510a3d7b703193/mypy-1.16.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:87ff2c13d58bdc4bbe7dc0dedfe622c0f04e2cb2a492269f3b418df2de05c536", size = 10090538, upload-time = "2025-06-16T16:46:43.92Z" }, - { url = "https://files.pythonhosted.org/packages/c9/4f/c3c6b4b66374b5f68bab07c8cabd63a049ff69796b844bc759a0ca99bb2a/mypy-1.16.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0a7cfb0fe29fe5a9841b7c8ee6dffb52382c45acdf68f032145b75620acfbd6f", size = 11836839, upload-time = "2025-06-16T16:36:28.039Z" }, - { url = "https://files.pythonhosted.org/packages/b4/7e/81ca3b074021ad9775e5cb97ebe0089c0f13684b066a750b7dc208438403/mypy-1.16.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:051e1677689c9d9578b9c7f4d206d763f9bbd95723cd1416fad50db49d52f359", size = 12715634, upload-time = "2025-06-16T16:50:34.441Z" }, - { url = "https://files.pythonhosted.org/packages/e9/95/bdd40c8be346fa4c70edb4081d727a54d0a05382d84966869738cfa8a497/mypy-1.16.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:d5d2309511cc56c021b4b4e462907c2b12f669b2dbeb68300110ec27723971be", size = 12895584, upload-time = "2025-06-16T16:34:54.857Z" }, - { url = "https://files.pythonhosted.org/packages/5a/fd/d486a0827a1c597b3b48b1bdef47228a6e9ee8102ab8c28f944cb83b65dc/mypy-1.16.1-cp313-cp313-win_amd64.whl", hash = "sha256:4f58ac32771341e38a853c5d0ec0dfe27e18e27da9cdb8bbc882d2249c71a3ee", size = 9573886, upload-time = "2025-06-16T16:36:43.589Z" }, - { url = "https://files.pythonhosted.org/packages/cf/d3/53e684e78e07c1a2bf7105715e5edd09ce951fc3f47cf9ed095ec1b7a037/mypy-1.16.1-py3-none-any.whl", hash = "sha256:5fc2ac4027d0ef28d6ba69a0343737a23c4d1b83672bf38d1fe237bdc0643b37", size = 2265923, upload-time = "2025-06-16T16:48:02.366Z" }, +sdist = { url = "https://files.pythonhosted.org/packages/1e/e3/034322d5a779685218ed69286c32faa505247f1f096251ef66c8fd203b08/mypy-1.17.0.tar.gz", hash = "sha256:e5d7ccc08ba089c06e2f5629c660388ef1fee708444f1dee0b9203fa031dee03", size = 3352114, upload-time = "2025-07-14T20:34:30.181Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d4/24/82efb502b0b0f661c49aa21cfe3e1999ddf64bf5500fc03b5a1536a39d39/mypy-1.17.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:9d4fe5c72fd262d9c2c91c1117d16aac555e05f5beb2bae6a755274c6eec42be", size = 10914150, upload-time = "2025-07-14T20:31:51.985Z" }, + { url = "https://files.pythonhosted.org/packages/03/96/8ef9a6ff8cedadff4400e2254689ca1dc4b420b92c55255b44573de10c54/mypy-1.17.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d96b196e5c16f41b4f7736840e8455958e832871990c7ba26bf58175e357ed61", size = 10039845, upload-time = "2025-07-14T20:32:30.527Z" }, + { url = "https://files.pythonhosted.org/packages/df/32/7ce359a56be779d38021d07941cfbb099b41411d72d827230a36203dbb81/mypy-1.17.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:73a0ff2dd10337ceb521c080d4147755ee302dcde6e1a913babd59473904615f", size = 11837246, upload-time = "2025-07-14T20:32:01.28Z" }, + { url = "https://files.pythonhosted.org/packages/82/16/b775047054de4d8dbd668df9137707e54b07fe18c7923839cd1e524bf756/mypy-1.17.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:24cfcc1179c4447854e9e406d3af0f77736d631ec87d31c6281ecd5025df625d", size = 12571106, upload-time = "2025-07-14T20:34:26.942Z" }, + { url = "https://files.pythonhosted.org/packages/a1/cf/fa33eaf29a606102c8d9ffa45a386a04c2203d9ad18bf4eef3e20c43ebc8/mypy-1.17.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:3c56f180ff6430e6373db7a1d569317675b0a451caf5fef6ce4ab365f5f2f6c3", size = 12759960, upload-time = "2025-07-14T20:33:42.882Z" }, + { url = "https://files.pythonhosted.org/packages/94/75/3f5a29209f27e739ca57e6350bc6b783a38c7621bdf9cac3ab8a08665801/mypy-1.17.0-cp311-cp311-win_amd64.whl", hash = "sha256:eafaf8b9252734400f9b77df98b4eee3d2eecab16104680d51341c75702cad70", size = 9503888, upload-time = "2025-07-14T20:32:34.392Z" }, + { url = "https://files.pythonhosted.org/packages/12/e9/e6824ed620bbf51d3bf4d6cbbe4953e83eaf31a448d1b3cfb3620ccb641c/mypy-1.17.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:f986f1cab8dbec39ba6e0eaa42d4d3ac6686516a5d3dccd64be095db05ebc6bb", size = 11086395, upload-time = "2025-07-14T20:34:11.452Z" }, + { url = "https://files.pythonhosted.org/packages/ba/51/a4afd1ae279707953be175d303f04a5a7bd7e28dc62463ad29c1c857927e/mypy-1.17.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:51e455a54d199dd6e931cd7ea987d061c2afbaf0960f7f66deef47c90d1b304d", size = 10120052, upload-time = "2025-07-14T20:33:09.897Z" }, + { url = "https://files.pythonhosted.org/packages/8a/71/19adfeac926ba8205f1d1466d0d360d07b46486bf64360c54cb5a2bd86a8/mypy-1.17.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3204d773bab5ff4ebbd1f8efa11b498027cd57017c003ae970f310e5b96be8d8", size = 11861806, upload-time = "2025-07-14T20:32:16.028Z" }, + { url = "https://files.pythonhosted.org/packages/0b/64/d6120eca3835baf7179e6797a0b61d6c47e0bc2324b1f6819d8428d5b9ba/mypy-1.17.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1051df7ec0886fa246a530ae917c473491e9a0ba6938cfd0ec2abc1076495c3e", size = 12744371, upload-time = "2025-07-14T20:33:33.503Z" }, + { url = "https://files.pythonhosted.org/packages/1f/dc/56f53b5255a166f5bd0f137eed960e5065f2744509dfe69474ff0ba772a5/mypy-1.17.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:f773c6d14dcc108a5b141b4456b0871df638eb411a89cd1c0c001fc4a9d08fc8", size = 12914558, upload-time = "2025-07-14T20:33:56.961Z" }, + { url = "https://files.pythonhosted.org/packages/69/ac/070bad311171badc9add2910e7f89271695a25c136de24bbafc7eded56d5/mypy-1.17.0-cp312-cp312-win_amd64.whl", hash = "sha256:1619a485fd0e9c959b943c7b519ed26b712de3002d7de43154a489a2d0fd817d", size = 9585447, upload-time = "2025-07-14T20:32:20.594Z" }, + { url = "https://files.pythonhosted.org/packages/be/7b/5f8ab461369b9e62157072156935cec9d272196556bdc7c2ff5f4c7c0f9b/mypy-1.17.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:2c41aa59211e49d717d92b3bb1238c06d387c9325d3122085113c79118bebb06", size = 11070019, upload-time = "2025-07-14T20:32:07.99Z" }, + { url = "https://files.pythonhosted.org/packages/9c/f8/c49c9e5a2ac0badcc54beb24e774d2499748302c9568f7f09e8730e953fa/mypy-1.17.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0e69db1fb65b3114f98c753e3930a00514f5b68794ba80590eb02090d54a5d4a", size = 10114457, upload-time = "2025-07-14T20:33:47.285Z" }, + { url = "https://files.pythonhosted.org/packages/89/0c/fb3f9c939ad9beed3e328008b3fb90b20fda2cddc0f7e4c20dbefefc3b33/mypy-1.17.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:03ba330b76710f83d6ac500053f7727270b6b8553b0423348ffb3af6f2f7b889", size = 11857838, upload-time = "2025-07-14T20:33:14.462Z" }, + { url = "https://files.pythonhosted.org/packages/4c/66/85607ab5137d65e4f54d9797b77d5a038ef34f714929cf8ad30b03f628df/mypy-1.17.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:037bc0f0b124ce46bfde955c647f3e395c6174476a968c0f22c95a8d2f589bba", size = 12731358, upload-time = "2025-07-14T20:32:25.579Z" }, + { url = "https://files.pythonhosted.org/packages/73/d0/341dbbfb35ce53d01f8f2969facbb66486cee9804048bf6c01b048127501/mypy-1.17.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:c38876106cb6132259683632b287238858bd58de267d80defb6f418e9ee50658", size = 12917480, upload-time = "2025-07-14T20:34:21.868Z" }, + { url = "https://files.pythonhosted.org/packages/64/63/70c8b7dbfc520089ac48d01367a97e8acd734f65bd07813081f508a8c94c/mypy-1.17.0-cp313-cp313-win_amd64.whl", hash = "sha256:d30ba01c0f151998f367506fab31c2ac4527e6a7b2690107c7a7f9e3cb419a9c", size = 9589666, upload-time = "2025-07-14T20:34:16.841Z" }, + { url = "https://files.pythonhosted.org/packages/e3/fc/ee058cc4316f219078464555873e99d170bde1d9569abd833300dbeb484a/mypy-1.17.0-py3-none-any.whl", hash = "sha256:15d9d0018237ab058e5de3d8fce61b6fa72cc59cc78fd91f1b474bce12abf496", size = 2283195, upload-time = "2025-07-14T20:31:54.753Z" }, ] [[package]] @@ -1999,18 +1999,21 @@ wheels = [ [[package]] name = "pywin32" -version = "310" -source = { registry = "https://pypi.org/simple" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/f7/b1/68aa2986129fb1011dabbe95f0136f44509afaf072b12b8f815905a39f33/pywin32-310-cp311-cp311-win32.whl", hash = "sha256:1e765f9564e83011a63321bb9d27ec456a0ed90d3732c4b2e312b855365ed8bd", size = 8784284, upload-time = "2025-03-17T00:55:53.124Z" }, - { url = "https://files.pythonhosted.org/packages/b3/bd/d1592635992dd8db5bb8ace0551bc3a769de1ac8850200cfa517e72739fb/pywin32-310-cp311-cp311-win_amd64.whl", hash = "sha256:126298077a9d7c95c53823934f000599f66ec9296b09167810eb24875f32689c", size = 9520748, upload-time = "2025-03-17T00:55:55.203Z" }, - { url = "https://files.pythonhosted.org/packages/90/b1/ac8b1ffce6603849eb45a91cf126c0fa5431f186c2e768bf56889c46f51c/pywin32-310-cp311-cp311-win_arm64.whl", hash = "sha256:19ec5fc9b1d51c4350be7bb00760ffce46e6c95eaf2f0b2f1150657b1a43c582", size = 8455941, upload-time = "2025-03-17T00:55:57.048Z" }, - { url = "https://files.pythonhosted.org/packages/6b/ec/4fdbe47932f671d6e348474ea35ed94227fb5df56a7c30cbbb42cd396ed0/pywin32-310-cp312-cp312-win32.whl", hash = "sha256:8a75a5cc3893e83a108c05d82198880704c44bbaee4d06e442e471d3c9ea4f3d", size = 8796239, upload-time = "2025-03-17T00:55:58.807Z" }, - { url = "https://files.pythonhosted.org/packages/e3/e5/b0627f8bb84e06991bea89ad8153a9e50ace40b2e1195d68e9dff6b03d0f/pywin32-310-cp312-cp312-win_amd64.whl", hash = "sha256:bf5c397c9a9a19a6f62f3fb821fbf36cac08f03770056711f765ec1503972060", size = 9503839, upload-time = "2025-03-17T00:56:00.8Z" }, - { url = "https://files.pythonhosted.org/packages/1f/32/9ccf53748df72301a89713936645a664ec001abd35ecc8578beda593d37d/pywin32-310-cp312-cp312-win_arm64.whl", hash = "sha256:2349cc906eae872d0663d4d6290d13b90621eaf78964bb1578632ff20e152966", size = 8459470, upload-time = "2025-03-17T00:56:02.601Z" }, - { url = "https://files.pythonhosted.org/packages/1c/09/9c1b978ffc4ae53999e89c19c77ba882d9fce476729f23ef55211ea1c034/pywin32-310-cp313-cp313-win32.whl", hash = "sha256:5d241a659c496ada3253cd01cfaa779b048e90ce4b2b38cd44168ad555ce74ab", size = 8794384, upload-time = "2025-03-17T00:56:04.383Z" }, - { url = "https://files.pythonhosted.org/packages/45/3c/b4640f740ffebadd5d34df35fecba0e1cfef8fde9f3e594df91c28ad9b50/pywin32-310-cp313-cp313-win_amd64.whl", hash = "sha256:667827eb3a90208ddbdcc9e860c81bde63a135710e21e4cb3348968e4bd5249e", size = 9503039, upload-time = "2025-03-17T00:56:06.207Z" }, - { url = "https://files.pythonhosted.org/packages/b4/f4/f785020090fb050e7fb6d34b780f2231f302609dc964672f72bfaeb59a28/pywin32-310-cp313-cp313-win_arm64.whl", hash = "sha256:e308f831de771482b7cf692a1f308f8fca701b2d8f9dde6cc440c7da17e47b33", size = 8458152, upload-time = "2025-03-17T00:56:07.819Z" }, +version = "311" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7c/af/449a6a91e5d6db51420875c54f6aff7c97a86a3b13a0b4f1a5c13b988de3/pywin32-311-cp311-cp311-win32.whl", hash = "sha256:184eb5e436dea364dcd3d2316d577d625c0351bf237c4e9a5fabbcfa5a58b151", size = 8697031, upload-time = "2025-07-14T20:13:13.266Z" }, + { url = "https://files.pythonhosted.org/packages/51/8f/9bb81dd5bb77d22243d33c8397f09377056d5c687aa6d4042bea7fbf8364/pywin32-311-cp311-cp311-win_amd64.whl", hash = "sha256:3ce80b34b22b17ccbd937a6e78e7225d80c52f5ab9940fe0506a1a16f3dab503", size = 9508308, upload-time = "2025-07-14T20:13:15.147Z" }, + { url = "https://files.pythonhosted.org/packages/44/7b/9c2ab54f74a138c491aba1b1cd0795ba61f144c711daea84a88b63dc0f6c/pywin32-311-cp311-cp311-win_arm64.whl", hash = "sha256:a733f1388e1a842abb67ffa8e7aad0e70ac519e09b0f6a784e65a136ec7cefd2", size = 8703930, upload-time = "2025-07-14T20:13:16.945Z" }, + { url = "https://files.pythonhosted.org/packages/e7/ab/01ea1943d4eba0f850c3c61e78e8dd59757ff815ff3ccd0a84de5f541f42/pywin32-311-cp312-cp312-win32.whl", hash = "sha256:750ec6e621af2b948540032557b10a2d43b0cee2ae9758c54154d711cc852d31", size = 8706543, upload-time = "2025-07-14T20:13:20.765Z" }, + { url = "https://files.pythonhosted.org/packages/d1/a8/a0e8d07d4d051ec7502cd58b291ec98dcc0c3fff027caad0470b72cfcc2f/pywin32-311-cp312-cp312-win_amd64.whl", hash = "sha256:b8c095edad5c211ff31c05223658e71bf7116daa0ecf3ad85f3201ea3190d067", size = 9495040, upload-time = "2025-07-14T20:13:22.543Z" }, + { url = "https://files.pythonhosted.org/packages/ba/3a/2ae996277b4b50f17d61f0603efd8253cb2d79cc7ae159468007b586396d/pywin32-311-cp312-cp312-win_arm64.whl", hash = "sha256:e286f46a9a39c4a18b319c28f59b61de793654af2f395c102b4f819e584b5852", size = 8710102, upload-time = "2025-07-14T20:13:24.682Z" }, + { url = "https://files.pythonhosted.org/packages/a5/be/3fd5de0979fcb3994bfee0d65ed8ca9506a8a1260651b86174f6a86f52b3/pywin32-311-cp313-cp313-win32.whl", hash = "sha256:f95ba5a847cba10dd8c4d8fefa9f2a6cf283b8b88ed6178fa8a6c1ab16054d0d", size = 8705700, upload-time = "2025-07-14T20:13:26.471Z" }, + { url = "https://files.pythonhosted.org/packages/e3/28/e0a1909523c6890208295a29e05c2adb2126364e289826c0a8bc7297bd5c/pywin32-311-cp313-cp313-win_amd64.whl", hash = "sha256:718a38f7e5b058e76aee1c56ddd06908116d35147e133427e59a3983f703a20d", size = 9494700, upload-time = "2025-07-14T20:13:28.243Z" }, + { url = "https://files.pythonhosted.org/packages/04/bf/90339ac0f55726dce7d794e6d79a18a91265bdf3aa70b6b9ca52f35e022a/pywin32-311-cp313-cp313-win_arm64.whl", hash = "sha256:7b4075d959648406202d92a2310cb990fea19b535c7f4a78d3f5e10b926eeb8a", size = 8709318, upload-time = "2025-07-14T20:13:30.348Z" }, + { url = "https://files.pythonhosted.org/packages/c9/31/097f2e132c4f16d99a22bfb777e0fd88bd8e1c634304e102f313af69ace5/pywin32-311-cp314-cp314-win32.whl", hash = "sha256:b7a2c10b93f8986666d0c803ee19b5990885872a7de910fc460f9b0c2fbf92ee", size = 8840714, upload-time = "2025-07-14T20:13:32.449Z" }, + { url = "https://files.pythonhosted.org/packages/90/4b/07c77d8ba0e01349358082713400435347df8426208171ce297da32c313d/pywin32-311-cp314-cp314-win_amd64.whl", hash = "sha256:3aca44c046bd2ed8c90de9cb8427f581c479e594e99b5c0bb19b29c10fd6cb87", size = 9656800, upload-time = "2025-07-14T20:13:34.312Z" }, + { url = "https://files.pythonhosted.org/packages/c0/d2/21af5c535501a7233e734b8af901574572da66fcc254cb35d0609c9080dd/pywin32-311-cp314-cp314-win_arm64.whl", hash = "sha256:a508e2d9025764a8270f93111a970e1d0fbfc33f4153b388bb649b7eec4f9b42", size = 8932540, upload-time = "2025-07-14T20:13:36.379Z" }, ] [[package]] From e174a05db298d281bc55b648aaee2ef624889ccb Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 16 Jul 2025 00:04:35 +0000 Subject: [PATCH 374/521] [pre-commit.ci] pre-commit autoupdate (#3050) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [pre-commit.ci] pre-commit autoupdate updates: - [github.com/python-jsonschema/check-jsonschema: 0.33.0 → 0.33.2](https://github.com/python-jsonschema/check-jsonschema/compare/0.33.0...0.33.2) - [github.com/macisamuele/language-formatters-pre-commit-hooks: v2.14.0 → v2.15.0](https://github.com/macisamuele/language-formatters-pre-commit-hooks/compare/v2.14.0...v2.15.0) - [github.com/mattlqx/pre-commit-search-and-replace: v1.0.5 → v1.1.8](https://github.com/mattlqx/pre-commit-search-and-replace/compare/v1.0.5...v1.1.8) - [github.com/crate-ci/typos: v1.33.1 → v1](https://github.com/crate-ci/typos/compare/v1.33.1...v1) - [github.com/astral-sh/ruff-pre-commit: v0.11.12 → v0.12.2](https://github.com/astral-sh/ruff-pre-commit/compare/v0.11.12...v0.12.2) * Revert some version updates * Reduce cadence of auto-updates * Move matplotlib imports to top of file * Fix new ruff errors * Fix new ruff errors * Fix ruff error for multiple statements in pytest.warns * Add __hash__ or set to ignore ruff rule * Revert Coulomb logarithm tests * Revert test_coulomb.py & add noqa comments * Ignore PT031 in test_coulomb.py * Remove noqa comments * Revert some files * Add noqa comments * Update pre-commit version of ruff * Revert changes to test_transport.py * Ignore ruff rule in test_transport.py * nox -s requirements --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Nick Murphy Co-authored-by: Nick Murphy --- .pre-commit-config.yaml | 10 +++++----- pyproject.toml | 4 +++- src/plasmapy/__init__.py | 4 ++-- src/plasmapy/analysis/nullpoint.py | 2 +- src/plasmapy/diagnostics/langmuir.py | 15 +-------------- src/plasmapy/formulary/dimensionless.py | 2 +- src/plasmapy/formulary/relativity.py | 3 +++ src/plasmapy/particles/ionization_state.py | 8 +++++++- .../particles/ionization_state_collection.py | 2 +- src/plasmapy/particles/particle_class.py | 8 +++++--- src/plasmapy/particles/particle_collections.py | 2 +- .../swept_langmuir/test_floating_potential.py | 3 ++- tests/analysis/test_fit_functions.py | 4 ++-- .../test_synthetic_radiography.py | 3 ++- .../collisions/test_collisions_dimensionless.py | 2 ++ .../collisions/test_collisions_frequencies.py | 1 + .../collisions/test_collisions_lengths.py | 2 +- .../formulary/collisions/test_collisions_misc.py | 2 +- tests/formulary/test_lengths.py | 8 +++----- tests/formulary/test_plasma_frequency.py | 4 ++-- tests/formulary/test_speeds.py | 4 ++-- tests/formulary/test_thermal_speed.py | 11 +++++------ tests/particles/test_parsing.py | 6 +++--- tests/particles/test_particle_class.py | 4 ++-- tests/plasma/sources/test_plasmablob.py | 2 +- tests/plasma/test_grids.py | 2 +- uv.lock | 6 +++--- 27 files changed, 63 insertions(+), 61 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 26c98231f3..f0b745169f 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ ci: autofix_prs: false - autoupdate_schedule: monthly + autoupdate_schedule: quarterly # Specify the default version of Ruby in case it is not installed default_language_version: @@ -28,7 +28,7 @@ repos: - id: check-yaml - repo: https://github.com/python-jsonschema/check-jsonschema - rev: 0.33.0 + rev: 0.33.2 hooks: - id: check-github-workflows @@ -41,7 +41,7 @@ repos: - id: forbid-bidi-controls - repo: https://github.com/macisamuele/language-formatters-pre-commit-hooks - rev: v2.14.0 + rev: v2.15.0 hooks: - id: pretty-format-ini args: [--autofix] @@ -80,13 +80,13 @@ repos: - tomli - repo: https://github.com/crate-ci/typos - rev: v1.33.1 + rev: v1.34.0 hooks: - id: typos name: typos (add false positives to _typos.toml) - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.11.12 + rev: v0.12.3 hooks: - id: ruff name: ruff (see https://docs.astral.sh/ruff/rules) diff --git a/pyproject.toml b/pyproject.toml index b2d9a9a368..e389b99a43 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -299,7 +299,7 @@ lint.per-file-ignores.".github/scripts/*.py" = [ "D103", "INP001" ] lint.per-file-ignores."__init__.py" = [ "D104", "E402", "F401", "F402", "F403" ] # ignore import errors lint.per-file-ignores."docs/conf.py" = [ "D100", "D103", "E402", "EXE001", "EXE005", "F401" ] -# Most ruff rule violations in the following notebooks should eventually be fixed +# Most ruff rule violations in the following files should eventually be fixed lint.per-file-ignores."docs/notebooks/analysis/fit_functions.ipynb" = [ "NPY002" ] lint.per-file-ignores."docs/notebooks/analysis/nullpoint.ipynb" = [ "D103" ] lint.per-file-ignores."docs/notebooks/analysis/swept_langmuir/find_floating_potential.ipynb" = [ "FBT003" ] @@ -349,7 +349,9 @@ lint.per-file-ignores."tests/**/test_*.py" = [ "RUF012", "SLF001", ] +lint.per-file-ignores."tests/formulary/collisions/test_coulomb.py" = [ "PT031" ] lint.per-file-ignores."tests/formulary/test_distribution.py" = [ "ARG005" ] +lint.per-file-ignores."tests/formulary/test_transport.py" = [ "PT031" ] lint.per-file-ignores."tests/particles/test_decorators.py" = [ "ARG001", "ARG002" ] lint.per-file-ignores."tests/utils/_pytest_helpers/test_pytest_helpers.py" = [ "BLE001", "TRY002" ] lint.per-file-ignores."tests/utils/decorators/test_converters.py" = [ "ARG001", "ARG005" ] diff --git a/src/plasmapy/__init__.py b/src/plasmapy/__init__.py index fa2d301366..839fca4c76 100644 --- a/src/plasmapy/__init__.py +++ b/src/plasmapy/__init__.py @@ -80,8 +80,8 @@ def online_help(query: str) -> None: # coverage: ignore query : str The search query. """ - import webbrowser - from urllib.parse import urlencode + import webbrowser # noqa: PLC0415 + from urllib.parse import urlencode # noqa: PLC0415 url = ( "http://docs.plasmapy.org/en/stable/search.html?" diff --git a/src/plasmapy/analysis/nullpoint.py b/src/plasmapy/analysis/nullpoint.py index 567b0862bb..8ea5cfb520 100644 --- a/src/plasmapy/analysis/nullpoint.py +++ b/src/plasmapy/analysis/nullpoint.py @@ -105,7 +105,7 @@ def get_loc(self): loc = property(get_loc) -class NullPoint(Point): +class NullPoint(Point): # noqa: PLW1641 """ A class for defining a null point in 3D space. diff --git a/src/plasmapy/diagnostics/langmuir.py b/src/plasmapy/diagnostics/langmuir.py index e1ee537aad..5892177a73 100644 --- a/src/plasmapy/diagnostics/langmuir.py +++ b/src/plasmapy/diagnostics/langmuir.py @@ -23,6 +23,7 @@ import warnings import astropy.units as u +import matplotlib.pyplot as plt import numpy as np from astropy.constants import si as const from astropy.visualization import quantity_support @@ -200,8 +201,6 @@ def get_padded_limit(self, padding, log: bool = False): def plot(self) -> None: r"""Plot the characteristic in matplotlib.""" - import matplotlib.pyplot as plt - with quantity_support(): plt.figure() plt.scatter(self.bias.to(u.V), self.current.to(u.mA), marker=".", color="k") @@ -365,8 +364,6 @@ def swept_probe_analysis( # noqa: PLR0915 ) if visualize: - import matplotlib.pyplot as plt - with quantity_support(): fig, (ax1, ax2) = plt.subplots(2, 1) ax1.plot( @@ -975,8 +972,6 @@ def get_electron_temperature( T_e = np.array([T0, T0 + Delta_T]) * u.eV if visualize: - import matplotlib.pyplot as plt - with quantity_support(): plt.figure() @@ -1083,8 +1078,6 @@ def extrapolate_electron_current( ) if visualize: - import matplotlib.pyplot as plt - with quantity_support(): plt.figure() plt.scatter( @@ -1236,8 +1229,6 @@ def get_ion_density_OML( ) if visualize: - import matplotlib.pyplot as plt - with quantity_support(): plt.figure() plt.scatter( @@ -1303,8 +1294,6 @@ def extrapolate_ion_current_OML(probe_characteristic, fit, visualize: bool = Fal ion_characteristic = Characteristic(probe_characteristic.bias, ion_current) if visualize: - import matplotlib.pyplot as plt - with quantity_support(): plt.figure() plt.scatter( @@ -1398,8 +1387,6 @@ def get_EEDF(probe_characteristic, visualize: bool = False): probability = probability / integral if visualize: - import matplotlib.pyplot as plt - with quantity_support(): plt.figure() plt.semilogy(energy, probability, c="k") diff --git a/src/plasmapy/formulary/dimensionless.py b/src/plasmapy/formulary/dimensionless.py index d67d203bb5..065c0beb17 100644 --- a/src/plasmapy/formulary/dimensionless.py +++ b/src/plasmapy/formulary/dimensionless.py @@ -209,7 +209,7 @@ def Hall_parameter( >>> Hall_parameter(1e10 * u.m**-3, 2.8e2 * u.eV, 2.3 * u.T, "He-4 +1", "e-") """ - from plasmapy.formulary.collisions import ( + from plasmapy.formulary.collisions import ( # noqa: PLC0415 fundamental_electron_collision_freq, fundamental_ion_collision_freq, ) diff --git a/src/plasmapy/formulary/relativity.py b/src/plasmapy/formulary/relativity.py index ca82656871..f47eaae7d6 100644 --- a/src/plasmapy/formulary/relativity.py +++ b/src/plasmapy/formulary/relativity.py @@ -533,3 +533,6 @@ def __eq__(self, other) -> bool: if self_value != other_value: return False return True + + def __hash__(self) -> int: + return hash(repr(self)) diff --git a/src/plasmapy/particles/ionization_state.py b/src/plasmapy/particles/ionization_state.py index ff58214245..b31f9e92e3 100644 --- a/src/plasmapy/particles/ionization_state.py +++ b/src/plasmapy/particles/ionization_state.py @@ -101,6 +101,9 @@ def __repr__(self) -> str: f"IonicLevel({self.ionic_symbol!r}, ionic_fraction={self.ionic_fraction})" ) + def __hash__(self) -> int: + return hash(repr(self)) + @property def ionic_symbol(self) -> str: """The symbol of the ion.""" @@ -698,7 +701,7 @@ def charge_numbers(self) -> np.ndarray: @property def Z_mean(self) -> np.float64: """Return the mean charge number.""" - if np.nan in self.ionic_fractions: + if np.nan in self.ionic_fractions: # noqa: PLW0177 raise ChargeError( "Z_mean cannot be found because no ionic fraction " f"information is available for {self.base_particle}." @@ -914,3 +917,6 @@ def summarize( for line in output: print(line) # noqa: T201 + + def __hash__(self) -> int: + return hash(repr(self)) diff --git a/src/plasmapy/particles/ionization_state_collection.py b/src/plasmapy/particles/ionization_state_collection.py index 531b071b2e..16e6e20efe 100644 --- a/src/plasmapy/particles/ionization_state_collection.py +++ b/src/plasmapy/particles/ionization_state_collection.py @@ -29,7 +29,7 @@ def _atomic_number_and_mass_number(p: ParticleLike): return p.atomic_number, p.mass_number if p.isotope else 0 -class IonizationStateCollection: +class IonizationStateCollection: # noqa: PLW1641 """ Describe the ionization state distributions of multiple elements or isotopes. diff --git a/src/plasmapy/particles/particle_class.py b/src/plasmapy/particles/particle_class.py index ed2b9c977f..7eb0411265 100644 --- a/src/plasmapy/particles/particle_class.py +++ b/src/plasmapy/particles/particle_class.py @@ -223,7 +223,9 @@ class AbstractPhysicalParticle(AbstractParticle): @property def _as_particle_list(self) -> ParticleList: # Avoid circular imports by importing here - from plasmapy.particles.particle_collections import ParticleList + from plasmapy.particles.particle_collections import ( # noqa: PLC0415 + ParticleList, + ) return ParticleList([self]) @@ -1592,7 +1594,7 @@ def isotopic_abundance(self) -> float: >>> D.isotopic_abundance 0.000115 """ - from plasmapy.particles.atomic import common_isotopes + from plasmapy.particles.atomic import common_isotopes # noqa: PLC0415 if not self.isotope or self.is_ion: raise InvalidIsotopeError(_category_errmsg(self.symbol, "isotope")) @@ -2130,7 +2132,7 @@ def _validate_parameter(obj: Any, can_be_negative: bool = True) -> np.float64: # TODO: Replace with validator? Use an equivalency between # coulombs and reals - if obj is None or obj is np.nan: + if obj is None or np.isnan(obj): return np.nan elif np.isinf(obj): return obj diff --git a/src/plasmapy/particles/particle_collections.py b/src/plasmapy/particles/particle_collections.py index a3b03662a9..2aada0f1f4 100644 --- a/src/plasmapy/particles/particle_collections.py +++ b/src/plasmapy/particles/particle_collections.py @@ -223,7 +223,7 @@ def __repr__(self) -> str: return f"ParticleList({self.symbols!r})" def __gt__(self, other): - from plasmapy.particles.nuclear import nuclear_reaction_energy + from plasmapy.particles.nuclear import nuclear_reaction_energy # noqa: PLC0415 other_as_particle_list = self._cast_other_as_particle_list(other) return nuclear_reaction_energy( diff --git a/tests/analysis/swept_langmuir/test_floating_potential.py b/tests/analysis/swept_langmuir/test_floating_potential.py index b330ebb8f3..e07ce67658 100644 --- a/tests/analysis/swept_langmuir/test_floating_potential.py +++ b/tests/analysis/swept_langmuir/test_floating_potential.py @@ -212,7 +212,8 @@ def test_warnings(self, kwargs, expected, _warning) -> None: """Test scenarios that issue warnings.""" with pytest.warns(_warning): vf, extras = find_floating_potential(**kwargs) - assert isinstance(extras, VFExtras) + + assert isinstance(extras, VFExtras) for key, val in expected.items(): rtn_val = vf if key == "vf" else getattr(extras, key) diff --git a/tests/analysis/test_fit_functions.py b/tests/analysis/test_fit_functions.py index 23e3d0bd82..09a47ef8f1 100644 --- a/tests/analysis/test_fit_functions.py +++ b/tests/analysis/test_fit_functions.py @@ -529,8 +529,8 @@ def test_root_solve(self) -> None: ff_obj.params = (3.0, 0.5, 5.0) with pytest.warns(RuntimeWarning, match="invalid value encountered in log"): root, err = ff_obj.root_solve() - assert np.isnan(root) - assert np.isnan(err) + assert np.isnan(root) + assert np.isnan(err) class TestFFLinear(BaseFFTests): diff --git a/tests/diagnostics/charged_particle_radiography/test_synthetic_radiography.py b/tests/diagnostics/charged_particle_radiography/test_synthetic_radiography.py index 6353ccb36f..aef188e678 100644 --- a/tests/diagnostics/charged_particle_radiography/test_synthetic_radiography.py +++ b/tests/diagnostics/charged_particle_radiography/test_synthetic_radiography.py @@ -367,10 +367,11 @@ def test_input_validation() -> None: # Choose a very small synthetic radiograph size that misses most of the # particles + size = np.array([[-1, 1], [-1, 1]]) * 1 * u.mm + with pytest.warns( RuntimeWarning, match="of the particles are shown on this synthetic radiograph." ): - size = np.array([[-1, 1], [-1, 1]]) * 1 * u.mm hax, vax, values = cpr.synthetic_radiograph(sim, size=size) diff --git a/tests/formulary/collisions/test_collisions_dimensionless.py b/tests/formulary/collisions/test_collisions_dimensionless.py index e9b9511ad3..42d6f1049a 100644 --- a/tests/formulary/collisions/test_collisions_dimensionless.py +++ b/tests/formulary/collisions/test_collisions_dimensionless.py @@ -132,6 +132,8 @@ def setup_class(cls) -> None: def test_symmetry(self) -> None: with pytest.warns(CouplingWarning): result = Knudsen_number(self.length, self.T, self.n_e, self.particles) + + with pytest.warns(CouplingWarning): resultRev = Knudsen_number( self.length, self.T, self.n_e, self.particles[::-1] ) diff --git a/tests/formulary/collisions/test_collisions_frequencies.py b/tests/formulary/collisions/test_collisions_frequencies.py index 338fc32e08..9d9489aa12 100644 --- a/tests/formulary/collisions/test_collisions_frequencies.py +++ b/tests/formulary/collisions/test_collisions_frequencies.py @@ -726,6 +726,7 @@ def setup_class(cls) -> None: def test_symmetry(self) -> None: with pytest.warns(CouplingWarning): result = collision_frequency(self.T, self.n, self.particles) + with pytest.warns(CouplingWarning): resultRev = collision_frequency(self.T, self.n, self.particles[::-1]) assert result == resultRev diff --git a/tests/formulary/collisions/test_collisions_lengths.py b/tests/formulary/collisions/test_collisions_lengths.py index 21c0a88e24..6b2494d06d 100644 --- a/tests/formulary/collisions/test_collisions_lengths.py +++ b/tests/formulary/collisions/test_collisions_lengths.py @@ -204,7 +204,7 @@ def setup_class(cls) -> None: cls.True1 = 4.4047571877932046e-07 def test_symmetry(self) -> None: - with pytest.warns(CouplingWarning): + with pytest.warns(CouplingWarning): # noqa: PT031 result = lengths.mean_free_path(self.T, self.n_e, self.particles) resultRev = lengths.mean_free_path(self.T, self.n_e, self.particles[::-1]) assert result == resultRev diff --git a/tests/formulary/collisions/test_collisions_misc.py b/tests/formulary/collisions/test_collisions_misc.py index 4d9ebc76f9..2240273ca0 100644 --- a/tests/formulary/collisions/test_collisions_misc.py +++ b/tests/formulary/collisions/test_collisions_misc.py @@ -149,7 +149,7 @@ def setup_class(cls) -> None: cls.True_zmean = 0.32665227217687254 def test_symmetry(self) -> None: - with pytest.warns(CouplingWarning): + with pytest.warns(CouplingWarning): # noqa: PT031 result = mobility(self.T, self.n_e, self.particles) resultRev = mobility(self.T, self.n_e, self.particles[::-1]) assert result == resultRev diff --git a/tests/formulary/test_lengths.py b/tests/formulary/test_lengths.py index 15a0a3f94d..16fbecaf26 100644 --- a/tests/formulary/test_lengths.py +++ b/tests/formulary/test_lengths.py @@ -332,8 +332,8 @@ def test_values(self, args, kwargs, expected, atol) -> None: def test_warns(self, args, kwargs, expected, _warns) -> None: with pytest.warns(_warns): rc = gyroradius(*args, **kwargs) - if expected is not None: - assert np.allclose(rc, expected) + if expected is not None: + assert np.allclose(rc, expected) def test_keeps_arguments_unchanged(self) -> None: Vperp1 = u.Quantity([np.nan, 1], unit=u.m / u.s) @@ -390,9 +390,7 @@ def test_inertial_length() -> None: with pytest.warns(u.UnitsWarning): inertial_length_no_units = inertial_length(1e19, particle="p+") - assert inertial_length_no_units == inertial_length( - 1e19 * u.m**-3, particle="p+" - ) + assert inertial_length_no_units == inertial_length(1e19 * u.m**-3, particle="p+") assert inertial_length(n_e, "e-").unit.is_equivalent(u.m) diff --git a/tests/formulary/test_plasma_frequency.py b/tests/formulary/test_plasma_frequency.py index f6d4a714c6..e852aeb81a 100644 --- a/tests/formulary/test_plasma_frequency.py +++ b/tests/formulary/test_plasma_frequency.py @@ -96,8 +96,8 @@ def test_warns(self, args, kwargs, _warning, expected) -> None: """ with pytest.warns(_warning): wp = plasma_frequency(*args, **kwargs) - assert isinstance(wp, u.Quantity) - assert wp.unit == u.rad / u.s + assert isinstance(wp, u.Quantity) + assert wp.unit == u.rad / u.s if expected is not None: assert np.allclose(wp, expected) diff --git a/tests/formulary/test_speeds.py b/tests/formulary/test_speeds.py index 13896435b8..164a6f0c20 100644 --- a/tests/formulary/test_speeds.py +++ b/tests/formulary/test_speeds.py @@ -108,7 +108,7 @@ def test_raises(self, args, kwargs, _error) -> None: ) def test_warns(self, args, kwargs, expected, isclose_kw, _warning) -> None: """Test scenarios that issue warnings""" - with pytest.warns(_warning): + with pytest.warns(_warning): # noqa: PT031 val = Alfven_speed(*args, **kwargs) assert isinstance(val, u.Quantity) assert val.unit == u.m / u.s @@ -331,7 +331,7 @@ def test_values(self, args, kwargs, expected, isclose_kw) -> None: ], ) def test_warns(self, kwargs1, kwargs2, _warning) -> None: - with pytest.warns(_warning): + with pytest.warns(_warning): # noqa: PT031 val = ion_sound_speed(**kwargs1) if kwargs2 != {}: val == ion_sound_speed(**kwargs2) # noqa: B015 diff --git a/tests/formulary/test_thermal_speed.py b/tests/formulary/test_thermal_speed.py index e45877fd13..3da0dbf9da 100644 --- a/tests/formulary/test_thermal_speed.py +++ b/tests/formulary/test_thermal_speed.py @@ -273,10 +273,10 @@ def test_warns(self, args, kwargs, _warning, expected) -> None: """Test scenarios where `thermal_speed` issues warnings.""" with pytest.warns(_warning): vth = thermal_speed(*args, **kwargs) - assert vth.unit == u.m / u.s + assert vth.unit == u.m / u.s - if expected is not None: - assert vth == expected + if expected is not None: + assert vth == expected def test_electron_vs_proton(self) -> None: """ @@ -397,8 +397,7 @@ def test_mean1(self) -> None: ) assert np.isclose(known1.value, self.mean1True, rtol=1e-8, atol=0.0), errstr - def test_handle_nparrays(self, kwargs=None) -> None: + def test_handle_nparrays(self) -> None: """Test for ability to handle numpy array quantities""" - if kwargs is None: - kwargs = {"kappa": 2} + kwargs = {"kappa": 2} assert_can_handle_nparray(kappa_thermal_speed, kwargs=kwargs) diff --git a/tests/particles/test_parsing.py b/tests/particles/test_parsing.py index 632713931b..4e14b7b09b 100644 --- a/tests/particles/test_parsing.py +++ b/tests/particles/test_parsing.py @@ -356,11 +356,11 @@ def test_parse_InvalidElementErrors(particle) -> None: @pytest.mark.parametrize(("arg", "kwargs", "num_warnings"), atomic_warnings_table) -def test_parse_AtomicWarnings(arg, kwargs, num_warnings: int) -> None: - r"""Tests that _parse_and_check_atomic_input issues an AtomicWarning +def test_parse_ParticleWarnings(arg, kwargs, num_warnings: int) -> None: + r"""Tests that _parse_and_check_atomic_input issues a ParticleWarning under the required conditions.""" - with pytest.warns(ParticleWarning) as record: + with pytest.warns(ParticleWarning) as record: # noqa: PT031 parse_and_check_atomic_input(arg, **kwargs) if not record: pytest.fail( diff --git a/tests/particles/test_particle_class.py b/tests/particles/test_particle_class.py index fa3661dc53..0d0400a47e 100644 --- a/tests/particles/test_particle_class.py +++ b/tests/particles/test_particle_class.py @@ -664,7 +664,7 @@ def test_Particle_warnings(arg, kwargs, attribute, warning) -> None: Test that the appropriate warnings are issued during the creation and use of a `~plasmapy.particles.Particle` object. """ - with pytest.warns(warning) as record: + with pytest.warns(warning) as record: # noqa: PT031 exec(f"Particle(arg, **kwargs){attribute}") # noqa: S102 if not record: pytest.fail( @@ -1666,7 +1666,7 @@ def test_undefined_electron_binding_energy() -> None: def test_warning_on_use_of_binding_energy() -> None: - with pytest.warns(FutureWarning): + with pytest.warns(FutureWarning): # noqa: PT031 particle = Particle("n") assert particle.binding_energy == particle.nuclear_binding_energy diff --git a/tests/plasma/sources/test_plasmablob.py b/tests/plasma/sources/test_plasmablob.py index 08159b9d34..914cdcc0e8 100644 --- a/tests/plasma/sources/test_plasmablob.py +++ b/tests/plasma/sources/test_plasmablob.py @@ -195,7 +195,7 @@ def test_weakly_coupled(self) -> None: n_e = 1e15 * u.cm**-3 Z = 2.5 * u.dimensionless_unscaled particle = "p+" - with pytest.warns( + with pytest.warns( # noqa: PT031 CouplingWarning, match="you might have strong coupling effects" ): blob = plasmablob.PlasmaBlob(T_e=T_e, n_e=n_e, Z=Z, particle=particle) diff --git a/tests/plasma/test_grids.py b/tests/plasma/test_grids.py index 983fb966bd..e00561eec2 100644 --- a/tests/plasma/test_grids.py +++ b/tests/plasma/test_grids.py @@ -3,6 +3,7 @@ """ import astropy.units as u +import matplotlib.pyplot as plt import numpy as np import pytest from astropy.tests.helper import assert_quantity_allclose @@ -1010,7 +1011,6 @@ def debug_volume_avg_interpolator() -> None: Plot the comparison of the nearest neighbor interpolator and volume averaged interpolator for `~plasmapy.plasma.grids.CartesianGrid`. """ - import matplotlib.pyplot as plt grid = grids.CartesianGrid(-1 * u.cm, 1 * u.cm, num=24) diff --git a/uv.lock b/uv.lock index 4463d5c009..8b8a881727 100644 --- a/uv.lock +++ b/uv.lock @@ -657,15 +657,15 @@ wheels = [ [[package]] name = "hypothesis" -version = "6.135.31" +version = "6.135.32" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "attrs" }, { name = "sortedcontainers" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/22/2c/988c75a27f805ce53ef5a3feaf96add76fe93aede509e16126408c426a0d/hypothesis-6.135.31.tar.gz", hash = "sha256:a759a6010a43424b66b634383a04717a30ed05f553cc51e3b3fe3931faace53a", size = 455774, upload-time = "2025-07-15T02:04:18.988Z" } +sdist = { url = "https://files.pythonhosted.org/packages/fa/1a/5b0a64bcbbf642ecc4697d89b762ed62481a7dd36e5f5cbf93f29043b1e9/hypothesis-6.135.32.tar.gz", hash = "sha256:b74019dc58065d806abea6292008a392bc9326b88d6a46c8cce51c9cd485af42", size = 456414, upload-time = "2025-07-15T23:36:41.986Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/08/f6/3a9ad54d87c3bc5d4fe4925b0eb5d93c5e3090cf6fe8472176651ce04eea/hypothesis-6.135.31-py3-none-any.whl", hash = "sha256:12f1cf4aa961884b71021ef8770d81045f66c0b3f4295abc956e4f84d862f321", size = 522768, upload-time = "2025-07-15T02:04:15.919Z" }, + { url = "https://files.pythonhosted.org/packages/0a/06/e430a4134be021e1965473804409584ddf9b6a42906d360b9c75d3c35c79/hypothesis-6.135.32-py3-none-any.whl", hash = "sha256:d0f2bf93863f19a7af2510685dde2b89efb94eaebd3ca0b86c548cd8daa33ab0", size = 523424, upload-time = "2025-07-15T23:36:37.601Z" }, ] [[package]] From 92af72fdfbb9e657de5a5617d3ab98e7ed9a95c4 Mon Sep 17 00:00:00 2001 From: Nick Murphy Date: Tue, 15 Jul 2025 20:08:39 -0400 Subject: [PATCH 375/521] Add a security policy and mechanisms to report security vulnerabilities (#2985) * Add template for security issues * Minor updates to issue template * Add initial security policy * pre-commit run --all-files * Apply pre-commit fixes * Add security rules to labeler.yml * Edit changelog: 2985.internal.rst * Discuss finding vulnerabilities via CI * pre-commit run --all-files * Link to security policy from coding guide * Add link to privately report security vulnerabilities * Update .github/SECURITY.md * Remove security issue template Instead, use GitHub's private security reporting. * Update security policy regarding private reporting * Update labeler * Edit changelog: 2985.internal.rst * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update .github/SECURITY.md * Add breadcrumbs to comment in SECURITY.md --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .github/SECURITY.md | 46 ++++++++++++++++++++++++++++++ .github/labeler.yml | 8 ++++++ changelog/2985.internal.rst | 1 + docs/contributing/coding_guide.rst | 9 ++++++ 4 files changed, 64 insertions(+) create mode 100644 .github/SECURITY.md create mode 100644 changelog/2985.internal.rst diff --git a/.github/SECURITY.md b/.github/SECURITY.md new file mode 100644 index 0000000000..efe5624b9b --- /dev/null +++ b/.github/SECURITY.md @@ -0,0 +1,46 @@ +# PlasmaPy Security Policy + + + +## Supported versions + +Security updates will only be provided for the most recent release of PlasmaPy. + +| Version | Supported | +| ------- | --------- | +| latest | ✅ | +| older | ❌ | + +## Reporting security vulnerabilities + +Please use this link to [privately report a security vulnerability]. + +## Finding security vulnerabilities via continuous integration + +PlasmaPy has an extensive suite of continuous integration checks, +including several that identify and flag common security vulnerabilities. + +- [`zizmor`] finds security vulnerabilities in the GitHub workflows. +- [`ruff`] has several [rule sets] that find security vulnerabilities, + including the [`flake8-bandit` rule set]. + +The checks are usually either run as [`pre-commit`] hooks +(defined in [`.pre-commit-config.yaml`]) +or as [Nox] sessions (defined in [`noxfile.py`]) +invoked during GitHub workflows (located in [`.github/workflows/`]). +The configurations for most of these tools are located in [`pyproject.toml`], +but some have a dedicated configuration file +(for `zizmor`, this would be at [`.github/zizmor.yml`]) + +[nox]: https://nox.thea.codes +[privately report a security vulnerability]: https://github.com/plasmapy/plasmapy/security/advisories/new +[rule sets]: https://docs.astral.sh/ruff/rules +[`.github/workflows/`]: https://github.com/PlasmaPy/PlasmaPy/tree/main/.github/workflows +[`.github/zizmor.yml`]: https://github.com/PlasmaPy/PlasmaPy/blob/main/.github/zizmor.yml +[`.pre-commit-config.yaml`]: https://github.com/PlasmaPy/PlasmaPy/blob/main/.pre-commit-config.yaml +[`flake8-bandit` rule set]: https://docs.astral.sh/ruff/rules/#flake8-bandit-s +[`noxfile.py`]: https://github.com/PlasmaPy/PlasmaPy/blob/main/noxfile.py +[`pre-commit`]: https://pre-commit.com/ +[`pyproject.toml`]: https://github.com/PlasmaPy/PlasmaPy/blob/main/pyproject.toml +[`ruff`]: https://docs.astral.sh/ruff +[`zizmor`]: https://github.com/woodruffw/zizmor diff --git a/.github/labeler.yml b/.github/labeler.yml index 327552ff7b..3e53fcf664 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -104,6 +104,14 @@ maintenance: 'licenses/**', ] +security: + - changed-files: + - any-glob-to-any-file: [ + '**/*security*', + '**/*SECURITY*', + '**/*zizmor*', + ] + notebooks: - changed-files: - any-glob-to-any-file: [ diff --git a/changelog/2985.internal.rst b/changelog/2985.internal.rst new file mode 100644 index 0000000000..6f020ed08a --- /dev/null +++ b/changelog/2985.internal.rst @@ -0,0 +1 @@ +Added a security policy at :file:`.github/SECURITY.md` and enabled private security reporting through GitHub. diff --git a/docs/contributing/coding_guide.rst b/docs/contributing/coding_guide.rst index efad7ce738..a227ce5c07 100644 --- a/docs/contributing/coding_guide.rst +++ b/docs/contributing/coding_guide.rst @@ -1059,6 +1059,13 @@ an angular frequency to get a length scale: .. _performing releases: +Security policy +=============== + +PlasmaPy's `security policy`_ is located at :file:`.github/SECURITY.md`. +The GitHub repository has a link to +`privately report security vulnerabilities`_. + Performing releases =================== @@ -1103,10 +1110,12 @@ The overall process of performing a release is: .. _NEP 29: https://numpy.org/neps/nep-0029-deprecation_policy.html .. _not a number: https://en.wikipedia.org/wiki/NaN .. _NumPy Enhancement Proposal 29: https://numpy.org/neps/nep-0029-deprecation_policy.html +.. _privately report security vulnerabilities: https://github.com/PlasmaPy/PlasmaPy/security/advisories/new .. _Python Packaging User Guide: https://packaging.python.org .. _pyupgrade: https://github.com/asottile/pyupgrade .. _release checklist: https://github.com/PlasmaPy/PlasmaPy/blob/main/.github/content/release-checklist.md .. _rename refactoring in PyCharm: https://www.jetbrains.com/help/pycharm/rename-refactorings.html +.. _security policy: https://github.com/PlasmaPy/PlasmaPy/blob/main/.github/SECURITY.md .. _TOML: https://toml.io/en/v1.0.0 .. _type hints cheat sheet: https://mypy.readthedocs.io/en/stable/cheat_sheet_py3.html .. _update pinned requirements: https://github.com/PlasmaPy/PlasmaPy/actions/workflows/update-pinned-reqs.yml From 821cd59b21e442adf2638a0368691d2b902d2a0b Mon Sep 17 00:00:00 2001 From: "plasmapy-requirements-bot[bot]" <134649236+plasmapy-requirements-bot[bot]@users.noreply.github.com> Date: Thu, 17 Jul 2025 10:14:51 -0400 Subject: [PATCH 376/521] Update requirements with 'nox -s requirements' (#3053) Co-authored-by: namurphy <8931994+namurphy@users.noreply.github.com> --- uv.lock | 58 ++++++++++++++++++++++++++++----------------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/uv.lock b/uv.lock index 8b8a881727..ce4a74846c 100644 --- a/uv.lock +++ b/uv.lock @@ -589,35 +589,35 @@ wheels = [ [[package]] name = "fonttools" -version = "4.58.5" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/52/97/5735503e58d3816b0989955ef9b2df07e4c99b246469bd8b3823a14095da/fonttools-4.58.5.tar.gz", hash = "sha256:b2a35b0a19f1837284b3a23dd64fd7761b8911d50911ecd2bdbaf5b2d1b5df9c", size = 3526243, upload-time = "2025-07-03T14:04:47.736Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/14/50/26c683bf6f30dcbde6955c8e07ec6af23764aab86ff06b36383654ab6739/fonttools-4.58.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:cda226253bf14c559bc5a17c570d46abd70315c9a687d91c0e01147f87736182", size = 2769557, upload-time = "2025-07-03T14:03:35.383Z" }, - { url = "https://files.pythonhosted.org/packages/b1/00/c3c75fb6196b9ff9988e6a82319ae23f4ae7098e1c01e2408e58d2e7d9c7/fonttools-4.58.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:83a96e4a4e65efd6c098da549ec34f328f08963acd2d7bc910ceba01d2dc73e6", size = 2329367, upload-time = "2025-07-03T14:03:37.322Z" }, - { url = "https://files.pythonhosted.org/packages/59/e9/6946366c8e88650c199da9b284559de5d47a6e66ed6d175a166953347959/fonttools-4.58.5-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2d172b92dff59ef8929b4452d5a7b19b8e92081aa87bfb2d82b03b1ff14fc667", size = 5019491, upload-time = "2025-07-03T14:03:39.759Z" }, - { url = "https://files.pythonhosted.org/packages/76/12/2f3f7d09bba7a93bd48dcb54b170fba665f0b7e80e959ac831b907d40785/fonttools-4.58.5-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0bfddfd09aafbbfb3bd98ae67415fbe51eccd614c17db0c8844fe724fbc5d43d", size = 4961579, upload-time = "2025-07-03T14:03:41.611Z" }, - { url = "https://files.pythonhosted.org/packages/2c/95/87e84071189e51c714074646dfac8275b2e9c6b2b118600529cc74f7451e/fonttools-4.58.5-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:cfde5045f1bc92ad11b4b7551807564045a1b38cb037eb3c2bc4e737cd3a8d0f", size = 4997792, upload-time = "2025-07-03T14:03:44.529Z" }, - { url = "https://files.pythonhosted.org/packages/73/47/5c4df7473ecbeb8aa4e01373e4f614ca33f53227fe13ae673c6d5ca99be7/fonttools-4.58.5-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:3515ac47a9a5ac025d2899d195198314023d89492340ba86e4ba79451f7518a8", size = 5109361, upload-time = "2025-07-03T14:03:46.693Z" }, - { url = "https://files.pythonhosted.org/packages/06/00/31406853c570210232b845e08e5a566e15495910790381566ffdbdc7f9a2/fonttools-4.58.5-cp311-cp311-win32.whl", hash = "sha256:9f7e2ab9c10b6811b4f12a0768661325a48e664ec0a0530232c1605896a598db", size = 2201369, upload-time = "2025-07-03T14:03:48.885Z" }, - { url = "https://files.pythonhosted.org/packages/c5/90/ac0facb57962cef53a5734d0be5d2f2936e55aa5c62647c38ca3497263d8/fonttools-4.58.5-cp311-cp311-win_amd64.whl", hash = "sha256:126c16ec4a672c9cb5c1c255dc438d15436b470afc8e9cac25a2d39dd2dc26eb", size = 2249021, upload-time = "2025-07-03T14:03:51.232Z" }, - { url = "https://files.pythonhosted.org/packages/d6/68/66b498ee66f3e7e92fd68476c2509508082b7f57d68c0cdb4b8573f44331/fonttools-4.58.5-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:c3af3fefaafb570a03051a0d6899b8374dcf8e6a4560e42575843aef33bdbad6", size = 2754751, upload-time = "2025-07-03T14:03:52.976Z" }, - { url = "https://files.pythonhosted.org/packages/f1/1e/edbc14b79290980c3944a1f43098624bc8965f534964aa03d52041f24cb4/fonttools-4.58.5-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:688137789dbd44e8757ad77b49a771539d8069195ffa9a8bcf18176e90bbd86d", size = 2322342, upload-time = "2025-07-03T14:03:54.957Z" }, - { url = "https://files.pythonhosted.org/packages/c1/d7/3c87cf147185d91c2e946460a5cf68c236427b4a23ab96793ccb7d8017c9/fonttools-4.58.5-cp312-cp312-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:2af65836cf84cd7cb882d0b353bdc73643a497ce23b7414c26499bb8128ca1af", size = 4897011, upload-time = "2025-07-03T14:03:56.829Z" }, - { url = "https://files.pythonhosted.org/packages/a0/d6/fbb44cc85d4195fe54356658bd9f934328b4f74ae14addd90b4b5558b5c9/fonttools-4.58.5-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d2d79cfeb456bf438cb9fb87437634d4d6f228f27572ca5c5355e58472d5519d", size = 4942291, upload-time = "2025-07-03T14:03:59.204Z" }, - { url = "https://files.pythonhosted.org/packages/4d/c8/453f82e21aedf25cdc2ae619c03a73512398cec9bd8b6c3b1c571e0b6632/fonttools-4.58.5-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:0feac9dda9a48a7a342a593f35d50a5cee2dbd27a03a4c4a5192834a4853b204", size = 4886824, upload-time = "2025-07-03T14:04:01.517Z" }, - { url = "https://files.pythonhosted.org/packages/40/54/e9190001b8e22d123f78925b2f508c866d9d18531694b979277ad45d59b0/fonttools-4.58.5-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:36555230e168511e83ad8637232268649634b8dfff6ef58f46e1ebc057a041ad", size = 5038510, upload-time = "2025-07-03T14:04:03.917Z" }, - { url = "https://files.pythonhosted.org/packages/cf/9c/07cdad4774841a6304aabae939f8cbb9538cb1d8e97f5016b334da98e73a/fonttools-4.58.5-cp312-cp312-win32.whl", hash = "sha256:26ec05319353842d127bd02516eacb25b97ca83966e40e9ad6fab85cab0576f4", size = 2188459, upload-time = "2025-07-03T14:04:06.103Z" }, - { url = "https://files.pythonhosted.org/packages/0e/4d/1eaaad22781d55f49d1b184563842172aeb6a4fe53c029e503be81114314/fonttools-4.58.5-cp312-cp312-win_amd64.whl", hash = "sha256:778a632e538f82c1920579c0c01566a8f83dc24470c96efbf2fbac698907f569", size = 2236565, upload-time = "2025-07-03T14:04:08.27Z" }, - { url = "https://files.pythonhosted.org/packages/3a/ee/764dd8b99891f815241f449345863cfed9e546923d9cef463f37fd1d7168/fonttools-4.58.5-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:f4b6f1360da13cecc88c0d60716145b31e1015fbe6a59e32f73a4404e2ea92cf", size = 2745867, upload-time = "2025-07-03T14:04:10.586Z" }, - { url = "https://files.pythonhosted.org/packages/e2/23/8fef484c02fef55e226dfeac4339a015c5480b6a496064058491759ac71e/fonttools-4.58.5-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:4a036822e915692aa2c03e2decc60f49a8190f8111b639c947a4f4e5774d0d7a", size = 2317933, upload-time = "2025-07-03T14:04:12.335Z" }, - { url = "https://files.pythonhosted.org/packages/ab/47/f92b135864fa777e11ad68420bf89446c91a572fe2782745586f8e6aac0c/fonttools-4.58.5-cp313-cp313-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:a6d7709fcf4577b0f294ee6327088884ca95046e1eccde87c53bbba4d5008541", size = 4877844, upload-time = "2025-07-03T14:04:14.58Z" }, - { url = "https://files.pythonhosted.org/packages/3e/65/6c1a83511d8ac32411930495645edb3f8dfabebcb78f08cf6009ba2585ec/fonttools-4.58.5-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b9b5099ca99b79d6d67162778b1b1616fc0e1de02c1a178248a0da8d78a33852", size = 4940106, upload-time = "2025-07-03T14:04:16.563Z" }, - { url = "https://files.pythonhosted.org/packages/fa/90/df8eb77d6cf266cbbba01866a1349a3e9121e0a63002cf8d6754e994f755/fonttools-4.58.5-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:3f2c05a8d82a4d15aebfdb3506e90793aea16e0302cec385134dd960647a36c0", size = 4879458, upload-time = "2025-07-03T14:04:19.584Z" }, - { url = "https://files.pythonhosted.org/packages/26/b1/e32f8de51b7afcfea6ad62780da2fa73212c43a32cd8cafcc852189d7949/fonttools-4.58.5-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:79f0c4b1cc63839b61deeac646d8dba46f8ed40332c2ac1b9997281462c2e4ba", size = 5021917, upload-time = "2025-07-03T14:04:21.736Z" }, - { url = "https://files.pythonhosted.org/packages/89/72/578aa7fe32918dd763c62f447aaed672d665ee10e3eeb1725f4d6493fe96/fonttools-4.58.5-cp313-cp313-win32.whl", hash = "sha256:a1a9a2c462760976882131cbab7d63407813413a2d32cd699e86a1ff22bf7aa5", size = 2186827, upload-time = "2025-07-03T14:04:24.237Z" }, - { url = "https://files.pythonhosted.org/packages/71/a3/21e921b16cb9c029d3308e0cb79c9a937e9ff1fc1ee28c2419f0957b9e7c/fonttools-4.58.5-cp313-cp313-win_amd64.whl", hash = "sha256:bca61b14031a4b7dc87e14bf6ca34c275f8e4b9f7a37bc2fe746b532a924cf30", size = 2235706, upload-time = "2025-07-03T14:04:26.082Z" }, - { url = "https://files.pythonhosted.org/packages/d7/d4/1d85a1996b6188cd2713230e002d79a6f3a289bb17cef600cba385848b72/fonttools-4.58.5-py3-none-any.whl", hash = "sha256:e48a487ed24d9b611c5c4b25db1e50e69e9854ca2670e39a3486ffcd98863ec4", size = 1115318, upload-time = "2025-07-03T14:04:45.378Z" }, +version = "4.59.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/8a/27/ec3c723bfdf86f34c5c82bf6305df3e0f0d8ea798d2d3a7cb0c0a866d286/fonttools-4.59.0.tar.gz", hash = "sha256:be392ec3529e2f57faa28709d60723a763904f71a2b63aabe14fee6648fe3b14", size = 3532521, upload-time = "2025-07-16T12:04:54.613Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/06/96/520733d9602fa1bf6592e5354c6721ac6fc9ea72bc98d112d0c38b967199/fonttools-4.59.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:841b2186adce48903c0fef235421ae21549020eca942c1da773ac380b056ab3c", size = 2782387, upload-time = "2025-07-16T12:03:51.424Z" }, + { url = "https://files.pythonhosted.org/packages/87/6a/170fce30b9bce69077d8eec9bea2cfd9f7995e8911c71be905e2eba6368b/fonttools-4.59.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:9bcc1e77fbd1609198966ded6b2a9897bd6c6bcbd2287a2fc7d75f1a254179c5", size = 2342194, upload-time = "2025-07-16T12:03:53.295Z" }, + { url = "https://files.pythonhosted.org/packages/b0/b6/7c8166c0066856f1408092f7968ac744060cf72ca53aec9036106f57eeca/fonttools-4.59.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:37c377f7cb2ab2eca8a0b319c68146d34a339792f9420fca6cd49cf28d370705", size = 5032333, upload-time = "2025-07-16T12:03:55.177Z" }, + { url = "https://files.pythonhosted.org/packages/eb/0c/707c5a19598eafcafd489b73c4cb1c142102d6197e872f531512d084aa76/fonttools-4.59.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:fa39475eaccb98f9199eccfda4298abaf35ae0caec676ffc25b3a5e224044464", size = 4974422, upload-time = "2025-07-16T12:03:57.406Z" }, + { url = "https://files.pythonhosted.org/packages/f6/e7/6d33737d9fe632a0f59289b6f9743a86d2a9d0673de2a0c38c0f54729822/fonttools-4.59.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d3972b13148c1d1fbc092b27678a33b3080d1ac0ca305742b0119b75f9e87e38", size = 5010631, upload-time = "2025-07-16T12:03:59.449Z" }, + { url = "https://files.pythonhosted.org/packages/63/e1/a4c3d089ab034a578820c8f2dff21ef60daf9668034a1e4fb38bb1cc3398/fonttools-4.59.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a408c3c51358c89b29cfa5317cf11518b7ce5de1717abb55c5ae2d2921027de6", size = 5122198, upload-time = "2025-07-16T12:04:01.542Z" }, + { url = "https://files.pythonhosted.org/packages/09/77/ca82b9c12fa4de3c520b7760ee61787640cf3fde55ef1b0bfe1de38c8153/fonttools-4.59.0-cp311-cp311-win32.whl", hash = "sha256:6770d7da00f358183d8fd5c4615436189e4f683bdb6affb02cad3d221d7bb757", size = 2214216, upload-time = "2025-07-16T12:04:03.515Z" }, + { url = "https://files.pythonhosted.org/packages/ab/25/5aa7ca24b560b2f00f260acf32c4cf29d7aaf8656e159a336111c18bc345/fonttools-4.59.0-cp311-cp311-win_amd64.whl", hash = "sha256:84fc186980231a287b28560d3123bd255d3c6b6659828c642b4cf961e2b923d0", size = 2261879, upload-time = "2025-07-16T12:04:05.015Z" }, + { url = "https://files.pythonhosted.org/packages/e2/77/b1c8af22f4265e951cd2e5535dbef8859efcef4fb8dee742d368c967cddb/fonttools-4.59.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:f9b3a78f69dcbd803cf2fb3f972779875b244c1115481dfbdd567b2c22b31f6b", size = 2767562, upload-time = "2025-07-16T12:04:06.895Z" }, + { url = "https://files.pythonhosted.org/packages/ff/5a/aeb975699588176bb357e8b398dfd27e5d3a2230d92b81ab8cbb6187358d/fonttools-4.59.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:57bb7e26928573ee7c6504f54c05860d867fd35e675769f3ce01b52af38d48e2", size = 2335168, upload-time = "2025-07-16T12:04:08.695Z" }, + { url = "https://files.pythonhosted.org/packages/54/97/c6101a7e60ae138c4ef75b22434373a0da50a707dad523dd19a4889315bf/fonttools-4.59.0-cp312-cp312-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:4536f2695fe5c1ffb528d84a35a7d3967e5558d2af58b4775e7ab1449d65767b", size = 4909850, upload-time = "2025-07-16T12:04:10.761Z" }, + { url = "https://files.pythonhosted.org/packages/bd/6c/fa4d18d641054f7bff878cbea14aa9433f292b9057cb1700d8e91a4d5f4f/fonttools-4.59.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:885bde7d26e5b40e15c47bd5def48b38cbd50830a65f98122a8fb90962af7cd1", size = 4955131, upload-time = "2025-07-16T12:04:12.846Z" }, + { url = "https://files.pythonhosted.org/packages/20/5c/331947fc1377deb928a69bde49f9003364f5115e5cbe351eea99e39412a2/fonttools-4.59.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6801aeddb6acb2c42eafa45bc1cb98ba236871ae6f33f31e984670b749a8e58e", size = 4899667, upload-time = "2025-07-16T12:04:14.558Z" }, + { url = "https://files.pythonhosted.org/packages/8a/46/b66469dfa26b8ff0baa7654b2cc7851206c6d57fe3abdabbaab22079a119/fonttools-4.59.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:31003b6a10f70742a63126b80863ab48175fb8272a18ca0846c0482968f0588e", size = 5051349, upload-time = "2025-07-16T12:04:16.388Z" }, + { url = "https://files.pythonhosted.org/packages/2e/05/ebfb6b1f3a4328ab69787d106a7d92ccde77ce66e98659df0f9e3f28d93d/fonttools-4.59.0-cp312-cp312-win32.whl", hash = "sha256:fbce6dae41b692a5973d0f2158f782b9ad05babc2c2019a970a1094a23909b1b", size = 2201315, upload-time = "2025-07-16T12:04:18.557Z" }, + { url = "https://files.pythonhosted.org/packages/09/45/d2bdc9ea20bbadec1016fd0db45696d573d7a26d95ab5174ffcb6d74340b/fonttools-4.59.0-cp312-cp312-win_amd64.whl", hash = "sha256:332bfe685d1ac58ca8d62b8d6c71c2e52a6c64bc218dc8f7825c9ea51385aa01", size = 2249408, upload-time = "2025-07-16T12:04:20.489Z" }, + { url = "https://files.pythonhosted.org/packages/f3/bb/390990e7c457d377b00890d9f96a3ca13ae2517efafb6609c1756e213ba4/fonttools-4.59.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:78813b49d749e1bb4db1c57f2d4d7e6db22c253cb0a86ad819f5dc197710d4b2", size = 2758704, upload-time = "2025-07-16T12:04:22.217Z" }, + { url = "https://files.pythonhosted.org/packages/df/6f/d730d9fcc9b410a11597092bd2eb9ca53e5438c6cb90e4b3047ce1b723e9/fonttools-4.59.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:401b1941ce37e78b8fd119b419b617277c65ae9417742a63282257434fd68ea2", size = 2330764, upload-time = "2025-07-16T12:04:23.985Z" }, + { url = "https://files.pythonhosted.org/packages/75/b4/b96bb66f6f8cc4669de44a158099b249c8159231d254ab6b092909388be5/fonttools-4.59.0-cp313-cp313-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:efd7e6660674e234e29937bc1481dceb7e0336bfae75b856b4fb272b5093c5d4", size = 4890699, upload-time = "2025-07-16T12:04:25.664Z" }, + { url = "https://files.pythonhosted.org/packages/b5/57/7969af50b26408be12baa317c6147588db5b38af2759e6df94554dbc5fdb/fonttools-4.59.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:51ab1ff33c19e336c02dee1e9fd1abd974a4ca3d8f7eef2a104d0816a241ce97", size = 4952934, upload-time = "2025-07-16T12:04:27.733Z" }, + { url = "https://files.pythonhosted.org/packages/d6/e2/dd968053b6cf1f46c904f5bd409b22341477c017d8201619a265e50762d3/fonttools-4.59.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a9bf8adc9e1f3012edc8f09b08336272aec0c55bc677422273e21280db748f7c", size = 4892319, upload-time = "2025-07-16T12:04:30.074Z" }, + { url = "https://files.pythonhosted.org/packages/6b/95/a59810d8eda09129f83467a4e58f84205dc6994ebaeb9815406363e07250/fonttools-4.59.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:37e01c6ec0c98599778c2e688350d624fa4770fbd6144551bd5e032f1199171c", size = 5034753, upload-time = "2025-07-16T12:04:32.292Z" }, + { url = "https://files.pythonhosted.org/packages/a5/84/51a69ee89ff8d1fea0c6997e946657e25a3f08513de8435fe124929f3eef/fonttools-4.59.0-cp313-cp313-win32.whl", hash = "sha256:70d6b3ceaa9cc5a6ac52884f3b3d9544e8e231e95b23f138bdb78e6d4dc0eae3", size = 2199688, upload-time = "2025-07-16T12:04:34.444Z" }, + { url = "https://files.pythonhosted.org/packages/a0/ee/f626cd372932d828508137a79b85167fdcf3adab2e3bed433f295c596c6a/fonttools-4.59.0-cp313-cp313-win_amd64.whl", hash = "sha256:26731739daa23b872643f0e4072d5939960237d540c35c14e6a06d47d71ca8fe", size = 2248560, upload-time = "2025-07-16T12:04:36.034Z" }, + { url = "https://files.pythonhosted.org/packages/d0/9c/df0ef2c51845a13043e5088f7bb988ca6cd5bb82d5d4203d6a158aa58cf2/fonttools-4.59.0-py3-none-any.whl", hash = "sha256:241313683afd3baacb32a6bd124d0bce7404bc5280e12e291bae1b9bba28711d", size = 1128050, upload-time = "2025-07-16T12:04:52.687Z" }, ] [[package]] From 9b3014e1ec145b8221bf4231699c446787f87598 Mon Sep 17 00:00:00 2001 From: "plasmapy-requirements-bot[bot]" <134649236+plasmapy-requirements-bot[bot]@users.noreply.github.com> Date: Thu, 24 Jul 2025 11:30:51 -0400 Subject: [PATCH 377/521] Update requirements with 'nox -s requirements' (#3054) Co-authored-by: namurphy <8931994+namurphy@users.noreply.github.com> --- uv.lock | 64 ++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 43 insertions(+), 21 deletions(-) diff --git a/uv.lock b/uv.lock index ce4a74846c..abcb99d9dd 100644 --- a/uv.lock +++ b/uv.lock @@ -140,11 +140,11 @@ wheels = [ [[package]] name = "astropy-iers-data" -version = "0.2025.7.14.0.40.29" +version = "0.2025.7.21.0.41.39" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/83/08/7e0be27f3748240e88ec86c7a01717163d5c92ef0bbbdf2f781903745bd8/astropy_iers_data-0.2025.7.14.0.40.29.tar.gz", hash = "sha256:2d2446eda1bb26a92b9235b67cee584f86e02afec27ad7a0edfc296e891dd820", size = 1902390, upload-time = "2025-07-14T00:41:11.052Z" } +sdist = { url = "https://files.pythonhosted.org/packages/87/7a/5d1094cf8fd37c8e79510a74d1a5e279b2180fb34e4233e6c941733d05e8/astropy_iers_data-0.2025.7.21.0.41.39.tar.gz", hash = "sha256:e482753c9d6979165be5a47e14a29650026579988a5f0656e52a962e07040a93", size = 1902919, upload-time = "2025-07-21T00:42:28.603Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/7b/82/6d548466803b15511841e473e9fed7a29cfbba98ffe653fd454fd46a878d/astropy_iers_data-0.2025.7.14.0.40.29-py3-none-any.whl", hash = "sha256:f5080ce17297328946deb11974a4eb0afdcba098764e622164f1acb9a796700a", size = 1957818, upload-time = "2025-07-14T00:41:09.431Z" }, + { url = "https://files.pythonhosted.org/packages/ca/b6/452abd866c18b18fb768d6b28ee9aaf9e24d2169e4e6b2945f85ad4bc2e6/astropy_iers_data-0.2025.7.21.0.41.39-py3-none-any.whl", hash = "sha256:1a5bbb3be6eb02c227ccc2549e22f322e64a5a6bc635b5baf34e214b28b621da", size = 1958365, upload-time = "2025-07-21T00:42:26.964Z" }, ] [[package]] @@ -535,11 +535,11 @@ wheels = [ [[package]] name = "distlib" -version = "0.3.9" +version = "0.4.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/0d/dd/1bec4c5ddb504ca60fc29472f3d27e8d4da1257a854e1d96742f15c1d02d/distlib-0.3.9.tar.gz", hash = "sha256:a60f20dea646b8a33f3e7772f74dc0b2d0772d2837ee1342a00645c81edf9403", size = 613923, upload-time = "2024-10-09T18:35:47.551Z" } +sdist = { url = "https://files.pythonhosted.org/packages/96/8e/709914eb2b5749865801041647dc7f4e6d00b549cfe88b65ca192995f07c/distlib-0.4.0.tar.gz", hash = "sha256:feec40075be03a04501a973d81f633735b4b69f98b05450592310c0f401a4e0d", size = 614605, upload-time = "2025-07-17T16:52:00.465Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/91/a1/cf2472db20f7ce4a6be1253a81cfdf85ad9c7885ffbed7047fb72c24cf87/distlib-0.3.9-py2.py3-none-any.whl", hash = "sha256:47f8c22fd27c27e25a65601af709b38e4f0a45ea4fc2e710f65755fa8caaaf87", size = 468973, upload-time = "2024-10-09T18:35:44.272Z" }, + { url = "https://files.pythonhosted.org/packages/33/6b/e0547afaf41bf2c42e52430072fa5658766e3d65bd4b03a563d1b6336f57/distlib-0.4.0-py2.py3-none-any.whl", hash = "sha256:9659f7d87e46584a30b5780e43ac7a2143098441670ff0a49d5f9034c54a6c16", size = 469047, upload-time = "2025-07-17T16:51:58.613Z" }, ] [[package]] @@ -657,15 +657,15 @@ wheels = [ [[package]] name = "hypothesis" -version = "6.135.32" +version = "6.136.3" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "attrs" }, { name = "sortedcontainers" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/fa/1a/5b0a64bcbbf642ecc4697d89b762ed62481a7dd36e5f5cbf93f29043b1e9/hypothesis-6.135.32.tar.gz", hash = "sha256:b74019dc58065d806abea6292008a392bc9326b88d6a46c8cce51c9cd485af42", size = 456414, upload-time = "2025-07-15T23:36:41.986Z" } +sdist = { url = "https://files.pythonhosted.org/packages/84/cd/714955a6ac2f4b786483a38f0b13e37e7efad37d23a2dc465b91a9fe2db0/hypothesis-6.136.3.tar.gz", hash = "sha256:89baa2bfc5af38f939e83b62f9f0e7e6407e81cade29cfcb3eafbc661177c2bd", size = 457758, upload-time = "2025-07-23T13:53:25.8Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/0a/06/e430a4134be021e1965473804409584ddf9b6a42906d360b9c75d3c35c79/hypothesis-6.135.32-py3-none-any.whl", hash = "sha256:d0f2bf93863f19a7af2510685dde2b89efb94eaebd3ca0b86c548cd8daa33ab0", size = 523424, upload-time = "2025-07-15T23:36:37.601Z" }, + { url = "https://files.pythonhosted.org/packages/f9/de/d2145a3c329751b13fcfddfe119e5ec72e263c2766d1f655dedc3ed33a0d/hypothesis-6.136.3-py3-none-any.whl", hash = "sha256:88163307c625688317bc5f3c7bd88f18b4d5c7cd773c784e3c4182eed2ae1b3d", size = 524703, upload-time = "2025-07-23T13:53:22.384Z" }, ] [[package]] @@ -697,7 +697,7 @@ wheels = [ [[package]] name = "ipykernel" -version = "6.29.5" +version = "6.30.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "appnope", marker = "sys_platform == 'darwin'" }, @@ -714,9 +714,9 @@ dependencies = [ { name = "tornado" }, { name = "traitlets" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/e9/5c/67594cb0c7055dc50814b21731c22a601101ea3b1b50a9a1b090e11f5d0f/ipykernel-6.29.5.tar.gz", hash = "sha256:f093a22c4a40f8828f8e330a9c297cb93dcab13bd9678ded6de8e5cf81c56215", size = 163367, upload-time = "2024-07-01T14:07:22.543Z" } +sdist = { url = "https://files.pythonhosted.org/packages/38/27/9e6e30ed92f2ac53d29f70b09da8b2dc456e256148e289678fa0e825f46a/ipykernel-6.30.0.tar.gz", hash = "sha256:b7b808ddb2d261aae2df3a26ff3ff810046e6de3dfbc6f7de8c98ea0a6cb632c", size = 165125, upload-time = "2025-07-21T10:36:09.259Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/94/5c/368ae6c01c7628438358e6d337c19b05425727fbb221d2a3c4303c372f42/ipykernel-6.29.5-py3-none-any.whl", hash = "sha256:afdb66ba5aa354b09b91379bac28ae4afebbb30e8b39510c9690afb7a10421b5", size = 117173, upload-time = "2024-07-01T14:07:19.603Z" }, + { url = "https://files.pythonhosted.org/packages/1f/3d/00813c3d9b46e3dcd88bd4530e0a3c63c0509e5d8c9eff34723ea243ab04/ipykernel-6.30.0-py3-none-any.whl", hash = "sha256:fd2936e55c4a1c2ee8b1e5fa6a372b8eecc0ab1338750dee76f48fa5cca1301e", size = 117264, upload-time = "2025-07-21T10:36:06.854Z" }, ] [[package]] @@ -825,7 +825,7 @@ wheels = [ [[package]] name = "jsonschema" -version = "4.24.0" +version = "4.25.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "attrs" }, @@ -833,9 +833,9 @@ dependencies = [ { name = "referencing" }, { name = "rpds-py" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/bf/d3/1cf5326b923a53515d8f3a2cd442e6d7e94fcc444716e879ea70a0ce3177/jsonschema-4.24.0.tar.gz", hash = "sha256:0b4e8069eb12aedfa881333004bccaec24ecef5a8a6a4b6df142b2cc9599d196", size = 353480, upload-time = "2025-05-26T18:48:10.459Z" } +sdist = { url = "https://files.pythonhosted.org/packages/d5/00/a297a868e9d0784450faa7365c2172a7d6110c763e30ba861867c32ae6a9/jsonschema-4.25.0.tar.gz", hash = "sha256:e63acf5c11762c0e6672ffb61482bdf57f0876684d8d249c0fe2d730d48bc55f", size = 356830, upload-time = "2025-07-18T15:39:45.11Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/a2/3d/023389198f69c722d039351050738d6755376c8fd343e91dc493ea485905/jsonschema-4.24.0-py3-none-any.whl", hash = "sha256:a462455f19f5faf404a7902952b6f0e3ce868f3ee09a359b05eca6673bd8412d", size = 88709, upload-time = "2025-05-26T18:48:08.417Z" }, + { url = "https://files.pythonhosted.org/packages/fe/54/c86cd8e011fe98803d7e382fd67c0df5ceab8d2b7ad8c5a81524f791551c/jsonschema-4.25.0-py3-none-any.whl", hash = "sha256:24c2e8da302de79c8b9382fee3e76b355e44d2a4364bb207159ce10b517bd716", size = 89184, upload-time = "2025-07-18T15:39:42.956Z" }, ] [package.optional-dependencies] @@ -846,6 +846,7 @@ format-nongpl = [ { name = "jsonpointer" }, { name = "rfc3339-validator" }, { name = "rfc3986-validator" }, + { name = "rfc3987-syntax" }, { name = "uri-template" }, { name = "webcolors" }, ] @@ -1056,6 +1057,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/4c/fa/be89a49c640930180657482a74970cdcf6f7072c8d2471e1babe17a222dc/kiwisolver-1.4.8-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:be4816dc51c8a471749d664161b434912eee82f2ea66bd7628bd14583a833e85", size = 2349213, upload-time = "2024-12-24T18:30:40.019Z" }, ] +[[package]] +name = "lark" +version = "1.2.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/af/60/bc7622aefb2aee1c0b4ba23c1446d3e30225c8770b38d7aedbfb65ca9d5a/lark-1.2.2.tar.gz", hash = "sha256:ca807d0162cd16cef15a8feecb862d7319e7a09bdb13aef927968e45040fed80", size = 252132, upload-time = "2024-08-13T19:49:00.652Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2d/00/d90b10b962b4277f5e64a78b6609968859ff86889f5b898c1a778c06ec00/lark-1.2.2-py3-none-any.whl", hash = "sha256:c2276486b02f0f1b90be155f2c8ba4a8e194d42775786db622faccd652d8e80c", size = 111036, upload-time = "2024-08-13T19:48:58.603Z" }, +] + [[package]] name = "latexcodec" version = "3.0.1" @@ -1067,7 +1077,7 @@ wheels = [ [[package]] name = "lmfit" -version = "1.3.3" +version = "1.3.4" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "asteval" }, @@ -1076,9 +1086,9 @@ dependencies = [ { name = "scipy" }, { name = "uncertainties" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/f9/c6/a8b4e4bc6b5a11c7b610083243505d6b693600f2a579b383f292776b1b8e/lmfit-1.3.3.tar.gz", hash = "sha256:73321e6b881f2f686235721a7dfc02af6bb0f030a25efeb66638f62b1c6053a1", size = 632645, upload-time = "2025-03-12T18:28:36.516Z" } +sdist = { url = "https://files.pythonhosted.org/packages/5a/e5/a35942aed2de95e228728c34609b51fe3ec9182398eac50d288eef313aa2/lmfit-1.3.4.tar.gz", hash = "sha256:3c22c28c43f717f6c5b4a3bd81e893a2149739c26a592c046f2e33c23cfbe497", size = 630720, upload-time = "2025-07-19T20:09:01.876Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/6a/e1/d5aeb89530550c7e797d3528225fa31012490e79c9df5cf72a0f07cc66d3/lmfit-1.3.3-py3-none-any.whl", hash = "sha256:a9e9ec7d0d0ec962cc6c078ad1ec6c8311d3ac0e5f0947a00a91f5509dacc2b2", size = 100241, upload-time = "2025-03-12T18:28:34.819Z" }, + { url = "https://files.pythonhosted.org/packages/38/7e/7b91c89a4cf0f543a83be978657afb20c86af6d725253e319589dcc4ce52/lmfit-1.3.4-py3-none-any.whl", hash = "sha256:afce1593b42324d37ae2908249b0c55445e2f4c1a0474ff706a8e2f7b5d949fa", size = 97662, upload-time = "2025-07-19T20:09:00.32Z" }, ] [[package]] @@ -2158,6 +2168,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/9e/51/17023c0f8f1869d8806b979a2bffa3f861f26a3f1a66b094288323fba52f/rfc3986_validator-0.1.1-py2.py3-none-any.whl", hash = "sha256:2f235c432ef459970b4306369336b9d5dbdda31b510ca1e327636e01f528bfa9", size = 4242, upload-time = "2019-10-28T16:00:13.976Z" }, ] +[[package]] +name = "rfc3987-syntax" +version = "1.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "lark" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/2c/06/37c1a5557acf449e8e406a830a05bf885ac47d33270aec454ef78675008d/rfc3987_syntax-1.1.0.tar.gz", hash = "sha256:717a62cbf33cffdd16dfa3a497d81ce48a660ea691b1ddd7be710c22f00b4a0d", size = 14239, upload-time = "2025-07-18T01:05:05.015Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7e/71/44ce230e1b7fadd372515a97e32a83011f906ddded8d03e3c6aafbdedbb7/rfc3987_syntax-1.1.0-py3-none-any.whl", hash = "sha256:6c3d97604e4c5ce9f714898e05401a0445a641cfa276432b0a648c80856f6a3f", size = 8046, upload-time = "2025-07-18T01:05:03.843Z" }, +] + [[package]] name = "roman-numerals-py" version = "3.1.0" @@ -2835,16 +2857,16 @@ wheels = [ [[package]] name = "virtualenv" -version = "20.31.2" +version = "20.32.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "distlib" }, { name = "filelock" }, { name = "platformdirs" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/56/2c/444f465fb2c65f40c3a104fd0c495184c4f2336d65baf398e3c75d72ea94/virtualenv-20.31.2.tar.gz", hash = "sha256:e10c0a9d02835e592521be48b332b6caee6887f332c111aa79a09b9e79efc2af", size = 6076316, upload-time = "2025-05-08T17:58:23.811Z" } +sdist = { url = "https://files.pythonhosted.org/packages/a9/96/0834f30fa08dca3738614e6a9d42752b6420ee94e58971d702118f7cfd30/virtualenv-20.32.0.tar.gz", hash = "sha256:886bf75cadfdc964674e6e33eb74d787dff31ca314ceace03ca5810620f4ecf0", size = 6076970, upload-time = "2025-07-21T04:09:50.985Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/f3/40/b1c265d4b2b62b58576588510fc4d1fe60a86319c8de99fd8e9fec617d2c/virtualenv-20.31.2-py3-none-any.whl", hash = "sha256:36efd0d9650ee985f0cad72065001e66d49a6f24eb44d98980f630686243cf11", size = 6057982, upload-time = "2025-05-08T17:58:21.15Z" }, + { url = "https://files.pythonhosted.org/packages/5c/c6/f8f28009920a736d0df434b52e9feebfb4d702ba942f15338cb4a83eafc1/virtualenv-20.32.0-py3-none-any.whl", hash = "sha256:2c310aecb62e5aa1b06103ed7c2977b81e042695de2697d01017ff0f1034af56", size = 6057761, upload-time = "2025-07-21T04:09:48.059Z" }, ] [[package]] From bdd996e8ddc788d5832d5fd3a527b710091bdf3a Mon Sep 17 00:00:00 2001 From: Nick Murphy Date: Tue, 29 Jul 2025 17:13:44 -0400 Subject: [PATCH 378/521] Fix hyperlinks in documentation (#3056) * Fix Anaconda hyperlinks * Update links in docs * Attempt to fix :wikipedia: role * Add doi to ignore * Update global substitutions * Sort lines * Push changes accidentally made in #3045 * Edit changelog: 3056.doc.rst --- changelog/3056.doc.rst | 1 + docs/_global_substitutions.py | 4 ++-- docs/conf.py | 7 +++++-- docs/contributing/coding_guide.rst | 2 +- docs/contributing/doc_guide.rst | 4 ++-- docs/contributing/getting_ready.rst | 12 ++++++------ docs/install.rst | 6 +++--- .../charged_particle_radiography_film_stacks.ipynb | 12 +++++------- docs/notebooks/getting_started/units.ipynb | 10 +++++----- src/plasmapy/formulary/laser.py | 2 +- 10 files changed, 31 insertions(+), 29 deletions(-) create mode 100644 changelog/3056.doc.rst diff --git a/changelog/3056.doc.rst b/changelog/3056.doc.rst new file mode 100644 index 0000000000..ba3c9eab98 --- /dev/null +++ b/changelog/3056.doc.rst @@ -0,0 +1 @@ +Fixed broken hyperlinks and permanent redirects. diff --git a/docs/_global_substitutions.py b/docs/_global_substitutions.py index 3e46625021..48a8d813ec 100644 --- a/docs/_global_substitutions.py +++ b/docs/_global_substitutions.py @@ -156,13 +156,13 @@ "pytest": "https://docs.pytest.org", "Python": "https://www.python.org", "Python's documentation": "https://docs.python.org/3", - "Read the Docs": "https://about.readthedocs.com/", + "Read the Docs": "https://about.readthedocs.com", "reStructuredText": "https://docutils.sourceforge.io/rst.html", "ruff": "https://docs.astral.sh/ruff", "SciPy": "https://scipy.org", "SPEC 0": "https://scientific-python.org/specs/spec-0000", "Sphinx": "https://www.sphinx-doc.org", - "static type checking": "https://realpython.com/lessons/python-type-checking-overview", + "static type checking": "https://realpython.com/videos/python-type-checking-overview", "towncrier": "https://github.com/twisted/towncrier", "type hint annotations": "https://peps.python.org/pep-0484", "xarray": "https://docs.xarray.dev", diff --git a/docs/conf.py b/docs/conf.py index 3ce914c994..4250d46211 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -396,6 +396,7 @@ r"https://doi\.org/10\.1371/journal\.pcbi\.1005510", r"https://doi\.org/10\.2172/5259641", r"https://doi\.org/10\.3847/1538-4357/accc32", + r"https://doi\.org/10\.5170/CERN-2016-001\.51", r"https://doi\.org/10\.5281/zenodo\.1436011", r"https://doi\.org/10\.5281/zenodo\.1460977", r"https://doi\.org/10\.5281/zenodo\.3406803", @@ -405,6 +406,8 @@ r"https://doi\.org/10\.5281/zenodo\.8015753", r"https://doi\.org/10\.18434/T4NC7P", r"https://github\.com/PlasmaPy/PlasmaPy/settings/secrets/actions", + r"https://www\.gnu\.org/software/make", + r"https://hdl\.handle\.net/10037/29416", r"https://orcid\.org/0000-0001-5050-6606", r"https://orcid\.org/0000-0001-5270-7487", r"https://orcid\.org/0000-0001-5308-6870", @@ -467,8 +470,8 @@ r"https://orcid\.org/0009-0008-3588-0497", r"https://orcid\.org/0009-0008-5134-6171", r"https://orcid\.org/0009-0009-9490-5284", - r"https://hdl\.handle\.net/10037/29416", - r"https://www\.iter\.org/", + r"https://www\.iter\.org", + r"https://www\.pppl\.gov", r"https://www\.sciencedirect\.com/book/9780123748775/.*", ] diff --git a/docs/contributing/coding_guide.rst b/docs/contributing/coding_guide.rst index a227ce5c07..1432156a08 100644 --- a/docs/contributing/coding_guide.rst +++ b/docs/contributing/coding_guide.rst @@ -1096,7 +1096,7 @@ The overall process of performing a release is: .. _ASCII: https://en.wikipedia.org/wiki/ASCII .. _autotyping: https://github.com/JelleZijlstra/autotyping -.. _cognitive complexity: https://docs.codeclimate.com/docs/cognitive-complexity +.. _cognitive complexity: https://getdx.com/blog/cognitive-complexity/ .. _create a release issue: https://github.com/PlasmaPy/PlasmaPy/actions/workflows/create-release-issue.yml .. _Cython: https://cython.org .. _equivalencies: https://docs.astropy.org/en/stable/units/equivalencies.html diff --git a/docs/contributing/doc_guide.rst b/docs/contributing/doc_guide.rst index a17d6c17b7..39e341172d 100644 --- a/docs/contributing/doc_guide.rst +++ b/docs/contributing/doc_guide.rst @@ -1594,7 +1594,7 @@ example Jupyter notebooks, the tables of contents are in .. _BibTeX: https://www.bibtex.org .. _BibTeX format: https://www.bibtex.com/g/bibtex-format .. _configuration options: https://www.sphinx-doc.org/en/master/usage/configuration.html -.. _CSS: https://www.w3schools.com:443/css +.. _CSS: http://www.w3schools.com/css/ .. _define substitutions: https://docutils.sourceforge.io/docs/ref/rst/restructuredtext.html#substitution-definitions .. _doctests: https://docs.pytest.org/en/6.2.x/doctest.html .. _full list of emoji codes: https://sphinxemojicodes.readthedocs.io/en/stable/#supported-codes @@ -1623,7 +1623,7 @@ example Jupyter notebooks, the tables of contents are in .. _sphinx-codeautolink: https://sphinx-codeautolink.readthedocs.io .. _Sphinx's glossary: https://www.sphinx-doc.org/en/master/glossary.html .. _Sphinx's templating page: https://www.sphinx-doc.org/en/master/development/templating.html -.. _style overrides: https://docs.readthedocs.io/en/stable/guides/adding-custom-css.html +.. _style overrides: https://docs.readthedocs.com/platform/stable/guides/adding-custom-css.html .. _toctree: https://www.sphinx-doc.org/en/master/usage/restructuredtext/directives.html#table-of-contents .. _warns: https://numpydoc.readthedocs.io/en/latest/format.html#warns .. _weekly tests: https://github.com/PlasmaPy/PlasmaPy/actions/workflows/weekly.yml diff --git a/docs/contributing/getting_ready.rst b/docs/contributing/getting_ready.rst index eed96db178..66ee76d92c 100644 --- a/docs/contributing/getting_ready.rst +++ b/docs/contributing/getting_ready.rst @@ -313,19 +313,19 @@ when you :py:`import plasmapy`. >>> reload(plasmapy) .. _Add a new SSH key to your GitHub account: https://docs.github.com/en/authentication/connecting-to-github-with-ssh/adding-a-new-ssh-key-to-your-github-account -.. _Anaconda Navigator: https://docs.anaconda.com/navigator -.. _Anaconda: https://docs.anaconda.com +.. _Anaconda Navigator: https://www.anaconda.com/docs/tools/anaconda-navigator/main +.. _Anaconda: https://www.anaconda.com/docs/main .. _clone: https://github.com/git-guides/git-clone .. _Conda: https://docs.conda.io -.. _creating an environment: https://docs.anaconda.com/navigator/tutorials/manage-environments/#creating-a-new-environment +.. _creating an environment: https://www.anaconda.com/docs/tools/anaconda-navigator/tutorials/manage-environments#creating-a-new-environment .. _download Python: https://www.python.org/downloads .. _fork: https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/about-forks -.. _frequently used Unix commands: https://faculty.tru.ca/nmora/Frequently%20used%20UNIX%20commands.pdf +.. _frequently used Unix commands: https://www.geeksforgeeks.org/linux-unix/essential-linuxunix-commands/ .. _git commands for setup and config: https://git-scm.com/book/en/v2/Appendix-C%3A-Git-Commands-Setup-and-Config .. _install git: https://git-scm.com/book/en/v2/Getting-Started-Installing-Git .. _install Graphviz: https://graphviz.org/download .. _install pandoc: https://pandoc.org/installing.html -.. _installing Anaconda Navigator: https://docs.anaconda.com/navigator/install +.. _installing Anaconda Navigator: https://www.anaconda.com/docs/tools/anaconda-navigator/install .. _installing Conda: https://docs.conda.io/projects/conda/en/latest/user-guide/install/index.html .. _installing Python: https://realpython.com/installing-python .. _installing WSL: https://learn.microsoft.com/en-us/windows/wsl/install @@ -338,7 +338,7 @@ when you :py:`import plasmapy`. .. _terminal user guide: https://support.apple.com/guide/terminal/welcome/mac .. _this xkcd comic: https://xkcd.com/1987 .. _unix tutorial: https://www.hpc.iastate.edu/guides/unix-introduction/unix-tutorial-1 -.. _using an environment: https://docs.anaconda.com/navigator/tutorials/manage-environments/#using-an-environment +.. _using an environment: https://www.anaconda.com/docs/tools/anaconda-navigator/tutorials/manage-environments#using-an-environment .. _venv: https://docs.python.org/3/library/venv.html .. _virtual environment: https://realpython.com/python-virtual-environments-a-primer .. _Windows Subsystem for Linux: https://learn.microsoft.com/en-us/windows/wsl diff --git a/docs/install.rst b/docs/install.rst index 1b8671f0bc..69f58c1ab6 100644 --- a/docs/install.rst +++ b/docs/install.rst @@ -248,7 +248,7 @@ package should also be installed. and create branches so that you may make contributions via pull requests. -.. _Anaconda Navigator: https://docs.anaconda.com/navigator +.. _Anaconda Navigator: https://www.anaconda.com/docs/tools/anaconda-navigator/main .. _clone a repository using SSH: https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-ssh-urls .. _Conda: https://docs.conda.io .. _conda-forge: https://conda-forge.org @@ -257,11 +257,11 @@ package should also be installed. .. _from PyPI: https://pypi.org/project/plasmapy .. _from Zenodo: https://doi.org/10.5281/zenodo.6774349 .. _improving Conda performance: https://docs.conda.io/projects/conda/en/latest/user-guide/concepts/conda-performance.html#improving-conda-performance -.. _installing Anaconda Navigator: https://docs.anaconda.com/navigator/install +.. _installing Anaconda Navigator: https://www.anaconda.com/docs/tools/anaconda-navigator/install .. _installing Conda: https://docs.conda.io/projects/conda/en/latest/user-guide/install/index.html .. _installing packages: https://packaging.python.org/en/latest/tutorials/installing-packages/#installing-from-vcs .. _installing uv: https://docs.astral.sh/uv/getting-started/installation/#installing-uv -.. _getting started with Anaconda Navigator: https://docs.anaconda.com/navigator/getting-started +.. _getting started with Anaconda Navigator: https://www.anaconda.com/docs/tools/anaconda-navigator/getting-started .. _miniconda: https://docs.conda.io/en/latest/miniconda.html .. _pip drop-in interface: https://docs.astral.sh/uv/pip/#the-pip-interface .. _publish a package: https://docs.astral.sh/uv/guides/publish/#publishing-a-package diff --git a/docs/notebooks/diagnostics/charged_particle_radiography_film_stacks.ipynb b/docs/notebooks/diagnostics/charged_particle_radiography_film_stacks.ipynb index f6b12c9f07..57019031a5 100644 --- a/docs/notebooks/diagnostics/charged_particle_radiography_film_stacks.ipynb +++ b/docs/notebooks/diagnostics/charged_particle_radiography_film_stacks.ipynb @@ -17,7 +17,7 @@ "\n", "[Bragg peak]:\n", "https://en.wikipedia.org/wiki/Bragg_peak\n", - " \n", + "\n", "Charged particle radiographs are often recorded on detector stacks with multiple layers (often either radiochromic film or CR39 plastic). Since charged particles deposit most of their energy at a depth related to their energy (the [Bragg peak]), each detector layer records a different energy band of particles. The energy bands recorded on each layer are further discriminated by including layers of filter material (eg. thin strips of aluminum) between the active layers. In order to analyze this data, it is necessary to calculate what range of particle energies are stopped in each detector layer.\n", "\n", "The [charged_particle_radiography] module includes a tool for calculating the energy bands for a given stack of detectors. This calculation is a simple approximation (more accurate calculations can be made using Monte Carlo codes), but is sufficient in many cases." @@ -57,7 +57,7 @@ "../../api/plasmapy.diagnostics.charged_particle_radiography.detector_stacks.Stack.rst#plasmapy.diagnostics.charged_particle_radiography.detector_stacks.Stack\n", "\n", "[astropy Quantity]:\n", - "https://docs.astropy.org/en/stable/api/astropy.units.quantity.Quantity.html\n", + "https://docs.astropy.org/en/stable/units/quantity.html\n", "\n", "[PSTAR]:\n", "https://physics.nist.gov/PhysRefData/Star/Text/PSTAR.html\n", @@ -71,9 +71,9 @@ "- `thickness`: an [astropy Quantity] defining the thickness of the layer.\n", "- `active`: a boolean flag which indicates whether the layer is active (detector) or inactive (eg. a filter).\n", "- `energy_axis`: An [astropy Quantity] array of energies.\n", - "- `stopping_power`: An [astropy Quantity] array containing the product of stopping power and material density at each energy in `energy_axis`. \n", + "- `stopping_power`: An [astropy Quantity] array containing the product of stopping power and material density at each energy in `energy_axis`.\n", "\n", - "The stopping power in various materials for protons and electrons is tabulated by NIST in the [PSTAR] and [ESTAR] databases. The stopping powers are tabulated in units of MeV cm$^2$ / g, so the product of stopping power and density has units of MeV/cm. \n", + "The stopping power in various materials for protons and electrons is tabulated by NIST in the [PSTAR] and [ESTAR] databases. The stopping powers are tabulated in units of MeV cm$^2$ / g, so the product of stopping power and density has units of MeV/cm.\n", "\n", "For this demonstration, we will load two stopping power tables, downloaded from [PSTAR], for aluminum and a human tissue equivalent that is a good approximation for many radiochromic films." ] @@ -144,9 +144,7 @@ "cell_type": "markdown", "id": "59d7daf8", "metadata": {}, - "source": [ - "If we plot the stopping powers as a function of energy on a log-log scale, we see that they are non-linear, with much higher values at lower energies. This is why particles deposit most of their energy at a characteristic depth. As particles propagate into material, they lose energy slowly at first. But, as they loose energy, the effective stopping power increases expontentially. " - ] + "source": "If we plot the stopping powers as a function of energy on a log-log scale, we see that they are non-linear, with much higher values at lower energies. This is why particles deposit most of their energy at a characteristic depth. As particles propagate into material, they lose energy slowly at first. But, as they loose energy, the effective stopping power increases expontentially." }, { "cell_type": "code", diff --git a/docs/notebooks/getting_started/units.ipynb b/docs/notebooks/getting_started/units.ipynb index 1d757ea98d..e3263ad794 100644 --- a/docs/notebooks/getting_started/units.ipynb +++ b/docs/notebooks/getting_started/units.ipynb @@ -73,7 +73,7 @@ "## Contents\n", "\n", "1. [Unit basics](#Unit-basics)\n", - "2. [Unit operations](#Unit-operations) \n", + "2. [Unit operations](#Unit-operations)\n", "3. [Unit conversations](#Unit-conversions)\n", "4. [Detaching units and values](#Detaching-units-and-values)\n", "5. [Equivalencies](#Equivalencies)\n", @@ -341,7 +341,7 @@ "[Quantity]: https://docs.astropy.org/en/stable/api/astropy.units.Quantity.html#astropy.units.Quantity\n", "[Quantity objects lose their units with some operations]: https://docs.astropy.org/en/stable/known_issues.html#quantities-lose-their-units-with-some-operations\n", "\n", - "Most frequently encountered [NumPy] and [SciPy] functions can be used with [Quantity] objects. However, [Quantity objects lose their units with some operations]. " + "Most frequently encountered [NumPy] and [SciPy] functions can be used with [Quantity] objects. However, [Quantity objects lose their units with some operations]." ] }, { @@ -386,7 +386,7 @@ "[si]: https://docs.astropy.org/en/stable/api/astropy.units.Quantity.html#astropy.units.Quantity.si\n", "[cgs]: https://docs.astropy.org/en/stable/api/astropy.units.Quantity.html#astropy.units.Quantity.cgs\n", "\n", - "The [si] and [cgs] attributes convert the [Quantity] to SI or CGS units, respectively. " + "The [si] and [cgs] attributes convert the [Quantity] to SI or CGS units, respectively." ] }, { @@ -416,7 +416,7 @@ "source": [ "## Detaching units and values\n", "\n", - "[value]: https://docs.astropy.org/en/stable/api/astropy.units.Quantity.html#astropy.units.Quantity.value \n", + "[value]: https://docs.astropy.org/en/stable/api/astropy.units.Quantity.html#astropy.units.Quantity.value\n", "[Quantity]: https://docs.astropy.org/en/stable/api/astropy.units.Quantity.html#astropy.units.Quantity\n", "\n", "The [value] attribute of a [Quantity] provides the number (as a NumPy scalar) or NumPy array without the unit." @@ -513,7 +513,7 @@ "id": "b4c492cc", "metadata": {}, "source": [ - "[dimensionless_angles()]: https://docs.astropy.org/en/stable/api/astropy.units.equivalencies.dimensionless_angles.html#dimensionless-angles\n", + "[dimensionless_angles()]: https://docs.astropy.org/en/stable/api/astropy.units.dimensionless_angles.html\n", "\n", "[frequency]: https://en.wikipedia.org/wiki/Frequency\n", "[angular frequency]: https://en.wikipedia.org/wiki/Angular_frequency\n", diff --git a/src/plasmapy/formulary/laser.py b/src/plasmapy/formulary/laser.py index bbd6927aea..162a87422e 100644 --- a/src/plasmapy/formulary/laser.py +++ b/src/plasmapy/formulary/laser.py @@ -472,7 +472,7 @@ def Gaussian_Rayleigh_length( Notes ----- - For details, see :wikipedia:`Rayleigh Length`\ . + For details, see :wikipedia:`Rayleigh length`. Examples -------- From 0f5c795dd82cc92ffc0e90bf6bda5a51b912bc3c Mon Sep 17 00:00:00 2001 From: Nick Murphy Date: Tue, 29 Jul 2025 18:10:55 -0400 Subject: [PATCH 379/521] Let `Particle` accept NumPy integers in the same ways as regular `int` objects (#3045) * Add minimal complete verifiable example * Fix formatting * Fix more links * Fix links * Make invalid particle type error message more explicit * Put type in error message * Add test case for np.integer supplied to Particle * Convert np.integer objects to ints in Particle * Remove test of easter egg * pre-commit run --all-files * Edit changelog: 3045.bugfix.rst * Revert changes intended for different PR * Remove accidentally commited line * Remove updated error message * Update src/plasmapy/particles/_factory.py * Add docstring to test along with assertion * Add comment to refer to issue * Update tests/particles/test_atomic.py * Simplify a test Co-authored-by: Erik Everson * Apply suggestion from @rocco8773 Co-authored-by: Erik Everson --------- Co-authored-by: Erik Everson --- changelog/3045.bugfix.rst | 1 + src/plasmapy/particles/_factory.py | 5 ++++- src/plasmapy/particles/_parsing.py | 3 +++ tests/particles/test_atomic.py | 8 ++++++++ tests/particles/test_parsing.py | 5 ----- tests/particles/test_particle_class.py | 8 ++++++++ 6 files changed, 24 insertions(+), 6 deletions(-) create mode 100644 changelog/3045.bugfix.rst diff --git a/changelog/3045.bugfix.rst b/changelog/3045.bugfix.rst new file mode 100644 index 0000000000..ad511cf299 --- /dev/null +++ b/changelog/3045.bugfix.rst @@ -0,0 +1 @@ +Enabled |Particle| to accept a `numpy.integer` object as the first argument to indicate the atomic number. diff --git a/src/plasmapy/particles/_factory.py b/src/plasmapy/particles/_factory.py index d09609db40..14ab01fb44 100644 --- a/src/plasmapy/particles/_factory.py +++ b/src/plasmapy/particles/_factory.py @@ -205,6 +205,9 @@ def _physical_particle_factory( return constructor(*args, **kwargs) # type: ignore[return-value] if args and not isinstance(args[0], str | Integral | u.Quantity): - raise TypeError("Invalid type for particle.") + raise TypeError( + f"{args[0]!r} is of type {type(args[0]).__name__}, which is not a " + f"valid particle type." + ) raise InvalidParticleError(_generate_particle_factory_error_message(args, kwargs)) diff --git a/src/plasmapy/particles/_parsing.py b/src/plasmapy/particles/_parsing.py index 896a92c3f0..a479eee669 100644 --- a/src/plasmapy/particles/_parsing.py +++ b/src/plasmapy/particles/_parsing.py @@ -380,6 +380,9 @@ def reconstruct_ion_symbol( return ion + if isinstance(argument, np.integer): # see issue 3044 + argument = int(argument) + if not isinstance(argument, str | int): raise TypeError(f"The argument {argument} is not an integer or string.") diff --git a/tests/particles/test_atomic.py b/tests/particles/test_atomic.py index c890d0600c..0ec41cfbe6 100644 --- a/tests/particles/test_atomic.py +++ b/tests/particles/test_atomic.py @@ -706,3 +706,11 @@ def test_stopping_power_no_interpolation() -> None: result = stopping_power(Particle("H+"), "COPPER") assert type(result) is tuple + + +def test_element_name_used_on_numpy_integer(): + """ + Test that `element_name` works when provided with a numpy.integer + object acquired from an ndarray (see #3044). + """ + assert element_name(np.int32(18)) == "argon" diff --git a/tests/particles/test_parsing.py b/tests/particles/test_parsing.py index 4e14b7b09b..3d0ddc8a20 100644 --- a/tests/particles/test_parsing.py +++ b/tests/particles/test_parsing.py @@ -375,8 +375,3 @@ def test_parse_ParticleWarnings(arg, kwargs, num_warnings: int) -> None: f"was {len(record)}, which differs from the expected number " f"of {num_warnings} warnings." ) - - -def test_Queen() -> None: - Queen = "Freddie Mercury (lead vocals, piano), Brian May (guitar, vocals), Roger Taylor (drums, vocals) and John Deacon (bass)" - assert Particle("Freddie").element_name.capitalize() in Queen diff --git a/tests/particles/test_particle_class.py b/tests/particles/test_particle_class.py index 0d0400a47e..f4b2aac46f 100644 --- a/tests/particles/test_particle_class.py +++ b/tests/particles/test_particle_class.py @@ -510,6 +510,14 @@ "ionic_symbol": "C-14 3+", }, ), + ( + np.int32(26), # test that Particle accepts np.integer objects (see #3044) + {}, + { + "symbol": "Fe", + "atomic_number": 26, + }, + ), ] From e881bfe43d129807397755bda70ff3b06abb1777 Mon Sep 17 00:00:00 2001 From: Nick Murphy Date: Tue, 29 Jul 2025 18:16:27 -0400 Subject: [PATCH 380/521] Update usage of `uv` by Nox (#2998) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update uv usage in noxfile.py * Fix keyword name * Update session.install usage * Undelete line * Try explicitly saying --extra=tests * Use uvx in workflows * Update uv usage * uv pip install: "--no-default-groups" → "--no-all-extras" * Go back to .[tests] * Make uv the sole backend for Nox * nox → nox[uv] in requirements * nox -s requirements * Use >= for nox[uv] requirement * nox -s requirements * Edit changelog: 2998.internal.rst * Edit changelog: 2998.internal.rst * nox -s requirements --- .github/workflows/ci.yml | 2 +- .github/workflows/linkcheck.yml | 4 +- .github/workflows/update-pinned-reqs.yml | 2 +- .github/workflows/weekly.yml | 2 +- changelog/2998.internal.rst | 1 + noxfile.py | 34 +- pyproject.toml | 4 +- uv.lock | 528 ++++++++++++++--------- 8 files changed, 350 insertions(+), 227 deletions(-) create mode 100644 changelog/2998.internal.rst diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6a5c595b9f..a538ad9a50 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -105,7 +105,7 @@ jobs: cache-suffix: ${{ matrix.nox_session }}-${{ matrix.python }}-${{ runner.os }} - name: Run the check - run: uv run --with nox --frozen nox -s '${{ matrix.nox_session }}' + run: uvx nox -s '${{ matrix.nox_session }}' - name: Upload coverage reports to Codecov if: ${{ contains(matrix.nox_session, 'cov') }} diff --git a/.github/workflows/linkcheck.yml b/.github/workflows/linkcheck.yml index 5a92a19a2b..f85619e4dd 100644 --- a/.github/workflows/linkcheck.yml +++ b/.github/workflows/linkcheck.yml @@ -43,10 +43,10 @@ jobs: - name: Install uv uses: astral-sh/setup-uv@v6 with: - python: 3.12 + python-version: 3.12 - name: Install graphviz & pandoc run: sudo apt-get install graphviz pandoc - name: Check hyperlinks - run: uv run --with nox --frozen nox -s linkcheck + run: uvx nox -s linkcheck diff --git a/.github/workflows/update-pinned-reqs.yml b/.github/workflows/update-pinned-reqs.yml index d4118cca81..2617c4c3da 100644 --- a/.github/workflows/update-pinned-reqs.yml +++ b/.github/workflows/update-pinned-reqs.yml @@ -24,7 +24,7 @@ jobs: python: 3.13 - name: Run Nox session to regenerate requirements - run: uv run --with nox --frozen nox -s requirements + run: uvx nox -s requirements # When a PR is created by a GitHub Action, normally the checks will # not be run. While the simplest workaround would have been to open diff --git a/.github/workflows/weekly.yml b/.github/workflows/weekly.yml index 9220d3b050..2f26782a2f 100644 --- a/.github/workflows/weekly.yml +++ b/.github/workflows/weekly.yml @@ -171,7 +171,7 @@ jobs: cache-suffix: ${{ matrix.nox_session }}-${{ matrix.python }}-${{ runner.os }} - name: Run Nox session - run: uv run --with nox nox -s '${{ matrix.nox_session }}' + run: uvx nox -s '${{ matrix.nox_session }}' - name: Upload coverage reports to Codecov if: ${{ contains(matrix.nox_session, 'cov') }} diff --git a/changelog/2998.internal.rst b/changelog/2998.internal.rst new file mode 100644 index 0000000000..e6a8da9aea --- /dev/null +++ b/changelog/2998.internal.rst @@ -0,0 +1 @@ +Set ``uv`` as the sole backend to Nox, and changed the ``docs`` and ``tests`` dependency sets to include ``nox[uv]`` instead of ``nox``. diff --git a/noxfile.py b/noxfile.py index db4ac85a60..516a1f177b 100644 --- a/noxfile.py +++ b/noxfile.py @@ -59,15 +59,13 @@ current_python = f"{sys.version_info.major}.{sys.version_info.minor}" nox.options.sessions = [f"tests-{current_python}(skipslow)"] -nox.options.default_venv_backend = "uv|virtualenv" +nox.options.default_venv_backend = "uv" uv_sync = ("uv", "sync", "--no-progress", "--frozen") running_on_ci = os.getenv("CI") running_on_rtd = os.environ.get("READTHEDOCS") == "True" -uv_requirement = "uv >= 0.6.5" - def _create_requirements_pr_message(uv_output: str, session: nox.Session) -> None: """ @@ -160,8 +158,6 @@ def requirements(session: nox.Session) -> None: pull request message for the GitHub workflow that updates the pinned requirements (:file:`.github/workflows/update-pinned-reqs.yml`). """ - session.install(uv_requirement) - uv_lock_upgrade = ["uv", "lock", "--upgrade", "--no-progress"] # When silent is `True`, `session.run()` returns a multi-line string @@ -184,7 +180,6 @@ def validate_requirements(session: nox.Session) -> None: Verify that the requirements in :file:`uv.lock` are compatible with the requirements in `pyproject.toml`. """ - session.install(uv_requirement) session.log( "🛡 If this check fails, regenerate the pinned requirements in " "`uv.lock` with `nox -s requirements`." @@ -238,8 +233,6 @@ def validate_requirements(session: nox.Session) -> None: def tests(session: nox.Session, test_specifier: nox._parametrize.Param) -> None: """Run tests with pytest.""" - session.install(uv_requirement) - options: list[str] = [] if test_specifier in {"skip slow tests", "lowest-direct-skipslow"}: @@ -259,12 +252,20 @@ def tests(session: nox.Session, test_specifier: nox._parametrize.Param) -> None: match test_specifier: case "lowest-direct" | "lowest-direct-skipslow": - session.install(".[tests]", "--resolution=lowest-direct") + session.install( + ".[tests]", + "--resolution=lowest-direct", + "--no-all-extras", + f"--python={session.virtualenv.location}", + env={"UV_PROJECT_ENVIRONMENT": session.virtualenv.location}, + ) case _: # From https://nox.thea.codes/en/stable/cookbook.html#using-a-lockfile session.run_install( *uv_sync, "--extra=tests", + "--no-default-groups", + f"--python={session.virtualenv.location}", env={"UV_PROJECT_ENVIRONMENT": session.virtualenv.location}, ) @@ -290,8 +291,6 @@ def run_tests_with_dev_version_of(session: nox.Session, repository: str) -> None changes in an upstream dependency before its official release. """ - session.install(uv_requirement) - if repository == "numpy": # From: https://numpy.org/doc/1.26/dev/depending_on_numpy.html session.run_install( @@ -361,11 +360,11 @@ def docs(session: nox.Session) -> None: if running_on_ci: session.log(doc_troubleshooting_message) - session.install(uv_requirement) - session.run_install( *uv_sync, "--extra=docs", + "--no-default-groups", + f"--python={session.virtualenv.location}", env={"UV_PROJECT_ENVIRONMENT": session.virtualenv.location}, ) session.run(*sphinx_base_command, *build_html, *session.posargs) @@ -481,14 +480,18 @@ def build_docs_with_dev_version_of( @nox.session(python=docpython) def linkcheck(session: nox.Session) -> None: """Check hyperlinks in documentation.""" + if running_on_ci: session.log(LINKCHECK_TROUBLESHOOTING) - session.install(uv_requirement) + session.run_install( *uv_sync, "--extra=docs", + "--no-default-groups", + f"--python={session.virtualenv.location}", env={"UV_PROJECT_ENVIRONMENT": session.virtualenv.location}, ) + session.run(*sphinx_base_command, *check_hyperlinks, *session.posargs) @@ -516,10 +519,11 @@ def mypy(session: nox.Session) -> None: Configuration file: mypy.ini """ - session.install(uv_requirement) session.run_install( *uv_sync, "--extra=tests", + "--no-default-groups", + f"--python={session.virtualenv.location}", env={"UV_PROJECT_ENVIRONMENT": session.virtualenv.location}, ) diff --git a/pyproject.toml b/pyproject.toml index e389b99a43..1a9b7a1fbf 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -85,7 +85,7 @@ optional-dependencies.docs = [ "docutils>=0.20.1", "jinja2>=3.1.4", "nbsphinx>=0.9.4", - "nox>=2024.10.9", + "nox[uv]>=2025.5.1", "numpydoc>=1.7", "pillow>=10.4", "plasmapy-sphinx>=0.2.0b1", @@ -112,7 +112,7 @@ optional-dependencies.docs = [ optional-dependencies.tests = [ "hypothesis>=6.108.2", "mypy>=1.11", - "nox>=2024.10.9", + "nox[uv]>=2025.5.1", "pytest>=8.3.1", "pytest-cov>=5", "pytest-filter-subpackage>=0.2", diff --git a/uv.lock b/uv.lock index abcb99d9dd..3df62b19de 100644 --- a/uv.lock +++ b/uv.lock @@ -140,11 +140,11 @@ wheels = [ [[package]] name = "astropy-iers-data" -version = "0.2025.7.21.0.41.39" +version = "0.2025.7.28.0.41.50" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/87/7a/5d1094cf8fd37c8e79510a74d1a5e279b2180fb34e4233e6c941733d05e8/astropy_iers_data-0.2025.7.21.0.41.39.tar.gz", hash = "sha256:e482753c9d6979165be5a47e14a29650026579988a5f0656e52a962e07040a93", size = 1902919, upload-time = "2025-07-21T00:42:28.603Z" } +sdist = { url = "https://files.pythonhosted.org/packages/a7/35/934488a768e1e0e891c38f3c905c7158d65ac99cea7f94d1fe614ebe985d/astropy_iers_data-0.2025.7.28.0.41.50.tar.gz", hash = "sha256:615b23572553ab2156131ccc6577be2f7528d79326bcde17ab788374aca085b2", size = 1903592, upload-time = "2025-07-28T00:42:27.429Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ca/b6/452abd866c18b18fb768d6b28ee9aaf9e24d2169e4e6b2945f85ad4bc2e6/astropy_iers_data-0.2025.7.21.0.41.39-py3-none-any.whl", hash = "sha256:1a5bbb3be6eb02c227ccc2549e22f322e64a5a6bc635b5baf34e214b28b621da", size = 1958365, upload-time = "2025-07-21T00:42:26.964Z" }, + { url = "https://files.pythonhosted.org/packages/45/0a/614957f5d35bc5b9a376e729bc31e1fae8ee226aecb1583179bbed889264/astropy_iers_data-0.2025.7.28.0.41.50-py3-none-any.whl", hash = "sha256:ed2ee1139f7838ce1e46cdc0024a7c169235f765a3e73b36d45ab6412cbbbb98", size = 1959055, upload-time = "2025-07-28T00:42:25.693Z" }, ] [[package]] @@ -341,122 +341,168 @@ wheels = [ [[package]] name = "comm" -version = "0.2.2" +version = "0.2.3" source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "traitlets" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/e9/a8/fb783cb0abe2b5fded9f55e5703015cdf1c9c85b3669087c538dd15a6a86/comm-0.2.2.tar.gz", hash = "sha256:3fd7a84065306e07bea1773df6eb8282de51ba82f77c72f9c85716ab11fe980e", size = 6210, upload-time = "2024-03-12T16:53:41.133Z" } +sdist = { url = "https://files.pythonhosted.org/packages/4c/13/7d740c5849255756bc17888787313b61fd38a0a8304fc4f073dfc46122aa/comm-0.2.3.tar.gz", hash = "sha256:2dc8048c10962d55d7ad693be1e7045d891b7ce8d999c97963a5e3e99c055971", size = 6319, upload-time = "2025-07-25T14:02:04.452Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/e6/75/49e5bfe642f71f272236b5b2d2691cf915a7283cc0ceda56357b61daa538/comm-0.2.2-py3-none-any.whl", hash = "sha256:e6fb86cb70ff661ee8c9c14e7d36d6de3b4066f1441be4063df9c5009f0a64d3", size = 7180, upload-time = "2024-03-12T16:53:39.226Z" }, + { url = "https://files.pythonhosted.org/packages/60/97/891a0971e1e4a8c5d2b20bbe0e524dc04548d2307fee33cdeba148fd4fc7/comm-0.2.3-py3-none-any.whl", hash = "sha256:c615d91d75f7f04f095b30d1c1711babd43bdc6419c1be9886a85f2f4e489417", size = 7294, upload-time = "2025-07-25T14:02:02.896Z" }, ] [[package]] name = "contourpy" -version = "1.3.2" +version = "1.3.3" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "numpy" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/66/54/eb9bfc647b19f2009dd5c7f5ec51c4e6ca831725f1aea7a993034f483147/contourpy-1.3.2.tar.gz", hash = "sha256:b6945942715a034c671b7fc54f9588126b0b8bf23db2696e3ca8328f3ff0ab54", size = 13466130, upload-time = "2025-04-15T17:47:53.79Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/b3/b9/ede788a0b56fc5b071639d06c33cb893f68b1178938f3425debebe2dab78/contourpy-1.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6a37a2fb93d4df3fc4c0e363ea4d16f83195fc09c891bc8ce072b9d084853445", size = 269636, upload-time = "2025-04-15T17:35:54.473Z" }, - { url = "https://files.pythonhosted.org/packages/e6/75/3469f011d64b8bbfa04f709bfc23e1dd71be54d05b1b083be9f5b22750d1/contourpy-1.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b7cd50c38f500bbcc9b6a46643a40e0913673f869315d8e70de0438817cb7773", size = 254636, upload-time = "2025-04-15T17:35:58.283Z" }, - { url = "https://files.pythonhosted.org/packages/8d/2f/95adb8dae08ce0ebca4fd8e7ad653159565d9739128b2d5977806656fcd2/contourpy-1.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d6658ccc7251a4433eebd89ed2672c2ed96fba367fd25ca9512aa92a4b46c4f1", size = 313053, upload-time = "2025-04-15T17:36:03.235Z" }, - { url = "https://files.pythonhosted.org/packages/c3/a6/8ccf97a50f31adfa36917707fe39c9a0cbc24b3bbb58185577f119736cc9/contourpy-1.3.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:70771a461aaeb335df14deb6c97439973d253ae70660ca085eec25241137ef43", size = 352985, upload-time = "2025-04-15T17:36:08.275Z" }, - { url = "https://files.pythonhosted.org/packages/1d/b6/7925ab9b77386143f39d9c3243fdd101621b4532eb126743201160ffa7e6/contourpy-1.3.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:65a887a6e8c4cd0897507d814b14c54a8c2e2aa4ac9f7686292f9769fcf9a6ab", size = 323750, upload-time = "2025-04-15T17:36:13.29Z" }, - { url = "https://files.pythonhosted.org/packages/c2/f3/20c5d1ef4f4748e52d60771b8560cf00b69d5c6368b5c2e9311bcfa2a08b/contourpy-1.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3859783aefa2b8355697f16642695a5b9792e7a46ab86da1118a4a23a51a33d7", size = 326246, upload-time = "2025-04-15T17:36:18.329Z" }, - { url = "https://files.pythonhosted.org/packages/8c/e5/9dae809e7e0b2d9d70c52b3d24cba134dd3dad979eb3e5e71f5df22ed1f5/contourpy-1.3.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:eab0f6db315fa4d70f1d8ab514e527f0366ec021ff853d7ed6a2d33605cf4b83", size = 1308728, upload-time = "2025-04-15T17:36:33.878Z" }, - { url = "https://files.pythonhosted.org/packages/e2/4a/0058ba34aeea35c0b442ae61a4f4d4ca84d6df8f91309bc2d43bb8dd248f/contourpy-1.3.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:d91a3ccc7fea94ca0acab82ceb77f396d50a1f67412efe4c526f5d20264e6ecd", size = 1375762, upload-time = "2025-04-15T17:36:51.295Z" }, - { url = "https://files.pythonhosted.org/packages/09/33/7174bdfc8b7767ef2c08ed81244762d93d5c579336fc0b51ca57b33d1b80/contourpy-1.3.2-cp311-cp311-win32.whl", hash = "sha256:1c48188778d4d2f3d48e4643fb15d8608b1d01e4b4d6b0548d9b336c28fc9b6f", size = 178196, upload-time = "2025-04-15T17:36:55.002Z" }, - { url = "https://files.pythonhosted.org/packages/5e/fe/4029038b4e1c4485cef18e480b0e2cd2d755448bb071eb9977caac80b77b/contourpy-1.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:5ebac872ba09cb8f2131c46b8739a7ff71de28a24c869bcad554477eb089a878", size = 222017, upload-time = "2025-04-15T17:36:58.576Z" }, - { url = "https://files.pythonhosted.org/packages/34/f7/44785876384eff370c251d58fd65f6ad7f39adce4a093c934d4a67a7c6b6/contourpy-1.3.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4caf2bcd2969402bf77edc4cb6034c7dd7c0803213b3523f111eb7460a51b8d2", size = 271580, upload-time = "2025-04-15T17:37:03.105Z" }, - { url = "https://files.pythonhosted.org/packages/93/3b/0004767622a9826ea3d95f0e9d98cd8729015768075d61f9fea8eeca42a8/contourpy-1.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:82199cb78276249796419fe36b7386bd8d2cc3f28b3bc19fe2454fe2e26c4c15", size = 255530, upload-time = "2025-04-15T17:37:07.026Z" }, - { url = "https://files.pythonhosted.org/packages/e7/bb/7bd49e1f4fa805772d9fd130e0d375554ebc771ed7172f48dfcd4ca61549/contourpy-1.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:106fab697af11456fcba3e352ad50effe493a90f893fca6c2ca5c033820cea92", size = 307688, upload-time = "2025-04-15T17:37:11.481Z" }, - { url = "https://files.pythonhosted.org/packages/fc/97/e1d5dbbfa170725ef78357a9a0edc996b09ae4af170927ba8ce977e60a5f/contourpy-1.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d14f12932a8d620e307f715857107b1d1845cc44fdb5da2bc8e850f5ceba9f87", size = 347331, upload-time = "2025-04-15T17:37:18.212Z" }, - { url = "https://files.pythonhosted.org/packages/6f/66/e69e6e904f5ecf6901be3dd16e7e54d41b6ec6ae3405a535286d4418ffb4/contourpy-1.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:532fd26e715560721bb0d5fc7610fce279b3699b018600ab999d1be895b09415", size = 318963, upload-time = "2025-04-15T17:37:22.76Z" }, - { url = "https://files.pythonhosted.org/packages/a8/32/b8a1c8965e4f72482ff2d1ac2cd670ce0b542f203c8e1d34e7c3e6925da7/contourpy-1.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f26b383144cf2d2c29f01a1e8170f50dacf0eac02d64139dcd709a8ac4eb3cfe", size = 323681, upload-time = "2025-04-15T17:37:33.001Z" }, - { url = "https://files.pythonhosted.org/packages/30/c6/12a7e6811d08757c7162a541ca4c5c6a34c0f4e98ef2b338791093518e40/contourpy-1.3.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:c49f73e61f1f774650a55d221803b101d966ca0c5a2d6d5e4320ec3997489441", size = 1308674, upload-time = "2025-04-15T17:37:48.64Z" }, - { url = "https://files.pythonhosted.org/packages/2a/8a/bebe5a3f68b484d3a2b8ffaf84704b3e343ef1addea528132ef148e22b3b/contourpy-1.3.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3d80b2c0300583228ac98d0a927a1ba6a2ba6b8a742463c564f1d419ee5b211e", size = 1380480, upload-time = "2025-04-15T17:38:06.7Z" }, - { url = "https://files.pythonhosted.org/packages/34/db/fcd325f19b5978fb509a7d55e06d99f5f856294c1991097534360b307cf1/contourpy-1.3.2-cp312-cp312-win32.whl", hash = "sha256:90df94c89a91b7362e1142cbee7568f86514412ab8a2c0d0fca72d7e91b62912", size = 178489, upload-time = "2025-04-15T17:38:10.338Z" }, - { url = "https://files.pythonhosted.org/packages/01/c8/fadd0b92ffa7b5eb5949bf340a63a4a496a6930a6c37a7ba0f12acb076d6/contourpy-1.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:8c942a01d9163e2e5cfb05cb66110121b8d07ad438a17f9e766317bcb62abf73", size = 223042, upload-time = "2025-04-15T17:38:14.239Z" }, - { url = "https://files.pythonhosted.org/packages/2e/61/5673f7e364b31e4e7ef6f61a4b5121c5f170f941895912f773d95270f3a2/contourpy-1.3.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:de39db2604ae755316cb5967728f4bea92685884b1e767b7c24e983ef5f771cb", size = 271630, upload-time = "2025-04-15T17:38:19.142Z" }, - { url = "https://files.pythonhosted.org/packages/ff/66/a40badddd1223822c95798c55292844b7e871e50f6bfd9f158cb25e0bd39/contourpy-1.3.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:3f9e896f447c5c8618f1edb2bafa9a4030f22a575ec418ad70611450720b5b08", size = 255670, upload-time = "2025-04-15T17:38:23.688Z" }, - { url = "https://files.pythonhosted.org/packages/1e/c7/cf9fdee8200805c9bc3b148f49cb9482a4e3ea2719e772602a425c9b09f8/contourpy-1.3.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:71e2bd4a1c4188f5c2b8d274da78faab884b59df20df63c34f74aa1813c4427c", size = 306694, upload-time = "2025-04-15T17:38:28.238Z" }, - { url = "https://files.pythonhosted.org/packages/dd/e7/ccb9bec80e1ba121efbffad7f38021021cda5be87532ec16fd96533bb2e0/contourpy-1.3.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de425af81b6cea33101ae95ece1f696af39446db9682a0b56daaa48cfc29f38f", size = 345986, upload-time = "2025-04-15T17:38:33.502Z" }, - { url = "https://files.pythonhosted.org/packages/dc/49/ca13bb2da90391fa4219fdb23b078d6065ada886658ac7818e5441448b78/contourpy-1.3.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:977e98a0e0480d3fe292246417239d2d45435904afd6d7332d8455981c408b85", size = 318060, upload-time = "2025-04-15T17:38:38.672Z" }, - { url = "https://files.pythonhosted.org/packages/c8/65/5245ce8c548a8422236c13ffcdcdada6a2a812c361e9e0c70548bb40b661/contourpy-1.3.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:434f0adf84911c924519d2b08fc10491dd282b20bdd3fa8f60fd816ea0b48841", size = 322747, upload-time = "2025-04-15T17:38:43.712Z" }, - { url = "https://files.pythonhosted.org/packages/72/30/669b8eb48e0a01c660ead3752a25b44fdb2e5ebc13a55782f639170772f9/contourpy-1.3.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:c66c4906cdbc50e9cba65978823e6e00b45682eb09adbb78c9775b74eb222422", size = 1308895, upload-time = "2025-04-15T17:39:00.224Z" }, - { url = "https://files.pythonhosted.org/packages/05/5a/b569f4250decee6e8d54498be7bdf29021a4c256e77fe8138c8319ef8eb3/contourpy-1.3.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8b7fc0cd78ba2f4695fd0a6ad81a19e7e3ab825c31b577f384aa9d7817dc3bef", size = 1379098, upload-time = "2025-04-15T17:43:29.649Z" }, - { url = "https://files.pythonhosted.org/packages/19/ba/b227c3886d120e60e41b28740ac3617b2f2b971b9f601c835661194579f1/contourpy-1.3.2-cp313-cp313-win32.whl", hash = "sha256:15ce6ab60957ca74cff444fe66d9045c1fd3e92c8936894ebd1f3eef2fff075f", size = 178535, upload-time = "2025-04-15T17:44:44.532Z" }, - { url = "https://files.pythonhosted.org/packages/12/6e/2fed56cd47ca739b43e892707ae9a13790a486a3173be063681ca67d2262/contourpy-1.3.2-cp313-cp313-win_amd64.whl", hash = "sha256:e1578f7eafce927b168752ed7e22646dad6cd9bca673c60bff55889fa236ebf9", size = 223096, upload-time = "2025-04-15T17:44:48.194Z" }, - { url = "https://files.pythonhosted.org/packages/54/4c/e76fe2a03014a7c767d79ea35c86a747e9325537a8b7627e0e5b3ba266b4/contourpy-1.3.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:0475b1f6604896bc7c53bb070e355e9321e1bc0d381735421a2d2068ec56531f", size = 285090, upload-time = "2025-04-15T17:43:34.084Z" }, - { url = "https://files.pythonhosted.org/packages/7b/e2/5aba47debd55d668e00baf9651b721e7733975dc9fc27264a62b0dd26eb8/contourpy-1.3.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:c85bb486e9be652314bb5b9e2e3b0d1b2e643d5eec4992c0fbe8ac71775da739", size = 268643, upload-time = "2025-04-15T17:43:38.626Z" }, - { url = "https://files.pythonhosted.org/packages/a1/37/cd45f1f051fe6230f751cc5cdd2728bb3a203f5619510ef11e732109593c/contourpy-1.3.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:745b57db7758f3ffc05a10254edd3182a2a83402a89c00957a8e8a22f5582823", size = 310443, upload-time = "2025-04-15T17:43:44.522Z" }, - { url = "https://files.pythonhosted.org/packages/8b/a2/36ea6140c306c9ff6dd38e3bcec80b3b018474ef4d17eb68ceecd26675f4/contourpy-1.3.2-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:970e9173dbd7eba9b4e01aab19215a48ee5dd3f43cef736eebde064a171f89a5", size = 349865, upload-time = "2025-04-15T17:43:49.545Z" }, - { url = "https://files.pythonhosted.org/packages/95/b7/2fc76bc539693180488f7b6cc518da7acbbb9e3b931fd9280504128bf956/contourpy-1.3.2-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c6c4639a9c22230276b7bffb6a850dfc8258a2521305e1faefe804d006b2e532", size = 321162, upload-time = "2025-04-15T17:43:54.203Z" }, - { url = "https://files.pythonhosted.org/packages/f4/10/76d4f778458b0aa83f96e59d65ece72a060bacb20cfbee46cf6cd5ceba41/contourpy-1.3.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cc829960f34ba36aad4302e78eabf3ef16a3a100863f0d4eeddf30e8a485a03b", size = 327355, upload-time = "2025-04-15T17:44:01.025Z" }, - { url = "https://files.pythonhosted.org/packages/43/a3/10cf483ea683f9f8ab096c24bad3cce20e0d1dd9a4baa0e2093c1c962d9d/contourpy-1.3.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:d32530b534e986374fc19eaa77fcb87e8a99e5431499949b828312bdcd20ac52", size = 1307935, upload-time = "2025-04-15T17:44:17.322Z" }, - { url = "https://files.pythonhosted.org/packages/78/73/69dd9a024444489e22d86108e7b913f3528f56cfc312b5c5727a44188471/contourpy-1.3.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:e298e7e70cf4eb179cc1077be1c725b5fd131ebc81181bf0c03525c8abc297fd", size = 1372168, upload-time = "2025-04-15T17:44:33.43Z" }, - { url = "https://files.pythonhosted.org/packages/0f/1b/96d586ccf1b1a9d2004dd519b25fbf104a11589abfd05484ff12199cca21/contourpy-1.3.2-cp313-cp313t-win32.whl", hash = "sha256:d0e589ae0d55204991450bb5c23f571c64fe43adaa53f93fc902a84c96f52fe1", size = 189550, upload-time = "2025-04-15T17:44:37.092Z" }, - { url = "https://files.pythonhosted.org/packages/b0/e6/6000d0094e8a5e32ad62591c8609e269febb6e4db83a1c75ff8868b42731/contourpy-1.3.2-cp313-cp313t-win_amd64.whl", hash = "sha256:78e9253c3de756b3f6a5174d024c4835acd59eb3f8e2ca13e775dbffe1558f69", size = 238214, upload-time = "2025-04-15T17:44:40.827Z" }, - { url = "https://files.pythonhosted.org/packages/ff/c0/91f1215d0d9f9f343e4773ba6c9b89e8c0cc7a64a6263f21139da639d848/contourpy-1.3.2-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:5f5964cdad279256c084b69c3f412b7801e15356b16efa9d78aa974041903da0", size = 266807, upload-time = "2025-04-15T17:45:15.535Z" }, - { url = "https://files.pythonhosted.org/packages/d4/79/6be7e90c955c0487e7712660d6cead01fa17bff98e0ea275737cc2bc8e71/contourpy-1.3.2-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:49b65a95d642d4efa8f64ba12558fcb83407e58a2dfba9d796d77b63ccfcaff5", size = 318729, upload-time = "2025-04-15T17:45:20.166Z" }, - { url = "https://files.pythonhosted.org/packages/87/68/7f46fb537958e87427d98a4074bcde4b67a70b04900cfc5ce29bc2f556c1/contourpy-1.3.2-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:8c5acb8dddb0752bf252e01a3035b21443158910ac16a3b0d20e7fed7d534ce5", size = 221791, upload-time = "2025-04-15T17:45:24.794Z" }, +sdist = { url = "https://files.pythonhosted.org/packages/58/01/1253e6698a07380cd31a736d248a3f2a50a7c88779a1813da27503cadc2a/contourpy-1.3.3.tar.gz", hash = "sha256:083e12155b210502d0bca491432bb04d56dc3432f95a979b429f2848c3dbe880", size = 13466174, upload-time = "2025-07-26T12:03:12.549Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/91/2e/c4390a31919d8a78b90e8ecf87cd4b4c4f05a5b48d05ec17db8e5404c6f4/contourpy-1.3.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:709a48ef9a690e1343202916450bc48b9e51c049b089c7f79a267b46cffcdaa1", size = 288773, upload-time = "2025-07-26T12:01:02.277Z" }, + { url = "https://files.pythonhosted.org/packages/0d/44/c4b0b6095fef4dc9c420e041799591e3b63e9619e3044f7f4f6c21c0ab24/contourpy-1.3.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:23416f38bfd74d5d28ab8429cc4d63fa67d5068bd711a85edb1c3fb0c3e2f381", size = 270149, upload-time = "2025-07-26T12:01:04.072Z" }, + { url = "https://files.pythonhosted.org/packages/30/2e/dd4ced42fefac8470661d7cb7e264808425e6c5d56d175291e93890cce09/contourpy-1.3.3-cp311-cp311-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:929ddf8c4c7f348e4c0a5a3a714b5c8542ffaa8c22954862a46ca1813b667ee7", size = 329222, upload-time = "2025-07-26T12:01:05.688Z" }, + { url = "https://files.pythonhosted.org/packages/f2/74/cc6ec2548e3d276c71389ea4802a774b7aa3558223b7bade3f25787fafc2/contourpy-1.3.3-cp311-cp311-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:9e999574eddae35f1312c2b4b717b7885d4edd6cb46700e04f7f02db454e67c1", size = 377234, upload-time = "2025-07-26T12:01:07.054Z" }, + { url = "https://files.pythonhosted.org/packages/03/b3/64ef723029f917410f75c09da54254c5f9ea90ef89b143ccadb09df14c15/contourpy-1.3.3-cp311-cp311-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:0bf67e0e3f482cb69779dd3061b534eb35ac9b17f163d851e2a547d56dba0a3a", size = 380555, upload-time = "2025-07-26T12:01:08.801Z" }, + { url = "https://files.pythonhosted.org/packages/5f/4b/6157f24ca425b89fe2eb7e7be642375711ab671135be21e6faa100f7448c/contourpy-1.3.3-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:51e79c1f7470158e838808d4a996fa9bac72c498e93d8ebe5119bc1e6becb0db", size = 355238, upload-time = "2025-07-26T12:01:10.319Z" }, + { url = "https://files.pythonhosted.org/packages/98/56/f914f0dd678480708a04cfd2206e7c382533249bc5001eb9f58aa693e200/contourpy-1.3.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:598c3aaece21c503615fd59c92a3598b428b2f01bfb4b8ca9c4edeecc2438620", size = 1326218, upload-time = "2025-07-26T12:01:12.659Z" }, + { url = "https://files.pythonhosted.org/packages/fb/d7/4a972334a0c971acd5172389671113ae82aa7527073980c38d5868ff1161/contourpy-1.3.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:322ab1c99b008dad206d406bb61d014cf0174df491ae9d9d0fac6a6fda4f977f", size = 1392867, upload-time = "2025-07-26T12:01:15.533Z" }, + { url = "https://files.pythonhosted.org/packages/75/3e/f2cc6cd56dc8cff46b1a56232eabc6feea52720083ea71ab15523daab796/contourpy-1.3.3-cp311-cp311-win32.whl", hash = "sha256:fd907ae12cd483cd83e414b12941c632a969171bf90fc937d0c9f268a31cafff", size = 183677, upload-time = "2025-07-26T12:01:17.088Z" }, + { url = "https://files.pythonhosted.org/packages/98/4b/9bd370b004b5c9d8045c6c33cf65bae018b27aca550a3f657cdc99acdbd8/contourpy-1.3.3-cp311-cp311-win_amd64.whl", hash = "sha256:3519428f6be58431c56581f1694ba8e50626f2dd550af225f82fb5f5814d2a42", size = 225234, upload-time = "2025-07-26T12:01:18.256Z" }, + { url = "https://files.pythonhosted.org/packages/d9/b6/71771e02c2e004450c12b1120a5f488cad2e4d5b590b1af8bad060360fe4/contourpy-1.3.3-cp311-cp311-win_arm64.whl", hash = "sha256:15ff10bfada4bf92ec8b31c62bf7c1834c244019b4a33095a68000d7075df470", size = 193123, upload-time = "2025-07-26T12:01:19.848Z" }, + { url = "https://files.pythonhosted.org/packages/be/45/adfee365d9ea3d853550b2e735f9d66366701c65db7855cd07621732ccfc/contourpy-1.3.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b08a32ea2f8e42cf1d4be3169a98dd4be32bafe4f22b6c4cb4ba810fa9e5d2cb", size = 293419, upload-time = "2025-07-26T12:01:21.16Z" }, + { url = "https://files.pythonhosted.org/packages/53/3e/405b59cfa13021a56bba395a6b3aca8cec012b45bf177b0eaf7a202cde2c/contourpy-1.3.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:556dba8fb6f5d8742f2923fe9457dbdd51e1049c4a43fd3986a0b14a1d815fc6", size = 273979, upload-time = "2025-07-26T12:01:22.448Z" }, + { url = "https://files.pythonhosted.org/packages/d4/1c/a12359b9b2ca3a845e8f7f9ac08bdf776114eb931392fcad91743e2ea17b/contourpy-1.3.3-cp312-cp312-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:92d9abc807cf7d0e047b95ca5d957cf4792fcd04e920ca70d48add15c1a90ea7", size = 332653, upload-time = "2025-07-26T12:01:24.155Z" }, + { url = "https://files.pythonhosted.org/packages/63/12/897aeebfb475b7748ea67b61e045accdfcf0d971f8a588b67108ed7f5512/contourpy-1.3.3-cp312-cp312-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:b2e8faa0ed68cb29af51edd8e24798bb661eac3bd9f65420c1887b6ca89987c8", size = 379536, upload-time = "2025-07-26T12:01:25.91Z" }, + { url = "https://files.pythonhosted.org/packages/43/8a/a8c584b82deb248930ce069e71576fc09bd7174bbd35183b7943fb1064fd/contourpy-1.3.3-cp312-cp312-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:626d60935cf668e70a5ce6ff184fd713e9683fb458898e4249b63be9e28286ea", size = 384397, upload-time = "2025-07-26T12:01:27.152Z" }, + { url = "https://files.pythonhosted.org/packages/cc/8f/ec6289987824b29529d0dfda0d74a07cec60e54b9c92f3c9da4c0ac732de/contourpy-1.3.3-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4d00e655fcef08aba35ec9610536bfe90267d7ab5ba944f7032549c55a146da1", size = 362601, upload-time = "2025-07-26T12:01:28.808Z" }, + { url = "https://files.pythonhosted.org/packages/05/0a/a3fe3be3ee2dceb3e615ebb4df97ae6f3828aa915d3e10549ce016302bd1/contourpy-1.3.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:451e71b5a7d597379ef572de31eeb909a87246974d960049a9848c3bc6c41bf7", size = 1331288, upload-time = "2025-07-26T12:01:31.198Z" }, + { url = "https://files.pythonhosted.org/packages/33/1d/acad9bd4e97f13f3e2b18a3977fe1b4a37ecf3d38d815333980c6c72e963/contourpy-1.3.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:459c1f020cd59fcfe6650180678a9993932d80d44ccde1fa1868977438f0b411", size = 1403386, upload-time = "2025-07-26T12:01:33.947Z" }, + { url = "https://files.pythonhosted.org/packages/cf/8f/5847f44a7fddf859704217a99a23a4f6417b10e5ab1256a179264561540e/contourpy-1.3.3-cp312-cp312-win32.whl", hash = "sha256:023b44101dfe49d7d53932be418477dba359649246075c996866106da069af69", size = 185018, upload-time = "2025-07-26T12:01:35.64Z" }, + { url = "https://files.pythonhosted.org/packages/19/e8/6026ed58a64563186a9ee3f29f41261fd1828f527dd93d33b60feca63352/contourpy-1.3.3-cp312-cp312-win_amd64.whl", hash = "sha256:8153b8bfc11e1e4d75bcb0bff1db232f9e10b274e0929de9d608027e0d34ff8b", size = 226567, upload-time = "2025-07-26T12:01:36.804Z" }, + { url = "https://files.pythonhosted.org/packages/d1/e2/f05240d2c39a1ed228d8328a78b6f44cd695f7ef47beb3e684cf93604f86/contourpy-1.3.3-cp312-cp312-win_arm64.whl", hash = "sha256:07ce5ed73ecdc4a03ffe3e1b3e3c1166db35ae7584be76f65dbbe28a7791b0cc", size = 193655, upload-time = "2025-07-26T12:01:37.999Z" }, + { url = "https://files.pythonhosted.org/packages/68/35/0167aad910bbdb9599272bd96d01a9ec6852f36b9455cf2ca67bd4cc2d23/contourpy-1.3.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:177fb367556747a686509d6fef71d221a4b198a3905fe824430e5ea0fda54eb5", size = 293257, upload-time = "2025-07-26T12:01:39.367Z" }, + { url = "https://files.pythonhosted.org/packages/96/e4/7adcd9c8362745b2210728f209bfbcf7d91ba868a2c5f40d8b58f54c509b/contourpy-1.3.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d002b6f00d73d69333dac9d0b8d5e84d9724ff9ef044fd63c5986e62b7c9e1b1", size = 274034, upload-time = "2025-07-26T12:01:40.645Z" }, + { url = "https://files.pythonhosted.org/packages/73/23/90e31ceeed1de63058a02cb04b12f2de4b40e3bef5e082a7c18d9c8ae281/contourpy-1.3.3-cp313-cp313-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:348ac1f5d4f1d66d3322420f01d42e43122f43616e0f194fc1c9f5d830c5b286", size = 334672, upload-time = "2025-07-26T12:01:41.942Z" }, + { url = "https://files.pythonhosted.org/packages/ed/93/b43d8acbe67392e659e1d984700e79eb67e2acb2bd7f62012b583a7f1b55/contourpy-1.3.3-cp313-cp313-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:655456777ff65c2c548b7c454af9c6f33f16c8884f11083244b5819cc214f1b5", size = 381234, upload-time = "2025-07-26T12:01:43.499Z" }, + { url = "https://files.pythonhosted.org/packages/46/3b/bec82a3ea06f66711520f75a40c8fc0b113b2a75edb36aa633eb11c4f50f/contourpy-1.3.3-cp313-cp313-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:644a6853d15b2512d67881586bd03f462c7ab755db95f16f14d7e238f2852c67", size = 385169, upload-time = "2025-07-26T12:01:45.219Z" }, + { url = "https://files.pythonhosted.org/packages/4b/32/e0f13a1c5b0f8572d0ec6ae2f6c677b7991fafd95da523159c19eff0696a/contourpy-1.3.3-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4debd64f124ca62069f313a9cb86656ff087786016d76927ae2cf37846b006c9", size = 362859, upload-time = "2025-07-26T12:01:46.519Z" }, + { url = "https://files.pythonhosted.org/packages/33/71/e2a7945b7de4e58af42d708a219f3b2f4cff7386e6b6ab0a0fa0033c49a9/contourpy-1.3.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a15459b0f4615b00bbd1e91f1b9e19b7e63aea7483d03d804186f278c0af2659", size = 1332062, upload-time = "2025-07-26T12:01:48.964Z" }, + { url = "https://files.pythonhosted.org/packages/12/fc/4e87ac754220ccc0e807284f88e943d6d43b43843614f0a8afa469801db0/contourpy-1.3.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ca0fdcd73925568ca027e0b17ab07aad764be4706d0a925b89227e447d9737b7", size = 1403932, upload-time = "2025-07-26T12:01:51.979Z" }, + { url = "https://files.pythonhosted.org/packages/a6/2e/adc197a37443f934594112222ac1aa7dc9a98faf9c3842884df9a9d8751d/contourpy-1.3.3-cp313-cp313-win32.whl", hash = "sha256:b20c7c9a3bf701366556e1b1984ed2d0cedf999903c51311417cf5f591d8c78d", size = 185024, upload-time = "2025-07-26T12:01:53.245Z" }, + { url = "https://files.pythonhosted.org/packages/18/0b/0098c214843213759692cc638fce7de5c289200a830e5035d1791d7a2338/contourpy-1.3.3-cp313-cp313-win_amd64.whl", hash = "sha256:1cadd8b8969f060ba45ed7c1b714fe69185812ab43bd6b86a9123fe8f99c3263", size = 226578, upload-time = "2025-07-26T12:01:54.422Z" }, + { url = "https://files.pythonhosted.org/packages/8a/9a/2f6024a0c5995243cd63afdeb3651c984f0d2bc727fd98066d40e141ad73/contourpy-1.3.3-cp313-cp313-win_arm64.whl", hash = "sha256:fd914713266421b7536de2bfa8181aa8c699432b6763a0ea64195ebe28bff6a9", size = 193524, upload-time = "2025-07-26T12:01:55.73Z" }, + { url = "https://files.pythonhosted.org/packages/c0/b3/f8a1a86bd3298513f500e5b1f5fd92b69896449f6cab6a146a5d52715479/contourpy-1.3.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:88df9880d507169449d434c293467418b9f6cbe82edd19284aa0409e7fdb933d", size = 306730, upload-time = "2025-07-26T12:01:57.051Z" }, + { url = "https://files.pythonhosted.org/packages/3f/11/4780db94ae62fc0c2053909b65dc3246bd7cecfc4f8a20d957ad43aa4ad8/contourpy-1.3.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:d06bb1f751ba5d417047db62bca3c8fde202b8c11fb50742ab3ab962c81e8216", size = 287897, upload-time = "2025-07-26T12:01:58.663Z" }, + { url = "https://files.pythonhosted.org/packages/ae/15/e59f5f3ffdd6f3d4daa3e47114c53daabcb18574a26c21f03dc9e4e42ff0/contourpy-1.3.3-cp313-cp313t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e4e6b05a45525357e382909a4c1600444e2a45b4795163d3b22669285591c1ae", size = 326751, upload-time = "2025-07-26T12:02:00.343Z" }, + { url = "https://files.pythonhosted.org/packages/0f/81/03b45cfad088e4770b1dcf72ea78d3802d04200009fb364d18a493857210/contourpy-1.3.3-cp313-cp313t-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ab3074b48c4e2cf1a960e6bbeb7f04566bf36b1861d5c9d4d8ac04b82e38ba20", size = 375486, upload-time = "2025-07-26T12:02:02.128Z" }, + { url = "https://files.pythonhosted.org/packages/0c/ba/49923366492ffbdd4486e970d421b289a670ae8cf539c1ea9a09822b371a/contourpy-1.3.3-cp313-cp313t-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:6c3d53c796f8647d6deb1abe867daeb66dcc8a97e8455efa729516b997b8ed99", size = 388106, upload-time = "2025-07-26T12:02:03.615Z" }, + { url = "https://files.pythonhosted.org/packages/9f/52/5b00ea89525f8f143651f9f03a0df371d3cbd2fccd21ca9b768c7a6500c2/contourpy-1.3.3-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:50ed930df7289ff2a8d7afeb9603f8289e5704755c7e5c3bbd929c90c817164b", size = 352548, upload-time = "2025-07-26T12:02:05.165Z" }, + { url = "https://files.pythonhosted.org/packages/32/1d/a209ec1a3a3452d490f6b14dd92e72280c99ae3d1e73da74f8277d4ee08f/contourpy-1.3.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:4feffb6537d64b84877da813a5c30f1422ea5739566abf0bd18065ac040e120a", size = 1322297, upload-time = "2025-07-26T12:02:07.379Z" }, + { url = "https://files.pythonhosted.org/packages/bc/9e/46f0e8ebdd884ca0e8877e46a3f4e633f6c9c8c4f3f6e72be3fe075994aa/contourpy-1.3.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:2b7e9480ffe2b0cd2e787e4df64270e3a0440d9db8dc823312e2c940c167df7e", size = 1391023, upload-time = "2025-07-26T12:02:10.171Z" }, + { url = "https://files.pythonhosted.org/packages/b9/70/f308384a3ae9cd2209e0849f33c913f658d3326900d0ff5d378d6a1422d2/contourpy-1.3.3-cp313-cp313t-win32.whl", hash = "sha256:283edd842a01e3dcd435b1c5116798d661378d83d36d337b8dde1d16a5fc9ba3", size = 196157, upload-time = "2025-07-26T12:02:11.488Z" }, + { url = "https://files.pythonhosted.org/packages/b2/dd/880f890a6663b84d9e34a6f88cded89d78f0091e0045a284427cb6b18521/contourpy-1.3.3-cp313-cp313t-win_amd64.whl", hash = "sha256:87acf5963fc2b34825e5b6b048f40e3635dd547f590b04d2ab317c2619ef7ae8", size = 240570, upload-time = "2025-07-26T12:02:12.754Z" }, + { url = "https://files.pythonhosted.org/packages/80/99/2adc7d8ffead633234817ef8e9a87115c8a11927a94478f6bb3d3f4d4f7d/contourpy-1.3.3-cp313-cp313t-win_arm64.whl", hash = "sha256:3c30273eb2a55024ff31ba7d052dde990d7d8e5450f4bbb6e913558b3d6c2301", size = 199713, upload-time = "2025-07-26T12:02:14.4Z" }, + { url = "https://files.pythonhosted.org/packages/72/8b/4546f3ab60f78c514ffb7d01a0bd743f90de36f0019d1be84d0a708a580a/contourpy-1.3.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:fde6c716d51c04b1c25d0b90364d0be954624a0ee9d60e23e850e8d48353d07a", size = 292189, upload-time = "2025-07-26T12:02:16.095Z" }, + { url = "https://files.pythonhosted.org/packages/fd/e1/3542a9cb596cadd76fcef413f19c79216e002623158befe6daa03dbfa88c/contourpy-1.3.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:cbedb772ed74ff5be440fa8eee9bd49f64f6e3fc09436d9c7d8f1c287b121d77", size = 273251, upload-time = "2025-07-26T12:02:17.524Z" }, + { url = "https://files.pythonhosted.org/packages/b1/71/f93e1e9471d189f79d0ce2497007731c1e6bf9ef6d1d61b911430c3db4e5/contourpy-1.3.3-cp314-cp314-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:22e9b1bd7a9b1d652cd77388465dc358dafcd2e217d35552424aa4f996f524f5", size = 335810, upload-time = "2025-07-26T12:02:18.9Z" }, + { url = "https://files.pythonhosted.org/packages/91/f9/e35f4c1c93f9275d4e38681a80506b5510e9327350c51f8d4a5a724d178c/contourpy-1.3.3-cp314-cp314-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a22738912262aa3e254e4f3cb079a95a67132fc5a063890e224393596902f5a4", size = 382871, upload-time = "2025-07-26T12:02:20.418Z" }, + { url = "https://files.pythonhosted.org/packages/b5/71/47b512f936f66a0a900d81c396a7e60d73419868fba959c61efed7a8ab46/contourpy-1.3.3-cp314-cp314-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:afe5a512f31ee6bd7d0dda52ec9864c984ca3d66664444f2d72e0dc4eb832e36", size = 386264, upload-time = "2025-07-26T12:02:21.916Z" }, + { url = "https://files.pythonhosted.org/packages/04/5f/9ff93450ba96b09c7c2b3f81c94de31c89f92292f1380261bd7195bea4ea/contourpy-1.3.3-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f64836de09927cba6f79dcd00fdd7d5329f3fccc633468507079c829ca4db4e3", size = 363819, upload-time = "2025-07-26T12:02:23.759Z" }, + { url = "https://files.pythonhosted.org/packages/3e/a6/0b185d4cc480ee494945cde102cb0149ae830b5fa17bf855b95f2e70ad13/contourpy-1.3.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:1fd43c3be4c8e5fd6e4f2baeae35ae18176cf2e5cced681cca908addf1cdd53b", size = 1333650, upload-time = "2025-07-26T12:02:26.181Z" }, + { url = "https://files.pythonhosted.org/packages/43/d7/afdc95580ca56f30fbcd3060250f66cedbde69b4547028863abd8aa3b47e/contourpy-1.3.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:6afc576f7b33cf00996e5c1102dc2a8f7cc89e39c0b55df93a0b78c1bd992b36", size = 1404833, upload-time = "2025-07-26T12:02:28.782Z" }, + { url = "https://files.pythonhosted.org/packages/e2/e2/366af18a6d386f41132a48f033cbd2102e9b0cf6345d35ff0826cd984566/contourpy-1.3.3-cp314-cp314-win32.whl", hash = "sha256:66c8a43a4f7b8df8b71ee1840e4211a3c8d93b214b213f590e18a1beca458f7d", size = 189692, upload-time = "2025-07-26T12:02:30.128Z" }, + { url = "https://files.pythonhosted.org/packages/7d/c2/57f54b03d0f22d4044b8afb9ca0e184f8b1afd57b4f735c2fa70883dc601/contourpy-1.3.3-cp314-cp314-win_amd64.whl", hash = "sha256:cf9022ef053f2694e31d630feaacb21ea24224be1c3ad0520b13d844274614fd", size = 232424, upload-time = "2025-07-26T12:02:31.395Z" }, + { url = "https://files.pythonhosted.org/packages/18/79/a9416650df9b525737ab521aa181ccc42d56016d2123ddcb7b58e926a42c/contourpy-1.3.3-cp314-cp314-win_arm64.whl", hash = "sha256:95b181891b4c71de4bb404c6621e7e2390745f887f2a026b2d99e92c17892339", size = 198300, upload-time = "2025-07-26T12:02:32.956Z" }, + { url = "https://files.pythonhosted.org/packages/1f/42/38c159a7d0f2b7b9c04c64ab317042bb6952b713ba875c1681529a2932fe/contourpy-1.3.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:33c82d0138c0a062380332c861387650c82e4cf1747aaa6938b9b6516762e772", size = 306769, upload-time = "2025-07-26T12:02:34.2Z" }, + { url = "https://files.pythonhosted.org/packages/c3/6c/26a8205f24bca10974e77460de68d3d7c63e282e23782f1239f226fcae6f/contourpy-1.3.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:ea37e7b45949df430fe649e5de8351c423430046a2af20b1c1961cae3afcda77", size = 287892, upload-time = "2025-07-26T12:02:35.807Z" }, + { url = "https://files.pythonhosted.org/packages/66/06/8a475c8ab718ebfd7925661747dbb3c3ee9c82ac834ccb3570be49d129f4/contourpy-1.3.3-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d304906ecc71672e9c89e87c4675dc5c2645e1f4269a5063b99b0bb29f232d13", size = 326748, upload-time = "2025-07-26T12:02:37.193Z" }, + { url = "https://files.pythonhosted.org/packages/b4/a3/c5ca9f010a44c223f098fccd8b158bb1cb287378a31ac141f04730dc49be/contourpy-1.3.3-cp314-cp314t-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ca658cd1a680a5c9ea96dc61cdbae1e85c8f25849843aa799dfd3cb370ad4fbe", size = 375554, upload-time = "2025-07-26T12:02:38.894Z" }, + { url = "https://files.pythonhosted.org/packages/80/5b/68bd33ae63fac658a4145088c1e894405e07584a316738710b636c6d0333/contourpy-1.3.3-cp314-cp314t-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:ab2fd90904c503739a75b7c8c5c01160130ba67944a7b77bbf36ef8054576e7f", size = 388118, upload-time = "2025-07-26T12:02:40.642Z" }, + { url = "https://files.pythonhosted.org/packages/40/52/4c285a6435940ae25d7410a6c36bda5145839bc3f0beb20c707cda18b9d2/contourpy-1.3.3-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b7301b89040075c30e5768810bc96a8e8d78085b47d8be6e4c3f5a0b4ed478a0", size = 352555, upload-time = "2025-07-26T12:02:42.25Z" }, + { url = "https://files.pythonhosted.org/packages/24/ee/3e81e1dd174f5c7fefe50e85d0892de05ca4e26ef1c9a59c2a57e43b865a/contourpy-1.3.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:2a2a8b627d5cc6b7c41a4beff6c5ad5eb848c88255fda4a8745f7e901b32d8e4", size = 1322295, upload-time = "2025-07-26T12:02:44.668Z" }, + { url = "https://files.pythonhosted.org/packages/3c/b2/6d913d4d04e14379de429057cd169e5e00f6c2af3bb13e1710bcbdb5da12/contourpy-1.3.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:fd6ec6be509c787f1caf6b247f0b1ca598bef13f4ddeaa126b7658215529ba0f", size = 1391027, upload-time = "2025-07-26T12:02:47.09Z" }, + { url = "https://files.pythonhosted.org/packages/93/8a/68a4ec5c55a2971213d29a9374913f7e9f18581945a7a31d1a39b5d2dfe5/contourpy-1.3.3-cp314-cp314t-win32.whl", hash = "sha256:e74a9a0f5e3fff48fb5a7f2fd2b9b70a3fe014a67522f79b7cca4c0c7e43c9ae", size = 202428, upload-time = "2025-07-26T12:02:48.691Z" }, + { url = "https://files.pythonhosted.org/packages/fa/96/fd9f641ffedc4fa3ace923af73b9d07e869496c9cc7a459103e6e978992f/contourpy-1.3.3-cp314-cp314t-win_amd64.whl", hash = "sha256:13b68d6a62db8eafaebb8039218921399baf6e47bf85006fd8529f2a08ef33fc", size = 250331, upload-time = "2025-07-26T12:02:50.137Z" }, + { url = "https://files.pythonhosted.org/packages/ae/8c/469afb6465b853afff216f9528ffda78a915ff880ed58813ba4faf4ba0b6/contourpy-1.3.3-cp314-cp314t-win_arm64.whl", hash = "sha256:b7448cb5a725bb1e35ce88771b86fba35ef418952474492cf7c764059933ff8b", size = 203831, upload-time = "2025-07-26T12:02:51.449Z" }, + { url = "https://files.pythonhosted.org/packages/a5/29/8dcfe16f0107943fa92388c23f6e05cff0ba58058c4c95b00280d4c75a14/contourpy-1.3.3-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:cd5dfcaeb10f7b7f9dc8941717c6c2ade08f587be2226222c12b25f0483ed497", size = 278809, upload-time = "2025-07-26T12:02:52.74Z" }, + { url = "https://files.pythonhosted.org/packages/85/a9/8b37ef4f7dafeb335daee3c8254645ef5725be4d9c6aa70b50ec46ef2f7e/contourpy-1.3.3-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:0c1fc238306b35f246d61a1d416a627348b5cf0648648a031e14bb8705fcdfe8", size = 261593, upload-time = "2025-07-26T12:02:54.037Z" }, + { url = "https://files.pythonhosted.org/packages/0a/59/ebfb8c677c75605cc27f7122c90313fd2f375ff3c8d19a1694bda74aaa63/contourpy-1.3.3-pp311-pypy311_pp73-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:70f9aad7de812d6541d29d2bbf8feb22ff7e1c299523db288004e3157ff4674e", size = 302202, upload-time = "2025-07-26T12:02:55.947Z" }, + { url = "https://files.pythonhosted.org/packages/3c/37/21972a15834d90bfbfb009b9d004779bd5a07a0ec0234e5ba8f64d5736f4/contourpy-1.3.3-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5ed3657edf08512fc3fe81b510e35c2012fbd3081d2e26160f27ca28affec989", size = 329207, upload-time = "2025-07-26T12:02:57.468Z" }, + { url = "https://files.pythonhosted.org/packages/0c/58/bd257695f39d05594ca4ad60df5bcb7e32247f9951fd09a9b8edb82d1daa/contourpy-1.3.3-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:3d1a3799d62d45c18bafd41c5fa05120b96a28079f2393af559b843d1a966a77", size = 225315, upload-time = "2025-07-26T12:02:58.801Z" }, ] [[package]] name = "coverage" -version = "7.9.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/04/b7/c0465ca253df10a9e8dae0692a4ae6e9726d245390aaef92360e1d6d3832/coverage-7.9.2.tar.gz", hash = "sha256:997024fa51e3290264ffd7492ec97d0690293ccd2b45a6cd7d82d945a4a80c8b", size = 813556, upload-time = "2025-07-03T10:54:15.101Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/39/40/916786453bcfafa4c788abee4ccd6f592b5b5eca0cd61a32a4e5a7ef6e02/coverage-7.9.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a7a56a2964a9687b6aba5b5ced6971af308ef6f79a91043c05dd4ee3ebc3e9ba", size = 212152, upload-time = "2025-07-03T10:52:53.562Z" }, - { url = "https://files.pythonhosted.org/packages/9f/66/cc13bae303284b546a030762957322bbbff1ee6b6cb8dc70a40f8a78512f/coverage-7.9.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:123d589f32c11d9be7fe2e66d823a236fe759b0096f5db3fb1b75b2fa414a4fa", size = 212540, upload-time = "2025-07-03T10:52:55.196Z" }, - { url = "https://files.pythonhosted.org/packages/0f/3c/d56a764b2e5a3d43257c36af4a62c379df44636817bb5f89265de4bf8bd7/coverage-7.9.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:333b2e0ca576a7dbd66e85ab402e35c03b0b22f525eed82681c4b866e2e2653a", size = 245097, upload-time = "2025-07-03T10:52:56.509Z" }, - { url = "https://files.pythonhosted.org/packages/b1/46/bd064ea8b3c94eb4ca5d90e34d15b806cba091ffb2b8e89a0d7066c45791/coverage-7.9.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:326802760da234baf9f2f85a39e4a4b5861b94f6c8d95251f699e4f73b1835dc", size = 242812, upload-time = "2025-07-03T10:52:57.842Z" }, - { url = "https://files.pythonhosted.org/packages/43/02/d91992c2b29bc7afb729463bc918ebe5f361be7f1daae93375a5759d1e28/coverage-7.9.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:19e7be4cfec248df38ce40968c95d3952fbffd57b400d4b9bb580f28179556d2", size = 244617, upload-time = "2025-07-03T10:52:59.239Z" }, - { url = "https://files.pythonhosted.org/packages/b7/4f/8fadff6bf56595a16d2d6e33415841b0163ac660873ed9a4e9046194f779/coverage-7.9.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0b4a4cb73b9f2b891c1788711408ef9707666501ba23684387277ededab1097c", size = 244263, upload-time = "2025-07-03T10:53:00.601Z" }, - { url = "https://files.pythonhosted.org/packages/9b/d2/e0be7446a2bba11739edb9f9ba4eff30b30d8257370e237418eb44a14d11/coverage-7.9.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:2c8937fa16c8c9fbbd9f118588756e7bcdc7e16a470766a9aef912dd3f117dbd", size = 242314, upload-time = "2025-07-03T10:53:01.932Z" }, - { url = "https://files.pythonhosted.org/packages/9d/7d/dcbac9345000121b8b57a3094c2dfcf1ccc52d8a14a40c1d4bc89f936f80/coverage-7.9.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:42da2280c4d30c57a9b578bafd1d4494fa6c056d4c419d9689e66d775539be74", size = 242904, upload-time = "2025-07-03T10:53:03.478Z" }, - { url = "https://files.pythonhosted.org/packages/41/58/11e8db0a0c0510cf31bbbdc8caf5d74a358b696302a45948d7c768dfd1cf/coverage-7.9.2-cp311-cp311-win32.whl", hash = "sha256:14fa8d3da147f5fdf9d298cacc18791818f3f1a9f542c8958b80c228320e90c6", size = 214553, upload-time = "2025-07-03T10:53:05.174Z" }, - { url = "https://files.pythonhosted.org/packages/3a/7d/751794ec8907a15e257136e48dc1021b1f671220ecccfd6c4eaf30802714/coverage-7.9.2-cp311-cp311-win_amd64.whl", hash = "sha256:549cab4892fc82004f9739963163fd3aac7a7b0df430669b75b86d293d2df2a7", size = 215441, upload-time = "2025-07-03T10:53:06.472Z" }, - { url = "https://files.pythonhosted.org/packages/62/5b/34abcedf7b946c1c9e15b44f326cb5b0da852885312b30e916f674913428/coverage-7.9.2-cp311-cp311-win_arm64.whl", hash = "sha256:c2667a2b913e307f06aa4e5677f01a9746cd08e4b35e14ebcde6420a9ebb4c62", size = 213873, upload-time = "2025-07-03T10:53:07.699Z" }, - { url = "https://files.pythonhosted.org/packages/53/d7/7deefc6fd4f0f1d4c58051f4004e366afc9e7ab60217ac393f247a1de70a/coverage-7.9.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:ae9eb07f1cfacd9cfe8eaee6f4ff4b8a289a668c39c165cd0c8548484920ffc0", size = 212344, upload-time = "2025-07-03T10:53:09.3Z" }, - { url = "https://files.pythonhosted.org/packages/95/0c/ee03c95d32be4d519e6a02e601267769ce2e9a91fc8faa1b540e3626c680/coverage-7.9.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9ce85551f9a1119f02adc46d3014b5ee3f765deac166acf20dbb851ceb79b6f3", size = 212580, upload-time = "2025-07-03T10:53:11.52Z" }, - { url = "https://files.pythonhosted.org/packages/8b/9f/826fa4b544b27620086211b87a52ca67592622e1f3af9e0a62c87aea153a/coverage-7.9.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f8f6389ac977c5fb322e0e38885fbbf901743f79d47f50db706e7644dcdcb6e1", size = 246383, upload-time = "2025-07-03T10:53:13.134Z" }, - { url = "https://files.pythonhosted.org/packages/7f/b3/4477aafe2a546427b58b9c540665feff874f4db651f4d3cb21b308b3a6d2/coverage-7.9.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ff0d9eae8cdfcd58fe7893b88993723583a6ce4dfbfd9f29e001922544f95615", size = 243400, upload-time = "2025-07-03T10:53:14.614Z" }, - { url = "https://files.pythonhosted.org/packages/f8/c2/efffa43778490c226d9d434827702f2dfbc8041d79101a795f11cbb2cf1e/coverage-7.9.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fae939811e14e53ed8a9818dad51d434a41ee09df9305663735f2e2d2d7d959b", size = 245591, upload-time = "2025-07-03T10:53:15.872Z" }, - { url = "https://files.pythonhosted.org/packages/c6/e7/a59888e882c9a5f0192d8627a30ae57910d5d449c80229b55e7643c078c4/coverage-7.9.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:31991156251ec202c798501e0a42bbdf2169dcb0f137b1f5c0f4267f3fc68ef9", size = 245402, upload-time = "2025-07-03T10:53:17.124Z" }, - { url = "https://files.pythonhosted.org/packages/92/a5/72fcd653ae3d214927edc100ce67440ed8a0a1e3576b8d5e6d066ed239db/coverage-7.9.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:d0d67963f9cbfc7c7f96d4ac74ed60ecbebd2ea6eeb51887af0f8dce205e545f", size = 243583, upload-time = "2025-07-03T10:53:18.781Z" }, - { url = "https://files.pythonhosted.org/packages/5c/f5/84e70e4df28f4a131d580d7d510aa1ffd95037293da66fd20d446090a13b/coverage-7.9.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:49b752a2858b10580969ec6af6f090a9a440a64a301ac1528d7ca5f7ed497f4d", size = 244815, upload-time = "2025-07-03T10:53:20.168Z" }, - { url = "https://files.pythonhosted.org/packages/39/e7/d73d7cbdbd09fdcf4642655ae843ad403d9cbda55d725721965f3580a314/coverage-7.9.2-cp312-cp312-win32.whl", hash = "sha256:88d7598b8ee130f32f8a43198ee02edd16d7f77692fa056cb779616bbea1b355", size = 214719, upload-time = "2025-07-03T10:53:21.521Z" }, - { url = "https://files.pythonhosted.org/packages/9f/d6/7486dcc3474e2e6ad26a2af2db7e7c162ccd889c4c68fa14ea8ec189c9e9/coverage-7.9.2-cp312-cp312-win_amd64.whl", hash = "sha256:9dfb070f830739ee49d7c83e4941cc767e503e4394fdecb3b54bfdac1d7662c0", size = 215509, upload-time = "2025-07-03T10:53:22.853Z" }, - { url = "https://files.pythonhosted.org/packages/b7/34/0439f1ae2593b0346164d907cdf96a529b40b7721a45fdcf8b03c95fcd90/coverage-7.9.2-cp312-cp312-win_arm64.whl", hash = "sha256:4e2c058aef613e79df00e86b6d42a641c877211384ce5bd07585ed7ba71ab31b", size = 213910, upload-time = "2025-07-03T10:53:24.472Z" }, - { url = "https://files.pythonhosted.org/packages/94/9d/7a8edf7acbcaa5e5c489a646226bed9591ee1c5e6a84733c0140e9ce1ae1/coverage-7.9.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:985abe7f242e0d7bba228ab01070fde1d6c8fa12f142e43debe9ed1dde686038", size = 212367, upload-time = "2025-07-03T10:53:25.811Z" }, - { url = "https://files.pythonhosted.org/packages/e8/9e/5cd6f130150712301f7e40fb5865c1bc27b97689ec57297e568d972eec3c/coverage-7.9.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:82c3939264a76d44fde7f213924021ed31f55ef28111a19649fec90c0f109e6d", size = 212632, upload-time = "2025-07-03T10:53:27.075Z" }, - { url = "https://files.pythonhosted.org/packages/a8/de/6287a2c2036f9fd991c61cefa8c64e57390e30c894ad3aa52fac4c1e14a8/coverage-7.9.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ae5d563e970dbe04382f736ec214ef48103d1b875967c89d83c6e3f21706d5b3", size = 245793, upload-time = "2025-07-03T10:53:28.408Z" }, - { url = "https://files.pythonhosted.org/packages/06/cc/9b5a9961d8160e3cb0b558c71f8051fe08aa2dd4b502ee937225da564ed1/coverage-7.9.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bdd612e59baed2a93c8843c9a7cb902260f181370f1d772f4842987535071d14", size = 243006, upload-time = "2025-07-03T10:53:29.754Z" }, - { url = "https://files.pythonhosted.org/packages/49/d9/4616b787d9f597d6443f5588619c1c9f659e1f5fc9eebf63699eb6d34b78/coverage-7.9.2-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:256ea87cb2a1ed992bcdfc349d8042dcea1b80436f4ddf6e246d6bee4b5d73b6", size = 244990, upload-time = "2025-07-03T10:53:31.098Z" }, - { url = "https://files.pythonhosted.org/packages/48/83/801cdc10f137b2d02b005a761661649ffa60eb173dcdaeb77f571e4dc192/coverage-7.9.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f44ae036b63c8ea432f610534a2668b0c3aee810e7037ab9d8ff6883de480f5b", size = 245157, upload-time = "2025-07-03T10:53:32.717Z" }, - { url = "https://files.pythonhosted.org/packages/c8/a4/41911ed7e9d3ceb0ffb019e7635468df7499f5cc3edca5f7dfc078e9c5ec/coverage-7.9.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:82d76ad87c932935417a19b10cfe7abb15fd3f923cfe47dbdaa74ef4e503752d", size = 243128, upload-time = "2025-07-03T10:53:34.009Z" }, - { url = "https://files.pythonhosted.org/packages/10/41/344543b71d31ac9cb00a664d5d0c9ef134a0fe87cb7d8430003b20fa0b7d/coverage-7.9.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:619317bb86de4193debc712b9e59d5cffd91dc1d178627ab2a77b9870deb2868", size = 244511, upload-time = "2025-07-03T10:53:35.434Z" }, - { url = "https://files.pythonhosted.org/packages/d5/81/3b68c77e4812105e2a060f6946ba9e6f898ddcdc0d2bfc8b4b152a9ae522/coverage-7.9.2-cp313-cp313-win32.whl", hash = "sha256:0a07757de9feb1dfafd16ab651e0f628fd7ce551604d1bf23e47e1ddca93f08a", size = 214765, upload-time = "2025-07-03T10:53:36.787Z" }, - { url = "https://files.pythonhosted.org/packages/06/a2/7fac400f6a346bb1a4004eb2a76fbff0e242cd48926a2ce37a22a6a1d917/coverage-7.9.2-cp313-cp313-win_amd64.whl", hash = "sha256:115db3d1f4d3f35f5bb021e270edd85011934ff97c8797216b62f461dd69374b", size = 215536, upload-time = "2025-07-03T10:53:38.188Z" }, - { url = "https://files.pythonhosted.org/packages/08/47/2c6c215452b4f90d87017e61ea0fd9e0486bb734cb515e3de56e2c32075f/coverage-7.9.2-cp313-cp313-win_arm64.whl", hash = "sha256:48f82f889c80af8b2a7bb6e158d95a3fbec6a3453a1004d04e4f3b5945a02694", size = 213943, upload-time = "2025-07-03T10:53:39.492Z" }, - { url = "https://files.pythonhosted.org/packages/a3/46/e211e942b22d6af5e0f323faa8a9bc7c447a1cf1923b64c47523f36ed488/coverage-7.9.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:55a28954545f9d2f96870b40f6c3386a59ba8ed50caf2d949676dac3ecab99f5", size = 213088, upload-time = "2025-07-03T10:53:40.874Z" }, - { url = "https://files.pythonhosted.org/packages/d2/2f/762551f97e124442eccd907bf8b0de54348635b8866a73567eb4e6417acf/coverage-7.9.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:cdef6504637731a63c133bb2e6f0f0214e2748495ec15fe42d1e219d1b133f0b", size = 213298, upload-time = "2025-07-03T10:53:42.218Z" }, - { url = "https://files.pythonhosted.org/packages/7a/b7/76d2d132b7baf7360ed69be0bcab968f151fa31abe6d067f0384439d9edb/coverage-7.9.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bcd5ebe66c7a97273d5d2ddd4ad0ed2e706b39630ed4b53e713d360626c3dbb3", size = 256541, upload-time = "2025-07-03T10:53:43.823Z" }, - { url = "https://files.pythonhosted.org/packages/a0/17/392b219837d7ad47d8e5974ce5f8dc3deb9f99a53b3bd4d123602f960c81/coverage-7.9.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9303aed20872d7a3c9cb39c5d2b9bdbe44e3a9a1aecb52920f7e7495410dfab8", size = 252761, upload-time = "2025-07-03T10:53:45.19Z" }, - { url = "https://files.pythonhosted.org/packages/d5/77/4256d3577fe1b0daa8d3836a1ebe68eaa07dd2cbaf20cf5ab1115d6949d4/coverage-7.9.2-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc18ea9e417a04d1920a9a76fe9ebd2f43ca505b81994598482f938d5c315f46", size = 254917, upload-time = "2025-07-03T10:53:46.931Z" }, - { url = "https://files.pythonhosted.org/packages/53/99/fc1a008eef1805e1ddb123cf17af864743354479ea5129a8f838c433cc2c/coverage-7.9.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:6406cff19880aaaadc932152242523e892faff224da29e241ce2fca329866584", size = 256147, upload-time = "2025-07-03T10:53:48.289Z" }, - { url = "https://files.pythonhosted.org/packages/92/c0/f63bf667e18b7f88c2bdb3160870e277c4874ced87e21426128d70aa741f/coverage-7.9.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:2d0d4f6ecdf37fcc19c88fec3e2277d5dee740fb51ffdd69b9579b8c31e4232e", size = 254261, upload-time = "2025-07-03T10:53:49.99Z" }, - { url = "https://files.pythonhosted.org/packages/8c/32/37dd1c42ce3016ff8ec9e4b607650d2e34845c0585d3518b2a93b4830c1a/coverage-7.9.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:c33624f50cf8de418ab2b4d6ca9eda96dc45b2c4231336bac91454520e8d1fac", size = 255099, upload-time = "2025-07-03T10:53:51.354Z" }, - { url = "https://files.pythonhosted.org/packages/da/2e/af6b86f7c95441ce82f035b3affe1cd147f727bbd92f563be35e2d585683/coverage-7.9.2-cp313-cp313t-win32.whl", hash = "sha256:1df6b76e737c6a92210eebcb2390af59a141f9e9430210595251fbaf02d46926", size = 215440, upload-time = "2025-07-03T10:53:52.808Z" }, - { url = "https://files.pythonhosted.org/packages/4d/bb/8a785d91b308867f6b2e36e41c569b367c00b70c17f54b13ac29bcd2d8c8/coverage-7.9.2-cp313-cp313t-win_amd64.whl", hash = "sha256:f5fd54310b92741ebe00d9c0d1d7b2b27463952c022da6d47c175d246a98d1bd", size = 216537, upload-time = "2025-07-03T10:53:54.273Z" }, - { url = "https://files.pythonhosted.org/packages/1d/a0/a6bffb5e0f41a47279fd45a8f3155bf193f77990ae1c30f9c224b61cacb0/coverage-7.9.2-cp313-cp313t-win_arm64.whl", hash = "sha256:c48c2375287108c887ee87d13b4070a381c6537d30e8487b24ec721bf2a781cb", size = 214398, upload-time = "2025-07-03T10:53:56.715Z" }, - { url = "https://files.pythonhosted.org/packages/d7/85/f8bbefac27d286386961c25515431482a425967e23d3698b75a250872924/coverage-7.9.2-pp39.pp310.pp311-none-any.whl", hash = "sha256:8a1166db2fb62473285bcb092f586e081e92656c7dfa8e9f62b4d39d7e6b5050", size = 204013, upload-time = "2025-07-03T10:54:12.084Z" }, - { url = "https://files.pythonhosted.org/packages/3c/38/bbe2e63902847cf79036ecc75550d0698af31c91c7575352eb25190d0fb3/coverage-7.9.2-py3-none-any.whl", hash = "sha256:e425cd5b00f6fc0ed7cdbd766c70be8baab4b7839e4d4fe5fac48581dd968ea4", size = 204005, upload-time = "2025-07-03T10:54:13.491Z" }, +version = "7.10.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/87/0e/66dbd4c6a7f0758a8d18044c048779ba21fb94856e1edcf764bd5403e710/coverage-7.10.1.tar.gz", hash = "sha256:ae2b4856f29ddfe827106794f3589949a57da6f0d38ab01e24ec35107979ba57", size = 819938, upload-time = "2025-07-27T14:13:39.045Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/20/8e/ef088112bd1b26e2aa931ee186992b3e42c222c64f33e381432c8ee52aae/coverage-7.10.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b45e2f9d5b0b5c1977cb4feb5f594be60eb121106f8900348e29331f553a726f", size = 214747, upload-time = "2025-07-27T14:11:18.217Z" }, + { url = "https://files.pythonhosted.org/packages/2d/76/a1e46f3c6e0897758eb43af88bb3c763cb005f4950769f7b553e22aa5f89/coverage-7.10.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3a7a4d74cb0f5e3334f9aa26af7016ddb94fb4bfa11b4a573d8e98ecba8c34f1", size = 215128, upload-time = "2025-07-27T14:11:19.706Z" }, + { url = "https://files.pythonhosted.org/packages/78/4d/903bafb371a8c887826ecc30d3977b65dfad0e1e66aa61b7e173de0828b0/coverage-7.10.1-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:d4b0aab55ad60ead26159ff12b538c85fbab731a5e3411c642b46c3525863437", size = 245140, upload-time = "2025-07-27T14:11:21.261Z" }, + { url = "https://files.pythonhosted.org/packages/55/f1/1f8f09536f38394a8698dd08a0e9608a512eacee1d3b771e2d06397f77bf/coverage-7.10.1-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:dcc93488c9ebd229be6ee1f0d9aad90da97b33ad7e2912f5495804d78a3cd6b7", size = 246977, upload-time = "2025-07-27T14:11:23.15Z" }, + { url = "https://files.pythonhosted.org/packages/57/cc/ed6bbc5a3bdb36ae1bca900bbbfdcb23b260ef2767a7b2dab38b92f61adf/coverage-7.10.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:aa309df995d020f3438407081b51ff527171cca6772b33cf8f85344b8b4b8770", size = 249140, upload-time = "2025-07-27T14:11:24.743Z" }, + { url = "https://files.pythonhosted.org/packages/10/f5/e881ade2d8e291b60fa1d93d6d736107e940144d80d21a0d4999cff3642f/coverage-7.10.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:cfb8b9d8855c8608f9747602a48ab525b1d320ecf0113994f6df23160af68262", size = 246869, upload-time = "2025-07-27T14:11:26.156Z" }, + { url = "https://files.pythonhosted.org/packages/53/b9/6a5665cb8996e3cd341d184bb11e2a8edf01d8dadcf44eb1e742186cf243/coverage-7.10.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:320d86da829b012982b414c7cdda65f5d358d63f764e0e4e54b33097646f39a3", size = 244899, upload-time = "2025-07-27T14:11:27.622Z" }, + { url = "https://files.pythonhosted.org/packages/27/11/24156776709c4e25bf8a33d6bb2ece9a9067186ddac19990f6560a7f8130/coverage-7.10.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:dc60ddd483c556590da1d9482a4518292eec36dd0e1e8496966759a1f282bcd0", size = 245507, upload-time = "2025-07-27T14:11:29.544Z" }, + { url = "https://files.pythonhosted.org/packages/43/db/a6f0340b7d6802a79928659c9a32bc778ea420e87a61b568d68ac36d45a8/coverage-7.10.1-cp311-cp311-win32.whl", hash = "sha256:4fcfe294f95b44e4754da5b58be750396f2b1caca8f9a0e78588e3ef85f8b8be", size = 217167, upload-time = "2025-07-27T14:11:31.349Z" }, + { url = "https://files.pythonhosted.org/packages/f5/6f/1990eb4fd05cea4cfabdf1d587a997ac5f9a8bee883443a1d519a2a848c9/coverage-7.10.1-cp311-cp311-win_amd64.whl", hash = "sha256:efa23166da3fe2915f8ab452dde40319ac84dc357f635737174a08dbd912980c", size = 218054, upload-time = "2025-07-27T14:11:33.202Z" }, + { url = "https://files.pythonhosted.org/packages/b4/4d/5e061d6020251b20e9b4303bb0b7900083a1a384ec4e5db326336c1c4abd/coverage-7.10.1-cp311-cp311-win_arm64.whl", hash = "sha256:d12b15a8c3759e2bb580ffa423ae54be4f184cf23beffcbd641f4fe6e1584293", size = 216483, upload-time = "2025-07-27T14:11:34.663Z" }, + { url = "https://files.pythonhosted.org/packages/a5/3f/b051feeb292400bd22d071fdf933b3ad389a8cef5c80c7866ed0c7414b9e/coverage-7.10.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:6b7dc7f0a75a7eaa4584e5843c873c561b12602439d2351ee28c7478186c4da4", size = 214934, upload-time = "2025-07-27T14:11:36.096Z" }, + { url = "https://files.pythonhosted.org/packages/f8/e4/a61b27d5c4c2d185bdfb0bfe9d15ab4ac4f0073032665544507429ae60eb/coverage-7.10.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:607f82389f0ecafc565813aa201a5cade04f897603750028dd660fb01797265e", size = 215173, upload-time = "2025-07-27T14:11:38.005Z" }, + { url = "https://files.pythonhosted.org/packages/8a/01/40a6ee05b60d02d0bc53742ad4966e39dccd450aafb48c535a64390a3552/coverage-7.10.1-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:f7da31a1ba31f1c1d4d5044b7c5813878adae1f3af8f4052d679cc493c7328f4", size = 246190, upload-time = "2025-07-27T14:11:39.887Z" }, + { url = "https://files.pythonhosted.org/packages/11/ef/a28d64d702eb583c377255047281305dc5a5cfbfb0ee36e721f78255adb6/coverage-7.10.1-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:51fe93f3fe4f5d8483d51072fddc65e717a175490804e1942c975a68e04bf97a", size = 248618, upload-time = "2025-07-27T14:11:41.841Z" }, + { url = "https://files.pythonhosted.org/packages/6a/ad/73d018bb0c8317725370c79d69b5c6e0257df84a3b9b781bda27a438a3be/coverage-7.10.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3e59d00830da411a1feef6ac828b90bbf74c9b6a8e87b8ca37964925bba76dbe", size = 250081, upload-time = "2025-07-27T14:11:43.705Z" }, + { url = "https://files.pythonhosted.org/packages/2d/dd/496adfbbb4503ebca5d5b2de8bed5ec00c0a76558ffc5b834fd404166bc9/coverage-7.10.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:924563481c27941229cb4e16eefacc35da28563e80791b3ddc5597b062a5c386", size = 247990, upload-time = "2025-07-27T14:11:45.244Z" }, + { url = "https://files.pythonhosted.org/packages/18/3c/a9331a7982facfac0d98a4a87b36ae666fe4257d0f00961a3a9ef73e015d/coverage-7.10.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:ca79146ee421b259f8131f153102220b84d1a5e6fb9c8aed13b3badfd1796de6", size = 246191, upload-time = "2025-07-27T14:11:47.093Z" }, + { url = "https://files.pythonhosted.org/packages/62/0c/75345895013b83f7afe92ec595e15a9a525ede17491677ceebb2ba5c3d85/coverage-7.10.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:2b225a06d227f23f386fdc0eab471506d9e644be699424814acc7d114595495f", size = 247400, upload-time = "2025-07-27T14:11:48.643Z" }, + { url = "https://files.pythonhosted.org/packages/e2/a9/98b268cfc5619ef9df1d5d34fee408ecb1542d9fd43d467e5c2f28668cd4/coverage-7.10.1-cp312-cp312-win32.whl", hash = "sha256:5ba9a8770effec5baaaab1567be916c87d8eea0c9ad11253722d86874d885eca", size = 217338, upload-time = "2025-07-27T14:11:50.258Z" }, + { url = "https://files.pythonhosted.org/packages/fe/31/22a5440e4d1451f253c5cd69fdcead65e92ef08cd4ec237b8756dc0b20a7/coverage-7.10.1-cp312-cp312-win_amd64.whl", hash = "sha256:9eb245a8d8dd0ad73b4062135a251ec55086fbc2c42e0eb9725a9b553fba18a3", size = 218125, upload-time = "2025-07-27T14:11:52.034Z" }, + { url = "https://files.pythonhosted.org/packages/d6/2b/40d9f0ce7ee839f08a43c5bfc9d05cec28aaa7c9785837247f96cbe490b9/coverage-7.10.1-cp312-cp312-win_arm64.whl", hash = "sha256:7718060dd4434cc719803a5e526838a5d66e4efa5dc46d2b25c21965a9c6fcc4", size = 216523, upload-time = "2025-07-27T14:11:53.965Z" }, + { url = "https://files.pythonhosted.org/packages/ef/72/135ff5fef09b1ffe78dbe6fcf1e16b2e564cd35faeacf3d63d60d887f12d/coverage-7.10.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ebb08d0867c5a25dffa4823377292a0ffd7aaafb218b5d4e2e106378b1061e39", size = 214960, upload-time = "2025-07-27T14:11:55.959Z" }, + { url = "https://files.pythonhosted.org/packages/b1/aa/73a5d1a6fc08ca709a8177825616aa95ee6bf34d522517c2595484a3e6c9/coverage-7.10.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f32a95a83c2e17422f67af922a89422cd24c6fa94041f083dd0bb4f6057d0bc7", size = 215220, upload-time = "2025-07-27T14:11:57.899Z" }, + { url = "https://files.pythonhosted.org/packages/8d/40/3124fdd45ed3772a42fc73ca41c091699b38a2c3bd4f9cb564162378e8b6/coverage-7.10.1-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:c4c746d11c8aba4b9f58ca8bfc6fbfd0da4efe7960ae5540d1a1b13655ee8892", size = 245772, upload-time = "2025-07-27T14:12:00.422Z" }, + { url = "https://files.pythonhosted.org/packages/42/62/a77b254822efa8c12ad59e8039f2bc3df56dc162ebda55e1943e35ba31a5/coverage-7.10.1-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:7f39edd52c23e5c7ed94e0e4bf088928029edf86ef10b95413e5ea670c5e92d7", size = 248116, upload-time = "2025-07-27T14:12:03.099Z" }, + { url = "https://files.pythonhosted.org/packages/1d/01/8101f062f472a3a6205b458d18ef0444a63ae5d36a8a5ed5dd0f6167f4db/coverage-7.10.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ab6e19b684981d0cd968906e293d5628e89faacb27977c92f3600b201926b994", size = 249554, upload-time = "2025-07-27T14:12:04.668Z" }, + { url = "https://files.pythonhosted.org/packages/8f/7b/e51bc61573e71ff7275a4f167aecbd16cb010aefdf54bcd8b0a133391263/coverage-7.10.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:5121d8cf0eacb16133501455d216bb5f99899ae2f52d394fe45d59229e6611d0", size = 247766, upload-time = "2025-07-27T14:12:06.234Z" }, + { url = "https://files.pythonhosted.org/packages/4b/71/1c96d66a51d4204a9d6d12df53c4071d87e110941a2a1fe94693192262f5/coverage-7.10.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:df1c742ca6f46a6f6cbcaef9ac694dc2cb1260d30a6a2f5c68c5f5bcfee1cfd7", size = 245735, upload-time = "2025-07-27T14:12:08.305Z" }, + { url = "https://files.pythonhosted.org/packages/13/d5/efbc2ac4d35ae2f22ef6df2ca084c60e13bd9378be68655e3268c80349ab/coverage-7.10.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:40f9a38676f9c073bf4b9194707aa1eb97dca0e22cc3766d83879d72500132c7", size = 247118, upload-time = "2025-07-27T14:12:09.903Z" }, + { url = "https://files.pythonhosted.org/packages/d1/22/073848352bec28ca65f2b6816b892fcf9a31abbef07b868487ad15dd55f1/coverage-7.10.1-cp313-cp313-win32.whl", hash = "sha256:2348631f049e884839553b9974f0821d39241c6ffb01a418efce434f7eba0fe7", size = 217381, upload-time = "2025-07-27T14:12:11.535Z" }, + { url = "https://files.pythonhosted.org/packages/b7/df/df6a0ff33b042f000089bd11b6bb034bab073e2ab64a56e78ed882cba55d/coverage-7.10.1-cp313-cp313-win_amd64.whl", hash = "sha256:4072b31361b0d6d23f750c524f694e1a417c1220a30d3ef02741eed28520c48e", size = 218152, upload-time = "2025-07-27T14:12:13.182Z" }, + { url = "https://files.pythonhosted.org/packages/30/e3/5085ca849a40ed6b47cdb8f65471c2f754e19390b5a12fa8abd25cbfaa8f/coverage-7.10.1-cp313-cp313-win_arm64.whl", hash = "sha256:3e31dfb8271937cab9425f19259b1b1d1f556790e98eb266009e7a61d337b6d4", size = 216559, upload-time = "2025-07-27T14:12:14.807Z" }, + { url = "https://files.pythonhosted.org/packages/cc/93/58714efbfdeb547909feaabe1d67b2bdd59f0597060271b9c548d5efb529/coverage-7.10.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:1c4f679c6b573a5257af6012f167a45be4c749c9925fd44d5178fd641ad8bf72", size = 215677, upload-time = "2025-07-27T14:12:16.68Z" }, + { url = "https://files.pythonhosted.org/packages/c0/0c/18eaa5897e7e8cb3f8c45e563e23e8a85686b4585e29d53cacb6bc9cb340/coverage-7.10.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:871ebe8143da284bd77b84a9136200bd638be253618765d21a1fce71006d94af", size = 215899, upload-time = "2025-07-27T14:12:18.758Z" }, + { url = "https://files.pythonhosted.org/packages/84/c1/9d1affacc3c75b5a184c140377701bbf14fc94619367f07a269cd9e4fed6/coverage-7.10.1-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:998c4751dabf7d29b30594af416e4bf5091f11f92a8d88eb1512c7ba136d1ed7", size = 257140, upload-time = "2025-07-27T14:12:20.357Z" }, + { url = "https://files.pythonhosted.org/packages/3d/0f/339bc6b8fa968c346df346068cca1f24bdea2ddfa93bb3dc2e7749730962/coverage-7.10.1-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:780f750a25e7749d0af6b3631759c2c14f45de209f3faaa2398312d1c7a22759", size = 259005, upload-time = "2025-07-27T14:12:22.007Z" }, + { url = "https://files.pythonhosted.org/packages/c8/22/89390864b92ea7c909079939b71baba7e5b42a76bf327c1d615bd829ba57/coverage-7.10.1-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:590bdba9445df4763bdbebc928d8182f094c1f3947a8dc0fc82ef014dbdd8324", size = 261143, upload-time = "2025-07-27T14:12:23.746Z" }, + { url = "https://files.pythonhosted.org/packages/2c/56/3d04d89017c0c41c7a71bd69b29699d919b6bbf2649b8b2091240b97dd6a/coverage-7.10.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9b2df80cb6a2af86d300e70acb82e9b79dab2c1e6971e44b78dbfc1a1e736b53", size = 258735, upload-time = "2025-07-27T14:12:25.73Z" }, + { url = "https://files.pythonhosted.org/packages/cb/40/312252c8afa5ca781063a09d931f4b9409dc91526cd0b5a2b84143ffafa2/coverage-7.10.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:d6a558c2725bfb6337bf57c1cd366c13798bfd3bfc9e3dd1f4a6f6fc95a4605f", size = 256871, upload-time = "2025-07-27T14:12:27.767Z" }, + { url = "https://files.pythonhosted.org/packages/1f/2b/564947d5dede068215aaddb9e05638aeac079685101462218229ddea9113/coverage-7.10.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:e6150d167f32f2a54690e572e0a4c90296fb000a18e9b26ab81a6489e24e78dd", size = 257692, upload-time = "2025-07-27T14:12:29.347Z" }, + { url = "https://files.pythonhosted.org/packages/93/1b/c8a867ade85cb26d802aea2209b9c2c80613b9c122baa8c8ecea6799648f/coverage-7.10.1-cp313-cp313t-win32.whl", hash = "sha256:d946a0c067aa88be4a593aad1236493313bafaa27e2a2080bfe88db827972f3c", size = 218059, upload-time = "2025-07-27T14:12:31.076Z" }, + { url = "https://files.pythonhosted.org/packages/a1/fe/cd4ab40570ae83a516bf5e754ea4388aeedd48e660e40c50b7713ed4f930/coverage-7.10.1-cp313-cp313t-win_amd64.whl", hash = "sha256:e37c72eaccdd5ed1130c67a92ad38f5b2af66eeff7b0abe29534225db2ef7b18", size = 219150, upload-time = "2025-07-27T14:12:32.746Z" }, + { url = "https://files.pythonhosted.org/packages/8d/16/6e5ed5854be6d70d0c39e9cb9dd2449f2c8c34455534c32c1a508c7dbdb5/coverage-7.10.1-cp313-cp313t-win_arm64.whl", hash = "sha256:89ec0ffc215c590c732918c95cd02b55c7d0f569d76b90bb1a5e78aa340618e4", size = 217014, upload-time = "2025-07-27T14:12:34.406Z" }, + { url = "https://files.pythonhosted.org/packages/54/8e/6d0bfe9c3d7121cf936c5f8b03e8c3da1484fb801703127dba20fb8bd3c7/coverage-7.10.1-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:166d89c57e877e93d8827dac32cedae6b0277ca684c6511497311249f35a280c", size = 214951, upload-time = "2025-07-27T14:12:36.069Z" }, + { url = "https://files.pythonhosted.org/packages/f2/29/e3e51a8c653cf2174c60532aafeb5065cea0911403fa144c9abe39790308/coverage-7.10.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:bed4a2341b33cd1a7d9ffc47df4a78ee61d3416d43b4adc9e18b7d266650b83e", size = 215229, upload-time = "2025-07-27T14:12:37.759Z" }, + { url = "https://files.pythonhosted.org/packages/e0/59/3c972080b2fa18b6c4510201f6d4dc87159d450627d062cd9ad051134062/coverage-7.10.1-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:ddca1e4f5f4c67980533df01430184c19b5359900e080248bbf4ed6789584d8b", size = 245738, upload-time = "2025-07-27T14:12:39.453Z" }, + { url = "https://files.pythonhosted.org/packages/2e/04/fc0d99d3f809452654e958e1788454f6e27b34e43f8f8598191c8ad13537/coverage-7.10.1-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:37b69226001d8b7de7126cad7366b0778d36777e4d788c66991455ba817c5b41", size = 248045, upload-time = "2025-07-27T14:12:41.387Z" }, + { url = "https://files.pythonhosted.org/packages/5e/2e/afcbf599e77e0dfbf4c97197747250d13d397d27e185b93987d9eaac053d/coverage-7.10.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b2f22102197bcb1722691296f9e589f02b616f874e54a209284dd7b9294b0b7f", size = 249666, upload-time = "2025-07-27T14:12:43.056Z" }, + { url = "https://files.pythonhosted.org/packages/6e/ae/bc47f7f8ecb7a06cbae2bf86a6fa20f479dd902bc80f57cff7730438059d/coverage-7.10.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:1e0c768b0f9ac5839dac5cf88992a4bb459e488ee8a1f8489af4cb33b1af00f1", size = 247692, upload-time = "2025-07-27T14:12:44.83Z" }, + { url = "https://files.pythonhosted.org/packages/b6/26/cbfa3092d31ccba8ba7647e4d25753263e818b4547eba446b113d7d1efdf/coverage-7.10.1-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:991196702d5e0b120a8fef2664e1b9c333a81d36d5f6bcf6b225c0cf8b0451a2", size = 245536, upload-time = "2025-07-27T14:12:46.527Z" }, + { url = "https://files.pythonhosted.org/packages/56/77/9c68e92500e6a1c83d024a70eadcc9a173f21aadd73c4675fe64c9c43fdf/coverage-7.10.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:ae8e59e5f4fd85d6ad34c2bb9d74037b5b11be072b8b7e9986beb11f957573d4", size = 246954, upload-time = "2025-07-27T14:12:49.279Z" }, + { url = "https://files.pythonhosted.org/packages/7f/a5/ba96671c5a669672aacd9877a5987c8551501b602827b4e84256da2a30a7/coverage-7.10.1-cp314-cp314-win32.whl", hash = "sha256:042125c89cf74a074984002e165d61fe0e31c7bd40ebb4bbebf07939b5924613", size = 217616, upload-time = "2025-07-27T14:12:51.214Z" }, + { url = "https://files.pythonhosted.org/packages/e7/3c/e1e1eb95fc1585f15a410208c4795db24a948e04d9bde818fe4eb893bc85/coverage-7.10.1-cp314-cp314-win_amd64.whl", hash = "sha256:a22c3bfe09f7a530e2c94c87ff7af867259c91bef87ed2089cd69b783af7b84e", size = 218412, upload-time = "2025-07-27T14:12:53.429Z" }, + { url = "https://files.pythonhosted.org/packages/b0/85/7e1e5be2cb966cba95566ba702b13a572ca744fbb3779df9888213762d67/coverage-7.10.1-cp314-cp314-win_arm64.whl", hash = "sha256:ee6be07af68d9c4fca4027c70cea0c31a0f1bc9cb464ff3c84a1f916bf82e652", size = 216776, upload-time = "2025-07-27T14:12:55.482Z" }, + { url = "https://files.pythonhosted.org/packages/62/0f/5bb8f29923141cca8560fe2217679caf4e0db643872c1945ac7d8748c2a7/coverage-7.10.1-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:d24fb3c0c8ff0d517c5ca5de7cf3994a4cd559cde0315201511dbfa7ab528894", size = 215698, upload-time = "2025-07-27T14:12:57.225Z" }, + { url = "https://files.pythonhosted.org/packages/80/29/547038ffa4e8e4d9e82f7dfc6d152f75fcdc0af146913f0ba03875211f03/coverage-7.10.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1217a54cfd79be20512a67ca81c7da3f2163f51bbfd188aab91054df012154f5", size = 215902, upload-time = "2025-07-27T14:12:59.071Z" }, + { url = "https://files.pythonhosted.org/packages/e1/8a/7aaa8fbfaed900147987a424e112af2e7790e1ac9cd92601e5bd4e1ba60a/coverage-7.10.1-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:51f30da7a52c009667e02f125737229d7d8044ad84b79db454308033a7808ab2", size = 257230, upload-time = "2025-07-27T14:13:01.248Z" }, + { url = "https://files.pythonhosted.org/packages/e5/1d/c252b5ffac44294e23a0d79dd5acf51749b39795ccc898faeabf7bee903f/coverage-7.10.1-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:ed3718c757c82d920f1c94089066225ca2ad7f00bb904cb72b1c39ebdd906ccb", size = 259194, upload-time = "2025-07-27T14:13:03.247Z" }, + { url = "https://files.pythonhosted.org/packages/16/ad/6c8d9f83d08f3bac2e7507534d0c48d1a4f52c18e6f94919d364edbdfa8f/coverage-7.10.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cc452481e124a819ced0c25412ea2e144269ef2f2534b862d9f6a9dae4bda17b", size = 261316, upload-time = "2025-07-27T14:13:04.957Z" }, + { url = "https://files.pythonhosted.org/packages/d6/4e/f9bbf3a36c061e2e0e0f78369c006d66416561a33d2bee63345aee8ee65e/coverage-7.10.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:9d6f494c307e5cb9b1e052ec1a471060f1dea092c8116e642e7a23e79d9388ea", size = 258794, upload-time = "2025-07-27T14:13:06.715Z" }, + { url = "https://files.pythonhosted.org/packages/87/82/e600bbe78eb2cb0541751d03cef9314bcd0897e8eea156219c39b685f869/coverage-7.10.1-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:fc0e46d86905ddd16b85991f1f4919028092b4e511689bbdaff0876bd8aab3dd", size = 256869, upload-time = "2025-07-27T14:13:08.933Z" }, + { url = "https://files.pythonhosted.org/packages/ce/5d/2fc9a9236c5268f68ac011d97cd3a5ad16cc420535369bedbda659fdd9b7/coverage-7.10.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:80b9ccd82e30038b61fc9a692a8dc4801504689651b281ed9109f10cc9fe8b4d", size = 257765, upload-time = "2025-07-27T14:13:10.778Z" }, + { url = "https://files.pythonhosted.org/packages/8a/05/b4e00b2bd48a2dc8e1c7d2aea7455f40af2e36484ab2ef06deb85883e9fe/coverage-7.10.1-cp314-cp314t-win32.whl", hash = "sha256:e58991a2b213417285ec866d3cd32db17a6a88061a985dbb7e8e8f13af429c47", size = 218420, upload-time = "2025-07-27T14:13:12.882Z" }, + { url = "https://files.pythonhosted.org/packages/77/fb/d21d05f33ea27ece327422240e69654b5932b0b29e7fbc40fbab3cf199bf/coverage-7.10.1-cp314-cp314t-win_amd64.whl", hash = "sha256:e88dd71e4ecbc49d9d57d064117462c43f40a21a1383507811cf834a4a620651", size = 219536, upload-time = "2025-07-27T14:13:14.718Z" }, + { url = "https://files.pythonhosted.org/packages/a6/68/7fea94b141281ed8be3d1d5c4319a97f2befc3e487ce33657fc64db2c45e/coverage-7.10.1-cp314-cp314t-win_arm64.whl", hash = "sha256:1aadfb06a30c62c2eb82322171fe1f7c288c80ca4156d46af0ca039052814bab", size = 217190, upload-time = "2025-07-27T14:13:16.85Z" }, + { url = "https://files.pythonhosted.org/packages/0f/64/922899cff2c0fd3496be83fa8b81230f5a8d82a2ad30f98370b133c2c83b/coverage-7.10.1-py3-none-any.whl", hash = "sha256:fa2a258aa6bf188eb9a8948f7102a83da7c430a0dce918dbd8b60ef8fcb772d7", size = 206597, upload-time = "2025-07-27T14:13:37.221Z" }, ] [package.optional-dependencies] @@ -657,15 +703,15 @@ wheels = [ [[package]] name = "hypothesis" -version = "6.136.3" +version = "6.136.6" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "attrs" }, { name = "sortedcontainers" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/84/cd/714955a6ac2f4b786483a38f0b13e37e7efad37d23a2dc465b91a9fe2db0/hypothesis-6.136.3.tar.gz", hash = "sha256:89baa2bfc5af38f939e83b62f9f0e7e6407e81cade29cfcb3eafbc661177c2bd", size = 457758, upload-time = "2025-07-23T13:53:25.8Z" } +sdist = { url = "https://files.pythonhosted.org/packages/e2/d6/6c45c56cdc532f25a354cf2c93a3bebc21b91b6a48125e3acfd364161447/hypothesis-6.136.6.tar.gz", hash = "sha256:2ad2e4f2012be4d41c6515b0628d84d48af6e6c38b4db50840bd9ac0899f5856", size = 458049, upload-time = "2025-07-28T09:48:02.495Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/f9/de/d2145a3c329751b13fcfddfe119e5ec72e263c2766d1f655dedc3ed33a0d/hypothesis-6.136.3-py3-none-any.whl", hash = "sha256:88163307c625688317bc5f3c7bd88f18b4d5c7cd773c784e3c4182eed2ae1b3d", size = 524703, upload-time = "2025-07-23T13:53:22.384Z" }, + { url = "https://files.pythonhosted.org/packages/e9/e2/7fd1a9b12740b3472349f7e3c216e94b1b2e03d32c9d842284b57eb5a3f8/hypothesis-6.136.6-py3-none-any.whl", hash = "sha256:1d6296dde36d42263bd44a084c74e91467e78186676e410167f920aa0374a9e7", size = 524958, upload-time = "2025-07-28T09:47:58.938Z" }, ] [[package]] @@ -1351,62 +1397,90 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/a6/be/7b423b02b09eb856beffe76fe8c4121c99852db74dd12a422dcb72d1134e/nox-2025.5.1-py3-none-any.whl", hash = "sha256:56abd55cf37ff523c254fcec4d152ed51e5fe80e2ab8317221d8b828ac970a31", size = 71753, upload-time = "2025-05-01T16:35:46.037Z" }, ] +[package.optional-dependencies] +uv = [ + { name = "uv" }, +] + [[package]] name = "numpy" -version = "2.3.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/2e/19/d7c972dfe90a353dbd3efbbe1d14a5951de80c99c9dc1b93cd998d51dc0f/numpy-2.3.1.tar.gz", hash = "sha256:1ec9ae20a4226da374362cca3c62cd753faf2f951440b0e3b98e93c235441d2b", size = 20390372, upload-time = "2025-06-21T12:28:33.469Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/b0/c7/87c64d7ab426156530676000c94784ef55676df2f13b2796f97722464124/numpy-2.3.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6ea9e48336a402551f52cd8f593343699003d2353daa4b72ce8d34f66b722070", size = 21199346, upload-time = "2025-06-21T11:47:47.57Z" }, - { url = "https://files.pythonhosted.org/packages/58/0e/0966c2f44beeac12af8d836e5b5f826a407cf34c45cb73ddcdfce9f5960b/numpy-2.3.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5ccb7336eaf0e77c1635b232c141846493a588ec9ea777a7c24d7166bb8533ae", size = 14361143, upload-time = "2025-06-21T11:48:10.766Z" }, - { url = "https://files.pythonhosted.org/packages/7d/31/6e35a247acb1bfc19226791dfc7d4c30002cd4e620e11e58b0ddf836fe52/numpy-2.3.1-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:0bb3a4a61e1d327e035275d2a993c96fa786e4913aa089843e6a2d9dd205c66a", size = 5378989, upload-time = "2025-06-21T11:48:19.998Z" }, - { url = "https://files.pythonhosted.org/packages/b0/25/93b621219bb6f5a2d4e713a824522c69ab1f06a57cd571cda70e2e31af44/numpy-2.3.1-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:e344eb79dab01f1e838ebb67aab09965fb271d6da6b00adda26328ac27d4a66e", size = 6912890, upload-time = "2025-06-21T11:48:31.376Z" }, - { url = "https://files.pythonhosted.org/packages/ef/60/6b06ed98d11fb32e27fb59468b42383f3877146d3ee639f733776b6ac596/numpy-2.3.1-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:467db865b392168ceb1ef1ffa6f5a86e62468c43e0cfb4ab6da667ede10e58db", size = 14569032, upload-time = "2025-06-21T11:48:52.563Z" }, - { url = "https://files.pythonhosted.org/packages/75/c9/9bec03675192077467a9c7c2bdd1f2e922bd01d3a69b15c3a0fdcd8548f6/numpy-2.3.1-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:afed2ce4a84f6b0fc6c1ce734ff368cbf5a5e24e8954a338f3bdffa0718adffb", size = 16930354, upload-time = "2025-06-21T11:49:17.473Z" }, - { url = "https://files.pythonhosted.org/packages/6a/e2/5756a00cabcf50a3f527a0c968b2b4881c62b1379223931853114fa04cda/numpy-2.3.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0025048b3c1557a20bc80d06fdeb8cc7fc193721484cca82b2cfa072fec71a93", size = 15879605, upload-time = "2025-06-21T11:49:41.161Z" }, - { url = "https://files.pythonhosted.org/packages/ff/86/a471f65f0a86f1ca62dcc90b9fa46174dd48f50214e5446bc16a775646c5/numpy-2.3.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a5ee121b60aa509679b682819c602579e1df14a5b07fe95671c8849aad8f2115", size = 18666994, upload-time = "2025-06-21T11:50:08.516Z" }, - { url = "https://files.pythonhosted.org/packages/43/a6/482a53e469b32be6500aaf61cfafd1de7a0b0d484babf679209c3298852e/numpy-2.3.1-cp311-cp311-win32.whl", hash = "sha256:a8b740f5579ae4585831b3cf0e3b0425c667274f82a484866d2adf9570539369", size = 6603672, upload-time = "2025-06-21T11:50:19.584Z" }, - { url = "https://files.pythonhosted.org/packages/6b/fb/bb613f4122c310a13ec67585c70e14b03bfc7ebabd24f4d5138b97371d7c/numpy-2.3.1-cp311-cp311-win_amd64.whl", hash = "sha256:d4580adadc53311b163444f877e0789f1c8861e2698f6b2a4ca852fda154f3ff", size = 13024015, upload-time = "2025-06-21T11:50:39.139Z" }, - { url = "https://files.pythonhosted.org/packages/51/58/2d842825af9a0c041aca246dc92eb725e1bc5e1c9ac89712625db0c4e11c/numpy-2.3.1-cp311-cp311-win_arm64.whl", hash = "sha256:ec0bdafa906f95adc9a0c6f26a4871fa753f25caaa0e032578a30457bff0af6a", size = 10456989, upload-time = "2025-06-21T11:50:55.616Z" }, - { url = "https://files.pythonhosted.org/packages/c6/56/71ad5022e2f63cfe0ca93559403d0edef14aea70a841d640bd13cdba578e/numpy-2.3.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:2959d8f268f3d8ee402b04a9ec4bb7604555aeacf78b360dc4ec27f1d508177d", size = 20896664, upload-time = "2025-06-21T12:15:30.845Z" }, - { url = "https://files.pythonhosted.org/packages/25/65/2db52ba049813670f7f987cc5db6dac9be7cd95e923cc6832b3d32d87cef/numpy-2.3.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:762e0c0c6b56bdedfef9a8e1d4538556438288c4276901ea008ae44091954e29", size = 14131078, upload-time = "2025-06-21T12:15:52.23Z" }, - { url = "https://files.pythonhosted.org/packages/57/dd/28fa3c17b0e751047ac928c1e1b6990238faad76e9b147e585b573d9d1bd/numpy-2.3.1-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:867ef172a0976aaa1f1d1b63cf2090de8b636a7674607d514505fb7276ab08fc", size = 5112554, upload-time = "2025-06-21T12:16:01.434Z" }, - { url = "https://files.pythonhosted.org/packages/c9/fc/84ea0cba8e760c4644b708b6819d91784c290288c27aca916115e3311d17/numpy-2.3.1-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:4e602e1b8682c2b833af89ba641ad4176053aaa50f5cacda1a27004352dde943", size = 6646560, upload-time = "2025-06-21T12:16:11.895Z" }, - { url = "https://files.pythonhosted.org/packages/61/b2/512b0c2ddec985ad1e496b0bd853eeb572315c0f07cd6997473ced8f15e2/numpy-2.3.1-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:8e333040d069eba1652fb08962ec5b76af7f2c7bce1df7e1418c8055cf776f25", size = 14260638, upload-time = "2025-06-21T12:16:32.611Z" }, - { url = "https://files.pythonhosted.org/packages/6e/45/c51cb248e679a6c6ab14b7a8e3ead3f4a3fe7425fc7a6f98b3f147bec532/numpy-2.3.1-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:e7cbf5a5eafd8d230a3ce356d892512185230e4781a361229bd902ff403bc660", size = 16632729, upload-time = "2025-06-21T12:16:57.439Z" }, - { url = "https://files.pythonhosted.org/packages/e4/ff/feb4be2e5c09a3da161b412019caf47183099cbea1132fd98061808c2df2/numpy-2.3.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5f1b8f26d1086835f442286c1d9b64bb3974b0b1e41bb105358fd07d20872952", size = 15565330, upload-time = "2025-06-21T12:17:20.638Z" }, - { url = "https://files.pythonhosted.org/packages/bc/6d/ceafe87587101e9ab0d370e4f6e5f3f3a85b9a697f2318738e5e7e176ce3/numpy-2.3.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ee8340cb48c9b7a5899d1149eece41ca535513a9698098edbade2a8e7a84da77", size = 18361734, upload-time = "2025-06-21T12:17:47.938Z" }, - { url = "https://files.pythonhosted.org/packages/2b/19/0fb49a3ea088be691f040c9bf1817e4669a339d6e98579f91859b902c636/numpy-2.3.1-cp312-cp312-win32.whl", hash = "sha256:e772dda20a6002ef7061713dc1e2585bc1b534e7909b2030b5a46dae8ff077ab", size = 6320411, upload-time = "2025-06-21T12:17:58.475Z" }, - { url = "https://files.pythonhosted.org/packages/b1/3e/e28f4c1dd9e042eb57a3eb652f200225e311b608632bc727ae378623d4f8/numpy-2.3.1-cp312-cp312-win_amd64.whl", hash = "sha256:cfecc7822543abdea6de08758091da655ea2210b8ffa1faf116b940693d3df76", size = 12734973, upload-time = "2025-06-21T12:18:17.601Z" }, - { url = "https://files.pythonhosted.org/packages/04/a8/8a5e9079dc722acf53522b8f8842e79541ea81835e9b5483388701421073/numpy-2.3.1-cp312-cp312-win_arm64.whl", hash = "sha256:7be91b2239af2658653c5bb6f1b8bccafaf08226a258caf78ce44710a0160d30", size = 10191491, upload-time = "2025-06-21T12:18:33.585Z" }, - { url = "https://files.pythonhosted.org/packages/d4/bd/35ad97006d8abff8631293f8ea6adf07b0108ce6fec68da3c3fcca1197f2/numpy-2.3.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:25a1992b0a3fdcdaec9f552ef10d8103186f5397ab45e2d25f8ac51b1a6b97e8", size = 20889381, upload-time = "2025-06-21T12:19:04.103Z" }, - { url = "https://files.pythonhosted.org/packages/f1/4f/df5923874d8095b6062495b39729178eef4a922119cee32a12ee1bd4664c/numpy-2.3.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:7dea630156d39b02a63c18f508f85010230409db5b2927ba59c8ba4ab3e8272e", size = 14152726, upload-time = "2025-06-21T12:19:25.599Z" }, - { url = "https://files.pythonhosted.org/packages/8c/0f/a1f269b125806212a876f7efb049b06c6f8772cf0121139f97774cd95626/numpy-2.3.1-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:bada6058dd886061f10ea15f230ccf7dfff40572e99fef440a4a857c8728c9c0", size = 5105145, upload-time = "2025-06-21T12:19:34.782Z" }, - { url = "https://files.pythonhosted.org/packages/6d/63/a7f7fd5f375b0361682f6ffbf686787e82b7bbd561268e4f30afad2bb3c0/numpy-2.3.1-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:a894f3816eb17b29e4783e5873f92faf55b710c2519e5c351767c51f79d8526d", size = 6639409, upload-time = "2025-06-21T12:19:45.228Z" }, - { url = "https://files.pythonhosted.org/packages/bf/0d/1854a4121af895aab383f4aa233748f1df4671ef331d898e32426756a8a6/numpy-2.3.1-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:18703df6c4a4fee55fd3d6e5a253d01c5d33a295409b03fda0c86b3ca2ff41a1", size = 14257630, upload-time = "2025-06-21T12:20:06.544Z" }, - { url = "https://files.pythonhosted.org/packages/50/30/af1b277b443f2fb08acf1c55ce9d68ee540043f158630d62cef012750f9f/numpy-2.3.1-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:5902660491bd7a48b2ec16c23ccb9124b8abfd9583c5fdfa123fe6b421e03de1", size = 16627546, upload-time = "2025-06-21T12:20:31.002Z" }, - { url = "https://files.pythonhosted.org/packages/6e/ec/3b68220c277e463095342d254c61be8144c31208db18d3fd8ef02712bcd6/numpy-2.3.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:36890eb9e9d2081137bd78d29050ba63b8dab95dff7912eadf1185e80074b2a0", size = 15562538, upload-time = "2025-06-21T12:20:54.322Z" }, - { url = "https://files.pythonhosted.org/packages/77/2b/4014f2bcc4404484021c74d4c5ee8eb3de7e3f7ac75f06672f8dcf85140a/numpy-2.3.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a780033466159c2270531e2b8ac063704592a0bc62ec4a1b991c7c40705eb0e8", size = 18360327, upload-time = "2025-06-21T12:21:21.053Z" }, - { url = "https://files.pythonhosted.org/packages/40/8d/2ddd6c9b30fcf920837b8672f6c65590c7d92e43084c25fc65edc22e93ca/numpy-2.3.1-cp313-cp313-win32.whl", hash = "sha256:39bff12c076812595c3a306f22bfe49919c5513aa1e0e70fac756a0be7c2a2b8", size = 6312330, upload-time = "2025-06-21T12:25:07.447Z" }, - { url = "https://files.pythonhosted.org/packages/dd/c8/beaba449925988d415efccb45bf977ff8327a02f655090627318f6398c7b/numpy-2.3.1-cp313-cp313-win_amd64.whl", hash = "sha256:8d5ee6eec45f08ce507a6570e06f2f879b374a552087a4179ea7838edbcbfa42", size = 12731565, upload-time = "2025-06-21T12:25:26.444Z" }, - { url = "https://files.pythonhosted.org/packages/0b/c3/5c0c575d7ec78c1126998071f58facfc124006635da75b090805e642c62e/numpy-2.3.1-cp313-cp313-win_arm64.whl", hash = "sha256:0c4d9e0a8368db90f93bd192bfa771ace63137c3488d198ee21dfb8e7771916e", size = 10190262, upload-time = "2025-06-21T12:25:42.196Z" }, - { url = "https://files.pythonhosted.org/packages/ea/19/a029cd335cf72f79d2644dcfc22d90f09caa86265cbbde3b5702ccef6890/numpy-2.3.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:b0b5397374f32ec0649dd98c652a1798192042e715df918c20672c62fb52d4b8", size = 20987593, upload-time = "2025-06-21T12:21:51.664Z" }, - { url = "https://files.pythonhosted.org/packages/25/91/8ea8894406209107d9ce19b66314194675d31761fe2cb3c84fe2eeae2f37/numpy-2.3.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:c5bdf2015ccfcee8253fb8be695516ac4457c743473a43290fd36eba6a1777eb", size = 14300523, upload-time = "2025-06-21T12:22:13.583Z" }, - { url = "https://files.pythonhosted.org/packages/a6/7f/06187b0066eefc9e7ce77d5f2ddb4e314a55220ad62dd0bfc9f2c44bac14/numpy-2.3.1-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:d70f20df7f08b90a2062c1f07737dd340adccf2068d0f1b9b3d56e2038979fee", size = 5227993, upload-time = "2025-06-21T12:22:22.53Z" }, - { url = "https://files.pythonhosted.org/packages/e8/ec/a926c293c605fa75e9cfb09f1e4840098ed46d2edaa6e2152ee35dc01ed3/numpy-2.3.1-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:2fb86b7e58f9ac50e1e9dd1290154107e47d1eef23a0ae9145ded06ea606f992", size = 6736652, upload-time = "2025-06-21T12:22:33.629Z" }, - { url = "https://files.pythonhosted.org/packages/e3/62/d68e52fb6fde5586650d4c0ce0b05ff3a48ad4df4ffd1b8866479d1d671d/numpy-2.3.1-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:23ab05b2d241f76cb883ce8b9a93a680752fbfcbd51c50eff0b88b979e471d8c", size = 14331561, upload-time = "2025-06-21T12:22:55.056Z" }, - { url = "https://files.pythonhosted.org/packages/fc/ec/b74d3f2430960044bdad6900d9f5edc2dc0fb8bf5a0be0f65287bf2cbe27/numpy-2.3.1-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:ce2ce9e5de4703a673e705183f64fd5da5bf36e7beddcb63a25ee2286e71ca48", size = 16693349, upload-time = "2025-06-21T12:23:20.53Z" }, - { url = "https://files.pythonhosted.org/packages/0d/15/def96774b9d7eb198ddadfcbd20281b20ebb510580419197e225f5c55c3e/numpy-2.3.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:c4913079974eeb5c16ccfd2b1f09354b8fed7e0d6f2cab933104a09a6419b1ee", size = 15642053, upload-time = "2025-06-21T12:23:43.697Z" }, - { url = "https://files.pythonhosted.org/packages/2b/57/c3203974762a759540c6ae71d0ea2341c1fa41d84e4971a8e76d7141678a/numpy-2.3.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:010ce9b4f00d5c036053ca684c77441f2f2c934fd23bee058b4d6f196efd8280", size = 18434184, upload-time = "2025-06-21T12:24:10.708Z" }, - { url = "https://files.pythonhosted.org/packages/22/8a/ccdf201457ed8ac6245187850aff4ca56a79edbea4829f4e9f14d46fa9a5/numpy-2.3.1-cp313-cp313t-win32.whl", hash = "sha256:6269b9edfe32912584ec496d91b00b6d34282ca1d07eb10e82dfc780907d6c2e", size = 6440678, upload-time = "2025-06-21T12:24:21.596Z" }, - { url = "https://files.pythonhosted.org/packages/f1/7e/7f431d8bd8eb7e03d79294aed238b1b0b174b3148570d03a8a8a8f6a0da9/numpy-2.3.1-cp313-cp313t-win_amd64.whl", hash = "sha256:2a809637460e88a113e186e87f228d74ae2852a2e0c44de275263376f17b5bdc", size = 12870697, upload-time = "2025-06-21T12:24:40.644Z" }, - { url = "https://files.pythonhosted.org/packages/d4/ca/af82bf0fad4c3e573c6930ed743b5308492ff19917c7caaf2f9b6f9e2e98/numpy-2.3.1-cp313-cp313t-win_arm64.whl", hash = "sha256:eccb9a159db9aed60800187bc47a6d3451553f0e1b08b068d8b277ddfbb9b244", size = 10260376, upload-time = "2025-06-21T12:24:56.884Z" }, - { url = "https://files.pythonhosted.org/packages/e8/34/facc13b9b42ddca30498fc51f7f73c3d0f2be179943a4b4da8686e259740/numpy-2.3.1-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:ad506d4b09e684394c42c966ec1527f6ebc25da7f4da4b1b056606ffe446b8a3", size = 21070637, upload-time = "2025-06-21T12:26:12.518Z" }, - { url = "https://files.pythonhosted.org/packages/65/b6/41b705d9dbae04649b529fc9bd3387664c3281c7cd78b404a4efe73dcc45/numpy-2.3.1-pp311-pypy311_pp73-macosx_14_0_arm64.whl", hash = "sha256:ebb8603d45bc86bbd5edb0d63e52c5fd9e7945d3a503b77e486bd88dde67a19b", size = 5304087, upload-time = "2025-06-21T12:26:22.294Z" }, - { url = "https://files.pythonhosted.org/packages/7a/b4/fe3ac1902bff7a4934a22d49e1c9d71a623204d654d4cc43c6e8fe337fcb/numpy-2.3.1-pp311-pypy311_pp73-macosx_14_0_x86_64.whl", hash = "sha256:15aa4c392ac396e2ad3d0a2680c0f0dee420f9fed14eef09bdb9450ee6dcb7b7", size = 6817588, upload-time = "2025-06-21T12:26:32.939Z" }, - { url = "https://files.pythonhosted.org/packages/ae/ee/89bedf69c36ace1ac8f59e97811c1f5031e179a37e4821c3a230bf750142/numpy-2.3.1-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:c6e0bf9d1a2f50d2b65a7cf56db37c095af17b59f6c132396f7c6d5dd76484df", size = 14399010, upload-time = "2025-06-21T12:26:54.086Z" }, - { url = "https://files.pythonhosted.org/packages/15/08/e00e7070ede29b2b176165eba18d6f9784d5349be3c0c1218338e79c27fd/numpy-2.3.1-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:eabd7e8740d494ce2b4ea0ff05afa1b7b291e978c0ae075487c51e8bd93c0c68", size = 16752042, upload-time = "2025-06-21T12:27:19.018Z" }, - { url = "https://files.pythonhosted.org/packages/48/6b/1c6b515a83d5564b1698a61efa245727c8feecf308f4091f565988519d20/numpy-2.3.1-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:e610832418a2bc09d974cc9fecebfa51e9532d6190223bc5ef6a7402ebf3b5cb", size = 12927246, upload-time = "2025-06-21T12:27:38.618Z" }, +version = "2.3.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/37/7d/3fec4199c5ffb892bed55cff901e4f39a58c81df9c44c280499e92cad264/numpy-2.3.2.tar.gz", hash = "sha256:e0486a11ec30cdecb53f184d496d1c6a20786c81e55e41640270130056f8ee48", size = 20489306, upload-time = "2025-07-24T21:32:07.553Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/96/26/1320083986108998bd487e2931eed2aeedf914b6e8905431487543ec911d/numpy-2.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:852ae5bed3478b92f093e30f785c98e0cb62fa0a939ed057c31716e18a7a22b9", size = 21259016, upload-time = "2025-07-24T20:24:35.214Z" }, + { url = "https://files.pythonhosted.org/packages/c4/2b/792b341463fa93fc7e55abbdbe87dac316c5b8cb5e94fb7a59fb6fa0cda5/numpy-2.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7a0e27186e781a69959d0230dd9909b5e26024f8da10683bd6344baea1885168", size = 14451158, upload-time = "2025-07-24T20:24:58.397Z" }, + { url = "https://files.pythonhosted.org/packages/b7/13/e792d7209261afb0c9f4759ffef6135b35c77c6349a151f488f531d13595/numpy-2.3.2-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:f0a1a8476ad77a228e41619af2fa9505cf69df928e9aaa165746584ea17fed2b", size = 5379817, upload-time = "2025-07-24T20:25:07.746Z" }, + { url = "https://files.pythonhosted.org/packages/49/ce/055274fcba4107c022b2113a213c7287346563f48d62e8d2a5176ad93217/numpy-2.3.2-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:cbc95b3813920145032412f7e33d12080f11dc776262df1712e1638207dde9e8", size = 6913606, upload-time = "2025-07-24T20:25:18.84Z" }, + { url = "https://files.pythonhosted.org/packages/17/f2/e4d72e6bc5ff01e2ab613dc198d560714971900c03674b41947e38606502/numpy-2.3.2-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f75018be4980a7324edc5930fe39aa391d5734531b1926968605416ff58c332d", size = 14589652, upload-time = "2025-07-24T20:25:40.356Z" }, + { url = "https://files.pythonhosted.org/packages/c8/b0/fbeee3000a51ebf7222016e2939b5c5ecf8000a19555d04a18f1e02521b8/numpy-2.3.2-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:20b8200721840f5621b7bd03f8dcd78de33ec522fc40dc2641aa09537df010c3", size = 16938816, upload-time = "2025-07-24T20:26:05.721Z" }, + { url = "https://files.pythonhosted.org/packages/a9/ec/2f6c45c3484cc159621ea8fc000ac5a86f1575f090cac78ac27193ce82cd/numpy-2.3.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1f91e5c028504660d606340a084db4b216567ded1056ea2b4be4f9d10b67197f", size = 16370512, upload-time = "2025-07-24T20:26:30.545Z" }, + { url = "https://files.pythonhosted.org/packages/b5/01/dd67cf511850bd7aefd6347aaae0956ed415abea741ae107834aae7d6d4e/numpy-2.3.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:fb1752a3bb9a3ad2d6b090b88a9a0ae1cd6f004ef95f75825e2f382c183b2097", size = 18884947, upload-time = "2025-07-24T20:26:58.24Z" }, + { url = "https://files.pythonhosted.org/packages/a7/17/2cf60fd3e6a61d006778735edf67a222787a8c1a7842aed43ef96d777446/numpy-2.3.2-cp311-cp311-win32.whl", hash = "sha256:4ae6863868aaee2f57503c7a5052b3a2807cf7a3914475e637a0ecd366ced220", size = 6599494, upload-time = "2025-07-24T20:27:09.786Z" }, + { url = "https://files.pythonhosted.org/packages/d5/03/0eade211c504bda872a594f045f98ddcc6caef2b7c63610946845e304d3f/numpy-2.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:240259d6564f1c65424bcd10f435145a7644a65a6811cfc3201c4a429ba79170", size = 13087889, upload-time = "2025-07-24T20:27:29.558Z" }, + { url = "https://files.pythonhosted.org/packages/13/32/2c7979d39dafb2a25087e12310fc7f3b9d3c7d960df4f4bc97955ae0ce1d/numpy-2.3.2-cp311-cp311-win_arm64.whl", hash = "sha256:4209f874d45f921bde2cff1ffcd8a3695f545ad2ffbef6d3d3c6768162efab89", size = 10459560, upload-time = "2025-07-24T20:27:46.803Z" }, + { url = "https://files.pythonhosted.org/packages/00/6d/745dd1c1c5c284d17725e5c802ca4d45cfc6803519d777f087b71c9f4069/numpy-2.3.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:bc3186bea41fae9d8e90c2b4fb5f0a1f5a690682da79b92574d63f56b529080b", size = 20956420, upload-time = "2025-07-24T20:28:18.002Z" }, + { url = "https://files.pythonhosted.org/packages/bc/96/e7b533ea5740641dd62b07a790af5d9d8fec36000b8e2d0472bd7574105f/numpy-2.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2f4f0215edb189048a3c03bd5b19345bdfa7b45a7a6f72ae5945d2a28272727f", size = 14184660, upload-time = "2025-07-24T20:28:39.522Z" }, + { url = "https://files.pythonhosted.org/packages/2b/53/102c6122db45a62aa20d1b18c9986f67e6b97e0d6fbc1ae13e3e4c84430c/numpy-2.3.2-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:8b1224a734cd509f70816455c3cffe13a4f599b1bf7130f913ba0e2c0b2006c0", size = 5113382, upload-time = "2025-07-24T20:28:48.544Z" }, + { url = "https://files.pythonhosted.org/packages/2b/21/376257efcbf63e624250717e82b4fae93d60178f09eb03ed766dbb48ec9c/numpy-2.3.2-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:3dcf02866b977a38ba3ec10215220609ab9667378a9e2150615673f3ffd6c73b", size = 6647258, upload-time = "2025-07-24T20:28:59.104Z" }, + { url = "https://files.pythonhosted.org/packages/91/ba/f4ebf257f08affa464fe6036e13f2bf9d4642a40228781dc1235da81be9f/numpy-2.3.2-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:572d5512df5470f50ada8d1972c5f1082d9a0b7aa5944db8084077570cf98370", size = 14281409, upload-time = "2025-07-24T20:40:30.298Z" }, + { url = "https://files.pythonhosted.org/packages/59/ef/f96536f1df42c668cbacb727a8c6da7afc9c05ece6d558927fb1722693e1/numpy-2.3.2-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8145dd6d10df13c559d1e4314df29695613575183fa2e2d11fac4c208c8a1f73", size = 16641317, upload-time = "2025-07-24T20:40:56.625Z" }, + { url = "https://files.pythonhosted.org/packages/f6/a7/af813a7b4f9a42f498dde8a4c6fcbff8100eed00182cc91dbaf095645f38/numpy-2.3.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:103ea7063fa624af04a791c39f97070bf93b96d7af7eb23530cd087dc8dbe9dc", size = 16056262, upload-time = "2025-07-24T20:41:20.797Z" }, + { url = "https://files.pythonhosted.org/packages/8b/5d/41c4ef8404caaa7f05ed1cfb06afe16a25895260eacbd29b4d84dff2920b/numpy-2.3.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fc927d7f289d14f5e037be917539620603294454130b6de200091e23d27dc9be", size = 18579342, upload-time = "2025-07-24T20:41:50.753Z" }, + { url = "https://files.pythonhosted.org/packages/a1/4f/9950e44c5a11636f4a3af6e825ec23003475cc9a466edb7a759ed3ea63bd/numpy-2.3.2-cp312-cp312-win32.whl", hash = "sha256:d95f59afe7f808c103be692175008bab926b59309ade3e6d25009e9a171f7036", size = 6320610, upload-time = "2025-07-24T20:42:01.551Z" }, + { url = "https://files.pythonhosted.org/packages/7c/2f/244643a5ce54a94f0a9a2ab578189c061e4a87c002e037b0829dd77293b6/numpy-2.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:9e196ade2400c0c737d93465327d1ae7c06c7cb8a1756121ebf54b06ca183c7f", size = 12786292, upload-time = "2025-07-24T20:42:20.738Z" }, + { url = "https://files.pythonhosted.org/packages/54/cd/7b5f49d5d78db7badab22d8323c1b6ae458fbf86c4fdfa194ab3cd4eb39b/numpy-2.3.2-cp312-cp312-win_arm64.whl", hash = "sha256:ee807923782faaf60d0d7331f5e86da7d5e3079e28b291973c545476c2b00d07", size = 10194071, upload-time = "2025-07-24T20:42:36.657Z" }, + { url = "https://files.pythonhosted.org/packages/1c/c0/c6bb172c916b00700ed3bf71cb56175fd1f7dbecebf8353545d0b5519f6c/numpy-2.3.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:c8d9727f5316a256425892b043736d63e89ed15bbfe6556c5ff4d9d4448ff3b3", size = 20949074, upload-time = "2025-07-24T20:43:07.813Z" }, + { url = "https://files.pythonhosted.org/packages/20/4e/c116466d22acaf4573e58421c956c6076dc526e24a6be0903219775d862e/numpy-2.3.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:efc81393f25f14d11c9d161e46e6ee348637c0a1e8a54bf9dedc472a3fae993b", size = 14177311, upload-time = "2025-07-24T20:43:29.335Z" }, + { url = "https://files.pythonhosted.org/packages/78/45/d4698c182895af189c463fc91d70805d455a227261d950e4e0f1310c2550/numpy-2.3.2-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:dd937f088a2df683cbb79dda9a772b62a3e5a8a7e76690612c2737f38c6ef1b6", size = 5106022, upload-time = "2025-07-24T20:43:37.999Z" }, + { url = "https://files.pythonhosted.org/packages/9f/76/3e6880fef4420179309dba72a8c11f6166c431cf6dee54c577af8906f914/numpy-2.3.2-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:11e58218c0c46c80509186e460d79fbdc9ca1eb8d8aee39d8f2dc768eb781089", size = 6640135, upload-time = "2025-07-24T20:43:49.28Z" }, + { url = "https://files.pythonhosted.org/packages/34/fa/87ff7f25b3c4ce9085a62554460b7db686fef1e0207e8977795c7b7d7ba1/numpy-2.3.2-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5ad4ebcb683a1f99f4f392cc522ee20a18b2bb12a2c1c42c3d48d5a1adc9d3d2", size = 14278147, upload-time = "2025-07-24T20:44:10.328Z" }, + { url = "https://files.pythonhosted.org/packages/1d/0f/571b2c7a3833ae419fe69ff7b479a78d313581785203cc70a8db90121b9a/numpy-2.3.2-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:938065908d1d869c7d75d8ec45f735a034771c6ea07088867f713d1cd3bbbe4f", size = 16635989, upload-time = "2025-07-24T20:44:34.88Z" }, + { url = "https://files.pythonhosted.org/packages/24/5a/84ae8dca9c9a4c592fe11340b36a86ffa9fd3e40513198daf8a97839345c/numpy-2.3.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:66459dccc65d8ec98cc7df61307b64bf9e08101f9598755d42d8ae65d9a7a6ee", size = 16053052, upload-time = "2025-07-24T20:44:58.872Z" }, + { url = "https://files.pythonhosted.org/packages/57/7c/e5725d99a9133b9813fcf148d3f858df98511686e853169dbaf63aec6097/numpy-2.3.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a7af9ed2aa9ec5950daf05bb11abc4076a108bd3c7db9aa7251d5f107079b6a6", size = 18577955, upload-time = "2025-07-24T20:45:26.714Z" }, + { url = "https://files.pythonhosted.org/packages/ae/11/7c546fcf42145f29b71e4d6f429e96d8d68e5a7ba1830b2e68d7418f0bbd/numpy-2.3.2-cp313-cp313-win32.whl", hash = "sha256:906a30249315f9c8e17b085cc5f87d3f369b35fedd0051d4a84686967bdbbd0b", size = 6311843, upload-time = "2025-07-24T20:49:24.444Z" }, + { url = "https://files.pythonhosted.org/packages/aa/6f/a428fd1cb7ed39b4280d057720fed5121b0d7754fd2a9768640160f5517b/numpy-2.3.2-cp313-cp313-win_amd64.whl", hash = "sha256:c63d95dc9d67b676e9108fe0d2182987ccb0f11933c1e8959f42fa0da8d4fa56", size = 12782876, upload-time = "2025-07-24T20:49:43.227Z" }, + { url = "https://files.pythonhosted.org/packages/65/85/4ea455c9040a12595fb6c43f2c217257c7b52dd0ba332c6a6c1d28b289fe/numpy-2.3.2-cp313-cp313-win_arm64.whl", hash = "sha256:b05a89f2fb84d21235f93de47129dd4f11c16f64c87c33f5e284e6a3a54e43f2", size = 10192786, upload-time = "2025-07-24T20:49:59.443Z" }, + { url = "https://files.pythonhosted.org/packages/80/23/8278f40282d10c3f258ec3ff1b103d4994bcad78b0cba9208317f6bb73da/numpy-2.3.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:4e6ecfeddfa83b02318f4d84acf15fbdbf9ded18e46989a15a8b6995dfbf85ab", size = 21047395, upload-time = "2025-07-24T20:45:58.821Z" }, + { url = "https://files.pythonhosted.org/packages/1f/2d/624f2ce4a5df52628b4ccd16a4f9437b37c35f4f8a50d00e962aae6efd7a/numpy-2.3.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:508b0eada3eded10a3b55725b40806a4b855961040180028f52580c4729916a2", size = 14300374, upload-time = "2025-07-24T20:46:20.207Z" }, + { url = "https://files.pythonhosted.org/packages/f6/62/ff1e512cdbb829b80a6bd08318a58698867bca0ca2499d101b4af063ee97/numpy-2.3.2-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:754d6755d9a7588bdc6ac47dc4ee97867271b17cee39cb87aef079574366db0a", size = 5228864, upload-time = "2025-07-24T20:46:30.58Z" }, + { url = "https://files.pythonhosted.org/packages/7d/8e/74bc18078fff03192d4032cfa99d5a5ca937807136d6f5790ce07ca53515/numpy-2.3.2-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:a9f66e7d2b2d7712410d3bc5684149040ef5f19856f20277cd17ea83e5006286", size = 6737533, upload-time = "2025-07-24T20:46:46.111Z" }, + { url = "https://files.pythonhosted.org/packages/19/ea/0731efe2c9073ccca5698ef6a8c3667c4cf4eea53fcdcd0b50140aba03bc/numpy-2.3.2-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:de6ea4e5a65d5a90c7d286ddff2b87f3f4ad61faa3db8dabe936b34c2275b6f8", size = 14352007, upload-time = "2025-07-24T20:47:07.1Z" }, + { url = "https://files.pythonhosted.org/packages/cf/90/36be0865f16dfed20f4bc7f75235b963d5939707d4b591f086777412ff7b/numpy-2.3.2-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a3ef07ec8cbc8fc9e369c8dcd52019510c12da4de81367d8b20bc692aa07573a", size = 16701914, upload-time = "2025-07-24T20:47:32.459Z" }, + { url = "https://files.pythonhosted.org/packages/94/30/06cd055e24cb6c38e5989a9e747042b4e723535758e6153f11afea88c01b/numpy-2.3.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:27c9f90e7481275c7800dc9c24b7cc40ace3fdb970ae4d21eaff983a32f70c91", size = 16132708, upload-time = "2025-07-24T20:47:58.129Z" }, + { url = "https://files.pythonhosted.org/packages/9a/14/ecede608ea73e58267fd7cb78f42341b3b37ba576e778a1a06baffbe585c/numpy-2.3.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:07b62978075b67eee4065b166d000d457c82a1efe726cce608b9db9dd66a73a5", size = 18651678, upload-time = "2025-07-24T20:48:25.402Z" }, + { url = "https://files.pythonhosted.org/packages/40/f3/2fe6066b8d07c3685509bc24d56386534c008b462a488b7f503ba82b8923/numpy-2.3.2-cp313-cp313t-win32.whl", hash = "sha256:c771cfac34a4f2c0de8e8c97312d07d64fd8f8ed45bc9f5726a7e947270152b5", size = 6441832, upload-time = "2025-07-24T20:48:37.181Z" }, + { url = "https://files.pythonhosted.org/packages/0b/ba/0937d66d05204d8f28630c9c60bc3eda68824abde4cf756c4d6aad03b0c6/numpy-2.3.2-cp313-cp313t-win_amd64.whl", hash = "sha256:72dbebb2dcc8305c431b2836bcc66af967df91be793d63a24e3d9b741374c450", size = 12927049, upload-time = "2025-07-24T20:48:56.24Z" }, + { url = "https://files.pythonhosted.org/packages/e9/ed/13542dd59c104d5e654dfa2ac282c199ba64846a74c2c4bcdbc3a0f75df1/numpy-2.3.2-cp313-cp313t-win_arm64.whl", hash = "sha256:72c6df2267e926a6d5286b0a6d556ebe49eae261062059317837fda12ddf0c1a", size = 10262935, upload-time = "2025-07-24T20:49:13.136Z" }, + { url = "https://files.pythonhosted.org/packages/c9/7c/7659048aaf498f7611b783e000c7268fcc4dcf0ce21cd10aad7b2e8f9591/numpy-2.3.2-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:448a66d052d0cf14ce9865d159bfc403282c9bc7bb2a31b03cc18b651eca8b1a", size = 20950906, upload-time = "2025-07-24T20:50:30.346Z" }, + { url = "https://files.pythonhosted.org/packages/80/db/984bea9d4ddf7112a04cfdfb22b1050af5757864cfffe8e09e44b7f11a10/numpy-2.3.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:546aaf78e81b4081b2eba1d105c3b34064783027a06b3ab20b6eba21fb64132b", size = 14185607, upload-time = "2025-07-24T20:50:51.923Z" }, + { url = "https://files.pythonhosted.org/packages/e4/76/b3d6f414f4eca568f469ac112a3b510938d892bc5a6c190cb883af080b77/numpy-2.3.2-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:87c930d52f45df092f7578889711a0768094debf73cfcde105e2d66954358125", size = 5114110, upload-time = "2025-07-24T20:51:01.041Z" }, + { url = "https://files.pythonhosted.org/packages/9e/d2/6f5e6826abd6bca52392ed88fe44a4b52aacb60567ac3bc86c67834c3a56/numpy-2.3.2-cp314-cp314-macosx_14_0_x86_64.whl", hash = "sha256:8dc082ea901a62edb8f59713c6a7e28a85daddcb67454c839de57656478f5b19", size = 6642050, upload-time = "2025-07-24T20:51:11.64Z" }, + { url = "https://files.pythonhosted.org/packages/c4/43/f12b2ade99199e39c73ad182f103f9d9791f48d885c600c8e05927865baf/numpy-2.3.2-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:af58de8745f7fa9ca1c0c7c943616c6fe28e75d0c81f5c295810e3c83b5be92f", size = 14296292, upload-time = "2025-07-24T20:51:33.488Z" }, + { url = "https://files.pythonhosted.org/packages/5d/f9/77c07d94bf110a916b17210fac38680ed8734c236bfed9982fd8524a7b47/numpy-2.3.2-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fed5527c4cf10f16c6d0b6bee1f89958bccb0ad2522c8cadc2efd318bcd545f5", size = 16638913, upload-time = "2025-07-24T20:51:58.517Z" }, + { url = "https://files.pythonhosted.org/packages/9b/d1/9d9f2c8ea399cc05cfff8a7437453bd4e7d894373a93cdc46361bbb49a7d/numpy-2.3.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:095737ed986e00393ec18ec0b21b47c22889ae4b0cd2d5e88342e08b01141f58", size = 16071180, upload-time = "2025-07-24T20:52:22.827Z" }, + { url = "https://files.pythonhosted.org/packages/4c/41/82e2c68aff2a0c9bf315e47d61951099fed65d8cb2c8d9dc388cb87e947e/numpy-2.3.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:b5e40e80299607f597e1a8a247ff8d71d79c5b52baa11cc1cce30aa92d2da6e0", size = 18576809, upload-time = "2025-07-24T20:52:51.015Z" }, + { url = "https://files.pythonhosted.org/packages/14/14/4b4fd3efb0837ed252d0f583c5c35a75121038a8c4e065f2c259be06d2d8/numpy-2.3.2-cp314-cp314-win32.whl", hash = "sha256:7d6e390423cc1f76e1b8108c9b6889d20a7a1f59d9a60cac4a050fa734d6c1e2", size = 6366410, upload-time = "2025-07-24T20:56:44.949Z" }, + { url = "https://files.pythonhosted.org/packages/11/9e/b4c24a6b8467b61aced5c8dc7dcfce23621baa2e17f661edb2444a418040/numpy-2.3.2-cp314-cp314-win_amd64.whl", hash = "sha256:b9d0878b21e3918d76d2209c924ebb272340da1fb51abc00f986c258cd5e957b", size = 12918821, upload-time = "2025-07-24T20:57:06.479Z" }, + { url = "https://files.pythonhosted.org/packages/0e/0f/0dc44007c70b1007c1cef86b06986a3812dd7106d8f946c09cfa75782556/numpy-2.3.2-cp314-cp314-win_arm64.whl", hash = "sha256:2738534837c6a1d0c39340a190177d7d66fdf432894f469728da901f8f6dc910", size = 10477303, upload-time = "2025-07-24T20:57:22.879Z" }, + { url = "https://files.pythonhosted.org/packages/8b/3e/075752b79140b78ddfc9c0a1634d234cfdbc6f9bbbfa6b7504e445ad7d19/numpy-2.3.2-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:4d002ecf7c9b53240be3bb69d80f86ddbd34078bae04d87be81c1f58466f264e", size = 21047524, upload-time = "2025-07-24T20:53:22.086Z" }, + { url = "https://files.pythonhosted.org/packages/fe/6d/60e8247564a72426570d0e0ea1151b95ce5bd2f1597bb878a18d32aec855/numpy-2.3.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:293b2192c6bcce487dbc6326de5853787f870aeb6c43f8f9c6496db5b1781e45", size = 14300519, upload-time = "2025-07-24T20:53:44.053Z" }, + { url = "https://files.pythonhosted.org/packages/4d/73/d8326c442cd428d47a067070c3ac6cc3b651a6e53613a1668342a12d4479/numpy-2.3.2-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:0a4f2021a6da53a0d580d6ef5db29947025ae8b35b3250141805ea9a32bbe86b", size = 5228972, upload-time = "2025-07-24T20:53:53.81Z" }, + { url = "https://files.pythonhosted.org/packages/34/2e/e71b2d6dad075271e7079db776196829019b90ce3ece5c69639e4f6fdc44/numpy-2.3.2-cp314-cp314t-macosx_14_0_x86_64.whl", hash = "sha256:9c144440db4bf3bb6372d2c3e49834cc0ff7bb4c24975ab33e01199e645416f2", size = 6737439, upload-time = "2025-07-24T20:54:04.742Z" }, + { url = "https://files.pythonhosted.org/packages/15/b0/d004bcd56c2c5e0500ffc65385eb6d569ffd3363cb5e593ae742749b2daa/numpy-2.3.2-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f92d6c2a8535dc4fe4419562294ff957f83a16ebdec66df0805e473ffaad8bd0", size = 14352479, upload-time = "2025-07-24T20:54:25.819Z" }, + { url = "https://files.pythonhosted.org/packages/11/e3/285142fcff8721e0c99b51686426165059874c150ea9ab898e12a492e291/numpy-2.3.2-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:cefc2219baa48e468e3db7e706305fcd0c095534a192a08f31e98d83a7d45fb0", size = 16702805, upload-time = "2025-07-24T20:54:50.814Z" }, + { url = "https://files.pythonhosted.org/packages/33/c3/33b56b0e47e604af2c7cd065edca892d180f5899599b76830652875249a3/numpy-2.3.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:76c3e9501ceb50b2ff3824c3589d5d1ab4ac857b0ee3f8f49629d0de55ecf7c2", size = 16133830, upload-time = "2025-07-24T20:55:17.306Z" }, + { url = "https://files.pythonhosted.org/packages/6e/ae/7b1476a1f4d6a48bc669b8deb09939c56dd2a439db1ab03017844374fb67/numpy-2.3.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:122bf5ed9a0221b3419672493878ba4967121514b1d7d4656a7580cd11dddcbf", size = 18652665, upload-time = "2025-07-24T20:55:46.665Z" }, + { url = "https://files.pythonhosted.org/packages/14/ba/5b5c9978c4bb161034148ade2de9db44ec316fab89ce8c400db0e0c81f86/numpy-2.3.2-cp314-cp314t-win32.whl", hash = "sha256:6f1ae3dcb840edccc45af496f312528c15b1f79ac318169d094e85e4bb35fdf1", size = 6514777, upload-time = "2025-07-24T20:55:57.66Z" }, + { url = "https://files.pythonhosted.org/packages/eb/46/3dbaf0ae7c17cdc46b9f662c56da2054887b8d9e737c1476f335c83d33db/numpy-2.3.2-cp314-cp314t-win_amd64.whl", hash = "sha256:087ffc25890d89a43536f75c5fe8770922008758e8eeeef61733957041ed2f9b", size = 13111856, upload-time = "2025-07-24T20:56:17.318Z" }, + { url = "https://files.pythonhosted.org/packages/c1/9e/1652778bce745a67b5fe05adde60ed362d38eb17d919a540e813d30f6874/numpy-2.3.2-cp314-cp314t-win_arm64.whl", hash = "sha256:092aeb3449833ea9c0bf0089d70c29ae480685dd2377ec9cdbbb620257f84631", size = 10544226, upload-time = "2025-07-24T20:56:34.509Z" }, + { url = "https://files.pythonhosted.org/packages/cf/ea/50ebc91d28b275b23b7128ef25c3d08152bc4068f42742867e07a870a42a/numpy-2.3.2-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:14a91ebac98813a49bc6aa1a0dfc09513dcec1d97eaf31ca21a87221a1cdcb15", size = 21130338, upload-time = "2025-07-24T20:57:54.37Z" }, + { url = "https://files.pythonhosted.org/packages/9f/57/cdd5eac00dd5f137277355c318a955c0d8fb8aa486020c22afd305f8b88f/numpy-2.3.2-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:71669b5daae692189540cffc4c439468d35a3f84f0c88b078ecd94337f6cb0ec", size = 14375776, upload-time = "2025-07-24T20:58:16.303Z" }, + { url = "https://files.pythonhosted.org/packages/83/85/27280c7f34fcd305c2209c0cdca4d70775e4859a9eaa92f850087f8dea50/numpy-2.3.2-pp311-pypy311_pp73-macosx_14_0_arm64.whl", hash = "sha256:69779198d9caee6e547adb933941ed7520f896fd9656834c300bdf4dd8642712", size = 5304882, upload-time = "2025-07-24T20:58:26.199Z" }, + { url = "https://files.pythonhosted.org/packages/48/b4/6500b24d278e15dd796f43824e69939d00981d37d9779e32499e823aa0aa/numpy-2.3.2-pp311-pypy311_pp73-macosx_14_0_x86_64.whl", hash = "sha256:2c3271cc4097beb5a60f010bcc1cc204b300bb3eafb4399376418a83a1c6373c", size = 6818405, upload-time = "2025-07-24T20:58:37.341Z" }, + { url = "https://files.pythonhosted.org/packages/9b/c9/142c1e03f199d202da8e980c2496213509291b6024fd2735ad28ae7065c7/numpy-2.3.2-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8446acd11fe3dc1830568c941d44449fd5cb83068e5c70bd5a470d323d448296", size = 14419651, upload-time = "2025-07-24T20:58:59.048Z" }, + { url = "https://files.pythonhosted.org/packages/8b/95/8023e87cbea31a750a6c00ff9427d65ebc5fef104a136bfa69f76266d614/numpy-2.3.2-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:aa098a5ab53fa407fded5870865c6275a5cd4101cfdef8d6fafc48286a96e981", size = 16760166, upload-time = "2025-07-24T21:28:56.38Z" }, + { url = "https://files.pythonhosted.org/packages/78/e3/6690b3f85a05506733c7e90b577e4762517404ea78bab2ca3a5cb1aeb78d/numpy-2.3.2-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:6936aff90dda378c09bea075af0d9c675fe3a977a9d2402f95a87f440f59f619", size = 12977811, upload-time = "2025-07-24T21:29:18.234Z" }, ] [[package]] @@ -1631,7 +1705,7 @@ docs = [ { name = "docutils" }, { name = "jinja2" }, { name = "nbsphinx" }, - { name = "nox" }, + { name = "nox", extra = ["uv"] }, { name = "numpydoc" }, { name = "pillow" }, { name = "plasmapy-sphinx" }, @@ -1656,7 +1730,7 @@ docs = [ tests = [ { name = "hypothesis" }, { name = "mypy" }, - { name = "nox" }, + { name = "nox", extra = ["uv"] }, { name = "pytest" }, { name = "pytest-cov" }, { name = "pytest-filter-subpackage" }, @@ -1680,8 +1754,8 @@ requires-dist = [ { name = "mpmath", specifier = ">=1.3" }, { name = "mypy", marker = "extra == 'tests'", specifier = ">=1.11" }, { name = "nbsphinx", marker = "extra == 'docs'", specifier = ">=0.9.4" }, - { name = "nox", marker = "extra == 'docs'", specifier = ">=2024.10.9" }, - { name = "nox", marker = "extra == 'tests'", specifier = ">=2024.10.9" }, + { name = "nox", extras = ["uv"], marker = "extra == 'docs'", specifier = ">=2025.5.1" }, + { name = "nox", extras = ["uv"], marker = "extra == 'tests'", specifier = ">=2025.5.1" }, { name = "numpy", specifier = ">=1.24" }, { name = "numpydoc", marker = "extra == 'docs'", specifier = ">=1.7" }, { name = "packaging", specifier = ">=22" }, @@ -2292,49 +2366,67 @@ wheels = [ [[package]] name = "scipy" -version = "1.16.0" +version = "1.16.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "numpy" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/81/18/b06a83f0c5ee8cddbde5e3f3d0bb9b702abfa5136ef6d4620ff67df7eee5/scipy-1.16.0.tar.gz", hash = "sha256:b5ef54021e832869c8cfb03bc3bf20366cbcd426e02a58e8a58d7584dfbb8f62", size = 30581216, upload-time = "2025-06-22T16:27:55.782Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/d9/f8/53fc4884df6b88afd5f5f00240bdc49fee2999c7eff3acf5953eb15bc6f8/scipy-1.16.0-cp311-cp311-macosx_10_14_x86_64.whl", hash = "sha256:deec06d831b8f6b5fb0b652433be6a09db29e996368ce5911faf673e78d20085", size = 36447362, upload-time = "2025-06-22T16:18:17.817Z" }, - { url = "https://files.pythonhosted.org/packages/c9/25/fad8aa228fa828705142a275fc593d701b1817c98361a2d6b526167d07bc/scipy-1.16.0-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:d30c0fe579bb901c61ab4bb7f3eeb7281f0d4c4a7b52dbf563c89da4fd2949be", size = 28547120, upload-time = "2025-06-22T16:18:24.117Z" }, - { url = "https://files.pythonhosted.org/packages/8d/be/d324ddf6b89fd1c32fecc307f04d095ce84abb52d2e88fab29d0cd8dc7a8/scipy-1.16.0-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:b2243561b45257f7391d0f49972fca90d46b79b8dbcb9b2cb0f9df928d370ad4", size = 20818922, upload-time = "2025-06-22T16:18:28.035Z" }, - { url = "https://files.pythonhosted.org/packages/cd/e0/cf3f39e399ac83fd0f3ba81ccc5438baba7cfe02176be0da55ff3396f126/scipy-1.16.0-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:e6d7dfc148135e9712d87c5f7e4f2ddc1304d1582cb3a7d698bbadedb61c7afd", size = 23409695, upload-time = "2025-06-22T16:18:32.497Z" }, - { url = "https://files.pythonhosted.org/packages/5b/61/d92714489c511d3ffd6830ac0eb7f74f243679119eed8b9048e56b9525a1/scipy-1.16.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:90452f6a9f3fe5a2cf3748e7be14f9cc7d9b124dce19667b54f5b429d680d539", size = 33444586, upload-time = "2025-06-22T16:18:37.992Z" }, - { url = "https://files.pythonhosted.org/packages/af/2c/40108915fd340c830aee332bb85a9160f99e90893e58008b659b9f3dddc0/scipy-1.16.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:a2f0bf2f58031c8701a8b601df41701d2a7be17c7ffac0a4816aeba89c4cdac8", size = 35284126, upload-time = "2025-06-22T16:18:43.605Z" }, - { url = "https://files.pythonhosted.org/packages/d3/30/e9eb0ad3d0858df35d6c703cba0a7e16a18a56a9e6b211d861fc6f261c5f/scipy-1.16.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:6c4abb4c11fc0b857474241b812ce69ffa6464b4bd8f4ecb786cf240367a36a7", size = 35608257, upload-time = "2025-06-22T16:18:49.09Z" }, - { url = "https://files.pythonhosted.org/packages/c8/ff/950ee3e0d612b375110d8cda211c1f787764b4c75e418a4b71f4a5b1e07f/scipy-1.16.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b370f8f6ac6ef99815b0d5c9f02e7ade77b33007d74802efc8316c8db98fd11e", size = 38040541, upload-time = "2025-06-22T16:18:55.077Z" }, - { url = "https://files.pythonhosted.org/packages/8b/c9/750d34788288d64ffbc94fdb4562f40f609d3f5ef27ab4f3a4ad00c9033e/scipy-1.16.0-cp311-cp311-win_amd64.whl", hash = "sha256:a16ba90847249bedce8aa404a83fb8334b825ec4a8e742ce6012a7a5e639f95c", size = 38570814, upload-time = "2025-06-22T16:19:00.912Z" }, - { url = "https://files.pythonhosted.org/packages/01/c0/c943bc8d2bbd28123ad0f4f1eef62525fa1723e84d136b32965dcb6bad3a/scipy-1.16.0-cp312-cp312-macosx_10_14_x86_64.whl", hash = "sha256:7eb6bd33cef4afb9fa5f1fb25df8feeb1e52d94f21a44f1d17805b41b1da3180", size = 36459071, upload-time = "2025-06-22T16:19:06.605Z" }, - { url = "https://files.pythonhosted.org/packages/99/0d/270e2e9f1a4db6ffbf84c9a0b648499842046e4e0d9b2275d150711b3aba/scipy-1.16.0-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:1dbc8fdba23e4d80394ddfab7a56808e3e6489176d559c6c71935b11a2d59db1", size = 28490500, upload-time = "2025-06-22T16:19:11.775Z" }, - { url = "https://files.pythonhosted.org/packages/1c/22/01d7ddb07cff937d4326198ec8d10831367a708c3da72dfd9b7ceaf13028/scipy-1.16.0-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:7dcf42c380e1e3737b343dec21095c9a9ad3f9cbe06f9c05830b44b1786c9e90", size = 20762345, upload-time = "2025-06-22T16:19:15.813Z" }, - { url = "https://files.pythonhosted.org/packages/34/7f/87fd69856569ccdd2a5873fe5d7b5bbf2ad9289d7311d6a3605ebde3a94b/scipy-1.16.0-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:26ec28675f4a9d41587266084c626b02899db373717d9312fa96ab17ca1ae94d", size = 23418563, upload-time = "2025-06-22T16:19:20.746Z" }, - { url = "https://files.pythonhosted.org/packages/f6/f1/e4f4324fef7f54160ab749efbab6a4bf43678a9eb2e9817ed71a0a2fd8de/scipy-1.16.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:952358b7e58bd3197cfbd2f2f2ba829f258404bdf5db59514b515a8fe7a36c52", size = 33203951, upload-time = "2025-06-22T16:19:25.813Z" }, - { url = "https://files.pythonhosted.org/packages/6d/f0/b6ac354a956384fd8abee2debbb624648125b298f2c4a7b4f0d6248048a5/scipy-1.16.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:03931b4e870c6fef5b5c0970d52c9f6ddd8c8d3e934a98f09308377eba6f3824", size = 35070225, upload-time = "2025-06-22T16:19:31.416Z" }, - { url = "https://files.pythonhosted.org/packages/e5/73/5cbe4a3fd4bc3e2d67ffad02c88b83edc88f381b73ab982f48f3df1a7790/scipy-1.16.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:512c4f4f85912767c351a0306824ccca6fd91307a9f4318efe8fdbd9d30562ef", size = 35389070, upload-time = "2025-06-22T16:19:37.387Z" }, - { url = "https://files.pythonhosted.org/packages/86/e8/a60da80ab9ed68b31ea5a9c6dfd3c2f199347429f229bf7f939a90d96383/scipy-1.16.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e69f798847e9add03d512eaf5081a9a5c9a98757d12e52e6186ed9681247a1ac", size = 37825287, upload-time = "2025-06-22T16:19:43.375Z" }, - { url = "https://files.pythonhosted.org/packages/ea/b5/29fece1a74c6a94247f8a6fb93f5b28b533338e9c34fdcc9cfe7a939a767/scipy-1.16.0-cp312-cp312-win_amd64.whl", hash = "sha256:adf9b1999323ba335adc5d1dc7add4781cb5a4b0ef1e98b79768c05c796c4e49", size = 38431929, upload-time = "2025-06-22T16:19:49.385Z" }, - { url = "https://files.pythonhosted.org/packages/46/95/0746417bc24be0c2a7b7563946d61f670a3b491b76adede420e9d173841f/scipy-1.16.0-cp313-cp313-macosx_10_14_x86_64.whl", hash = "sha256:e9f414cbe9ca289a73e0cc92e33a6a791469b6619c240aa32ee18abdce8ab451", size = 36418162, upload-time = "2025-06-22T16:19:56.3Z" }, - { url = "https://files.pythonhosted.org/packages/19/5a/914355a74481b8e4bbccf67259bbde171348a3f160b67b4945fbc5f5c1e5/scipy-1.16.0-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:bbba55fb97ba3cdef9b1ee973f06b09d518c0c7c66a009c729c7d1592be1935e", size = 28465985, upload-time = "2025-06-22T16:20:01.238Z" }, - { url = "https://files.pythonhosted.org/packages/58/46/63477fc1246063855969cbefdcee8c648ba4b17f67370bd542ba56368d0b/scipy-1.16.0-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:58e0d4354eacb6004e7aa1cd350e5514bd0270acaa8d5b36c0627bb3bb486974", size = 20737961, upload-time = "2025-06-22T16:20:05.913Z" }, - { url = "https://files.pythonhosted.org/packages/93/86/0fbb5588b73555e40f9d3d6dde24ee6fac7d8e301a27f6f0cab9d8f66ff2/scipy-1.16.0-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:75b2094ec975c80efc273567436e16bb794660509c12c6a31eb5c195cbf4b6dc", size = 23377941, upload-time = "2025-06-22T16:20:10.668Z" }, - { url = "https://files.pythonhosted.org/packages/ca/80/a561f2bf4c2da89fa631b3cbf31d120e21ea95db71fd9ec00cb0247c7a93/scipy-1.16.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:6b65d232157a380fdd11a560e7e21cde34fdb69d65c09cb87f6cc024ee376351", size = 33196703, upload-time = "2025-06-22T16:20:16.097Z" }, - { url = "https://files.pythonhosted.org/packages/11/6b/3443abcd0707d52e48eb315e33cc669a95e29fc102229919646f5a501171/scipy-1.16.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:1d8747f7736accd39289943f7fe53a8333be7f15a82eea08e4afe47d79568c32", size = 35083410, upload-time = "2025-06-22T16:20:21.734Z" }, - { url = "https://files.pythonhosted.org/packages/20/ab/eb0fc00e1e48961f1bd69b7ad7e7266896fe5bad4ead91b5fc6b3561bba4/scipy-1.16.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:eb9f147a1b8529bb7fec2a85cf4cf42bdfadf9e83535c309a11fdae598c88e8b", size = 35387829, upload-time = "2025-06-22T16:20:27.548Z" }, - { url = "https://files.pythonhosted.org/packages/57/9e/d6fc64e41fad5d481c029ee5a49eefc17f0b8071d636a02ceee44d4a0de2/scipy-1.16.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:d2b83c37edbfa837a8923d19c749c1935ad3d41cf196006a24ed44dba2ec4358", size = 37841356, upload-time = "2025-06-22T16:20:35.112Z" }, - { url = "https://files.pythonhosted.org/packages/7c/a7/4c94bbe91f12126b8bf6709b2471900577b7373a4fd1f431f28ba6f81115/scipy-1.16.0-cp313-cp313-win_amd64.whl", hash = "sha256:79a3c13d43c95aa80b87328a46031cf52508cf5f4df2767602c984ed1d3c6bbe", size = 38403710, upload-time = "2025-06-22T16:21:54.473Z" }, - { url = "https://files.pythonhosted.org/packages/47/20/965da8497f6226e8fa90ad3447b82ed0e28d942532e92dd8b91b43f100d4/scipy-1.16.0-cp313-cp313t-macosx_10_14_x86_64.whl", hash = "sha256:f91b87e1689f0370690e8470916fe1b2308e5b2061317ff76977c8f836452a47", size = 36813833, upload-time = "2025-06-22T16:20:43.925Z" }, - { url = "https://files.pythonhosted.org/packages/28/f4/197580c3dac2d234e948806e164601c2df6f0078ed9f5ad4a62685b7c331/scipy-1.16.0-cp313-cp313t-macosx_12_0_arm64.whl", hash = "sha256:88a6ca658fb94640079e7a50b2ad3b67e33ef0f40e70bdb7dc22017dae73ac08", size = 28974431, upload-time = "2025-06-22T16:20:51.302Z" }, - { url = "https://files.pythonhosted.org/packages/8a/fc/e18b8550048d9224426e76906694c60028dbdb65d28b1372b5503914b89d/scipy-1.16.0-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:ae902626972f1bd7e4e86f58fd72322d7f4ec7b0cfc17b15d4b7006efc385176", size = 21246454, upload-time = "2025-06-22T16:20:57.276Z" }, - { url = "https://files.pythonhosted.org/packages/8c/48/07b97d167e0d6a324bfd7484cd0c209cc27338b67e5deadae578cf48e809/scipy-1.16.0-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:8cb824c1fc75ef29893bc32b3ddd7b11cf9ab13c1127fe26413a05953b8c32ed", size = 23772979, upload-time = "2025-06-22T16:21:03.363Z" }, - { url = "https://files.pythonhosted.org/packages/4c/4f/9efbd3f70baf9582edf271db3002b7882c875ddd37dc97f0f675ad68679f/scipy-1.16.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:de2db7250ff6514366a9709c2cba35cb6d08498e961cba20d7cff98a7ee88938", size = 33341972, upload-time = "2025-06-22T16:21:11.14Z" }, - { url = "https://files.pythonhosted.org/packages/3f/dc/9e496a3c5dbe24e76ee24525155ab7f659c20180bab058ef2c5fa7d9119c/scipy-1.16.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:e85800274edf4db8dd2e4e93034f92d1b05c9421220e7ded9988b16976f849c1", size = 35185476, upload-time = "2025-06-22T16:21:19.156Z" }, - { url = "https://files.pythonhosted.org/packages/ce/b3/21001cff985a122ba434c33f2c9d7d1dc3b669827e94f4fc4e1fe8b9dfd8/scipy-1.16.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:4f720300a3024c237ace1cb11f9a84c38beb19616ba7c4cdcd771047a10a1706", size = 35570990, upload-time = "2025-06-22T16:21:27.797Z" }, - { url = "https://files.pythonhosted.org/packages/e5/d3/7ba42647d6709251cdf97043d0c107e0317e152fa2f76873b656b509ff55/scipy-1.16.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:aad603e9339ddb676409b104c48a027e9916ce0d2838830691f39552b38a352e", size = 37950262, upload-time = "2025-06-22T16:21:36.976Z" }, - { url = "https://files.pythonhosted.org/packages/eb/c4/231cac7a8385394ebbbb4f1ca662203e9d8c332825ab4f36ffc3ead09a42/scipy-1.16.0-cp313-cp313t-win_amd64.whl", hash = "sha256:f56296fefca67ba605fd74d12f7bd23636267731a72cb3947963e76b8c0a25db", size = 38515076, upload-time = "2025-06-22T16:21:45.694Z" }, +sdist = { url = "https://files.pythonhosted.org/packages/f5/4a/b927028464795439faec8eaf0b03b011005c487bb2d07409f28bf30879c4/scipy-1.16.1.tar.gz", hash = "sha256:44c76f9e8b6e8e488a586190ab38016e4ed2f8a038af7cd3defa903c0a2238b3", size = 30580861, upload-time = "2025-07-27T16:33:30.834Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/da/91/812adc6f74409b461e3a5fa97f4f74c769016919203138a3bf6fc24ba4c5/scipy-1.16.1-cp311-cp311-macosx_10_14_x86_64.whl", hash = "sha256:c033fa32bab91dc98ca59d0cf23bb876454e2bb02cbe592d5023138778f70030", size = 36552519, upload-time = "2025-07-27T16:26:29.658Z" }, + { url = "https://files.pythonhosted.org/packages/47/18/8e355edcf3b71418d9e9f9acd2708cc3a6c27e8f98fde0ac34b8a0b45407/scipy-1.16.1-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:6e5c2f74e5df33479b5cd4e97a9104c511518fbd979aa9b8f6aec18b2e9ecae7", size = 28638010, upload-time = "2025-07-27T16:26:38.196Z" }, + { url = "https://files.pythonhosted.org/packages/d9/eb/e931853058607bdfbc11b86df19ae7a08686121c203483f62f1ecae5989c/scipy-1.16.1-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:0a55ffe0ba0f59666e90951971a884d1ff6f4ec3275a48f472cfb64175570f77", size = 20909790, upload-time = "2025-07-27T16:26:43.93Z" }, + { url = "https://files.pythonhosted.org/packages/45/0c/be83a271d6e96750cd0be2e000f35ff18880a46f05ce8b5d3465dc0f7a2a/scipy-1.16.1-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:f8a5d6cd147acecc2603fbd382fed6c46f474cccfcf69ea32582e033fb54dcfe", size = 23513352, upload-time = "2025-07-27T16:26:50.017Z" }, + { url = "https://files.pythonhosted.org/packages/7c/bf/fe6eb47e74f762f933cca962db7f2c7183acfdc4483bd1c3813cfe83e538/scipy-1.16.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:cb18899127278058bcc09e7b9966d41a5a43740b5bb8dcba401bd983f82e885b", size = 33534643, upload-time = "2025-07-27T16:26:57.503Z" }, + { url = "https://files.pythonhosted.org/packages/bb/ba/63f402e74875486b87ec6506a4f93f6d8a0d94d10467280f3d9d7837ce3a/scipy-1.16.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:adccd93a2fa937a27aae826d33e3bfa5edf9aa672376a4852d23a7cd67a2e5b7", size = 35376776, upload-time = "2025-07-27T16:27:06.639Z" }, + { url = "https://files.pythonhosted.org/packages/c3/b4/04eb9d39ec26a1b939689102da23d505ea16cdae3dbb18ffc53d1f831044/scipy-1.16.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:18aca1646a29ee9a0625a1be5637fa798d4d81fdf426481f06d69af828f16958", size = 35698906, upload-time = "2025-07-27T16:27:14.943Z" }, + { url = "https://files.pythonhosted.org/packages/04/d6/bb5468da53321baeb001f6e4e0d9049eadd175a4a497709939128556e3ec/scipy-1.16.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:d85495cef541729a70cdddbbf3e6b903421bc1af3e8e3a9a72a06751f33b7c39", size = 38129275, upload-time = "2025-07-27T16:27:23.873Z" }, + { url = "https://files.pythonhosted.org/packages/c4/94/994369978509f227cba7dfb9e623254d0d5559506fe994aef4bea3ed469c/scipy-1.16.1-cp311-cp311-win_amd64.whl", hash = "sha256:226652fca853008119c03a8ce71ffe1b3f6d2844cc1686e8f9806edafae68596", size = 38644572, upload-time = "2025-07-27T16:27:32.637Z" }, + { url = "https://files.pythonhosted.org/packages/f8/d9/ec4864f5896232133f51382b54a08de91a9d1af7a76dfa372894026dfee2/scipy-1.16.1-cp312-cp312-macosx_10_14_x86_64.whl", hash = "sha256:81b433bbeaf35728dad619afc002db9b189e45eebe2cd676effe1fb93fef2b9c", size = 36575194, upload-time = "2025-07-27T16:27:41.321Z" }, + { url = "https://files.pythonhosted.org/packages/5c/6d/40e81ecfb688e9d25d34a847dca361982a6addf8e31f0957b1a54fbfa994/scipy-1.16.1-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:886cc81fdb4c6903a3bb0464047c25a6d1016fef77bb97949817d0c0d79f9e04", size = 28594590, upload-time = "2025-07-27T16:27:49.204Z" }, + { url = "https://files.pythonhosted.org/packages/0e/37/9f65178edfcc629377ce9a64fc09baebea18c80a9e57ae09a52edf84880b/scipy-1.16.1-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:15240c3aac087a522b4eaedb09f0ad061753c5eebf1ea430859e5bf8640d5919", size = 20866458, upload-time = "2025-07-27T16:27:54.98Z" }, + { url = "https://files.pythonhosted.org/packages/2c/7b/749a66766871ea4cb1d1ea10f27004db63023074c22abed51f22f09770e0/scipy-1.16.1-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:65f81a25805f3659b48126b5053d9e823d3215e4a63730b5e1671852a1705921", size = 23539318, upload-time = "2025-07-27T16:28:01.604Z" }, + { url = "https://files.pythonhosted.org/packages/c4/db/8d4afec60eb833a666434d4541a3151eedbf2494ea6d4d468cbe877f00cd/scipy-1.16.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:6c62eea7f607f122069b9bad3f99489ddca1a5173bef8a0c75555d7488b6f725", size = 33292899, upload-time = "2025-07-27T16:28:09.147Z" }, + { url = "https://files.pythonhosted.org/packages/51/1e/79023ca3bbb13a015d7d2757ecca3b81293c663694c35d6541b4dca53e98/scipy-1.16.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:f965bbf3235b01c776115ab18f092a95aa74c271a52577bcb0563e85738fd618", size = 35162637, upload-time = "2025-07-27T16:28:17.535Z" }, + { url = "https://files.pythonhosted.org/packages/b6/49/0648665f9c29fdaca4c679182eb972935b3b4f5ace41d323c32352f29816/scipy-1.16.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:f006e323874ffd0b0b816d8c6a8e7f9a73d55ab3b8c3f72b752b226d0e3ac83d", size = 35490507, upload-time = "2025-07-27T16:28:25.705Z" }, + { url = "https://files.pythonhosted.org/packages/62/8f/66cbb9d6bbb18d8c658f774904f42a92078707a7c71e5347e8bf2f52bb89/scipy-1.16.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e8fd15fc5085ab4cca74cb91fe0a4263b1f32e4420761ddae531ad60934c2119", size = 37923998, upload-time = "2025-07-27T16:28:34.339Z" }, + { url = "https://files.pythonhosted.org/packages/14/c3/61f273ae550fbf1667675701112e380881905e28448c080b23b5a181df7c/scipy-1.16.1-cp312-cp312-win_amd64.whl", hash = "sha256:f7b8013c6c066609577d910d1a2a077021727af07b6fab0ee22c2f901f22352a", size = 38508060, upload-time = "2025-07-27T16:28:43.242Z" }, + { url = "https://files.pythonhosted.org/packages/93/0b/b5c99382b839854a71ca9482c684e3472badc62620287cbbdab499b75ce6/scipy-1.16.1-cp313-cp313-macosx_10_14_x86_64.whl", hash = "sha256:5451606823a5e73dfa621a89948096c6528e2896e40b39248295d3a0138d594f", size = 36533717, upload-time = "2025-07-27T16:28:51.706Z" }, + { url = "https://files.pythonhosted.org/packages/eb/e5/69ab2771062c91e23e07c12e7d5033a6b9b80b0903ee709c3c36b3eb520c/scipy-1.16.1-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:89728678c5ca5abd610aee148c199ac1afb16e19844401ca97d43dc548a354eb", size = 28570009, upload-time = "2025-07-27T16:28:57.017Z" }, + { url = "https://files.pythonhosted.org/packages/f4/69/bd75dbfdd3cf524f4d753484d723594aed62cfaac510123e91a6686d520b/scipy-1.16.1-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:e756d688cb03fd07de0fffad475649b03cb89bee696c98ce508b17c11a03f95c", size = 20841942, upload-time = "2025-07-27T16:29:01.152Z" }, + { url = "https://files.pythonhosted.org/packages/ea/74/add181c87663f178ba7d6144b370243a87af8476664d5435e57d599e6874/scipy-1.16.1-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:5aa2687b9935da3ed89c5dbed5234576589dd28d0bf7cd237501ccfbdf1ad608", size = 23498507, upload-time = "2025-07-27T16:29:05.202Z" }, + { url = "https://files.pythonhosted.org/packages/1d/74/ece2e582a0d9550cee33e2e416cc96737dce423a994d12bbe59716f47ff1/scipy-1.16.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:0851f6a1e537fe9399f35986897e395a1aa61c574b178c0d456be5b1a0f5ca1f", size = 33286040, upload-time = "2025-07-27T16:29:10.201Z" }, + { url = "https://files.pythonhosted.org/packages/e4/82/08e4076df538fb56caa1d489588d880ec7c52d8273a606bb54d660528f7c/scipy-1.16.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:fedc2cbd1baed37474b1924c331b97bdff611d762c196fac1a9b71e67b813b1b", size = 35176096, upload-time = "2025-07-27T16:29:17.091Z" }, + { url = "https://files.pythonhosted.org/packages/fa/79/cd710aab8c921375711a8321c6be696e705a120e3011a643efbbcdeeabcc/scipy-1.16.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:2ef500e72f9623a6735769e4b93e9dcb158d40752cdbb077f305487e3e2d1f45", size = 35490328, upload-time = "2025-07-27T16:29:22.928Z" }, + { url = "https://files.pythonhosted.org/packages/71/73/e9cc3d35ee4526d784520d4494a3e1ca969b071fb5ae5910c036a375ceec/scipy-1.16.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:978d8311674b05a8f7ff2ea6c6bce5d8b45a0cb09d4c5793e0318f448613ea65", size = 37939921, upload-time = "2025-07-27T16:29:29.108Z" }, + { url = "https://files.pythonhosted.org/packages/21/12/c0efd2941f01940119b5305c375ae5c0fcb7ec193f806bd8f158b73a1782/scipy-1.16.1-cp313-cp313-win_amd64.whl", hash = "sha256:81929ed0fa7a5713fcdd8b2e6f73697d3b4c4816d090dd34ff937c20fa90e8ab", size = 38479462, upload-time = "2025-07-27T16:30:24.078Z" }, + { url = "https://files.pythonhosted.org/packages/7a/19/c3d08b675260046a991040e1ea5d65f91f40c7df1045fffff412dcfc6765/scipy-1.16.1-cp313-cp313t-macosx_10_14_x86_64.whl", hash = "sha256:bcc12db731858abda693cecdb3bdc9e6d4bd200213f49d224fe22df82687bdd6", size = 36938832, upload-time = "2025-07-27T16:29:35.057Z" }, + { url = "https://files.pythonhosted.org/packages/81/f2/ce53db652c033a414a5b34598dba6b95f3d38153a2417c5a3883da429029/scipy-1.16.1-cp313-cp313t-macosx_12_0_arm64.whl", hash = "sha256:744d977daa4becb9fc59135e75c069f8d301a87d64f88f1e602a9ecf51e77b27", size = 29093084, upload-time = "2025-07-27T16:29:40.201Z" }, + { url = "https://files.pythonhosted.org/packages/a9/ae/7a10ff04a7dc15f9057d05b33737ade244e4bd195caa3f7cc04d77b9e214/scipy-1.16.1-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:dc54f76ac18073bcecffb98d93f03ed6b81a92ef91b5d3b135dcc81d55a724c7", size = 21365098, upload-time = "2025-07-27T16:29:44.295Z" }, + { url = "https://files.pythonhosted.org/packages/36/ac/029ff710959932ad3c2a98721b20b405f05f752f07344622fd61a47c5197/scipy-1.16.1-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:367d567ee9fc1e9e2047d31f39d9d6a7a04e0710c86e701e053f237d14a9b4f6", size = 23896858, upload-time = "2025-07-27T16:29:48.784Z" }, + { url = "https://files.pythonhosted.org/packages/71/13/d1ef77b6bd7898720e1f0b6b3743cb945f6c3cafa7718eaac8841035ab60/scipy-1.16.1-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:4cf5785e44e19dcd32a0e4807555e1e9a9b8d475c6afff3d21c3c543a6aa84f4", size = 33438311, upload-time = "2025-07-27T16:29:54.164Z" }, + { url = "https://files.pythonhosted.org/packages/2d/e0/e64a6821ffbb00b4c5b05169f1c1fddb4800e9307efe3db3788995a82a2c/scipy-1.16.1-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:3d0b80fb26d3e13a794c71d4b837e2a589d839fd574a6bbb4ee1288c213ad4a3", size = 35279542, upload-time = "2025-07-27T16:30:00.249Z" }, + { url = "https://files.pythonhosted.org/packages/57/59/0dc3c8b43e118f1e4ee2b798dcc96ac21bb20014e5f1f7a8e85cc0653bdb/scipy-1.16.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:8503517c44c18d1030d666cb70aaac1cc8913608816e06742498833b128488b7", size = 35667665, upload-time = "2025-07-27T16:30:05.916Z" }, + { url = "https://files.pythonhosted.org/packages/45/5f/844ee26e34e2f3f9f8febb9343748e72daeaec64fe0c70e9bf1ff84ec955/scipy-1.16.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:30cc4bb81c41831ecfd6dc450baf48ffd80ef5aed0f5cf3ea775740e80f16ecc", size = 38045210, upload-time = "2025-07-27T16:30:11.655Z" }, + { url = "https://files.pythonhosted.org/packages/8d/d7/210f2b45290f444f1de64bc7353aa598ece9f0e90c384b4a156f9b1a5063/scipy-1.16.1-cp313-cp313t-win_amd64.whl", hash = "sha256:c24fa02f7ed23ae514460a22c57eca8f530dbfa50b1cfdbf4f37c05b5309cc39", size = 38593661, upload-time = "2025-07-27T16:30:17.825Z" }, + { url = "https://files.pythonhosted.org/packages/81/ea/84d481a5237ed223bd3d32d6e82d7a6a96e34756492666c260cef16011d1/scipy-1.16.1-cp314-cp314-macosx_10_14_x86_64.whl", hash = "sha256:796a5a9ad36fa3a782375db8f4241ab02a091308eb079746bc0f874c9b998318", size = 36525921, upload-time = "2025-07-27T16:30:30.081Z" }, + { url = "https://files.pythonhosted.org/packages/4e/9f/d9edbdeff9f3a664807ae3aea383e10afaa247e8e6255e6d2aa4515e8863/scipy-1.16.1-cp314-cp314-macosx_12_0_arm64.whl", hash = "sha256:3ea0733a2ff73fd6fdc5fecca54ee9b459f4d74f00b99aced7d9a3adb43fb1cc", size = 28564152, upload-time = "2025-07-27T16:30:35.336Z" }, + { url = "https://files.pythonhosted.org/packages/3b/95/8125bcb1fe04bc267d103e76516243e8d5e11229e6b306bda1024a5423d1/scipy-1.16.1-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:85764fb15a2ad994e708258bb4ed8290d1305c62a4e1ef07c414356a24fcfbf8", size = 20836028, upload-time = "2025-07-27T16:30:39.421Z" }, + { url = "https://files.pythonhosted.org/packages/77/9c/bf92e215701fc70bbcd3d14d86337cf56a9b912a804b9c776a269524a9e9/scipy-1.16.1-cp314-cp314-macosx_14_0_x86_64.whl", hash = "sha256:ca66d980469cb623b1759bdd6e9fd97d4e33a9fad5b33771ced24d0cb24df67e", size = 23489666, upload-time = "2025-07-27T16:30:43.663Z" }, + { url = "https://files.pythonhosted.org/packages/5e/00/5e941d397d9adac41b02839011594620d54d99488d1be5be755c00cde9ee/scipy-1.16.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:e7cc1ffcc230f568549fc56670bcf3df1884c30bd652c5da8138199c8c76dae0", size = 33358318, upload-time = "2025-07-27T16:30:48.982Z" }, + { url = "https://files.pythonhosted.org/packages/0e/87/8db3aa10dde6e3e8e7eb0133f24baa011377d543f5b19c71469cf2648026/scipy-1.16.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:3ddfb1e8d0b540cb4ee9c53fc3dea3186f97711248fb94b4142a1b27178d8b4b", size = 35185724, upload-time = "2025-07-27T16:30:54.26Z" }, + { url = "https://files.pythonhosted.org/packages/89/b4/6ab9ae443216807622bcff02690262d8184078ea467efee2f8c93288a3b1/scipy-1.16.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:4dc0e7be79e95d8ba3435d193e0d8ce372f47f774cffd882f88ea4e1e1ddc731", size = 35554335, upload-time = "2025-07-27T16:30:59.765Z" }, + { url = "https://files.pythonhosted.org/packages/9c/9a/d0e9dc03c5269a1afb60661118296a32ed5d2c24298af61b676c11e05e56/scipy-1.16.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:f23634f9e5adb51b2a77766dac217063e764337fbc816aa8ad9aaebcd4397fd3", size = 37960310, upload-time = "2025-07-27T16:31:06.151Z" }, + { url = "https://files.pythonhosted.org/packages/5e/00/c8f3130a50521a7977874817ca89e0599b1b4ee8e938bad8ae798a0e1f0d/scipy-1.16.1-cp314-cp314-win_amd64.whl", hash = "sha256:57d75524cb1c5a374958a2eae3d84e1929bb971204cc9d52213fb8589183fc19", size = 39319239, upload-time = "2025-07-27T16:31:59.942Z" }, + { url = "https://files.pythonhosted.org/packages/f2/f2/1ca3eda54c3a7e4c92f6acef7db7b3a057deb135540d23aa6343ef8ad333/scipy-1.16.1-cp314-cp314t-macosx_10_14_x86_64.whl", hash = "sha256:d8da7c3dd67bcd93f15618938f43ed0995982eb38973023d46d4646c4283ad65", size = 36939460, upload-time = "2025-07-27T16:31:11.865Z" }, + { url = "https://files.pythonhosted.org/packages/80/30/98c2840b293a132400c0940bb9e140171dcb8189588619048f42b2ce7b4f/scipy-1.16.1-cp314-cp314t-macosx_12_0_arm64.whl", hash = "sha256:cc1d2f2fd48ba1e0620554fe5bc44d3e8f5d4185c8c109c7fbdf5af2792cfad2", size = 29093322, upload-time = "2025-07-27T16:31:17.045Z" }, + { url = "https://files.pythonhosted.org/packages/c1/e6/1e6e006e850622cf2a039b62d1a6ddc4497d4851e58b68008526f04a9a00/scipy-1.16.1-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:21a611ced9275cb861bacadbada0b8c0623bc00b05b09eb97f23b370fc2ae56d", size = 21365329, upload-time = "2025-07-27T16:31:21.188Z" }, + { url = "https://files.pythonhosted.org/packages/8e/02/72a5aa5b820589dda9a25e329ca752842bfbbaf635e36bc7065a9b42216e/scipy-1.16.1-cp314-cp314t-macosx_14_0_x86_64.whl", hash = "sha256:8dfbb25dffc4c3dd9371d8ab456ca81beeaf6f9e1c2119f179392f0dc1ab7695", size = 23897544, upload-time = "2025-07-27T16:31:25.408Z" }, + { url = "https://files.pythonhosted.org/packages/2b/dc/7122d806a6f9eb8a33532982234bed91f90272e990f414f2830cfe656e0b/scipy-1.16.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f0ebb7204f063fad87fc0a0e4ff4a2ff40b2a226e4ba1b7e34bf4b79bf97cd86", size = 33442112, upload-time = "2025-07-27T16:31:30.62Z" }, + { url = "https://files.pythonhosted.org/packages/24/39/e383af23564daa1021a5b3afbe0d8d6a68ec639b943661841f44ac92de85/scipy-1.16.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:f1b9e5962656f2734c2b285a8745358ecb4e4efbadd00208c80a389227ec61ff", size = 35286594, upload-time = "2025-07-27T16:31:36.112Z" }, + { url = "https://files.pythonhosted.org/packages/95/47/1a0b0aff40c3056d955f38b0df5d178350c3d74734ec54f9c68d23910be5/scipy-1.16.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:5e1a106f8c023d57a2a903e771228bf5c5b27b5d692088f457acacd3b54511e4", size = 35665080, upload-time = "2025-07-27T16:31:42.025Z" }, + { url = "https://files.pythonhosted.org/packages/64/df/ce88803e9ed6e27fe9b9abefa157cf2c80e4fa527cf17ee14be41f790ad4/scipy-1.16.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:709559a1db68a9abc3b2c8672c4badf1614f3b440b3ab326d86a5c0491eafae3", size = 38050306, upload-time = "2025-07-27T16:31:48.109Z" }, + { url = "https://files.pythonhosted.org/packages/6e/6c/a76329897a7cae4937d403e623aa6aaea616a0bb5b36588f0b9d1c9a3739/scipy-1.16.1-cp314-cp314t-win_amd64.whl", hash = "sha256:c0c804d60492a0aad7f5b2bb1862f4548b990049e27e828391ff2bf6f7199998", size = 39427705, upload-time = "2025-07-27T16:31:53.96Z" }, ] [[package]] @@ -2855,6 +2947,32 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/a7/c2/fe1e52489ae3122415c51f387e221dd0773709bad6c6cdaa599e8a2c5185/urllib3-2.5.0-py3-none-any.whl", hash = "sha256:e6b01673c0fa6a13e374b50871808eb3bf7046c4b125b216f6bf1cc604cff0dc", size = 129795, upload-time = "2025-06-18T14:07:40.39Z" }, ] +[[package]] +name = "uv" +version = "0.8.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/eb/e3/2c3cb3e992fa1bf9af590bb37983f13e3ae67155820a09a98945664f71f3/uv-0.8.3.tar.gz", hash = "sha256:2ccaae4c749126c99f6404d67a0ae1eae29cbafb05603d09094a775061fdf4e5", size = 3415565, upload-time = "2025-07-24T21:14:34.417Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c1/ab/7b881bb236b9c5f6d99a98adf0c4d1e7c4f0cf4b49051d6d24eb82f19c10/uv-0.8.3-py3-none-linux_armv6l.whl", hash = "sha256:ae7efe91dcfc24126fa91e0fb69a1daf6c0e494a781ba192bb0cc62d7ab623ee", size = 17912668, upload-time = "2025-07-24T21:13:50.682Z" }, + { url = "https://files.pythonhosted.org/packages/fa/9b/64d2ed7388ce88971ffb93d45e74465c95bb885bff40c93f5037b7250930/uv-0.8.3-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:966ec7d7f57521fef0fee685d71e183c9cafb358ddcfe27519dfeaf40550f247", size = 17947557, upload-time = "2025-07-24T21:13:54.59Z" }, + { url = "https://files.pythonhosted.org/packages/9c/ba/8ceec5d6a1adf6b827db557077d8059e573a84c3708a70433d22a0470fab/uv-0.8.3-py3-none-macosx_11_0_arm64.whl", hash = "sha256:3f904f574dc2d7aa1d96ddf2483480ecd121dc9d060108cadd8bff100b754b64", size = 16638472, upload-time = "2025-07-24T21:13:57.57Z" }, + { url = "https://files.pythonhosted.org/packages/a3/76/6d2eb90936603756c4a71f9cf5de8d9214fa4d11dcb5a89117389acecd5e/uv-0.8.3-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:8b16f1bddfdf8f7470924ab34a7b55e4c372d5340c7c1e47e7fc84a743dc541f", size = 17221472, upload-time = "2025-07-24T21:14:00.158Z" }, + { url = "https://files.pythonhosted.org/packages/5b/bf/c3e1cc9604b114dfb49a3a40a230b5410fc97776c149ca73bb524990f9ba/uv-0.8.3-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:526f2c3bd6f311ce31f6f7b6b7d818b191f41e76bed3aaab671b716220c02d8f", size = 17607299, upload-time = "2025-07-24T21:14:02.226Z" }, + { url = "https://files.pythonhosted.org/packages/53/16/819f876f5ca2f8989c19d9b65b7d794d60e6cca0d13187bbc8c8b5532b52/uv-0.8.3-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:76de331a07e5ae9b6490e70a9439a072b91b3167a5684510af10c2752c4ece9a", size = 18218124, upload-time = "2025-07-24T21:14:04.809Z" }, + { url = "https://files.pythonhosted.org/packages/61/a8/1df852a9153fec0c713358a50cfd7a21a4e17b5ed5704a390c0f3da448ab/uv-0.8.3-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:989898caeb6e972979543b57547d1c28ab8af81ff8fc15921fd354c17d432749", size = 19638846, upload-time = "2025-07-24T21:14:07.074Z" }, + { url = "https://files.pythonhosted.org/packages/ac/31/adeedaa009d8d919107c52afb58689d5e9db578b07f8dea5e15e4c738d52/uv-0.8.3-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9ce7981f4fbeecf93dc5cf0a5a7915e84956fd99ad3ac977c048fe0cfdb1a17e", size = 19384261, upload-time = "2025-07-24T21:14:09.425Z" }, + { url = "https://files.pythonhosted.org/packages/8d/87/b3981f499e2b13c5ef0022fd7809f0fccbecd41282ae4f6a0e3fd5fa1430/uv-0.8.3-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8486f7576d15cc73509f93f47b3190f44701ea36839906369301b58c8604d5db", size = 18673722, upload-time = "2025-07-24T21:14:11.656Z" }, + { url = "https://files.pythonhosted.org/packages/5e/62/0d1ba1c666c5492d3716d8d3fba425f65ed2acc6707544c3cbbd381f6cbe/uv-0.8.3-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f1eb7c896fc0d80ed534748aaf46697b6ebc8ce401f1c51666ce0b9923c3db9a", size = 18658829, upload-time = "2025-07-24T21:14:13.798Z" }, + { url = "https://files.pythonhosted.org/packages/cc/ae/11d09be3c74ca4896d55701ebbca7fe7a32db0502cf9f4c57e20bf77bfc4/uv-0.8.3-py3-none-manylinux_2_28_aarch64.whl", hash = "sha256:1121ad1c9389b865d029385031d3fd7d90d343c92a2149a4d4aa20bf469cb27f", size = 17460029, upload-time = "2025-07-24T21:14:15.993Z" }, + { url = "https://files.pythonhosted.org/packages/22/47/b67296c62381b8369f082a33d9fdcb7c579ad9922bcce7b09cd4af935dfa/uv-0.8.3-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:5313ee776ad65731ffa8ac585246f987d3a2bf72e6153c12add1fff22ad6e500", size = 18398665, upload-time = "2025-07-24T21:14:18.399Z" }, + { url = "https://files.pythonhosted.org/packages/01/5f/23990de5487085ca86e12f99d0a8f8410419442ffd35c42838675df5549b/uv-0.8.3-py3-none-musllinux_1_1_armv7l.whl", hash = "sha256:daa6e0d657a94f20e962d4a03d833ef7af5c8e51b7c8a2d92ba6cf64a4c07ac1", size = 17560408, upload-time = "2025-07-24T21:14:20.609Z" }, + { url = "https://files.pythonhosted.org/packages/89/42/1a8ce79d2ce7268e52690cd0f1b6c3e6c8d748a68d42de206e37219e9627/uv-0.8.3-py3-none-musllinux_1_1_i686.whl", hash = "sha256:ad13453ab0a1dfa64a221aac8f52199efdcaa52c97134fffd7bcebed794a6f4b", size = 17758504, upload-time = "2025-07-24T21:14:23.086Z" }, + { url = "https://files.pythonhosted.org/packages/6b/39/ae94e06ac00cb5002e636af0e48c5180fab5b50a463dc96386875ea511ea/uv-0.8.3-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:5843cc43bafad05cc710d8e31bd347ee37202462a63d32c30746e9df48cfbda2", size = 18741736, upload-time = "2025-07-24T21:14:25.329Z" }, + { url = "https://files.pythonhosted.org/packages/18/e0/a2fe9cc5f7b8815cbf97cb1bf64abb71fcb65f25ca7a5a8cdd4c2e23af97/uv-0.8.3-py3-none-win32.whl", hash = "sha256:17bcdb0615e37cc5f985f7d7546f755ac6343c1dc8bbe876c892437f14f8f904", size = 17723422, upload-time = "2025-07-24T21:14:28.02Z" }, + { url = "https://files.pythonhosted.org/packages/cf/c3/da508ec0f6883f1c269a0a477bb6447c81d5383fe3ad5d5ea3d45469fd30/uv-0.8.3-py3-none-win_amd64.whl", hash = "sha256:2e311c029bff2ca07c6ddf877ccc5935cabb78e09b94b53a849542665b6a6fa1", size = 19531666, upload-time = "2025-07-24T21:14:30.192Z" }, + { url = "https://files.pythonhosted.org/packages/b2/8d/c0354e416697b4baa7ceaad0e423639b6683d1f8299355e390a64809f7bf/uv-0.8.3-py3-none-win_arm64.whl", hash = "sha256:391c97577048a40fd8c85b370055df6420f26e81df7fa906f0e0ce1aa2af3527", size = 18161557, upload-time = "2025-07-24T21:14:32.482Z" }, +] + [[package]] name = "virtualenv" version = "20.32.0" From 836cafdce59599cc71fc7de7fe4be2d36290c8c5 Mon Sep 17 00:00:00 2001 From: Erik Everson Date: Tue, 29 Jul 2025 16:15:54 -0700 Subject: [PATCH 381/521] [SLA] Add helper function `merge_voltage_clusters` (#3037) * add argument allow_unsorted to check_sweep * rough out helper function sort_sweep_arrays * add a lint E402 ignore for swept_langmuir/__init__.py * move full construction of the __all__ dunder to the top of the file * fix error string * add messages to raised errors * appease grumpy ruff * add docstring * add test case for allow_unsort == True * use np.diff to decide if we can manually reorder arrays or need to use argsort * add value test cases for sort_sweep_arrays * remove unused code * use the newer numpy.random.Generator * add change log * reformat with statement * fix references * rough out a merge_voltage_clusters() helper func * too much to explain * rename _nan_stuff_regular_grid -> _force_regular_spacing * add docstring to _force_regular_spacing * _force_regular_spacing: only nan stuff the current array * appease grumpy ruff * fix invalid ruff rule in noqa * appease ruff formatter * move grid regularity checking into separate func _is_voltage_regularly_spaced() * rough out docstring for merge_voltage_clusters() * _force_regular_spacing() only NaN stuff if steps of multiples (>1) of voltage_step_size * merge_voltage_clusters(): return quickly if already regularly spaced * add docstring to _is_voltage_regularly_spaced() * create _interpolate_sweep() * create _merge_zero_diff_voltage_clusters() * add return annotations to _interpolate_sweep() * appease grumpy ruff * appease grumpy ruff formatter * add else case so new_voltage and new_current are always defined * create _merge_voltage_clusters() * remove noqa from merge_voltage_clusters() * put back noqa C901 and PLR0912 * fix typo * _force_regular_spacing: fix docstring wording * _is_voltage_regularly_spaced: fix docstring wording * _interpolate_sweep: fix docstring wording * _merge_zero_diff_voltage_clusters: fix docstring wording * _merge_voltage_clusters: fix docstring wording * rename _merge_voltage_clusters -> _merge_voltage_clusters__within_dv * rename _merge_zero_diff_voltage_clusters -> _merge_voltage_clusters__zero_diff_neighbors * rename _interpolate_sweep -> _merge_voltage_clusters__interpolate_sweep * avoid possible infinite loop when voltage_step_size = 0 * expand merge_voltage_clusters docstring * start test_merge_voltage_clusters() * add cases to the tests * use np.arange to generate reg_voltage instead of np.linspace * replace UserWarning with PlasmaPyWarning * add more test scenarios * add another scenario for the PlasmaPyWarning * disable untyped mypy error for tests * update docstring * removed unnecessary mock * rework _merge_voltage_clusters__within_dv so clusters are identified and then merged * remove force_regular_spacing * update warning messages * remove _force_regular_spacing() * if voltage cluster spans a distance larger than voltage_step_size then bin the cluster for averaging * improve docstring * update docstring * update test for removal of kwarg force_regular_spacing * use newshape kwarg * fix variable start_current was supposed to be stop_voltage * add newshape to _typos.toml * add test cases * remove nan mask test (not needed after removing force_regular_spacing) * add clarifying comments about test scenarios * remove _merge_voltage_clusters__interpolate_sweep() * use np.isclose to identify voltage steps near voltage_step_size * if voltage_steps_size is None default to 95% of average step size * modify cluster binning to accounts for clusters sizes that are close to integer multiples of voltage_step_size * only consider voltage regularly spaced if the largest step is less than 10x the smallest step * add test cases * enforce the voltage array needs to be monotonically ascending * add texttt and nbins to _typos.toml * appease grumpy ruff * simplify conditional * add noqa * add changelog entry * remove unused import * appease grump ruff format * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Apply suggestion from @namurphy Co-authored-by: Nick Murphy * replace isinstance type check with numbers.Real * replace isinstance type check with numbers.Integral * return False immediately * add clarifying statement in the docstring * add test case with numpy.nan in voltage array * add kwarg filter_nan and code to automatically filter nan values from the voltage and current arrays * add docstring for filter_nan * add test case for current having np.nan values * more explicit re-raise of Value error * add noqa's to merge_voltage_clusters * fix spelling error * rework cluster identification algorithm so we do not accidentally merge neighboring clusters * add test case for filtering out nan values * all mock count to be 1 or 2 * raise ... from err * appease grumpy ruff format * refacto volt -> leading_cluster_volt * update comment * update error messages * add comment about mock check_sweep() call assertion --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Erik Everson Co-authored-by: Nick Murphy --- _typos.toml | 3 + changelog/3037.feature.rst | 4 + mypy.ini | 3 + .../analysis/swept_langmuir/__init__.py | 2 + .../analysis/swept_langmuir/helpers.py | 342 +++++++++++++++++- .../test_helpers__merge_voltage_clusters.py | 197 ++++++++++ 6 files changed, 545 insertions(+), 6 deletions(-) create mode 100644 changelog/3037.feature.rst create mode 100644 tests/analysis/swept_langmuir/test_helpers__merge_voltage_clusters.py diff --git a/_typos.toml b/_typos.toml index e9f704263a..22c2e5515f 100644 --- a/_typos.toml +++ b/_typos.toml @@ -10,3 +10,6 @@ hax = "hax" iy = "iy" nd = "nd" rety = "rety" +newshape = "newshape" +texttt = "texttt" +nbins = "nbins" diff --git a/changelog/3037.feature.rst b/changelog/3037.feature.rst new file mode 100644 index 0000000000..0b4bbb42aa --- /dev/null +++ b/changelog/3037.feature.rst @@ -0,0 +1,4 @@ +.. currentmodule:: plasmapy.analysis.swept_langmuir + +Added helper function `~helpers.merge_voltage_clusters` to the +`~plasmapy.analysis.swept_langmuir` analysis module. diff --git a/mypy.ini b/mypy.ini index a6b8fd8ae4..c093717935 100644 --- a/mypy.ini +++ b/mypy.ini @@ -331,6 +331,9 @@ disable_error_code = arg-type,no-untyped-def,union-attr [mypy-tests.analysis.swept_langmuir.test_swept_langmuir_helpers] disable_error_code = no-untyped-def +[mypy-tests.analysis.swept_langmuir.test_helpers__merge_voltage_clusters] +disable_error_code = no-untyped-def + [mypy-tests.analysis.test_fit_functions] disable_error_code = assignment,index,no-any-return,no-untyped-call,no-untyped-def,override,type-arg diff --git a/src/plasmapy/analysis/swept_langmuir/__init__.py b/src/plasmapy/analysis/swept_langmuir/__init__.py index 387fd40008..3da6d9bacb 100644 --- a/src/plasmapy/analysis/swept_langmuir/__init__.py +++ b/src/plasmapy/analysis/swept_langmuir/__init__.py @@ -7,6 +7,7 @@ "check_sweep", "find_floating_potential", "find_ion_saturation_current", + "merge_voltage_clusters", "sort_sweep_arrays", "ISatExtras", "VFExtras", @@ -21,6 +22,7 @@ ) from plasmapy.analysis.swept_langmuir.helpers import ( check_sweep, + merge_voltage_clusters, sort_sweep_arrays, ) from plasmapy.analysis.swept_langmuir.ion_saturation_current import ( diff --git a/src/plasmapy/analysis/swept_langmuir/helpers.py b/src/plasmapy/analysis/swept_langmuir/helpers.py index ed739bd613..2a78d65a11 100644 --- a/src/plasmapy/analysis/swept_langmuir/helpers.py +++ b/src/plasmapy/analysis/swept_langmuir/helpers.py @@ -1,12 +1,16 @@ """Helper functions for analyzing swept Langmuir traces.""" -__all__ = ["check_sweep", "sort_sweep_arrays"] +__all__ = ["check_sweep", "merge_voltage_clusters", "sort_sweep_arrays"] +import numbers +import warnings from typing import Literal import astropy.units as u import numpy as np +from plasmapy.utils.exceptions import PlasmaPyWarning + def check_sweep( # noqa: C901, PLR0912 voltage: np.ndarray, @@ -15,9 +19,8 @@ def check_sweep( # noqa: C901, PLR0912 allow_unsorted: bool = False, ) -> tuple[np.ndarray, np.ndarray]: """ - Check that the voltage and current arrays are - properly formatted for analysis by - `plasmapy.analysis.swept_langmuir`. + Check that the voltage and current arrays are properly formatted + for analysis by `plasmapy.analysis.swept_langmuir`. Parameters ---------- @@ -40,8 +43,8 @@ def check_sweep( # noqa: C901, PLR0912 `~astropy.units.Quantity`. allow_unsorted: `bool`, default: `False` - If `True`, then the supplied ``voltage`` - array must be monotonically increasing. + If `True`, then the supplied ``voltage`` array must be + monotonically increasing. Returns ------- @@ -235,3 +238,330 @@ def sort_sweep_arrays( current = current[::-1] return voltage, current + + +def _is_voltage_regularly_spaced( + voltage_diff: np.ndarray, + mask_zero_diff: np.ndarray, +) -> bool: + """ + Determine if the voltage difference array ``voltage_diff`` is + regularly spaced; that is the differences are all equal or some + integer multiple of the smallest difference. + """ + is_regular_grid = False + if np.count_nonzero(mask_zero_diff) > 0: + # is_regular_grid = False + return False + elif np.allclose(voltage_diff, voltage_diff[0]): + # grid is already regularly spaced + is_regular_grid = True + elif np.allclose( + np.rint(voltage_diff / np.min(voltage_diff)) + - voltage_diff / np.min(voltage_diff), + 0, + ): + # grid has a common dV, but at times jumps N * dV times + min_dV = np.min(voltage_diff) + ndV = np.rint(voltage_diff / min_dV) + + is_regular_grid = not np.any(ndV > 10) + + return is_regular_grid + + +def _merge_voltage_clusters__zero_diff_neighbors( + voltage: np.ndarray, current: np.ndarray +) -> tuple[np.ndarray, np.ndarray]: + """ + Take the ``voltage`` and ``current`` arrays associated with a swept + langmuir trace and average together clusters of identical voltage + values. + """ + # generate boolean mask for zero diff locations + voltage_diff = np.diff(voltage) + mask_zero_diff = np.isclose(voltage_diff, 0.0) + mask_zero_diff = np.append(mask_zero_diff, [mask_zero_diff[-1]]) + + # initialize new voltage and current arrays + new_voltage = np.full(voltage.shape, np.nan, dtype=voltage.dtype) + new_current = np.full(current.shape, np.nan, dtype=current.dtype) + + mask = np.logical_not(mask_zero_diff) + new_voltage[mask] = voltage[mask] + new_current[mask] = current[mask] + + # merge zero diff clusters + while np.any(mask_zero_diff): + leading_cluster_volt = voltage[mask_zero_diff][0] + index = np.where(new_voltage == leading_cluster_volt)[0] + if len(index) == 0: + index = np.where(mask_zero_diff)[0] + + index = index[0] + volt_mask = np.isclose(voltage, leading_cluster_volt) + + new_voltage[index] = leading_cluster_volt + new_current[index] = np.average(current[volt_mask]) + + mask_zero_diff[volt_mask] = False + + # remove nan entries + mask = np.logical_not(np.isnan(new_voltage)) + new_voltage = new_voltage[mask] + new_current = new_current[mask] + + return new_voltage, new_current + + +def _merge_voltage_clusters__within_dv( # noqa: C901 + voltage: np.ndarray, + current: np.ndarray, + voltage_step_size: float, +) -> tuple[np.ndarray, np.ndarray]: + """ + Take the ``voltage`` and ``current`` arrays associated with a swept + langmuir trace and average together clusters of voltage values + within step size ``voltage_step_size``. + """ + # initialize new voltage and current arrays + new_voltage = voltage.copy() + new_current = current.copy() + + voltage_diff = np.diff(voltage) + + # generate global cluster mask + mask1 = voltage_diff < voltage_step_size + mask2 = np.isclose(voltage_diff, voltage_step_size) + cluster_mask = np.logical_or(mask1, mask2) + + # determine cluster locations + indices = np.where(np.diff(cluster_mask))[0] + if cluster_mask[0]: + # 1st element in voltage is in a cluster + indices = np.append([0], indices) + indices[1] = indices[1] + 1 + else: + indices[0:2] = indices[0:2] + 1 + if indices.size > 1: + indices[2:] = indices[2:] + 1 + if cluster_mask[-1] and indices[-1] != voltage.size - 1: + # last element in voltage is in a cluster + indices = np.append(indices, [voltage.size - 1]) + indices = np.reshape(indices, newshape=(int(indices.size / 2), 2)) + # ^ using newshape kwarg for backwards compatibility, newshape kwarg + # has been deprecated since numpy v2.1 + + # merge clusters and update new_voltage and new_current + for ii in range(indices.shape[0]): + start_index = indices[ii][0] + stop_index = indices[ii][1] + 1 + + new_voltage[start_index:stop_index] = np.nan + new_current[start_index:stop_index] = np.nan + + sub_voltage = voltage[start_index:stop_index] + sub_current = current[start_index:stop_index] + + v_range = sub_voltage[-1] - sub_voltage[0] + nbins = int(np.rint(v_range / voltage_step_size)) + if not np.isclose(nbins - (v_range / voltage_step_size), 0): + nbins = int( + np.floor((sub_voltage[-1] - sub_voltage[0]) / voltage_step_size) + ) + + if nbins == 0: + nbins = 1 + + if nbins == 1: + new_voltage[start_index] = np.average(sub_voltage) + new_current[start_index] = np.average(sub_current) + continue + + range_array = np.linspace(sub_voltage[0], sub_voltage[-1], nbins + 1) + for jj in range(nbins): + start_voltage = range_array[jj] + stop_voltage = range_array[jj + 1] + + mask1 = sub_voltage >= start_voltage + if jj == nbins - 1: + mask2 = sub_voltage <= stop_voltage + else: + mask2 = sub_voltage < stop_voltage + mask = np.logical_and(mask1, mask2) + + if np.count_nonzero(mask) > 0: + new_voltage[start_index + jj] = np.average(sub_voltage[mask]) + new_current[start_index + jj] = np.average(sub_current[mask]) + + # filter out NaN values + nan_mask = np.logical_not(np.isnan(new_voltage)) + new_voltage = new_voltage[nan_mask] + new_current = new_current[nan_mask] + + return new_voltage, new_current + + +def merge_voltage_clusters( # noqa: C901, PLR0912 + voltage: np.ndarray, + current: np.ndarray, + voltage_step_size: float | None = None, + filter_nan: bool = False, +) -> tuple[np.ndarray, np.ndarray]: + r""" + Search the ``voltage`` array for closely spaced voltage clusters + based on the ``voltage_step_size`` parameter and merge those + clusters, and associated ``current`` values, into a single point. + + This function is intended to merge together identical, or close, + voltage points to remove small step sizes in the swept langmuir + trace before differentiation. + + Parameters + ---------- + voltage: `numpy.ndarray` + 1D `numpy.ndarray` representing the voltage of the swept + Langmuir trace. Voltage needs to be monotonically ascending. + *No units are assumed or checked, but values should be in + volts.* + + current: `numpy.ndarray` + 1D `numpy.ndarray` representing the current of the swept + Langmuir trace. Values should start from a negative + ion-saturation current and increase to a positive + electron-saturation current. *No units are assumed or checked, + but values should be in amperes.* + + voltage_step_size: `float` | `None`, default: `None` + A non-zero, positive step size for the ``voltage`` array + cluster identification. A value of ``0`` will merge only + duplicate voltage values. A value of `None` will default to + 95% of the average step size of the ``voltage`` array (only + counting duplicate voltages once). + + filter_nan: `bool`, default: `False` + Set `True` to automatically filter `~numpy.nan` values from the + ``voltage`` and ``current`` arrays. + + Returns + ------- + voltage : `numpy.ndarray` + The new ``voltage`` array. + + current : `numpy.ndarray` + The new ``current`` array. + + Notes + ----- + An identified voltage cluster can span a voltage range larger than + ``voltage_step_size`` and still have every voltage step being + smaller than ``voltage_step_size``. In this scenario, the voltage + cluster will be divided up into :math:`N`-sections for averaging, + where :math:`N` is given by + + .. math:: + + N = \texttt{floor}\left( + \frac{V_{cluster,max} - V_{cluster,min}}{\texttt{voltage_step_size}} + \right) + """ + # condition voltage_step_size + if voltage_step_size is not None and not isinstance( + voltage_step_size, numbers.Real + ): + raise TypeError( + "Expected 'voltage_step_size' to be a float or None, got type " + f"{type(voltage_step_size)}." + ) + elif isinstance(voltage_step_size, numbers.Integral): + voltage_step_size = float(voltage_step_size) + + try: + voltage, current = check_sweep(voltage, current) + except ValueError as err: + # check if the ValueError was a result of voltage containing nan + # values + if not np.any(np.isnan(voltage)): + # voltage array has no nan values + raise ValueError(*err.args) from err + + if not filter_nan: + raise ValueError( + "The voltage array contains NaN values. If you want NaN " + "values to be automatically filtered, then set argument " + "filter_nan=True." + ) from err + + # filter (voltage) NaN values and check sweep again + nan_mask = np.logical_not(np.isnan(voltage)) + voltage = voltage[nan_mask] + current = current[nan_mask] + + voltage, current = check_sweep(voltage, current) + + # filter (current) NaN values + if not np.any(np.isnan(current)): + # voltage array has no nan values + pass + elif filter_nan: + # mask out current NaN values + nan_mask = np.logical_not(np.isnan(current)) + voltage = voltage[nan_mask] + current = current[nan_mask] + else: + raise ValueError( + "The current array contains NaN values. If you want NaN " + "values to be automatically filtered, then set argument " + "filter_nan=True." + ) + + # check if grid is regularly spaced + voltage_diff = np.diff(voltage) + mask_zero_diff = np.isclose(voltage_diff, 0.0) + is_regular_grid = _is_voltage_regularly_spaced(voltage_diff, mask_zero_diff) + + # return if voltage is already regularly spaced and no voltage merging is + # requested + if is_regular_grid and voltage_step_size is None: + warnings.warn( + "The supplied ``voltage`` array is already regularly spaced. If " + "you want to re-bin the arrays to a different voltage_step_size, " + "then use something like numpy.interp. No merging performed.", + PlasmaPyWarning, + ) + + return voltage.copy(), current.copy() + + # condition voltage_step_size ... Round 2 + if voltage_step_size is None: + voltage_step_size = 0.95 * np.abs( + np.average(voltage_diff[np.logical_not(mask_zero_diff)]) + ) + elif voltage_step_size == 0: + voltage_step_size = 0.0 + elif voltage_step_size < 0: + voltage_step_size = -voltage_step_size + + if np.all(voltage_step_size <= np.abs(voltage_diff)) and voltage_step_size != 0: + warnings.warn( + f"The supplied voltage_step_size ({voltage_step_size}) is smaller than " + f"any of the voltage steps in the voltage array. Supply a step size " + f"greater than the smallest voltage step ({np.min(voltage_diff)}). " + f"No merging performed.", + PlasmaPyWarning, + ) + + return voltage.copy(), current.copy() + + # now merge clusters + if voltage_step_size == 0: + new_voltage, new_current = _merge_voltage_clusters__zero_diff_neighbors( + voltage, current + ) + + else: + new_voltage, new_current = _merge_voltage_clusters__within_dv( + voltage, current, voltage_step_size + ) + + return new_voltage, new_current diff --git a/tests/analysis/swept_langmuir/test_helpers__merge_voltage_clusters.py b/tests/analysis/swept_langmuir/test_helpers__merge_voltage_clusters.py new file mode 100644 index 0000000000..2df5df136f --- /dev/null +++ b/tests/analysis/swept_langmuir/test_helpers__merge_voltage_clusters.py @@ -0,0 +1,197 @@ +""" +Tests for helper function `merge_voltage_clusters` contained in +`plasmapy.analysis.swept_langmuir.helpers`. +""" + +from contextlib import nullcontext as does_not_raise +from unittest import mock + +import numpy as np +import pytest + +from plasmapy.analysis.swept_langmuir.helpers import check_sweep, merge_voltage_clusters +from plasmapy.utils.exceptions import PlasmaPyWarning + + +@pytest.mark.parametrize( + ("voltage", "current", "kwargs", "with_context", "expected"), + [ + # raises + ( + np.linspace(-40.0, 40, 100), + np.linspace(-10.0, 30, 100), + {"voltage_step_size": "wrong type"}, + pytest.raises(TypeError), + None, + ), + ( # voltage array has np.nan values (hence not monotonic) + np.array([1.0, 1.2, np.nan, 2.5]), + np.array([-1, 0, np.nan, 4.3]), + {"filter_nan": False}, + pytest.raises(ValueError), + None, + ), + ( # current array has np.nan values (hence not monotonic) + np.array([1.0, 1.2, 1.8, 2.5]), + np.array([-1, 0, np.nan, 4.3]), + {"filter_nan": False}, + pytest.raises(ValueError), + None, + ), + # warnings (and values) + ( # voltage spacing is regular and not step size given + np.linspace(-40.0, 40, 100), + np.linspace(-10.0, 30, 100), + {"voltage_step_size": None}, + pytest.warns(PlasmaPyWarning), + None, # same as inputs + ), + ( # non-zero voltage_step_size < any step size + np.array([1.1, 1.5, 2, 3.8, 6.0, 6.2], dtype=float), + np.array([-5, -5.2, -2, 0, 4.2, 5], dtype=float), + {"voltage_step_size": 0.1}, + pytest.warns(PlasmaPyWarning), + None, + ), + ( + np.array([1, 1.5, 2.1, 4, 5.5, 6], dtype=float), + np.array([-5, -2, -2, 0, 5, 5], dtype=float), + {"voltage_step_size": 0.2}, + pytest.warns(PlasmaPyWarning), + None, + ), + # values + ( # no merging needed + np.linspace(-40.0, 40, 100), + np.linspace(-10.0, 30, 100), + {"voltage_step_size": 0.0}, + does_not_raise(), + None, # same as inputs + ), + ( # merge identical voltages + np.array([1, 2, 2, 4, 6, 6], dtype=float), + np.array([-5, -2, -2.1, 0, 5, 4.9], dtype=float), + {"voltage_step_size": 0.0}, + does_not_raise(), + ( + np.array([1, 2, 4, 6], dtype=float), + np.array([-5, -2.05, 0, 4.95], dtype=float), + ), + ), + ( # step size given as an integer + np.array([1, 2, 2, 4, 6, 6], dtype=float), + np.array([-5, -2, -2.1, 0, 5, 4.9], dtype=float), + {"voltage_step_size": 0}, # integer value + does_not_raise(), + ( + np.array([1, 2, 4, 6], dtype=float), + np.array([-5, -2.05, 0, 4.95], dtype=float), + ), + ), + ( # voltage_step_size is negative + np.array([1, 1.5, 1.56, 2.1, 4, 5.5, 5.52], dtype=float), + np.array([-5, -2, -2.1, 0, 5, 7, 7.1], dtype=float), + {"voltage_step_size": -0.1}, + does_not_raise(), + ( + np.array([1, 1.53, 2.1, 4, 5.51], dtype=float), + np.array([-5, -2.05, 0, 5, 7.05], dtype=float), + ), + ), + ( # voltage array starts with a cluster + np.array([1, 1.1, 1.2, 1.5, 2, 4, 5.5], dtype=float), + np.array([-5, -5.1, -4.9, -4, 0, 5, 7], dtype=float), + {"voltage_step_size": 0.1}, + does_not_raise(), + ( + np.array([1.0, 1.15, 1.5, 2, 4, 5.5], dtype=float), + np.array([-5.0, -5, -4, 0, 5, 7], dtype=float), + ), + ), + ( # voltage array starts with a cluster, spans < 2 * voltage_step_size + np.array([1, 1.1, 1.2, 1.5, 2, 4, 5.5], dtype=float), + np.array([-5, -5.1, -4.9, -4, 0, 5, 7], dtype=float), + {"voltage_step_size": 0.12}, + does_not_raise(), + ( + np.array([1.1, 1.5, 2, 4, 5.5], dtype=float), + np.array([-5.0, -4, 0, 5, 7], dtype=float), + ), + ), + ( # multiple voltage clusters, including at beginning and end + np.array( + [1, 1.01, 1.05, 1.5, 2, 3.88, 3.9, 3.92, 4.8, 5.5, 5.55], + dtype=float, + ), + np.array( + [-5, -5.1, -4.9, -4, -3, 0, 0.1, -0.1, 5, 7, 6.9], + dtype=float, + ), + {"voltage_step_size": 0.1}, + does_not_raise(), + ( + np.array([1.02, 1.5, 2, 3.9, 4.8, 5.525], dtype=float), + np.array([-5.0, -4, -3, 0, 5, 6.95], dtype=float), + ), + ), + ( # self determine voltage_step_size + np.array( + [1, 1.01, 1.05, 1.5, 2, 3.88, 3.9, 3.92, 4.8, 5.5, 5.55], + dtype=float, + ), + np.array( + [-5, -5.1, -4.9, -4, -3, 0, 0.1, -0.1, 5, 7, 6.9], + dtype=float, + ), + {"voltage_step_size": None}, + does_not_raise(), + ( + np.array([1.02, 1.5, 2, 3.9, 4.8, 5.525], dtype=float), + np.array([-5.0, -4, -3, 0, 5, 6.95], dtype=float), + ), + ), + ( # test case for auto filtering NaN values + np.array( + [1, 1.01, np.nan, 1.5, 2, 3.88, 3.9, np.nan, 4.8, 5.5, 5.55], + dtype=float, + ), + np.array( + [-5, -5.1, np.nan, -4, -3, 0, 0.1, np.nan, np.nan, 7, 6.9], + dtype=float, + ), + {"filter_nan": True, "voltage_step_size": 0.12}, + does_not_raise(), + ( + np.array([1.005, 1.5, 2, 3.89, 5.525], dtype=float), + np.array([-5.05, -4, -3, 0.05, 6.95], dtype=float), + ), + ), + ], +) +def test_merge_voltage_clusters( + voltage, current, kwargs, with_context, expected +) -> None: + with ( + with_context, + mock.patch( + "plasmapy.analysis.swept_langmuir.helpers.check_sweep", + wraps=check_sweep, + ) as mock_sweep, + ): + rtn_voltage, rtn_current = merge_voltage_clusters( + voltage=voltage, + current=current, + **kwargs, + ) + + if expected is not None: + assert np.allclose(rtn_voltage, expected[0]) + assert np.allclose(rtn_current, expected[1]) + else: + assert np.allclose(rtn_voltage, voltage) + assert np.allclose(rtn_current, current) + + # ensure check_sweep() is called...then we do not have to + # explicitly add test cases covered by check_sweep() + assert 0 < mock_sweep.call_count <= 2 + mock_sweep.reset_mock() From 445e1999cb15f23c75a2a90233f554c9ffd36cca Mon Sep 17 00:00:00 2001 From: "plasmapy-requirements-bot[bot]" <134649236+plasmapy-requirements-bot[bot]@users.noreply.github.com> Date: Wed, 30 Jul 2025 00:00:53 +0000 Subject: [PATCH 382/521] Update pinned requirements for `plasmapy_sphinx>=2025.5.1` (#3058) * Update requirements with 'nox -s requirements' * uv add 'plasmapy-sphinx>=2025.5.1' --------- Co-authored-by: namurphy <8931994+namurphy@users.noreply.github.com> Co-authored-by: Nick Murphy --- pyproject.toml | 1 + uv.lock | 8 +++++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 1a9b7a1fbf..59d6ac69ee 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -68,6 +68,7 @@ dependencies = [ "numpy>=1.24", "packaging>=22", "pandas>=2", + "plasmapy-sphinx>=2025.5.1", "requests>=2.28", "scipy>=1.10", "setuptools>=66", diff --git a/uv.lock b/uv.lock index 3df62b19de..4946eb72d3 100644 --- a/uv.lock +++ b/uv.lock @@ -1691,6 +1691,7 @@ dependencies = [ { name = "numpy" }, { name = "packaging" }, { name = "pandas" }, + { name = "plasmapy-sphinx" }, { name = "requests" }, { name = "scipy" }, { name = "setuptools" }, @@ -1761,6 +1762,7 @@ requires-dist = [ { name = "packaging", specifier = ">=22" }, { name = "pandas", specifier = ">=2" }, { name = "pillow", marker = "extra == 'docs'", specifier = ">=10.4" }, + { name = "plasmapy-sphinx", specifier = ">=2025.5.1" }, { name = "plasmapy-sphinx", marker = "extra == 'docs'", specifier = ">=0.2.0b1" }, { name = "pygments", marker = "extra == 'docs'", specifier = "==2.18" }, { name = "pytest", marker = "extra == 'tests'", specifier = ">=8.3.1" }, @@ -1798,7 +1800,7 @@ provides-extras = ["docs", "tests"] [[package]] name = "plasmapy-sphinx" -version = "2025.5.0" +version = "2025.5.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "docutils" }, @@ -1808,9 +1810,9 @@ dependencies = [ { name = "sphinx-gallery" }, { name = "sphinx-rtd-theme" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/1c/c8/cc313f867d1b4106cd7c8717f5f36d720da58d2c2c34cddbf9e36c06e0a6/plasmapy_sphinx-2025.5.0.tar.gz", hash = "sha256:daed4cd5a9a6cee7912f7b2dbf118890e6c1f481c6f2fd0fbe84884f4bdb40ad", size = 74094, upload-time = "2025-05-09T01:49:05.611Z" } +sdist = { url = "https://files.pythonhosted.org/packages/93/2a/8a3c4bdff6de3641db3d99e91a17152200542e7b681ca4731fa088b250b3/plasmapy_sphinx-2025.5.1.tar.gz", hash = "sha256:aac5c182fca4e0fba96fa7f1a8f19ea3e09fb6e93d2ec0e3b999e1a8155518c2", size = 74132, upload-time = "2025-07-29T23:44:02.119Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ee/e3/f2bbc2b507668fa49d72332d41a0ba6456ea860389041457bdd98cb2fb2e/plasmapy_sphinx-2025.5.0-py3-none-any.whl", hash = "sha256:84ea61f639c8c2999732e900bc17f526f3d9221e9bd086cf3ed798c8dc7ae4a3", size = 44342, upload-time = "2025-05-09T01:49:03.652Z" }, + { url = "https://files.pythonhosted.org/packages/ca/12/4efedf0181989f0288027c6f1d47bd4f5d8b273ccb4fd17626d346dfead1/plasmapy_sphinx-2025.5.1-py3-none-any.whl", hash = "sha256:e8e08fa7b48e7c2f87ea9e26c2496cac0efc8925ac836408cb3ca8fcb74a51a1", size = 44347, upload-time = "2025-07-29T23:44:00.628Z" }, ] [[package]] From dcea729cd6f85e2e2e7996570f26fbc71e120dba Mon Sep 17 00:00:00 2001 From: Erik Everson Date: Wed, 30 Jul 2025 08:10:57 -0700 Subject: [PATCH 383/521] remove alias find_vp_ --- src/plasmapy/analysis/swept_langmuir/__init__.py | 3 +-- src/plasmapy/analysis/swept_langmuir/plasma_potential.py | 9 +-------- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/src/plasmapy/analysis/swept_langmuir/__init__.py b/src/plasmapy/analysis/swept_langmuir/__init__.py index 8677651059..a17579f11b 100644 --- a/src/plasmapy/analysis/swept_langmuir/__init__.py +++ b/src/plasmapy/analysis/swept_langmuir/__init__.py @@ -13,7 +13,7 @@ "ISatExtras", "VFExtras", ] -__aliases__ = ["find_isat_", "find_vf_", "find_vp_"] +__aliases__ = ["find_isat_", "find_vf_"] __all__ += __aliases__ from plasmapy.analysis.swept_langmuir.floating_potential import ( @@ -33,5 +33,4 @@ ) from plasmapy.analysis.swept_langmuir.plasma_potential import ( find_plasma_potential_via_didv_peak, - find_vp_, ) diff --git a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py index 0564710d4f..9ccac9efab 100644 --- a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py +++ b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py @@ -3,7 +3,7 @@ """ __all__ = ["find_plasma_potential_via_didv_peak"] -__aliases__ = ["find_vp_"] +__aliases__ = [] from typing import NamedTuple @@ -108,10 +108,3 @@ def find_plasma_potential_via_didv_peak( vp = float(np.average(plasma_potentials)) return vp, VpExtras(**rtn_extras) - - -find_vp_ = find_plasma_potential_via_didv_peak -""" -Alias to -:func:`~plasmapy.analysis.swept_langmuir.plasma_potential.find_plasma_potential_via_didv_peak`. -""" From e4cdf8763def11a772a2b98a7daaef08feb246db Mon Sep 17 00:00:00 2001 From: Erik Everson Date: Wed, 30 Jul 2025 08:11:27 -0700 Subject: [PATCH 384/521] rename find_plasma_potential_via_didv_peak -> find_didv_peak --- src/plasmapy/analysis/swept_langmuir/__init__.py | 4 ++-- src/plasmapy/analysis/swept_langmuir/plasma_potential.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/plasmapy/analysis/swept_langmuir/__init__.py b/src/plasmapy/analysis/swept_langmuir/__init__.py index a17579f11b..53ae49b762 100644 --- a/src/plasmapy/analysis/swept_langmuir/__init__.py +++ b/src/plasmapy/analysis/swept_langmuir/__init__.py @@ -7,7 +7,7 @@ "check_sweep", "find_floating_potential", "find_ion_saturation_current", - "find_plasma_potential_via_didv_peak", + "find_didv_peak", "merge_voltage_clusters", "sort_sweep_arrays", "ISatExtras", @@ -32,5 +32,5 @@ find_isat_, ) from plasmapy.analysis.swept_langmuir.plasma_potential import ( - find_plasma_potential_via_didv_peak, + find_didv_peak, ) diff --git a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py index 9ccac9efab..f1785db6ce 100644 --- a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py +++ b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py @@ -2,7 +2,7 @@ Functionality for determining the plasma potential of a Langmuir sweep. """ -__all__ = ["find_plasma_potential_via_didv_peak"] +__all__ = ["find_didv_peak"] __aliases__ = [] from typing import NamedTuple @@ -24,7 +24,7 @@ class VpExtras(NamedTuple): method: str | None -def find_plasma_potential_via_didv_peak( +def find_didv_peak( voltage: np.ndarray, current: np.ndarray, # *, From 64766ab49755c33fa9a5b94385307d09437eff3e Mon Sep 17 00:00:00 2001 From: Erik Everson Date: Wed, 30 Jul 2025 08:31:35 -0700 Subject: [PATCH 385/521] have E402 lint exception be applied to all files in swept_langmuir --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 1a9b7a1fbf..ab119fd6fc 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -325,7 +325,7 @@ lint.per-file-ignores."docs/notebooks/plasma/grids_nonuniform.ipynb" = [ "NPY002 lint.per-file-ignores."setup.py" = [ "D100" ] lint.per-file-ignores."src/plasmapy/analysis/fit_functions.py" = [ "D301" ] -lint.per-file-ignores."src/plasmapy/analysis/swept_langmuir/__init__.py" = [ "E402" ] +lint.per-file-ignores."src/plasmapy/analysis/swept_langmuir/**" = [ "E402" ] lint.per-file-ignores."src/plasmapy/formulary/braginskii.py" = [ "C901", "RET503", "RET504" ] lint.per-file-ignores."src/plasmapy/plasma/sources/*.py" = [ "D102" ] lint.per-file-ignores."src/plasmapy/utils/_pytest_helpers/pytest_helpers.py" = [ "BLE001", "PLR", "SLF001" ] From 3d3ed5dab2eaae267a942c084f75cbe774543902 Mon Sep 17 00:00:00 2001 From: Erik Everson Date: Wed, 30 Jul 2025 08:32:04 -0700 Subject: [PATCH 386/521] put all dunders at the top of the file --- src/plasmapy/analysis/swept_langmuir/plasma_potential.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py index f1785db6ce..8a07c53697 100644 --- a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py +++ b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py @@ -4,11 +4,10 @@ __all__ = ["find_didv_peak"] __aliases__ = [] +__all__ += __aliases__ from typing import NamedTuple -__all__ += __aliases__ - import numpy as np from scipy import signal From 446bf9a678b14e3c27ddd3a4c84e174382bc8411 Mon Sep 17 00:00:00 2001 From: Erik Everson Date: Wed, 30 Jul 2025 08:32:32 -0700 Subject: [PATCH 387/521] remove namedtuple filed mehtod --- src/plasmapy/analysis/swept_langmuir/plasma_potential.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py index 8a07c53697..2c71b5246b 100644 --- a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py +++ b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py @@ -20,7 +20,6 @@ class VpExtras(NamedTuple): data_slice: slice | None savgol_windows: list[int] | None computed_plasma_potentials: list[float] | None - method: str | None def find_didv_peak( @@ -35,7 +34,6 @@ def find_didv_peak( data_slice=None, savgol_windows=None, computed_plasma_potentials=None, - method="didv_peak", )._asdict() # check voltage and current arrays From 80acae629ec2c6e81afbd70911bfc045786e9327 Mon Sep 17 00:00:00 2001 From: Erik Everson Date: Wed, 30 Jul 2025 08:33:08 -0700 Subject: [PATCH 388/521] rename namedtuple fields vp_std -> std and computed_plasma_potentials -> savgol_peaks --- .../analysis/swept_langmuir/plasma_potential.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py index 2c71b5246b..92286319ce 100644 --- a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py +++ b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py @@ -16,10 +16,10 @@ class VpExtras(NamedTuple): - vp_std: float | None + std: float | None data_slice: slice | None savgol_windows: list[int] | None - computed_plasma_potentials: list[float] | None + savgol_peaks: list[float] | None def find_didv_peak( @@ -30,10 +30,10 @@ def find_didv_peak( smooth_fractions=None, ): rtn_extras = VpExtras( - vp_std=None, + std=None, data_slice=None, savgol_windows=None, - computed_plasma_potentials=None, + savgol_peaks=None, )._asdict() # check voltage and current arrays @@ -100,8 +100,8 @@ def find_didv_peak( plasma_potentials.append(float(vp)) rtn_extras["savgol_windows"].append(int(_window)) - rtn_extras["computed_plasma_potentials"] = plasma_potentials - rtn_extras["vp_std"] = float(np.std(plasma_potentials)) + rtn_extras["savgol_peaks"] = plasma_potentials + rtn_extras["std"] = float(np.std(plasma_potentials)) vp = float(np.average(plasma_potentials)) return vp, VpExtras(**rtn_extras) From 0d6cb8fa6353fc880575cef57619ae1c796c580e Mon Sep 17 00:00:00 2001 From: Erik Everson Date: Wed, 30 Jul 2025 08:50:26 -0700 Subject: [PATCH 389/521] rename VpExtras -> dIdVExtras --- src/plasmapy/analysis/swept_langmuir/plasma_potential.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py index 92286319ce..0bccc61c59 100644 --- a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py +++ b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py @@ -15,7 +15,7 @@ from plasmapy.analysis.swept_langmuir.helpers import check_sweep, merge_voltage_clusters -class VpExtras(NamedTuple): +class dIdVExtras(NamedTuple): std: float | None data_slice: slice | None savgol_windows: list[int] | None @@ -29,7 +29,7 @@ def find_didv_peak( floating_potential: float | None = None, smooth_fractions=None, ): - rtn_extras = VpExtras( + rtn_extras = dIdVExtras( std=None, data_slice=None, savgol_windows=None, @@ -104,4 +104,4 @@ def find_didv_peak( rtn_extras["std"] = float(np.std(plasma_potentials)) vp = float(np.average(plasma_potentials)) - return vp, VpExtras(**rtn_extras) + return vp, dIdVExtras(**rtn_extras) From 1412afc58aeab35cfdebc32075c429c578aca2f6 Mon Sep 17 00:00:00 2001 From: Erik Everson Date: Wed, 30 Jul 2025 08:53:22 -0700 Subject: [PATCH 390/521] add noqa's --- src/plasmapy/analysis/swept_langmuir/plasma_potential.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py index 0bccc61c59..a8c4ea3b79 100644 --- a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py +++ b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py @@ -15,14 +15,14 @@ from plasmapy.analysis.swept_langmuir.helpers import check_sweep, merge_voltage_clusters -class dIdVExtras(NamedTuple): +class dIdVExtras(NamedTuple): # noqa: N801 std: float | None data_slice: slice | None savgol_windows: list[int] | None savgol_peaks: list[float] | None -def find_didv_peak( +def find_didv_peak( # noqa: C901, PLR0912 voltage: np.ndarray, current: np.ndarray, # *, From 5b001252dfbadd8c6e0228af44ad3dc98ab63b1a Mon Sep 17 00:00:00 2001 From: Erik Everson Date: Wed, 30 Jul 2025 08:58:44 -0700 Subject: [PATCH 391/521] appease grumpy ruff --- src/plasmapy/analysis/swept_langmuir/plasma_potential.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py index a8c4ea3b79..08903ee3a0 100644 --- a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py +++ b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py @@ -9,7 +9,6 @@ from typing import NamedTuple import numpy as np - from scipy import signal from plasmapy.analysis.swept_langmuir.helpers import check_sweep, merge_voltage_clusters From 7b87e1f44ebb2c0b0055c122f6b298bb73c1df26 Mon Sep 17 00:00:00 2001 From: Erik Everson Date: Wed, 30 Jul 2025 10:15:11 -0700 Subject: [PATCH 392/521] replace kwarg floating_potential with voltage_window --- .../swept_langmuir/plasma_potential.py | 79 ++++++++++++++----- 1 file changed, 59 insertions(+), 20 deletions(-) diff --git a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py index 08903ee3a0..9de3b7f78b 100644 --- a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py +++ b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py @@ -6,6 +6,8 @@ __aliases__ = [] __all__ += __aliases__ +import numbers +from collections.abc import Sequence from typing import NamedTuple import numpy as np @@ -24,8 +26,8 @@ class dIdVExtras(NamedTuple): # noqa: N801 def find_didv_peak( # noqa: C901, PLR0912 voltage: np.ndarray, current: np.ndarray, - # *, - floating_potential: float | None = None, + *, + voltage_window: list[float | None] | None = None, smooth_fractions=None, ): rtn_extras = dIdVExtras( @@ -39,28 +41,65 @@ def find_didv_peak( # noqa: C901, PLR0912 voltage, current = check_sweep(voltage, current, strip_units=True) voltage, current = merge_voltage_clusters(voltage, current, voltage_step_size=0) - # condition floating potential - if floating_potential is None: - pass - elif not isinstance(floating_potential, float | int | np.floating | np.integer): + # condition voltage_windows + if voltage_window is None: + voltage_window = [None, None] + elif not isinstance(voltage_window, Sequence): raise TypeError( - f"Expected None or float for floating_potential, got type " - f"{type(floating_potential)}." + f"Expected a 2-element list of floats or None for 'voltage_window', " + f"but got type {type(voltage_window)}." ) - elif not (np.min(voltage) <= floating_potential <= np.max(voltage)): + elif len(voltage_window) != 2: raise ValueError( - f"Given floating_potential ({floating_potential}) is outside range " - f"[{np.min(voltage)}, {np.max(voltage)}]." + f"Expected a 2-element list of floats or None for 'voltage_window', " + f"but got type {len(voltage_window)} elements." ) + elif not all( + isinstance(element, numbers.Real) or element is None + for element in voltage_window + ): + raise TypeError(f"Not all elements of 'voltage_window' are floats or None.") + elif None not in voltage_window: + voltage_window = np.sort(voltage).tolist() # determine data window - first_index = 0 - if floating_potential is not None: - mask = voltage > floating_potential - if np.count_nonzero(mask) > 0: - first_index = np.where(mask)[0][0] - data_size = voltage.size - first_index - rtn_extras["data_slice"] = slice(int(first_index), None, 1) + if ( + voltage_window[0] is None + or voltage_window[0] <= voltage[0] + ): + first_index = None + elif voltage_window[0] >= voltage[-1]: + raise ValueError( + f"The min value for the voltage window ({voltage_window[0]}) " + f"is larger than the max value of the langmuir trace " + f"({voltage[-1]})." + ) + else: + first_index = int(np.where(voltage >= voltage_window[0])[0][0]) + + if ( + voltage_window[1] is None + or voltage_window[1] >= voltage[-1] + ): + last_index = None + elif voltage_window[1] <= voltage[0]: + raise ValueError( + f"The max value for the voltage window ({voltage_window[1]}) " + f"is smaller than the min value of the langmuir trace " + f"({voltage[0]})." + ) + else: + last_index = int(np.where(voltage < voltage_window[1])[0][0]) + + _slice = slice(first_index, last_index, 1) + data_size = len(_slice.indices(voltage.size)) + if data_size <= 1: + raise ValueError( + f"The specified voltage_window ({voltage_window}) would result " + f"in a null window or a 1-element window." + ) + + rtn_extras["data_slice"] = _slice # define smooth_fractions # TODO: add better description @@ -76,8 +115,8 @@ def find_didv_peak( # noqa: C901, PLR0912 smooth_windows[mask] = smooth_windows[mask] + 1 smooth_windows = np.unique(smooth_windows) - voltage_slice = voltage[first_index:] - current_slice = current[first_index:] + voltage_slice = voltage[_slice] + current_slice = current[_slice] plasma_potentials = [] rtn_extras["savgol_windows"] = [] for _window in smooth_windows: From 2f89e21dddac76022b3a4053854fa00fccd88668 Mon Sep 17 00:00:00 2001 From: Erik Everson Date: Wed, 30 Jul 2025 10:22:40 -0700 Subject: [PATCH 393/521] rough out docstring for find_didv_peak --- .../swept_langmuir/plasma_potential.py | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py index 9de3b7f78b..acf11b394b 100644 --- a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py +++ b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py @@ -30,6 +30,34 @@ def find_didv_peak( # noqa: C901, PLR0912 voltage_window: list[float | None] | None = None, smooth_fractions=None, ): + """ + Find the peak slope (:math:`dI/dV_{max}`) of the swept Langmuir + trace. + + This is often used as a rough estimate of the plasma potential. + However, it will always be slightly less than the actual plasma + potential. + + Parameters + ---------- + voltage : `numpy.ndarray` + 1-D numpy array of monotonically increasing probe biases + (should be in volts). + + current : `numpy.ndarray` + 1-D numpy array of probe current (should be in amperes) + corresponding to the ``voltage`` array. + + voltage_window : `list[float | None]` | `None`, default: `None` + A two-element list ``[v_min, v_max]`` that specifies the voltage + range in which the peak slope will be looked for. Specifying + `None` for either the first or second element will result in a + window using the lower or upper bound of ``voltage`` + respectively. If set to `None` (default), then the whole + ``voltage`` window will be used. + + smooth_fractions : `list[float]` | `None`, default: `None` + """ rtn_extras = dIdVExtras( std=None, data_slice=None, From c242dd438a39b6815fbdbcaeb1c4e04417de01f5 Mon Sep 17 00:00:00 2001 From: Erik Everson Date: Wed, 30 Jul 2025 11:35:25 -0700 Subject: [PATCH 394/521] move voltage_window conditioning into dedicated func _condition_voltage_window --- .../swept_langmuir/plasma_potential.py | 100 +++++++++--------- 1 file changed, 52 insertions(+), 48 deletions(-) diff --git a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py index acf11b394b..1b312ccb11 100644 --- a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py +++ b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py @@ -23,53 +23,7 @@ class dIdVExtras(NamedTuple): # noqa: N801 savgol_peaks: list[float] | None -def find_didv_peak( # noqa: C901, PLR0912 - voltage: np.ndarray, - current: np.ndarray, - *, - voltage_window: list[float | None] | None = None, - smooth_fractions=None, -): - """ - Find the peak slope (:math:`dI/dV_{max}`) of the swept Langmuir - trace. - - This is often used as a rough estimate of the plasma potential. - However, it will always be slightly less than the actual plasma - potential. - - Parameters - ---------- - voltage : `numpy.ndarray` - 1-D numpy array of monotonically increasing probe biases - (should be in volts). - - current : `numpy.ndarray` - 1-D numpy array of probe current (should be in amperes) - corresponding to the ``voltage`` array. - - voltage_window : `list[float | None]` | `None`, default: `None` - A two-element list ``[v_min, v_max]`` that specifies the voltage - range in which the peak slope will be looked for. Specifying - `None` for either the first or second element will result in a - window using the lower or upper bound of ``voltage`` - respectively. If set to `None` (default), then the whole - ``voltage`` window will be used. - - smooth_fractions : `list[float]` | `None`, default: `None` - """ - rtn_extras = dIdVExtras( - std=None, - data_slice=None, - savgol_windows=None, - savgol_peaks=None, - )._asdict() - - # check voltage and current arrays - voltage, current = check_sweep(voltage, current, strip_units=True) - voltage, current = merge_voltage_clusters(voltage, current, voltage_step_size=0) - - # condition voltage_windows +def _condition_voltage_window(voltage, voltage_window) -> slice: if voltage_window is None: voltage_window = [None, None] elif not isinstance(voltage_window, Sequence): @@ -119,7 +73,57 @@ def find_didv_peak( # noqa: C901, PLR0912 else: last_index = int(np.where(voltage < voltage_window[1])[0][0]) - _slice = slice(first_index, last_index, 1) + return slice(first_index, last_index, 1) + + +def find_didv_peak( # noqa: C901, PLR0912 + voltage: np.ndarray, + current: np.ndarray, + *, + voltage_window: list[float | None] | None = None, + smooth_fractions=None, +) -> tuple[np.ndarray, np.ndarray]: + """ + Find the peak slope (:math:`dI/dV_{max}`) of the swept Langmuir + trace. + + This is often used as a rough estimate of the plasma potential. + However, it will always be slightly less than the actual plasma + potential. + + Parameters + ---------- + voltage : `numpy.ndarray` + 1-D numpy array of monotonically increasing probe biases + (should be in volts). + + current : `numpy.ndarray` + 1-D numpy array of probe current (should be in amperes) + corresponding to the ``voltage`` array. + + voltage_window : `list[float | None]` | `None`, default: `None` + A two-element list ``[v_min, v_max]`` that specifies the voltage + range in which the peak slope will be looked for. Specifying + `None` for either the first or second element will result in a + window using the lower or upper bound of ``voltage`` + respectively. If set to `None` (default), then the whole + ``voltage`` window will be used. + + smooth_fractions : `list[float]` | `None`, default: `None` + """ + rtn_extras = dIdVExtras( + std=None, + data_slice=None, + savgol_windows=None, + savgol_peaks=None, + )._asdict() + + # check voltage and current arrays + voltage, current = check_sweep(voltage, current, strip_units=True) + voltage, current = merge_voltage_clusters(voltage, current, voltage_step_size=0) + + # condition voltage_windows + _slice = _condition_voltage_window(voltage, voltage_window) data_size = len(_slice.indices(voltage.size)) if data_size <= 1: raise ValueError( From dd89acda5a8d68d51fca0e8ed19abe361ae80536 Mon Sep 17 00:00:00 2001 From: Erik Everson Date: Wed, 30 Jul 2025 11:36:36 -0700 Subject: [PATCH 395/521] add docstring for _condition_voltage_window --- src/plasmapy/analysis/swept_langmuir/plasma_potential.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py index 1b312ccb11..b0208a4e41 100644 --- a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py +++ b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py @@ -24,6 +24,10 @@ class dIdVExtras(NamedTuple): # noqa: N801 def _condition_voltage_window(voltage, voltage_window) -> slice: + """ + Condition ``voltage_window`` and return resulting `slice` object to + index ``voltage``. + """ if voltage_window is None: voltage_window = [None, None] elif not isinstance(voltage_window, Sequence): From d41dfc61b63f2986c65a1d7c80a97567c8de45ec Mon Sep 17 00:00:00 2001 From: Erik Everson Date: Wed, 30 Jul 2025 11:37:41 -0700 Subject: [PATCH 396/521] a little minor restructuring --- src/plasmapy/analysis/swept_langmuir/plasma_potential.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py index b0208a4e41..03ee947f42 100644 --- a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py +++ b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py @@ -128,6 +128,7 @@ def find_didv_peak( # noqa: C901, PLR0912 # condition voltage_windows _slice = _condition_voltage_window(voltage, voltage_window) + rtn_extras["data_slice"] = _slice data_size = len(_slice.indices(voltage.size)) if data_size <= 1: raise ValueError( @@ -135,8 +136,6 @@ def find_didv_peak( # noqa: C901, PLR0912 f"in a null window or a 1-element window." ) - rtn_extras["data_slice"] = _slice - # define smooth_fractions # TODO: add better description if smooth_fractions is None: From 684343e503bf5733a10ec073efdb53134ba9cfcc Mon Sep 17 00:00:00 2001 From: Erik Everson Date: Wed, 30 Jul 2025 12:19:09 -0700 Subject: [PATCH 397/521] fix the return annotation for find_didv_peak --- src/plasmapy/analysis/swept_langmuir/plasma_potential.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py index 03ee947f42..975520e5f2 100644 --- a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py +++ b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py @@ -86,7 +86,7 @@ def find_didv_peak( # noqa: C901, PLR0912 *, voltage_window: list[float | None] | None = None, smooth_fractions=None, -) -> tuple[np.ndarray, np.ndarray]: +) -> tuple[float, dIdVExtras]: """ Find the peak slope (:math:`dI/dV_{max}`) of the swept Langmuir trace. From 6f4621dd94fb19feeab1c651a465732e1b198e8e Mon Sep 17 00:00:00 2001 From: Erik Everson Date: Wed, 30 Jul 2025 12:19:43 -0700 Subject: [PATCH 398/521] fix misspelling --- src/plasmapy/analysis/swept_langmuir/plasma_potential.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py index 975520e5f2..c3863be141 100644 --- a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py +++ b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py @@ -126,7 +126,7 @@ def find_didv_peak( # noqa: C901, PLR0912 voltage, current = check_sweep(voltage, current, strip_units=True) voltage, current = merge_voltage_clusters(voltage, current, voltage_step_size=0) - # condition voltage_windows + # condition voltage_window _slice = _condition_voltage_window(voltage, voltage_window) rtn_extras["data_slice"] = _slice data_size = len(_slice.indices(voltage.size)) From f725d84c546ac80beb290216fe1f5fb95da64999 Mon Sep 17 00:00:00 2001 From: Erik Everson Date: Wed, 30 Jul 2025 12:20:36 -0700 Subject: [PATCH 399/521] create and implement helper function _condition_smooth_fractions --- .../swept_langmuir/plasma_potential.py | 85 ++++++++++++++++--- 1 file changed, 71 insertions(+), 14 deletions(-) diff --git a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py index c3863be141..7fab24a5cb 100644 --- a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py +++ b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py @@ -80,6 +80,74 @@ def _condition_voltage_window(voltage, voltage_window) -> slice: return slice(first_index, last_index, 1) +def _condition_smooth_fractions(smooth_fractions, data_size): + """ + Condition ``smooth_fractions`` and return the resulting + Savitzky-Golay filter windows sizes, based on the ``data_size``. + """ + if smooth_fractions is None: + smooth_fractions = np.linspace(0.01, 0.25, num=30) + elif ( + isinstance(smooth_fractions, Sequence) + and not isinstance(smooth_fractions, np.ndarray) + ): + smooth_fractions = np.array(smooth_fractions) + + if not isinstance(smooth_fractions, np.ndarray): + raise TypeError( + "Expected a 1-D list of floats in the interval (0, 1] for argument " + f"'smooth_fractions', but got type {type(smooth_fractions)}." + ) + elif smooth_fractions.ndim != 1: + raise ValueError( + "Expected a 1-D list of floats in the interval (0, 1] for argument " + f"'smooth_fractions', but got a {smooth_fractions.ndim}-D list.") + elif not np.issubdtype(smooth_fractions.dtype, np.floating): + raise ValueError( + "Expected a 1-D list of floats in the interval (0, 1] for argument " + f"'smooth_fractions', not all elements are floats." + ) + + smooth_fractions = np.unique(np.sort(smooth_fractions)) + mask1 = smooth_fractions > 0 + mask2 = smooth_fractions <= 1 + mask = np.logical_and(mask1, mask2) + if np.count_nonzero(mask) == 0: + raise ValueError( + "Expected a 1-D list of floats in the interval (0, 1] for argument " + f"'smooth_fractions', no elements are within this interval " + f"{smooth_fractions.tolist()}." + ) + + # create bin sizes (savgol_windows) for the savgol_filter + savgol_windows = np.unique(np.rint(smooth_fractions * data_size).astype(int)) + + # windows need to have at least 2 points + mask = savgol_windows > 2 + savgol_windows = savgol_windows[mask] + + # force windows sizes to be odd + mask = savgol_windows % 2 == 0 + if np.count_nonzero(mask) > 0: + savgol_windows[mask] = savgol_windows[mask] + 1 + savgol_windows = np.unique(savgol_windows) + + # do not let windows sizes be larget than data_size + mask = savgol_windows <= data_size + savgol_windows = savgol_windows[mask] + + # check savgol_windows is not null + if savgol_windows.size == 0: + raise ValueError( + f"The given smooth_fractions ({smooth_fractions}) and " + f"window size ({data_size}) resulted in no valid Savitzky-Golay " + f"filter windows. Computed windows must be odd, greater than 3, " + f"and less than or equal to the windows size." + ) + + return savgol_windows + + def find_didv_peak( # noqa: C901, PLR0912 voltage: np.ndarray, current: np.ndarray, @@ -136,25 +204,14 @@ def find_didv_peak( # noqa: C901, PLR0912 f"in a null window or a 1-element window." ) - # define smooth_fractions - # TODO: add better description - if smooth_fractions is None: - smooth_fractions = np.linspace(0.01, 0.25, num=30) - - # create bin sizes (smooth_windows) for the savgol_filter - smooth_windows = np.unique(np.rint(smooth_fractions * data_size).astype(int)) - mask = smooth_windows > 2 - smooth_windows = smooth_windows[mask] - mask = smooth_windows % 2 == 0 - if np.count_nonzero(mask) > 0: - smooth_windows[mask] = smooth_windows[mask] + 1 - smooth_windows = np.unique(smooth_windows) + # define starting savgol windows + savgol_windows = _condition_smooth_fractions(smooth_fractions, data_size) voltage_slice = voltage[_slice] current_slice = current[_slice] plasma_potentials = [] rtn_extras["savgol_windows"] = [] - for _window in smooth_windows: + for _window in savgol_windows: v_smooth = signal.savgol_filter(voltage_slice, _window, 1) c_smooth = signal.savgol_filter(current_slice, _window, 1) From 7f4a3371e7d25580685c27d0c6779f9426cdc235 Mon Sep 17 00:00:00 2001 From: Erik Everson Date: Wed, 30 Jul 2025 12:21:01 -0700 Subject: [PATCH 400/521] force data_size to be at least 3 elements --- src/plasmapy/analysis/swept_langmuir/plasma_potential.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py index 7fab24a5cb..9f9194eac6 100644 --- a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py +++ b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py @@ -198,10 +198,10 @@ def find_didv_peak( # noqa: C901, PLR0912 _slice = _condition_voltage_window(voltage, voltage_window) rtn_extras["data_slice"] = _slice data_size = len(_slice.indices(voltage.size)) - if data_size <= 1: + if data_size < 3: raise ValueError( f"The specified voltage_window ({voltage_window}) would result " - f"in a null window or a 1-element window." + f"in a null window or a window less than 3-elements." ) # define starting savgol windows From 4a2ab10cfe70c8ae7e8bb7f9a3be233f5c47a668 Mon Sep 17 00:00:00 2001 From: Erik Everson Date: Wed, 30 Jul 2025 12:26:56 -0700 Subject: [PATCH 401/521] add smooth_fractions to docstring, and update annotations --- .../analysis/swept_langmuir/plasma_potential.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py index 9f9194eac6..9330c0f8a7 100644 --- a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py +++ b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py @@ -153,7 +153,7 @@ def find_didv_peak( # noqa: C901, PLR0912 current: np.ndarray, *, voltage_window: list[float | None] | None = None, - smooth_fractions=None, + smooth_fractions: list[float] | None = None, ) -> tuple[float, dIdVExtras]: """ Find the peak slope (:math:`dI/dV_{max}`) of the swept Langmuir @@ -182,6 +182,18 @@ def find_didv_peak( # noqa: C901, PLR0912 ``voltage`` window will be used. smooth_fractions : `list[float]` | `None`, default: `None` + An order list of fractions in the interval :math:`(0, 1]` used + to compute the Savitzky-Golay filter window sizes. For example, + if the ``voltage_windows`` had a size of 50, then a + ``smooth_fraction`` value of 0.5 would result in a + Savitzky-Golay window size of 25. If `None` (default), then + ``smooth_fractions`` will default to + ``np.linspace(0.01, 0.25, num=30)``. + + Notes + ----- + + Add details about algorithm. """ rtn_extras = dIdVExtras( std=None, From 15653ba73c16c52977d18e152424392aa3edaa11 Mon Sep 17 00:00:00 2001 From: Erik Everson Date: Wed, 30 Jul 2025 13:16:14 -0700 Subject: [PATCH 402/521] add breadcrumb note --- src/plasmapy/analysis/swept_langmuir/plasma_potential.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py index 9330c0f8a7..a8c612f790 100644 --- a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py +++ b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py @@ -86,6 +86,9 @@ def _condition_smooth_fractions(smooth_fractions, data_size): Savitzky-Golay filter windows sizes, based on the ``data_size``. """ if smooth_fractions is None: + # Note: If this default value is changed, then the docstring entry + # for smooth_fractions in the find_didv_peak() docstring + # needs to be updated accordingly. smooth_fractions = np.linspace(0.01, 0.25, num=30) elif ( isinstance(smooth_fractions, Sequence) From 75fab19025b2cfd36b043ee62a38274e3690237c Mon Sep 17 00:00:00 2001 From: Erik Everson Date: Wed, 30 Jul 2025 13:16:27 -0700 Subject: [PATCH 403/521] use numpy instead np --- src/plasmapy/analysis/swept_langmuir/plasma_potential.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py index a8c612f790..dfd9b60826 100644 --- a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py +++ b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py @@ -191,7 +191,7 @@ def find_didv_peak( # noqa: C901, PLR0912 ``smooth_fraction`` value of 0.5 would result in a Savitzky-Golay window size of 25. If `None` (default), then ``smooth_fractions`` will default to - ``np.linspace(0.01, 0.25, num=30)``. + ``numpy.linspace(0.01, 0.25, num=30)``. Notes ----- From 82f73aa152293eb80c33570f7d496dad7788a8cb Mon Sep 17 00:00:00 2001 From: Erik Everson Date: Wed, 30 Jul 2025 13:21:48 -0700 Subject: [PATCH 404/521] Apply suggestion from @namurphy Co-authored-by: Nick Murphy --- src/plasmapy/analysis/swept_langmuir/plasma_potential.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py index dfd9b60826..c5b4b509da 100644 --- a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py +++ b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py @@ -135,7 +135,7 @@ def _condition_smooth_fractions(smooth_fractions, data_size): savgol_windows[mask] = savgol_windows[mask] + 1 savgol_windows = np.unique(savgol_windows) - # do not let windows sizes be larget than data_size + # do not let windows sizes exceed data_size mask = savgol_windows <= data_size savgol_windows = savgol_windows[mask] From 15eceef7a016e1b987ab7d99ff753f15b2efb58f Mon Sep 17 00:00:00 2001 From: Erik Everson Date: Wed, 30 Jul 2025 13:22:07 -0700 Subject: [PATCH 405/521] Apply suggestion from @namurphy Co-authored-by: Nick Murphy --- src/plasmapy/analysis/swept_langmuir/plasma_potential.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py index c5b4b509da..b0b24e3979 100644 --- a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py +++ b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py @@ -162,7 +162,7 @@ def find_didv_peak( # noqa: C901, PLR0912 Find the peak slope (:math:`dI/dV_{max}`) of the swept Langmuir trace. - This is often used as a rough estimate of the plasma potential. + The peak slope is often used as a rough estimate of the plasma potential. However, it will always be slightly less than the actual plasma potential. From 3a3946d2072b65c308cba61e9f6f9795ac890109 Mon Sep 17 00:00:00 2001 From: Erik Everson Date: Wed, 30 Jul 2025 13:22:52 -0700 Subject: [PATCH 406/521] Apply suggestion from @namurphy Co-authored-by: Nick Murphy --- src/plasmapy/analysis/swept_langmuir/plasma_potential.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py index b0b24e3979..81cd5c04bd 100644 --- a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py +++ b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py @@ -216,7 +216,7 @@ def find_didv_peak( # noqa: C901, PLR0912 if data_size < 3: raise ValueError( f"The specified voltage_window ({voltage_window}) would result " - f"in a null window or a window less than 3-elements." + f"in a null window or a window with fewer than 3 elements." ) # define starting savgol windows From 0abf9ea64bd287293193feabd9f3f58cb7c96239 Mon Sep 17 00:00:00 2001 From: Erik Everson Date: Wed, 30 Jul 2025 13:26:43 -0700 Subject: [PATCH 407/521] fix line length for docstring --- src/plasmapy/analysis/swept_langmuir/plasma_potential.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py index 81cd5c04bd..7eb9e29697 100644 --- a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py +++ b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py @@ -162,9 +162,9 @@ def find_didv_peak( # noqa: C901, PLR0912 Find the peak slope (:math:`dI/dV_{max}`) of the swept Langmuir trace. - The peak slope is often used as a rough estimate of the plasma potential. - However, it will always be slightly less than the actual plasma - potential. + The peak slope is often used as a rough estimate of the plasma + potential. However, it will always be slightly less than the + actual plasma potential. Parameters ---------- From 6ac2a09cf707e0b6bd32df5082fa3662b2d64a19 Mon Sep 17 00:00:00 2001 From: Erik Everson Date: Wed, 30 Jul 2025 13:54:53 -0700 Subject: [PATCH 408/521] reword docstring for clarity --- .../analysis/swept_langmuir/plasma_potential.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py index 7eb9e29697..c62e22874e 100644 --- a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py +++ b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py @@ -159,12 +159,12 @@ def find_didv_peak( # noqa: C901, PLR0912 smooth_fractions: list[float] | None = None, ) -> tuple[float, dIdVExtras]: """ - Find the peak slope (:math:`dI/dV_{max}`) of the swept Langmuir - trace. + Find the bias voltage at which the peak slope (:math:`dI/dV_{max}`) + of the swept Langmuir trace occurs. - The peak slope is often used as a rough estimate of the plasma - potential. However, it will always be slightly less than the - actual plasma potential. + The peak slope bias voltage is often used as a rough estimate of + the plasma potential. However, the value will always be slightly + less than the actual plasma potential. Parameters ---------- From 9be5e5536976ebd93eadc2fe53b2933cc1bbec99 Mon Sep 17 00:00:00 2001 From: Erik Everson Date: Wed, 30 Jul 2025 13:55:15 -0700 Subject: [PATCH 409/521] fix calculation of data_size --- src/plasmapy/analysis/swept_langmuir/plasma_potential.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py index c62e22874e..12500f120c 100644 --- a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py +++ b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py @@ -212,7 +212,7 @@ def find_didv_peak( # noqa: C901, PLR0912 # condition voltage_window _slice = _condition_voltage_window(voltage, voltage_window) rtn_extras["data_slice"] = _slice - data_size = len(_slice.indices(voltage.size)) + data_size = voltage[_slice].size if data_size < 3: raise ValueError( f"The specified voltage_window ({voltage_window}) would result " From 199191cf33674f7c1963edecb3d33f51d8e09eba Mon Sep 17 00:00:00 2001 From: Erik Everson Date: Wed, 30 Jul 2025 13:56:57 -0700 Subject: [PATCH 410/521] rename find_didv_peak -> find_didv_peak_location --- src/plasmapy/analysis/swept_langmuir/__init__.py | 4 ++-- src/plasmapy/analysis/swept_langmuir/plasma_potential.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/plasmapy/analysis/swept_langmuir/__init__.py b/src/plasmapy/analysis/swept_langmuir/__init__.py index 53ae49b762..ac1678cd9e 100644 --- a/src/plasmapy/analysis/swept_langmuir/__init__.py +++ b/src/plasmapy/analysis/swept_langmuir/__init__.py @@ -7,7 +7,7 @@ "check_sweep", "find_floating_potential", "find_ion_saturation_current", - "find_didv_peak", + "find_didv_peak_location", "merge_voltage_clusters", "sort_sweep_arrays", "ISatExtras", @@ -32,5 +32,5 @@ find_isat_, ) from plasmapy.analysis.swept_langmuir.plasma_potential import ( - find_didv_peak, + find_didv_peak_location, ) diff --git a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py index 12500f120c..508ee92560 100644 --- a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py +++ b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py @@ -2,7 +2,7 @@ Functionality for determining the plasma potential of a Langmuir sweep. """ -__all__ = ["find_didv_peak"] +__all__ = ["find_didv_peak_location"] __aliases__ = [] __all__ += __aliases__ @@ -151,7 +151,7 @@ def _condition_smooth_fractions(smooth_fractions, data_size): return savgol_windows -def find_didv_peak( # noqa: C901, PLR0912 +def find_didv_peak_location( # noqa: C901, PLR0912 voltage: np.ndarray, current: np.ndarray, *, From 28385eff028baf4cf3d609f4493f691f5cf9aa88 Mon Sep 17 00:00:00 2001 From: Erik Everson Date: Wed, 30 Jul 2025 16:19:56 -0700 Subject: [PATCH 411/521] sort voltage_window, not voltage --- src/plasmapy/analysis/swept_langmuir/plasma_potential.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py index 508ee92560..16835ecbb3 100644 --- a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py +++ b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py @@ -46,7 +46,7 @@ def _condition_voltage_window(voltage, voltage_window) -> slice: ): raise TypeError(f"Not all elements of 'voltage_window' are floats or None.") elif None not in voltage_window: - voltage_window = np.sort(voltage).tolist() + voltage_window = np.sort(voltage_window).tolist() # determine data window if ( From e6b537871cc5e8c5fa4a052349b1e3b8107411a5 Mon Sep 17 00:00:00 2001 From: Erik Everson Date: Wed, 30 Jul 2025 16:24:04 -0700 Subject: [PATCH 412/521] initial rough notebook for find_didv_peak_location() --- .../find_didv_peak_location.ipynb | 249 ++++++++++++++++++ 1 file changed, 249 insertions(+) create mode 100644 docs/notebooks/analysis/swept_langmuir/find_didv_peak_location.ipynb diff --git a/docs/notebooks/analysis/swept_langmuir/find_didv_peak_location.ipynb b/docs/notebooks/analysis/swept_langmuir/find_didv_peak_location.ipynb new file mode 100644 index 0000000000..8f3f2c7647 --- /dev/null +++ b/docs/notebooks/analysis/swept_langmuir/find_didv_peak_location.ipynb @@ -0,0 +1,249 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "881e5b44-992f-45fb-b7b0-0ec3db38512d", + "metadata": {}, + "source": [ + "# Swept Langmuir Analysis: Finding Peak Slope\n", + "\n", + "This notebook covers the use of the [**find_didv_peak_location()**](../../../api/plasmapy.analysis.swept_langmuir.plasma_potential.find_didv_peak_location.rst#find-didv-peak-location) function which finds the bias location associated with the peak slope of the swept Langmuir traces.\n", + "\n", + "The bias voltage at the peaks slope is often used as a rough estimate for the plasma potential, but will always be slighlty lower than the actual plasma potential." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d60a04df-c4cc-4b16-956c-e1967d07d4c5", + "metadata": {}, + "outputs": [], + "source": [ + "%matplotlib inline\n", + "\n", + "from pathlib import Path\n", + "\n", + "import matplotlib.pyplot as plt\n", + "import numpy as np\n", + "from scipy import signal\n", + "\n", + "from plasmapy.analysis import swept_langmuir as sla\n", + "\n", + "plt.rcParams[\"figure.figsize\"] = [10.5, 0.56 * 10.5]" + ] + }, + { + "cell_type": "markdown", + "id": "50e81f77-5218-43b4-aa4f-a5aece966c65", + "metadata": { + "editable": true, + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, + "source": [ + "## Contents:\n", + "\n", + "1. [How find_didv_peak_location() works](#How-find_didv_peak_location()-works)\n", + " 1. [Notes about usage](#Notes-about-usage)\n", + " 1. [Knobs to turn](#Knobs-to-turn)\n", + "1. [Calculate the Floating Potential](#Calculate-the-Floating-Potential)\n", + " 1. [Interpreting results](#Interpreting-results)\n", + " 1. [Plotting results](#Plotting-results)" + ] + }, + { + "cell_type": "markdown", + "id": "d00a4864-f2c6-4606-ba19-a35ab420ac5b", + "metadata": {}, + "source": [ + "## How `find_didv_peak_location()` works" + ] + }, + { + "cell_type": "markdown", + "id": "c8f84fdd-6ec3-4633-bb0c-d827635f66cc", + "metadata": {}, + "source": [ + "## Calcualte the Peak Slope" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ab816d3e-caf5-4654-a1e1-b4c7f15c1cb0", + "metadata": {}, + "outputs": [], + "source": [ + "# load data\n", + "filename = \"Beckers2017_noisy.npy\"\n", + "# filename = \"Pace2015.npy\"\n", + "filepath = (Path.cwd() / \"..\" / \"..\" / \"langmuir_samples\" / filename).resolve()\n", + "voltage, current = np.load(filepath)\n", + "\n", + "# voltage array needs to be monotonically increasing/decreasing\n", + "voltage, current = sla.sort_sweep_arrays(voltage, current)\n", + "\n", + "# grabbing floating potential for future use\n", + "vf, _ = sla.find_floating_potential(voltage, current)\n", + "print(f\"floating potential = {vf:.2f} V\")" + ] + }, + { + "cell_type": "markdown", + "id": "8963f972-1159-4058-b313-400023f0ad14", + "metadata": {}, + "source": [ + "### Interpreting results" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e46204b7-a825-4c3a-b00a-46af218a7a05", + "metadata": {}, + "outputs": [], + "source": [ + "results = sla.find_didv_peak_location(voltage, current, voltage_window=[vf, None])\n", + "\n", + "# bias at peak slope\n", + "results[0]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5a544261-3fef-4519-bcaa-489df4ab209a", + "metadata": {}, + "outputs": [], + "source": [ + "results[1].data_slice" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3f20ecd4-5a8f-46e7-8094-c5f0a859277c", + "metadata": {}, + "outputs": [], + "source": [ + "np.where(voltage >= -30)[0][0]" + ] + }, + { + "cell_type": "markdown", + "id": "759e0477-6fb2-4bd4-88d2-29bcd833265f", + "metadata": {}, + "source": [ + "### Plotting results" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7ad1273f-69f8-49f2-bf5e-d9b63311e6fd", + "metadata": { + "editable": true, + "nbsphinx-thumbnail": { + "tooltip": "Peak dI/dV" + }, + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, + "outputs": [], + "source": [ + "figwidth, figheight = plt.rcParams[\"figure.figsize\"]\n", + "figheight = 1.5 * figheight\n", + "fig, axs = plt.subplots(2, 1, figsize=[figwidth, figheight])\n", + "_font_size = 12\n", + "\n", + "bias = results[0]\n", + "extras = results[1]\n", + "\n", + "# first (I vs. V) plot\n", + "axs[0].set_xlabel(\"Bias Voltage (V)\", fontsize=_font_size)\n", + "axs[0].set_ylabel(\"Current (A)\", fontsize=_font_size)\n", + "\n", + "axs[0].plot(voltage, current, label=\"Sweep Data\")\n", + "\n", + "ylim = axs[0].get_ylim()\n", + "xlim = axs[0].get_xlim()\n", + "axs[0].set_ylim(ylim)\n", + "axs[0].axvline(bias, color=\"grey\")\n", + "axs[0].fill_between(\n", + " [bias - extras.std, bias + extras.std],\n", + " 2*[ylim[0]],\n", + " 2*[ylim[1]],\n", + " color=\"grey\",\n", + " alpha=0.2,\n", + ")\n", + "\n", + "# second (dI/dV vs V) plot\n", + "axs[1].set_xlabel(\"Bias Voltage (V)\", fontsize=_font_size)\n", + "axs[1].set_ylabel(\"$dI/dV$ (A / V)\", fontsize=_font_size)\n", + "\n", + "axs[1].set_xlim(xlim)\n", + "\n", + "voltage_merge, current_merge = sla.merge_voltage_clusters(voltage, current, voltage_step_size=0)\n", + "voltage_slice = voltage_merge[extras.data_slice]\n", + "current_slice = current_merge[extras.data_slice]\n", + "\n", + "_colors = plt.get_cmap(\"OrRd\")(np.linspace(0.2, 0.8, len(extras.savgol_windows)))\n", + "for ii, _window in enumerate(extras.savgol_windows):\n", + " v_smooth = signal.savgol_filter(voltage_slice, _window, 1)\n", + " c_smooth = signal.savgol_filter(current_slice, _window, 1)\n", + "\n", + " didv = np.gradient(c_smooth, v_smooth)\n", + "\n", + " axs[1].plot(\n", + " v_smooth[_window:-_window],\n", + " didv[_window:-_window],\n", + " color=_colors[ii],\n", + " label=f\"Savgol window {_window}\",\n", + " )\n", + "\n", + "ylim = axs[1].get_ylim()\n", + "axs[1].set_ylim(ylim)\n", + "\n", + "axs[1].axvline(bias, color=\"grey\", zorder=100)\n", + "axs[1].fill_between(\n", + " [bias - extras.std, bias + extras.std],\n", + " 2*[ylim[0]],\n", + " 2*[ylim[1]],\n", + " color=\"grey\",\n", + " alpha=0.2,\n", + " zorder=0\n", + ")\n", + "\n", + "axs[1].legend()\n", + ";\n", + "\n", + "# axs[1].set_xlim([1, 4]);" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.13.3" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} From 08dd09b52ba71467b7febfebdd1536ccf5a92c1b Mon Sep 17 00:00:00 2001 From: Erik Everson Date: Wed, 30 Jul 2025 16:30:21 -0700 Subject: [PATCH 413/521] add stub file for plasma_potential.py --- .../plasmapy.analysis.swept_langmuir.plasma_potential.rst | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 docs/api_static/plasmapy.analysis.swept_langmuir.plasma_potential.rst diff --git a/docs/api_static/plasmapy.analysis.swept_langmuir.plasma_potential.rst b/docs/api_static/plasmapy.analysis.swept_langmuir.plasma_potential.rst new file mode 100644 index 0000000000..4d04f058db --- /dev/null +++ b/docs/api_static/plasmapy.analysis.swept_langmuir.plasma_potential.rst @@ -0,0 +1,8 @@ +:orphan: + +`plasmapy.analysis.swept_langmuir.plasma_potential` +=================================================== + +.. currentmodule:: plasmapy.analysis.swept_langmuir.plasma_potential + +.. automodapi:: plasmapy.analysis.swept_langmuir.plasma_potential From 593e76edfb369602e6b6db177be3d3c865207a65 Mon Sep 17 00:00:00 2001 From: Erik Everson Date: Wed, 30 Jul 2025 16:47:39 -0700 Subject: [PATCH 414/521] expose dIdVExtras to the swept_langmuir namespace --- src/plasmapy/analysis/swept_langmuir/__init__.py | 2 ++ src/plasmapy/analysis/swept_langmuir/plasma_potential.py | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/plasmapy/analysis/swept_langmuir/__init__.py b/src/plasmapy/analysis/swept_langmuir/__init__.py index ac1678cd9e..be428289e1 100644 --- a/src/plasmapy/analysis/swept_langmuir/__init__.py +++ b/src/plasmapy/analysis/swept_langmuir/__init__.py @@ -10,6 +10,7 @@ "find_didv_peak_location", "merge_voltage_clusters", "sort_sweep_arrays", + "dIdVExtras", "ISatExtras", "VFExtras", ] @@ -32,5 +33,6 @@ find_isat_, ) from plasmapy.analysis.swept_langmuir.plasma_potential import ( + dIdVExtras, find_didv_peak_location, ) diff --git a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py index 16835ecbb3..044190f886 100644 --- a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py +++ b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py @@ -2,7 +2,7 @@ Functionality for determining the plasma potential of a Langmuir sweep. """ -__all__ = ["find_didv_peak_location"] +__all__ = ["find_didv_peak_location", "dIdVExtras"] __aliases__ = [] __all__ += __aliases__ From 7e9c00026cf19af68fdca82122f6441990ca50f1 Mon Sep 17 00:00:00 2001 From: Erik Everson Date: Wed, 30 Jul 2025 16:48:15 -0700 Subject: [PATCH 415/521] add bias text to the plot --- .../find_didv_peak_location.ipynb | 28 ++++++++++++++++--- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/docs/notebooks/analysis/swept_langmuir/find_didv_peak_location.ipynb b/docs/notebooks/analysis/swept_langmuir/find_didv_peak_location.ipynb index 8f3f2c7647..58ebf27f56 100644 --- a/docs/notebooks/analysis/swept_langmuir/find_didv_peak_location.ipynb +++ b/docs/notebooks/analysis/swept_langmuir/find_didv_peak_location.ipynb @@ -181,6 +181,21 @@ " alpha=0.2,\n", ")\n", "\n", + "txt = f\"${bias:.2f} \\\\pm {extras.std:.2f}$ V\\n\"\n", + "txt_loc = [bias, ylim[1]]\n", + "txt_loc = axs[0].transData.transform(txt_loc)\n", + "txt_loc = axs[0].transAxes.inverted().transform(txt_loc)\n", + "txt_loc[0] -= 0.02\n", + "txt_loc[1] -= 0.15\n", + "axs[0].text(\n", + " txt_loc[0],\n", + " txt_loc[1],\n", + " txt,\n", + " fontsize=\"large\",\n", + " transform=axs[0].transAxes,\n", + " ha=\"right\",\n", + ")\n", + "\n", "# second (dI/dV vs V) plot\n", "axs[1].set_xlabel(\"Bias Voltage (V)\", fontsize=_font_size)\n", "axs[1].set_ylabel(\"$dI/dV$ (A / V)\", fontsize=_font_size)\n", @@ -218,11 +233,16 @@ " zorder=0\n", ")\n", "\n", - "axs[1].legend()\n", - ";\n", - "\n", - "# axs[1].set_xlim([1, 4]);" + "axs[1].legend();" ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "50eefb5e-788c-4796-a76f-c27f702eca3b", + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": { From 1a0d1754e347044a45f3071ecc99ba7db60680b4 Mon Sep 17 00:00:00 2001 From: "plasmapy-requirements-bot[bot]" <134649236+plasmapy-requirements-bot[bot]@users.noreply.github.com> Date: Thu, 31 Jul 2025 11:03:35 -0400 Subject: [PATCH 416/521] Update requirements with 'nox -s requirements' (#3062) Co-authored-by: namurphy <8931994+namurphy@users.noreply.github.com> --- uv.lock | 154 ++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 100 insertions(+), 54 deletions(-) diff --git a/uv.lock b/uv.lock index 4946eb72d3..ed815b1e58 100644 --- a/uv.lock +++ b/uv.lock @@ -1,8 +1,9 @@ version = 1 -revision = 2 +revision = 3 requires-python = ">=3.11" resolution-markers = [ - "python_full_version >= '3.12'", + "python_full_version >= '3.14'", + "python_full_version >= '3.12' and python_full_version < '3.14'", "python_full_version < '3.12'", ] @@ -52,7 +53,8 @@ name = "argon2-cffi" version = "25.1.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "argon2-cffi-bindings" }, + { name = "argon2-cffi-bindings", version = "21.2.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.14'" }, + { name = "argon2-cffi-bindings", version = "25.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.14'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/0e/89/ce5af8a7d472a67cc819d5d998aa8c82c5d860608c4db9f46f1162d7dab9/argon2_cffi-25.1.0.tar.gz", hash = "sha256:694ae5cc8a42f4c4e2bf2ca0e64e51e23a040c6a517a85074683d3959e1346c1", size = 45706, upload-time = "2025-06-03T06:55:32.073Z" } wheels = [ @@ -63,8 +65,11 @@ wheels = [ name = "argon2-cffi-bindings" version = "21.2.0" source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.14'", +] dependencies = [ - { name = "cffi" }, + { name = "cffi", marker = "python_full_version >= '3.14'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/b9/e9/184b8ccce6683b0aa2fbb7ba5683ea4b9c5763f1356347f1312c32e3c66e/argon2-cffi-bindings-21.2.0.tar.gz", hash = "sha256:bb89ceffa6c791807d1305ceb77dbfacc5aa499891d2c55661c6459651fc39e3", size = 1779911, upload-time = "2021-12-01T08:52:55.68Z" } wheels = [ @@ -80,6 +85,41 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/5a/e4/bf8034d25edaa495da3c8a3405627d2e35758e44ff6eaa7948092646fdcc/argon2_cffi_bindings-21.2.0-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:e415e3f62c8d124ee16018e491a009937f8cf7ebf5eb430ffc5de21b900dad93", size = 53104, upload-time = "2021-12-01T09:09:31.335Z" }, ] +[[package]] +name = "argon2-cffi-bindings" +version = "25.1.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.12' and python_full_version < '3.14'", + "python_full_version < '3.12'", +] +dependencies = [ + { name = "cffi", marker = "python_full_version < '3.14'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/5c/2d/db8af0df73c1cf454f71b2bbe5e356b8c1f8041c979f505b3d3186e520a9/argon2_cffi_bindings-25.1.0.tar.gz", hash = "sha256:b957f3e6ea4d55d820e40ff76f450952807013d361a65d7f28acc0acbf29229d", size = 1783441, upload-time = "2025-07-30T10:02:05.147Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/60/97/3c0a35f46e52108d4707c44b95cfe2afcafc50800b5450c197454569b776/argon2_cffi_bindings-25.1.0-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:3d3f05610594151994ca9ccb3c771115bdb4daef161976a266f0dd8aa9996b8f", size = 54393, upload-time = "2025-07-30T10:01:40.97Z" }, + { url = "https://files.pythonhosted.org/packages/9d/f4/98bbd6ee89febd4f212696f13c03ca302b8552e7dbf9c8efa11ea4a388c3/argon2_cffi_bindings-25.1.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:8b8efee945193e667a396cbc7b4fb7d357297d6234d30a489905d96caabde56b", size = 29328, upload-time = "2025-07-30T10:01:41.916Z" }, + { url = "https://files.pythonhosted.org/packages/43/24/90a01c0ef12ac91a6be05969f29944643bc1e5e461155ae6559befa8f00b/argon2_cffi_bindings-25.1.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:3c6702abc36bf3ccba3f802b799505def420a1b7039862014a65db3205967f5a", size = 31269, upload-time = "2025-07-30T10:01:42.716Z" }, + { url = "https://files.pythonhosted.org/packages/d4/d3/942aa10782b2697eee7af5e12eeff5ebb325ccfb86dd8abda54174e377e4/argon2_cffi_bindings-25.1.0-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a1c70058c6ab1e352304ac7e3b52554daadacd8d453c1752e547c76e9c99ac44", size = 86558, upload-time = "2025-07-30T10:01:43.943Z" }, + { url = "https://files.pythonhosted.org/packages/0d/82/b484f702fec5536e71836fc2dbc8c5267b3f6e78d2d539b4eaa6f0db8bf8/argon2_cffi_bindings-25.1.0-cp314-cp314t-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e2fd3bfbff3c5d74fef31a722f729bf93500910db650c925c2d6ef879a7e51cb", size = 92364, upload-time = "2025-07-30T10:01:44.887Z" }, + { url = "https://files.pythonhosted.org/packages/c9/c1/a606ff83b3f1735f3759ad0f2cd9e038a0ad11a3de3b6c673aa41c24bb7b/argon2_cffi_bindings-25.1.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:c4f9665de60b1b0e99bcd6be4f17d90339698ce954cfd8d9cf4f91c995165a92", size = 85637, upload-time = "2025-07-30T10:01:46.225Z" }, + { url = "https://files.pythonhosted.org/packages/44/b4/678503f12aceb0262f84fa201f6027ed77d71c5019ae03b399b97caa2f19/argon2_cffi_bindings-25.1.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:ba92837e4a9aa6a508c8d2d7883ed5a8f6c308c89a4790e1e447a220deb79a85", size = 91934, upload-time = "2025-07-30T10:01:47.203Z" }, + { url = "https://files.pythonhosted.org/packages/f0/c7/f36bd08ef9bd9f0a9cff9428406651f5937ce27b6c5b07b92d41f91ae541/argon2_cffi_bindings-25.1.0-cp314-cp314t-win32.whl", hash = "sha256:84a461d4d84ae1295871329b346a97f68eade8c53b6ed9a7ca2d7467f3c8ff6f", size = 28158, upload-time = "2025-07-30T10:01:48.341Z" }, + { url = "https://files.pythonhosted.org/packages/b3/80/0106a7448abb24a2c467bf7d527fe5413b7fdfa4ad6d6a96a43a62ef3988/argon2_cffi_bindings-25.1.0-cp314-cp314t-win_amd64.whl", hash = "sha256:b55aec3565b65f56455eebc9b9f34130440404f27fe21c3b375bf1ea4d8fbae6", size = 32597, upload-time = "2025-07-30T10:01:49.112Z" }, + { url = "https://files.pythonhosted.org/packages/05/b8/d663c9caea07e9180b2cb662772865230715cbd573ba3b5e81793d580316/argon2_cffi_bindings-25.1.0-cp314-cp314t-win_arm64.whl", hash = "sha256:87c33a52407e4c41f3b70a9c2d3f6056d88b10dad7695be708c5021673f55623", size = 28231, upload-time = "2025-07-30T10:01:49.92Z" }, + { url = "https://files.pythonhosted.org/packages/1d/57/96b8b9f93166147826da5f90376e784a10582dd39a393c99bb62cfcf52f0/argon2_cffi_bindings-25.1.0-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:aecba1723ae35330a008418a91ea6cfcedf6d31e5fbaa056a166462ff066d500", size = 54121, upload-time = "2025-07-30T10:01:50.815Z" }, + { url = "https://files.pythonhosted.org/packages/0a/08/a9bebdb2e0e602dde230bdde8021b29f71f7841bd54801bcfd514acb5dcf/argon2_cffi_bindings-25.1.0-cp39-abi3-macosx_10_9_x86_64.whl", hash = "sha256:2630b6240b495dfab90aebe159ff784d08ea999aa4b0d17efa734055a07d2f44", size = 29177, upload-time = "2025-07-30T10:01:51.681Z" }, + { url = "https://files.pythonhosted.org/packages/b6/02/d297943bcacf05e4f2a94ab6f462831dc20158614e5d067c35d4e63b9acb/argon2_cffi_bindings-25.1.0-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:7aef0c91e2c0fbca6fc68e7555aa60ef7008a739cbe045541e438373bc54d2b0", size = 31090, upload-time = "2025-07-30T10:01:53.184Z" }, + { url = "https://files.pythonhosted.org/packages/c1/93/44365f3d75053e53893ec6d733e4a5e3147502663554b4d864587c7828a7/argon2_cffi_bindings-25.1.0-cp39-abi3-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1e021e87faa76ae0d413b619fe2b65ab9a037f24c60a1e6cc43457ae20de6dc6", size = 81246, upload-time = "2025-07-30T10:01:54.145Z" }, + { url = "https://files.pythonhosted.org/packages/09/52/94108adfdd6e2ddf58be64f959a0b9c7d4ef2fa71086c38356d22dc501ea/argon2_cffi_bindings-25.1.0-cp39-abi3-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d3e924cfc503018a714f94a49a149fdc0b644eaead5d1f089330399134fa028a", size = 87126, upload-time = "2025-07-30T10:01:55.074Z" }, + { url = "https://files.pythonhosted.org/packages/72/70/7a2993a12b0ffa2a9271259b79cc616e2389ed1a4d93842fac5a1f923ffd/argon2_cffi_bindings-25.1.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:c87b72589133f0346a1cb8d5ecca4b933e3c9b64656c9d175270a000e73b288d", size = 80343, upload-time = "2025-07-30T10:01:56.007Z" }, + { url = "https://files.pythonhosted.org/packages/78/9a/4e5157d893ffc712b74dbd868c7f62365618266982b64accab26bab01edc/argon2_cffi_bindings-25.1.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:1db89609c06afa1a214a69a462ea741cf735b29a57530478c06eb81dd403de99", size = 86777, upload-time = "2025-07-30T10:01:56.943Z" }, + { url = "https://files.pythonhosted.org/packages/74/cd/15777dfde1c29d96de7f18edf4cc94c385646852e7c7b0320aa91ccca583/argon2_cffi_bindings-25.1.0-cp39-abi3-win32.whl", hash = "sha256:473bcb5f82924b1becbb637b63303ec8d10e84c8d241119419897a26116515d2", size = 27180, upload-time = "2025-07-30T10:01:57.759Z" }, + { url = "https://files.pythonhosted.org/packages/e2/c6/a759ece8f1829d1f162261226fbfd2c6832b3ff7657384045286d2afa384/argon2_cffi_bindings-25.1.0-cp39-abi3-win_amd64.whl", hash = "sha256:a98cd7d17e9f7ce244c0803cad3c23a7d379c301ba618a5fa76a67d116618b98", size = 31715, upload-time = "2025-07-30T10:01:58.56Z" }, + { url = "https://files.pythonhosted.org/packages/42/b9/f8d6fa329ab25128b7e98fd83a3cb34d9db5b059a9847eddb840a0af45dd/argon2_cffi_bindings-25.1.0-cp39-abi3-win_arm64.whl", hash = "sha256:b0fdbcf513833809c882823f98dc2f931cf659d9a1429616ac3adebb49f5db94", size = 27149, upload-time = "2025-07-30T10:01:59.329Z" }, +] + [[package]] name = "arrow" version = "1.3.0" @@ -1260,34 +1300,40 @@ wheels = [ [[package]] name = "mypy" -version = "1.17.0" +version = "1.17.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "mypy-extensions" }, { name = "pathspec" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/1e/e3/034322d5a779685218ed69286c32faa505247f1f096251ef66c8fd203b08/mypy-1.17.0.tar.gz", hash = "sha256:e5d7ccc08ba089c06e2f5629c660388ef1fee708444f1dee0b9203fa031dee03", size = 3352114, upload-time = "2025-07-14T20:34:30.181Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/d4/24/82efb502b0b0f661c49aa21cfe3e1999ddf64bf5500fc03b5a1536a39d39/mypy-1.17.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:9d4fe5c72fd262d9c2c91c1117d16aac555e05f5beb2bae6a755274c6eec42be", size = 10914150, upload-time = "2025-07-14T20:31:51.985Z" }, - { url = "https://files.pythonhosted.org/packages/03/96/8ef9a6ff8cedadff4400e2254689ca1dc4b420b92c55255b44573de10c54/mypy-1.17.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d96b196e5c16f41b4f7736840e8455958e832871990c7ba26bf58175e357ed61", size = 10039845, upload-time = "2025-07-14T20:32:30.527Z" }, - { url = "https://files.pythonhosted.org/packages/df/32/7ce359a56be779d38021d07941cfbb099b41411d72d827230a36203dbb81/mypy-1.17.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:73a0ff2dd10337ceb521c080d4147755ee302dcde6e1a913babd59473904615f", size = 11837246, upload-time = "2025-07-14T20:32:01.28Z" }, - { url = "https://files.pythonhosted.org/packages/82/16/b775047054de4d8dbd668df9137707e54b07fe18c7923839cd1e524bf756/mypy-1.17.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:24cfcc1179c4447854e9e406d3af0f77736d631ec87d31c6281ecd5025df625d", size = 12571106, upload-time = "2025-07-14T20:34:26.942Z" }, - { url = "https://files.pythonhosted.org/packages/a1/cf/fa33eaf29a606102c8d9ffa45a386a04c2203d9ad18bf4eef3e20c43ebc8/mypy-1.17.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:3c56f180ff6430e6373db7a1d569317675b0a451caf5fef6ce4ab365f5f2f6c3", size = 12759960, upload-time = "2025-07-14T20:33:42.882Z" }, - { url = "https://files.pythonhosted.org/packages/94/75/3f5a29209f27e739ca57e6350bc6b783a38c7621bdf9cac3ab8a08665801/mypy-1.17.0-cp311-cp311-win_amd64.whl", hash = "sha256:eafaf8b9252734400f9b77df98b4eee3d2eecab16104680d51341c75702cad70", size = 9503888, upload-time = "2025-07-14T20:32:34.392Z" }, - { url = "https://files.pythonhosted.org/packages/12/e9/e6824ed620bbf51d3bf4d6cbbe4953e83eaf31a448d1b3cfb3620ccb641c/mypy-1.17.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:f986f1cab8dbec39ba6e0eaa42d4d3ac6686516a5d3dccd64be095db05ebc6bb", size = 11086395, upload-time = "2025-07-14T20:34:11.452Z" }, - { url = "https://files.pythonhosted.org/packages/ba/51/a4afd1ae279707953be175d303f04a5a7bd7e28dc62463ad29c1c857927e/mypy-1.17.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:51e455a54d199dd6e931cd7ea987d061c2afbaf0960f7f66deef47c90d1b304d", size = 10120052, upload-time = "2025-07-14T20:33:09.897Z" }, - { url = "https://files.pythonhosted.org/packages/8a/71/19adfeac926ba8205f1d1466d0d360d07b46486bf64360c54cb5a2bd86a8/mypy-1.17.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3204d773bab5ff4ebbd1f8efa11b498027cd57017c003ae970f310e5b96be8d8", size = 11861806, upload-time = "2025-07-14T20:32:16.028Z" }, - { url = "https://files.pythonhosted.org/packages/0b/64/d6120eca3835baf7179e6797a0b61d6c47e0bc2324b1f6819d8428d5b9ba/mypy-1.17.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1051df7ec0886fa246a530ae917c473491e9a0ba6938cfd0ec2abc1076495c3e", size = 12744371, upload-time = "2025-07-14T20:33:33.503Z" }, - { url = "https://files.pythonhosted.org/packages/1f/dc/56f53b5255a166f5bd0f137eed960e5065f2744509dfe69474ff0ba772a5/mypy-1.17.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:f773c6d14dcc108a5b141b4456b0871df638eb411a89cd1c0c001fc4a9d08fc8", size = 12914558, upload-time = "2025-07-14T20:33:56.961Z" }, - { url = "https://files.pythonhosted.org/packages/69/ac/070bad311171badc9add2910e7f89271695a25c136de24bbafc7eded56d5/mypy-1.17.0-cp312-cp312-win_amd64.whl", hash = "sha256:1619a485fd0e9c959b943c7b519ed26b712de3002d7de43154a489a2d0fd817d", size = 9585447, upload-time = "2025-07-14T20:32:20.594Z" }, - { url = "https://files.pythonhosted.org/packages/be/7b/5f8ab461369b9e62157072156935cec9d272196556bdc7c2ff5f4c7c0f9b/mypy-1.17.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:2c41aa59211e49d717d92b3bb1238c06d387c9325d3122085113c79118bebb06", size = 11070019, upload-time = "2025-07-14T20:32:07.99Z" }, - { url = "https://files.pythonhosted.org/packages/9c/f8/c49c9e5a2ac0badcc54beb24e774d2499748302c9568f7f09e8730e953fa/mypy-1.17.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0e69db1fb65b3114f98c753e3930a00514f5b68794ba80590eb02090d54a5d4a", size = 10114457, upload-time = "2025-07-14T20:33:47.285Z" }, - { url = "https://files.pythonhosted.org/packages/89/0c/fb3f9c939ad9beed3e328008b3fb90b20fda2cddc0f7e4c20dbefefc3b33/mypy-1.17.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:03ba330b76710f83d6ac500053f7727270b6b8553b0423348ffb3af6f2f7b889", size = 11857838, upload-time = "2025-07-14T20:33:14.462Z" }, - { url = "https://files.pythonhosted.org/packages/4c/66/85607ab5137d65e4f54d9797b77d5a038ef34f714929cf8ad30b03f628df/mypy-1.17.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:037bc0f0b124ce46bfde955c647f3e395c6174476a968c0f22c95a8d2f589bba", size = 12731358, upload-time = "2025-07-14T20:32:25.579Z" }, - { url = "https://files.pythonhosted.org/packages/73/d0/341dbbfb35ce53d01f8f2969facbb66486cee9804048bf6c01b048127501/mypy-1.17.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:c38876106cb6132259683632b287238858bd58de267d80defb6f418e9ee50658", size = 12917480, upload-time = "2025-07-14T20:34:21.868Z" }, - { url = "https://files.pythonhosted.org/packages/64/63/70c8b7dbfc520089ac48d01367a97e8acd734f65bd07813081f508a8c94c/mypy-1.17.0-cp313-cp313-win_amd64.whl", hash = "sha256:d30ba01c0f151998f367506fab31c2ac4527e6a7b2690107c7a7f9e3cb419a9c", size = 9589666, upload-time = "2025-07-14T20:34:16.841Z" }, - { url = "https://files.pythonhosted.org/packages/e3/fc/ee058cc4316f219078464555873e99d170bde1d9569abd833300dbeb484a/mypy-1.17.0-py3-none-any.whl", hash = "sha256:15d9d0018237ab058e5de3d8fce61b6fa72cc59cc78fd91f1b474bce12abf496", size = 2283195, upload-time = "2025-07-14T20:31:54.753Z" }, +sdist = { url = "https://files.pythonhosted.org/packages/8e/22/ea637422dedf0bf36f3ef238eab4e455e2a0dcc3082b5cc067615347ab8e/mypy-1.17.1.tar.gz", hash = "sha256:25e01ec741ab5bb3eec8ba9cdb0f769230368a22c959c4937360efb89b7e9f01", size = 3352570, upload-time = "2025-07-31T07:54:19.204Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/46/cf/eadc80c4e0a70db1c08921dcc220357ba8ab2faecb4392e3cebeb10edbfa/mypy-1.17.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ad37544be07c5d7fba814eb370e006df58fed8ad1ef33ed1649cb1889ba6ff58", size = 10921009, upload-time = "2025-07-31T07:53:23.037Z" }, + { url = "https://files.pythonhosted.org/packages/5d/c1/c869d8c067829ad30d9bdae051046561552516cfb3a14f7f0347b7d973ee/mypy-1.17.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:064e2ff508e5464b4bd807a7c1625bc5047c5022b85c70f030680e18f37273a5", size = 10047482, upload-time = "2025-07-31T07:53:26.151Z" }, + { url = "https://files.pythonhosted.org/packages/98/b9/803672bab3fe03cee2e14786ca056efda4bb511ea02dadcedde6176d06d0/mypy-1.17.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:70401bbabd2fa1aa7c43bb358f54037baf0586f41e83b0ae67dd0534fc64edfd", size = 11832883, upload-time = "2025-07-31T07:53:47.948Z" }, + { url = "https://files.pythonhosted.org/packages/88/fb/fcdac695beca66800918c18697b48833a9a6701de288452b6715a98cfee1/mypy-1.17.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e92bdc656b7757c438660f775f872a669b8ff374edc4d18277d86b63edba6b8b", size = 12566215, upload-time = "2025-07-31T07:54:04.031Z" }, + { url = "https://files.pythonhosted.org/packages/7f/37/a932da3d3dace99ee8eb2043b6ab03b6768c36eb29a02f98f46c18c0da0e/mypy-1.17.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:c1fdf4abb29ed1cb091cf432979e162c208a5ac676ce35010373ff29247bcad5", size = 12751956, upload-time = "2025-07-31T07:53:36.263Z" }, + { url = "https://files.pythonhosted.org/packages/8c/cf/6438a429e0f2f5cab8bc83e53dbebfa666476f40ee322e13cac5e64b79e7/mypy-1.17.1-cp311-cp311-win_amd64.whl", hash = "sha256:ff2933428516ab63f961644bc49bc4cbe42bbffb2cd3b71cc7277c07d16b1a8b", size = 9507307, upload-time = "2025-07-31T07:53:59.734Z" }, + { url = "https://files.pythonhosted.org/packages/17/a2/7034d0d61af8098ec47902108553122baa0f438df8a713be860f7407c9e6/mypy-1.17.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:69e83ea6553a3ba79c08c6e15dbd9bfa912ec1e493bf75489ef93beb65209aeb", size = 11086295, upload-time = "2025-07-31T07:53:28.124Z" }, + { url = "https://files.pythonhosted.org/packages/14/1f/19e7e44b594d4b12f6ba8064dbe136505cec813549ca3e5191e40b1d3cc2/mypy-1.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1b16708a66d38abb1e6b5702f5c2c87e133289da36f6a1d15f6a5221085c6403", size = 10112355, upload-time = "2025-07-31T07:53:21.121Z" }, + { url = "https://files.pythonhosted.org/packages/5b/69/baa33927e29e6b4c55d798a9d44db5d394072eef2bdc18c3e2048c9ed1e9/mypy-1.17.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:89e972c0035e9e05823907ad5398c5a73b9f47a002b22359b177d40bdaee7056", size = 11875285, upload-time = "2025-07-31T07:53:55.293Z" }, + { url = "https://files.pythonhosted.org/packages/90/13/f3a89c76b0a41e19490b01e7069713a30949d9a6c147289ee1521bcea245/mypy-1.17.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:03b6d0ed2b188e35ee6d5c36b5580cffd6da23319991c49ab5556c023ccf1341", size = 12737895, upload-time = "2025-07-31T07:53:43.623Z" }, + { url = "https://files.pythonhosted.org/packages/23/a1/c4ee79ac484241301564072e6476c5a5be2590bc2e7bfd28220033d2ef8f/mypy-1.17.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c837b896b37cd103570d776bda106eabb8737aa6dd4f248451aecf53030cdbeb", size = 12931025, upload-time = "2025-07-31T07:54:17.125Z" }, + { url = "https://files.pythonhosted.org/packages/89/b8/7409477be7919a0608900e6320b155c72caab4fef46427c5cc75f85edadd/mypy-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:665afab0963a4b39dff7c1fa563cc8b11ecff7910206db4b2e64dd1ba25aed19", size = 9584664, upload-time = "2025-07-31T07:54:12.842Z" }, + { url = "https://files.pythonhosted.org/packages/5b/82/aec2fc9b9b149f372850291827537a508d6c4d3664b1750a324b91f71355/mypy-1.17.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:93378d3203a5c0800c6b6d850ad2f19f7a3cdf1a3701d3416dbf128805c6a6a7", size = 11075338, upload-time = "2025-07-31T07:53:38.873Z" }, + { url = "https://files.pythonhosted.org/packages/07/ac/ee93fbde9d2242657128af8c86f5d917cd2887584cf948a8e3663d0cd737/mypy-1.17.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:15d54056f7fe7a826d897789f53dd6377ec2ea8ba6f776dc83c2902b899fee81", size = 10113066, upload-time = "2025-07-31T07:54:14.707Z" }, + { url = "https://files.pythonhosted.org/packages/5a/68/946a1e0be93f17f7caa56c45844ec691ca153ee8b62f21eddda336a2d203/mypy-1.17.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:209a58fed9987eccc20f2ca94afe7257a8f46eb5df1fb69958650973230f91e6", size = 11875473, upload-time = "2025-07-31T07:53:14.504Z" }, + { url = "https://files.pythonhosted.org/packages/9f/0f/478b4dce1cb4f43cf0f0d00fba3030b21ca04a01b74d1cd272a528cf446f/mypy-1.17.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:099b9a5da47de9e2cb5165e581f158e854d9e19d2e96b6698c0d64de911dd849", size = 12744296, upload-time = "2025-07-31T07:53:03.896Z" }, + { url = "https://files.pythonhosted.org/packages/ca/70/afa5850176379d1b303f992a828de95fc14487429a7139a4e0bdd17a8279/mypy-1.17.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:fa6ffadfbe6994d724c5a1bb6123a7d27dd68fc9c059561cd33b664a79578e14", size = 12914657, upload-time = "2025-07-31T07:54:08.576Z" }, + { url = "https://files.pythonhosted.org/packages/53/f9/4a83e1c856a3d9c8f6edaa4749a4864ee98486e9b9dbfbc93842891029c2/mypy-1.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:9a2b7d9180aed171f033c9f2fc6c204c1245cf60b0cb61cf2e7acc24eea78e0a", size = 9593320, upload-time = "2025-07-31T07:53:01.341Z" }, + { url = "https://files.pythonhosted.org/packages/38/56/79c2fac86da57c7d8c48622a05873eaab40b905096c33597462713f5af90/mypy-1.17.1-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:15a83369400454c41ed3a118e0cc58bd8123921a602f385cb6d6ea5df050c733", size = 11040037, upload-time = "2025-07-31T07:54:10.942Z" }, + { url = "https://files.pythonhosted.org/packages/4d/c3/adabe6ff53638e3cad19e3547268482408323b1e68bf082c9119000cd049/mypy-1.17.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:55b918670f692fc9fba55c3298d8a3beae295c5cded0a55dccdc5bbead814acd", size = 10131550, upload-time = "2025-07-31T07:53:41.307Z" }, + { url = "https://files.pythonhosted.org/packages/b8/c5/2e234c22c3bdeb23a7817af57a58865a39753bde52c74e2c661ee0cfc640/mypy-1.17.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:62761474061feef6f720149d7ba876122007ddc64adff5ba6f374fda35a018a0", size = 11872963, upload-time = "2025-07-31T07:53:16.878Z" }, + { url = "https://files.pythonhosted.org/packages/ab/26/c13c130f35ca8caa5f2ceab68a247775648fdcd6c9a18f158825f2bc2410/mypy-1.17.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c49562d3d908fd49ed0938e5423daed8d407774a479b595b143a3d7f87cdae6a", size = 12710189, upload-time = "2025-07-31T07:54:01.962Z" }, + { url = "https://files.pythonhosted.org/packages/82/df/c7d79d09f6de8383fe800521d066d877e54d30b4fb94281c262be2df84ef/mypy-1.17.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:397fba5d7616a5bc60b45c7ed204717eaddc38f826e3645402c426057ead9a91", size = 12900322, upload-time = "2025-07-31T07:53:10.551Z" }, + { url = "https://files.pythonhosted.org/packages/b8/98/3d5a48978b4f708c55ae832619addc66d677f6dc59f3ebad71bae8285ca6/mypy-1.17.1-cp314-cp314-win_amd64.whl", hash = "sha256:9d6b20b97d373f41617bd0708fd46aa656059af57f2ef72aa8c7d6a2b73b74ed", size = 9751879, upload-time = "2025-07-31T07:52:56.683Z" }, + { url = "https://files.pythonhosted.org/packages/1d/f3/8fcd2af0f5b806f6cf463efaffd3c9548a28f84220493ecd38d127b6b66d/mypy-1.17.1-py3-none-any.whl", hash = "sha256:a9f52c0351c21fe24c21d8c0eb1f62967b262d6729393397b6f443c3b773c3b9", size = 2283411, upload-time = "2025-07-31T07:53:24.664Z" }, ] [[package]] @@ -1990,14 +2036,14 @@ wheels = [ [[package]] name = "pytest-datadir" -version = "1.7.2" +version = "1.8.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pytest" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/2f/16/7701db071caf7d8f7226b76323de40a09d2a391c7d064cda072d45a87c7b/pytest_datadir-1.7.2.tar.gz", hash = "sha256:15f5228a35d0a3205e4968e75d3b9cca91762424e1eafc21eb637d380a48443e", size = 11265, upload-time = "2025-06-06T11:24:18.075Z" } +sdist = { url = "https://files.pythonhosted.org/packages/b4/46/db060b291999ca048edd06d6fa9ee95945d088edc38b1172c59eeb46ec45/pytest_datadir-1.8.0.tar.gz", hash = "sha256:7a15faed76cebe87cc91941dd1920a9a38eba56a09c11e9ddf1434d28a0f78eb", size = 11848, upload-time = "2025-07-30T13:52:12.518Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/d3/61/a06f3406852534e186413c75f544c90251db00fd8eb9625ee3ac239499f3/pytest_datadir-1.7.2-py3-none-any.whl", hash = "sha256:8392ba0e9eaf37030e663dcd91cc5123dec99c44300f0c5eac44f35f13f0e086", size = 6273, upload-time = "2025-06-06T11:24:16.388Z" }, + { url = "https://files.pythonhosted.org/packages/8f/7a/33895863aec26ac3bb5068a73583f935680d6ab6af2a9567d409430c3ee1/pytest_datadir-1.8.0-py3-none-any.whl", hash = "sha256:5c677bc097d907ac71ca418109adc3abe34cf0bddfe6cf78aecfbabd96a15cf0", size = 6512, upload-time = "2025-07-30T13:52:11.525Z" }, ] [[package]] @@ -2951,28 +2997,28 @@ wheels = [ [[package]] name = "uv" -version = "0.8.3" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/eb/e3/2c3cb3e992fa1bf9af590bb37983f13e3ae67155820a09a98945664f71f3/uv-0.8.3.tar.gz", hash = "sha256:2ccaae4c749126c99f6404d67a0ae1eae29cbafb05603d09094a775061fdf4e5", size = 3415565, upload-time = "2025-07-24T21:14:34.417Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/c1/ab/7b881bb236b9c5f6d99a98adf0c4d1e7c4f0cf4b49051d6d24eb82f19c10/uv-0.8.3-py3-none-linux_armv6l.whl", hash = "sha256:ae7efe91dcfc24126fa91e0fb69a1daf6c0e494a781ba192bb0cc62d7ab623ee", size = 17912668, upload-time = "2025-07-24T21:13:50.682Z" }, - { url = "https://files.pythonhosted.org/packages/fa/9b/64d2ed7388ce88971ffb93d45e74465c95bb885bff40c93f5037b7250930/uv-0.8.3-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:966ec7d7f57521fef0fee685d71e183c9cafb358ddcfe27519dfeaf40550f247", size = 17947557, upload-time = "2025-07-24T21:13:54.59Z" }, - { url = "https://files.pythonhosted.org/packages/9c/ba/8ceec5d6a1adf6b827db557077d8059e573a84c3708a70433d22a0470fab/uv-0.8.3-py3-none-macosx_11_0_arm64.whl", hash = "sha256:3f904f574dc2d7aa1d96ddf2483480ecd121dc9d060108cadd8bff100b754b64", size = 16638472, upload-time = "2025-07-24T21:13:57.57Z" }, - { url = "https://files.pythonhosted.org/packages/a3/76/6d2eb90936603756c4a71f9cf5de8d9214fa4d11dcb5a89117389acecd5e/uv-0.8.3-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:8b16f1bddfdf8f7470924ab34a7b55e4c372d5340c7c1e47e7fc84a743dc541f", size = 17221472, upload-time = "2025-07-24T21:14:00.158Z" }, - { url = "https://files.pythonhosted.org/packages/5b/bf/c3e1cc9604b114dfb49a3a40a230b5410fc97776c149ca73bb524990f9ba/uv-0.8.3-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:526f2c3bd6f311ce31f6f7b6b7d818b191f41e76bed3aaab671b716220c02d8f", size = 17607299, upload-time = "2025-07-24T21:14:02.226Z" }, - { url = "https://files.pythonhosted.org/packages/53/16/819f876f5ca2f8989c19d9b65b7d794d60e6cca0d13187bbc8c8b5532b52/uv-0.8.3-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:76de331a07e5ae9b6490e70a9439a072b91b3167a5684510af10c2752c4ece9a", size = 18218124, upload-time = "2025-07-24T21:14:04.809Z" }, - { url = "https://files.pythonhosted.org/packages/61/a8/1df852a9153fec0c713358a50cfd7a21a4e17b5ed5704a390c0f3da448ab/uv-0.8.3-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:989898caeb6e972979543b57547d1c28ab8af81ff8fc15921fd354c17d432749", size = 19638846, upload-time = "2025-07-24T21:14:07.074Z" }, - { url = "https://files.pythonhosted.org/packages/ac/31/adeedaa009d8d919107c52afb58689d5e9db578b07f8dea5e15e4c738d52/uv-0.8.3-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9ce7981f4fbeecf93dc5cf0a5a7915e84956fd99ad3ac977c048fe0cfdb1a17e", size = 19384261, upload-time = "2025-07-24T21:14:09.425Z" }, - { url = "https://files.pythonhosted.org/packages/8d/87/b3981f499e2b13c5ef0022fd7809f0fccbecd41282ae4f6a0e3fd5fa1430/uv-0.8.3-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8486f7576d15cc73509f93f47b3190f44701ea36839906369301b58c8604d5db", size = 18673722, upload-time = "2025-07-24T21:14:11.656Z" }, - { url = "https://files.pythonhosted.org/packages/5e/62/0d1ba1c666c5492d3716d8d3fba425f65ed2acc6707544c3cbbd381f6cbe/uv-0.8.3-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f1eb7c896fc0d80ed534748aaf46697b6ebc8ce401f1c51666ce0b9923c3db9a", size = 18658829, upload-time = "2025-07-24T21:14:13.798Z" }, - { url = "https://files.pythonhosted.org/packages/cc/ae/11d09be3c74ca4896d55701ebbca7fe7a32db0502cf9f4c57e20bf77bfc4/uv-0.8.3-py3-none-manylinux_2_28_aarch64.whl", hash = "sha256:1121ad1c9389b865d029385031d3fd7d90d343c92a2149a4d4aa20bf469cb27f", size = 17460029, upload-time = "2025-07-24T21:14:15.993Z" }, - { url = "https://files.pythonhosted.org/packages/22/47/b67296c62381b8369f082a33d9fdcb7c579ad9922bcce7b09cd4af935dfa/uv-0.8.3-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:5313ee776ad65731ffa8ac585246f987d3a2bf72e6153c12add1fff22ad6e500", size = 18398665, upload-time = "2025-07-24T21:14:18.399Z" }, - { url = "https://files.pythonhosted.org/packages/01/5f/23990de5487085ca86e12f99d0a8f8410419442ffd35c42838675df5549b/uv-0.8.3-py3-none-musllinux_1_1_armv7l.whl", hash = "sha256:daa6e0d657a94f20e962d4a03d833ef7af5c8e51b7c8a2d92ba6cf64a4c07ac1", size = 17560408, upload-time = "2025-07-24T21:14:20.609Z" }, - { url = "https://files.pythonhosted.org/packages/89/42/1a8ce79d2ce7268e52690cd0f1b6c3e6c8d748a68d42de206e37219e9627/uv-0.8.3-py3-none-musllinux_1_1_i686.whl", hash = "sha256:ad13453ab0a1dfa64a221aac8f52199efdcaa52c97134fffd7bcebed794a6f4b", size = 17758504, upload-time = "2025-07-24T21:14:23.086Z" }, - { url = "https://files.pythonhosted.org/packages/6b/39/ae94e06ac00cb5002e636af0e48c5180fab5b50a463dc96386875ea511ea/uv-0.8.3-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:5843cc43bafad05cc710d8e31bd347ee37202462a63d32c30746e9df48cfbda2", size = 18741736, upload-time = "2025-07-24T21:14:25.329Z" }, - { url = "https://files.pythonhosted.org/packages/18/e0/a2fe9cc5f7b8815cbf97cb1bf64abb71fcb65f25ca7a5a8cdd4c2e23af97/uv-0.8.3-py3-none-win32.whl", hash = "sha256:17bcdb0615e37cc5f985f7d7546f755ac6343c1dc8bbe876c892437f14f8f904", size = 17723422, upload-time = "2025-07-24T21:14:28.02Z" }, - { url = "https://files.pythonhosted.org/packages/cf/c3/da508ec0f6883f1c269a0a477bb6447c81d5383fe3ad5d5ea3d45469fd30/uv-0.8.3-py3-none-win_amd64.whl", hash = "sha256:2e311c029bff2ca07c6ddf877ccc5935cabb78e09b94b53a849542665b6a6fa1", size = 19531666, upload-time = "2025-07-24T21:14:30.192Z" }, - { url = "https://files.pythonhosted.org/packages/b2/8d/c0354e416697b4baa7ceaad0e423639b6683d1f8299355e390a64809f7bf/uv-0.8.3-py3-none-win_arm64.whl", hash = "sha256:391c97577048a40fd8c85b370055df6420f26e81df7fa906f0e0ce1aa2af3527", size = 18161557, upload-time = "2025-07-24T21:14:32.482Z" }, +version = "0.8.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/71/05/779581d8e5cd8d12dc3e2297280a03293f7b465bb5f53308479e508c5c44/uv-0.8.4.tar.gz", hash = "sha256:2ab21c32a28dbe434c9074f899ed8084955f7b09ac5e7ffac548d3454f77516f", size = 3442716, upload-time = "2025-07-30T17:10:56.404Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/96/10/4d52b081defca3cfb4a11d6af3af4314fe7f289ba19e40d6cfab778f9257/uv-0.8.4-py3-none-linux_armv6l.whl", hash = "sha256:f9a5da616ca0d2bbe79367db9cf339cbaf1affee5d6b130a3be2779a917c14fa", size = 18077025, upload-time = "2025-07-30T17:10:13.016Z" }, + { url = "https://files.pythonhosted.org/packages/36/fa/7847373d214de987e96ef6b820a4ed2fa5e1c392ecc73cd53e94013d6074/uv-0.8.4-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:4d8422b3058998d87fee46d4d1a437e202407cafca8b8ac69e01c6479fbe0271", size = 18143542, upload-time = "2025-07-30T17:10:18.006Z" }, + { url = "https://files.pythonhosted.org/packages/16/39/7d4b68132868c550ae97c3b2c348c55db47a987dff05ab0e5f577bf0e197/uv-0.8.4-py3-none-macosx_11_0_arm64.whl", hash = "sha256:edc813645348665a3b4716a7d5e961cf7c8d1d3bfb9d907a4f18cf87c712a430", size = 16860749, upload-time = "2025-07-30T17:10:20.417Z" }, + { url = "https://files.pythonhosted.org/packages/e3/8f/f703e4ba41aae195d4958b701c2ee6cdbbbb8cdccb082845d6abfe834cf9/uv-0.8.4-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:c2323e915ae562db4ebcdf5e20d3dd37a14959d07cc54939d86ab0dcdbf08f58", size = 17469507, upload-time = "2025-07-30T17:10:22.779Z" }, + { url = "https://files.pythonhosted.org/packages/59/f8/9366ceeb63f9dd6aa11375047762c1033d36521722e748b65a24e435f459/uv-0.8.4-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:96d7a68c360383d638c283811d57558fbf7b5f769ff4bdbc99ee2a3bf9a6e574", size = 17766700, upload-time = "2025-07-30T17:10:24.903Z" }, + { url = "https://files.pythonhosted.org/packages/f2/e3/190eb0ca91b8a0e5f80f93aeb7924b12be89656066170d6e1244e90c5e80/uv-0.8.4-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:385dec5a0c0909d5a24af5b02db24b49b025cbed59c6225e4c794ff40069d9aa", size = 18432996, upload-time = "2025-07-30T17:10:27.239Z" }, + { url = "https://files.pythonhosted.org/packages/ab/f6/b5fc5fe6e93e0294cbd8ba228d10b12e46a5e27b143565e868da758e0209/uv-0.8.4-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:b2230310ca303328c9fd351044fb81349f3ccfaa2863f135d37bfcee707adfd1", size = 19842168, upload-time = "2025-07-30T17:10:29.958Z" }, + { url = "https://files.pythonhosted.org/packages/f5/f0/d01779df4ac2ae39bf440c97f53346f1b9eef17cc84a45ed66206e348650/uv-0.8.4-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:86d64c66993eb0d9821caea27920175a27cd24df1eba8a340d8b3ae4074fac77", size = 19497445, upload-time = "2025-07-30T17:10:32.064Z" }, + { url = "https://files.pythonhosted.org/packages/80/ca/48c78393cb3a73940e768b74f74c30ca7719de6f83457a125b9cfa0c37e0/uv-0.8.4-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:624cf5b7bdc5cc0253115fefaad40008205d4acf34b77b294479dfe4eacb9697", size = 18852025, upload-time = "2025-07-30T17:10:34.34Z" }, + { url = "https://files.pythonhosted.org/packages/42/e2/5cf11c85fb48276b49979ea06e92c1e95524e1e4c5bccbd591a334c8de68/uv-0.8.4-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f9cd287982f62419f98ca7182fbbc2fd0fad1a04008b956a88eb85ce1d522611", size = 18806944, upload-time = "2025-07-30T17:10:36.819Z" }, + { url = "https://files.pythonhosted.org/packages/1c/b1/773dcd5ef4947a5bd7c183f1cc8afb9e761488ff1b48b46cb0d95bc5c8cf/uv-0.8.4-py3-none-manylinux_2_28_aarch64.whl", hash = "sha256:e6fa3754a2b965dceecfce8c38cacf7cd6b76a2787b9e189cf33acdb64a7472a", size = 17706599, upload-time = "2025-07-30T17:10:38.976Z" }, + { url = "https://files.pythonhosted.org/packages/e6/8f/20dcb6aaa9c9d7e16320b5143b1fdaa5fd1ebc42a99e2d5f4283aafc59f1/uv-0.8.4-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:9f2a7042553e85c66884a6a3c1b88e116bc5fe5e5d1c9b62f025b1de41534734", size = 18564686, upload-time = "2025-07-30T17:10:41.163Z" }, + { url = "https://files.pythonhosted.org/packages/8a/19/9f9df99259d6725fc269d5394606919f32c3e0d21f486277c040cb7c5dad/uv-0.8.4-py3-none-musllinux_1_1_armv7l.whl", hash = "sha256:2c80470d7253bd26c5990f4914cfddc68a6bb4da7c7da316a29e99feafe272a1", size = 17722213, upload-time = "2025-07-30T17:10:43.354Z" }, + { url = "https://files.pythonhosted.org/packages/00/f4/358576eea98eb4ba58135690a60f8052dbd8b50173a5c0e93e59c8797c2c/uv-0.8.4-py3-none-musllinux_1_1_i686.whl", hash = "sha256:b90eb86019ff92922dea54b8772074909ce7ab3359b2e8f8f3fe4d0658d3a898", size = 17997363, upload-time = "2025-07-30T17:10:45.631Z" }, + { url = "https://files.pythonhosted.org/packages/51/0f/9e5ff7d73846d8c924a5ef262dee247b453b7b2bd2ba5db1a819c72bd176/uv-0.8.4-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:cad63a02a735ba591679d713376767fc7649ad1e7097a95d0d267a68c2e803fc", size = 18954586, upload-time = "2025-07-30T17:10:47.789Z" }, + { url = "https://files.pythonhosted.org/packages/3c/fa/58c416c634253bdd7ec50baa5d79010f887453425a62e6a23f9668a75305/uv-0.8.4-py3-none-win32.whl", hash = "sha256:b83cd9eeb4c63ab69c6e8d0e26e57b5a9a8b1dca4015f4ddf088ed4a234e7018", size = 17907610, upload-time = "2025-07-30T17:10:49.966Z" }, + { url = "https://files.pythonhosted.org/packages/76/8e/2d6f5bce0f41074122caed1672f90f7ed5df2bd9827c8723c73a657bea7b/uv-0.8.4-py3-none-win_amd64.whl", hash = "sha256:ad056c8f6568d9f495e402753e79a092f28d513e6b5146d1c8dc2bdea668adb1", size = 19704945, upload-time = "2025-07-30T17:10:52.145Z" }, + { url = "https://files.pythonhosted.org/packages/58/de/196e862af4c3b2ff8cb4a7a3ad38ecf0306fa87d03ec9275f16e2f5dc416/uv-0.8.4-py3-none-win_arm64.whl", hash = "sha256:41f3a22550811bf7a0980b3d4dfce09e2c93aec7c42c92313ae3d3d0b97e1054", size = 18316402, upload-time = "2025-07-30T17:10:54.507Z" }, ] [[package]] @@ -2991,7 +3037,7 @@ wheels = [ [[package]] name = "voila" -version = "0.5.8" +version = "0.5.9" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "jupyter-client" }, @@ -3003,9 +3049,9 @@ dependencies = [ { name = "traitlets" }, { name = "websockets" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/de/9e/e9c14c97507d1724779cbd7bf282c11c0be8b05e6e83f9f54607a2ebd8ed/voila-0.5.8.tar.gz", hash = "sha256:3d9078c252a8b1f3fe58d465749d31cdc241b29c8f4ab77f123be35a17e2da95", size = 5344487, upload-time = "2024-10-18T10:08:59.431Z" } +sdist = { url = "https://files.pythonhosted.org/packages/87/0a/fbf69c8ecb129c3204b6c103f831b5f2d2dbdd763e8d7dcdbcf30749f155/voila-0.5.9.tar.gz", hash = "sha256:a98ab3e72ca221ae1bd32eaf44c333c337f74f2864ea5efe60d4589103294610", size = 5344681, upload-time = "2025-07-30T09:55:45.176Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/7a/fc/ebc74e04619f84200df9ab029be6aeeab6ae3b82ec3e97c177d83839383d/voila-0.5.8-py3-none-any.whl", hash = "sha256:7cdb1f0629a2e9c11f0c07e7d386f3b7cc5441f584dc9b8030d08a82e5c09063", size = 4511252, upload-time = "2024-10-18T10:08:56.464Z" }, + { url = "https://files.pythonhosted.org/packages/37/ac/40932d771f93da83735a8e0a9d5234835fedda14457e8251ac5b4d192137/voila-0.5.9-py3-none-any.whl", hash = "sha256:a2bc6954014c2321912ea402716b0305f79a35fbf08540a0921b61632b7a9a89", size = 4511082, upload-time = "2025-07-30T09:55:42.845Z" }, ] [[package]] From ea9ebd20f864902df143e3eeb332f98e12ed7e1b Mon Sep 17 00:00:00 2001 From: Nick Murphy Date: Thu, 31 Jul 2025 11:43:09 -0400 Subject: [PATCH 417/521] Extract plasma formulary calculator into a standalone package (#3060) * Remove plasma formulary calculator * Edit changelog: 3060.breaking.rst * Make plasma calculator main() raise error * nox -s requirements * Move ipykernel to docs dependency set * Add comment to pyproject.toml * Update comment and remove other calculator lines * pre-commit * Add NoReturn type hint * Exclude from code coverage * Ignore coverage * Add ipywidgets to docs dependency set * nox -s requirements * Update changelog entry * Update changelog entry * Update exception message when running plasmapy-calculator * nox -s requirements * Use |plasmapy-calculator| substitution * Updated & removed information on the plasma calculator --- changelog/3060.breaking.rst | 2 + docs/_global_substitutions.py | 2 +- docs/changelog/0.8.1.rst | 2 +- docs/plasma_calculator/index.rst | 29 +- pyproject.toml | 12 +- src/plasmapy/utils/calculator/__init__.py | 65 +- src/plasmapy/utils/calculator/favicon.ico | Bin 90022 -> 0 bytes .../utils/calculator/main_interface.py | 180 ----- .../utils/calculator/plasma_calculator.ipynb | 70 -- .../utils/calculator/properties_metadata.json | 77 -- .../utils/calculator/widget_helpers.py | 684 ------------------ uv.lock | 454 +----------- 12 files changed, 30 insertions(+), 1547 deletions(-) create mode 100644 changelog/3060.breaking.rst delete mode 100644 src/plasmapy/utils/calculator/favicon.ico delete mode 100644 src/plasmapy/utils/calculator/main_interface.py delete mode 100644 src/plasmapy/utils/calculator/plasma_calculator.ipynb delete mode 100644 src/plasmapy/utils/calculator/properties_metadata.json delete mode 100644 src/plasmapy/utils/calculator/widget_helpers.py diff --git a/changelog/3060.breaking.rst b/changelog/3060.breaking.rst new file mode 100644 index 0000000000..f916a9523c --- /dev/null +++ b/changelog/3060.breaking.rst @@ -0,0 +1,2 @@ +Removed the prototype plasma calculator from PlasmaPy so that it can be +included in the |plasmapy-calculator| standalone package. diff --git a/docs/_global_substitutions.py b/docs/_global_substitutions.py index 48a8d813ec..aa29ca85b1 100644 --- a/docs/_global_substitutions.py +++ b/docs/_global_substitutions.py @@ -98,7 +98,6 @@ "parameters": r":term:`parameters `\ ", "particle-like": r":term:`particle-like`\ ", "particle-list-like": r":term:`particle-list-like`\ ", - "plasma-calculator": r":ref:`plasmapy-calculator`\ ", "src/plasmapy": r":file:`src/plasmapy`\ ", "testing guide": r":ref:`testing guide`\ ", "tests": r":file:`tests`\ ", @@ -144,6 +143,7 @@ "pandas": "https://pandas.pydata.org", "pip": "https://pip.pypa.io", "Plasma Hack Week": "https://hack.plasmapy.org", + "plasmapy-calculator": "https://github.com/PlasmaPy/plasmapy-calculator", "PlasmaPy": "https://www.plasmapy.org", "PlasmaPy's data repository": "https://github.com/PlasmaPy/PlasmaPy-data", "PlasmaPy's documentation": "https://docs.plasmapy.org/en/stable", diff --git a/docs/changelog/0.8.1.rst b/docs/changelog/0.8.1.rst index 36ac4f062d..1fb715959e 100644 --- a/docs/changelog/0.8.1.rst +++ b/docs/changelog/0.8.1.rst @@ -399,7 +399,7 @@ Improved Documentation - Added an example notebook that introduces how to use `plasmapy.particles`. (`#1382 `__) -- Described the |plasma-calculator| in the narrative +- Described the prototype plasma-calculator in the narrative documentation. (`#1390 `__) - Updated the cold magnetized plasma dielectric permittivity tensor diff --git a/docs/plasma_calculator/index.rst b/docs/plasma_calculator/index.rst index 21c22010d1..b2a2893f3a 100644 --- a/docs/plasma_calculator/index.rst +++ b/docs/plasma_calculator/index.rst @@ -6,29 +6,8 @@ Plasma Calculator .. currentmodule:: plasmapy.utils.calculator -.. attention:: +.. important:: - |expect-api-changes| - -Overview --------- - -The Plasma Calculator is an interactive Jupyter notebook that is -packaged with `plasmapy`, and allows users to input a set of plasma -properties and immediately calculate multiple plasma parameters. - -.. note:: - - This functionality is still under development and the API may change - in future releases. - -Using Plasma Calculator ------------------------ - -To invoke the app use ``plasma-calculator`` in the command line. By -default this opens the app in a browser, bootstrapping the notebook in a -light theme and using port 8866 by default. - -``plasma-calculator`` takes optional arguments such as ``--dark``, -``--port``, and ``--no-browser``. Pass flag ``-h`` or ``--help`` to get -full list of supported arguments. + The prototype plasma calculator has been removed from PlasmaPy and + extracted into its own package. See |plasmapy-calculator| for + up-to-date usage information. diff --git a/pyproject.toml b/pyproject.toml index 59d6ac69ee..1a8ee65239 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -59,9 +59,6 @@ dependencies = [ # astropy upper limit described in https://github.com/PlasmaPy/PlasmaPy/issues/2883 "astropy>=5.2,<7", "h5py>=3.8", - # Minimum version of ipykernel should not exceed what's used by Google Colab - "ipykernel>=5.5.6", - "ipywidgets>=6", "lmfit>=1.1", "matplotlib>=3.7", "mpmath>=1.3", @@ -73,8 +70,6 @@ dependencies = [ "scipy>=1.10", "setuptools>=66", "tqdm>=4.65", - # Use loose requirements for voila because it impacts ipykernel version - "voila>=0.2.7", "wrapt>=1.15", # xarray upper limit described in: https://github.com/PlasmaPy/PlasmaPy/issues/2922 "xarray>=2022.12,<=2024.10", @@ -84,6 +79,8 @@ dependencies = [ # user-facing, so we can have stricter requirements. optional-dependencies.docs = [ "docutils>=0.20.1", + "ipykernel>=6.30", + "ipywidgets>=8.1.7", "jinja2>=3.1.4", "nbsphinx>=0.9.4", "nox[uv]>=2025.5.1", @@ -128,6 +125,8 @@ urls.Documentation = "https://docs.plasmapy.org/" urls.Issues = "https://github.com/PlasmaPy/plasmapy/issues/" urls.Source = "https://github.com/PlasmaPy/plasmapy" urls.website = "https://www.plasmapy.org" + +# Remove references to plasma calculator after mid-2026 scripts.plasma-calculator = "plasmapy.utils.calculator:main" [tool.setuptools] @@ -136,7 +135,6 @@ include-package-data = true [tool.setuptools.package-data] "plasmapy.particles.data" = [ "*" ] "plasmapy.tests" = [ "coveragerc" ] -"plasmapy.utils.calculator" = [ "*" ] [tool.setuptools.packages.find] where = [ "src" ] @@ -330,7 +328,6 @@ lint.per-file-ignores."src/plasmapy/analysis/swept_langmuir/__init__.py" = [ "E4 lint.per-file-ignores."src/plasmapy/formulary/braginskii.py" = [ "C901", "RET503", "RET504" ] lint.per-file-ignores."src/plasmapy/plasma/sources/*.py" = [ "D102" ] lint.per-file-ignores."src/plasmapy/utils/_pytest_helpers/pytest_helpers.py" = [ "BLE001", "PLR", "SLF001" ] -lint.per-file-ignores."src/plasmapy/utils/calculator/plasma_calculator.ipynb" = [ "SLF001" ] lint.per-file-ignores."tests/**/__init__.py" = [ "D104" ] lint.per-file-ignores."tests/**/test_*.py" = [ "D100", @@ -535,7 +532,6 @@ exclude_lines = [ branch = true source = [ "src" ] omit = [ - "*/plasmapy/utils/calculator/*", "*/plasmapy/tests/*", "*/plasmapy/*version.py", "*/plasmapy/_dev/*", diff --git a/src/plasmapy/utils/calculator/__init__.py b/src/plasmapy/utils/calculator/__init__.py index db2cdf6cce..c9ef57b1d9 100644 --- a/src/plasmapy/utils/calculator/__init__.py +++ b/src/plasmapy/utils/calculator/__init__.py @@ -1,59 +1,20 @@ """ -Script and utilities to launch the plasma calculator. -""" - -__all__ = ["main"] - -import argparse -import pathlib -import shlex -import subprocess +Subpackage formerly containing a prototype plasma calculator. -_description = """ -Plasma calculator is a tool that opens a page in a web browser for -interactive calculation of plasma parameters. +.. important:: -This tool is currently in the prototype stage and is expected to change in -the future. Please raise an issue at the following link to provide suggestions -and feedback: https://github.com/PlasmaPy/PlasmaPy/issues/new + The plasma calculator has been removed from PlasmaPy + so that it can be included in the |plasmapy-calculator| standalone + package. """ +from typing import NoReturn # coverage: ignore -def main() -> None: - """ - Stub function for command line tool that launches the plasma calculator notebook. - """ - parser = argparse.ArgumentParser(description=_description) - parser.add_argument( - "--port", type=int, default=8866, help="Port to run the notebook" - ) - parser.add_argument( - "--dark", action="store_true", help="Turn on dark mode, reduces eye strain" - ) - parser.add_argument( - "--no-browser", action="store_true", help="Do not open the browser" - ) - - module_path = pathlib.Path(__file__).parent.absolute() - notebook_path = module_path / "plasma_calculator.ipynb" - favicon_path = module_path / "favicon.ico" - - args = parser.parse_args() - theme = "dark" if args.dark else "light" - no_browser = "--no-browser" if args.no_browser else "" - command = [ - "voila", - notebook_path, - f"--port={args.port}", - f"--theme={theme}", - f"--VoilaConfiguration.file_whitelist={favicon_path}", - ] - if no_browser: - command.append(no_browser) - - try: - subprocess.call(command) # noqa: S603 - except KeyboardInterrupt: - # We'll need to switch from print() to using logging library - print("Stopping calculator! Bye") # noqa: T201 +def main() -> NoReturn: # coverage: ignore + """Plasma calculator.""" + raise RuntimeError( + "The plasma calculator has been extracted from PlasmaPy into a " + "standalone package. For more details, see: " + "https://github.com/PlasmaPy/plasmapy-calculator" + ) diff --git a/src/plasmapy/utils/calculator/favicon.ico b/src/plasmapy/utils/calculator/favicon.ico deleted file mode 100644 index 5714d36a33289bc513e2b81d2c94535f45929a29..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 90022 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 - Electron Density Number:"), - *_create_widget( - _FloatBox, - property_name="n_e", - unit=u.m**-3, - opts=[u.m**-3, u.cm**-3, u.mm**-3], - ), - ], - [ - _create_label("ni - Ion Number Density:"), - *_create_widget( - _FloatBox, - property_name="n_i", - unit=u.m**-3, - opts=[u.m**-3, u.cm**-3, u.mm**-3], - ), - ], - [ - _create_label("_" * 20, color=LIGHT_BLUE), - _create_label("Temperature"), - _create_label("_" * 20, color=LIGHT_BLUE), - ], - [ - _create_label("T - Standard Temperature:"), - _create_widget(_FloatBox, property_name="T", min=0, unit=u.K), - _create_label("K", color=LIGHT_GRAY), - ], - [ - _create_label("Te - Electron Temperature:"), - _create_widget(_FloatBox, property_name="T_e", min=0, unit=u.K), - _create_label("K", color=LIGHT_GRAY), - ], - [ - _create_label("Ti - Ion Temperature:"), - _create_widget(_FloatBox, property_name="T_i", min=0, unit=u.K), - _create_label("K", color=LIGHT_GRAY), - ], -] -""" -grid_data: Contains widgets layout for input parameters -""" - - -def _create_interactive_layout(): - """ - Interactive grid layout for input parameters populated in grid_data. - """ - grid = widgets.GridspecLayout(18, 3) - grid.layout.margin = "10px" - - for i, row in enumerate(grid_data): - for j, cell in enumerate(row): - grid[i, j] = cell - - grid[-1, 0] = _calculate_button - grid[-1, 1] = _clear_button - return grid - - -def _create_output_layout(): - """ - Tab layout for output parameters, populated from - ``properties_metadata.json``. - """ - app = widgets.Tab() - children = [] - - properties_metadata = Path("properties_metadata.json") - - with properties_metadata.open() as f: - data = json.load(f) - - for i, title in enumerate(data): - grid_layout = widgets.GridspecLayout(10, 2, width="100%") - for j, prop in enumerate(data[title]): - fn = _FunctionInfo(prop["module_name"], prop["function_name"]) - if "spec_combo" in prop: - for spec_combo in prop["spec_combo"]: - fn.add_combo(spec_combo) - grid_layout[j, 0] = _create_label(prop["function_name"] + ":") - grid_layout[j, 1] = fn.get_output_widget() - _process_queue.append(fn) - children.append(grid_layout) - app.set_title(i, title) - app.children = children - - return app diff --git a/src/plasmapy/utils/calculator/plasma_calculator.ipynb b/src/plasmapy/utils/calculator/plasma_calculator.ipynb deleted file mode 100644 index 19f0d947e3..0000000000 --- a/src/plasmapy/utils/calculator/plasma_calculator.ipynb +++ /dev/null @@ -1,70 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Calculate plasma parameters" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "%matplotlib inline" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import plasmapy.utils.calculator.main_interface as pc" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "pc._create_interactive_layout()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "pc._create_output_layout()" - ] - } - ], - "metadata": { - "interpreter": { - "hash": "a1fafe92487e6823dbe852514612f53ec74aa37737c5bc2c8ee36ad7d3fbdcd4" - }, - "kernelspec": { - "display_name": "Python 3.9.7 64-bit (windows store)", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.7" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} diff --git a/src/plasmapy/utils/calculator/properties_metadata.json b/src/plasmapy/utils/calculator/properties_metadata.json deleted file mode 100644 index 2c9c82a94e..0000000000 --- a/src/plasmapy/utils/calculator/properties_metadata.json +++ /dev/null @@ -1,77 +0,0 @@ -{ - "Speed":[ - { - "function_name":"Alfven_speed", - "module_name":"plasmapy.formulary" - }, - { - "function_name":"thermal_speed", - "module_name":"plasmapy.formulary" - }, - { - "function_name":"ion_sound_speed", - "module_name":"plasmapy.formulary" - } - ], - "Length":[ - { - "function_name":"inertial_length", - "module_name":"plasmapy.formulary" - }, - { - "function_name":"gyroradius", - "module_name":"plasmapy.formulary", - "spec_combo":[ - ["B","particle","Vperp"], - ["B","particle","T"] - ] - }, - { - "function_name":"Debye_length", - "module_name":"plasmapy.formulary" - } - ], - "Frequency":[ - { - "function_name":"gyrofrequency", - "module_name":"plasmapy.formulary" - }, - { - "function_name":"plasma_frequency", - "module_name":"plasmapy.formulary" - }, - { - "function_name":"lower_hybrid_frequency", - "module_name":"plasmapy.formulary" - }, - { - "function_name":"upper_hybrid_frequency", - "module_name":"plasmapy.formulary" - } - ], - "Dimensionless numbers":[ - { - "function_name":"Hall_parameter", - "module_name":"plasmapy.formulary" - }, - { - "function_name":"Debye_number", - "module_name":"plasmapy.formulary" - } - ], - "Magnetics":[ - { - "function_name":"magnetic_pressure", - "module_name":"plasmapy.formulary" - }, - { - "function_name":"magnetic_energy_density", - "module_name":"plasmapy.formulary" - }, - { - "function_name":"Bohm_diffusion", - "module_name":"plasmapy.formulary" - } - ] - -} diff --git a/src/plasmapy/utils/calculator/widget_helpers.py b/src/plasmapy/utils/calculator/widget_helpers.py deleted file mode 100644 index 6ee61de81c..0000000000 --- a/src/plasmapy/utils/calculator/widget_helpers.py +++ /dev/null @@ -1,684 +0,0 @@ -""" -Contains functions that create widgets and process properties for the calculator. -""" - -__all__: list[str] = [] - -import abc -import importlib -from inspect import signature - -import ipywidgets as widgets - -from plasmapy.particles import Particle - -BLACK = (0, 0, 0) -"""RGB constant for black.""" - -DARK_RED = (255, 0, 0) -"""RGB Constant for dark red.""" - -LIGHT_GREEN = (0, 128, 0) -"""RGB Constant for light green.""" - -ERROR_STYLE = "2px solid red" -"""Constant for error style.""" - -EQUAL_SPACING_CONFIG = "10px 10px 10px 10px" -"""Constant for equal spacing config among widgets.""" - -values_container = {} -"""stores the values of widget with corresponding ``property_name``.""" - -_process_queue = [] -""" -Stores the functions to be processed. This data is gathered from -``properties_metadata.json``. -""" - - -class _GenericWidget(abc.ABC): - """ - Generic widget class. - - Parameters - ---------- - property_name: `str` - Name of the property the widget is associated with. - This value is key for the values_container. - - property_alias: `str` - Alias of the property. Useful to display in validation error messages. - - values_cont: `dict` - Reference to global dictionary to store the values of the widgets. - - Raises - ------ - `NotImplementedError` - If the method `create_widget` is not implemented. - """ - - def __init__( - self, property_name: str, property_alias: str = "", values_cont=values_container - ) -> None: - self.property_name = property_name - self.property_alias = property_alias or property_name - self.widget = None - self.values_cont = values_cont - self.unit = None - self.units_dropdown = None - - def set_unit(self, unit) -> None: - """ - Set unit for the value of widget, defaults to `None`. - - Parameters - ---------- - unit: `astropy.units.Unit` - Unit to be set for the value of widget - """ - self.unit = unit - - def get_widget(self): - """ - Get current widget object reference. - - Returns - ------- - `ipywidgets.Widget` - Current widget object reference - """ - return self.widget - - def get_dropdown_widget(self): - """ - Get dropdown widget associated with current widget, defaults to `None`. - - Returns - ------- - `ipywidgets.Dropdown` - Dropdown widget associated with current widget - """ - return self.units_dropdown - - def set_place_holder(self, text: str) -> None: - """ - Set place holder text of the widget, defaults to empty string. - - Parameters - ---------- - text: `str` - Place holder text to be set - """ - self.widget.placeholder = text - - @abc.abstractmethod - def create_widget(self): - """ - Virtual method to create widget. - """ - - def post_creation(self) -> None: - """ - Default method that is called after widget creation. - Attaches change listener to the widget. - """ - self.set_place_holder("") - self.widget.observe(self.handle_change, names="value") - - def edge_case(self, value) -> None: # noqa: B027 - """ - Edge case handling for the widget. This is called within handle_change. - - Parameters - ---------- - value: `any` - Value of the widget - """ - - def edge_case_condition(self, value) -> bool: # noqa: ARG002 - """ - Edge case condition for the widget. - - Parameters - ---------- - value: `any` - Value of the widget - - Returns - ------- - `bool` - `True` if the value is an edge case, `False` otherwise - """ - return False - - def try_change_value(self, value) -> None: - """ - Set property_name in values_container to value. - - Parameters - ---------- - value: `any` - Value to be set - """ - self.values_cont[self.property_name] = value - - def display_error(self, value) -> None: # noqa: ARG002 - """ - Handle invalid input provide realtime validation. - - Parameters - ---------- - value: `any` - Value of the widget - """ - if self.widget: - self.widget.layout.border = ERROR_STYLE - self.widget.description = f"Invalid {self.property_alias}" - self.values_cont[self.property_name] = None - - def convert_to_unit(self, change): - """ - Convert the value of the widget to the unit specified by the dropdown. - - Parameters - ---------- - change: `any` - New value of the widget - - Returns - ------- - `any` - Value of the widget in the unit specified by the dropdown - """ - return change.new * self.unit if self.unit else change.new - - def attach_units_dropdown(self, options) -> None: - """ - Special method that attaches dropdown widget to the input widget, - and handles the change event of the dropdown widget. - - Parameters - ---------- - options: `list` - List of units to be displayed in the dropdown widget - """ - self.units_dropdown = widgets.Dropdown( - options=options, value=options[0], layout=widgets.Layout(width="100px") - ) - self.units_dropdown.observe(self.handle_dropdown_change, names="value") - - def handle_dropdown_change(self, change) -> None: # noqa: ARG002 - """ - Handle change event of the dropdown widget. - - Parameters - ---------- - change: `any` - New value of the dropdown widget - """ - self.set_unit(self.units_dropdown.value) - if self.property_name in self.values_cont: - self.values_cont[self.property_name] = ( - self.values_cont[self.property_name].value * self.unit - ) - - def handle_change(self, change) -> None: - """ - Handle change event of the widget, follows same process - for all widgets. - - Gets the new value with units, checks for invalid input, - edge case and updates values_container accordingly. - - Parameters - ---------- - change: `any` - New value of the widget - """ - value = self.convert_to_unit(change) - if self.edge_case_condition(value): - self.edge_case(value) - else: - try: - self.try_change_value(value) - except ValueError: - self.display_error(value) - - -class _FloatBox(_GenericWidget): - """ - Derived from _GenericWidget, a FloatBox input widget - with incremental options. - - Parameters - ---------- - property_name: `str` - Name of the property the widget is associated with. - - min: `float` - Minimum value the widget can take - - max: `float` - Maximum value the widget can take - """ - - def __init__( - self, - property_name: str, - min: float = -1e50, # noqa: A002 - max: float = 1e50, # noqa: A002 - ) -> None: - super().__init__(property_name) - self.min = min - self.max = max - - def create_widget(self, style=None) -> None: - """ - Implements create_widget. description_width is set to initial - to make the widget as wide as possible. - """ - if style is None: - style = {"description_width": "initial"} - self.widget = widgets.BoundedFloatText( - name=self.property_name, - min=self.min, - max=self.max, - value=0, - step=0.1, - style=style, - ) - self.post_creation() - - -class _CheckBox(_GenericWidget): - """ - Derived from _GenericWidget, a CheckBox input widget. - - Parameters - ---------- - property_name: `str` - Name of the property the widget is associated with. - """ - - def __init__(self, property_name: str) -> None: - super().__init__(property_name) - - def create_widget(self) -> None: - """ - Implements create_widget. - """ - self.widget = widgets.Checkbox(value=False) - self.post_creation() - - -class _ParticleBox(_GenericWidget): - """ - Derived from _GenericWidget, input widget specific for particle - name. - - Parameters - ---------- - property_name: `str` - Name of the property the widget is associated with. - - property_alias: `str` - Alias of the property the widget is associated with. - (particle_type in this case) - """ - - def __init__(self, property_name: str, property_alias=None) -> None: - super().__init__(property_name, property_alias=property_alias) - - def edge_case_condition(self, value): - """ - Edge case for particle box, checks if value is empty. - - Parameters - ---------- - value: `str` - Value of the widget - - Returns - ------- - `bool` - `True` if the value is empty, `False` otherwise - """ - return value is None or value == "" - - def edge_case(self, value) -> None: # noqa: ARG002 - """ - Edge case to handle empty value of particle box - resets the container value to `None`, and resets the error status. - """ - self.values_cont[self.property_name] = None - self.widget.description = "" - self.widget.layout.border = "" - - def try_change_value(self, value) -> None: - """ - Set property_name in values_container to value, - and resets the error status. - - Parameters - ---------- - value: `str` - Value to be set - - Raises - ------ - `~plasmapy.particles.exceptions.InvalidParticleError` - Raised when the particle input does not correspond to a valid - particle or is contradictory. - """ - particle = Particle(value) - self.values_cont[self.property_name] = particle - self.widget.layout.border = "" - self.widget.description = "" - - def create_widget(self, style=None) -> None: - """ - Implements create_widget. description_width is set to initial - to make the widget as wide as possible. - """ - if style is None: - style = {"description_width": "initial"} - self.widget = widgets.Text(style=style) - self.post_creation() - - -class _IonBox(_ParticleBox): - """ - Derived from _ParticleBox, input widget specific for ion. - - Parameters - ---------- - property_name: `str` - Name of the property the widget is associated with. - - property_alias: `str` - Alias of the property the widget is associated with. - """ - - def __init__(self, property_name: str, property_alias=None) -> None: - super().__init__(property_name, property_alias=property_alias) - - def try_change_value(self, value): - """ - Set property_name in values_container to value on validating input. - - Parameters - ---------- - value: `str` - Value to be set - - Raises - ------ - `~plasmapy.particles.exceptions.InvalidParticleError` - Raised when the particle input does not correspond to a valid - particle or is contradictory. - `ValueError` - Raised when the input is not a valid ion - """ - ion = Particle(value) - if not ion.is_ion: - raise ValueError(f"{ion} is not an ion") - - self.values_cont[self.property_name] = ion - self.widget.layout.border = "" - self.widget.description = "" - - -class _FunctionInfo: - """ - Class to store information about a function. Gets the function's parameters, - and uses to process input based on function signature. - - Parameters - ---------- - module_name: `str` - Name of the module the function is in - - function_name: `str` - Name of the function - - values_container: `dict` - Reference to global dictionary of values to be passed to the function - """ - - def __init__( - self, module_name: str, function_name: str, values_cont=values_container - ) -> None: - self.module = module_name - self.fname = function_name - self.fattr = getattr(importlib.import_module(module_name), function_name) - self.values_cont = values_cont - self.spec_combo = None - self.sig = list(signature(self.fattr).parameters.keys()) - self.output_widget = widgets.Output() - self.output_widget.layout.margin = EQUAL_SPACING_CONFIG - self.output_widget.layout.padding = EQUAL_SPACING_CONFIG - - def add_combo(self, spec_combo) -> None: - """ - Specify selective combination of parameters to be used in the function, - This is the case for few functions where having all parameters doesn't yield - output. - - Parameters - ---------- - spec_combo: `list` - List of parameters to be used in the function - - Examples - -------- - For `plasmapy.formulary.gyroradius` the specific combos are as follows: - :py:`["B","particle","Vperp"]` and :py:`["B","particle","T"]` - """ - if not self.spec_combo: - self.spec_combo = [] - self.spec_combo.append(spec_combo) - - def get_output_widget(self): - """ - Returns the output widget of the function. - - Returns - ------- - `~ipywidgets.widgets.Output` - Output widget of the function - """ - return self.output_widget - - def produce_arg(self, spec): - """ - Prepares a dictionary of arguments that is present in both values_container, - and in spec. - - Parameters - ---------- - spec: `list` - List of parameters to be used in the function - - Returns - ------- - `dict` - Dictionary of arguments that is available - """ - return { - arg: self.values_cont[arg] - for arg in spec - if arg in self.values_cont and self.values_cont[arg] is not None - } - - def error_message(self, spec) -> None: - """ - Generates an error message for the function when parameters are missing. - - Parameters - ---------- - spec: `list` - List of parameters to be used in the function - """ - # We'll need to switch from print() to using logging library - - print(_colored_text(BLACK, "["), end="") # noqa: T201 - - for arg in spec: - if arg in self.values_cont and self.values_cont[arg] is not None: - print( # noqa: T201 - _colored_text(LIGHT_GREEN, f"{arg}:present,"), - end="", - ) - else: - print( # noqa: T201 - _colored_text(DARK_RED, f"{arg}:missing,"), - end="", - ) - - print(_colored_text(BLACK, "]")) # noqa: T201 - - def process(self) -> None: - """ - Processes the function based on signatures and spec_combo provided. - Spec_combo is prioritized over the function signature. - """ - self.output_widget.clear_output() - args_dict = {} - if self.spec_combo: - for spec in self.spec_combo: - args_dict = self.produce_arg(spec) - - if len(args_dict) == len(spec): - break - else: - args_dict = self.produce_arg(self.sig) - with self.output_widget: - try: - self.output_widget.layout.border = "0px" - - # We'll need to switch from print() to using logging library - - print(f" : {self.fattr(**args_dict)}") # noqa: T201 - - except Exception as e: # noqa: BLE001 - self.output_widget.layout.border = ERROR_STYLE - print(e) # noqa: T201 - print( # noqa: T201 - " : could not be computed one or more parameter is missing - check below for missing parameters" - ) - if self.spec_combo: - for spec in self.spec_combo: - self.error_message(spec) - else: - self.error_message(self.sig) - - -def _create_label(label: str, color: str = "black"): - """ - Creates a label widget with the given text and color. - - Parameters - ---------- - label: `str` - Text of the label - - color: `str` - Color of the label, defaults to black - """ - # This is done so voila switches colors according to theme - color_param = f"color:{color}" if color != "black" else "" - return widgets.HTML(f"

{label}

") - - -def _handle_button_click(event) -> None: - """ - Handles the click event of the calculate properties button. - """ - for fn in _process_queue: - fn.process() - - -def _handle_clear_click(event) -> None: - """ - Handles the click event of the clear properties button. - Clears output of all functions. - """ - for fn in _process_queue: - fn.output_widget.clear_output() - - -def _colored_text(color, text: str) -> str: - """ - Prepares an inline string with the given color. - - Parameters - ---------- - color: `list` - RGB color of the text - - text: `str` - Text to be colored - - Returns - ------- - `str` - Colored text - """ - return f"\033[38;2;{color[0]};{color[1]};{color[2]}m{text} \033[38;2;255;255;255m" - - -_calculate_button = widgets.Button( - description="Calculate Properties", button_style="info" -) -_calculate_button.on_click(_handle_button_click) - -_clear_button = widgets.Button(description="Clear Output", button_style="danger") -_clear_button.on_click(_handle_clear_click) - - -def _create_widget(widget_type, **kwargs): - """ - Creates a widget of the given type with the given parameters. - Widget can be with/without units dropdown. - - Parameters - ---------- - widget_type: `any` - Type of the widget to be created. - - **kwargs: `dict` - Parameters specific to the widget. - - Returns - ------- - |Widget| or [|Widget|, |Widget|] - widget or [widget, units_dropdown] - - .. |Widget| replace:: `~ipywidgets.widgets.Widget` - """ - unit = None - placeholder = None - opts = None - if "unit" in kwargs: - unit = kwargs["unit"] - kwargs.pop("unit") - if "placeholder" in kwargs: - placeholder = kwargs["placeholder"] - kwargs.pop("placeholder") - if "opts" in kwargs: - opts = kwargs["opts"] - kwargs.pop("opts") - widget_element = widget_type(**kwargs) - widget_element.create_widget() - if unit: - widget_element.set_unit(unit) - if placeholder: - widget_element.set_place_holder(placeholder) - - if opts: - widget_element.attach_units_dropdown(opts) - return [widget_element.get_widget(), widget_element.get_dropdown_widget()] - - return widget_element.get_widget() diff --git a/uv.lock b/uv.lock index ed815b1e58..b1f63ff877 100644 --- a/uv.lock +++ b/uv.lock @@ -2,8 +2,7 @@ version = 1 revision = 3 requires-python = ">=3.11" resolution-markers = [ - "python_full_version >= '3.14'", - "python_full_version >= '3.12' and python_full_version < '3.14'", + "python_full_version >= '3.12'", "python_full_version < '3.12'", ] @@ -16,20 +15,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/7e/b3/6b4067be973ae96ba0d615946e314c5ae35f9f993eca561b356540bb0c2b/alabaster-1.0.0-py3-none-any.whl", hash = "sha256:fc6786402dc3fcb2de3cabd5fe455a2db534b371124f1f21de8731783dec828b", size = 13929, upload-time = "2024-07-26T18:15:02.05Z" }, ] -[[package]] -name = "anyio" -version = "4.9.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "idna" }, - { name = "sniffio" }, - { name = "typing-extensions", marker = "python_full_version < '3.13'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/95/7d/4c1bd541d4dffa1b52bd83fb8527089e097a106fc90b467a7313b105f840/anyio-4.9.0.tar.gz", hash = "sha256:673c0c244e15788651a4ff38710fea9675823028a6f08a5eda409e0c9840a028", size = 190949, upload-time = "2025-03-17T00:02:54.77Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/a1/ee/48ca1a7c89ffec8b6a0c5d02b89c305671d5ffd8d3c94acf8b8c408575bb/anyio-4.9.0-py3-none-any.whl", hash = "sha256:9f76d541cad6e36af7beb62e978876f3b41e3e04f2c1fbf0884604c0a9c4d93c", size = 100916, upload-time = "2025-03-17T00:02:52.713Z" }, -] - [[package]] name = "appnope" version = "0.1.4" @@ -48,91 +33,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/31/da/e42d7a9d8dd33fa775f467e4028a47936da2f01e4b0e561f9ba0d74cb0ca/argcomplete-3.6.2-py3-none-any.whl", hash = "sha256:65b3133a29ad53fb42c48cf5114752c7ab66c1c38544fdf6460f450c09b42591", size = 43708, upload-time = "2025-04-03T04:57:01.591Z" }, ] -[[package]] -name = "argon2-cffi" -version = "25.1.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "argon2-cffi-bindings", version = "21.2.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.14'" }, - { name = "argon2-cffi-bindings", version = "25.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.14'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/0e/89/ce5af8a7d472a67cc819d5d998aa8c82c5d860608c4db9f46f1162d7dab9/argon2_cffi-25.1.0.tar.gz", hash = "sha256:694ae5cc8a42f4c4e2bf2ca0e64e51e23a040c6a517a85074683d3959e1346c1", size = 45706, upload-time = "2025-06-03T06:55:32.073Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/4f/d3/a8b22fa575b297cd6e3e3b0155c7e25db170edf1c74783d6a31a2490b8d9/argon2_cffi-25.1.0-py3-none-any.whl", hash = "sha256:fdc8b074db390fccb6eb4a3604ae7231f219aa669a2652e0f20e16ba513d5741", size = 14657, upload-time = "2025-06-03T06:55:30.804Z" }, -] - -[[package]] -name = "argon2-cffi-bindings" -version = "21.2.0" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.14'", -] -dependencies = [ - { name = "cffi", marker = "python_full_version >= '3.14'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/b9/e9/184b8ccce6683b0aa2fbb7ba5683ea4b9c5763f1356347f1312c32e3c66e/argon2-cffi-bindings-21.2.0.tar.gz", hash = "sha256:bb89ceffa6c791807d1305ceb77dbfacc5aa499891d2c55661c6459651fc39e3", size = 1779911, upload-time = "2021-12-01T08:52:55.68Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/d4/13/838ce2620025e9666aa8f686431f67a29052241692a3dd1ae9d3692a89d3/argon2_cffi_bindings-21.2.0-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:ccb949252cb2ab3a08c02024acb77cfb179492d5701c7cbdbfd776124d4d2367", size = 29658, upload-time = "2021-12-01T09:09:17.016Z" }, - { url = "https://files.pythonhosted.org/packages/b3/02/f7f7bb6b6af6031edb11037639c697b912e1dea2db94d436e681aea2f495/argon2_cffi_bindings-21.2.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9524464572e12979364b7d600abf96181d3541da11e23ddf565a32e70bd4dc0d", size = 80583, upload-time = "2021-12-01T09:09:19.546Z" }, - { url = "https://files.pythonhosted.org/packages/ec/f7/378254e6dd7ae6f31fe40c8649eea7d4832a42243acaf0f1fff9083b2bed/argon2_cffi_bindings-21.2.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b746dba803a79238e925d9046a63aa26bf86ab2a2fe74ce6b009a1c3f5c8f2ae", size = 86168, upload-time = "2021-12-01T09:09:21.445Z" }, - { url = "https://files.pythonhosted.org/packages/74/f6/4a34a37a98311ed73bb80efe422fed95f2ac25a4cacc5ae1d7ae6a144505/argon2_cffi_bindings-21.2.0-cp36-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:58ed19212051f49a523abb1dbe954337dc82d947fb6e5a0da60f7c8471a8476c", size = 82709, upload-time = "2021-12-01T09:09:18.182Z" }, - { url = "https://files.pythonhosted.org/packages/74/2b/73d767bfdaab25484f7e7901379d5f8793cccbb86c6e0cbc4c1b96f63896/argon2_cffi_bindings-21.2.0-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:bd46088725ef7f58b5a1ef7ca06647ebaf0eb4baff7d1d0d177c6cc8744abd86", size = 83613, upload-time = "2021-12-01T09:09:22.741Z" }, - { url = "https://files.pythonhosted.org/packages/4f/fd/37f86deef67ff57c76f137a67181949c2d408077e2e3dd70c6c42912c9bf/argon2_cffi_bindings-21.2.0-cp36-abi3-musllinux_1_1_i686.whl", hash = "sha256:8cd69c07dd875537a824deec19f978e0f2078fdda07fd5c42ac29668dda5f40f", size = 84583, upload-time = "2021-12-01T09:09:24.177Z" }, - { url = "https://files.pythonhosted.org/packages/6f/52/5a60085a3dae8fded8327a4f564223029f5f54b0cb0455a31131b5363a01/argon2_cffi_bindings-21.2.0-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:f1152ac548bd5b8bcecfb0b0371f082037e47128653df2e8ba6e914d384f3c3e", size = 88475, upload-time = "2021-12-01T09:09:26.673Z" }, - { url = "https://files.pythonhosted.org/packages/8b/95/143cd64feb24a15fa4b189a3e1e7efbaeeb00f39a51e99b26fc62fbacabd/argon2_cffi_bindings-21.2.0-cp36-abi3-win32.whl", hash = "sha256:603ca0aba86b1349b147cab91ae970c63118a0f30444d4bc80355937c950c082", size = 27698, upload-time = "2021-12-01T09:09:27.87Z" }, - { url = "https://files.pythonhosted.org/packages/37/2c/e34e47c7dee97ba6f01a6203e0383e15b60fb85d78ac9a15cd066f6fe28b/argon2_cffi_bindings-21.2.0-cp36-abi3-win_amd64.whl", hash = "sha256:b2ef1c30440dbbcba7a5dc3e319408b59676e2e039e2ae11a8775ecf482b192f", size = 30817, upload-time = "2021-12-01T09:09:30.267Z" }, - { url = "https://files.pythonhosted.org/packages/5a/e4/bf8034d25edaa495da3c8a3405627d2e35758e44ff6eaa7948092646fdcc/argon2_cffi_bindings-21.2.0-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:e415e3f62c8d124ee16018e491a009937f8cf7ebf5eb430ffc5de21b900dad93", size = 53104, upload-time = "2021-12-01T09:09:31.335Z" }, -] - -[[package]] -name = "argon2-cffi-bindings" -version = "25.1.0" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.12' and python_full_version < '3.14'", - "python_full_version < '3.12'", -] -dependencies = [ - { name = "cffi", marker = "python_full_version < '3.14'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/5c/2d/db8af0df73c1cf454f71b2bbe5e356b8c1f8041c979f505b3d3186e520a9/argon2_cffi_bindings-25.1.0.tar.gz", hash = "sha256:b957f3e6ea4d55d820e40ff76f450952807013d361a65d7f28acc0acbf29229d", size = 1783441, upload-time = "2025-07-30T10:02:05.147Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/60/97/3c0a35f46e52108d4707c44b95cfe2afcafc50800b5450c197454569b776/argon2_cffi_bindings-25.1.0-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:3d3f05610594151994ca9ccb3c771115bdb4daef161976a266f0dd8aa9996b8f", size = 54393, upload-time = "2025-07-30T10:01:40.97Z" }, - { url = "https://files.pythonhosted.org/packages/9d/f4/98bbd6ee89febd4f212696f13c03ca302b8552e7dbf9c8efa11ea4a388c3/argon2_cffi_bindings-25.1.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:8b8efee945193e667a396cbc7b4fb7d357297d6234d30a489905d96caabde56b", size = 29328, upload-time = "2025-07-30T10:01:41.916Z" }, - { url = "https://files.pythonhosted.org/packages/43/24/90a01c0ef12ac91a6be05969f29944643bc1e5e461155ae6559befa8f00b/argon2_cffi_bindings-25.1.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:3c6702abc36bf3ccba3f802b799505def420a1b7039862014a65db3205967f5a", size = 31269, upload-time = "2025-07-30T10:01:42.716Z" }, - { url = "https://files.pythonhosted.org/packages/d4/d3/942aa10782b2697eee7af5e12eeff5ebb325ccfb86dd8abda54174e377e4/argon2_cffi_bindings-25.1.0-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a1c70058c6ab1e352304ac7e3b52554daadacd8d453c1752e547c76e9c99ac44", size = 86558, upload-time = "2025-07-30T10:01:43.943Z" }, - { url = "https://files.pythonhosted.org/packages/0d/82/b484f702fec5536e71836fc2dbc8c5267b3f6e78d2d539b4eaa6f0db8bf8/argon2_cffi_bindings-25.1.0-cp314-cp314t-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e2fd3bfbff3c5d74fef31a722f729bf93500910db650c925c2d6ef879a7e51cb", size = 92364, upload-time = "2025-07-30T10:01:44.887Z" }, - { url = "https://files.pythonhosted.org/packages/c9/c1/a606ff83b3f1735f3759ad0f2cd9e038a0ad11a3de3b6c673aa41c24bb7b/argon2_cffi_bindings-25.1.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:c4f9665de60b1b0e99bcd6be4f17d90339698ce954cfd8d9cf4f91c995165a92", size = 85637, upload-time = "2025-07-30T10:01:46.225Z" }, - { url = "https://files.pythonhosted.org/packages/44/b4/678503f12aceb0262f84fa201f6027ed77d71c5019ae03b399b97caa2f19/argon2_cffi_bindings-25.1.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:ba92837e4a9aa6a508c8d2d7883ed5a8f6c308c89a4790e1e447a220deb79a85", size = 91934, upload-time = "2025-07-30T10:01:47.203Z" }, - { url = "https://files.pythonhosted.org/packages/f0/c7/f36bd08ef9bd9f0a9cff9428406651f5937ce27b6c5b07b92d41f91ae541/argon2_cffi_bindings-25.1.0-cp314-cp314t-win32.whl", hash = "sha256:84a461d4d84ae1295871329b346a97f68eade8c53b6ed9a7ca2d7467f3c8ff6f", size = 28158, upload-time = "2025-07-30T10:01:48.341Z" }, - { url = "https://files.pythonhosted.org/packages/b3/80/0106a7448abb24a2c467bf7d527fe5413b7fdfa4ad6d6a96a43a62ef3988/argon2_cffi_bindings-25.1.0-cp314-cp314t-win_amd64.whl", hash = "sha256:b55aec3565b65f56455eebc9b9f34130440404f27fe21c3b375bf1ea4d8fbae6", size = 32597, upload-time = "2025-07-30T10:01:49.112Z" }, - { url = "https://files.pythonhosted.org/packages/05/b8/d663c9caea07e9180b2cb662772865230715cbd573ba3b5e81793d580316/argon2_cffi_bindings-25.1.0-cp314-cp314t-win_arm64.whl", hash = "sha256:87c33a52407e4c41f3b70a9c2d3f6056d88b10dad7695be708c5021673f55623", size = 28231, upload-time = "2025-07-30T10:01:49.92Z" }, - { url = "https://files.pythonhosted.org/packages/1d/57/96b8b9f93166147826da5f90376e784a10582dd39a393c99bb62cfcf52f0/argon2_cffi_bindings-25.1.0-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:aecba1723ae35330a008418a91ea6cfcedf6d31e5fbaa056a166462ff066d500", size = 54121, upload-time = "2025-07-30T10:01:50.815Z" }, - { url = "https://files.pythonhosted.org/packages/0a/08/a9bebdb2e0e602dde230bdde8021b29f71f7841bd54801bcfd514acb5dcf/argon2_cffi_bindings-25.1.0-cp39-abi3-macosx_10_9_x86_64.whl", hash = "sha256:2630b6240b495dfab90aebe159ff784d08ea999aa4b0d17efa734055a07d2f44", size = 29177, upload-time = "2025-07-30T10:01:51.681Z" }, - { url = "https://files.pythonhosted.org/packages/b6/02/d297943bcacf05e4f2a94ab6f462831dc20158614e5d067c35d4e63b9acb/argon2_cffi_bindings-25.1.0-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:7aef0c91e2c0fbca6fc68e7555aa60ef7008a739cbe045541e438373bc54d2b0", size = 31090, upload-time = "2025-07-30T10:01:53.184Z" }, - { url = "https://files.pythonhosted.org/packages/c1/93/44365f3d75053e53893ec6d733e4a5e3147502663554b4d864587c7828a7/argon2_cffi_bindings-25.1.0-cp39-abi3-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1e021e87faa76ae0d413b619fe2b65ab9a037f24c60a1e6cc43457ae20de6dc6", size = 81246, upload-time = "2025-07-30T10:01:54.145Z" }, - { url = "https://files.pythonhosted.org/packages/09/52/94108adfdd6e2ddf58be64f959a0b9c7d4ef2fa71086c38356d22dc501ea/argon2_cffi_bindings-25.1.0-cp39-abi3-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d3e924cfc503018a714f94a49a149fdc0b644eaead5d1f089330399134fa028a", size = 87126, upload-time = "2025-07-30T10:01:55.074Z" }, - { url = "https://files.pythonhosted.org/packages/72/70/7a2993a12b0ffa2a9271259b79cc616e2389ed1a4d93842fac5a1f923ffd/argon2_cffi_bindings-25.1.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:c87b72589133f0346a1cb8d5ecca4b933e3c9b64656c9d175270a000e73b288d", size = 80343, upload-time = "2025-07-30T10:01:56.007Z" }, - { url = "https://files.pythonhosted.org/packages/78/9a/4e5157d893ffc712b74dbd868c7f62365618266982b64accab26bab01edc/argon2_cffi_bindings-25.1.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:1db89609c06afa1a214a69a462ea741cf735b29a57530478c06eb81dd403de99", size = 86777, upload-time = "2025-07-30T10:01:56.943Z" }, - { url = "https://files.pythonhosted.org/packages/74/cd/15777dfde1c29d96de7f18edf4cc94c385646852e7c7b0320aa91ccca583/argon2_cffi_bindings-25.1.0-cp39-abi3-win32.whl", hash = "sha256:473bcb5f82924b1becbb637b63303ec8d10e84c8d241119419897a26116515d2", size = 27180, upload-time = "2025-07-30T10:01:57.759Z" }, - { url = "https://files.pythonhosted.org/packages/e2/c6/a759ece8f1829d1f162261226fbfd2c6832b3ff7657384045286d2afa384/argon2_cffi_bindings-25.1.0-cp39-abi3-win_amd64.whl", hash = "sha256:a98cd7d17e9f7ce244c0803cad3c23a7d379c301ba618a5fa76a67d116618b98", size = 31715, upload-time = "2025-07-30T10:01:58.56Z" }, - { url = "https://files.pythonhosted.org/packages/42/b9/f8d6fa329ab25128b7e98fd83a3cb34d9db5b059a9847eddb840a0af45dd/argon2_cffi_bindings-25.1.0-cp39-abi3-win_arm64.whl", hash = "sha256:b0fdbcf513833809c882823f98dc2f931cf659d9a1429616ac3adebb49f5db94", size = 27149, upload-time = "2025-07-30T10:01:59.329Z" }, -] - -[[package]] -name = "arrow" -version = "1.3.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "python-dateutil" }, - { name = "types-python-dateutil" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/2e/00/0f6e8fcdb23ea632c866620cc872729ff43ed91d284c866b515c6342b173/arrow-1.3.0.tar.gz", hash = "sha256:d4540617648cb5f895730f1ad8c82a65f2dad0166f57b75f3ca54759c4d67a85", size = 131960, upload-time = "2023-09-30T22:11:18.25Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/f8/ed/e97229a566617f2ae958a6b13e7cc0f585470eac730a73e9e82c32a3cdd2/arrow-1.3.0-py3-none-any.whl", hash = "sha256:c728b120ebc00eb84e01882a6f5e7927a53960aa990ce7dd2b10f39005a67f80", size = 66419, upload-time = "2023-09-30T22:11:16.072Z" }, -] - [[package]] name = "asteval" version = "1.0.6" @@ -706,15 +606,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/d0/9c/df0ef2c51845a13043e5088f7bb988ca6cd5bb82d5d4203d6a158aa58cf2/fonttools-4.59.0-py3-none-any.whl", hash = "sha256:241313683afd3baacb32a6bd124d0bce7404bc5280e12e291bae1b9bba28711d", size = 1128050, upload-time = "2025-07-16T12:04:52.687Z" }, ] -[[package]] -name = "fqdn" -version = "1.5.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/30/3e/a80a8c077fd798951169626cde3e239adeba7dab75deb3555716415bd9b0/fqdn-1.5.1.tar.gz", hash = "sha256:105ed3677e767fb5ca086a0c1f4bb66ebc3c100be518f0e0d755d9eae164d89f", size = 6015, upload-time = "2021-03-11T07:16:29.08Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/cf/58/8acf1b3e91c58313ce5cb67df61001fc9dcd21be4fadb76c1a2d540e09ed/fqdn-1.5.1-py3-none-any.whl", hash = "sha256:3a179af3761e4df6eb2e026ff9e1a3033d3587bf980a0b1b2e1e5d08d7358014", size = 9121, upload-time = "2021-03-11T07:16:28.351Z" }, -] - [[package]] name = "h5py" version = "3.14.0" @@ -855,18 +746,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/58/6a/9166369a2f092bd286d24e6307de555d63616e8ddb373ebad2b5635ca4cd/ipywidgets-8.1.7-py3-none-any.whl", hash = "sha256:764f2602d25471c213919b8a1997df04bef869251db4ca8efba1b76b1bd9f7bb", size = 139806, upload-time = "2025-05-05T12:41:56.833Z" }, ] -[[package]] -name = "isoduration" -version = "20.11.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "arrow" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/7c/1a/3c8edc664e06e6bd06cce40c6b22da5f1429aa4224d0c590f3be21c91ead/isoduration-20.11.0.tar.gz", hash = "sha256:ac2f9015137935279eac671f94f89eb00584f940f5dc49462a0c4ee692ba1bd9", size = 11649, upload-time = "2020-11-01T11:00:00.312Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/7b/55/e5326141505c5d5e34c5e0935d2908a74e4561eca44108fbfb9c13d2911a/isoduration-20.11.0-py3-none-any.whl", hash = "sha256:b2904c2a4228c3d44f409c8ae8e2370eb21a26f7ac2ec5446df141dde3452042", size = 11321, upload-time = "2020-11-01T10:59:58.02Z" }, -] - [[package]] name = "jedi" version = "0.19.2" @@ -891,24 +770,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67", size = 134899, upload-time = "2025-03-05T20:05:00.369Z" }, ] -[[package]] -name = "json5" -version = "0.12.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/12/be/c6c745ec4c4539b25a278b70e29793f10382947df0d9efba2fa09120895d/json5-0.12.0.tar.gz", hash = "sha256:0b4b6ff56801a1c7dc817b0241bca4ce474a0e6a163bfef3fc594d3fd263ff3a", size = 51907, upload-time = "2025-04-03T16:33:13.201Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/41/9f/3500910d5a98549e3098807493851eeef2b89cdd3032227558a104dfe926/json5-0.12.0-py3-none-any.whl", hash = "sha256:6d37aa6c08b0609f16e1ec5ff94697e2cbbfbad5ac112afa05794da9ab7810db", size = 36079, upload-time = "2025-04-03T16:33:11.927Z" }, -] - -[[package]] -name = "jsonpointer" -version = "3.0.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/6a/0a/eebeb1fa92507ea94016a2a790b93c2ae41a7e18778f85471dc54475ed25/jsonpointer-3.0.0.tar.gz", hash = "sha256:2b2d729f2091522d61c3b31f82e11870f60b68f43fbc705cb76bf4b832af59ef", size = 9114, upload-time = "2024-06-10T19:24:42.462Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/71/92/5e77f98553e9e75130c78900d000368476aed74276eb8ae8796f65f00918/jsonpointer-3.0.0-py2.py3-none-any.whl", hash = "sha256:13e088adc14fca8b6aa8177c044e12701e6ad4b28ff10e65f2267a90109c9942", size = 7595, upload-time = "2024-06-10T19:24:40.698Z" }, -] - [[package]] name = "jsonschema" version = "4.25.0" @@ -924,19 +785,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/fe/54/c86cd8e011fe98803d7e382fd67c0df5ceab8d2b7ad8c5a81524f791551c/jsonschema-4.25.0-py3-none-any.whl", hash = "sha256:24c2e8da302de79c8b9382fee3e76b355e44d2a4364bb207159ce10b517bd716", size = 89184, upload-time = "2025-07-18T15:39:42.956Z" }, ] -[package.optional-dependencies] -format-nongpl = [ - { name = "fqdn" }, - { name = "idna" }, - { name = "isoduration" }, - { name = "jsonpointer" }, - { name = "rfc3339-validator" }, - { name = "rfc3986-validator" }, - { name = "rfc3987-syntax" }, - { name = "uri-template" }, - { name = "webcolors" }, -] - [[package]] name = "jsonschema-specifications" version = "2025.4.1" @@ -979,68 +827,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/2f/57/6bffd4b20b88da3800c5d691e0337761576ee688eb01299eae865689d2df/jupyter_core-5.8.1-py3-none-any.whl", hash = "sha256:c28d268fc90fb53f1338ded2eb410704c5449a358406e8a948b75706e24863d0", size = 28880, upload-time = "2025-05-27T07:38:15.137Z" }, ] -[[package]] -name = "jupyter-events" -version = "0.12.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "jsonschema", extra = ["format-nongpl"] }, - { name = "packaging" }, - { name = "python-json-logger" }, - { name = "pyyaml" }, - { name = "referencing" }, - { name = "rfc3339-validator" }, - { name = "rfc3986-validator" }, - { name = "traitlets" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/9d/c3/306d090461e4cf3cd91eceaff84bede12a8e52cd821c2d20c9a4fd728385/jupyter_events-0.12.0.tar.gz", hash = "sha256:fc3fce98865f6784c9cd0a56a20644fc6098f21c8c33834a8d9fe383c17e554b", size = 62196, upload-time = "2025-02-03T17:23:41.485Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/e2/48/577993f1f99c552f18a0428731a755e06171f9902fa118c379eb7c04ea22/jupyter_events-0.12.0-py3-none-any.whl", hash = "sha256:6464b2fa5ad10451c3d35fabc75eab39556ae1e2853ad0c0cc31b656731a97fb", size = 19430, upload-time = "2025-02-03T17:23:38.643Z" }, -] - -[[package]] -name = "jupyter-server" -version = "2.16.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "anyio" }, - { name = "argon2-cffi" }, - { name = "jinja2" }, - { name = "jupyter-client" }, - { name = "jupyter-core" }, - { name = "jupyter-events" }, - { name = "jupyter-server-terminals" }, - { name = "nbconvert" }, - { name = "nbformat" }, - { name = "overrides" }, - { name = "packaging" }, - { name = "prometheus-client" }, - { name = "pywinpty", marker = "os_name == 'nt'" }, - { name = "pyzmq" }, - { name = "send2trash" }, - { name = "terminado" }, - { name = "tornado" }, - { name = "traitlets" }, - { name = "websocket-client" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/41/c8/ba2bbcd758c47f1124c4ca14061e8ce60d9c6fd537faee9534a95f83521a/jupyter_server-2.16.0.tar.gz", hash = "sha256:65d4b44fdf2dcbbdfe0aa1ace4a842d4aaf746a2b7b168134d5aaed35621b7f6", size = 728177, upload-time = "2025-05-12T16:44:46.245Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/46/1f/5ebbced977171d09a7b0c08a285ff9a20aafb9c51bde07e52349ff1ddd71/jupyter_server-2.16.0-py3-none-any.whl", hash = "sha256:3d8db5be3bc64403b1c65b400a1d7f4647a5ce743f3b20dbdefe8ddb7b55af9e", size = 386904, upload-time = "2025-05-12T16:44:43.335Z" }, -] - -[[package]] -name = "jupyter-server-terminals" -version = "0.5.3" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "pywinpty", marker = "os_name == 'nt'" }, - { name = "terminado" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/fc/d5/562469734f476159e99a55426d697cbf8e7eb5efe89fb0e0b4f83a3d3459/jupyter_server_terminals-0.5.3.tar.gz", hash = "sha256:5ae0295167220e9ace0edcfdb212afd2b01ee8d179fe6f23c899590e9b8a5269", size = 31430, upload-time = "2024-03-12T14:37:03.049Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/07/2d/2b32cdbe8d2a602f697a649798554e4f072115438e92249624e532e8aca6/jupyter_server_terminals-0.5.3-py3-none-any.whl", hash = "sha256:41ee0d7dc0ebf2809c668e0fc726dfaf258fcd3e769568996ca731b6194ae9aa", size = 13656, upload-time = "2024-03-12T14:37:00.708Z" }, -] - [[package]] name = "jupyterlab-pygments" version = "0.3.0" @@ -1050,24 +836,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/b1/dd/ead9d8ea85bf202d90cc513b533f9c363121c7792674f78e0d8a854b63b4/jupyterlab_pygments-0.3.0-py3-none-any.whl", hash = "sha256:841a89020971da1d8693f1a99997aefc5dc424bb1b251fd6322462a1b8842780", size = 15884, upload-time = "2023-11-23T09:26:34.325Z" }, ] -[[package]] -name = "jupyterlab-server" -version = "2.27.3" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "babel" }, - { name = "jinja2" }, - { name = "json5" }, - { name = "jsonschema" }, - { name = "jupyter-server" }, - { name = "packaging" }, - { name = "requests" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/0a/c9/a883ce65eb27905ce77ace410d83587c82ea64dc85a48d1f7ed52bcfa68d/jupyterlab_server-2.27.3.tar.gz", hash = "sha256:eb36caca59e74471988f0ae25c77945610b887f777255aa21f8065def9e51ed4", size = 76173, upload-time = "2024-07-16T17:02:04.149Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/54/09/2032e7d15c544a0e3cd831c51d77a8ca57f7555b2e1b2922142eddb02a84/jupyterlab_server-2.27.3-py3-none-any.whl", hash = "sha256:e697488f66c3db49df675158a77b3b017520d772c6e1548c7d9bcc5df7944ee4", size = 59700, upload-time = "2024-07-16T17:02:01.115Z" }, -] - [[package]] name = "jupyterlab-widgets" version = "3.0.15" @@ -1143,15 +911,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/4c/fa/be89a49c640930180657482a74970cdcf6f7072c8d2471e1babe17a222dc/kiwisolver-1.4.8-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:be4816dc51c8a471749d664161b434912eee82f2ea66bd7628bd14583a833e85", size = 2349213, upload-time = "2024-12-24T18:30:40.019Z" }, ] -[[package]] -name = "lark" -version = "1.2.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/af/60/bc7622aefb2aee1c0b4ba23c1446d3e30225c8770b38d7aedbfb65ca9d5a/lark-1.2.2.tar.gz", hash = "sha256:ca807d0162cd16cef15a8feecb862d7319e7a09bdb13aef927968e45040fed80", size = 252132, upload-time = "2024-08-13T19:49:00.652Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/2d/00/d90b10b962b4277f5e64a78b6609968859ff86889f5b898c1a778c06ec00/lark-1.2.2-py3-none-any.whl", hash = "sha256:c2276486b02f0f1b90be155f2c8ba4a8e194d42775786db622faccd652d8e80c", size = 111036, upload-time = "2024-08-13T19:48:58.603Z" }, -] - [[package]] name = "latexcodec" version = "3.0.1" @@ -1541,15 +1300,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/26/62/5783d8924fca72529defb2c7dbe2070d49224d2dba03a85b20b37adb24d8/numpydoc-1.9.0-py3-none-any.whl", hash = "sha256:8a2983b2d62bfd0a8c470c7caa25e7e0c3d163875cdec12a8a1034020a9d1135", size = 64871, upload-time = "2025-06-24T12:22:53.701Z" }, ] -[[package]] -name = "overrides" -version = "7.7.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/36/86/b585f53236dec60aba864e050778b25045f857e17f6e5ea0ae95fe80edd2/overrides-7.7.0.tar.gz", hash = "sha256:55158fa3d93b98cc75299b1e67078ad9003ca27945c76162c1c0766d6f91820a", size = 22812, upload-time = "2024-01-27T21:01:33.423Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/2c/ab/fc8290c6a4c722e5514d80f62b2dc4c4df1a68a41d1364e625c35990fcf3/overrides-7.7.0-py3-none-any.whl", hash = "sha256:c7ed9d062f78b8e4c1a7b70bd8796b35ead4d9f510227ef9c5dc7626c60d7e49", size = 17832, upload-time = "2024-01-27T21:01:31.393Z" }, -] - [[package]] name = "packaging" version = "25.0" @@ -1729,8 +1479,6 @@ source = { editable = "." } dependencies = [ { name = "astropy" }, { name = "h5py" }, - { name = "ipykernel" }, - { name = "ipywidgets" }, { name = "lmfit" }, { name = "matplotlib" }, { name = "mpmath" }, @@ -1742,7 +1490,6 @@ dependencies = [ { name = "scipy" }, { name = "setuptools" }, { name = "tqdm" }, - { name = "voila" }, { name = "wrapt" }, { name = "xarray" }, ] @@ -1750,6 +1497,8 @@ dependencies = [ [package.optional-dependencies] docs = [ { name = "docutils" }, + { name = "ipykernel" }, + { name = "ipywidgets" }, { name = "jinja2" }, { name = "nbsphinx" }, { name = "nox", extra = ["uv"] }, @@ -1793,8 +1542,8 @@ requires-dist = [ { name = "docutils", marker = "extra == 'docs'", specifier = ">=0.20.1" }, { name = "h5py", specifier = ">=3.8" }, { name = "hypothesis", marker = "extra == 'tests'", specifier = ">=6.108.2" }, - { name = "ipykernel", specifier = ">=5.5.6" }, - { name = "ipywidgets", specifier = ">=6" }, + { name = "ipykernel", marker = "extra == 'docs'", specifier = ">=6.30" }, + { name = "ipywidgets", marker = "extra == 'docs'", specifier = ">=8.1.7" }, { name = "jinja2", marker = "extra == 'docs'", specifier = ">=3.1.4" }, { name = "lmfit", specifier = ">=1.1" }, { name = "matplotlib", specifier = ">=3.7" }, @@ -1838,7 +1587,6 @@ requires-dist = [ { name = "towncrier", marker = "extra == 'docs'", specifier = ">=23.11" }, { name = "tqdm", specifier = ">=4.65" }, { name = "unidecode", marker = "extra == 'docs'", specifier = ">=1.3.8" }, - { name = "voila", specifier = ">=0.2.7" }, { name = "wrapt", specifier = ">=1.15" }, { name = "xarray", specifier = ">=2022.12,<=2024.10" }, ] @@ -1879,15 +1627,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" }, ] -[[package]] -name = "prometheus-client" -version = "0.22.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/5e/cf/40dde0a2be27cc1eb41e333d1a674a74ce8b8b0457269cc640fd42b07cf7/prometheus_client-0.22.1.tar.gz", hash = "sha256:190f1331e783cf21eb60bca559354e0a4d4378facecf78f5428c39b675d20d28", size = 69746, upload-time = "2025-06-02T14:29:01.152Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/32/ae/ec06af4fe3ee72d16973474f122541746196aaa16cea6f66d18b963c6177/prometheus_client-0.22.1-py3-none-any.whl", hash = "sha256:cca895342e308174341b2cbf99a56bef291fbc0ef7b9e5412a0f26d653ba7094", size = 58694, upload-time = "2025-06-02T14:29:00.068Z" }, -] - [[package]] name = "prompt-toolkit" version = "3.0.51" @@ -2111,15 +1850,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892, upload-time = "2024-03-01T18:36:18.57Z" }, ] -[[package]] -name = "python-json-logger" -version = "3.3.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/9e/de/d3144a0bceede957f961e975f3752760fbe390d57fbe194baf709d8f1f7b/python_json_logger-3.3.0.tar.gz", hash = "sha256:12b7e74b17775e7d565129296105bbe3910842d9d0eb083fc83a6a617aa8df84", size = 16642, upload-time = "2025-03-07T07:08:27.301Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/08/20/0f2523b9e50a8052bc6a8b732dfc8568abbdc42010aef03a2d750bdab3b2/python_json_logger-3.3.0-py3-none-any.whl", hash = "sha256:dd980fae8cffb24c13caf6e158d3d61c0d6d22342f932cb6e9deedab3d35eec7", size = 15163, upload-time = "2025-03-07T07:08:25.627Z" }, -] - [[package]] name = "pytz" version = "2025.2" @@ -2148,18 +1878,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/c0/d2/21af5c535501a7233e734b8af901574572da66fcc254cb35d0609c9080dd/pywin32-311-cp314-cp314-win_arm64.whl", hash = "sha256:a508e2d9025764a8270f93111a970e1d0fbfc33f4153b388bb649b7eec4f9b42", size = 8932540, upload-time = "2025-07-14T20:13:36.379Z" }, ] -[[package]] -name = "pywinpty" -version = "2.0.15" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/2d/7c/917f9c4681bb8d34bfbe0b79d36bbcd902651aeab48790df3d30ba0202fb/pywinpty-2.0.15.tar.gz", hash = "sha256:312cf39153a8736c617d45ce8b6ad6cd2107de121df91c455b10ce6bba7a39b2", size = 29017, upload-time = "2025-02-03T21:53:23.265Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/5e/ac/6884dcb7108af66ad53f73ef4dad096e768c9203a6e6ce5e6b0c4a46e238/pywinpty-2.0.15-cp311-cp311-win_amd64.whl", hash = "sha256:9a6bcec2df2707aaa9d08b86071970ee32c5026e10bcc3cc5f6f391d85baf7ca", size = 1405249, upload-time = "2025-02-03T21:55:47.114Z" }, - { url = "https://files.pythonhosted.org/packages/88/e5/9714def18c3a411809771a3fbcec70bffa764b9675afb00048a620fca604/pywinpty-2.0.15-cp312-cp312-win_amd64.whl", hash = "sha256:83a8f20b430bbc5d8957249f875341a60219a4e971580f2ba694fbfb54a45ebc", size = 1405243, upload-time = "2025-02-03T21:56:52.476Z" }, - { url = "https://files.pythonhosted.org/packages/fb/16/2ab7b3b7f55f3c6929e5f629e1a68362981e4e5fed592a2ed1cb4b4914a5/pywinpty-2.0.15-cp313-cp313-win_amd64.whl", hash = "sha256:ab5920877dd632c124b4ed17bc6dd6ef3b9f86cd492b963ffdb1a67b85b0f408", size = 1405020, upload-time = "2025-02-03T21:56:04.753Z" }, - { url = "https://files.pythonhosted.org/packages/7c/16/edef3515dd2030db2795dbfbe392232c7a0f3dc41b98e92b38b42ba497c7/pywinpty-2.0.15-cp313-cp313t-win_amd64.whl", hash = "sha256:a4560ad8c01e537708d2790dbe7da7d986791de805d89dd0d3697ca59e9e4901", size = 1404151, upload-time = "2025-02-03T21:55:53.628Z" }, -] - [[package]] name = "pyyaml" version = "6.0.2" @@ -2269,39 +1987,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/7c/e4/56027c4a6b4ae70ca9de302488c5ca95ad4a39e190093d6c1a8ace08341b/requests-2.32.4-py3-none-any.whl", hash = "sha256:27babd3cda2a6d50b30443204ee89830707d396671944c998b5975b031ac2b2c", size = 64847, upload-time = "2025-06-09T16:43:05.728Z" }, ] -[[package]] -name = "rfc3339-validator" -version = "0.1.4" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "six" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/28/ea/a9387748e2d111c3c2b275ba970b735e04e15cdb1eb30693b6b5708c4dbd/rfc3339_validator-0.1.4.tar.gz", hash = "sha256:138a2abdf93304ad60530167e51d2dfb9549521a836871b88d7f4695d0022f6b", size = 5513, upload-time = "2021-05-12T16:37:54.178Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/7b/44/4e421b96b67b2daff264473f7465db72fbdf36a07e05494f50300cc7b0c6/rfc3339_validator-0.1.4-py2.py3-none-any.whl", hash = "sha256:24f6ec1eda14ef823da9e36ec7113124b39c04d50a4d3d3a3c2859577e7791fa", size = 3490, upload-time = "2021-05-12T16:37:52.536Z" }, -] - -[[package]] -name = "rfc3986-validator" -version = "0.1.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/da/88/f270de456dd7d11dcc808abfa291ecdd3f45ff44e3b549ffa01b126464d0/rfc3986_validator-0.1.1.tar.gz", hash = "sha256:3d44bde7921b3b9ec3ae4e3adca370438eccebc676456449b145d533b240d055", size = 6760, upload-time = "2019-10-28T16:00:19.144Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/9e/51/17023c0f8f1869d8806b979a2bffa3f861f26a3f1a66b094288323fba52f/rfc3986_validator-0.1.1-py2.py3-none-any.whl", hash = "sha256:2f235c432ef459970b4306369336b9d5dbdda31b510ca1e327636e01f528bfa9", size = 4242, upload-time = "2019-10-28T16:00:13.976Z" }, -] - -[[package]] -name = "rfc3987-syntax" -version = "1.1.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "lark" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/2c/06/37c1a5557acf449e8e406a830a05bf885ac47d33270aec454ef78675008d/rfc3987_syntax-1.1.0.tar.gz", hash = "sha256:717a62cbf33cffdd16dfa3a497d81ce48a660ea691b1ddd7be710c22f00b4a0d", size = 14239, upload-time = "2025-07-18T01:05:05.015Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/7e/71/44ce230e1b7fadd372515a97e32a83011f906ddded8d03e3c6aafbdedbb7/rfc3987_syntax-1.1.0-py3-none-any.whl", hash = "sha256:6c3d97604e4c5ce9f714898e05401a0445a641cfa276432b0a648c80856f6a3f", size = 8046, upload-time = "2025-07-18T01:05:03.843Z" }, -] - [[package]] name = "roman-numerals-py" version = "3.1.0" @@ -2477,15 +2162,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/6e/6c/a76329897a7cae4937d403e623aa6aaea616a0bb5b36588f0b9d1c9a3739/scipy-1.16.1-cp314-cp314t-win_amd64.whl", hash = "sha256:c0c804d60492a0aad7f5b2bb1862f4548b990049e27e828391ff2bf6f7199998", size = 39427705, upload-time = "2025-07-27T16:31:53.96Z" }, ] -[[package]] -name = "send2trash" -version = "1.8.3" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/fd/3a/aec9b02217bb79b87bbc1a21bc6abc51e3d5dcf65c30487ac96c0908c722/Send2Trash-1.8.3.tar.gz", hash = "sha256:b18e7a3966d99871aefeb00cfbcfdced55ce4871194810fc71f4aa484b953abf", size = 17394, upload-time = "2024-04-07T00:01:09.267Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/40/b0/4562db6223154aa4e22f939003cb92514c79f3d4dccca3444253fd17f902/Send2Trash-1.8.3-py3-none-any.whl", hash = "sha256:0c31227e0bd08961c7665474a3d1ef7193929fedda4233843689baa056be46c9", size = 18072, upload-time = "2024-04-07T00:01:07.438Z" }, -] - [[package]] name = "setuptools" version = "80.9.0" @@ -2504,15 +2180,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050, upload-time = "2024-12-04T17:35:26.475Z" }, ] -[[package]] -name = "sniffio" -version = "1.3.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/a2/87/a6771e1546d97e7e041b6ae58d80074f81b7d5121207425c964ddf5cfdbd/sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc", size = 20372, upload-time = "2024-02-25T23:20:04.057Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235, upload-time = "2024-02-25T23:20:01.196Z" }, -] - [[package]] name = "snowballstemmer" version = "3.0.1" @@ -2814,20 +2481,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/f1/7b/ce1eafaf1a76852e2ec9b22edecf1daa58175c090266e9f6c64afcd81d91/stack_data-0.6.3-py3-none-any.whl", hash = "sha256:d5558e0c25a4cb0853cddad3d77da9891a08cb85dd9f9f91b9f8cd66e511e695", size = 24521, upload-time = "2023-09-30T13:58:03.53Z" }, ] -[[package]] -name = "terminado" -version = "0.18.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "ptyprocess", marker = "os_name != 'nt'" }, - { name = "pywinpty", marker = "os_name == 'nt'" }, - { name = "tornado" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/8a/11/965c6fd8e5cc254f1fe142d547387da17a8ebfd75a3455f637c663fb38a0/terminado-0.18.1.tar.gz", hash = "sha256:de09f2c4b85de4765f7714688fff57d3e75bad1f909b589fde880460c753fd2e", size = 32701, upload-time = "2024-03-12T14:34:39.026Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/6a/9e/2064975477fdc887e47ad42157e214526dcad8f317a948dee17e1659a62f/terminado-0.18.1-py3-none-any.whl", hash = "sha256:a4468e1b37bb318f8a86514f65814e1afc977cf29b3992a4500d9dd305dcceb0", size = 14154, upload-time = "2024-03-12T14:34:36.569Z" }, -] - [[package]] name = "tinycss2" version = "1.4.0" @@ -2932,15 +2585,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/00/c0/8f5d070730d7836adc9c9b6408dec68c6ced86b304a9b26a14df072a6e8c/traitlets-5.14.3-py3-none-any.whl", hash = "sha256:b74e89e397b1ed28cc831db7aea759ba6640cb3de13090ca145426688ff1ac4f", size = 85359, upload-time = "2024-04-19T11:11:46.763Z" }, ] -[[package]] -name = "types-python-dateutil" -version = "2.9.0.20250708" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/c9/95/6bdde7607da2e1e99ec1c1672a759d42f26644bbacf939916e086db34870/types_python_dateutil-2.9.0.20250708.tar.gz", hash = "sha256:ccdbd75dab2d6c9696c350579f34cffe2c281e4c5f27a585b2a2438dd1d5c8ab", size = 15834, upload-time = "2025-07-08T03:14:03.382Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/72/52/43e70a8e57fefb172c22a21000b03ebcc15e47e97f5cb8495b9c2832efb4/types_python_dateutil-2.9.0.20250708-py3-none-any.whl", hash = "sha256:4d6d0cc1cc4d24a2dc3816024e502564094497b713f7befda4d5bc7a8e3fd21f", size = 17724, upload-time = "2025-07-08T03:14:02.593Z" }, -] - [[package]] name = "typing-extensions" version = "4.14.1" @@ -2977,15 +2621,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/8f/b7/559f59d57d18b44c6d1250d2eeaa676e028b9c527431f5d0736478a73ba1/Unidecode-1.4.0-py3-none-any.whl", hash = "sha256:c3c7606c27503ad8d501270406e345ddb480a7b5f38827eafe4fa82a137f0021", size = 235837, upload-time = "2025-04-24T08:45:01.609Z" }, ] -[[package]] -name = "uri-template" -version = "1.3.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/31/c7/0336f2bd0bcbada6ccef7aaa25e443c118a704f828a0620c6fa0207c1b64/uri-template-1.3.0.tar.gz", hash = "sha256:0e00f8eb65e18c7de20d595a14336e9f337ead580c70934141624b6d1ffdacc7", size = 21678, upload-time = "2023-06-21T01:49:05.374Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/e7/00/3fca040d7cf8a32776d3d81a00c8ee7457e00f80c649f1e4a863c8321ae9/uri_template-1.3.0-py3-none-any.whl", hash = "sha256:a44a133ea12d44a0c0f06d7d42a52d71282e77e2f937d8abd5655b8d56fc1363", size = 11140, upload-time = "2023-06-21T01:49:03.467Z" }, -] - [[package]] name = "urllib3" version = "2.5.0" @@ -3035,25 +2670,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/5c/c6/f8f28009920a736d0df434b52e9feebfb4d702ba942f15338cb4a83eafc1/virtualenv-20.32.0-py3-none-any.whl", hash = "sha256:2c310aecb62e5aa1b06103ed7c2977b81e042695de2697d01017ff0f1034af56", size = 6057761, upload-time = "2025-07-21T04:09:48.059Z" }, ] -[[package]] -name = "voila" -version = "0.5.9" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "jupyter-client" }, - { name = "jupyter-core" }, - { name = "jupyter-server" }, - { name = "jupyterlab-server" }, - { name = "nbclient" }, - { name = "nbconvert" }, - { name = "traitlets" }, - { name = "websockets" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/87/0a/fbf69c8ecb129c3204b6c103f831b5f2d2dbdd763e8d7dcdbcf30749f155/voila-0.5.9.tar.gz", hash = "sha256:a98ab3e72ca221ae1bd32eaf44c333c337f74f2864ea5efe60d4589103294610", size = 5344681, upload-time = "2025-07-30T09:55:45.176Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/37/ac/40932d771f93da83735a8e0a9d5234835fedda14457e8251ac5b4d192137/voila-0.5.9-py3-none-any.whl", hash = "sha256:a2bc6954014c2321912ea402716b0305f79a35fbf08540a0921b61632b7a9a89", size = 4511082, upload-time = "2025-07-30T09:55:42.845Z" }, -] - [[package]] name = "wcwidth" version = "0.2.13" @@ -3063,15 +2679,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/fd/84/fd2ba7aafacbad3c4201d395674fc6348826569da3c0937e75505ead3528/wcwidth-0.2.13-py2.py3-none-any.whl", hash = "sha256:3da69048e4540d84af32131829ff948f1e022c1c6bdb8d6102117aac784f6859", size = 34166, upload-time = "2024-01-06T02:10:55.763Z" }, ] -[[package]] -name = "webcolors" -version = "24.11.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/7b/29/061ec845fb58521848f3739e466efd8250b4b7b98c1b6c5bf4d40b419b7e/webcolors-24.11.1.tar.gz", hash = "sha256:ecb3d768f32202af770477b8b65f318fa4f566c22948673a977b00d589dd80f6", size = 45064, upload-time = "2024-11-11T07:43:24.224Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/60/e8/c0e05e4684d13459f93d312077a9a2efbe04d59c393bc2b8802248c908d4/webcolors-24.11.1-py3-none-any.whl", hash = "sha256:515291393b4cdf0eb19c155749a096f779f7d909f7cceea072791cb9095b92e9", size = 14934, upload-time = "2024-11-11T07:43:22.529Z" }, -] - [[package]] name = "webencodings" version = "0.5.1" @@ -3081,57 +2688,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/f4/24/2a3e3df732393fed8b3ebf2ec078f05546de641fe1b667ee316ec1dcf3b7/webencodings-0.5.1-py2.py3-none-any.whl", hash = "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78", size = 11774, upload-time = "2017-04-05T20:21:32.581Z" }, ] -[[package]] -name = "websocket-client" -version = "1.8.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e6/30/fba0d96b4b5fbf5948ed3f4681f7da2f9f64512e1d303f94b4cc174c24a5/websocket_client-1.8.0.tar.gz", hash = "sha256:3239df9f44da632f96012472805d40a23281a991027ce11d2f45a6f24ac4c3da", size = 54648, upload-time = "2024-04-23T22:16:16.976Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/5a/84/44687a29792a70e111c5c477230a72c4b957d88d16141199bf9acb7537a3/websocket_client-1.8.0-py3-none-any.whl", hash = "sha256:17b44cc997f5c498e809b22cdf2d9c7a9e71c02c8cc2b6c56e7c2d1239bfa526", size = 58826, upload-time = "2024-04-23T22:16:14.422Z" }, -] - -[[package]] -name = "websockets" -version = "15.0.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/21/e6/26d09fab466b7ca9c7737474c52be4f76a40301b08362eb2dbc19dcc16c1/websockets-15.0.1.tar.gz", hash = "sha256:82544de02076bafba038ce055ee6412d68da13ab47f0c60cab827346de828dee", size = 177016, upload-time = "2025-03-05T20:03:41.606Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/9f/32/18fcd5919c293a398db67443acd33fde142f283853076049824fc58e6f75/websockets-15.0.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:823c248b690b2fd9303ba00c4f66cd5e2d8c3ba4aa968b2779be9532a4dad431", size = 175423, upload-time = "2025-03-05T20:01:56.276Z" }, - { url = "https://files.pythonhosted.org/packages/76/70/ba1ad96b07869275ef42e2ce21f07a5b0148936688c2baf7e4a1f60d5058/websockets-15.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678999709e68425ae2593acf2e3ebcbcf2e69885a5ee78f9eb80e6e371f1bf57", size = 173082, upload-time = "2025-03-05T20:01:57.563Z" }, - { url = "https://files.pythonhosted.org/packages/86/f2/10b55821dd40eb696ce4704a87d57774696f9451108cff0d2824c97e0f97/websockets-15.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d50fd1ee42388dcfb2b3676132c78116490976f1300da28eb629272d5d93e905", size = 173330, upload-time = "2025-03-05T20:01:59.063Z" }, - { url = "https://files.pythonhosted.org/packages/a5/90/1c37ae8b8a113d3daf1065222b6af61cc44102da95388ac0018fcb7d93d9/websockets-15.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d99e5546bf73dbad5bf3547174cd6cb8ba7273062a23808ffea025ecb1cf8562", size = 182878, upload-time = "2025-03-05T20:02:00.305Z" }, - { url = "https://files.pythonhosted.org/packages/8e/8d/96e8e288b2a41dffafb78e8904ea7367ee4f891dafc2ab8d87e2124cb3d3/websockets-15.0.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:66dd88c918e3287efc22409d426c8f729688d89a0c587c88971a0faa2c2f3792", size = 181883, upload-time = "2025-03-05T20:02:03.148Z" }, - { url = "https://files.pythonhosted.org/packages/93/1f/5d6dbf551766308f6f50f8baf8e9860be6182911e8106da7a7f73785f4c4/websockets-15.0.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8dd8327c795b3e3f219760fa603dcae1dcc148172290a8ab15158cf85a953413", size = 182252, upload-time = "2025-03-05T20:02:05.29Z" }, - { url = "https://files.pythonhosted.org/packages/d4/78/2d4fed9123e6620cbf1706c0de8a1632e1a28e7774d94346d7de1bba2ca3/websockets-15.0.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8fdc51055e6ff4adeb88d58a11042ec9a5eae317a0a53d12c062c8a8865909e8", size = 182521, upload-time = "2025-03-05T20:02:07.458Z" }, - { url = "https://files.pythonhosted.org/packages/e7/3b/66d4c1b444dd1a9823c4a81f50231b921bab54eee2f69e70319b4e21f1ca/websockets-15.0.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:693f0192126df6c2327cce3baa7c06f2a117575e32ab2308f7f8216c29d9e2e3", size = 181958, upload-time = "2025-03-05T20:02:09.842Z" }, - { url = "https://files.pythonhosted.org/packages/08/ff/e9eed2ee5fed6f76fdd6032ca5cd38c57ca9661430bb3d5fb2872dc8703c/websockets-15.0.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:54479983bd5fb469c38f2f5c7e3a24f9a4e70594cd68cd1fa6b9340dadaff7cf", size = 181918, upload-time = "2025-03-05T20:02:11.968Z" }, - { url = "https://files.pythonhosted.org/packages/d8/75/994634a49b7e12532be6a42103597b71098fd25900f7437d6055ed39930a/websockets-15.0.1-cp311-cp311-win32.whl", hash = "sha256:16b6c1b3e57799b9d38427dda63edcbe4926352c47cf88588c0be4ace18dac85", size = 176388, upload-time = "2025-03-05T20:02:13.32Z" }, - { url = "https://files.pythonhosted.org/packages/98/93/e36c73f78400a65f5e236cd376713c34182e6663f6889cd45a4a04d8f203/websockets-15.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:27ccee0071a0e75d22cb35849b1db43f2ecd3e161041ac1ee9d2352ddf72f065", size = 176828, upload-time = "2025-03-05T20:02:14.585Z" }, - { url = "https://files.pythonhosted.org/packages/51/6b/4545a0d843594f5d0771e86463606a3988b5a09ca5123136f8a76580dd63/websockets-15.0.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:3e90baa811a5d73f3ca0bcbf32064d663ed81318ab225ee4f427ad4e26e5aff3", size = 175437, upload-time = "2025-03-05T20:02:16.706Z" }, - { url = "https://files.pythonhosted.org/packages/f4/71/809a0f5f6a06522af902e0f2ea2757f71ead94610010cf570ab5c98e99ed/websockets-15.0.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:592f1a9fe869c778694f0aa806ba0374e97648ab57936f092fd9d87f8bc03665", size = 173096, upload-time = "2025-03-05T20:02:18.832Z" }, - { url = "https://files.pythonhosted.org/packages/3d/69/1a681dd6f02180916f116894181eab8b2e25b31e484c5d0eae637ec01f7c/websockets-15.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0701bc3cfcb9164d04a14b149fd74be7347a530ad3bbf15ab2c678a2cd3dd9a2", size = 173332, upload-time = "2025-03-05T20:02:20.187Z" }, - { url = "https://files.pythonhosted.org/packages/a6/02/0073b3952f5bce97eafbb35757f8d0d54812b6174ed8dd952aa08429bcc3/websockets-15.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8b56bdcdb4505c8078cb6c7157d9811a85790f2f2b3632c7d1462ab5783d215", size = 183152, upload-time = "2025-03-05T20:02:22.286Z" }, - { url = "https://files.pythonhosted.org/packages/74/45/c205c8480eafd114b428284840da0b1be9ffd0e4f87338dc95dc6ff961a1/websockets-15.0.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0af68c55afbd5f07986df82831c7bff04846928ea8d1fd7f30052638788bc9b5", size = 182096, upload-time = "2025-03-05T20:02:24.368Z" }, - { url = "https://files.pythonhosted.org/packages/14/8f/aa61f528fba38578ec553c145857a181384c72b98156f858ca5c8e82d9d3/websockets-15.0.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:64dee438fed052b52e4f98f76c5790513235efaa1ef7f3f2192c392cd7c91b65", size = 182523, upload-time = "2025-03-05T20:02:25.669Z" }, - { url = "https://files.pythonhosted.org/packages/ec/6d/0267396610add5bc0d0d3e77f546d4cd287200804fe02323797de77dbce9/websockets-15.0.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d5f6b181bb38171a8ad1d6aa58a67a6aa9d4b38d0f8c5f496b9e42561dfc62fe", size = 182790, upload-time = "2025-03-05T20:02:26.99Z" }, - { url = "https://files.pythonhosted.org/packages/02/05/c68c5adbf679cf610ae2f74a9b871ae84564462955d991178f95a1ddb7dd/websockets-15.0.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:5d54b09eba2bada6011aea5375542a157637b91029687eb4fdb2dab11059c1b4", size = 182165, upload-time = "2025-03-05T20:02:30.291Z" }, - { url = "https://files.pythonhosted.org/packages/29/93/bb672df7b2f5faac89761cb5fa34f5cec45a4026c383a4b5761c6cea5c16/websockets-15.0.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3be571a8b5afed347da347bfcf27ba12b069d9d7f42cb8c7028b5e98bbb12597", size = 182160, upload-time = "2025-03-05T20:02:31.634Z" }, - { url = "https://files.pythonhosted.org/packages/ff/83/de1f7709376dc3ca9b7eeb4b9a07b4526b14876b6d372a4dc62312bebee0/websockets-15.0.1-cp312-cp312-win32.whl", hash = "sha256:c338ffa0520bdb12fbc527265235639fb76e7bc7faafbb93f6ba80d9c06578a9", size = 176395, upload-time = "2025-03-05T20:02:33.017Z" }, - { url = "https://files.pythonhosted.org/packages/7d/71/abf2ebc3bbfa40f391ce1428c7168fb20582d0ff57019b69ea20fa698043/websockets-15.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:fcd5cf9e305d7b8338754470cf69cf81f420459dbae8a3b40cee57417f4614a7", size = 176841, upload-time = "2025-03-05T20:02:34.498Z" }, - { url = "https://files.pythonhosted.org/packages/cb/9f/51f0cf64471a9d2b4d0fc6c534f323b664e7095640c34562f5182e5a7195/websockets-15.0.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ee443ef070bb3b6ed74514f5efaa37a252af57c90eb33b956d35c8e9c10a1931", size = 175440, upload-time = "2025-03-05T20:02:36.695Z" }, - { url = "https://files.pythonhosted.org/packages/8a/05/aa116ec9943c718905997412c5989f7ed671bc0188ee2ba89520e8765d7b/websockets-15.0.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5a939de6b7b4e18ca683218320fc67ea886038265fd1ed30173f5ce3f8e85675", size = 173098, upload-time = "2025-03-05T20:02:37.985Z" }, - { url = "https://files.pythonhosted.org/packages/ff/0b/33cef55ff24f2d92924923c99926dcce78e7bd922d649467f0eda8368923/websockets-15.0.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:746ee8dba912cd6fc889a8147168991d50ed70447bf18bcda7039f7d2e3d9151", size = 173329, upload-time = "2025-03-05T20:02:39.298Z" }, - { url = "https://files.pythonhosted.org/packages/31/1d/063b25dcc01faa8fada1469bdf769de3768b7044eac9d41f734fd7b6ad6d/websockets-15.0.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:595b6c3969023ecf9041b2936ac3827e4623bfa3ccf007575f04c5a6aa318c22", size = 183111, upload-time = "2025-03-05T20:02:40.595Z" }, - { url = "https://files.pythonhosted.org/packages/93/53/9a87ee494a51bf63e4ec9241c1ccc4f7c2f45fff85d5bde2ff74fcb68b9e/websockets-15.0.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3c714d2fc58b5ca3e285461a4cc0c9a66bd0e24c5da9911e30158286c9b5be7f", size = 182054, upload-time = "2025-03-05T20:02:41.926Z" }, - { url = "https://files.pythonhosted.org/packages/ff/b2/83a6ddf56cdcbad4e3d841fcc55d6ba7d19aeb89c50f24dd7e859ec0805f/websockets-15.0.1-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0f3c1e2ab208db911594ae5b4f79addeb3501604a165019dd221c0bdcabe4db8", size = 182496, upload-time = "2025-03-05T20:02:43.304Z" }, - { url = "https://files.pythonhosted.org/packages/98/41/e7038944ed0abf34c45aa4635ba28136f06052e08fc2168520bb8b25149f/websockets-15.0.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:229cf1d3ca6c1804400b0a9790dc66528e08a6a1feec0d5040e8b9eb14422375", size = 182829, upload-time = "2025-03-05T20:02:48.812Z" }, - { url = "https://files.pythonhosted.org/packages/e0/17/de15b6158680c7623c6ef0db361da965ab25d813ae54fcfeae2e5b9ef910/websockets-15.0.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:756c56e867a90fb00177d530dca4b097dd753cde348448a1012ed6c5131f8b7d", size = 182217, upload-time = "2025-03-05T20:02:50.14Z" }, - { url = "https://files.pythonhosted.org/packages/33/2b/1f168cb6041853eef0362fb9554c3824367c5560cbdaad89ac40f8c2edfc/websockets-15.0.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:558d023b3df0bffe50a04e710bc87742de35060580a293c2a984299ed83bc4e4", size = 182195, upload-time = "2025-03-05T20:02:51.561Z" }, - { url = "https://files.pythonhosted.org/packages/86/eb/20b6cdf273913d0ad05a6a14aed4b9a85591c18a987a3d47f20fa13dcc47/websockets-15.0.1-cp313-cp313-win32.whl", hash = "sha256:ba9e56e8ceeeedb2e080147ba85ffcd5cd0711b89576b83784d8605a7df455fa", size = 176393, upload-time = "2025-03-05T20:02:53.814Z" }, - { url = "https://files.pythonhosted.org/packages/1b/6c/c65773d6cab416a64d191d6ee8a8b1c68a09970ea6909d16965d26bfed1e/websockets-15.0.1-cp313-cp313-win_amd64.whl", hash = "sha256:e09473f095a819042ecb2ab9465aee615bd9c2028e4ef7d933600a8401c79561", size = 176837, upload-time = "2025-03-05T20:02:55.237Z" }, - { url = "https://files.pythonhosted.org/packages/fa/a8/5b41e0da817d64113292ab1f8247140aac61cbf6cfd085d6a0fa77f4984f/websockets-15.0.1-py3-none-any.whl", hash = "sha256:f7a866fbc1e97b5c617ee4116daaa09b722101d4a3c170c787450ba409f9736f", size = 169743, upload-time = "2025-03-05T20:03:39.41Z" }, -] - [[package]] name = "widgetsnbextension" version = "4.0.14" From 78430b0ea50470d12b2f0dd124ba36b33df0fd4e Mon Sep 17 00:00:00 2001 From: Nick Murphy Date: Thu, 31 Jul 2025 14:39:34 -0400 Subject: [PATCH 418/521] Update changelog entries prior to release (#3064) * Add two search and replace fixes * Exclude .pre-commit-search-and-replace.yaml from typos check * Minor changelog updates * Update changelog entries prior to release * Add link to method * Update 3013.doc.rst * Update changelog/2961.internal.rst * Update changelog/2932.doc.rst * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 1 + .pre-commit-search-and-replace.yaml | 6 ++++++ changelog/1643.doc.1.rst | 2 +- changelog/1643.doc.6.rst | 2 +- changelog/2892.doc.rst | 2 +- changelog/2911.breaking.1.rst | 4 ++-- changelog/2911.breaking.2.rst | 4 ++-- changelog/2911.breaking.3.rst | 2 +- changelog/2911.feature.rst | 2 +- changelog/2911.trivial.1.rst | 2 +- changelog/2915.doc.rst | 6 +++--- changelog/2932.doc.rst | 2 +- changelog/2935.doc.rst | 2 +- changelog/2961.internal.rst | 3 ++- changelog/2968.feature.1.rst | 2 ++ changelog/2968.feature.2.rst | 3 +++ changelog/2968.feature.rst | 4 ---- changelog/2974.internal.rst | 2 +- changelog/2981.internal.rst | 2 +- changelog/2997.internal.rst | 2 +- changelog/2998.internal.rst | 2 +- changelog/3013.doc.rst | 2 +- changelog/3024.doc.rst | 2 +- changelog/3032.feature.rst | 2 +- changelog/3034.feature.rst | 4 ++-- changelog/3036.feature.rst | 2 +- changelog/3037.feature.rst | 4 ++-- 27 files changed, 41 insertions(+), 32 deletions(-) create mode 100644 changelog/2968.feature.1.rst create mode 100644 changelog/2968.feature.2.rst delete mode 100644 changelog/2968.feature.rst diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index f0b745169f..15cb5faa15 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -84,6 +84,7 @@ repos: hooks: - id: typos name: typos (add false positives to _typos.toml) + exclude: .pre-commit-search-and-replace.yaml - repo: https://github.com/astral-sh/ruff-pre-commit rev: v0.12.3 diff --git a/.pre-commit-search-and-replace.yaml b/.pre-commit-search-and-replace.yaml index b4c68d5ddc..646931e490 100644 --- a/.pre-commit-search-and-replace.yaml +++ b/.pre-commit-search-and-replace.yaml @@ -71,3 +71,9 @@ - search: /astropy\.unit\./ replacement: 'astropy.units.' + +- search: quantitity + replacement: quantity + +- search: quantitities + replacement: quantities diff --git a/changelog/1643.doc.1.rst b/changelog/1643.doc.1.rst index 9e8882233c..b845c4a749 100644 --- a/changelog/1643.doc.1.rst +++ b/changelog/1643.doc.1.rst @@ -1,2 +1,2 @@ Removed :file:`docs/plasmapy_sphinx` and put `plasmapy_sphinx` into its own -repository, https://github.com/PlasmaPy/plasmapy_sphinx\ . +repository at https://github.com/PlasmaPy/plasmapy_sphinx\ . diff --git a/changelog/1643.doc.6.rst b/changelog/1643.doc.6.rst index 670af13f15..430039de79 100644 --- a/changelog/1643.doc.6.rst +++ b/changelog/1643.doc.6.rst @@ -1,3 +1,3 @@ -Created a GitHub Action (in :file:`weekly.yml` and :file:`noxfile.py`) +Created a GitHub workflow (in :file:`weekly.yml` and :file:`noxfile.py`) to build documentation using the latest development version of `plasmapy_sphinx` on a weekly basis. diff --git a/changelog/2892.doc.rst b/changelog/2892.doc.rst index 48db46fe25..9d94509771 100644 --- a/changelog/2892.doc.rst +++ b/changelog/2892.doc.rst @@ -1 +1 @@ -Removed duplicate section headers for example notebooks in documentation for `plasmapy.formulary`. +Removed duplicate section headers for example notebooks in the documentation for `plasmapy.formulary`. diff --git a/changelog/2911.breaking.1.rst b/changelog/2911.breaking.1.rst index 54fb8e0bbd..f433c7577a 100644 --- a/changelog/2911.breaking.1.rst +++ b/changelog/2911.breaking.1.rst @@ -1,3 +1,3 @@ -|ParticleTracker| no longer takes the keyword ``req_quantities``, but instead automatically requires -quantitities required by the tracker for the given setup. Users wishing to require quantitities +|ParticleTracker| no longer accepts the parameter ``req_quantities``, but instead automatically requires +quantities required by the tracker for the given setup. Users wishing to require quantities may use the method `~plasmapy.plasma.grids.AbstractGrid.require_quantities`. diff --git a/changelog/2911.breaking.2.rst b/changelog/2911.breaking.2.rst index d99d629e1d..ac1f1b8116 100644 --- a/changelog/2911.breaking.2.rst +++ b/changelog/2911.breaking.2.rst @@ -1,4 +1,4 @@ The method `~plasmapy.simulation.particle_tracker.particle_tracker.ParticleTracker.add_stopping` -argument ``I`` must now be a list of `~astropy.units.Quantity` objects rather than a single -`~astropy.units.Quantity` array. This is because ``None`` entries are now also accepted to that +requires that the argument ``I`` must now be a list of |Quantity| objects rather than a single +|Quantity| array. This change is needed because `None` entries are now also accepted to that keyword as placeholders for grids on which stopping will not be applied. diff --git a/changelog/2911.breaking.3.rst b/changelog/2911.breaking.3.rst index cba592317a..c80e8b2128 100644 --- a/changelog/2911.breaking.3.rst +++ b/changelog/2911.breaking.3.rst @@ -1,4 +1,4 @@ Variables in |ParticleTracker| and `~plasmapy.diagnostics.charged_particle_radiography.synthetic_radiography.Tracker` have been updated -such that ``n*`` is now ``num_*``, e.g. ``nparticles`` is now ``num_particles``. Similarly, ``v_init`` is +such that ``n*`` is now ``num_*`` (e.g., ``nparticles`` is now ``num_particles``). Similarly, ``v_init`` is now ``v0`` to be consistent with ``x0``. diff --git a/changelog/2911.feature.rst b/changelog/2911.feature.rst index 9c9fdf407d..7b4b46cfd5 100644 --- a/changelog/2911.feature.rst +++ b/changelog/2911.feature.rst @@ -1,3 +1,3 @@ The new method `~plasmapy.plasma.grids.CartesianGrid.soften_edges` applies an error function mask to the edges of all quantities on a grid. This is useful for any application where the grid must -go to zero smoothly at the edges, e.g. for particle tracking with |ParticleTracker|. +go to zero smoothly at the edges (e.g., for particle tracking with |ParticleTracker|). diff --git a/changelog/2911.trivial.1.rst b/changelog/2911.trivial.1.rst index 283ca48685..7cf79aff95 100644 --- a/changelog/2911.trivial.1.rst +++ b/changelog/2911.trivial.1.rst @@ -1,2 +1,2 @@ -``ax#``, ``dx#`` and ``*_si`` properties of `~plasmapy.plasma.grids.AbstractGrid` are now +The ``ax#``, ``dx#`` and ``*_si`` properties of `~plasmapy.plasma.grids.AbstractGrid` are now cached properties for faster access, since these attributes do not change after the grid has been initialized. diff --git a/changelog/2915.doc.rst b/changelog/2915.doc.rst index e1eb2afc41..39d91c6220 100644 --- a/changelog/2915.doc.rst +++ b/changelog/2915.doc.rst @@ -1,4 +1,4 @@ Fixed references to the ``astropy.units.equivalencies`` module in the docs. Astropy now considers -this file to be private API, and wants its contents imported through the ``units`` module namespace, -which broke PlasmaPy's intersphinx links. This PR changes those links to a direct URL to the page in the -astropy docs: |Astropy Equivalencies|. +this file to be private API (which broke PlasmaPy's intersphinx links), and +recommends that its contents be imported through the `astropy.units` namespace. +This pull request changes those links to a direct URL to |Astropy Equivalencies|. diff --git a/changelog/2932.doc.rst b/changelog/2932.doc.rst index aba2223f69..f71c94fbfe 100644 --- a/changelog/2932.doc.rst +++ b/changelog/2932.doc.rst @@ -1 +1 @@ -Added a sentence to introduce what a dispersion relation is and why it's useful. +Added a sentence to the documentation for `plasmapy.dispersion` to describe dispersion relations and their usefulness. diff --git a/changelog/2935.doc.rst b/changelog/2935.doc.rst index c7e0b7287a..f92d54631f 100644 --- a/changelog/2935.doc.rst +++ b/changelog/2935.doc.rst @@ -1 +1 @@ -Updated how to access test results and documentation previews in the |contributor guide| after recent changes to GitHub's user interface. +Updated the instructions for accessing test results and documentation previews in the |contributor guide| after recent changes to GitHub's user interface. diff --git a/changelog/2961.internal.rst b/changelog/2961.internal.rst index 26dd965ef5..b616afeca8 100644 --- a/changelog/2961.internal.rst +++ b/changelog/2961.internal.rst @@ -1 +1,2 @@ -Enabled :file:`noxfile.py` to be run as a script, in alignment with :pep:`723`. +Enabled :file:`noxfile.py` to be run as a script. +The commands ``python noxfile.py -s 'tests-3.13(all)'`` and ``nox -s 'tests-3.13(all)'`` can now both be used to run all tests for Python 3.13. diff --git a/changelog/2968.feature.1.rst b/changelog/2968.feature.1.rst new file mode 100644 index 0000000000..91cb360471 --- /dev/null +++ b/changelog/2968.feature.1.rst @@ -0,0 +1,2 @@ +Added the ``detector_vdir`` keyword to `~plasmapy.diagnostics.charged_particle_radiography.synthetic_radiography.Tracker` +to explicitly define the detector's vertical surface vector. diff --git a/changelog/2968.feature.2.rst b/changelog/2968.feature.2.rst new file mode 100644 index 0000000000..48a243cbd5 --- /dev/null +++ b/changelog/2968.feature.2.rst @@ -0,0 +1,3 @@ +Added the ``source_vdir`` keyword to the `~plasmapy.diagnostics.charged_particle_radiography.synthetic_radiography.Tracker.create_particles` +method of `~plasmapy.diagnostics.charged_particle_radiography.synthetic_radiography.Tracker` to explicitly define the +orientation of the mean velocity of the source particles. diff --git a/changelog/2968.feature.rst b/changelog/2968.feature.rst deleted file mode 100644 index fb91b2ab73..0000000000 --- a/changelog/2968.feature.rst +++ /dev/null @@ -1,4 +0,0 @@ -Added the ``detector_vdir`` keyword to `~plasmapy.diagnostics.charged_particle_radiography.synthetic_radiography.Tracker` -to explicitly define the detector's vertical surface vector. Added the ``source_vdir`` keyword to the ``create_particles`` -method of `~plasmapy.diagnostics.charged_particle_radiography.synthetic_radiography.Tracker` to explicitly define the -orientation of the mean velocity of the source particles. diff --git a/changelog/2974.internal.rst b/changelog/2974.internal.rst index f2419577af..ed3a1ad769 100644 --- a/changelog/2974.internal.rst +++ b/changelog/2974.internal.rst @@ -1 +1 @@ -Enabled ``pyproject-fmt`` as an autoformatter and ``validate-pyproject`` as a validator for :file:`pyproject.toml`. +Enabled ``pyproject-fmt`` as an autoformatter and ``validate-pyproject`` as a validator for :file:`pyproject.toml` via |pre-commit|. diff --git a/changelog/2981.internal.rst b/changelog/2981.internal.rst index 3039d42e76..34fd0496d7 100644 --- a/changelog/2981.internal.rst +++ b/changelog/2981.internal.rst @@ -1 +1 @@ -Enabled a ``pre-commit`` hook for ``mdformat`` to automatically format GitHub-flavored Markdown files. +Enabled a |pre-commit| hook for ``mdformat`` to automatically format GitHub-flavored Markdown files. diff --git a/changelog/2997.internal.rst b/changelog/2997.internal.rst index 8114301178..b34f7f8d3d 100644 --- a/changelog/2997.internal.rst +++ b/changelog/2997.internal.rst @@ -1,3 +1,3 @@ -Updated :file:`.gitignore` to put content that is custom or PlasmaPy-specific +Reorganized :file:`.gitignore` to put content that is custom or PlasmaPy-specific at the top of the file, followed by content adapted from :file:`.gitignore` templates at the bottom. diff --git a/changelog/2998.internal.rst b/changelog/2998.internal.rst index e6a8da9aea..7bc0e273ef 100644 --- a/changelog/2998.internal.rst +++ b/changelog/2998.internal.rst @@ -1 +1 @@ -Set ``uv`` as the sole backend to Nox, and changed the ``docs`` and ``tests`` dependency sets to include ``nox[uv]`` instead of ``nox``. +Set |uv| as the sole backend to Nox, and changed the ``docs`` and ``tests`` dependency sets to include ``nox[uv]`` instead of ``nox``. diff --git a/changelog/3013.doc.rst b/changelog/3013.doc.rst index 414fb1ad30..7becef25b8 100644 --- a/changelog/3013.doc.rst +++ b/changelog/3013.doc.rst @@ -1 +1 @@ -Put office hours an an indefinite hiatus due to the conclusion of the NSF award supporting the development of PlasmaPy. +Put office hours an an indefinite hiatus due to the conclusion of the NSF collaborative awards supporting the development and growth of PlasmaPy. diff --git a/changelog/3024.doc.rst b/changelog/3024.doc.rst index 189678920b..de76d23c0e 100644 --- a/changelog/3024.doc.rst +++ b/changelog/3024.doc.rst @@ -1 +1 @@ -Removed the `sphinx-hoverxref `_ |Sphinx| extension, since it has been deprecated in favor of the Read the Docs addon `Link Previews `_\ . +Removed the `sphinx-hoverxref `_ |Sphinx| extension, since it has been deprecated in favor of the |Read the Docs| add-on for `Link Previews `_\ . diff --git a/changelog/3032.feature.rst b/changelog/3032.feature.rst index b920e16ce3..e28ded4fc3 100644 --- a/changelog/3032.feature.rst +++ b/changelog/3032.feature.rst @@ -1 +1 @@ -Added the second function to `plasmapy.formulary.laser`, `~plasmapy.formulary.laser.intensity`, which calculates intensity from the electric field amplitude. +Added `plasmapy.formulary.laser.intensity` to calculate intensity from the electric field amplitude for a laser. diff --git a/changelog/3034.feature.rst b/changelog/3034.feature.rst index 38f150ade6..32c7b1b62f 100644 --- a/changelog/3034.feature.rst +++ b/changelog/3034.feature.rst @@ -1,4 +1,4 @@ .. currentmodule:: plasmapy.analysis.swept_langmuir -Added helper function `~helpers.sort_sweep_arrays` to the -`~plasmapy.analysis.swept_langmuir` module. +Added helper function `~helpers.sort_sweep_arrays` to +`plasmapy.analysis.swept_langmuir`. diff --git a/changelog/3036.feature.rst b/changelog/3036.feature.rst index 26ccc29a04..34c510a353 100644 --- a/changelog/3036.feature.rst +++ b/changelog/3036.feature.rst @@ -1 +1 @@ -Added functions for calculating `~plasmapy.formulary.laser.em_wavelength` from `~plasmapy.formulary.laser.em_angular_frequency` and vice versa, `~plasmapy.formulary.laser.Gaussian_beam_waist_radius` from `~plasmapy.formulary.laser.Gaussian_spot_size_FWHM` and vice versa, `~plasmapy.formulary.laser.Gaussian_power`, `~plasmapy.formulary.laser.Gaussian_Rayleigh_length`, and `~plasmapy.formulary.laser.normalized_vector_potential` to `plasmapy.formulary.laser`. +Added `~plasmapy.formulary.laser.em_wavelength`, `~plasmapy.formulary.laser.em_angular_frequency`, `~plasmapy.formulary.laser.Gaussian_beam_waist_radius`, `~plasmapy.formulary.laser.Gaussian_spot_size_FWHM`, `~plasmapy.formulary.laser.Gaussian_power`, `~plasmapy.formulary.laser.Gaussian_Rayleigh_length`, and `~plasmapy.formulary.laser.normalized_vector_potential` to `plasmapy.formulary.laser`. diff --git a/changelog/3037.feature.rst b/changelog/3037.feature.rst index 0b4bbb42aa..af8126a8f9 100644 --- a/changelog/3037.feature.rst +++ b/changelog/3037.feature.rst @@ -1,4 +1,4 @@ .. currentmodule:: plasmapy.analysis.swept_langmuir -Added helper function `~helpers.merge_voltage_clusters` to the -`~plasmapy.analysis.swept_langmuir` analysis module. +Added helper function `~helpers.merge_voltage_clusters` to +`plasmapy.analysis.swept_langmuir`. From d3a9e001d025a822b6e18ea0f76df449ff25b100 Mon Sep 17 00:00:00 2001 From: Nick Murphy Date: Thu, 31 Jul 2025 14:45:34 -0400 Subject: [PATCH 419/521] Make `plasmapy_sphinx` solely a `docs` dependency (#3066) * Remove plasmapy_sphinx as hard dependency * Update version of plasmapy-sphinx in docs dependency set * nox -s requirements --- pyproject.toml | 4 +-- uv.lock | 79 +++++++++++++++++++++++++++++++------------------- 2 files changed, 50 insertions(+), 33 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 1a8ee65239..0e972f1397 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -65,7 +65,6 @@ dependencies = [ "numpy>=1.24", "packaging>=22", "pandas>=2", - "plasmapy-sphinx>=2025.5.1", "requests>=2.28", "scipy>=1.10", "setuptools>=66", @@ -86,7 +85,7 @@ optional-dependencies.docs = [ "nox[uv]>=2025.5.1", "numpydoc>=1.7", "pillow>=10.4", - "plasmapy-sphinx>=0.2.0b1", + "plasmapy-sphinx>=2025.5.1", "pygments==2.18", "sphinx>=8.2.3", "sphinx-changelog>=1.5", @@ -153,7 +152,6 @@ extend-exclude = [ ".jupyter", "__pycache__", "_dev", - "docs/plasmapy_sphinx", ] show-fixes = true diff --git a/uv.lock b/uv.lock index b1f63ff877..bf5f224c7b 100644 --- a/uv.lock +++ b/uv.lock @@ -986,7 +986,7 @@ wheels = [ [[package]] name = "matplotlib" -version = "3.10.3" +version = "3.10.5" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "contourpy" }, @@ -999,32 +999,53 @@ dependencies = [ { name = "pyparsing" }, { name = "python-dateutil" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/26/91/d49359a21893183ed2a5b6c76bec40e0b1dcbf8ca148f864d134897cfc75/matplotlib-3.10.3.tar.gz", hash = "sha256:2f82d2c5bb7ae93aaaa4cd42aca65d76ce6376f83304fa3a630b569aca274df0", size = 34799811, upload-time = "2025-05-08T19:10:54.39Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/f5/bd/af9f655456f60fe1d575f54fb14704ee299b16e999704817a7645dfce6b0/matplotlib-3.10.3-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:0ef061f74cd488586f552d0c336b2f078d43bc00dc473d2c3e7bfee2272f3fa8", size = 8178873, upload-time = "2025-05-08T19:09:53.857Z" }, - { url = "https://files.pythonhosted.org/packages/c2/86/e1c86690610661cd716eda5f9d0b35eaf606ae6c9b6736687cfc8f2d0cd8/matplotlib-3.10.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d96985d14dc5f4a736bbea4b9de9afaa735f8a0fc2ca75be2fa9e96b2097369d", size = 8052205, upload-time = "2025-05-08T19:09:55.684Z" }, - { url = "https://files.pythonhosted.org/packages/54/51/a9f8e49af3883dacddb2da1af5fca1f7468677f1188936452dd9aaaeb9ed/matplotlib-3.10.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7c5f0283da91e9522bdba4d6583ed9d5521566f63729ffb68334f86d0bb98049", size = 8465823, upload-time = "2025-05-08T19:09:57.442Z" }, - { url = "https://files.pythonhosted.org/packages/e7/e3/c82963a3b86d6e6d5874cbeaa390166458a7f1961bab9feb14d3d1a10f02/matplotlib-3.10.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fdfa07c0ec58035242bc8b2c8aae37037c9a886370eef6850703d7583e19964b", size = 8606464, upload-time = "2025-05-08T19:09:59.471Z" }, - { url = "https://files.pythonhosted.org/packages/0e/34/24da1027e7fcdd9e82da3194c470143c551852757a4b473a09a012f5b945/matplotlib-3.10.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:c0b9849a17bce080a16ebcb80a7b714b5677d0ec32161a2cc0a8e5a6030ae220", size = 9413103, upload-time = "2025-05-08T19:10:03.208Z" }, - { url = "https://files.pythonhosted.org/packages/a6/da/948a017c3ea13fd4a97afad5fdebe2f5bbc4d28c0654510ce6fd6b06b7bd/matplotlib-3.10.3-cp311-cp311-win_amd64.whl", hash = "sha256:eef6ed6c03717083bc6d69c2d7ee8624205c29a8e6ea5a31cd3492ecdbaee1e1", size = 8065492, upload-time = "2025-05-08T19:10:05.271Z" }, - { url = "https://files.pythonhosted.org/packages/eb/43/6b80eb47d1071f234ef0c96ca370c2ca621f91c12045f1401b5c9b28a639/matplotlib-3.10.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:0ab1affc11d1f495ab9e6362b8174a25afc19c081ba5b0775ef00533a4236eea", size = 8179689, upload-time = "2025-05-08T19:10:07.602Z" }, - { url = "https://files.pythonhosted.org/packages/0f/70/d61a591958325c357204870b5e7b164f93f2a8cca1dc6ce940f563909a13/matplotlib-3.10.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2a818d8bdcafa7ed2eed74487fdb071c09c1ae24152d403952adad11fa3c65b4", size = 8050466, upload-time = "2025-05-08T19:10:09.383Z" }, - { url = "https://files.pythonhosted.org/packages/e7/75/70c9d2306203148cc7902a961240c5927dd8728afedf35e6a77e105a2985/matplotlib-3.10.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:748ebc3470c253e770b17d8b0557f0aa85cf8c63fd52f1a61af5b27ec0b7ffee", size = 8456252, upload-time = "2025-05-08T19:10:11.958Z" }, - { url = "https://files.pythonhosted.org/packages/c4/91/ba0ae1ff4b3f30972ad01cd4a8029e70a0ec3b8ea5be04764b128b66f763/matplotlib-3.10.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ed70453fd99733293ace1aec568255bc51c6361cb0da94fa5ebf0649fdb2150a", size = 8601321, upload-time = "2025-05-08T19:10:14.47Z" }, - { url = "https://files.pythonhosted.org/packages/d2/88/d636041eb54a84b889e11872d91f7cbf036b3b0e194a70fa064eb8b04f7a/matplotlib-3.10.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:dbed9917b44070e55640bd13419de83b4c918e52d97561544814ba463811cbc7", size = 9406972, upload-time = "2025-05-08T19:10:16.569Z" }, - { url = "https://files.pythonhosted.org/packages/b1/79/0d1c165eac44405a86478082e225fce87874f7198300bbebc55faaf6d28d/matplotlib-3.10.3-cp312-cp312-win_amd64.whl", hash = "sha256:cf37d8c6ef1a48829443e8ba5227b44236d7fcaf7647caa3178a4ff9f7a5be05", size = 8067954, upload-time = "2025-05-08T19:10:18.663Z" }, - { url = "https://files.pythonhosted.org/packages/3b/c1/23cfb566a74c696a3b338d8955c549900d18fe2b898b6e94d682ca21e7c2/matplotlib-3.10.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:9f2efccc8dcf2b86fc4ee849eea5dcaecedd0773b30f47980dc0cbeabf26ec84", size = 8180318, upload-time = "2025-05-08T19:10:20.426Z" }, - { url = "https://files.pythonhosted.org/packages/6c/0c/02f1c3b66b30da9ee343c343acbb6251bef5b01d34fad732446eaadcd108/matplotlib-3.10.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:3ddbba06a6c126e3301c3d272a99dcbe7f6c24c14024e80307ff03791a5f294e", size = 8051132, upload-time = "2025-05-08T19:10:22.569Z" }, - { url = "https://files.pythonhosted.org/packages/b4/ab/8db1a5ac9b3a7352fb914133001dae889f9fcecb3146541be46bed41339c/matplotlib-3.10.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:748302b33ae9326995b238f606e9ed840bf5886ebafcb233775d946aa8107a15", size = 8457633, upload-time = "2025-05-08T19:10:24.749Z" }, - { url = "https://files.pythonhosted.org/packages/f5/64/41c4367bcaecbc03ef0d2a3ecee58a7065d0a36ae1aa817fe573a2da66d4/matplotlib-3.10.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a80fcccbef63302c0efd78042ea3c2436104c5b1a4d3ae20f864593696364ac7", size = 8601031, upload-time = "2025-05-08T19:10:27.03Z" }, - { url = "https://files.pythonhosted.org/packages/12/6f/6cc79e9e5ab89d13ed64da28898e40fe5b105a9ab9c98f83abd24e46d7d7/matplotlib-3.10.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:55e46cbfe1f8586adb34f7587c3e4f7dedc59d5226719faf6cb54fc24f2fd52d", size = 9406988, upload-time = "2025-05-08T19:10:29.056Z" }, - { url = "https://files.pythonhosted.org/packages/b1/0f/eed564407bd4d935ffabf561ed31099ed609e19287409a27b6d336848653/matplotlib-3.10.3-cp313-cp313-win_amd64.whl", hash = "sha256:151d89cb8d33cb23345cd12490c76fd5d18a56581a16d950b48c6ff19bb2ab93", size = 8068034, upload-time = "2025-05-08T19:10:31.221Z" }, - { url = "https://files.pythonhosted.org/packages/3e/e5/2f14791ff69b12b09e9975e1d116d9578ac684460860ce542c2588cb7a1c/matplotlib-3.10.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:c26dd9834e74d164d06433dc7be5d75a1e9890b926b3e57e74fa446e1a62c3e2", size = 8218223, upload-time = "2025-05-08T19:10:33.114Z" }, - { url = "https://files.pythonhosted.org/packages/5c/08/30a94afd828b6e02d0a52cae4a29d6e9ccfcf4c8b56cc28b021d3588873e/matplotlib-3.10.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:24853dad5b8c84c8c2390fc31ce4858b6df504156893292ce8092d190ef8151d", size = 8094985, upload-time = "2025-05-08T19:10:35.337Z" }, - { url = "https://files.pythonhosted.org/packages/89/44/f3bc6b53066c889d7a1a3ea8094c13af6a667c5ca6220ec60ecceec2dabe/matplotlib-3.10.3-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:68f7878214d369d7d4215e2a9075fef743be38fa401d32e6020bab2dfabaa566", size = 8483109, upload-time = "2025-05-08T19:10:37.611Z" }, - { url = "https://files.pythonhosted.org/packages/ba/c7/473bc559beec08ebee9f86ca77a844b65747e1a6c2691e8c92e40b9f42a8/matplotlib-3.10.3-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f6929fc618cb6db9cb75086f73b3219bbb25920cb24cee2ea7a12b04971a4158", size = 8618082, upload-time = "2025-05-08T19:10:39.892Z" }, - { url = "https://files.pythonhosted.org/packages/d8/e9/6ce8edd264c8819e37bbed8172e0ccdc7107fe86999b76ab5752276357a4/matplotlib-3.10.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:6c7818292a5cc372a2dc4c795e5c356942eb8350b98ef913f7fda51fe175ac5d", size = 9413699, upload-time = "2025-05-08T19:10:42.376Z" }, - { url = "https://files.pythonhosted.org/packages/1b/92/9a45c91089c3cf690b5badd4be81e392ff086ccca8a1d4e3a08463d8a966/matplotlib-3.10.3-cp313-cp313t-win_amd64.whl", hash = "sha256:4f23ffe95c5667ef8a2b56eea9b53db7f43910fa4a2d5472ae0f72b64deab4d5", size = 8139044, upload-time = "2025-05-08T19:10:44.551Z" }, +sdist = { url = "https://files.pythonhosted.org/packages/43/91/f2939bb60b7ebf12478b030e0d7f340247390f402b3b189616aad790c366/matplotlib-3.10.5.tar.gz", hash = "sha256:352ed6ccfb7998a00881692f38b4ca083c691d3e275b4145423704c34c909076", size = 34804044, upload-time = "2025-07-31T18:09:33.805Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/aa/c7/1f2db90a1d43710478bb1e9b57b162852f79234d28e4f48a28cc415aa583/matplotlib-3.10.5-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:dcfc39c452c6a9f9028d3e44d2d721484f665304857188124b505b2c95e1eecf", size = 8239216, upload-time = "2025-07-31T18:07:51.947Z" }, + { url = "https://files.pythonhosted.org/packages/82/6d/ca6844c77a4f89b1c9e4d481c412e1d1dbabf2aae2cbc5aa2da4a1d6683e/matplotlib-3.10.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:903352681b59f3efbf4546985142a9686ea1d616bb054b09a537a06e4b892ccf", size = 8102130, upload-time = "2025-07-31T18:07:53.65Z" }, + { url = "https://files.pythonhosted.org/packages/1d/1e/5e187a30cc673a3e384f3723e5f3c416033c1d8d5da414f82e4e731128ea/matplotlib-3.10.5-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:080c3676a56b8ee1c762bcf8fca3fe709daa1ee23e6ef06ad9f3fc17332f2d2a", size = 8666471, upload-time = "2025-07-31T18:07:55.304Z" }, + { url = "https://files.pythonhosted.org/packages/03/c0/95540d584d7d645324db99a845ac194e915ef75011a0d5e19e1b5cee7e69/matplotlib-3.10.5-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4b4984d5064a35b6f66d2c11d668565f4389b1119cc64db7a4c1725bc11adffc", size = 9500518, upload-time = "2025-07-31T18:07:57.199Z" }, + { url = "https://files.pythonhosted.org/packages/ba/2e/e019352099ea58b4169adb9c6e1a2ad0c568c6377c2b677ee1f06de2adc7/matplotlib-3.10.5-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:3967424121d3a46705c9fa9bdb0931de3228f13f73d7bb03c999c88343a89d89", size = 9552372, upload-time = "2025-07-31T18:07:59.41Z" }, + { url = "https://files.pythonhosted.org/packages/b7/81/3200b792a5e8b354f31f4101ad7834743ad07b6d620259f2059317b25e4d/matplotlib-3.10.5-cp311-cp311-win_amd64.whl", hash = "sha256:33775bbeb75528555a15ac29396940128ef5613cf9a2d31fb1bfd18b3c0c0903", size = 8100634, upload-time = "2025-07-31T18:08:01.801Z" }, + { url = "https://files.pythonhosted.org/packages/52/46/a944f6f0c1f5476a0adfa501969d229ce5ae60cf9a663be0e70361381f89/matplotlib-3.10.5-cp311-cp311-win_arm64.whl", hash = "sha256:c61333a8e5e6240e73769d5826b9a31d8b22df76c0778f8480baf1b4b01c9420", size = 7978880, upload-time = "2025-07-31T18:08:03.407Z" }, + { url = "https://files.pythonhosted.org/packages/66/1e/c6f6bcd882d589410b475ca1fc22e34e34c82adff519caf18f3e6dd9d682/matplotlib-3.10.5-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:00b6feadc28a08bd3c65b2894f56cf3c94fc8f7adcbc6ab4516ae1e8ed8f62e2", size = 8253056, upload-time = "2025-07-31T18:08:05.385Z" }, + { url = "https://files.pythonhosted.org/packages/53/e6/d6f7d1b59413f233793dda14419776f5f443bcccb2dfc84b09f09fe05dbe/matplotlib-3.10.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ee98a5c5344dc7f48dc261b6ba5d9900c008fc12beb3fa6ebda81273602cc389", size = 8110131, upload-time = "2025-07-31T18:08:07.293Z" }, + { url = "https://files.pythonhosted.org/packages/66/2b/bed8a45e74957549197a2ac2e1259671cd80b55ed9e1fe2b5c94d88a9202/matplotlib-3.10.5-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:a17e57e33de901d221a07af32c08870ed4528db0b6059dce7d7e65c1122d4bea", size = 8669603, upload-time = "2025-07-31T18:08:09.064Z" }, + { url = "https://files.pythonhosted.org/packages/7e/a7/315e9435b10d057f5e52dfc603cd353167ae28bb1a4e033d41540c0067a4/matplotlib-3.10.5-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:97b9d6443419085950ee4a5b1ee08c363e5c43d7176e55513479e53669e88468", size = 9508127, upload-time = "2025-07-31T18:08:10.845Z" }, + { url = "https://files.pythonhosted.org/packages/7f/d9/edcbb1f02ca99165365d2768d517898c22c6040187e2ae2ce7294437c413/matplotlib-3.10.5-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ceefe5d40807d29a66ae916c6a3915d60ef9f028ce1927b84e727be91d884369", size = 9566926, upload-time = "2025-07-31T18:08:13.186Z" }, + { url = "https://files.pythonhosted.org/packages/3b/d9/6dd924ad5616c97b7308e6320cf392c466237a82a2040381163b7500510a/matplotlib-3.10.5-cp312-cp312-win_amd64.whl", hash = "sha256:c04cba0f93d40e45b3c187c6c52c17f24535b27d545f757a2fffebc06c12b98b", size = 8107599, upload-time = "2025-07-31T18:08:15.116Z" }, + { url = "https://files.pythonhosted.org/packages/0e/f3/522dc319a50f7b0279fbe74f86f7a3506ce414bc23172098e8d2bdf21894/matplotlib-3.10.5-cp312-cp312-win_arm64.whl", hash = "sha256:a41bcb6e2c8e79dc99c5511ae6f7787d2fb52efd3d805fff06d5d4f667db16b2", size = 7978173, upload-time = "2025-07-31T18:08:21.518Z" }, + { url = "https://files.pythonhosted.org/packages/8d/05/4f3c1f396075f108515e45cb8d334aff011a922350e502a7472e24c52d77/matplotlib-3.10.5-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:354204db3f7d5caaa10e5de74549ef6a05a4550fdd1c8f831ab9bca81efd39ed", size = 8253586, upload-time = "2025-07-31T18:08:23.107Z" }, + { url = "https://files.pythonhosted.org/packages/2f/2c/e084415775aac7016c3719fe7006cdb462582c6c99ac142f27303c56e243/matplotlib-3.10.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:b072aac0c3ad563a2b3318124756cb6112157017f7431626600ecbe890df57a1", size = 8110715, upload-time = "2025-07-31T18:08:24.675Z" }, + { url = "https://files.pythonhosted.org/packages/52/1b/233e3094b749df16e3e6cd5a44849fd33852e692ad009cf7de00cf58ddf6/matplotlib-3.10.5-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d52fd5b684d541b5a51fb276b2b97b010c75bee9aa392f96b4a07aeb491e33c7", size = 8669397, upload-time = "2025-07-31T18:08:26.778Z" }, + { url = "https://files.pythonhosted.org/packages/e8/ec/03f9e003a798f907d9f772eed9b7c6a9775d5bd00648b643ebfb88e25414/matplotlib-3.10.5-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ee7a09ae2f4676276f5a65bd9f2bd91b4f9fbaedf49f40267ce3f9b448de501f", size = 9508646, upload-time = "2025-07-31T18:08:28.848Z" }, + { url = "https://files.pythonhosted.org/packages/91/e7/c051a7a386680c28487bca27d23b02d84f63e3d2a9b4d2fc478e6a42e37e/matplotlib-3.10.5-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ba6c3c9c067b83481d647af88b4e441d532acdb5ef22178a14935b0b881188f4", size = 9567424, upload-time = "2025-07-31T18:08:30.726Z" }, + { url = "https://files.pythonhosted.org/packages/36/c2/24302e93ff431b8f4173ee1dd88976c8d80483cadbc5d3d777cef47b3a1c/matplotlib-3.10.5-cp313-cp313-win_amd64.whl", hash = "sha256:07442d2692c9bd1cceaa4afb4bbe5b57b98a7599de4dabfcca92d3eea70f9ebe", size = 8107809, upload-time = "2025-07-31T18:08:33.928Z" }, + { url = "https://files.pythonhosted.org/packages/0b/33/423ec6a668d375dad825197557ed8fbdb74d62b432c1ed8235465945475f/matplotlib-3.10.5-cp313-cp313-win_arm64.whl", hash = "sha256:48fe6d47380b68a37ccfcc94f009530e84d41f71f5dae7eda7c4a5a84aa0a674", size = 7978078, upload-time = "2025-07-31T18:08:36.764Z" }, + { url = "https://files.pythonhosted.org/packages/51/17/521fc16ec766455c7bb52cc046550cf7652f6765ca8650ff120aa2d197b6/matplotlib-3.10.5-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:3b80eb8621331449fc519541a7461987f10afa4f9cfd91afcd2276ebe19bd56c", size = 8295590, upload-time = "2025-07-31T18:08:38.521Z" }, + { url = "https://files.pythonhosted.org/packages/f8/12/23c28b2c21114c63999bae129fce7fd34515641c517ae48ce7b7dcd33458/matplotlib-3.10.5-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:47a388908e469d6ca2a6015858fa924e0e8a2345a37125948d8e93a91c47933e", size = 8158518, upload-time = "2025-07-31T18:08:40.195Z" }, + { url = "https://files.pythonhosted.org/packages/81/f8/aae4eb25e8e7190759f3cb91cbeaa344128159ac92bb6b409e24f8711f78/matplotlib-3.10.5-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:8b6b49167d208358983ce26e43aa4196073b4702858670f2eb111f9a10652b4b", size = 8691815, upload-time = "2025-07-31T18:08:42.238Z" }, + { url = "https://files.pythonhosted.org/packages/d0/ba/450c39ebdd486bd33a359fc17365ade46c6a96bf637bbb0df7824de2886c/matplotlib-3.10.5-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8a8da0453a7fd8e3da114234ba70c5ba9ef0e98f190309ddfde0f089accd46ea", size = 9522814, upload-time = "2025-07-31T18:08:44.914Z" }, + { url = "https://files.pythonhosted.org/packages/89/11/9c66f6a990e27bb9aa023f7988d2d5809cb98aa39c09cbf20fba75a542ef/matplotlib-3.10.5-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:52c6573dfcb7726a9907b482cd5b92e6b5499b284ffacb04ffbfe06b3e568124", size = 9573917, upload-time = "2025-07-31T18:08:47.038Z" }, + { url = "https://files.pythonhosted.org/packages/b3/69/8b49394de92569419e5e05e82e83df9b749a0ff550d07631ea96ed2eb35a/matplotlib-3.10.5-cp313-cp313t-win_amd64.whl", hash = "sha256:a23193db2e9d64ece69cac0c8231849db7dd77ce59c7b89948cf9d0ce655a3ce", size = 8181034, upload-time = "2025-07-31T18:08:48.943Z" }, + { url = "https://files.pythonhosted.org/packages/47/23/82dc435bb98a2fc5c20dffcac8f0b083935ac28286413ed8835df40d0baa/matplotlib-3.10.5-cp313-cp313t-win_arm64.whl", hash = "sha256:56da3b102cf6da2776fef3e71cd96fcf22103a13594a18ac9a9b31314e0be154", size = 8023337, upload-time = "2025-07-31T18:08:50.791Z" }, + { url = "https://files.pythonhosted.org/packages/ac/e0/26b6cfde31f5383503ee45dcb7e691d45dadf0b3f54639332b59316a97f8/matplotlib-3.10.5-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:96ef8f5a3696f20f55597ffa91c28e2e73088df25c555f8d4754931515512715", size = 8253591, upload-time = "2025-07-31T18:08:53.254Z" }, + { url = "https://files.pythonhosted.org/packages/c1/89/98488c7ef7ea20ea659af7499628c240a608b337af4be2066d644cfd0a0f/matplotlib-3.10.5-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:77fab633e94b9da60512d4fa0213daeb76d5a7b05156840c4fd0399b4b818837", size = 8112566, upload-time = "2025-07-31T18:08:55.116Z" }, + { url = "https://files.pythonhosted.org/packages/52/67/42294dfedc82aea55e1a767daf3263aacfb5a125f44ba189e685bab41b6f/matplotlib-3.10.5-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:27f52634315e96b1debbfdc5c416592edcd9c4221bc2f520fd39c33db5d9f202", size = 9513281, upload-time = "2025-07-31T18:08:56.885Z" }, + { url = "https://files.pythonhosted.org/packages/e7/68/f258239e0cf34c2cbc816781c7ab6fca768452e6bf1119aedd2bd4a882a3/matplotlib-3.10.5-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:525f6e28c485c769d1f07935b660c864de41c37fd716bfa64158ea646f7084bb", size = 9780873, upload-time = "2025-07-31T18:08:59.241Z" }, + { url = "https://files.pythonhosted.org/packages/89/64/f4881554006bd12e4558bd66778bdd15d47b00a1f6c6e8b50f6208eda4b3/matplotlib-3.10.5-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:1f5f3ec4c191253c5f2b7c07096a142c6a1c024d9f738247bfc8e3f9643fc975", size = 9568954, upload-time = "2025-07-31T18:09:01.244Z" }, + { url = "https://files.pythonhosted.org/packages/06/f8/42779d39c3f757e1f012f2dda3319a89fb602bd2ef98ce8faf0281f4febd/matplotlib-3.10.5-cp314-cp314-win_amd64.whl", hash = "sha256:707f9c292c4cd4716f19ab8a1f93f26598222cd931e0cd98fbbb1c5994bf7667", size = 8237465, upload-time = "2025-07-31T18:09:03.206Z" }, + { url = "https://files.pythonhosted.org/packages/cf/f8/153fd06b5160f0cd27c8b9dd797fcc9fb56ac6a0ebf3c1f765b6b68d3c8a/matplotlib-3.10.5-cp314-cp314-win_arm64.whl", hash = "sha256:21a95b9bf408178d372814de7baacd61c712a62cae560b5e6f35d791776f6516", size = 8108898, upload-time = "2025-07-31T18:09:05.231Z" }, + { url = "https://files.pythonhosted.org/packages/9a/ee/c4b082a382a225fe0d2a73f1f57cf6f6f132308805b493a54c8641006238/matplotlib-3.10.5-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:a6b310f95e1102a8c7c817ef17b60ee5d1851b8c71b63d9286b66b177963039e", size = 8295636, upload-time = "2025-07-31T18:09:07.306Z" }, + { url = "https://files.pythonhosted.org/packages/30/73/2195fa2099718b21a20da82dfc753bf2af58d596b51aefe93e359dd5915a/matplotlib-3.10.5-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:94986a242747a0605cb3ff1cb98691c736f28a59f8ffe5175acaeb7397c49a5a", size = 8158575, upload-time = "2025-07-31T18:09:09.083Z" }, + { url = "https://files.pythonhosted.org/packages/f6/e9/a08cdb34618a91fa08f75e6738541da5cacde7c307cea18ff10f0d03fcff/matplotlib-3.10.5-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1ff10ea43288f0c8bab608a305dc6c918cc729d429c31dcbbecde3b9f4d5b569", size = 9522815, upload-time = "2025-07-31T18:09:11.191Z" }, + { url = "https://files.pythonhosted.org/packages/4e/bb/34d8b7e0d1bb6d06ef45db01dfa560d5a67b1c40c0b998ce9ccde934bb09/matplotlib-3.10.5-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f6adb644c9d040ffb0d3434e440490a66cf73dbfa118a6f79cd7568431f7a012", size = 9783514, upload-time = "2025-07-31T18:09:13.307Z" }, + { url = "https://files.pythonhosted.org/packages/12/09/d330d1e55dcca2e11b4d304cc5227f52e2512e46828d6249b88e0694176e/matplotlib-3.10.5-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:4fa40a8f98428f789a9dcacd625f59b7bc4e3ef6c8c7c80187a7a709475cf592", size = 9573932, upload-time = "2025-07-31T18:09:15.335Z" }, + { url = "https://files.pythonhosted.org/packages/eb/3b/f70258ac729aa004aca673800a53a2b0a26d49ca1df2eaa03289a1c40f81/matplotlib-3.10.5-cp314-cp314t-win_amd64.whl", hash = "sha256:95672a5d628b44207aab91ec20bf59c26da99de12b88f7e0b1fb0a84a86ff959", size = 8322003, upload-time = "2025-07-31T18:09:17.416Z" }, + { url = "https://files.pythonhosted.org/packages/5b/60/3601f8ce6d76a7c81c7f25a0e15fde0d6b66226dd187aa6d2838e6374161/matplotlib-3.10.5-cp314-cp314t-win_arm64.whl", hash = "sha256:2efaf97d72629e74252e0b5e3c46813e9eeaa94e011ecf8084a971a31a97f40b", size = 8153849, upload-time = "2025-07-31T18:09:19.673Z" }, + { url = "https://files.pythonhosted.org/packages/dc/d6/e921be4e1a5f7aca5194e1f016cb67ec294548e530013251f630713e456d/matplotlib-3.10.5-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:160e125da27a749481eaddc0627962990f6029811dbeae23881833a011a0907f", size = 8233224, upload-time = "2025-07-31T18:09:27.512Z" }, + { url = "https://files.pythonhosted.org/packages/ec/74/a2b9b04824b9c349c8f1b2d21d5af43fa7010039427f2b133a034cb09e59/matplotlib-3.10.5-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:ac3d50760394d78a3c9be6b28318fe22b494c4fcf6407e8fd4794b538251899b", size = 8098539, upload-time = "2025-07-31T18:09:29.629Z" }, + { url = "https://files.pythonhosted.org/packages/fc/66/cd29ebc7f6c0d2a15d216fb572573e8fc38bd5d6dec3bd9d7d904c0949f7/matplotlib-3.10.5-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:6c49465bf689c4d59d174d0c7795fb42a21d4244d11d70e52b8011987367ac61", size = 8672192, upload-time = "2025-07-31T18:09:31.407Z" }, ] [[package]] @@ -1485,7 +1506,6 @@ dependencies = [ { name = "numpy" }, { name = "packaging" }, { name = "pandas" }, - { name = "plasmapy-sphinx" }, { name = "requests" }, { name = "scipy" }, { name = "setuptools" }, @@ -1557,8 +1577,7 @@ requires-dist = [ { name = "packaging", specifier = ">=22" }, { name = "pandas", specifier = ">=2" }, { name = "pillow", marker = "extra == 'docs'", specifier = ">=10.4" }, - { name = "plasmapy-sphinx", specifier = ">=2025.5.1" }, - { name = "plasmapy-sphinx", marker = "extra == 'docs'", specifier = ">=0.2.0b1" }, + { name = "plasmapy-sphinx", marker = "extra == 'docs'", specifier = ">=2025.5.1" }, { name = "pygments", marker = "extra == 'docs'", specifier = "==2.18" }, { name = "pytest", marker = "extra == 'tests'", specifier = ">=8.3.1" }, { name = "pytest-cov", marker = "extra == 'tests'", specifier = ">=5" }, From ee669cc73966213ed70e7b47c08f483407c464d8 Mon Sep 17 00:00:00 2001 From: William Nguyen <108578700+wnguyen1312@users.noreply.github.com> Date: Thu, 31 Jul 2025 14:08:23 -0500 Subject: [PATCH 420/521] Expand the docstring of `Hall_parameter` (#2938) * Expanded on the description of Hall parameter * replaced ions with particles * Added my changelog entry * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Edit changelog: 2938.doc.rst * Edit changelog: 2938.doc.rst --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Nick Murphy --- changelog/2938.doc.rst | 1 + src/plasmapy/formulary/dimensionless.py | 4 ++++ 2 files changed, 5 insertions(+) create mode 100644 changelog/2938.doc.rst diff --git a/changelog/2938.doc.rst b/changelog/2938.doc.rst new file mode 100644 index 0000000000..7fa5027e1d --- /dev/null +++ b/changelog/2938.doc.rst @@ -0,0 +1 @@ +Expanded the docstring of `~plasmapy.formulary.dimensionless.Hall_parameter`. diff --git a/src/plasmapy/formulary/dimensionless.py b/src/plasmapy/formulary/dimensionless.py index 065c0beb17..5cae4d23dc 100644 --- a/src/plasmapy/formulary/dimensionless.py +++ b/src/plasmapy/formulary/dimensionless.py @@ -138,6 +138,10 @@ def Hall_parameter( collision frequency between plasma species :math:`s` (``particle``) and species :math:`s^{\prime}` (``ion``). + If the Hall parameter is low, the trajectory of electrons between + two encounters of heavy particles is approximately linear. If the Hall + parameter is high, the motion of the electrons is highly curved. + **Aliases:** `betaH_` Parameters From d41cb81872fc801e2cf2d9b07cb296f0002a609a Mon Sep 17 00:00:00 2001 From: Nick Murphy Date: Thu, 31 Jul 2025 15:35:30 -0400 Subject: [PATCH 421/521] Use `typing.Self` in type hint annotations for `particle_class.py` (#2887) * Use typing.Self in particle_class.py * Edit changelog: 2887.internal.rst * Change Self back to Particle for molecule() * Change Self back to Particle for function --- changelog/2887.internal.rst | 1 + src/plasmapy/particles/particle_class.py | 16 ++++++++-------- 2 files changed, 9 insertions(+), 8 deletions(-) create mode 100644 changelog/2887.internal.rst diff --git a/changelog/2887.internal.rst b/changelog/2887.internal.rst new file mode 100644 index 0000000000..e21d9ae539 --- /dev/null +++ b/changelog/2887.internal.rst @@ -0,0 +1 @@ +Used `typing.Self` for type hint annotations for |Particle| and |CustomParticle|. diff --git a/src/plasmapy/particles/particle_class.py b/src/plasmapy/particles/particle_class.py index 7eb0411265..cffaf8ac25 100644 --- a/src/plasmapy/particles/particle_class.py +++ b/src/plasmapy/particles/particle_class.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import Any, Literal +from typing import Any, Literal, Self __all__ = [ "AbstractParticle", @@ -381,7 +381,7 @@ def become_set(arg: str | set | Sequence) -> set[str]: return require <= self.categories - def __add__(self, other: str | Particle | ParticleList) -> ParticleList: + def __add__(self, other: str | Self | ParticleList) -> ParticleList: return self._as_particle_list + other def __radd__(self, other: str) -> ParticleList: @@ -968,7 +968,7 @@ def __hash__(self) -> int: """ return hash(self.__repr__()) - def __invert__(self) -> Particle: + def __invert__(self) -> Self: """ Return the corresponding antiparticle, or raise an `~plasmapy.particles.exceptions.ParticleError` if the particle @@ -1025,7 +1025,7 @@ def symbol(self) -> str: return self._attributes["symbol"] @property - def antiparticle(self) -> Particle: + def antiparticle(self) -> Self: """ The antiparticle corresponding to the particle. @@ -1085,7 +1085,7 @@ def isotope(self) -> str | None: return self._attributes["isotope"] @property - def nucleus(self) -> Particle: + def nucleus(self) -> Self: """ Return the nucleus of an atom. @@ -1797,7 +1797,7 @@ def is_ion(self) -> bool: def ionize( self, n: int | Literal[np.inf] = 1, inplace: bool = False - ) -> Particle | None: + ) -> Self | None: """ Create a new |Particle| instance corresponding to the current |Particle| after being ionized ``n`` times. @@ -1888,7 +1888,7 @@ def ionize( else: return Particle(base_particle, Z=new_charge_number) - def recombine(self, n: int = 1, inplace: bool = False) -> Particle | None: + def recombine(self, n: int = 1, inplace: bool = False) -> Self | None: """ Create a new |Particle| instance corresponding to the current |Particle| after undergoing recombination ``n`` times. @@ -2339,7 +2339,7 @@ def _from_quantities( *quantities, symbol: str | None = None, Z: float | None = None, - ) -> CustomParticle: + ) -> Self: """ An alternate constructor for |CustomParticle| objects where the positional arguments correspond to the mass and/or charge in From 0e7e5cca25759b4c535e04ef01fcff329716197c Mon Sep 17 00:00:00 2001 From: Physics_is_awesome Date: Thu, 31 Jul 2025 14:46:17 -0500 Subject: [PATCH 422/521] Update `validators.py` (#2919) * Resolving issue #2788 * Edit changelog: 2919.internal.rst * Update CITATION.cff * pre-commit * Revert some changes to fix tests * Revert some names * Edit changelog: 2919.internal.rst --------- Co-authored-by: Nick Murphy Co-authored-by: Nick Murphy --- CITATION.cff | 2 ++ changelog/2919.internal.rst | 1 + src/plasmapy/utils/decorators/validators.py | 3 ++- 3 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 changelog/2919.internal.rst diff --git a/CITATION.cff b/CITATION.cff index 577381b2fa..856a3efa5e 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -731,6 +731,8 @@ authors: family-names: Zhang alias: carolyz +- alias: Physics-is-awesome + - given-names: Bao family-names: Nguyen affiliation: Imperial College London diff --git a/changelog/2919.internal.rst b/changelog/2919.internal.rst new file mode 100644 index 0000000000..86b984e03e --- /dev/null +++ b/changelog/2919.internal.rst @@ -0,0 +1 @@ +Updated :file:`validators.py`. diff --git a/src/plasmapy/utils/decorators/validators.py b/src/plasmapy/utils/decorators/validators.py index d263abc704..341d6ba395 100644 --- a/src/plasmapy/utils/decorators/validators.py +++ b/src/plasmapy/utils/decorators/validators.py @@ -500,7 +500,8 @@ def foo(x: u.Quantity[u.m], time: u.Quantity[u.s]) -> u.Quantity[u.m / u.s]: Allow `None` values to pass:: @validate_quantities( - arg2={"none_shall_pass": True}, validations_on_return=[u.cm, None] + arg2={"none_shall_pass": True}, + validations_on_return=[u.cm, None], ) def foo(arg1: u.cm, arg2: u.cm = None): return None From 74d9779dfbe1e9a90e628d00ea41b9f64d44a15b Mon Sep 17 00:00:00 2001 From: Nick Murphy Date: Thu, 31 Jul 2025 19:37:00 -0400 Subject: [PATCH 423/521] Update the code of conduct to the Contributor Covenant v3.0 (#3069) * Update to Contributor Covenant v3.0 * Edit changelog: 3069.doc.rst * Edit changelog: 3069.doc.rst * Edit changelog: 3069.doc.rst --- changelog/3069.doc.rst | 2 + docs/CODE_OF_CONDUCT.rst | 329 +++++++++++++++++++++++---------------- 2 files changed, 193 insertions(+), 138 deletions(-) create mode 100644 changelog/3069.doc.rst diff --git a/changelog/3069.doc.rst b/changelog/3069.doc.rst new file mode 100644 index 0000000000..e08f29a51f --- /dev/null +++ b/changelog/3069.doc.rst @@ -0,0 +1,2 @@ +Upgraded :ref:`PlasmaPy's Code of Conduct ` to +version 3.0 of the Contributor Covenant. diff --git a/docs/CODE_OF_CONDUCT.rst b/docs/CODE_OF_CONDUCT.rst index 404ebf4def..756a8ae06d 100644 --- a/docs/CODE_OF_CONDUCT.rst +++ b/docs/CODE_OF_CONDUCT.rst @@ -1,150 +1,203 @@ .. _plasmapy-code-of-conduct: -Contributor Covenant Code of Conduct -==================================== - -We adopt the `Contributor Covenant`_, version 2.1, which is reproduced -below. - -Our Pledge đŸ€ž -------------- - -We as members, contributors, and leaders pledge to make participation in -our community a harassment-free experience for everyone, regardless of -age, body size, visible or invisible disability, ethnicity, sex -characteristics, gender identity and expression, level of experience, -education, socioeconomic status, nationality, personal appearance, -race, caste, color, religion, or sexual identity and orientation. - -We pledge to act and interact in ways that contribute to an open, -welcoming, diverse, inclusive, and healthy community. ✹ - -Our Standards -------------- - -Examples of behavior that contributes to a positive environment for our -community include: - -- Demonstrating empathy and kindness toward other people -- Being respectful of differing opinions, viewpoints, and experiences -- Giving and gracefully accepting constructive feedback -- Accepting responsibility and apologizing to those affected by our - mistakes, and learning from the experience -- Focusing on what is best not just for us as individuals, but for the - overall community - -Examples of unacceptable behavior include: - -- The use of sexualized language or imagery, and sexual attention or - advances of any kind -- Trolling, insulting or derogatory comments, and personal or political - attacks -- Public or private harassment -- Publishing others' private information, such as a physical or email - address, without their explicit permission -- Other conduct which could reasonably be considered inappropriate in a - professional setting - -Enforcement Responsibilities ----------------------------- - -Community leaders are responsible for clarifying and enforcing our -standards of acceptable behavior and will take appropriate and fair -corrective action in response to any behavior that they deem -inappropriate, threatening, offensive, or harmful. - -Community leaders have the right and responsibility to remove, edit, or -reject comments, commits, code, wiki edits, issues, and other -contributions that are not aligned to this Code of Conduct, and will -communicate reasons for moderation decisions when appropriate. +Contributor Covenant 3.0 +======================== + +To respect the inherent worth and dignity of every person, the +PlasmaPy community abides by the Contributor Covenant Code of Conduct, +version 3.0. + +.. important:: + + To report a possible violation of the code of conduct, please email + conduct@plasmapy.org. + +Our Pledge +---------- + +We pledge to make our community welcoming, safe, and equitable for all. + +We are committed to fostering an environment that respects and promotes +the dignity, rights, and contributions of all individuals, regardless of +characteristics including race, ethnicity, caste, color, age, physical +characteristics, neurodiversity, disability, sex or gender, gender +identity or expression, sexual orientation, language, philosophy or +religion, national or social origin, socio-economic position, level of +education, or other status. The same privileges of participation are +extended to everyone who participates in good faith and in accordance +with this Covenant. + +Encouraged Behaviors +-------------------- + +While acknowledging differences in social norms, we all strive to meet +our community's expectations for positive behavior. We also understand +that our words and actions may be interpreted differently than we intend +based on culture, background, or native language. + +With these considerations in mind, we agree to behave mindfully toward +each other and act in ways that center our shared values, including: + +1. Respecting the **purpose of our community**, our activities, and our + ways of gathering. +2. Engaging **kindly and honestly** with others. +3. Respecting **different viewpoints** and experiences. +4. **Taking responsibility** for our actions and contributions. +5. Gracefully giving and accepting **constructive feedback**. +6. Committing to **repairing harm** when it occurs. +7. Behaving in other ways that promote and sustain the **well-being of + our community**. + +Restricted Behaviors +-------------------- + +We agree to restrict the following behaviors in our community. +Instances, threats, and promotion of these behaviors are violations of +this Code of Conduct. + +1. **Harassment.** Violating explicitly expressed boundaries or engaging + in unnecessary personal attention after any clear request to stop. +2. **Character attacks.** Making insulting, demeaning, or pejorative + comments directed at a community member or group of people. +3. **Stereotyping or discrimination.** Characterizing anyone's + personality or behavior on the basis of immutable identities or + traits. +4. **Sexualization.** Behaving in a way that would generally be + considered inappropriately intimate in the context or purpose of the + community. +5. **Violating confidentiality**. Sharing or acting on someone's + personal or private information without their permission. +6. **Endangerment.** Causing, encouraging, or threatening violence or + other harm toward any person or group. +7. Behaving in other ways that **threaten the well-being** of our + community. + +Other Restrictions +~~~~~~~~~~~~~~~~~~ + +1. **Misleading identity.** Impersonating someone else for any reason, + or pretending to be someone else to evade enforcement actions. +2. **Failing to credit sources.** Not properly crediting the sources of + content you contribute. +3. **Promotional materials**. Sharing marketing or other commercial + content in a way that is outside the norms of the community. +4. **Irresponsible communication.** Failing to responsibly present + content which includes, links or describes any other restricted + behaviors. + +Reporting an Issue +------------------ + +Tensions can occur between community members even when they are trying +their best to collaborate. Not every conflict represents a code of +conduct violation, and this Code of Conduct reinforces encouraged +behaviors and norms that can help avoid conflicts and minimize harm. + +When an incident does occur, it is important to report it promptly. +To report a possible violation of the code of conduct, please email +conduct@plasmapy.org. + +Community Moderators take reports of violations seriously and will make +every effort to respond in a timely manner. They will investigate all +reports of code of conduct violations, reviewing messages, logs, and +recordings, or interviewing witnesses and other participants. Community +Moderators will keep investigation and enforcement actions as +transparent as possible while prioritizing safety and confidentiality. +In order to honor these values, enforcement actions are carried out in +private with the involved parties, but communicating to the whole +community may be part of a mutually agreed upon resolution. + +Addressing and Repairing Harm +----------------------------- + +If an investigation by the Community Moderators finds that this Code of +Conduct has been violated, the following enforcement ladder may be used +to determine how best to repair harm, based on the incident's impact on +the individuals involved and the community as a whole. Depending on the +severity of a violation, lower rungs on the ladder may be skipped. + +1) Warning + + 1) Event: A violation involving a single incident or series of + incidents. + 2) Consequence: A private, written warning from the Community + Moderators. + 3) Repair: Examples of repair include a private written apology, + acknowledgement of responsibility, and seeking clarification on + expectations. + +2) Temporarily Limited Activities + + 1) Event: A repeated incidence of a violation that previously + resulted in a warning, or the first incidence of a more serious + violation. + 2) Consequence: A private, written warning with a time-limited + cooldown period designed to underscore the seriousness of the + situation and give the community members involved time to process + the incident. The cooldown period may be limited to particular + communication channels or interactions with particular community + members. + 3) Repair: Examples of repair may include making an apology, using + the cooldown period to reflect on actions and impact, and being + thoughtful about re-entering community spaces after the period is + over. + +3) Temporary Suspension + + 1) Event: A pattern of repeated violation which the Community + Moderators have tried to address with warnings, or a single + serious violation. + 2) Consequence: A private written warning with conditions for return + from suspension. In general, temporary suspensions give the person + being suspended time to reflect upon their behavior and possible + corrective actions. + 3) Repair: Examples of repair include respecting the spirit of the + suspension, meeting the specified conditions for return, and being + thoughtful about how to reintegrate with the community when the + suspension is lifted. + +4) Permanent Ban + + 1) Event: A pattern of repeated code of conduct violations that other + steps on the ladder have failed to resolve, or a violation so + serious that the Community Moderators determine there is no way to + keep the community safe with this person as a member. + 2) Consequence: Access to all community spaces, tools, and + communication channels is removed. In general, permanent bans + should be rarely used, should have strong reasoning behind them, + and should only be resorted to if working through other remedies + has failed to change the behavior. + 3) Repair: There is no possible repair in cases of this severity. + +This enforcement ladder is intended as a guideline. It does not limit +the ability of Community Managers to use their discretion and judgment, +in keeping with the best interests of our community. Scope ----- This Code of Conduct applies within all community spaces, and also applies when an individual is officially representing the community in -public spaces. Examples of representing our community include using an -official e-mail address, posting via an official social media account, -or acting as an appointed representative at an online or offline event. - -Enforcement ------------ - -Instances of abusive, harassing, or otherwise unacceptable behavior may -be reported to the community leaders responsible for enforcement at -conduct@plasmapy.org. All complaints will be reviewed and investigated -promptly and fairly. - -All community leaders are obligated to respect the privacy and security -of the reporter of any incident. - -Enforcement Guidelines ----------------------- - -Community leaders will follow these Community Impact Guidelines in -determining the consequences for any action they deem in violation of -this Code of Conduct: - -1. Correction -~~~~~~~~~~~~~ - -**Community Impact**: Use of inappropriate language or other behavior -deemed unprofessional or unwelcome in the community. - -**Consequence**: A private, written warning from community leaders, -providing clarity around the nature of the violation and an explanation -of why the behavior was inappropriate. A public apology may be -requested. - -2. Warning -~~~~~~~~~~ - -**Community Impact**: A violation through a single incident or series of -actions. - -**Consequence**: A warning with consequences for continued behavior. No -interaction with the people involved, including unsolicited interaction -with those enforcing the Code of Conduct, for a specified period of -time. This includes avoiding interactions in community spaces as well as -external channels like social media. Violating these terms may lead to a -temporary or permanent ban. - -3. Temporary Ban -~~~~~~~~~~~~~~~~ - -**Community Impact**: A serious violation of community standards, -including sustained inappropriate behavior. - -**Consequence**: A temporary ban from any sort of interaction or public -communication with the community for a specified period of time. No -public or private interaction with the people involved, including -unsolicited interaction with those enforcing the Code of Conduct, is -allowed during this period. Violating these terms may lead to a -permanent ban. - -4. Permanent Ban -~~~~~~~~~~~~~~~~ - -**Community Impact**: Demonstrating a pattern of violation of community -standards, including sustained inappropriate behavior, harassment of an -individual, or aggression toward or disparagement of classes of -individuals. - -**Consequence**: A permanent ban from any sort of public interaction -within the community. +public or other spaces. Examples of representing our community include +using an official email address, posting via an official social media +account, or acting as an appointed representative at an online or +offline event. Attribution ----------- -This Code of Conduct is adapted from the `Contributor Covenant`_, -version 2.1, available at -https://www.contributor-covenant.org/version/2/1/code_of_conduct\ . - -Community Impact Guidelines were inspired by `Mozilla's code of conduct -enforcement ladder `__. - -For answers to common questions about this code of conduct, see the FAQ -at https://www.contributor-covenant.org/faq. Translations are available -at https://www.contributor-covenant.org/translations. - -.. _Contributor Covenant: https://www.contributor-covenant.org +This Code of Conduct is adapted from the Contributor Covenant, version +3.0, permanently available at +https://www.contributor-covenant.org/version/3/0/. + +Contributor Covenant is stewarded by the Organization for Ethical Source +and licensed under CC BY-SA 4.0. To view a copy of this license, visit +https://creativecommons.org/licenses/by-sa/4.0/ + +For answers to common questions about Contributor Covenant, see the FAQ +at https://www.contributor-covenant.org/faq. Translations are provided +at https://www.contributor-covenant.org/translations. Additional +enforcement and community guideline resources can be found at +https://www.contributor-covenant.org/resources. The enforcement ladder +was inspired by the work of `Mozilla's code of conduct +team `__. From 091a5f78afc81f6be66cc3ae2d9fb7fa7eb63da0 Mon Sep 17 00:00:00 2001 From: Nick Murphy Date: Thu, 31 Jul 2025 19:37:23 -0400 Subject: [PATCH 424/521] Update installation instructions for uv (#2999) * Update Python versions * Update installation instructions for uv * Update uv installation text * Update uv installation text * Edit changelog: 2999.doc.rst * Specify that Windows instructions are for PowerShell * Reword * Update instructions * Fix rst errors * Change -> PlasmaPy * Update to Contributor Covenant v3.0 * Revert "Change -> PlasmaPy" This reverts commit 0a816656749dfcb7da74e46ed3e0cc61d7b28f7d. * Reapply "Change -> PlasmaPy" This reverts commit 68653386db1647abeae02c339dde883945b2a59b. * Revert "Update to Contributor Covenant v3.0" This reverts commit 6630a9e068aebdcd734fa8aa8241d4dd46a73fb0. * Edit changelog: 2999.doc.rst * Minor formatting changes * Update pygment lexers to PowerShell * Fix typo --- README.md | 4 +- changelog/2999.doc.rst | 1 + docs/changelog/0.8.1.rst | 6 +- docs/changelog/2024.5.0.rst | 10 +-- docs/contributing/coding_guide.rst | 2 +- docs/contributing/getting_ready.rst | 2 +- docs/contributing/pre-commit.rst | 2 +- docs/contributing/testing_guide.rst | 2 +- docs/glossary.rst | 2 +- docs/install.rst | 98 +++++++++++++++++------------ 10 files changed, 73 insertions(+), 56 deletions(-) create mode 100644 changelog/2999.doc.rst diff --git a/README.md b/README.md index 36e479394d..187e597514 100644 --- a/README.md +++ b/README.md @@ -55,7 +55,7 @@ On some systems, it might be necessary to specify the Python version number, for example by using `python3` or `python3.13` instead of `python`. -To install PlasmaPy on Windows, open a terminal and run +To install PlasmaPy in Windows via PowerShell, run: ```Shell py -3.13 -m pip install plasmapy @@ -142,7 +142,7 @@ added [protections against software patents]. ## Acknowledgments Development of PlasmaPy has been supported in part by the -[National Science Foundation], [Department of Energy], [NASA], and the +[National Science Foundation], [NASA], [Department of Energy], and the [Smithsonian Institution]. For more details, please see PlasmaPy's documentation page on [authors and credits]. diff --git a/changelog/2999.doc.rst b/changelog/2999.doc.rst new file mode 100644 index 0000000000..7ed5175d5d --- /dev/null +++ b/changelog/2999.doc.rst @@ -0,0 +1 @@ +Updated the instructions on how to install PlasmaPy. diff --git a/docs/changelog/0.8.1.rst b/docs/changelog/0.8.1.rst index 1fb715959e..4c00b276c8 100644 --- a/docs/changelog/0.8.1.rst +++ b/docs/changelog/0.8.1.rst @@ -95,7 +95,7 @@ Deprecations and Removals policy laid out in `NumPy Enhancement Proposal 29 `__. (`#1465 `__) -- The ``[all]`` option when using |pip| to install `plasmapy` is now +- The ``[all]`` option when using |pip| to install PlasmaPy is now deprecated and may be removed in a future release. Packages that were previously optional (|h5py|, |lmfit|, |mpmath|, and Numba) are now installed by default when running ``pip install @@ -423,9 +423,9 @@ Improved Documentation - Added a discussion of doctests to the |documentation guide|. (`#1478 `__) - Removed the section on package requirements from the instructions on - how to install `plasmapy`. (`#1482 + how to install PlasmaPy. (`#1482 `__) -- Updated the instructions on how to install `plasmapy`. (`#1482 +- Updated the instructions on how to install PlasmaPy`. (`#1482 `__) - Defined ``autodoc_typehints_format="short"`` so signature type hints are displayed in short form, i.e. without the leading module diff --git a/docs/changelog/2024.5.0.rst b/docs/changelog/2024.5.0.rst index 5737158998..cefca2b1d8 100644 --- a/docs/changelog/2024.5.0.rst +++ b/docs/changelog/2024.5.0.rst @@ -124,14 +124,14 @@ Internal Changes and Refactorings to follow the updated recommendation from the Python Packaging Authority's `packaging guide `__. The motivation for this change is described in :issue:`2581`. Source - code previously in :file:`plasmapy` is now located in - :file:`src/plasmapy` and tests are now in a separate :file:`tests` - directory. Tests previously in :file:`plasmapy/**/tests` are now in + code previously in :file:`plasmapy/` is now located in + :file:`src/plasmapy/` and tests are now in a separate :file:`tests` + directory. Tests previously in :file:`plasmapy/**/tests/` are now in :file:`tests/**/`, where :file:`**` refers to an arbitrary number of subdirectories. For example, the source code of `plasmapy.formulary` - is now located in :file:`src/plasmapy/formulary` and the tests for + is now located in :file:`src/plasmapy/formulary/` and the tests for `plasmapy.formulary` are now in - :file:`tests/formulary`. (:pr:`2598`) + :file:`tests/formulary/`. (:pr:`2598`) - Reconfigured the auto-generated requirements files used during continuous integration and for documentation builds, while adding corresponding documentation. (:pr:`2650`) diff --git a/docs/contributing/coding_guide.rst b/docs/contributing/coding_guide.rst index 1432156a08..7d8d12d967 100644 --- a/docs/contributing/coding_guide.rst +++ b/docs/contributing/coding_guide.rst @@ -777,7 +777,7 @@ not noticeably impact performance during typical interactive use, but the performance penalty can become significant for numerically intensive applications. -A :term:`lite-function` is an optimized version of another `plasmapy` +A :term:`lite-function` is an optimized version of another PlasmaPy function that accepts numbers and |NumPy| arrays in assumed SI units. :term:`Lite-functions` skip all validations and instead prioritize performance. Most :term:`lite-functions` are defined in diff --git a/docs/contributing/getting_ready.rst b/docs/contributing/getting_ready.rst index 66ee76d92c..ce207c6758 100644 --- a/docs/contributing/getting_ready.rst +++ b/docs/contributing/getting_ready.rst @@ -264,7 +264,7 @@ when you :py:`import plasmapy`. .. group-tab:: Windows - .. code-block:: bash + .. code-block:: PowerShell py -m pip install -e .[docs,tests] diff --git a/docs/contributing/pre-commit.rst b/docs/contributing/pre-commit.rst index 16cde20534..fcbb3e4495 100644 --- a/docs/contributing/pre-commit.rst +++ b/docs/contributing/pre-commit.rst @@ -128,7 +128,7 @@ To enable pre-commit on your computer: .. group-tab:: Windows - .. code-block:: bash + .. code-block:: PowerShell py -m pip install pre-commit diff --git a/docs/contributing/testing_guide.rst b/docs/contributing/testing_guide.rst index 56acfa855a..4b94bb7676 100644 --- a/docs/contributing/testing_guide.rst +++ b/docs/contributing/testing_guide.rst @@ -31,7 +31,7 @@ install |Nox| and |uv|: .. group-tab:: Windows - .. code-block:: bash + .. code-block:: PowerShell py -m pip install nox uv diff --git a/docs/glossary.rst b/docs/glossary.rst index 94bd9e584d..31f5d8eae1 100644 --- a/docs/glossary.rst +++ b/docs/glossary.rst @@ -95,7 +95,7 @@ Glossary lite-function lite-functions - An optimized version of an existing `plasmapy` function intended + An optimized version of an existing PlasmaPy function intended for applications where computational efficiency is most important. While most `~plasmapy.formulary` functions accept |Quantity| objects created using `astropy.units`, lite-functions accept diff --git a/docs/install.rst b/docs/install.rst index 69f58c1ab6..7bf51fd617 100644 --- a/docs/install.rst +++ b/docs/install.rst @@ -22,20 +22,12 @@ PlasmaPy requires a version of |Python| between |minpython| and |maxpython|. If you do not have |Python| installed already, here are the instructions to `download Python`_ and install it. 🐍 -.. tip:: - - New versions of |Python| are released annually in October, and it can - take a few months for the scientific Python ecosystem to catch up. If - you have trouble installing `plasmapy` on the most recent |Python| - version between October and March, then try installing it on the - second most recent version. - .. _install-pip: Installing PlasmaPy with pip ============================ -To install the most recent release of `plasmapy` on |PyPI| with |pip| into +To install the most recent release of PlasmaPy on |PyPI| with |pip| into an existing |Python| |minpython|\ + environment on macOS or Linux, open a terminal and run: @@ -43,17 +35,19 @@ terminal and run: python -m pip install plasmapy -On some systems, it might be necessary to specify the |Python| version -number by using ``python3``, ``python3.8``, ``python3.9``, -``python3.10``, or ``python3.11`` instead of ``python``. +.. note:: + + On some systems, it might be necessary to specify the |Python| + version by using ``python3``, ``python3.11``, ``python3.12``, or + ``python3.13`` instead of ``python``. To install PlasmaPy on Windows, run: .. code-block:: bash - py -3.11 -m pip install plasmapy + py -3.13 -m pip install plasmapy -The version of |Python| may be changed from ``3.11`` to another supported +The version of |Python| may be changed from ``3.13`` to another supported Python |minpython|\ + release that has been installed on your computer. For more detailed information, please refer to this tutorial on @@ -67,27 +61,47 @@ Installing PlasmaPy with uv |uv| is "an extremely fast |Python| package and project manager, written in Rust". |uv| lets us create and switch between |Python| environments that are isolated from each other and the system's |Python| -installation. In addition, |uv| provides a `pip drop-in interface`_ for -common |pip| commands so that |Python| packages on |PyPI| may be -installed into |uv|-managed -`virtual environments `_ without installing |pip|. +installation. |uv| provides a `pip drop-in interface`_ for common |pip| +commands to install packages from |PyPI|. -After `installing uv`_, a `virtual environment`_ with |Python| version -3.12 can be created by opening a terminal and running: +By default, |uv| requires that packages be installed into +`uv managed virtual environments`_ rather than the system Python +installation. After `installing uv`_, create a virtual environment by +opening a terminal and running: .. code-block:: bash - uv venv --python 3.12 + uv venv --python 3.13 -|uv| will automatically download |Python| and link it to -the `virtual environment`_'s directory at (by default) :file:`.venv`. The -environment can then be activated by running: +This command will create a virtual environment managed by |uv| in a new +:file:`.venv` subdirectory, and then print out the command that will +activate the virtual environment from the directory that the above +command was run in. The activation command differs between +different operating systems and Unix shells. -.. code-block:: bash +.. tabs:: + + .. group-tab:: Windows + + To activate the virtual environment in Powershell, run: + + .. code-block:: PowerShell + + .venv\Scripts\activate + + .. group-tab:: macOS and Linux + + To activate the virtual environment on POSIX-compliant shells like + ``bash``, ``zsh``, and ``sh``, run: + + .. code-block:: bash + + source .venv/bin/activate - source .venv/bin/activate + For alternative shells, see the |uv| documentation page for + `using a virtual environment`_. -Then, to install `plasmapy` into the activated environment, run: +To install PlasmaPy, run: .. code-block:: bash @@ -101,24 +115,24 @@ Installing PlasmaPy with Conda Conda_ is a package management system and environment manager that is commonly used in the scientific |Python| ecosystem. Similar to |uv|, Conda_ is used to create and manage isolated virtual |Python| environments. -However, Conda_ can also be used for packages written in languages other -than |Python|. +Conda_ can also be used for packages written in languages other than +|Python|. -After `installing Conda`_ or miniconda_, `plasmapy` can be installed +After `installing Conda`_ or miniconda_, PlasmaPy can be installed into an activated Conda_ environment by opening a terminal and running: .. code-block:: bash conda install -c conda-forge plasmapy -Here :bash:`-c conda-forge` indicates that `plasmapy` should be installed +Here :bash:`-c conda-forge` indicates that PlasmaPy should be installed from the conda-forge_ channel. -To install `plasmapy` into another existing Conda_ environment, append +To install PlasmaPy into another existing Conda_ environment, append :samp:`-n {env_name}` to the previous command, where :samp:`{env_name}` is replaced with the name of the environment. -To create a new environment with `plasmapy` installed in it, run: +To create a new environment with PlasmaPy installed in it, run: .. code-block:: bash @@ -131,7 +145,7 @@ This step may take several minutes. To activate this environment, run: conda activate env_name -To update `plasmapy` to the most recent version within a currently +To update PlasmaPy to the most recent version within a currently activated Conda_ environment, run: .. code-block:: bash @@ -171,7 +185,7 @@ click on :guilabel:`Update channels` and then :guilabel:`Update index`. .. Is clicking on `Update index` actually necessary? Next, while on the :guilabel:`Environments` tab, select the environment -that you would like to install `plasmapy` in. The default is generally +that you would like to install PlasmaPy in. The default is generally ``base (root)``. Optionally, you may select :guilabel:`Create` to start a new environment. In the search bar, enter ``plasmapy``. Click on the checkbox next to ``plasmapy``, and select :guilabel:`Apply` to begin the @@ -190,7 +204,7 @@ Obtaining official releases --------------------------- A ZIP_ file containing the source code for official releases of -`plasmapy` can be obtained `from PyPI`_ or `from Zenodo`_. +PlasmaPy can be obtained `from PyPI`_ or `from Zenodo`_. Alternatively, official releases since 0.7.0 can be downloaded from the releases_ page on |PlasmaPy's GitHub repository|. @@ -199,7 +213,7 @@ Obtaining source code from GitHub --------------------------------- If you have |git| installed on your computer, you may clone -|PlasmaPy's GitHub repository| and access the source code from the most +|PlasmaPy's GitHub repository| and access the source code for the most recent development version by running: .. code-block:: bash @@ -207,20 +221,20 @@ recent development version by running: git clone https://github.com/PlasmaPy/PlasmaPy.git The repository will be cloned inside a new subdirectory called -:file:`PlasmaPy`. +:file:`PlasmaPy/`. If you do not have |git| installed on your computer, then you may download the most recent source code from |PlasmaPy's GitHub repository| by going to :guilabel:`Code` and selecting :guilabel:`Download ZIP`. `Unzipping `__ the file will -create a subdirectory called :file:`PlasmaPy` that contains the source +create a subdirectory called :file:`PlasmaPy/` that contains the source code. Building and installing ----------------------- -To install the downloaded version of `plasmapy`, enter the -:file:`PlasmaPy` directory and run: +To install the downloaded version of PlasmaPy, enter the +:file:`PlasmaPy/` directory and run: .. code-block:: bash @@ -268,6 +282,8 @@ package should also be installed. .. _project metadata: https://docs.astral.sh/uv/concepts/projects/#project-metadata .. _Python project: https://docs.astral.sh/uv/concepts/projects/#projects .. _releases: https://github.com/PlasmaPy/PlasmaPy/releases +.. _using a virtual environment: https://docs.astral.sh/uv/pip/environments/#using-a-virtual-environment .. _uv init options: https://docs.astral.sh/uv/reference/cli/#uv-init +.. _uv managed virtual environments: https://docs.astral.sh/uv/pip/environments .. _virtual environment: https://realpython.com/python-virtual-environments-a-primer .. _ZIP: https://en.wikipedia.org/wiki/ZIP_(file_format) From a1fffc7c49705b90822c0edbdc774d7a76ed0c57 Mon Sep 17 00:00:00 2001 From: Erik Everson Date: Fri, 1 Aug 2025 10:02:20 -0700 Subject: [PATCH 425/521] _condition_voltage_window() add conversion of ndarray to list --- src/plasmapy/analysis/swept_langmuir/plasma_potential.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py index 044190f886..6d59a1e543 100644 --- a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py +++ b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py @@ -28,6 +28,9 @@ def _condition_voltage_window(voltage, voltage_window) -> slice: Condition ``voltage_window`` and return resulting `slice` object to index ``voltage``. """ + if isinstance(voltage_window, np.ndarray): + voltage_window = voltage_window.tolist() + if voltage_window is None: voltage_window = [None, None] elif not isinstance(voltage_window, Sequence): From a8d3debde7c06b655193a6bb6f69268339f3d3d9 Mon Sep 17 00:00:00 2001 From: Erik Everson Date: Fri, 1 Aug 2025 11:26:14 -0700 Subject: [PATCH 426/521] refactor _condition_voltage_window to handle unsorted voltage_window after main conditioning --- .../swept_langmuir/plasma_potential.py | 33 ++++++++++--------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py index 6d59a1e543..7e544eca4d 100644 --- a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py +++ b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py @@ -52,33 +52,34 @@ def _condition_voltage_window(voltage, voltage_window) -> slice: voltage_window = np.sort(voltage_window).tolist() # determine data window - if ( - voltage_window[0] is None - or voltage_window[0] <= voltage[0] - ): - first_index = None - elif voltage_window[0] >= voltage[-1]: + if voltage_window[0] is not None and voltage_window[0] >= voltage[-1]: raise ValueError( f"The min value for the voltage window ({voltage_window[0]}) " f"is larger than the max value of the langmuir trace " f"({voltage[-1]})." ) - else: - first_index = int(np.where(voltage >= voltage_window[0])[0][0]) - if ( - voltage_window[1] is None - or voltage_window[1] >= voltage[-1] - ): - last_index = None - elif voltage_window[1] <= voltage[0]: + if voltage_window[1] is not None and voltage_window[1] <= voltage[0]: raise ValueError( f"The max value for the voltage window ({voltage_window[1]}) " f"is smaller than the min value of the langmuir trace " f"({voltage[0]})." ) - else: - last_index = int(np.where(voltage < voltage_window[1])[0][0]) + + if all(isinstance(element, numbers.Real) for element in voltage_window): + voltage_window = np.sort(voltage_window).tolist() + + first_index = ( + None + if voltage_window[0] is None + else int(np.where(voltage >= voltage_window[0])[0][0]) + ) + + last_index = ( + None + if voltage_window[1] is None + else int(np.where(voltage <= voltage_window[1])[0][-1]) + ) return slice(first_index, last_index, 1) From 7db70b7b4d4fbbc32ab7aa7d1ec3e10306a32175 Mon Sep 17 00:00:00 2001 From: Nick Murphy Date: Fri, 1 Aug 2025 17:00:12 -0400 Subject: [PATCH 427/521] Summarize dependency support policy and link to security policy in the documentation (#3059) * Discuss SPEC 0 at end of installation instructions * Edit changelog: 3059.doc.rst * Add SPEC 0 badge to README.md * pre-commit * Move version support policy for dependencies to separate page * Add table of contents * Link to security policy * Rename file * Update emojis * Add missing word * Rearrange toc --- README.md | 1 + changelog/3059.doc.rst | 1 + docs/about/policies.rst | 48 ++++++++++++++++++ docs/index.rst | 1 + docs/install.rst | 108 +++++++++++++++++----------------------- 5 files changed, 97 insertions(+), 62 deletions(-) create mode 100644 changelog/3059.doc.rst create mode 100644 docs/about/policies.rst diff --git a/README.md b/README.md index 187e597514..597c067b51 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,7 @@ [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.1436011.svg)](https://doi.org/10.5281/zenodo.1436011) [![astropy](http://img.shields.io/badge/powered%20by-Astropy-orange.svg?style=flat&logo=astropy)](http://www.astropy.org/) [![pre-commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit&logoColor=white)](https://github.com/pre-commit/pre-commit) +[![SPEC 0 — Minimum Supported Dependencies](https://img.shields.io/badge/SPEC-0-green?labelColor=%23004811&color=%235CA038)](https://scientific-python.org/specs/spec-0000/) [PlasmaPy] is an open source, community-developed [Python] package for plasma research and education. PlasmaPy intends to be for plasma science diff --git a/changelog/3059.doc.rst b/changelog/3059.doc.rst new file mode 100644 index 0000000000..cea1bae984 --- /dev/null +++ b/changelog/3059.doc.rst @@ -0,0 +1 @@ +Summarized the dependency support policy from |SPEC 0| at the end of the installation instructions. diff --git a/docs/about/policies.rst b/docs/about/policies.rst new file mode 100644 index 0000000000..9afdb2c2d1 --- /dev/null +++ b/docs/about/policies.rst @@ -0,0 +1,48 @@ +.. _policies: + +********************** +Policies and practices +********************** + +.. contents:: Contents + :local: + +.. _version-support: + +Version support policy for dependencies +======================================= + +.. image:: https://img.shields.io/badge/SPEC-0-green?labelColor=%23004811&color=%235CA038 + :target: https://scientific-python.org/specs/spec-0000/ + +PlasmaPy generally follows the time-based policy for dropping +dependencies as recommended in |SPEC 0|. SPEC 0 recommends a common +dependency support window across the scientific Python ecosystem, while +limiting the maintenance burden associated with supporting older +versions of dependencies. The specific recommendations are that: + +1. Support for Python versions be dropped **3 years** after their + initial release. +2. Support for core package dependencies be dropped **2 years** after + their initial release. + +Support for dependencies may be dropped sooner than what SPEC 0 +recommends if a more recent release of a dependency contains critical +bug fixes or includes important new features. + +.. note:: + + Dependency groups used primarily for code development activities such + as running tests and building documentation are excluded from this + policy because they are not intended for use by end users. + +.. _security-policy: + +Security policy +=============== + +PlasmaPy's `security policy`_ is maintained within its GitHub repository. +Please use this link to `privately report a security vulnerability`_. + +.. _privately report a security vulnerability: https://github.com/plasmapy/plasmapy/security/advisories/new +.. _security policy: https://github.com/PlasmaPy/PlasmaPy?tab=security-ov-file diff --git a/docs/index.rst b/docs/index.rst index 9ad570e09b..49c001744b 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -77,6 +77,7 @@ Example notebooks bibliography glossary performance_tips + about/policies PlasmaPy Enhancement Proposals PlasmaPy website GitHub Repository diff --git a/docs/install.rst b/docs/install.rst index 7bf51fd617..9340ad6d14 100644 --- a/docs/install.rst +++ b/docs/install.rst @@ -1,13 +1,13 @@ .. _plasmapy-install: -********************** -Installing PlasmaPy ☀ -********************** +******************* +Installing PlasmaPy +******************* .. note:: If you would like to contribute to PlasmaPy, please check out the - |contributor guide|. + |contributor guide|. :sunny: .. contents:: Contents :local: @@ -20,14 +20,22 @@ Installing Python PlasmaPy requires a version of |Python| between |minpython| and |maxpython|. If you do not have |Python| installed already, here are the -instructions to `download Python`_ and install it. 🐍 +instructions to `download Python`_ and install it. :snake: + +.. tip:: + + New versions of |Python| are released annually in October, and it can + take a few months for the scientific Python ecosystem to catch up. If + you have trouble installing `plasmapy` on the most recent |Python| + version between October and March, then try installing it on the + second most recent version. .. _install-pip: Installing PlasmaPy with pip ============================ -To install the most recent release of PlasmaPy on |PyPI| with |pip| into +To install the most recent release of `plasmapy` on |PyPI| with |pip| into an existing |Python| |minpython|\ + environment on macOS or Linux, open a terminal and run: @@ -35,19 +43,17 @@ terminal and run: python -m pip install plasmapy -.. note:: - - On some systems, it might be necessary to specify the |Python| - version by using ``python3``, ``python3.11``, ``python3.12``, or - ``python3.13`` instead of ``python``. +On some systems, it might be necessary to specify the |Python| version +number by using ``python3``, ``python3.8``, ``python3.9``, +``python3.10``, or ``python3.11`` instead of ``python``. To install PlasmaPy on Windows, run: .. code-block:: bash - py -3.13 -m pip install plasmapy + py -3.11 -m pip install plasmapy -The version of |Python| may be changed from ``3.13`` to another supported +The version of |Python| may be changed from ``3.11`` to another supported Python |minpython|\ + release that has been installed on your computer. For more detailed information, please refer to this tutorial on @@ -61,47 +67,27 @@ Installing PlasmaPy with uv |uv| is "an extremely fast |Python| package and project manager, written in Rust". |uv| lets us create and switch between |Python| environments that are isolated from each other and the system's |Python| -installation. |uv| provides a `pip drop-in interface`_ for common |pip| -commands to install packages from |PyPI|. +installation. In addition, |uv| provides a `pip drop-in interface`_ for +common |pip| commands so that |Python| packages on |PyPI| may be +installed into |uv|-managed +`virtual environments `_ without installing |pip|. -By default, |uv| requires that packages be installed into -`uv managed virtual environments`_ rather than the system Python -installation. After `installing uv`_, create a virtual environment by -opening a terminal and running: +After `installing uv`_, a `virtual environment`_ with |Python| version +3.12 can be created by opening a terminal and running: .. code-block:: bash - uv venv --python 3.13 - -This command will create a virtual environment managed by |uv| in a new -:file:`.venv` subdirectory, and then print out the command that will -activate the virtual environment from the directory that the above -command was run in. The activation command differs between -different operating systems and Unix shells. - -.. tabs:: + uv venv --python 3.12 - .. group-tab:: Windows +|uv| will automatically download |Python| and link it to +the `virtual environment`_'s directory at (by default) :file:`.venv`. The +environment can then be activated by running: - To activate the virtual environment in Powershell, run: - - .. code-block:: PowerShell - - .venv\Scripts\activate - - .. group-tab:: macOS and Linux - - To activate the virtual environment on POSIX-compliant shells like - ``bash``, ``zsh``, and ``sh``, run: - - .. code-block:: bash - - source .venv/bin/activate +.. code-block:: bash - For alternative shells, see the |uv| documentation page for - `using a virtual environment`_. + source .venv/bin/activate -To install PlasmaPy, run: +Then, to install `plasmapy` into the activated environment, run: .. code-block:: bash @@ -115,24 +101,24 @@ Installing PlasmaPy with Conda Conda_ is a package management system and environment manager that is commonly used in the scientific |Python| ecosystem. Similar to |uv|, Conda_ is used to create and manage isolated virtual |Python| environments. -Conda_ can also be used for packages written in languages other than -|Python|. +However, Conda_ can also be used for packages written in languages other +than |Python|. -After `installing Conda`_ or miniconda_, PlasmaPy can be installed +After `installing Conda`_ or miniconda_, `plasmapy` can be installed into an activated Conda_ environment by opening a terminal and running: .. code-block:: bash conda install -c conda-forge plasmapy -Here :bash:`-c conda-forge` indicates that PlasmaPy should be installed +Here :bash:`-c conda-forge` indicates that `plasmapy` should be installed from the conda-forge_ channel. -To install PlasmaPy into another existing Conda_ environment, append +To install `plasmapy` into another existing Conda_ environment, append :samp:`-n {env_name}` to the previous command, where :samp:`{env_name}` is replaced with the name of the environment. -To create a new environment with PlasmaPy installed in it, run: +To create a new environment with `plasmapy` installed in it, run: .. code-block:: bash @@ -145,7 +131,7 @@ This step may take several minutes. To activate this environment, run: conda activate env_name -To update PlasmaPy to the most recent version within a currently +To update `plasmapy` to the most recent version within a currently activated Conda_ environment, run: .. code-block:: bash @@ -185,7 +171,7 @@ click on :guilabel:`Update channels` and then :guilabel:`Update index`. .. Is clicking on `Update index` actually necessary? Next, while on the :guilabel:`Environments` tab, select the environment -that you would like to install PlasmaPy in. The default is generally +that you would like to install `plasmapy` in. The default is generally ``base (root)``. Optionally, you may select :guilabel:`Create` to start a new environment. In the search bar, enter ``plasmapy``. Click on the checkbox next to ``plasmapy``, and select :guilabel:`Apply` to begin the @@ -204,7 +190,7 @@ Obtaining official releases --------------------------- A ZIP_ file containing the source code for official releases of -PlasmaPy can be obtained `from PyPI`_ or `from Zenodo`_. +`plasmapy` can be obtained `from PyPI`_ or `from Zenodo`_. Alternatively, official releases since 0.7.0 can be downloaded from the releases_ page on |PlasmaPy's GitHub repository|. @@ -213,7 +199,7 @@ Obtaining source code from GitHub --------------------------------- If you have |git| installed on your computer, you may clone -|PlasmaPy's GitHub repository| and access the source code for the most +|PlasmaPy's GitHub repository| and access the source code from the most recent development version by running: .. code-block:: bash @@ -221,20 +207,20 @@ recent development version by running: git clone https://github.com/PlasmaPy/PlasmaPy.git The repository will be cloned inside a new subdirectory called -:file:`PlasmaPy/`. +:file:`PlasmaPy`. If you do not have |git| installed on your computer, then you may download the most recent source code from |PlasmaPy's GitHub repository| by going to :guilabel:`Code` and selecting :guilabel:`Download ZIP`. `Unzipping `__ the file will -create a subdirectory called :file:`PlasmaPy/` that contains the source +create a subdirectory called :file:`PlasmaPy` that contains the source code. Building and installing ----------------------- -To install the downloaded version of PlasmaPy, enter the -:file:`PlasmaPy/` directory and run: +To install the downloaded version of `plasmapy`, enter the +:file:`PlasmaPy` directory and run: .. code-block:: bash @@ -282,8 +268,6 @@ package should also be installed. .. _project metadata: https://docs.astral.sh/uv/concepts/projects/#project-metadata .. _Python project: https://docs.astral.sh/uv/concepts/projects/#projects .. _releases: https://github.com/PlasmaPy/PlasmaPy/releases -.. _using a virtual environment: https://docs.astral.sh/uv/pip/environments/#using-a-virtual-environment .. _uv init options: https://docs.astral.sh/uv/reference/cli/#uv-init -.. _uv managed virtual environments: https://docs.astral.sh/uv/pip/environments .. _virtual environment: https://realpython.com/python-virtual-environments-a-primer .. _ZIP: https://en.wikipedia.org/wiki/ZIP_(file_format) From 66647b2b8f24534837a25c5b21d6d9db7cd78145 Mon Sep 17 00:00:00 2001 From: Nick Murphy Date: Fri, 1 Aug 2025 17:59:13 -0400 Subject: [PATCH 428/521] Update contributor guide pages on contribution workflow and pre-commit (#3068) * Update refs for pre-commit guide sections * Update first pre-commit admonition * Update admonitions at bottom of workflow.rst * Change -> PlasmaPy in install.rst * Update pre-commit hooks * Edit changelog: 3068.doc.rst * Fix rst ref * Apply suggestion from @namurphy * Apply suggestion from @namurphy * Apply suggestion from @namurphy * Apply suggestion from @namurphy * Simplify pre-commit guide * Update workflow page * Fix rst * Don't mention using uvx * Update ruff section * Remove comments from rst * Advertise github discussions and de-emphasize Matrix chat --- .pre-commit-config.yaml | 4 +- changelog/3068.doc.rst | 2 + docs/contributing/pre-commit.rst | 184 ++++++++++--------------------- docs/contributing/workflow.rst | 64 ++++++----- docs/index.rst | 9 +- 5 files changed, 100 insertions(+), 163 deletions(-) create mode 100644 changelog/3068.doc.rst diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 15cb5faa15..1e5fdc8d52 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -33,7 +33,7 @@ repos: - id: check-github-workflows - repo: https://github.com/sirosen/texthooks - rev: 0.6.8 + rev: 0.7.1 hooks: - id: fix-smartquotes - id: fix-spaces @@ -87,7 +87,7 @@ repos: exclude: .pre-commit-search-and-replace.yaml - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.12.3 + rev: v0.12.7 hooks: - id: ruff name: ruff (see https://docs.astral.sh/ruff/rules) diff --git a/changelog/3068.doc.rst b/changelog/3068.doc.rst new file mode 100644 index 0000000000..70608c4066 --- /dev/null +++ b/changelog/3068.doc.rst @@ -0,0 +1,2 @@ +Updated the |contributor guide| pages on the |code contribution workflow| +and :ref:`using pre-commit `. diff --git a/docs/contributing/pre-commit.rst b/docs/contributing/pre-commit.rst index fcbb3e4495..170e7c76a1 100644 --- a/docs/contributing/pre-commit.rst +++ b/docs/contributing/pre-commit.rst @@ -1,4 +1,4 @@ -.. _pre-commit: +.. _using-pre-commit: **************** Using pre-commit @@ -13,24 +13,37 @@ Introduction ============ PlasmaPy uses |pre-commit| to automate code quality checks and perform -auto-fixes. +auto-fixes. |pre-commit| checks are performed on GitHub for every pull +request. -.. _pre-commit-troubleshooting: +.. important:: -Troubleshooting pre-commit failures -=================================== + Automatically fix most |pre-commit| failures on pull requests by + commenting: -.. tip:: + pre-commit.ci autofix - Many common |pre-commit| test failures related to formatting can be - automatically fixed by adding a comment on a pull request that says: + Adding this comment to the :guilabel:`Conversation` tab of a pull + request triggers a new commit that applies automatic fixes made by + PlasmaPy's pre-commit hooks. Use :bash:`git pull` to bring changes on + GitHub back to your computer. - pre-commit.ci autofix +Running pre-commit locally +========================== - This comment will produce a new commit to applies auto-fixes from - pre-commit. After doing this, don't forget to do a :bash:`git pull` - in your clone of the repository to pull back the changes to your - computer. +After `installing pre-commit`_, |pre-commit| can be run locally for all +files in your clone of the repository by running: + +.. code-block:: bash + + pre-commit run -a + +The ``-a`` is short for ``--all-files``. + +.. _pre-commit-troubleshooting: + +Troubleshooting pre-commit failures +=================================== The following sections contain suggestions for how to fix pre-commit failures that were not corrected by commenting ``pre-commit.ci autofix`` @@ -39,52 +52,48 @@ on the issue. ruff ---- -PlasmaPy uses |ruff| as its primary linter and code quality tool. |ruff| -can quickly find code quality issues and is able to do many code quality -fixes. - -Every issue detected by ruff corresponds to a specific lint rule. For -example, lint rule F401_ removes unused :py:`import` statements. If you -encounter a confusing ruff rule, search `ruff's documentation page on -rules`_ for the rule code and click on its name for more information. +PlasmaPy uses |ruff| as its primary linter and code formatter. |ruff| +quickly finds and often fixes many code quality issues. -Problems flagged by C901_ occur when a function is too complex (i.e., -when it contains heavily nested control flow), which makes code much -more difficult to maintain. +Every issue detected by |ruff| corresponds to a specific linter rule. For +example, lint rule F401_ removes unused :py:`import` statements. .. tip:: - Reduce complexity by breaking up complicated functions into short - functions that do exactly one thing with no side effects. + Find more information about issues flagged by |ruff| by searching + `ruff's documentation page on rules`_ for the rule code and clicking + on its name. Disabling a ruff rule ~~~~~~~~~~~~~~~~~~~~~ -While |ruff| usually suggests improvements, there will occasionally be -times where a departure from a |ruff| rule is (at least temporarily) -justified. In these cases, we can append a :samp:`# noqa {}` -comment to the end of a line (where :samp:`{}` is replaced -with the corresponding |ruff| rule codes, and ``noqa`` stands for "no -quality assurance") to tell |ruff| to ignore that error on that line. +While |ruff| usually suggests improvements, there are occasionally +times when a departure from a |ruff| rule is preferable. -For example, we can tell |ruff| to ignore a function with excessive -code complexity (C901_), too many branches (PLR0912_), and too many -statements (PLR0915_) by adding the following ``noqa`` comment: +To ignore a |ruff| rule on a specific line, append a comment of the form +:samp:`# noqa {}`, where :samp:`` is replaced by +the |ruff| rule code(s) to ignore. + +For example, we can tell |ruff| to ignore a function with excessive code +complexity (C901_), too many branches (PLR0912_), and too many +statements (PLR0915_) by adding a ``noqa`` comment like in the following +example: .. code-block:: python def overly_complicated_function(): # noqa: C901, PLR0912, PLR0915 - """A function with 100+ lines of code and lots of if/else branches.""" + """A function with 97 lines and multiple nested if/else blocks.""" + +When writing new code, it is almost always preferable to refactor the +code to remove the error than to add a ``# noqa`` comment to ignore the +rule. Complex functions flagged by C901_ could be simplified by +extracting sections of code into separate functions that do exactly one +thing with no side effects. .. important:: - When writing new code, it is almost always better to refactor the - code to remove the error rather than add a ``noqa`` comment. In the - above example, it would be better to refactor an overly complicated - function into multiple short functions that do exactly one thing with - no side effects so that the code is easier to understand, modify, and - maintain. We should only add ``noqa`` statements when we have a good - reason to. + Use ``# noqa`` comments sparingly, and only when you have a strong + reason to do so. Spellchecks ----------- @@ -93,97 +102,18 @@ PlasmaPy uses codespell_ and typos_ to spellcheck source code. While these tools generally work well, occasionally there will be false positives. -* If you encounter a false positive with codespell, add it to - ``ignore-words-list`` under ``[codespell]`` in :file:`pyproject.toml`. - -* False positives from typos_ should be added to :file:`_typos.toml`. - - -Using pre-commit locally -======================== - -|pre-commit| checks are performed on GitHub for every pull request, but -it is also possible to set up pre-commit locally. - -.. tip:: - - We recommend enabling pre-commit for the clone of - |PlasmaPy's GitHub repository| only *after* you have become - comfortable with the |code contribution workflow|. - -Enabling pre-commit -------------------- - -To enable pre-commit on your computer: - -#. |Open a terminal|. - -#. If you use a Conda or virtual environment for developing PlasmaPy, - activate it (i.e., with ``conda activate plasmapy-dev``). - -#. Make sure that pre-commit is installed to your Python environment by - running: - - .. tabs:: - - .. group-tab:: Windows - - .. code-block:: PowerShell - - py -m pip install pre-commit - - .. group-tab:: macOS - - .. code-block:: bash - - python -m pip install pre-commit - - .. group-tab:: Linux/WSL - - .. code-block:: bash - - python -m pip install pre-commit - -#. Navigate to the :file:`PlasmaPy` directory that contains your clone - of PlasmaPy's repository. For example, if you cloned PlasmaPy into - the :file:`~/repos` directory, then run: - - .. code-block:: bash - - cd ~/repos/PlasmaPy - -#. Enable pre-commit with: - - .. code-block:: bash - - pre-commit install - -Changes to the workflow ------------------------ - -Once |pre-commit| has been installed for a repository, pre-commit will -run every time you try to commit a change. - -If any pre-commit checks fail, or if pre-commit changes any files, it -will be necessary to redo :bash:`git add` on the changed files and -:bash:`git commit` once again. - -.. tip:: - - To commit a change without running pre-commit, use the :bash:`-n` - flag (short for :bash:`--no-verify`) with |git|. - .. tip:: - To run pre-commit on all files, use - - .. code-block:: bash + Add false positives found by codespell_ to ``ignore-words-list`` in + the ``[tool.codespell]`` section of :file:`pyproject.toml`. - pre-commit run --all-files + Add false positives found by typos_ to the ``[default.extend-words]`` + section of :file:`_typos.toml`. .. _C901: https://docs.astral.sh/ruff/rules/complex-structure .. _codespell: https://github.com/codespell-project/codespell .. _F401: https://docs.astral.sh/ruff/rules/unused-import +.. _installing pre-commit: https://pre-commit.com/#installation .. _PLR0912: https://docs.astral.sh/ruff/rules/too-many-branches .. _PLR0915: https://docs.astral.sh/ruff/rules/too-many-statements .. _ruff's documentation page on rules: https://docs.astral.sh/ruff/rules diff --git a/docs/contributing/workflow.rst b/docs/contributing/workflow.rst index d2145d2c89..2345fc3213 100644 --- a/docs/contributing/workflow.rst +++ b/docs/contributing/workflow.rst @@ -132,16 +132,6 @@ each step, try running :bash:`git status`. Committing a change is like preserving a snapshot of what each file looks like at this point in history. - .. hint:: - - If it has been installed, |pre-commit| will perform automated - checks and possibly auto-fixes. If pre-commit fails, then - it'll be necessary to fix any remaining problems and do the - :bash:`git add` and :bash:`git commit` steps once more. Try using - :bash:`git diff` and :bash:`git diff --cached` to view the - changes, and :guilabel:`↑` and :guilabel:`↓` to scroll through - previous commands in a terminal. - #. To push the changes to GitHub, run: .. code-block:: bash @@ -219,30 +209,19 @@ Creating a pull request At this stage, a reviewer will perform a code review, unless it has been marked as a draft pull request. Thank you for contributing! -Pulling changes from GitHub ---------------------------- - -If your branch changes on GitHub, run - -.. code-block:: bash - - git pull - -to pull the changes from GitHub to your computer. If you'd like to pull -the changes from the ``main`` branch, instead run - -.. code-block:: bash +.. tip:: - git pull upstream main + If a continuous integration check at the bottom of a pull request + fails, click on the name of the test for more details. -If any of the changes conflict with each other, it will be necessary to -`resolve the merge conflict`_. +.. hint:: -.. note:: + Most ``pre-commit.ci`` failures can be fixed by adding a comment that + says ``pre-commit.ci autofix`` in the conversation tab of a pull + request. - After the pull request has been created, it can be updated by - using :bash:`git push` to update the corresponding branch on - GitHub. + To learn more about fixing common |pre-commit| failures, see + :ref:`pre-commit-troubleshooting`. .. important:: @@ -264,6 +243,31 @@ If any of the changes conflict with each other, it will be necessary to unique, persistent identifier used by researchers, authors, and open source contributors. +Pulling changes from GitHub +--------------------------- + +If your branch changes on GitHub, run + +.. code-block:: bash + + git pull + +to pull the changes from GitHub to your computer. If you'd like to pull +the changes from the ``main`` branch, instead run + +.. code-block:: bash + + git pull upstream main + +If any of the changes conflict with each other, it will be necessary to +`resolve the merge conflict`_. + +.. note:: + + After the pull request has been created, it can be updated by + using :bash:`git push` to update the corresponding branch on + GitHub. + .. _Add a new SSH key to your GitHub account: https://docs.github.com/en/authentication/connecting-to-github-with-ssh/adding-a-new-ssh-key-to-your-github-account .. _branch: https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/about-branches .. _fork: https://docs.github.com/en/get-started/quickstart/fork-a-repo diff --git a/docs/index.rst b/docs/index.rst index 49c001744b..c1fbe865a1 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -22,13 +22,13 @@ If you are new to PlasmaPy, please check out our PlasmaPy is developed openly `on GitHub`_, where you can `request a new feature`_ or `report a bug`_. We invite you to share -ideas and ask questions in our |Matrix chat room| or during our -virtual |community meetings|. +ideas and ask questions as `GitHub discussions`_ or during our +|community meetings|. .. important:: If you use PlasmaPy for work presented in a publication or talk, - please help the project by following these instructions to + please support the project by following these instructions to :ref:`cite or acknowledge ` PlasmaPy. .. toctree:: @@ -92,10 +92,11 @@ Example notebooks contributing/workflow Coding Guide contributing/testing_guide + contributing/pre-commit contributing/doc_guide contributing/changelog_guide - contributing/pre-commit +.. _GitHub discussions: https://github.com/PlasmaPy/PlasmaPy/discussions .. _new discussion on GitHub: https://github.com/PlasmaPy/PlasmaPy/discussions/new/choose .. _on GitHub: https://github.com/PlasmaPy/PlasmaPy .. _report a bug: https://github.com/PlasmaPy/PlasmaPy/issues/new?assignees=&labels=Bug&template=bug_report.yml From 5473909b897971922d49e3a004bfb25219761a88 Mon Sep 17 00:00:00 2001 From: Erik Everson Date: Fri, 1 Aug 2025 15:17:28 -0700 Subject: [PATCH 429/521] move _condition_voltage_window() from plasma_potential.py to helpers.py --- .../analysis/swept_langmuir/helpers.py | 63 ++++++++++++++++- .../swept_langmuir/plasma_potential.py | 68 ++----------------- 2 files changed, 67 insertions(+), 64 deletions(-) diff --git a/src/plasmapy/analysis/swept_langmuir/helpers.py b/src/plasmapy/analysis/swept_langmuir/helpers.py index 2a78d65a11..13e3505467 100644 --- a/src/plasmapy/analysis/swept_langmuir/helpers.py +++ b/src/plasmapy/analysis/swept_langmuir/helpers.py @@ -4,7 +4,7 @@ import numbers import warnings -from typing import Literal +from typing import Literal, Sequence import astropy.units as u import numpy as np @@ -565,3 +565,64 @@ def merge_voltage_clusters( # noqa: C901, PLR0912 ) return new_voltage, new_current + + +def _condition_voltage_window(voltage, voltage_window) -> slice: + """ + Condition ``voltage_window`` and return resulting `slice` object to + index ``voltage``. + """ + if isinstance(voltage_window, np.ndarray): + voltage_window = voltage_window.tolist() + + if voltage_window is None: + voltage_window = [None, None] + elif not isinstance(voltage_window, Sequence): + raise TypeError( + f"Expected a 2-element list of floats or None for 'voltage_window', " + f"but got type {type(voltage_window)}." + ) + elif len(voltage_window) != 2: + raise ValueError( + f"Expected a 2-element list of floats or None for 'voltage_window', " + f"but got type {len(voltage_window)} elements." + ) + elif not all( + isinstance(element, numbers.Real) or element is None + for element in voltage_window + ): + raise TypeError(f"Not all elements of 'voltage_window' are floats or None.") + elif None not in voltage_window: + voltage_window = np.sort(voltage_window).tolist() + + # determine data window + if voltage_window[0] is not None and voltage_window[0] >= voltage[-1]: + raise ValueError( + f"The min value for the voltage window ({voltage_window[0]}) " + f"is larger than the max value of the langmuir trace " + f"({voltage[-1]})." + ) + + if voltage_window[1] is not None and voltage_window[1] <= voltage[0]: + raise ValueError( + f"The max value for the voltage window ({voltage_window[1]}) " + f"is smaller than the min value of the langmuir trace " + f"({voltage[0]})." + ) + + if all(isinstance(element, numbers.Real) for element in voltage_window): + voltage_window = np.sort(voltage_window).tolist() + + first_index = ( + None + if voltage_window[0] is None + else int(np.where(voltage >= voltage_window[0])[0][0]) + ) + + last_index = ( + None + if voltage_window[1] is None + else int(np.where(voltage <= voltage_window[1])[0][-1]) + ) + + return slice(first_index, last_index, 1) diff --git a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py index 7e544eca4d..9aa4498ba7 100644 --- a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py +++ b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py @@ -6,14 +6,17 @@ __aliases__ = [] __all__ += __aliases__ -import numbers from collections.abc import Sequence from typing import NamedTuple import numpy as np from scipy import signal -from plasmapy.analysis.swept_langmuir.helpers import check_sweep, merge_voltage_clusters +from plasmapy.analysis.swept_langmuir.helpers import ( + _condition_voltage_window, + check_sweep, + merge_voltage_clusters, +) class dIdVExtras(NamedTuple): # noqa: N801 @@ -23,67 +26,6 @@ class dIdVExtras(NamedTuple): # noqa: N801 savgol_peaks: list[float] | None -def _condition_voltage_window(voltage, voltage_window) -> slice: - """ - Condition ``voltage_window`` and return resulting `slice` object to - index ``voltage``. - """ - if isinstance(voltage_window, np.ndarray): - voltage_window = voltage_window.tolist() - - if voltage_window is None: - voltage_window = [None, None] - elif not isinstance(voltage_window, Sequence): - raise TypeError( - f"Expected a 2-element list of floats or None for 'voltage_window', " - f"but got type {type(voltage_window)}." - ) - elif len(voltage_window) != 2: - raise ValueError( - f"Expected a 2-element list of floats or None for 'voltage_window', " - f"but got type {len(voltage_window)} elements." - ) - elif not all( - isinstance(element, numbers.Real) or element is None - for element in voltage_window - ): - raise TypeError(f"Not all elements of 'voltage_window' are floats or None.") - elif None not in voltage_window: - voltage_window = np.sort(voltage_window).tolist() - - # determine data window - if voltage_window[0] is not None and voltage_window[0] >= voltage[-1]: - raise ValueError( - f"The min value for the voltage window ({voltage_window[0]}) " - f"is larger than the max value of the langmuir trace " - f"({voltage[-1]})." - ) - - if voltage_window[1] is not None and voltage_window[1] <= voltage[0]: - raise ValueError( - f"The max value for the voltage window ({voltage_window[1]}) " - f"is smaller than the min value of the langmuir trace " - f"({voltage[0]})." - ) - - if all(isinstance(element, numbers.Real) for element in voltage_window): - voltage_window = np.sort(voltage_window).tolist() - - first_index = ( - None - if voltage_window[0] is None - else int(np.where(voltage >= voltage_window[0])[0][0]) - ) - - last_index = ( - None - if voltage_window[1] is None - else int(np.where(voltage <= voltage_window[1])[0][-1]) - ) - - return slice(first_index, last_index, 1) - - def _condition_smooth_fractions(smooth_fractions, data_size): """ Condition ``smooth_fractions`` and return the resulting From 339a3ea26d46dca84310a88075e6de07a72d088b Mon Sep 17 00:00:00 2001 From: Erik Everson Date: Fri, 1 Aug 2025 15:30:12 -0700 Subject: [PATCH 430/521] add docstring to dIdVExtras --- .../swept_langmuir/plasma_potential.py | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py index 9aa4498ba7..9a1b7af755 100644 --- a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py +++ b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py @@ -20,10 +20,36 @@ class dIdVExtras(NamedTuple): # noqa: N801 + """ + `~typing.NamedTuple` structured to contain the extra parameters + calculated by + `~plasmapy.analysis.swept_langmuir.plasma_potential.find_didv_peak_location`. + """ + std: float | None + """ + Alias for field number 0, standard deviation of all the computed + peak slope bias locations for each Savitzky-Golay filtered Langmuir + trace. Standard deviation of :attr:`savgol_peaks`. + """ + data_slice: slice | None + """ + Alias for field number 1, `slice` objected corresponding to the + sub-arrays of the Langmuir trace used for the calculation. + """ + savgol_windows: list[int] | None + """ + Alias for field number 2, list of windows sizes used for each + Savitzky-Golay filtered Langmuir trace. + """ + savgol_peaks: list[float] | None + """ + Alias for field number 3, list of computed peak slope bias locations + for each Savitzky-Golay filtered Langmuir trace. + """ def _condition_smooth_fractions(smooth_fractions, data_size): From 5fa7b86974a56a9ca6241c05daebd919687e4d1b Mon Sep 17 00:00:00 2001 From: Erik Everson Date: Fri, 1 Aug 2025 15:35:52 -0700 Subject: [PATCH 431/521] fix spelling mistakes --- .../swept_langmuir/find_didv_peak_location.ipynb | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/docs/notebooks/analysis/swept_langmuir/find_didv_peak_location.ipynb b/docs/notebooks/analysis/swept_langmuir/find_didv_peak_location.ipynb index 58ebf27f56..306d676873 100644 --- a/docs/notebooks/analysis/swept_langmuir/find_didv_peak_location.ipynb +++ b/docs/notebooks/analysis/swept_langmuir/find_didv_peak_location.ipynb @@ -9,14 +9,20 @@ "\n", "This notebook covers the use of the [**find_didv_peak_location()**](../../../api/plasmapy.analysis.swept_langmuir.plasma_potential.find_didv_peak_location.rst#find-didv-peak-location) function which finds the bias location associated with the peak slope of the swept Langmuir traces.\n", "\n", - "The bias voltage at the peaks slope is often used as a rough estimate for the plasma potential, but will always be slighlty lower than the actual plasma potential." + "The bias voltage at the peaks slope is often used as a rough estimate for the plasma potential, but will always be slightly lower than the actual plasma potential." ] }, { "cell_type": "code", "execution_count": null, "id": "d60a04df-c4cc-4b16-956c-e1967d07d4c5", - "metadata": {}, + "metadata": { + "editable": true, + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, "outputs": [], "source": [ "%matplotlib inline\n", @@ -66,7 +72,7 @@ "id": "c8f84fdd-6ec3-4633-bb0c-d827635f66cc", "metadata": {}, "source": [ - "## Calcualte the Peak Slope" + "## Calculate the Peak Slope" ] }, { From 7dedac569272561b003c9a19fbe3d14b3a72ce08 Mon Sep 17 00:00:00 2001 From: Erik Everson Date: Fri, 1 Aug 2025 15:38:42 -0700 Subject: [PATCH 432/521] appease grumpy ruff --- src/plasmapy/analysis/swept_langmuir/helpers.py | 5 +++-- src/plasmapy/analysis/swept_langmuir/plasma_potential.py | 5 ++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/plasmapy/analysis/swept_langmuir/helpers.py b/src/plasmapy/analysis/swept_langmuir/helpers.py index 13e3505467..334ebbea9d 100644 --- a/src/plasmapy/analysis/swept_langmuir/helpers.py +++ b/src/plasmapy/analysis/swept_langmuir/helpers.py @@ -4,7 +4,8 @@ import numbers import warnings -from typing import Literal, Sequence +from collections.abc import Sequence +from typing import Literal import astropy.units as u import numpy as np @@ -591,7 +592,7 @@ def _condition_voltage_window(voltage, voltage_window) -> slice: isinstance(element, numbers.Real) or element is None for element in voltage_window ): - raise TypeError(f"Not all elements of 'voltage_window' are floats or None.") + raise TypeError("Not all elements of 'voltage_window' are floats or None.") elif None not in voltage_window: voltage_window = np.sort(voltage_window).tolist() diff --git a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py index 9a1b7af755..ebb00f0a15 100644 --- a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py +++ b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py @@ -80,7 +80,7 @@ def _condition_smooth_fractions(smooth_fractions, data_size): elif not np.issubdtype(smooth_fractions.dtype, np.floating): raise ValueError( "Expected a 1-D list of floats in the interval (0, 1] for argument " - f"'smooth_fractions', not all elements are floats." + "'smooth_fractions', not all elements are floats." ) smooth_fractions = np.unique(np.sort(smooth_fractions)) @@ -123,7 +123,7 @@ def _condition_smooth_fractions(smooth_fractions, data_size): return savgol_windows -def find_didv_peak_location( # noqa: C901, PLR0912 +def find_didv_peak_location( voltage: np.ndarray, current: np.ndarray, *, @@ -167,7 +167,6 @@ def find_didv_peak_location( # noqa: C901, PLR0912 Notes ----- - Add details about algorithm. """ rtn_extras = dIdVExtras( From caef8f3880c25d9551eab5640550f8c5013d1a7f Mon Sep 17 00:00:00 2001 From: Nick Murphy Date: Fri, 1 Aug 2025 19:49:06 -0400 Subject: [PATCH 433/521] Make miscellaneous updates prior to release (#3070) * pre-commit autoupdate * Title case * Update communication page * Update communication pages * Update .mailmap to remove duplicate names in git log * Edit changelog: 3070.doc.rst * nox -s 'autotyping(safe)' * Add back link to Matrix chat * linkname: PlasmaPy website -> PlasmaPy Project --- .mailmap | 2 + README.md | 4 +- changelog/3070.doc.rst | 1 + docs/COMMUNICATION.rst | 70 ++++++++++++------- docs/about/citation.rst | 2 +- docs/about/policies.rst | 2 +- docs/examples.rst | 2 +- docs/index.rst | 2 +- .../particle_tracker/particle_tracker.py | 4 +- .../test_synthetic_radiography.py | 2 +- tests/particles/test_atomic.py | 2 +- tests/plasma/test_grids.py | 2 +- 12 files changed, 60 insertions(+), 35 deletions(-) create mode 100644 changelog/3070.doc.rst diff --git a/.mailmap b/.mailmap index 05b21ffe83..aa6e5e82e3 100644 --- a/.mailmap +++ b/.mailmap @@ -19,6 +19,7 @@ Elliot Johnson <77989826+etjohnson@users.noreply.github.com> Erik Everson Jasper Beckers Jayden Roberts <109694185+JaydenR2305@users.noreply.github.com> +Joseph Smith <11745431+josephrhsmith@users.noreply.github.com> Julien Hillairet Leah Nick Murphy @@ -27,5 +28,6 @@ Pawel Kozlowski Poh Zi How Rajagopalan Gangadharan Ritiek Malhotra +Tien Vo Tiger Du <56400881+Tiger-Du@users.noreply.github.com> Wu Tingfeng diff --git a/README.md b/README.md index 597c067b51..4e74f27636 100644 --- a/README.md +++ b/README.md @@ -132,8 +132,8 @@ channel; Gitter uses a bridge to link the two. ### Mailing list -You can subscribe to PlasmaPy's low-volume [mailing list] to receive -PlasmaPy newsletters and other announcements. +Subscribe to PlasmaPy's low-volume [mailing list] to receive occasional +newsletters and announcements. ## License diff --git a/changelog/3070.doc.rst b/changelog/3070.doc.rst new file mode 100644 index 0000000000..4a0704d831 --- /dev/null +++ b/changelog/3070.doc.rst @@ -0,0 +1 @@ +Updated the :ref:`Feedback and Communication ` page. diff --git a/docs/COMMUNICATION.rst b/docs/COMMUNICATION.rst index 327a4ccd4c..706647c203 100644 --- a/docs/COMMUNICATION.rst +++ b/docs/COMMUNICATION.rst @@ -3,44 +3,66 @@ Feedback and Communication ========================== -Matrix chat room ----------------- +Requesting features +------------------- -The primary communication channel for PlasmaPy is our `Matrix chat -room`_ 💬. There is also a `Gitter bridge`_ to this chat room. +Please `submit a feature request`_ on |PlasmaPy's GitHub repository| if +you have an idea for new or improved functionality. PlasmaPy is +community-driven, and feature requests really help guide the future of +the project! + +Submitting bug reports +---------------------- + +Please `submit a bug report`_ on PlasmaPy's GitHub repository if you +notice any problems. We greatly appreciate it! + +Meetings and events +------------------- + +To meet with members of the PlasmaPy team, we encourage you to stop by +our regularly scheduled `community meetings`_. + +Please check `PlasmaPy meetings`_ for other regularly scheduled meetings +and special events. GitHub Discussions page ----------------------- PlasmaPy's `GitHub Discussions page`_ is a great place to suggest ideas, -bring up discussion topics, and ask questions in threaded public -discussions. +bring up discussion topics, and ask questions. -Mailing list ------------- +Matrix chat room +---------------- -We also have a low traffic `mailing list`_ for occasional announcements -and infrequent discussions. +PlasmaPy team members are occasionally available via the `Matrix chat +room`_, which has a `Gitter bridge`_. -Suggestion box --------------- +Email +----- -We have a `suggestion box`_ if you would like to (optionally -anonymously) suggest a feature/topic for consideration. These will be -reposted as GitHub issues, as appropriate, for further discussion. +Members of the PlasmaPy team can be reached at team@plasmapy.org. -Meetings and events -------------------- +Please use these links to `submit a feature request`_ or +`submit a bug report`_ on |PlasmaPy's GitHub repository|. + +Mailing list +------------ + +Subscribe to PlasmaPy's low-volume `mailing list`_ to receive occasional +newsletters and announcements. + +Reporting security vulnerabilities +---------------------------------- -Please check `PlasmaPy meetings`_ for regularly scheduled meetings and -special events. The regularly scheduled meetings include a community -meeting to discuss code development, a project meeting to discuss -broader aspects of the PlasmaPy project like education and outreach to -the broader plasma community, and meetings of PlasmaPy working groups. -The special events include |Plasma Hack Week|. +Please use this link to `privately report a security vulnerability`_ +.. _community meetings: https://www.plasmapy.org/meetings/weekly/ .. _GitHub Discussions page: https://github.com/PlasmaPy/PlasmaPy/discussions .. _Gitter bridge: https://app.gitter.im/#/room/#PlasmaPy_Lobby:gitter.im .. _mailing list: https://groups.google.com/forum/#!forum/plasmapy +.. _matrix chat room: https://app.element.io/#/room/#plasmapy:openastronomy.org .. _PlasmaPy meetings: https://www.plasmapy.org/meetings -.. _suggestion box: https://docs.google.com/forms/d/e/1FAIpQLSdT3O5iHZrLJRuavFyzoR23PGy0Prfzx2SQOcwJGWtvHyT2lw/viewform?usp=sf_link +.. _privately report a security vulnerability: https://github.com/plasmapy/plasmapy/security/advisories/new +.. _submit a bug report: https://github.com/PlasmaPy/PlasmaPy/issues/new?assignees=&labels=Bug&template=bug_report.yml +.. _submit a feature request: https://github.com/PlasmaPy/PlasmaPy/issues/new?assignees=&labels=Feature+request&template=feature_request.yml diff --git a/docs/about/citation.rst b/docs/about/citation.rst index cb80be453e..95ae9aa27f 100644 --- a/docs/about/citation.rst +++ b/docs/about/citation.rst @@ -1,6 +1,6 @@ .. _citation: -Acknowledging and citing PlasmaPy +Acknowledging and Citing PlasmaPy ================================= .. |version_to_cite| replace:: 2024.10.0 diff --git a/docs/about/policies.rst b/docs/about/policies.rst index 9afdb2c2d1..28a42e6975 100644 --- a/docs/about/policies.rst +++ b/docs/about/policies.rst @@ -1,7 +1,7 @@ .. _policies: ********************** -Policies and practices +Policies and Practices ********************** .. contents:: Contents diff --git a/docs/examples.rst b/docs/examples.rst index a7a17786a0..b2d3428762 100644 --- a/docs/examples.rst +++ b/docs/examples.rst @@ -1,6 +1,6 @@ .. _examples: -Example notebooks +Example Notebooks ================= Here we catalog all the example Jupyter notebooks that have been created diff --git a/docs/index.rst b/docs/index.rst index c1fbe865a1..eff5bf46a2 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -79,7 +79,7 @@ Example notebooks performance_tips about/policies PlasmaPy Enhancement Proposals - PlasmaPy website + PlasmaPy Project GitHub Repository .. toctree:: diff --git a/src/plasmapy/simulation/particle_tracker/particle_tracker.py b/src/plasmapy/simulation/particle_tracker/particle_tracker.py index f9036c0a90..e3a6d5c976 100644 --- a/src/plasmapy/simulation/particle_tracker/particle_tracker.py +++ b/src/plasmapy/simulation/particle_tracker/particle_tracker.py @@ -855,7 +855,7 @@ def _adaptive_dt(self) -> NDArray[np.float64] | float: return dt - def _interpolate_grid(self): + def _interpolate_grid(self) -> None: # Get a list of positions (input for interpolator) pos_tracked = self.x[self._tracked_particle_mask] @@ -1075,7 +1075,7 @@ def _push(self) -> None: np.bool_ ) - def _reset_cache(self): + def _reset_cache(self) -> None: """ Reset the cached properties. diff --git a/tests/diagnostics/charged_particle_radiography/test_synthetic_radiography.py b/tests/diagnostics/charged_particle_radiography/test_synthetic_radiography.py index aef188e678..b573608a7d 100644 --- a/tests/diagnostics/charged_particle_radiography/test_synthetic_radiography.py +++ b/tests/diagnostics/charged_particle_radiography/test_synthetic_radiography.py @@ -611,7 +611,7 @@ def test_warns(self) -> None: with pytest.warns(RuntimeWarning): cpr.synthetic_radiograph(sim_results) - def test_ignore_grid(self): + def test_ignore_grid(self) -> None: """ Verifies that the no grid option runs - no good tests for whether it is correct currently """ diff --git a/tests/particles/test_atomic.py b/tests/particles/test_atomic.py index 0ec41cfbe6..660cf97127 100644 --- a/tests/particles/test_atomic.py +++ b/tests/particles/test_atomic.py @@ -708,7 +708,7 @@ def test_stopping_power_no_interpolation() -> None: assert type(result) is tuple -def test_element_name_used_on_numpy_integer(): +def test_element_name_used_on_numpy_integer() -> None: """ Test that `element_name` works when provided with a numpy.integer object acquired from an ndarray (see #3044). diff --git a/tests/plasma/test_grids.py b/tests/plasma/test_grids.py index e00561eec2..c261e4466b 100644 --- a/tests/plasma/test_grids.py +++ b/tests/plasma/test_grids.py @@ -514,7 +514,7 @@ def uniform_cartesian_grid(): 0.1 * u.cm, ], ) -def test_soften_edges(uniform_cartesian_grid, width): +def test_soften_edges(uniform_cartesian_grid, width) -> None: grid = uniform_cartesian_grid # Find the approximate center of the grid From bc1c75198e4cbe2f9652a2d292603390c01f251d Mon Sep 17 00:00:00 2001 From: Nick Murphy Date: Fri, 1 Aug 2025 20:22:30 -0400 Subject: [PATCH 434/521] Build documentation with Python 3.13 (#2943) * Build documentation with Python 3.13 * Edit changelog: 2943.doc.rst * Bump version of pygments & sphinx-codeautolink * Add blank lines for legibility * Unquietify sphinx-build * Update docs requirements * Add suppress_warnings option to docs/conf.py * Re-enable --quiet for sphinx-build * Adjust math to see if error is related * Remove .. math: directive * Remove colon * Remove colons preceding warnings in docstrings * pre-commit run --all-files * Update Python version in GitHub workflows * Add comment to noxfile.py * Remove ci_requirements * nox -s requirements * nox -s requirements --- .github/workflows/ci.yml | 4 ++-- .github/workflows/weekly.yml | 16 ++++++++-------- .readthedocs.yml | 4 ++-- changelog/2943.doc.rst | 1 + docs/conf.py | 4 ++++ src/plasmapy/formulary/frequencies.py | 15 ++++++++------- uv.lock | 6 +++--- 7 files changed, 28 insertions(+), 22 deletions(-) create mode 100644 changelog/2943.doc.rst diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a538ad9a50..d6d739ef28 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -49,9 +49,9 @@ jobs: python: '3.11' nox_session: tests-3.11(lowest-direct-skipslow) - - name: Documentation, Python 3.12, Ubuntu + - name: Documentation, Python 3.13, Ubuntu os: ubuntu-latest - python: '3.12' + python: '3.13' nox_session: docs - name: Static type checking with mypy, Python 3.13, Ubuntu diff --git a/.github/workflows/weekly.yml b/.github/workflows/weekly.yml index 2f26782a2f..2884ed6df2 100644 --- a/.github/workflows/weekly.yml +++ b/.github/workflows/weekly.yml @@ -75,24 +75,24 @@ jobs: python: '3.13' nox_session: run_tests_with_dev_version_of(lmfit) - - name: Documentation, Python 3.12, Ubuntu + - name: Documentation, Python 3.13, Ubuntu os: ubuntu-latest - python: '3.12' + python: '3.13' nox_session: docs - - name: Documentation, Python 3.12, sphinx-dev, Ubuntu + - name: Documentation, Python 3.13, sphinx-dev, Ubuntu os: ubuntu-latest - python: '3.12' + python: '3.13' nox_session: build_docs_with_dev_version_of(sphinx) - - name: Documentation, Python 3.12, sphinx_rtd_theme-dev, Ubuntu + - name: Documentation, Python 3.13, sphinx_rtd_theme-dev, Ubuntu os: ubuntu-latest - python: '3.12' + python: '3.13' nox_session: build_docs_with_dev_version_of(sphinx_rtd_theme) - - name: Documentation, Python 3.12, nbsphinx-dev, Ubuntu + - name: Documentation, Python 3.13, nbsphinx-dev, Ubuntu os: ubuntu-latest - python: '3.12' + python: '3.13' nox_session: build_docs_with_dev_version_of(nbsphinx) - name: Documentation, Python 3.12, plasmapy_sphinx-dev, Ubuntu diff --git a/.readthedocs.yml b/.readthedocs.yml index eabdc55869..38401fb62d 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -12,7 +12,7 @@ formats: build: os: ubuntu-24.04 tools: - python: '3.12' + python: '3.13' apt_packages: - graphviz @@ -23,7 +23,7 @@ build: - asdf plugin add uv - asdf install uv latest - asdf global uv latest - - uv venv --python=3.12 + - uv venv --python=3.13 install: - uv sync --extra docs --frozen --exact diff --git a/changelog/2943.doc.rst b/changelog/2943.doc.rst new file mode 100644 index 0000000000..36ce0e6835 --- /dev/null +++ b/changelog/2943.doc.rst @@ -0,0 +1 @@ +Bumped the Python version for documentation builds from 3.12 to 3.13. diff --git a/docs/conf.py b/docs/conf.py index 4250d46211..eaf0660c75 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -131,6 +131,10 @@ maximum_signature_line_length = 90 sphinxemoji_style = "twemoji" +suppress_warnings = [ + "autosummary.import_cycle", +] + # Specify patterns to ignore when doing a nitpicky documentation build. # These may include common expressions like "real number" as well as # workarounds for nested inline literals as defined in docs/common_links.py diff --git a/src/plasmapy/formulary/frequencies.py b/src/plasmapy/formulary/frequencies.py index 18aef9744e..c68849361b 100644 --- a/src/plasmapy/formulary/frequencies.py +++ b/src/plasmapy/formulary/frequencies.py @@ -91,7 +91,7 @@ def gyrofrequency( Warns ----- - : `~astropy.units.UnitsWarning` + `~astropy.units.UnitsWarning` If units are not provided, and SI units are assumed. Notes @@ -284,7 +284,7 @@ def plasma_frequency( Warns ----- - : `~astropy.units.UnitsWarning` + `~astropy.units.UnitsWarning` If units are not provided, SI units are assumed. Notes @@ -392,7 +392,7 @@ def lower_hybrid_frequency( Warns ----- - : `~astropy.units.UnitsWarning` + `~astropy.units.UnitsWarning` If units are not provided, SI units are assumed. Notes @@ -484,7 +484,7 @@ def upper_hybrid_frequency( Warns ----- - : `~astropy.units.UnitsWarning` + `~astropy.units.UnitsWarning` If units are not provided, SI units are assumed. Notes @@ -590,7 +590,7 @@ def Buchsbaum_frequency( Warns ----- - : `~astropy.units.UnitsWarning` + `~astropy.units.UnitsWarning` If units are not provided, SI units are assumed. Notes @@ -601,11 +601,12 @@ def Buchsbaum_frequency( to as the Buchsbaum frequency :cite:p:`buchsbaum:1960`, also called the bi-ion hybrid resonance frequency :cite:p:`thompson:1995`, or ion-ion hybrid frequency :cite:p:`vincena:2013`. This frequency - can be defined as: + can be defined as .. math:: + ω_{BB} ≡ \sqrt{\frac{ω_{p1}^2 ω_{c2}^2 - + ω_{p2}^2 ω_{c1}^2}{ω_{p2}^2 + ω_{p2}^2}} + + ω_{p2}^2 ω_{c1}^2}{ω_{p2}^2 + ω_{p2}^2}} Examples -------- diff --git a/uv.lock b/uv.lock index bf5f224c7b..247506a892 100644 --- a/uv.lock +++ b/uv.lock @@ -634,15 +634,15 @@ wheels = [ [[package]] name = "hypothesis" -version = "6.136.6" +version = "6.136.7" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "attrs" }, { name = "sortedcontainers" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/e2/d6/6c45c56cdc532f25a354cf2c93a3bebc21b91b6a48125e3acfd364161447/hypothesis-6.136.6.tar.gz", hash = "sha256:2ad2e4f2012be4d41c6515b0628d84d48af6e6c38b4db50840bd9ac0899f5856", size = 458049, upload-time = "2025-07-28T09:48:02.495Z" } +sdist = { url = "https://files.pythonhosted.org/packages/2e/19/92369e1d5f2ead5f3f491d5453f28a04be82133886d3a7b46ebdcf7e109d/hypothesis-6.136.7.tar.gz", hash = "sha256:864c5cf7779adc58871ee51595bc724c496047c5bc45229e0baa950b103a73ea", size = 458037, upload-time = "2025-08-01T22:14:23.057Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/e9/e2/7fd1a9b12740b3472349f7e3c216e94b1b2e03d32c9d842284b57eb5a3f8/hypothesis-6.136.6-py3-none-any.whl", hash = "sha256:1d6296dde36d42263bd44a084c74e91467e78186676e410167f920aa0374a9e7", size = 524958, upload-time = "2025-07-28T09:47:58.938Z" }, + { url = "https://files.pythonhosted.org/packages/88/59/32813aa1a2715d7c531f87b46a04ba23d05d2bd4f7e21ecda8135100f8ce/hypothesis-6.136.7-py3-none-any.whl", hash = "sha256:12a8b76a5c453f8478d6bb4b5450824856af571c5e7821604a15aeaafa9beefd", size = 524917, upload-time = "2025-08-01T22:14:18.845Z" }, ] [[package]] From e98b8b2883150bcf61b5ca9d011bb9498ccade65 Mon Sep 17 00:00:00 2001 From: Nick Murphy Date: Sat, 2 Aug 2025 11:13:15 -0400 Subject: [PATCH 435/521] Set upper limit on Sphinx version (#3073) * Unpin pygments and sphinx-codeautolink * Put upper limit on Sphinx * nox -s requirements * Re-pin pygments and sphinx-codeautolink * nox -s requirements * Edit changelog: 3073.doc.rst * nox -s requirements --- changelog/3073.doc.rst | 3 +++ pyproject.toml | 2 +- uv.lock | 8 ++++---- 3 files changed, 8 insertions(+), 5 deletions(-) create mode 100644 changelog/3073.doc.rst diff --git a/changelog/3073.doc.rst b/changelog/3073.doc.rst new file mode 100644 index 0000000000..f590c41e8c --- /dev/null +++ b/changelog/3073.doc.rst @@ -0,0 +1,3 @@ +Limited the allowed version of |Sphinx| to ``sphinx>=8.2.3,<8.3`` +because planned breaking changes to Sphinx are causing documentation +build errors due to incompatibilities with some extensions. diff --git a/pyproject.toml b/pyproject.toml index 0e972f1397..d921eb5148 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -87,7 +87,7 @@ optional-dependencies.docs = [ "pillow>=10.4", "plasmapy-sphinx>=2025.5.1", "pygments==2.18", - "sphinx>=8.2.3", + "sphinx>=8.2.3,<8.3", "sphinx-changelog>=1.5", "sphinx-codeautolink==0.15.2", "sphinx-collapse>=0.1.3", diff --git a/uv.lock b/uv.lock index 247506a892..f6c1642159 100644 --- a/uv.lock +++ b/uv.lock @@ -248,14 +248,14 @@ wheels = [ [[package]] name = "click" -version = "8.2.1" +version = "8.2.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "colorama", marker = "sys_platform == 'win32'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/60/6c/8ca2efa64cf75a977a0d7fac081354553ebe483345c734fb6b6515d96bbc/click-8.2.1.tar.gz", hash = "sha256:27c491cc05d968d271d5a1db13e3b5a184636d9d930f148c50b038f0d0646202", size = 286342, upload-time = "2025-05-20T23:19:49.832Z" } +sdist = { url = "https://files.pythonhosted.org/packages/e9/87/105111999772ec9730e3d4d910c723ea9763ece2ec441533a5cea1e87e3c/click-8.2.2.tar.gz", hash = "sha256:068616e6ef9705a07b6db727cb9c248f4eb9dae437a30239f56fa94b18b852ef", size = 263977, upload-time = "2025-08-02T02:23:41.102Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/85/32/10bb5764d90a8eee674e9dc6f4db6a0ab47c8c4d0d83c27f7c39ac415a4d/click-8.2.1-py3-none-any.whl", hash = "sha256:61a3265b914e850b85317d0b3109c7f8cd35a670f963866005d6ef1d5175a12b", size = 102215, upload-time = "2025-05-20T23:19:47.796Z" }, + { url = "https://files.pythonhosted.org/packages/ec/85/e7297e34133ae1cfde3bffd30c24e1ef055248251baa877834e048687a28/click-8.2.2-py3-none-any.whl", hash = "sha256:52e1e9f5d3db8c85aa76968c7c67ed41ddbacb167f43201511c8fd61eb5ba2ca", size = 103900, upload-time = "2025-08-02T02:23:39.299Z" }, ] [[package]] @@ -1588,7 +1588,7 @@ requires-dist = [ { name = "requests", specifier = ">=2.28" }, { name = "scipy", specifier = ">=1.10" }, { name = "setuptools", specifier = ">=66" }, - { name = "sphinx", marker = "extra == 'docs'", specifier = ">=8.2.3" }, + { name = "sphinx", marker = "extra == 'docs'", specifier = ">=8.2.3,<8.3" }, { name = "sphinx-changelog", marker = "extra == 'docs'", specifier = ">=1.5" }, { name = "sphinx-codeautolink", marker = "extra == 'docs'", specifier = "==0.15.2" }, { name = "sphinx-collapse", marker = "extra == 'docs'", specifier = ">=0.1.3" }, From feb3a58d7d8e8f08bf4ccc23b23023e694fc000f Mon Sep 17 00:00:00 2001 From: Nick Murphy Date: Mon, 4 Aug 2025 21:02:57 -0400 Subject: [PATCH 436/521] Remove upper limits on versions of Astropy and xarray (#3065) * Remove upper limits for astropy & xarray * Edit changelog: 3065.internal.rst * nox -s requirements * Fix first bug * Edit changelog: 3065.internal.rst * move all attribute existence tests to dedicated test TestCheckUnits.test_method_existence() * Edit changelog: 3065.bugfix.rst * nox -s requirements * Edit changelog: 3065.bugfix.rst * parametrize TestCheckUnits.text_cu_method__get_unit_checks() * remove uses of textwrap.dedent * update test to handle the fact that an astropy Equivalency does not equate to a list * update annotations * appease grumpy black * correct asserting * add description back into assert fail message * appease grumpy ruff * appease grumpy ruff formatting * do element wise equating of equivalencies list * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Bump minimum version of astropy * nox -s requirements * Bump minimum version of Astropy - SPEC 0 * Skip a test for older Astropys * pre-commit * nox -s requirements * binding_energy -> nuclear_binding_energy * Update changelog entries * nox -s requirements --------- Co-authored-by: Erik Everson Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- changelog/3065.bugfix.rst | 2 + changelog/3065.internal.1.rst | 1 + changelog/3065.internal.2.rst | 2 + changelog/3065.internal.3.rst | 1 + .../notebooks/getting_started/particles.ipynb | 2 +- pyproject.toml | 8 +- src/plasmapy/plasma/grids.py | 8 +- tests/utils/decorators/test_checks.py | 398 ++++++++++-------- uv.lock | 325 +++++++------- 9 files changed, 415 insertions(+), 332 deletions(-) create mode 100644 changelog/3065.bugfix.rst create mode 100644 changelog/3065.internal.1.rst create mode 100644 changelog/3065.internal.2.rst create mode 100644 changelog/3065.internal.3.rst diff --git a/changelog/3065.bugfix.rst b/changelog/3065.bugfix.rst new file mode 100644 index 0000000000..0ae4911d17 --- /dev/null +++ b/changelog/3065.bugfix.rst @@ -0,0 +1,2 @@ +Fixed a possible bug when using `plasmapy.plasma.grids.AbstractGrid.add_quantities` +alongside newer versions of |xarray|. diff --git a/changelog/3065.internal.1.rst b/changelog/3065.internal.1.rst new file mode 100644 index 0000000000..fd0e6c3c07 --- /dev/null +++ b/changelog/3065.internal.1.rst @@ -0,0 +1 @@ +Removed upper limits on the allowed versions of Astropy and xarray. diff --git a/changelog/3065.internal.2.rst b/changelog/3065.internal.2.rst new file mode 100644 index 0000000000..cbd4f2a6e3 --- /dev/null +++ b/changelog/3065.internal.2.rst @@ -0,0 +1,2 @@ +Updated :file:`tests/utils/decorators/test_checks.py` for compatibility with +updates to how `astropy.units.Equivalency` handles equality comparisons. diff --git a/changelog/3065.internal.3.rst b/changelog/3065.internal.3.rst new file mode 100644 index 0000000000..b7ba187190 --- /dev/null +++ b/changelog/3065.internal.3.rst @@ -0,0 +1 @@ +Parametrized tests within :file:`tests/utils/decorators.test_checks.py`. diff --git a/docs/notebooks/getting_started/particles.ipynb b/docs/notebooks/getting_started/particles.ipynb index f1049dcb85..f154e9a6fb 100644 --- a/docs/notebooks/getting_started/particles.ipynb +++ b/docs/notebooks/getting_started/particles.ipynb @@ -321,7 +321,7 @@ "metadata": {}, "outputs": [], "source": [ - "iron56_nuclide.binding_energy" + "iron56_nuclide.nuclear_binding_energy" ] }, { diff --git a/pyproject.toml b/pyproject.toml index d921eb5148..5e3273e484 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -56,13 +56,12 @@ dynamic = [ "version" ] # pinned environments in `uv.lock`. dependencies = [ - # astropy upper limit described in https://github.com/PlasmaPy/PlasmaPy/issues/2883 - "astropy>=5.2,<7", + "astropy>=6", "h5py>=3.8", "lmfit>=1.1", "matplotlib>=3.7", "mpmath>=1.3", - "numpy>=1.24", + "numpy>=1.25", "packaging>=22", "pandas>=2", "requests>=2.28", @@ -70,8 +69,7 @@ dependencies = [ "setuptools>=66", "tqdm>=4.65", "wrapt>=1.15", - # xarray upper limit described in: https://github.com/PlasmaPy/PlasmaPy/issues/2922 - "xarray>=2022.12,<=2024.10", + "xarray>=2023.7", ] # The documentation build occurs in an isolated environment that is not diff --git a/src/plasmapy/plasma/grids.py b/src/plasmapy/plasma/grids.py index b6009f0742..39d9078cb3 100644 --- a/src/plasmapy/plasma/grids.py +++ b/src/plasmapy/plasma/grids.py @@ -667,9 +667,15 @@ def add_quantities(self, **kwargs: u.Quantity) -> None: f"does not match the grid shape {self.shape}." ) + # xarray gained better Quantity support around v2024.11.0, but + # this file was originally written with the assumption that + # xarray lacks Quantity support. As a workaround, use + # `quantity.value` instead of `quantity` in the creation of + # this DataArray. data = xr.DataArray( - quantity, dims=dims, coords=coords, attrs={"unit": quantity.unit} + quantity.value, dims=dims, coords=coords, attrs={"unit": quantity.unit} ) + self.ds[key] = data @property diff --git a/tests/utils/decorators/test_checks.py b/tests/utils/decorators/test_checks.py index 05388055da..d90216ceb9 100644 --- a/tests/utils/decorators/test_checks.py +++ b/tests/utils/decorators/test_checks.py @@ -4,10 +4,12 @@ """ import inspect +from contextlib import nullcontext as does_not_raise from types import LambdaType from typing import Any from unittest import mock +import astropy import astropy.units as u import numpy as np import pytest @@ -28,10 +30,9 @@ RelativityWarning, ) +does_not_warn = does_not_raise + -# ---------------------------------------------------------------------------------------- -# Test Decorator class `CheckBase` -# ---------------------------------------------------------------------------------------- class TestCheckBase: """ Test for decorator class :class:`~plasmapy.utils.decorators.checks.CheckBase`. @@ -87,10 +88,24 @@ def foo_with_none(x: u.Quantity, y: u.cm = None): # noqa: ANN205 def test_inheritance(self) -> None: assert issubclass(CheckUnits, CheckBase) + @pytest.mark.parametrize( + "name", + [ + "_CheckUnits__check_defaults", + "_flatten_equivalencies_list", + "_condition_target_units", + "_normalize_equivalencies", + "_get_unit_checks", + "_check_unit", + "_check_unit_core", + ], + ) + def test_method_existence(self, name: str) -> None: + assert hasattr(CheckUnits, name) + def test_cu_default_check_values(self) -> None: """Test the default check dictionary for CheckUnits.""" cu = CheckUnits() - assert hasattr(cu, "_CheckUnits__check_defaults") assert isinstance(cu._CheckUnits__check_defaults, dict) _defaults = [ ("units", None), @@ -102,8 +117,6 @@ def test_cu_default_check_values(self) -> None: assert cu._CheckUnits__check_defaults[key] == val def test_cu_method__flatten_equivalencies_list(self) -> None: - assert hasattr(CheckUnits, "_flatten_equivalencies_list") - cu = CheckUnits() pairs = [([1, 2, 4], [1, 2, 4]), ([1, 2, (3, 4), [5, 6]], [1, 2, (3, 4), 5, 6])] for pair in pairs: @@ -111,7 +124,6 @@ def test_cu_method__flatten_equivalencies_list(self) -> None: def test_cu_method__condition_target_units(self) -> None: """Test method `CheckUnits._condition_target_units`.""" - assert hasattr(CheckUnits, "_condition_target_units") cu = CheckUnits() @@ -130,7 +142,6 @@ def test_cu_method__condition_target_units(self) -> None: def test_cu_method__normalize_equivalencies(self) -> None: """Test method `CheckUnits._normalize_equivalencies`.""" - assert hasattr(CheckUnits, "_normalize_equivalencies") cu = CheckUnits() @@ -181,90 +192,88 @@ def test_cu_method__normalize_equivalencies(self) -> None: with pytest.raises(ValueError): cu._normalize_equivalencies([("cm", u.cm)]) - def test_cu_method__get_unit_checks(self) -> None: - """ - Test functionality/behavior of the method `_get_unit_checks` on `CheckUnits`. - This method reviews the decorator `checks` arguments and wrapped function - annotations to build a complete checks dictionary. - """ - # methods must exist - assert hasattr(CheckUnits, "_get_unit_checks") - - # setup default checks - default_checks = { - **self.check_defaults.copy(), - "units": [self.check_defaults["units"]], - } - - # setup test cases - # 'setup' = arguments for `_get_unit_checks` - # 'output' = expected return from `_get_unit_checks` - # 'raises' = if `_get_unit_checks` raises an Exception - # 'warns' = if `_get_unit_checks` issues a warning - # - equivs = [ - # list of astropy Equivalency objects - [u.temperature_energy(), u.temperature()], - # list of equivalencies (pre astropy v3.2.1 style) - list(u.temperature()), - ] - _cases = [ - { - "description": "x units are defined via decorator kwarg of CheckUnits\n" - "y units are defined via decorator annotations, additional\n" - " checks thru CheckUnits kwarg", - "setup": { - "function": self.foo_partial_anno, + @pytest.mark.parametrize( + ("description", "setup", "expected", "warn_context", "raise_context"), + [ + ( + "x units are defined via decorator kwarg of CheckUnits " + "y units are defined via decorator annotations, additional " + "checks thru CheckUnits kwarg", + { + "function": foo_partial_anno, "args": (2 * u.cm, 3 * u.cm), "kwargs": {}, - "checks": {"x": {"units": [u.cm], "equivalencies": equivs[0][0]}}, + "checks": { + "x": { + "units": [u.cm], + "equivalencies": u.temperature_energy(), + }, + }, }, - "output": { - "x": {"units": [u.cm], "equivalencies": equivs[0][0]}, + { + "x": {"units": [u.cm], "equivalencies": u.temperature_energy()}, "y": {"units": [u.cm]}, }, - }, - { - "description": "x units are defined via decorator kwarg of CheckUnits\n" - "y units are defined via function annotations, additional\n" - " checks thru CheckUnits kwarg", - "setup": { - "function": self.foo_partial_anno, + does_not_warn(), + does_not_raise(), + ), + ( + "x units are defined via decorator kwarg of CheckUnits " + "y units are defined via function annotations, additional " + "checks thru CheckUnits kwarg", + { + "function": foo_partial_anno, "args": (2 * u.cm, 3 * u.cm), "kwargs": {}, "checks": { - "x": {"units": [u.cm], "equivalencies": equivs[0]}, + "x": { + "units": [u.cm], + "equivalencies": [ + u.temperature_energy(), + u.temperature(), + ], + }, "y": {"pass_equivalent_units": False}, }, }, - "output": { + { "x": { "units": [u.cm], - "equivalencies": equivs[0][0] + equivs[0][1], + "equivalencies": u.temperature_energy() + u.temperature(), }, "y": {"units": [u.cm], "pass_equivalent_units": False}, }, - }, - { - "description": "equivalencies are a list instead of astropy Equivalency objects", - "setup": { - "function": self.foo_no_anno, + does_not_warn(), + does_not_raise(), + ), + ( + "equivalencies are a list instead of astropy Equivalency objects", + { + "function": foo_no_anno, "args": (2 * u.K, 3 * u.K), "kwargs": {}, "checks": { - "x": {"units": [u.K], "equivalencies": equivs[1][0]}, - "y": {"units": [u.K], "equivalencies": equivs[1]}, + "x": { + "units": [u.K], + "equivalencies": next(iter(u.temperature())), + }, + "y": {"units": [u.K], "equivalencies": list(u.temperature())}, }, }, - "output": { - "x": {"units": [u.K], "equivalencies": [equivs[1][0]]}, - "y": {"units": [u.K], "equivalencies": equivs[1]}, + { + "x": { + "units": [u.K], + "equivalencies": [next(iter(u.temperature()))], + }, + "y": {"units": [u.K], "equivalencies": list(u.temperature())}, }, - }, - { - "description": "number of checked arguments exceed number of function arguments", - "setup": { - "function": self.foo_partial_anno, + does_not_warn(), + does_not_raise(), + ), + ( + "number of checked arguments exceed number of function arguments", + { + "function": foo_partial_anno, "args": (2 * u.cm, 3 * u.cm), "kwargs": {}, "checks": { @@ -273,13 +282,17 @@ def test_cu_method__get_unit_checks(self) -> None: "z": {"units": [u.cm]}, }, }, - "warns": PlasmaPyWarning, - "output": {"x": {"units": [u.cm]}, "y": {"units": [u.cm]}}, - }, - { - "description": "arguments passed via *args and **kwargs are ignored", - "setup": { - "function": self.foo_stars, + { + "x": {"units": [u.cm]}, + "y": {"units": [u.cm]}, + }, + pytest.warns(PlasmaPyWarning), + does_not_raise(), + ), + ( + "arguments passed via *args and **kwargs are ignored", + { + "function": foo_stars, "args": (2 * u.cm, "hello"), "kwargs": {"z": None}, "checks": { @@ -288,150 +301,200 @@ def test_cu_method__get_unit_checks(self) -> None: "z": {"units": [u.cm]}, }, }, - "warns": PlasmaPyWarning, - "output": {"x": {"units": [u.cm]}, "y": {"units": [u.cm]}}, - }, - { - "description": "arguments can be None values", - "setup": { - "function": self.foo_with_none, + { + "x": {"units": [u.cm]}, + "y": {"units": [u.cm]}, + }, + pytest.warns(PlasmaPyWarning), + does_not_raise(), + ), + ( + "arguments can be None values", + { + "function": foo_with_none, "args": (2 * u.cm, 3 * u.cm), "kwargs": {}, "checks": {"x": {"units": [u.cm, None]}}, }, - "output": { + { "x": {"units": [u.cm], "none_shall_pass": True}, "y": {"units": [u.cm], "none_shall_pass": True}, }, - }, - { - "description": "checks and annotations do not specify units", - "setup": { - "function": self.foo_no_anno, + does_not_warn(), + does_not_raise(), + ), + ( + "checks and annotations do not specify units", + { + "function": foo_no_anno, "args": (2 * u.cm, 3 * u.cm), "kwargs": {}, "checks": {"x": {"pass_equivalent_units": True}}, }, - "raises": ValueError, - }, - { - "description": "units are directly assigned to the check kwarg", - "setup": { - "function": self.foo_partial_anno, + {}, + does_not_warn(), + pytest.raises(ValueError), + ), + ( + "units are directly assigned to the check kwarg", + { + "function": foo_partial_anno, "args": (2 * u.cm, 3 * u.cm), "kwargs": {}, "checks": {"x": u.cm}, }, - "output": {"x": {"units": [u.cm]}, "y": {"units": [u.cm]}}, - }, - { - "description": "return units are assigned via checks", - "setup": { - "function": self.foo_no_anno, + {"x": {"units": [u.cm]}, "y": {"units": [u.cm]}}, + does_not_warn(), + does_not_raise(), + ), + ( + "return units are assigned via checks", + { + "function": foo_no_anno, "args": (2 * u.km, 3 * u.km), "kwargs": {}, "checks": {"checks_on_return": u.km}, }, - "output": {"checks_on_return": {"units": [u.km]}}, - }, - { - "description": "return units are assigned via annotations", - "setup": { - "function": self.foo_return_anno, + {"checks_on_return": {"units": [u.km]}}, + does_not_warn(), + does_not_raise(), + ), + ( + "return units are assigned via annotations", + { + "function": foo_return_anno, "args": (2 * u.cm, 3 * u.cm), "kwargs": {}, "checks": {}, }, - "output": {"checks_on_return": {"units": [u.um]}}, - }, - { - "description": "return units are assigned via annotations and checks arg, but" + {"checks_on_return": {"units": [u.um]}}, + does_not_warn(), + does_not_raise(), + ), + ( + "return units are assigned via annotations and checks arg, but " "are not consistent", - "setup": { - "function": self.foo_return_anno, + { + "function": foo_return_anno, "args": (2 * u.cm, 3 * u.cm), "kwargs": {}, "checks": {"checks_on_return": {"units": u.km}}, }, - "raises": ValueError, - }, - { - "description": "return units are not specified but other checks are", - "setup": { - "function": self.foo_no_anno, + {}, + does_not_warn(), + pytest.raises(ValueError), + ), + ( + "return units are not specified but other checks are", + { + "function": foo_no_anno, "args": (2 * u.cm, 3 * u.cm), "kwargs": {}, "checks": {"checks_on_return": {"pass_equivalent_units": True}}, }, - "raises": ValueError, - }, - { - "description": "no parameter checks for x are defined, but a non-unit annotation" + {}, + does_not_warn(), + pytest.raises(ValueError), + ), + ( + "no parameter checks for x are defined, but a non-unit annotation " "is used", - "setup": { - "function": self.foo_partial_anno, + { + "function": foo_partial_anno, "args": (2 * u.cm, 3 * u.cm), "kwargs": {}, "checks": {}, }, - "output": {"y": {"units": [u.cm]}}, - }, - { - "description": "parameter checks defined for x but unit checks calculated from" + {"y": {"units": [u.cm]}}, + does_not_warn(), + does_not_raise(), + ), + ( + "parameter checks defined for x but unit checks calculated from " "function annotations. Function annotations do NOT define " "a proper unit type.", - "setup": { - "function": self.foo_partial_anno, + { + "function": foo_partial_anno, "args": (2 * u.cm, 3 * u.cm), "kwargs": {}, "checks": {"x": {"pass_equivalent_units": True}}, }, - "raises": ValueError, - }, - { - "description": "parameter checks defined for return argument but unit checks " + {}, + does_not_warn(), + pytest.raises(ValueError), + ), + ( + "parameter checks defined for return argument but unit checks " "calculated from function annotations. Function annotations do " "NOT define a proper unit type.", - "setup": { - "function": self.foo_partial_anno, + { + "function": foo_partial_anno, "args": (2 * u.cm, 3 * u.cm), "kwargs": {}, "checks": {"checks_on_return": {"pass_equivalent_units": True}}, }, - "raises": ValueError, - }, - ] + {}, + does_not_warn(), + pytest.raises(ValueError), + ), + ], + ) + @pytest.mark.skipif(astropy.__version__ < "7", reason="see #3065") + def test_cu_method__get_unit_checks( + self, + description: str, + setup: dict[str, Any], + expected: dict[str, Any], + warn_context, + raise_context, + ) -> None: + """ + Test functionality/behavior of the method `_get_unit_checks` on `CheckUnits`. + This method reviews the decorator `checks` arguments and wrapped function + annotations to build a complete checks dictionary. + """ + + # setup default checks + default_checks = { + **self.check_defaults.copy(), + "units": [self.check_defaults["units"]], + } + + sig = inspect.signature(setup["function"]) + bound_args = sig.bind(*setup["args"], **setup["kwargs"]) # perform tests - for _ii, case in enumerate(_cases): - sig = inspect.signature(case["setup"]["function"]) - bound_args = sig.bind(*case["setup"]["args"], **case["setup"]["kwargs"]) + cu = CheckUnits(**setup["checks"]) + cu.f = setup["function"] + with warn_context, raise_context: + checks = cu._get_unit_checks(bound_args) - cu = CheckUnits(**case["setup"]["checks"]) - cu.f = case["setup"]["function"] - if "warns" in case: - with pytest.warns(case["warns"]): - checks = cu._get_unit_checks(bound_args) - elif "raises" in case: - with pytest.raises(case["raises"]): - cu._get_unit_checks(bound_args) - continue - else: - checks = cu._get_unit_checks(bound_args) + if not isinstance(raise_context, does_not_raise): + # method call raised except, no more tests needed + return - # only expected argument checks exist - assert sorted(checks.keys()) == sorted(case["output"].keys()) + # only expected argument checks exist + assert set(checks.keys()) == set(expected.keys()) - # if check key-value not specified then default is assumed - for arg_name in case["output"]: - arg_checks = checks[arg_name] + # if check key-value not specified then default is assumed + for arg_name, expected_checks in expected.items(): + for key in default_checks: # noqa: PLC0206 + _check = checks[arg_name][key] - for key, val in default_checks.items(): - if key in case["output"][arg_name]: - val = case["output"][arg_name][key] # noqa: PLW2901 - assert arg_checks[key] == val, ( - f"{case['description'] = }\n\n{arg_checks[key] = }\n\n{val = }" - ) + if key in expected_checks: + val = expected_checks[key] + else: + val = default_checks[key] + + if key == "equivalencies" and _check is not None and val is not None: + # Note: for some reason an equals comparison of an Equivalency + # and a list are not equal even if all the elements + # are equal. astropy.units.Equivalency is a subclass + # of a list...lets just do elementwise comparison instead + + assert all(_c == _v for _c, _v in zip(_check, val, strict=False)) + else: + assert _check == val, description def test_cu_method__check_unit(self) -> None: """ @@ -439,9 +502,6 @@ def test_cu_method__check_unit(self) -> None: on `CheckUnits`. These methods do the actual checking of the argument units and should be called by `CheckUnits.__call__()`. """ - # methods must exist - assert hasattr(CheckUnits, "_check_unit") - assert hasattr(CheckUnits, "_check_unit_core") # setup default checks check = {**self.check_defaults, "units": [u.cm]} diff --git a/uv.lock b/uv.lock index f6c1642159..dfef47f8e7 100644 --- a/uv.lock +++ b/uv.lock @@ -44,7 +44,7 @@ wheels = [ [[package]] name = "astropy" -version = "6.1.7" +version = "7.1.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "astropy-iers-data" }, @@ -53,38 +53,38 @@ dependencies = [ { name = "pyerfa" }, { name = "pyyaml" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/8a/f8/9c6675ab4c646b95aae2762d108f6be4504033d91bd50da21daa62cab5ce/astropy-6.1.7.tar.gz", hash = "sha256:a405ac186306b6cb152e6df2f7444ab8bd764e4127d7519da1b3ae4dd65357ef", size = 7063411, upload-time = "2024-11-22T21:22:34.373Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/4f/5e/d31204823764f6e5fa4820c1b4f49f8eef7cf691b796ec389f41b4f5a699/astropy-6.1.7-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:09edca01276ee63f7b2ff511da9bfb432068ba3242e27ef27d76e5a171087b7e", size = 6531221, upload-time = "2024-11-22T21:21:46.2Z" }, - { url = "https://files.pythonhosted.org/packages/22/e2/ae5dd6d9272e41619d85df4e4a03cf06acea8bcb44c42fe67e5cd04ae131/astropy-6.1.7-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:072f62a67992393beb016dc80bee8fb994fda9aa69e945f536ed8ac0e51291e6", size = 6409477, upload-time = "2024-11-22T21:21:47.862Z" }, - { url = "https://files.pythonhosted.org/packages/01/ed/9bc17beb457943ee04b8c85614ddb4a64a4a91597340dca28332e112209d/astropy-6.1.7-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b2706156d3646f9c9a7fc810475d8ab0df4c717beefa8326552576a0f8ddca20", size = 10150734, upload-time = "2024-11-22T21:21:49.847Z" }, - { url = "https://files.pythonhosted.org/packages/39/38/1c5263f0d775def518707ccd1cf9d4df1d99d523fc148df9e38aa5ba9d54/astropy-6.1.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fcd99e627692f8e58bb3097d330bfbd109a22e00dab162a67f203b0a0601ad2c", size = 10210679, upload-time = "2024-11-22T21:21:52.011Z" }, - { url = "https://files.pythonhosted.org/packages/32/d1/7365e16b0158f755977a5bdbd329df40a9772b0423a1d5075aba9246673f/astropy-6.1.7-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b0ebbcb637b2e9bcb73011f2b7890d7a3f5a41b66ccaad7c28f065e81e28f0b2", size = 10245960, upload-time = "2024-11-22T21:21:54.785Z" }, - { url = "https://files.pythonhosted.org/packages/e9/b6/4dc6f9ef1c17738b8ebd8922bc1c6fec48542ccfe5124b6719737b012b8c/astropy-6.1.7-cp311-cp311-win32.whl", hash = "sha256:192b12ede49cd828362ab1a6ede2367fe203f4d851804ec22fa92e009a524281", size = 6272124, upload-time = "2024-11-22T21:21:57.504Z" }, - { url = "https://files.pythonhosted.org/packages/ba/c6/b5f33597bfbc1afad0640b20000633127dfa0a4295b607a0439f45546d9a/astropy-6.1.7-cp311-cp311-win_amd64.whl", hash = "sha256:3cac64bcdf570c947019bd2bc96711eeb2c7763afe192f18c9551e52a6c296b2", size = 6396627, upload-time = "2024-11-22T21:21:59.913Z" }, - { url = "https://files.pythonhosted.org/packages/46/2b/007c888fead170c714ecdcf56bc59e8d3252776bd3f16e1797158a46f65d/astropy-6.1.7-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f2a8bcbb1306052cc38c9eed2c9331bfafe2582b499a7321946abf74b26eb256", size = 6535604, upload-time = "2024-11-22T21:22:02.515Z" }, - { url = "https://files.pythonhosted.org/packages/8e/4c/cc30c9b1440f4a2f1f52845873ae3f8f7c4343261e516603a35546574ed7/astropy-6.1.7-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:eaf88878684f9d31aff36475c90d101f4cff22fdd4fd50098d9950fd56994df7", size = 6415117, upload-time = "2024-11-22T21:22:04.484Z" }, - { url = "https://files.pythonhosted.org/packages/12/2d/9985b8b4225c2495c4e64713d1630937c83af863db606d12676b72b4f651/astropy-6.1.7-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1cb8cd231e53556e4eebe0393ea95a8cea6b2ff4187c95ac4ff8b17e7a8da823", size = 10177861, upload-time = "2024-11-22T21:22:06.043Z" }, - { url = "https://files.pythonhosted.org/packages/b7/b6/63ccb085757638d15f0f9d6f2dffaccce7785236fe8bf23e4b380a333ce0/astropy-6.1.7-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5ad36334d138a4f71d6fdcf225a98ad1dad6c343da4362d5a47a71f5c9da3ca9", size = 10258014, upload-time = "2024-11-22T21:22:08.164Z" }, - { url = "https://files.pythonhosted.org/packages/c8/ee/a6af891802de463f70e3fddf09f3aeb1d46dde87885e2245d25a2ac46948/astropy-6.1.7-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:dd731c526869d0c68507be7b31dd10871b7c44d310bb5495476505560c83cd33", size = 10277363, upload-time = "2024-11-22T21:22:10.331Z" }, - { url = "https://files.pythonhosted.org/packages/dd/98/b253583f9de7033f03a7c5f5314b9e93177725a2020e0f36d338d242bf0e/astropy-6.1.7-cp312-cp312-win32.whl", hash = "sha256:662bacd7ae42561e038cbd85eea3b749308cf3575611a745b60f034d3350c97a", size = 6271741, upload-time = "2024-11-22T21:22:12.696Z" }, - { url = "https://files.pythonhosted.org/packages/7a/63/e1b5f01e6735ed8f9d62d3eed5f226bc0ab516ab8558ffaccf6d4185f91d/astropy-6.1.7-cp312-cp312-win_amd64.whl", hash = "sha256:5b4d02a98a0bf91ff7fd4ef0bd0ecca83c9497338cb88b61ec9f971350688222", size = 6396352, upload-time = "2024-11-22T21:22:14.525Z" }, - { url = "https://files.pythonhosted.org/packages/73/9d/21d2e61080a81e7e1f5e5006204a76e70588aa1a88aa9044c2d203578d07/astropy-6.1.7-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:fbeaf04427987c0c6fa2e579eb40011802b06fba6b3a7870e082d5c693564e1b", size = 6528360, upload-time = "2024-11-22T21:22:16.275Z" }, - { url = "https://files.pythonhosted.org/packages/d5/3e/b999ec6cd607c512e66d8a138443361eb88899760c7cb8517a66155732ee/astropy-6.1.7-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:ab6e88241a14185b9404b02246329185b70292984aa0616b20a0628dfe4f4ebb", size = 6407905, upload-time = "2024-11-22T21:22:18.035Z" }, - { url = "https://files.pythonhosted.org/packages/db/2d/44557c63688c2ed03d0d72b4f27fc30fc1ea250aeb5ebd939796c5f98bee/astropy-6.1.7-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0529c75565feaabb629946806b4763ae7b02069aeff4c3b56a69e8a9e638500", size = 10106849, upload-time = "2024-11-22T21:22:20.393Z" }, - { url = "https://files.pythonhosted.org/packages/66/bc/993552eb932dec528fe6b95f511e918473ea4406dee4b17c223f3fd8a919/astropy-6.1.7-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c5ec347631da77573fc729ba04e5d89a3bc94500bf6037152a2d0f9965ae1ce", size = 10194766, upload-time = "2024-11-22T21:22:23.116Z" }, - { url = "https://files.pythonhosted.org/packages/9f/f3/3c5282762c8a5746e7752e46a1e328c79a5d0186d96cfd0995bdf976e1f9/astropy-6.1.7-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:dc496f87aaccaa5c6624acc985b8770f039c5bbe74b120c8ed7bad3698e24e1b", size = 10219291, upload-time = "2024-11-22T21:22:26.079Z" }, - { url = "https://files.pythonhosted.org/packages/d8/52/949bb79df9c03f56d0ae93ac62f2616fe3e67db51677bf412473bf6d077e/astropy-6.1.7-cp313-cp313-win32.whl", hash = "sha256:b1e01d534383c038dbf8664b964fa4ea818c7419318830d3c732c750c64115c6", size = 6269501, upload-time = "2024-11-22T21:22:28.468Z" }, - { url = "https://files.pythonhosted.org/packages/a1/da/f369561a67061dd42e13c7f758b393ae90319dbbcf7e301a18ce3fa43ec6/astropy-6.1.7-cp313-cp313-win_amd64.whl", hash = "sha256:af08cf2b0368f1ea585eb26a55d99a2de9e9b0bd30aba84b5329059c3ec33590", size = 6393207, upload-time = "2024-11-22T21:22:31.797Z" }, +sdist = { url = "https://files.pythonhosted.org/packages/83/91/124d020cea78e4e4b6db7ff726c2c2e4a5865293d0a4355d13b0312d99f1/astropy-7.1.0.tar.gz", hash = "sha256:c8f254322295b1b8cf24303d6f155bf7efdb6c1282882b966ce3040eff8c53c5", size = 6976116, upload-time = "2025-05-20T13:40:10.557Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fe/0d/ed4d605f8dfa8ec236dd2c91489b24d223fa98f41f181437f6d15a98190d/astropy-7.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:8e2bc5cb91dc319bcf65ee08c68abea617c52b5d042d245542a4853b07269233", size = 6378504, upload-time = "2025-05-20T13:39:29.056Z" }, + { url = "https://files.pythonhosted.org/packages/de/18/38e92baafca43f654704d7ca8cd0efdd626d9987d9918de08abe8a1cb297/astropy-7.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fba97e3d99ad48540b6eb7c6f7849e57dd6aaf9d9d48707b227bf39ac77c6368", size = 6303097, upload-time = "2025-05-20T13:39:31.586Z" }, + { url = "https://files.pythonhosted.org/packages/f9/03/cca1b2259ab22dae67a7d7a7b22454206c0fb5384e99b00d2326663fbed6/astropy-7.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a58498f9549a0e94a1f2cd48ddb96c0bed7b0375a6362ee4025f19d6bd114f9a", size = 10080125, upload-time = "2025-05-20T13:39:33.034Z" }, + { url = "https://files.pythonhosted.org/packages/80/a1/87254b4f8ec58308ad745574da66fd205ba59da74cdf7e8319d442bb3161/astropy-7.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7694e0b2ffc5fa60c47a55667bdfda98cbae8df736f60cc57afbe38bc5c98b41", size = 10087022, upload-time = "2025-05-20T13:39:35.315Z" }, + { url = "https://files.pythonhosted.org/packages/d7/4d/96f3806e6cf50dd8bd08ccac668e54d3d66b43bf5574bf27bf5fbad4de74/astropy-7.1.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:83fe4c581bbdf1cbaeab1efc58891e4433d729412847f4d0788c870fee709432", size = 10120923, upload-time = "2025-05-20T13:39:39.781Z" }, + { url = "https://files.pythonhosted.org/packages/a3/c2/0f089b4c387fc6a4b4ac9760b8a5ec3b3552af7ecf4d3a372963cd5d43e2/astropy-7.1.0-cp311-cp311-win32.whl", hash = "sha256:a2d277cf0d34748bfc23bb6b4d1974f058c8541ec92113cb00db06eebe5a2862", size = 6151431, upload-time = "2025-05-20T13:39:41.974Z" }, + { url = "https://files.pythonhosted.org/packages/3f/7e/13b136c020e009daf8481163087f287c634cd44aad600becc6cdafa6c0b1/astropy-7.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:3b66b8dbb678fca9a811f24227a953a3c2f7b02c951c5b2dee3ab6853ac6e1b0", size = 6278397, upload-time = "2025-05-20T13:39:43.709Z" }, + { url = "https://files.pythonhosted.org/packages/cf/9a/ed2b35b55e28a6317471b61456d2feda7798b2dd3601e17859620e8eae4c/astropy-7.1.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:e0fec2f4b5265caab68020eaa320704e7ce9433ae8dbea75c300468fed695437", size = 6381273, upload-time = "2025-05-20T13:39:45.481Z" }, + { url = "https://files.pythonhosted.org/packages/5c/45/333bc1072f3b2ac31aec33063bb7122661405a97cb7fec702e95af707bd4/astropy-7.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:e4bb022f863cf13eefeb406692f58824c0d9bdb1aa36ae786e87c096d8ebdd07", size = 6301716, upload-time = "2025-05-20T13:39:47.339Z" }, + { url = "https://files.pythonhosted.org/packages/58/90/bfb7a1b5d9e3401967e351cf31add576cddf7466d2030cc6f4d1d841a18d/astropy-7.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c811a4aedd8fbf6d7611d64d40af1f0c1c1e6621e5992e7e1a7b5fec47dc1fa1", size = 10096600, upload-time = "2025-05-20T13:39:49.169Z" }, + { url = "https://files.pythonhosted.org/packages/fb/69/a34f20db7146912f25e2487c5283f1ae2aed5d24f615fa976439ece35f7e/astropy-7.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:654261df547c150e5b6a022f3785f47a2e547e0cc1c06fbcf6293b5f4e85722a", size = 10160320, upload-time = "2025-05-20T13:39:51.079Z" }, + { url = "https://files.pythonhosted.org/packages/7a/be/0b874f551acbac27ff3d5d73bdf3c0860a8b78c6db574b19e6d0b7d363e4/astropy-7.1.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:6bd25761ba1385bb99a189401fbc486e0884d97129e271b655b6efa956a12a77", size = 10137307, upload-time = "2025-05-20T13:39:53.175Z" }, + { url = "https://files.pythonhosted.org/packages/ea/1c/132241ab2006a52b4809ee82a71fde793c0159916ae45dae374b0412b037/astropy-7.1.0-cp312-cp312-win32.whl", hash = "sha256:f637e39622b23750a12b19ab4642f2e3970f6cb84f2228587725f15bf1d80d03", size = 6152433, upload-time = "2025-05-20T13:39:54.933Z" }, + { url = "https://files.pythonhosted.org/packages/11/39/0a38241008905a9c1048f7b351310deee71cf42e0de1f929e84a10878864/astropy-7.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:06ba650db237557912fdd7bb8ffdd87838e23e58b0fa0001b4d43c2bb5a79412", size = 6279663, upload-time = "2025-05-20T13:39:56.274Z" }, + { url = "https://files.pythonhosted.org/packages/a3/d6/ec68703aff787ca1bb2ed92a109256a6e4d9975aeee0b4bd2b0ab84b2993/astropy-7.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:116149abdebafab193f7ca16427bd6bb4afc111677c78c32f48cffbc0ecb6a18", size = 6375607, upload-time = "2025-05-20T13:39:57.6Z" }, + { url = "https://files.pythonhosted.org/packages/2b/79/0f6eacbe575c3b677d70193c22b68c3a95bec68204ccf53068b657c7ed06/astropy-7.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:734d5e93e76d2e2175f991b17ca130463f2edb56c107fbc07c6532ca461a6ea7", size = 6296640, upload-time = "2025-05-20T13:39:58.973Z" }, + { url = "https://files.pythonhosted.org/packages/c7/c1/06bd8bd17b2302c05d75079ca89d79825dede63c00876e439ec91f120405/astropy-7.1.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fd94f755f2e9104c5caf0afe69175d2620708828233d387c1dad0044e79f543", size = 10030192, upload-time = "2025-05-20T13:40:01.129Z" }, + { url = "https://files.pythonhosted.org/packages/17/ce/f9e103e6be3d801cadffef8eb814bd10e4de3603b9ba9f97dd41c6a59bde/astropy-7.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:49effea6de855dcdba09a211d51ca279766c66284c8db3d911b4523bbd96eae9", size = 10079889, upload-time = "2025-05-20T13:40:03.076Z" }, + { url = "https://files.pythonhosted.org/packages/a3/fe/605a09e74b03ea2981632cd9a9a3720bd8d232ddaa729fc63ce46d538218/astropy-7.1.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:52709e6bbe65c6d6c2a342506ad8c2801ff2aed80cc0a5d7817387122e0ac616", size = 10084024, upload-time = "2025-05-20T13:40:04.776Z" }, + { url = "https://files.pythonhosted.org/packages/af/e9/8259c4699227e5ee71d5d15a297f1e9469b99a980a1fd3140ecf68e98c4d/astropy-7.1.0-cp313-cp313-win32.whl", hash = "sha256:a77d07a104ec24ed7f8a45de3935f46071551aa2eb6d6b62efebdc888f65b6d6", size = 6150536, upload-time = "2025-05-20T13:40:06.638Z" }, + { url = "https://files.pythonhosted.org/packages/0b/dd/d9c55247172f7156696d85c9146b64b41c30405bf86b775a731bed4d52f8/astropy-7.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:8e317f34e33a8f5517bc9fc6fbc005f42730d3be7d2820ef41e0468bcb796843", size = 6278127, upload-time = "2025-05-20T13:40:08.643Z" }, ] [[package]] name = "astropy-iers-data" -version = "0.2025.7.28.0.41.50" +version = "0.2025.8.4.0.42.59" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/a7/35/934488a768e1e0e891c38f3c905c7158d65ac99cea7f94d1fe614ebe985d/astropy_iers_data-0.2025.7.28.0.41.50.tar.gz", hash = "sha256:615b23572553ab2156131ccc6577be2f7528d79326bcde17ab788374aca085b2", size = 1903592, upload-time = "2025-07-28T00:42:27.429Z" } +sdist = { url = "https://files.pythonhosted.org/packages/07/f7/d6404e1a96eb71e7f5df2f52e135ceb15b43c1a7aff3173ff128e68c3fda/astropy_iers_data-0.2025.8.4.0.42.59.tar.gz", hash = "sha256:a6e8723fe962e2b4103aa7837d021e6857d0bf2b4de28a891cd4c8d1919d4129", size = 1904207, upload-time = "2025-08-04T00:43:44.386Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/45/0a/614957f5d35bc5b9a376e729bc31e1fae8ee226aecb1583179bbed889264/astropy_iers_data-0.2025.7.28.0.41.50-py3-none-any.whl", hash = "sha256:ed2ee1139f7838ce1e46cdc0024a7c169235f765a3e73b36d45ab6412cbbbb98", size = 1959055, upload-time = "2025-07-28T00:42:25.693Z" }, + { url = "https://files.pythonhosted.org/packages/eb/4e/905209e3b347a9d781623ac092ce7fc6ab55b67ae09d46fd5274b2d6eeba/astropy_iers_data-0.2025.8.4.0.42.59-py3-none-any.whl", hash = "sha256:b3cc6795083e7efed1d335d24534f0ca204e5950132e41a24b178ea1d659ded9", size = 1959667, upload-time = "2025-08-04T00:43:42.822Z" }, ] [[package]] @@ -146,11 +146,11 @@ css = [ [[package]] name = "certifi" -version = "2025.7.14" +version = "2025.8.3" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/b3/76/52c535bcebe74590f296d6c77c86dabf761c41980e1347a2422e4aa2ae41/certifi-2025.7.14.tar.gz", hash = "sha256:8ea99dbdfaaf2ba2f9bac77b9249ef62ec5218e7c2b2e903378ed5fccf765995", size = 163981, upload-time = "2025-07-14T03:29:28.449Z" } +sdist = { url = "https://files.pythonhosted.org/packages/dc/67/960ebe6bf230a96cda2e0abcf73af550ec4f090005363542f0765df162e0/certifi-2025.8.3.tar.gz", hash = "sha256:e564105f78ded564e3ae7c923924435e1daa7463faeab5bb932bc53ffae63407", size = 162386, upload-time = "2025-08-03T03:07:47.08Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/4f/52/34c6cf5bb9285074dc3531c437b3919e825d976fde097a7a73f79e726d03/certifi-2025.7.14-py3-none-any.whl", hash = "sha256:6b31f564a415d79ee77df69d757bb49a5bb53bd9f756cbbe24394ffd6fc1f4b2", size = 162722, upload-time = "2025-07-14T03:29:26.863Z" }, + { url = "https://files.pythonhosted.org/packages/e5/48/1549795ba7742c948d2ad169c1c8cdbae65bc450d6cd753d124b17c8cd32/certifi-2025.8.3-py3-none-any.whl", hash = "sha256:f6c12493cfb1b06ba2ff328595af9350c65d6644968e5d3a2ffd78699af217a5", size = 161216, upload-time = "2025-08-03T03:07:45.777Z" }, ] [[package]] @@ -248,14 +248,14 @@ wheels = [ [[package]] name = "click" -version = "8.2.2" +version = "8.2.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "colorama", marker = "sys_platform == 'win32'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/e9/87/105111999772ec9730e3d4d910c723ea9763ece2ec441533a5cea1e87e3c/click-8.2.2.tar.gz", hash = "sha256:068616e6ef9705a07b6db727cb9c248f4eb9dae437a30239f56fa94b18b852ef", size = 263977, upload-time = "2025-08-02T02:23:41.102Z" } +sdist = { url = "https://files.pythonhosted.org/packages/60/6c/8ca2efa64cf75a977a0d7fac081354553ebe483345c734fb6b6515d96bbc/click-8.2.1.tar.gz", hash = "sha256:27c491cc05d968d271d5a1db13e3b5a184636d9d930f148c50b038f0d0646202", size = 286342, upload-time = "2025-05-20T23:19:49.832Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ec/85/e7297e34133ae1cfde3bffd30c24e1ef055248251baa877834e048687a28/click-8.2.2-py3-none-any.whl", hash = "sha256:52e1e9f5d3db8c85aa76968c7c67ed41ddbacb167f43201511c8fd61eb5ba2ca", size = 103900, upload-time = "2025-08-02T02:23:39.299Z" }, + { url = "https://files.pythonhosted.org/packages/85/32/10bb5764d90a8eee674e9dc6f4db6a0ab47c8c4d0d83c27f7c39ac415a4d/click-8.2.1-py3-none-any.whl", hash = "sha256:61a3265b914e850b85317d0b3109c7f8cd35a670f963866005d6ef1d5175a12b", size = 102215, upload-time = "2025-05-20T23:19:47.796Z" }, ] [[package]] @@ -372,77 +372,77 @@ wheels = [ [[package]] name = "coverage" -version = "7.10.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/87/0e/66dbd4c6a7f0758a8d18044c048779ba21fb94856e1edcf764bd5403e710/coverage-7.10.1.tar.gz", hash = "sha256:ae2b4856f29ddfe827106794f3589949a57da6f0d38ab01e24ec35107979ba57", size = 819938, upload-time = "2025-07-27T14:13:39.045Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/20/8e/ef088112bd1b26e2aa931ee186992b3e42c222c64f33e381432c8ee52aae/coverage-7.10.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b45e2f9d5b0b5c1977cb4feb5f594be60eb121106f8900348e29331f553a726f", size = 214747, upload-time = "2025-07-27T14:11:18.217Z" }, - { url = "https://files.pythonhosted.org/packages/2d/76/a1e46f3c6e0897758eb43af88bb3c763cb005f4950769f7b553e22aa5f89/coverage-7.10.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3a7a4d74cb0f5e3334f9aa26af7016ddb94fb4bfa11b4a573d8e98ecba8c34f1", size = 215128, upload-time = "2025-07-27T14:11:19.706Z" }, - { url = "https://files.pythonhosted.org/packages/78/4d/903bafb371a8c887826ecc30d3977b65dfad0e1e66aa61b7e173de0828b0/coverage-7.10.1-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:d4b0aab55ad60ead26159ff12b538c85fbab731a5e3411c642b46c3525863437", size = 245140, upload-time = "2025-07-27T14:11:21.261Z" }, - { url = "https://files.pythonhosted.org/packages/55/f1/1f8f09536f38394a8698dd08a0e9608a512eacee1d3b771e2d06397f77bf/coverage-7.10.1-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:dcc93488c9ebd229be6ee1f0d9aad90da97b33ad7e2912f5495804d78a3cd6b7", size = 246977, upload-time = "2025-07-27T14:11:23.15Z" }, - { url = "https://files.pythonhosted.org/packages/57/cc/ed6bbc5a3bdb36ae1bca900bbbfdcb23b260ef2767a7b2dab38b92f61adf/coverage-7.10.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:aa309df995d020f3438407081b51ff527171cca6772b33cf8f85344b8b4b8770", size = 249140, upload-time = "2025-07-27T14:11:24.743Z" }, - { url = "https://files.pythonhosted.org/packages/10/f5/e881ade2d8e291b60fa1d93d6d736107e940144d80d21a0d4999cff3642f/coverage-7.10.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:cfb8b9d8855c8608f9747602a48ab525b1d320ecf0113994f6df23160af68262", size = 246869, upload-time = "2025-07-27T14:11:26.156Z" }, - { url = "https://files.pythonhosted.org/packages/53/b9/6a5665cb8996e3cd341d184bb11e2a8edf01d8dadcf44eb1e742186cf243/coverage-7.10.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:320d86da829b012982b414c7cdda65f5d358d63f764e0e4e54b33097646f39a3", size = 244899, upload-time = "2025-07-27T14:11:27.622Z" }, - { url = "https://files.pythonhosted.org/packages/27/11/24156776709c4e25bf8a33d6bb2ece9a9067186ddac19990f6560a7f8130/coverage-7.10.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:dc60ddd483c556590da1d9482a4518292eec36dd0e1e8496966759a1f282bcd0", size = 245507, upload-time = "2025-07-27T14:11:29.544Z" }, - { url = "https://files.pythonhosted.org/packages/43/db/a6f0340b7d6802a79928659c9a32bc778ea420e87a61b568d68ac36d45a8/coverage-7.10.1-cp311-cp311-win32.whl", hash = "sha256:4fcfe294f95b44e4754da5b58be750396f2b1caca8f9a0e78588e3ef85f8b8be", size = 217167, upload-time = "2025-07-27T14:11:31.349Z" }, - { url = "https://files.pythonhosted.org/packages/f5/6f/1990eb4fd05cea4cfabdf1d587a997ac5f9a8bee883443a1d519a2a848c9/coverage-7.10.1-cp311-cp311-win_amd64.whl", hash = "sha256:efa23166da3fe2915f8ab452dde40319ac84dc357f635737174a08dbd912980c", size = 218054, upload-time = "2025-07-27T14:11:33.202Z" }, - { url = "https://files.pythonhosted.org/packages/b4/4d/5e061d6020251b20e9b4303bb0b7900083a1a384ec4e5db326336c1c4abd/coverage-7.10.1-cp311-cp311-win_arm64.whl", hash = "sha256:d12b15a8c3759e2bb580ffa423ae54be4f184cf23beffcbd641f4fe6e1584293", size = 216483, upload-time = "2025-07-27T14:11:34.663Z" }, - { url = "https://files.pythonhosted.org/packages/a5/3f/b051feeb292400bd22d071fdf933b3ad389a8cef5c80c7866ed0c7414b9e/coverage-7.10.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:6b7dc7f0a75a7eaa4584e5843c873c561b12602439d2351ee28c7478186c4da4", size = 214934, upload-time = "2025-07-27T14:11:36.096Z" }, - { url = "https://files.pythonhosted.org/packages/f8/e4/a61b27d5c4c2d185bdfb0bfe9d15ab4ac4f0073032665544507429ae60eb/coverage-7.10.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:607f82389f0ecafc565813aa201a5cade04f897603750028dd660fb01797265e", size = 215173, upload-time = "2025-07-27T14:11:38.005Z" }, - { url = "https://files.pythonhosted.org/packages/8a/01/40a6ee05b60d02d0bc53742ad4966e39dccd450aafb48c535a64390a3552/coverage-7.10.1-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:f7da31a1ba31f1c1d4d5044b7c5813878adae1f3af8f4052d679cc493c7328f4", size = 246190, upload-time = "2025-07-27T14:11:39.887Z" }, - { url = "https://files.pythonhosted.org/packages/11/ef/a28d64d702eb583c377255047281305dc5a5cfbfb0ee36e721f78255adb6/coverage-7.10.1-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:51fe93f3fe4f5d8483d51072fddc65e717a175490804e1942c975a68e04bf97a", size = 248618, upload-time = "2025-07-27T14:11:41.841Z" }, - { url = "https://files.pythonhosted.org/packages/6a/ad/73d018bb0c8317725370c79d69b5c6e0257df84a3b9b781bda27a438a3be/coverage-7.10.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3e59d00830da411a1feef6ac828b90bbf74c9b6a8e87b8ca37964925bba76dbe", size = 250081, upload-time = "2025-07-27T14:11:43.705Z" }, - { url = "https://files.pythonhosted.org/packages/2d/dd/496adfbbb4503ebca5d5b2de8bed5ec00c0a76558ffc5b834fd404166bc9/coverage-7.10.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:924563481c27941229cb4e16eefacc35da28563e80791b3ddc5597b062a5c386", size = 247990, upload-time = "2025-07-27T14:11:45.244Z" }, - { url = "https://files.pythonhosted.org/packages/18/3c/a9331a7982facfac0d98a4a87b36ae666fe4257d0f00961a3a9ef73e015d/coverage-7.10.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:ca79146ee421b259f8131f153102220b84d1a5e6fb9c8aed13b3badfd1796de6", size = 246191, upload-time = "2025-07-27T14:11:47.093Z" }, - { url = "https://files.pythonhosted.org/packages/62/0c/75345895013b83f7afe92ec595e15a9a525ede17491677ceebb2ba5c3d85/coverage-7.10.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:2b225a06d227f23f386fdc0eab471506d9e644be699424814acc7d114595495f", size = 247400, upload-time = "2025-07-27T14:11:48.643Z" }, - { url = "https://files.pythonhosted.org/packages/e2/a9/98b268cfc5619ef9df1d5d34fee408ecb1542d9fd43d467e5c2f28668cd4/coverage-7.10.1-cp312-cp312-win32.whl", hash = "sha256:5ba9a8770effec5baaaab1567be916c87d8eea0c9ad11253722d86874d885eca", size = 217338, upload-time = "2025-07-27T14:11:50.258Z" }, - { url = "https://files.pythonhosted.org/packages/fe/31/22a5440e4d1451f253c5cd69fdcead65e92ef08cd4ec237b8756dc0b20a7/coverage-7.10.1-cp312-cp312-win_amd64.whl", hash = "sha256:9eb245a8d8dd0ad73b4062135a251ec55086fbc2c42e0eb9725a9b553fba18a3", size = 218125, upload-time = "2025-07-27T14:11:52.034Z" }, - { url = "https://files.pythonhosted.org/packages/d6/2b/40d9f0ce7ee839f08a43c5bfc9d05cec28aaa7c9785837247f96cbe490b9/coverage-7.10.1-cp312-cp312-win_arm64.whl", hash = "sha256:7718060dd4434cc719803a5e526838a5d66e4efa5dc46d2b25c21965a9c6fcc4", size = 216523, upload-time = "2025-07-27T14:11:53.965Z" }, - { url = "https://files.pythonhosted.org/packages/ef/72/135ff5fef09b1ffe78dbe6fcf1e16b2e564cd35faeacf3d63d60d887f12d/coverage-7.10.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ebb08d0867c5a25dffa4823377292a0ffd7aaafb218b5d4e2e106378b1061e39", size = 214960, upload-time = "2025-07-27T14:11:55.959Z" }, - { url = "https://files.pythonhosted.org/packages/b1/aa/73a5d1a6fc08ca709a8177825616aa95ee6bf34d522517c2595484a3e6c9/coverage-7.10.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f32a95a83c2e17422f67af922a89422cd24c6fa94041f083dd0bb4f6057d0bc7", size = 215220, upload-time = "2025-07-27T14:11:57.899Z" }, - { url = "https://files.pythonhosted.org/packages/8d/40/3124fdd45ed3772a42fc73ca41c091699b38a2c3bd4f9cb564162378e8b6/coverage-7.10.1-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:c4c746d11c8aba4b9f58ca8bfc6fbfd0da4efe7960ae5540d1a1b13655ee8892", size = 245772, upload-time = "2025-07-27T14:12:00.422Z" }, - { url = "https://files.pythonhosted.org/packages/42/62/a77b254822efa8c12ad59e8039f2bc3df56dc162ebda55e1943e35ba31a5/coverage-7.10.1-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:7f39edd52c23e5c7ed94e0e4bf088928029edf86ef10b95413e5ea670c5e92d7", size = 248116, upload-time = "2025-07-27T14:12:03.099Z" }, - { url = "https://files.pythonhosted.org/packages/1d/01/8101f062f472a3a6205b458d18ef0444a63ae5d36a8a5ed5dd0f6167f4db/coverage-7.10.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ab6e19b684981d0cd968906e293d5628e89faacb27977c92f3600b201926b994", size = 249554, upload-time = "2025-07-27T14:12:04.668Z" }, - { url = "https://files.pythonhosted.org/packages/8f/7b/e51bc61573e71ff7275a4f167aecbd16cb010aefdf54bcd8b0a133391263/coverage-7.10.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:5121d8cf0eacb16133501455d216bb5f99899ae2f52d394fe45d59229e6611d0", size = 247766, upload-time = "2025-07-27T14:12:06.234Z" }, - { url = "https://files.pythonhosted.org/packages/4b/71/1c96d66a51d4204a9d6d12df53c4071d87e110941a2a1fe94693192262f5/coverage-7.10.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:df1c742ca6f46a6f6cbcaef9ac694dc2cb1260d30a6a2f5c68c5f5bcfee1cfd7", size = 245735, upload-time = "2025-07-27T14:12:08.305Z" }, - { url = "https://files.pythonhosted.org/packages/13/d5/efbc2ac4d35ae2f22ef6df2ca084c60e13bd9378be68655e3268c80349ab/coverage-7.10.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:40f9a38676f9c073bf4b9194707aa1eb97dca0e22cc3766d83879d72500132c7", size = 247118, upload-time = "2025-07-27T14:12:09.903Z" }, - { url = "https://files.pythonhosted.org/packages/d1/22/073848352bec28ca65f2b6816b892fcf9a31abbef07b868487ad15dd55f1/coverage-7.10.1-cp313-cp313-win32.whl", hash = "sha256:2348631f049e884839553b9974f0821d39241c6ffb01a418efce434f7eba0fe7", size = 217381, upload-time = "2025-07-27T14:12:11.535Z" }, - { url = "https://files.pythonhosted.org/packages/b7/df/df6a0ff33b042f000089bd11b6bb034bab073e2ab64a56e78ed882cba55d/coverage-7.10.1-cp313-cp313-win_amd64.whl", hash = "sha256:4072b31361b0d6d23f750c524f694e1a417c1220a30d3ef02741eed28520c48e", size = 218152, upload-time = "2025-07-27T14:12:13.182Z" }, - { url = "https://files.pythonhosted.org/packages/30/e3/5085ca849a40ed6b47cdb8f65471c2f754e19390b5a12fa8abd25cbfaa8f/coverage-7.10.1-cp313-cp313-win_arm64.whl", hash = "sha256:3e31dfb8271937cab9425f19259b1b1d1f556790e98eb266009e7a61d337b6d4", size = 216559, upload-time = "2025-07-27T14:12:14.807Z" }, - { url = "https://files.pythonhosted.org/packages/cc/93/58714efbfdeb547909feaabe1d67b2bdd59f0597060271b9c548d5efb529/coverage-7.10.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:1c4f679c6b573a5257af6012f167a45be4c749c9925fd44d5178fd641ad8bf72", size = 215677, upload-time = "2025-07-27T14:12:16.68Z" }, - { url = "https://files.pythonhosted.org/packages/c0/0c/18eaa5897e7e8cb3f8c45e563e23e8a85686b4585e29d53cacb6bc9cb340/coverage-7.10.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:871ebe8143da284bd77b84a9136200bd638be253618765d21a1fce71006d94af", size = 215899, upload-time = "2025-07-27T14:12:18.758Z" }, - { url = "https://files.pythonhosted.org/packages/84/c1/9d1affacc3c75b5a184c140377701bbf14fc94619367f07a269cd9e4fed6/coverage-7.10.1-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:998c4751dabf7d29b30594af416e4bf5091f11f92a8d88eb1512c7ba136d1ed7", size = 257140, upload-time = "2025-07-27T14:12:20.357Z" }, - { url = "https://files.pythonhosted.org/packages/3d/0f/339bc6b8fa968c346df346068cca1f24bdea2ddfa93bb3dc2e7749730962/coverage-7.10.1-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:780f750a25e7749d0af6b3631759c2c14f45de209f3faaa2398312d1c7a22759", size = 259005, upload-time = "2025-07-27T14:12:22.007Z" }, - { url = "https://files.pythonhosted.org/packages/c8/22/89390864b92ea7c909079939b71baba7e5b42a76bf327c1d615bd829ba57/coverage-7.10.1-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:590bdba9445df4763bdbebc928d8182f094c1f3947a8dc0fc82ef014dbdd8324", size = 261143, upload-time = "2025-07-27T14:12:23.746Z" }, - { url = "https://files.pythonhosted.org/packages/2c/56/3d04d89017c0c41c7a71bd69b29699d919b6bbf2649b8b2091240b97dd6a/coverage-7.10.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9b2df80cb6a2af86d300e70acb82e9b79dab2c1e6971e44b78dbfc1a1e736b53", size = 258735, upload-time = "2025-07-27T14:12:25.73Z" }, - { url = "https://files.pythonhosted.org/packages/cb/40/312252c8afa5ca781063a09d931f4b9409dc91526cd0b5a2b84143ffafa2/coverage-7.10.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:d6a558c2725bfb6337bf57c1cd366c13798bfd3bfc9e3dd1f4a6f6fc95a4605f", size = 256871, upload-time = "2025-07-27T14:12:27.767Z" }, - { url = "https://files.pythonhosted.org/packages/1f/2b/564947d5dede068215aaddb9e05638aeac079685101462218229ddea9113/coverage-7.10.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:e6150d167f32f2a54690e572e0a4c90296fb000a18e9b26ab81a6489e24e78dd", size = 257692, upload-time = "2025-07-27T14:12:29.347Z" }, - { url = "https://files.pythonhosted.org/packages/93/1b/c8a867ade85cb26d802aea2209b9c2c80613b9c122baa8c8ecea6799648f/coverage-7.10.1-cp313-cp313t-win32.whl", hash = "sha256:d946a0c067aa88be4a593aad1236493313bafaa27e2a2080bfe88db827972f3c", size = 218059, upload-time = "2025-07-27T14:12:31.076Z" }, - { url = "https://files.pythonhosted.org/packages/a1/fe/cd4ab40570ae83a516bf5e754ea4388aeedd48e660e40c50b7713ed4f930/coverage-7.10.1-cp313-cp313t-win_amd64.whl", hash = "sha256:e37c72eaccdd5ed1130c67a92ad38f5b2af66eeff7b0abe29534225db2ef7b18", size = 219150, upload-time = "2025-07-27T14:12:32.746Z" }, - { url = "https://files.pythonhosted.org/packages/8d/16/6e5ed5854be6d70d0c39e9cb9dd2449f2c8c34455534c32c1a508c7dbdb5/coverage-7.10.1-cp313-cp313t-win_arm64.whl", hash = "sha256:89ec0ffc215c590c732918c95cd02b55c7d0f569d76b90bb1a5e78aa340618e4", size = 217014, upload-time = "2025-07-27T14:12:34.406Z" }, - { url = "https://files.pythonhosted.org/packages/54/8e/6d0bfe9c3d7121cf936c5f8b03e8c3da1484fb801703127dba20fb8bd3c7/coverage-7.10.1-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:166d89c57e877e93d8827dac32cedae6b0277ca684c6511497311249f35a280c", size = 214951, upload-time = "2025-07-27T14:12:36.069Z" }, - { url = "https://files.pythonhosted.org/packages/f2/29/e3e51a8c653cf2174c60532aafeb5065cea0911403fa144c9abe39790308/coverage-7.10.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:bed4a2341b33cd1a7d9ffc47df4a78ee61d3416d43b4adc9e18b7d266650b83e", size = 215229, upload-time = "2025-07-27T14:12:37.759Z" }, - { url = "https://files.pythonhosted.org/packages/e0/59/3c972080b2fa18b6c4510201f6d4dc87159d450627d062cd9ad051134062/coverage-7.10.1-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:ddca1e4f5f4c67980533df01430184c19b5359900e080248bbf4ed6789584d8b", size = 245738, upload-time = "2025-07-27T14:12:39.453Z" }, - { url = "https://files.pythonhosted.org/packages/2e/04/fc0d99d3f809452654e958e1788454f6e27b34e43f8f8598191c8ad13537/coverage-7.10.1-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:37b69226001d8b7de7126cad7366b0778d36777e4d788c66991455ba817c5b41", size = 248045, upload-time = "2025-07-27T14:12:41.387Z" }, - { url = "https://files.pythonhosted.org/packages/5e/2e/afcbf599e77e0dfbf4c97197747250d13d397d27e185b93987d9eaac053d/coverage-7.10.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b2f22102197bcb1722691296f9e589f02b616f874e54a209284dd7b9294b0b7f", size = 249666, upload-time = "2025-07-27T14:12:43.056Z" }, - { url = "https://files.pythonhosted.org/packages/6e/ae/bc47f7f8ecb7a06cbae2bf86a6fa20f479dd902bc80f57cff7730438059d/coverage-7.10.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:1e0c768b0f9ac5839dac5cf88992a4bb459e488ee8a1f8489af4cb33b1af00f1", size = 247692, upload-time = "2025-07-27T14:12:44.83Z" }, - { url = "https://files.pythonhosted.org/packages/b6/26/cbfa3092d31ccba8ba7647e4d25753263e818b4547eba446b113d7d1efdf/coverage-7.10.1-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:991196702d5e0b120a8fef2664e1b9c333a81d36d5f6bcf6b225c0cf8b0451a2", size = 245536, upload-time = "2025-07-27T14:12:46.527Z" }, - { url = "https://files.pythonhosted.org/packages/56/77/9c68e92500e6a1c83d024a70eadcc9a173f21aadd73c4675fe64c9c43fdf/coverage-7.10.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:ae8e59e5f4fd85d6ad34c2bb9d74037b5b11be072b8b7e9986beb11f957573d4", size = 246954, upload-time = "2025-07-27T14:12:49.279Z" }, - { url = "https://files.pythonhosted.org/packages/7f/a5/ba96671c5a669672aacd9877a5987c8551501b602827b4e84256da2a30a7/coverage-7.10.1-cp314-cp314-win32.whl", hash = "sha256:042125c89cf74a074984002e165d61fe0e31c7bd40ebb4bbebf07939b5924613", size = 217616, upload-time = "2025-07-27T14:12:51.214Z" }, - { url = "https://files.pythonhosted.org/packages/e7/3c/e1e1eb95fc1585f15a410208c4795db24a948e04d9bde818fe4eb893bc85/coverage-7.10.1-cp314-cp314-win_amd64.whl", hash = "sha256:a22c3bfe09f7a530e2c94c87ff7af867259c91bef87ed2089cd69b783af7b84e", size = 218412, upload-time = "2025-07-27T14:12:53.429Z" }, - { url = "https://files.pythonhosted.org/packages/b0/85/7e1e5be2cb966cba95566ba702b13a572ca744fbb3779df9888213762d67/coverage-7.10.1-cp314-cp314-win_arm64.whl", hash = "sha256:ee6be07af68d9c4fca4027c70cea0c31a0f1bc9cb464ff3c84a1f916bf82e652", size = 216776, upload-time = "2025-07-27T14:12:55.482Z" }, - { url = "https://files.pythonhosted.org/packages/62/0f/5bb8f29923141cca8560fe2217679caf4e0db643872c1945ac7d8748c2a7/coverage-7.10.1-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:d24fb3c0c8ff0d517c5ca5de7cf3994a4cd559cde0315201511dbfa7ab528894", size = 215698, upload-time = "2025-07-27T14:12:57.225Z" }, - { url = "https://files.pythonhosted.org/packages/80/29/547038ffa4e8e4d9e82f7dfc6d152f75fcdc0af146913f0ba03875211f03/coverage-7.10.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1217a54cfd79be20512a67ca81c7da3f2163f51bbfd188aab91054df012154f5", size = 215902, upload-time = "2025-07-27T14:12:59.071Z" }, - { url = "https://files.pythonhosted.org/packages/e1/8a/7aaa8fbfaed900147987a424e112af2e7790e1ac9cd92601e5bd4e1ba60a/coverage-7.10.1-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:51f30da7a52c009667e02f125737229d7d8044ad84b79db454308033a7808ab2", size = 257230, upload-time = "2025-07-27T14:13:01.248Z" }, - { url = "https://files.pythonhosted.org/packages/e5/1d/c252b5ffac44294e23a0d79dd5acf51749b39795ccc898faeabf7bee903f/coverage-7.10.1-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:ed3718c757c82d920f1c94089066225ca2ad7f00bb904cb72b1c39ebdd906ccb", size = 259194, upload-time = "2025-07-27T14:13:03.247Z" }, - { url = "https://files.pythonhosted.org/packages/16/ad/6c8d9f83d08f3bac2e7507534d0c48d1a4f52c18e6f94919d364edbdfa8f/coverage-7.10.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cc452481e124a819ced0c25412ea2e144269ef2f2534b862d9f6a9dae4bda17b", size = 261316, upload-time = "2025-07-27T14:13:04.957Z" }, - { url = "https://files.pythonhosted.org/packages/d6/4e/f9bbf3a36c061e2e0e0f78369c006d66416561a33d2bee63345aee8ee65e/coverage-7.10.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:9d6f494c307e5cb9b1e052ec1a471060f1dea092c8116e642e7a23e79d9388ea", size = 258794, upload-time = "2025-07-27T14:13:06.715Z" }, - { url = "https://files.pythonhosted.org/packages/87/82/e600bbe78eb2cb0541751d03cef9314bcd0897e8eea156219c39b685f869/coverage-7.10.1-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:fc0e46d86905ddd16b85991f1f4919028092b4e511689bbdaff0876bd8aab3dd", size = 256869, upload-time = "2025-07-27T14:13:08.933Z" }, - { url = "https://files.pythonhosted.org/packages/ce/5d/2fc9a9236c5268f68ac011d97cd3a5ad16cc420535369bedbda659fdd9b7/coverage-7.10.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:80b9ccd82e30038b61fc9a692a8dc4801504689651b281ed9109f10cc9fe8b4d", size = 257765, upload-time = "2025-07-27T14:13:10.778Z" }, - { url = "https://files.pythonhosted.org/packages/8a/05/b4e00b2bd48a2dc8e1c7d2aea7455f40af2e36484ab2ef06deb85883e9fe/coverage-7.10.1-cp314-cp314t-win32.whl", hash = "sha256:e58991a2b213417285ec866d3cd32db17a6a88061a985dbb7e8e8f13af429c47", size = 218420, upload-time = "2025-07-27T14:13:12.882Z" }, - { url = "https://files.pythonhosted.org/packages/77/fb/d21d05f33ea27ece327422240e69654b5932b0b29e7fbc40fbab3cf199bf/coverage-7.10.1-cp314-cp314t-win_amd64.whl", hash = "sha256:e88dd71e4ecbc49d9d57d064117462c43f40a21a1383507811cf834a4a620651", size = 219536, upload-time = "2025-07-27T14:13:14.718Z" }, - { url = "https://files.pythonhosted.org/packages/a6/68/7fea94b141281ed8be3d1d5c4319a97f2befc3e487ce33657fc64db2c45e/coverage-7.10.1-cp314-cp314t-win_arm64.whl", hash = "sha256:1aadfb06a30c62c2eb82322171fe1f7c288c80ca4156d46af0ca039052814bab", size = 217190, upload-time = "2025-07-27T14:13:16.85Z" }, - { url = "https://files.pythonhosted.org/packages/0f/64/922899cff2c0fd3496be83fa8b81230f5a8d82a2ad30f98370b133c2c83b/coverage-7.10.1-py3-none-any.whl", hash = "sha256:fa2a258aa6bf188eb9a8948f7102a83da7c430a0dce918dbd8b60ef8fcb772d7", size = 206597, upload-time = "2025-07-27T14:13:37.221Z" }, +version = "7.10.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ee/76/17780846fc7aade1e66712e1e27dd28faa0a5d987a1f433610974959eaa8/coverage-7.10.2.tar.gz", hash = "sha256:5d6e6d84e6dd31a8ded64759626627247d676a23c1b892e1326f7c55c8d61055", size = 820754, upload-time = "2025-08-04T00:35:17.511Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6e/53/0125a6fc0af4f2687b4e08b0fb332cd0d5e60f3ca849e7456f995d022656/coverage-7.10.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2c3b210d79925a476dfc8d74c7d53224888421edebf3a611f3adae923e212b27", size = 215119, upload-time = "2025-08-04T00:33:19.101Z" }, + { url = "https://files.pythonhosted.org/packages/0e/2e/960d9871de9152dbc9ff950913c6a6e9cf2eb4cc80d5bc8f93029f9f2f9f/coverage-7.10.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:bf67d1787cd317c3f8b2e4c6ed1ae93497be7e30605a0d32237ac37a37a8a322", size = 215511, upload-time = "2025-08-04T00:33:20.32Z" }, + { url = "https://files.pythonhosted.org/packages/3f/34/68509e44995b9cad806d81b76c22bc5181f3535bca7cd9c15791bfd8951e/coverage-7.10.2-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:069b779d03d458602bc0e27189876e7d8bdf6b24ac0f12900de22dd2154e6ad7", size = 245513, upload-time = "2025-08-04T00:33:21.896Z" }, + { url = "https://files.pythonhosted.org/packages/ef/d4/9b12f357413248ce40804b0f58030b55a25b28a5c02db95fb0aa50c5d62c/coverage-7.10.2-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:4c2de4cb80b9990e71c62c2d3e9f3ec71b804b1f9ca4784ec7e74127e0f42468", size = 247350, upload-time = "2025-08-04T00:33:23.917Z" }, + { url = "https://files.pythonhosted.org/packages/b6/40/257945eda1f72098e4a3c350b1d68fdc5d7d032684a0aeb6c2391153ecf4/coverage-7.10.2-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:75bf7ab2374a7eb107602f1e07310cda164016cd60968abf817b7a0b5703e288", size = 249516, upload-time = "2025-08-04T00:33:25.5Z" }, + { url = "https://files.pythonhosted.org/packages/ff/55/8987f852ece378cecbf39a367f3f7ec53351e39a9151b130af3a3045b83f/coverage-7.10.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:3f37516458ec1550815134937f73d6d15b434059cd10f64678a2068f65c62406", size = 247241, upload-time = "2025-08-04T00:33:26.767Z" }, + { url = "https://files.pythonhosted.org/packages/df/ae/da397de7a42a18cea6062ed9c3b72c50b39e0b9e7b2893d7172d3333a9a1/coverage-7.10.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:de3c6271c482c250d3303fb5c6bdb8ca025fff20a67245e1425df04dc990ece9", size = 245274, upload-time = "2025-08-04T00:33:28.494Z" }, + { url = "https://files.pythonhosted.org/packages/4e/64/7baa895eb55ec0e1ec35b988687ecd5d4475ababb0d7ae5ca3874dd90ee7/coverage-7.10.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:98a838101321ac3089c9bb1d4bfa967e8afed58021fda72d7880dc1997f20ae1", size = 245882, upload-time = "2025-08-04T00:33:30.048Z" }, + { url = "https://files.pythonhosted.org/packages/24/6c/1fd76a0bd09ae75220ae9775a8290416d726f0e5ba26ea72346747161240/coverage-7.10.2-cp311-cp311-win32.whl", hash = "sha256:f2a79145a531a0e42df32d37be5af069b4a914845b6f686590739b786f2f7bce", size = 217541, upload-time = "2025-08-04T00:33:31.376Z" }, + { url = "https://files.pythonhosted.org/packages/5f/2d/8c18fb7a6e74c79fd4661e82535bc8c68aee12f46c204eabf910b097ccc9/coverage-7.10.2-cp311-cp311-win_amd64.whl", hash = "sha256:e4f5f1320f8ee0d7cfa421ceb257bef9d39fd614dd3ddcfcacd284d4824ed2c2", size = 218426, upload-time = "2025-08-04T00:33:32.976Z" }, + { url = "https://files.pythonhosted.org/packages/da/40/425bb35e4ff7c7af177edf5dffd4154bc2a677b27696afe6526d75c77fec/coverage-7.10.2-cp311-cp311-win_arm64.whl", hash = "sha256:d8f2d83118f25328552c728b8e91babf93217db259ca5c2cd4dd4220b8926293", size = 217116, upload-time = "2025-08-04T00:33:34.302Z" }, + { url = "https://files.pythonhosted.org/packages/4e/1e/2c752bdbbf6f1199c59b1a10557fbb6fb3dc96b3c0077b30bd41a5922c1f/coverage-7.10.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:890ad3a26da9ec7bf69255b9371800e2a8da9bc223ae5d86daeb940b42247c83", size = 215311, upload-time = "2025-08-04T00:33:35.524Z" }, + { url = "https://files.pythonhosted.org/packages/68/6a/84277d73a2cafb96e24be81b7169372ba7ff28768ebbf98e55c85a491b0f/coverage-7.10.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:38fd1ccfca7838c031d7a7874d4353e2f1b98eb5d2a80a2fe5732d542ae25e9c", size = 215550, upload-time = "2025-08-04T00:33:37.109Z" }, + { url = "https://files.pythonhosted.org/packages/b5/e7/5358b73b46ac76f56cc2de921eeabd44fabd0b7ff82ea4f6b8c159c4d5dc/coverage-7.10.2-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:76c1ffaaf4f6f0f6e8e9ca06f24bb6454a7a5d4ced97a1bc466f0d6baf4bd518", size = 246564, upload-time = "2025-08-04T00:33:38.33Z" }, + { url = "https://files.pythonhosted.org/packages/7c/0e/b0c901dd411cb7fc0cfcb28ef0dc6f3049030f616bfe9fc4143aecd95901/coverage-7.10.2-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:86da8a3a84b79ead5c7d0e960c34f580bc3b231bb546627773a3f53c532c2f21", size = 248993, upload-time = "2025-08-04T00:33:39.555Z" }, + { url = "https://files.pythonhosted.org/packages/0e/4e/a876db272072a9e0df93f311e187ccdd5f39a190c6d1c1f0b6e255a0d08e/coverage-7.10.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:99cef9731c8a39801830a604cc53c93c9e57ea8b44953d26589499eded9576e0", size = 250454, upload-time = "2025-08-04T00:33:41.023Z" }, + { url = "https://files.pythonhosted.org/packages/64/d6/1222dc69f8dd1be208d55708a9f4a450ad582bf4fa05320617fea1eaa6d8/coverage-7.10.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:ea58b112f2966a8b91eb13f5d3b1f8bb43c180d624cd3283fb33b1cedcc2dd75", size = 248365, upload-time = "2025-08-04T00:33:42.376Z" }, + { url = "https://files.pythonhosted.org/packages/62/e3/40fd71151064fc315c922dd9a35e15b30616f00146db1d6a0b590553a75a/coverage-7.10.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:20f405188d28da9522b7232e51154e1b884fc18d0b3a10f382d54784715bbe01", size = 246562, upload-time = "2025-08-04T00:33:43.663Z" }, + { url = "https://files.pythonhosted.org/packages/fc/14/8aa93ddcd6623ddaef5d8966268ac9545b145bce4fe7b1738fd1c3f0d957/coverage-7.10.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:64586ce42bbe0da4d9f76f97235c545d1abb9b25985a8791857690f96e23dc3b", size = 247772, upload-time = "2025-08-04T00:33:45.068Z" }, + { url = "https://files.pythonhosted.org/packages/07/4e/dcb1c01490623c61e2f2ea85cb185fa6a524265bb70eeb897d3c193efeb9/coverage-7.10.2-cp312-cp312-win32.whl", hash = "sha256:bc2e69b795d97ee6d126e7e22e78a509438b46be6ff44f4dccbb5230f550d340", size = 217710, upload-time = "2025-08-04T00:33:46.378Z" }, + { url = "https://files.pythonhosted.org/packages/79/16/e8aab4162b5f80ad2e5e1f54b1826e2053aa2f4db508b864af647f00c239/coverage-7.10.2-cp312-cp312-win_amd64.whl", hash = "sha256:adda2268b8cf0d11f160fad3743b4dfe9813cd6ecf02c1d6397eceaa5b45b388", size = 218499, upload-time = "2025-08-04T00:33:48.048Z" }, + { url = "https://files.pythonhosted.org/packages/06/7f/c112ec766e8f1131ce8ce26254be028772757b2d1e63e4f6a4b0ad9a526c/coverage-7.10.2-cp312-cp312-win_arm64.whl", hash = "sha256:164429decd0d6b39a0582eaa30c67bf482612c0330572343042d0ed9e7f15c20", size = 217154, upload-time = "2025-08-04T00:33:49.299Z" }, + { url = "https://files.pythonhosted.org/packages/8d/04/9b7a741557f93c0ed791b854d27aa8d9fe0b0ce7bb7c52ca1b0f2619cb74/coverage-7.10.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:aca7b5645afa688de6d4f8e89d30c577f62956fefb1bad021490d63173874186", size = 215337, upload-time = "2025-08-04T00:33:50.61Z" }, + { url = "https://files.pythonhosted.org/packages/02/a4/8d1088cd644750c94bc305d3cf56082b4cdf7fb854a25abb23359e74892f/coverage-7.10.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:96e5921342574a14303dfdb73de0019e1ac041c863743c8fe1aa6c2b4a257226", size = 215596, upload-time = "2025-08-04T00:33:52.33Z" }, + { url = "https://files.pythonhosted.org/packages/01/2f/643a8d73343f70e162d8177a3972b76e306b96239026bc0c12cfde4f7c7a/coverage-7.10.2-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:11333094c1bff621aa811b67ed794865cbcaa99984dedea4bd9cf780ad64ecba", size = 246145, upload-time = "2025-08-04T00:33:53.641Z" }, + { url = "https://files.pythonhosted.org/packages/1f/4a/722098d1848db4072cda71b69ede1e55730d9063bf868375264d0d302bc9/coverage-7.10.2-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:6eb586fa7d2aee8d65d5ae1dd71414020b2f447435c57ee8de8abea0a77d5074", size = 248492, upload-time = "2025-08-04T00:33:55.366Z" }, + { url = "https://files.pythonhosted.org/packages/3f/b0/8a6d7f326f6e3e6ed398cde27f9055e860a1e858317001835c521673fb60/coverage-7.10.2-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2d358f259d8019d4ef25d8c5b78aca4c7af25e28bd4231312911c22a0e824a57", size = 249927, upload-time = "2025-08-04T00:33:57.042Z" }, + { url = "https://files.pythonhosted.org/packages/bb/21/1aaadd3197b54d1e61794475379ecd0f68d8fc5c2ebd352964dc6f698a3d/coverage-7.10.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:5250bda76e30382e0a2dcd68d961afcab92c3a7613606e6269855c6979a1b0bb", size = 248138, upload-time = "2025-08-04T00:33:58.329Z" }, + { url = "https://files.pythonhosted.org/packages/48/65/be75bafb2bdd22fd8bf9bf63cd5873b91bb26ec0d68f02d4b8b09c02decb/coverage-7.10.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:a91e027d66eff214d88d9afbe528e21c9ef1ecdf4956c46e366c50f3094696d0", size = 246111, upload-time = "2025-08-04T00:33:59.899Z" }, + { url = "https://files.pythonhosted.org/packages/5e/30/a4f0c5e249c3cc60e6c6f30d8368e372f2d380eda40e0434c192ac27ccf5/coverage-7.10.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:228946da741558904e2c03ce870ba5efd9cd6e48cbc004d9a27abee08100a15a", size = 247493, upload-time = "2025-08-04T00:34:01.619Z" }, + { url = "https://files.pythonhosted.org/packages/85/99/f09b9493e44a75cf99ca834394c12f8cb70da6c1711ee296534f97b52729/coverage-7.10.2-cp313-cp313-win32.whl", hash = "sha256:95e23987b52d02e7c413bf2d6dc6288bd5721beb518052109a13bfdc62c8033b", size = 217756, upload-time = "2025-08-04T00:34:03.277Z" }, + { url = "https://files.pythonhosted.org/packages/2d/bb/cbcb09103be330c7d26ff0ab05c4a8861dd2e254656fdbd3eb7600af4336/coverage-7.10.2-cp313-cp313-win_amd64.whl", hash = "sha256:f35481d42c6d146d48ec92d4e239c23f97b53a3f1fbd2302e7c64336f28641fe", size = 218526, upload-time = "2025-08-04T00:34:04.635Z" }, + { url = "https://files.pythonhosted.org/packages/37/8f/8bfb4e0bca52c00ab680767c0dd8cfd928a2a72d69897d9b2d5d8b5f63f5/coverage-7.10.2-cp313-cp313-win_arm64.whl", hash = "sha256:65b451949cb789c346f9f9002441fc934d8ccedcc9ec09daabc2139ad13853f7", size = 217176, upload-time = "2025-08-04T00:34:05.973Z" }, + { url = "https://files.pythonhosted.org/packages/1e/25/d458ba0bf16a8204a88d74dbb7ec5520f29937ffcbbc12371f931c11efd2/coverage-7.10.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:e8415918856a3e7d57a4e0ad94651b761317de459eb74d34cc1bb51aad80f07e", size = 216058, upload-time = "2025-08-04T00:34:07.368Z" }, + { url = "https://files.pythonhosted.org/packages/0b/1c/af4dfd2d7244dc7610fed6d59d57a23ea165681cd764445dc58d71ed01a6/coverage-7.10.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:f287a25a8ca53901c613498e4a40885b19361a2fe8fbfdbb7f8ef2cad2a23f03", size = 216273, upload-time = "2025-08-04T00:34:09.073Z" }, + { url = "https://files.pythonhosted.org/packages/8e/67/ec5095d4035c6e16368226fa9cb15f77f891194c7e3725aeefd08e7a3e5a/coverage-7.10.2-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:75cc1a3f8c88c69bf16a871dab1fe5a7303fdb1e9f285f204b60f1ee539b8fc0", size = 257513, upload-time = "2025-08-04T00:34:10.403Z" }, + { url = "https://files.pythonhosted.org/packages/1c/47/be5550b57a3a8ba797de4236b0fd31031f88397b2afc84ab3c2d4cf265f6/coverage-7.10.2-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:ca07fa78cc9d26bc8c4740de1abd3489cf9c47cc06d9a8ab3d552ff5101af4c0", size = 259377, upload-time = "2025-08-04T00:34:12.138Z" }, + { url = "https://files.pythonhosted.org/packages/37/50/b12a4da1382e672305c2d17cd3029dc16b8a0470de2191dbf26b91431378/coverage-7.10.2-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c2e117e64c26300032755d4520cd769f2623cde1a1d1c3515b05a3b8add0ade1", size = 261516, upload-time = "2025-08-04T00:34:13.608Z" }, + { url = "https://files.pythonhosted.org/packages/db/41/4d3296dbd33dd8da178171540ca3391af7c0184c0870fd4d4574ac290290/coverage-7.10.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:daaf98009977f577b71f8800208f4d40d4dcf5c2db53d4d822787cdc198d76e1", size = 259110, upload-time = "2025-08-04T00:34:15.089Z" }, + { url = "https://files.pythonhosted.org/packages/ea/f1/b409959ecbc0cec0e61e65683b22bacaa4a3b11512f834e16dd8ffbc37db/coverage-7.10.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:ea8d8fe546c528535c761ba424410bbeb36ba8a0f24be653e94b70c93fd8a8ca", size = 257248, upload-time = "2025-08-04T00:34:16.501Z" }, + { url = "https://files.pythonhosted.org/packages/48/ab/7076dc1c240412e9267d36ec93e9e299d7659f6a5c1e958f87e998b0fb6d/coverage-7.10.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:fe024d40ac31eb8d5aae70215b41dafa264676caa4404ae155f77d2fa95c37bb", size = 258063, upload-time = "2025-08-04T00:34:18.338Z" }, + { url = "https://files.pythonhosted.org/packages/1e/77/f6b51a0288f8f5f7dcc7c89abdd22cf514f3bc5151284f5cd628917f8e10/coverage-7.10.2-cp313-cp313t-win32.whl", hash = "sha256:8f34b09f68bdadec122ffad312154eda965ade433559cc1eadd96cca3de5c824", size = 218433, upload-time = "2025-08-04T00:34:19.71Z" }, + { url = "https://files.pythonhosted.org/packages/7b/6d/547a86493e25270ce8481543e77f3a0aa3aa872c1374246b7b76273d66eb/coverage-7.10.2-cp313-cp313t-win_amd64.whl", hash = "sha256:71d40b3ac0f26fa9ffa6ee16219a714fed5c6ec197cdcd2018904ab5e75bcfa3", size = 219523, upload-time = "2025-08-04T00:34:21.171Z" }, + { url = "https://files.pythonhosted.org/packages/ff/d5/3c711e38eaf9ab587edc9bed232c0298aed84e751a9f54aaa556ceaf7da6/coverage-7.10.2-cp313-cp313t-win_arm64.whl", hash = "sha256:abb57fdd38bf6f7dcc66b38dafb7af7c5fdc31ac6029ce373a6f7f5331d6f60f", size = 217739, upload-time = "2025-08-04T00:34:22.514Z" }, + { url = "https://files.pythonhosted.org/packages/71/53/83bafa669bb9d06d4c8c6a055d8d05677216f9480c4698fb183ba7ec5e47/coverage-7.10.2-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:a3e853cc04987c85ec410905667eed4bf08b1d84d80dfab2684bb250ac8da4f6", size = 215328, upload-time = "2025-08-04T00:34:23.991Z" }, + { url = "https://files.pythonhosted.org/packages/1d/6c/30827a9c5a48a813e865fbaf91e2db25cce990bd223a022650ef2293fe11/coverage-7.10.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:0100b19f230df72c90fdb36db59d3f39232391e8d89616a7de30f677da4f532b", size = 215608, upload-time = "2025-08-04T00:34:25.437Z" }, + { url = "https://files.pythonhosted.org/packages/bb/a0/c92d85948056ddc397b72a3d79d36d9579c53cb25393ed3c40db7d33b193/coverage-7.10.2-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:9c1cd71483ea78331bdfadb8dcec4f4edfb73c7002c1206d8e0af6797853f5be", size = 246111, upload-time = "2025-08-04T00:34:26.857Z" }, + { url = "https://files.pythonhosted.org/packages/c2/cf/d695cf86b2559aadd072c91720a7844be4fb82cb4a3b642a2c6ce075692d/coverage-7.10.2-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:9f75dbf4899e29a37d74f48342f29279391668ef625fdac6d2f67363518056a1", size = 248419, upload-time = "2025-08-04T00:34:28.726Z" }, + { url = "https://files.pythonhosted.org/packages/ce/0a/03206aec4a05986e039418c038470d874045f6e00426b0c3879adc1f9251/coverage-7.10.2-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a7df481e7508de1c38b9b8043da48d94931aefa3e32b47dd20277e4978ed5b95", size = 250038, upload-time = "2025-08-04T00:34:30.061Z" }, + { url = "https://files.pythonhosted.org/packages/ab/9b/b3bd6bd52118c12bc4cf319f5baba65009c9beea84e665b6b9f03fa3f180/coverage-7.10.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:835f39e618099325e7612b3406f57af30ab0a0af350490eff6421e2e5f608e46", size = 248066, upload-time = "2025-08-04T00:34:31.53Z" }, + { url = "https://files.pythonhosted.org/packages/80/cc/bfa92e261d3e055c851a073e87ba6a3bff12a1f7134233e48a8f7d855875/coverage-7.10.2-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:12e52b5aa00aa720097d6947d2eb9e404e7c1101ad775f9661ba165ed0a28303", size = 245909, upload-time = "2025-08-04T00:34:32.943Z" }, + { url = "https://files.pythonhosted.org/packages/12/80/c8df15db4847710c72084164f615ae900af1ec380dce7f74a5678ccdf5e1/coverage-7.10.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:718044729bf1fe3e9eb9f31b52e44ddae07e434ec050c8c628bf5adc56fe4bdd", size = 247329, upload-time = "2025-08-04T00:34:34.388Z" }, + { url = "https://files.pythonhosted.org/packages/04/6f/cb66e1f7124d5dd9ced69f889f02931419cb448125e44a89a13f4e036124/coverage-7.10.2-cp314-cp314-win32.whl", hash = "sha256:f256173b48cc68486299d510a3e729a96e62c889703807482dbf56946befb5c8", size = 218007, upload-time = "2025-08-04T00:34:35.846Z" }, + { url = "https://files.pythonhosted.org/packages/8c/e1/3d4be307278ce32c1b9d95cc02ee60d54ddab784036101d053ec9e4fe7f5/coverage-7.10.2-cp314-cp314-win_amd64.whl", hash = "sha256:2e980e4179f33d9b65ac4acb86c9c0dde904098853f27f289766657ed16e07b3", size = 218802, upload-time = "2025-08-04T00:34:37.35Z" }, + { url = "https://files.pythonhosted.org/packages/ec/66/1e43bbeb66c55a5a5efec70f1c153cf90cfc7f1662ab4ebe2d844de9122c/coverage-7.10.2-cp314-cp314-win_arm64.whl", hash = "sha256:14fb5b6641ab5b3c4161572579f0f2ea8834f9d3af2f7dd8fbaecd58ef9175cc", size = 217397, upload-time = "2025-08-04T00:34:39.15Z" }, + { url = "https://files.pythonhosted.org/packages/81/01/ae29c129217f6110dc694a217475b8aecbb1b075d8073401f868c825fa99/coverage-7.10.2-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:e96649ac34a3d0e6491e82a2af71098e43be2874b619547c3282fc11d3840a4b", size = 216068, upload-time = "2025-08-04T00:34:40.648Z" }, + { url = "https://files.pythonhosted.org/packages/a2/50/6e9221d4139f357258f36dfa1d8cac4ec56d9d5acf5fdcc909bb016954d7/coverage-7.10.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1a2e934e9da26341d342d30bfe91422bbfdb3f1f069ec87f19b2909d10d8dcc4", size = 216285, upload-time = "2025-08-04T00:34:42.441Z" }, + { url = "https://files.pythonhosted.org/packages/eb/ec/89d1d0c0ece0d296b4588e0ef4df185200456d42a47f1141335f482c2fc5/coverage-7.10.2-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:651015dcd5fd9b5a51ca79ece60d353cacc5beaf304db750407b29c89f72fe2b", size = 257603, upload-time = "2025-08-04T00:34:43.899Z" }, + { url = "https://files.pythonhosted.org/packages/82/06/c830af66734671c778fc49d35b58339e8f0687fbd2ae285c3f96c94da092/coverage-7.10.2-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:81bf6a32212f9f66da03d63ecb9cd9bd48e662050a937db7199dbf47d19831de", size = 259568, upload-time = "2025-08-04T00:34:45.519Z" }, + { url = "https://files.pythonhosted.org/packages/60/57/f280dd6f1c556ecc744fbf39e835c33d3ae987d040d64d61c6f821e87829/coverage-7.10.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d800705f6951f75a905ea6feb03fff8f3ea3468b81e7563373ddc29aa3e5d1ca", size = 261691, upload-time = "2025-08-04T00:34:47.019Z" }, + { url = "https://files.pythonhosted.org/packages/54/2b/c63a0acbd19d99ec32326164c23df3a4e18984fb86e902afdd66ff7b3d83/coverage-7.10.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:248b5394718e10d067354448dc406d651709c6765669679311170da18e0e9af8", size = 259166, upload-time = "2025-08-04T00:34:48.792Z" }, + { url = "https://files.pythonhosted.org/packages/fd/c5/cd2997dcfcbf0683634da9df52d3967bc1f1741c1475dd0e4722012ba9ef/coverage-7.10.2-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:5c61675a922b569137cf943770d7ad3edd0202d992ce53ac328c5ff68213ccf4", size = 257241, upload-time = "2025-08-04T00:34:51.038Z" }, + { url = "https://files.pythonhosted.org/packages/16/26/c9e30f82fdad8d47aee90af4978b18c88fa74369ae0f0ba0dbf08cee3a80/coverage-7.10.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:52d708b5fd65589461381fa442d9905f5903d76c086c6a4108e8e9efdca7a7ed", size = 258139, upload-time = "2025-08-04T00:34:52.533Z" }, + { url = "https://files.pythonhosted.org/packages/c9/99/bdb7bd00bebcd3dedfb895fa9af8e46b91422993e4a37ac634a5f1113790/coverage-7.10.2-cp314-cp314t-win32.whl", hash = "sha256:916369b3b914186b2c5e5ad2f7264b02cff5df96cdd7cdad65dccd39aa5fd9f0", size = 218809, upload-time = "2025-08-04T00:34:54.075Z" }, + { url = "https://files.pythonhosted.org/packages/eb/5e/56a7852e38a04d1520dda4dfbfbf74a3d6dec932c20526968f7444763567/coverage-7.10.2-cp314-cp314t-win_amd64.whl", hash = "sha256:5b9d538e8e04916a5df63052d698b30c74eb0174f2ca9cd942c981f274a18eaf", size = 219926, upload-time = "2025-08-04T00:34:55.643Z" }, + { url = "https://files.pythonhosted.org/packages/e0/12/7fbe6b9c52bb9d627e9556f9f2edfdbe88b315e084cdecc9afead0c3b36a/coverage-7.10.2-cp314-cp314t-win_arm64.whl", hash = "sha256:04c74f9ef1f925456a9fd23a7eef1103126186d0500ef9a0acb0bd2514bdc7cc", size = 217925, upload-time = "2025-08-04T00:34:57.564Z" }, + { url = "https://files.pythonhosted.org/packages/18/d8/9b768ac73a8ac2d10c080af23937212434a958c8d2a1c84e89b450237942/coverage-7.10.2-py3-none-any.whl", hash = "sha256:95db3750dd2e6e93d99fa2498f3a1580581e49c494bddccc6f85c5c21604921f", size = 206973, upload-time = "2025-08-04T00:35:15.918Z" }, ] [package.optional-dependencies] @@ -634,15 +634,15 @@ wheels = [ [[package]] name = "hypothesis" -version = "6.136.7" +version = "6.136.9" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "attrs" }, { name = "sortedcontainers" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/2e/19/92369e1d5f2ead5f3f491d5453f28a04be82133886d3a7b46ebdcf7e109d/hypothesis-6.136.7.tar.gz", hash = "sha256:864c5cf7779adc58871ee51595bc724c496047c5bc45229e0baa950b103a73ea", size = 458037, upload-time = "2025-08-01T22:14:23.057Z" } +sdist = { url = "https://files.pythonhosted.org/packages/62/fe/f872b3f29d5b59179c2b9c51e594703ab21e07dd22a354091b130cb863f2/hypothesis-6.136.9.tar.gz", hash = "sha256:8cc3c75a57cf3706249e3f7055b194648aa04a537deaa2099e28dc70d88da129", size = 459298, upload-time = "2025-08-04T21:54:48.774Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/88/59/32813aa1a2715d7c531f87b46a04ba23d05d2bd4f7e21ecda8135100f8ce/hypothesis-6.136.7-py3-none-any.whl", hash = "sha256:12a8b76a5c453f8478d6bb4b5450824856af571c5e7821604a15aeaafa9beefd", size = 524917, upload-time = "2025-08-01T22:14:18.845Z" }, + { url = "https://files.pythonhosted.org/packages/fb/3b/cfdc2e2f13decd9be1fb32ba58473b974f953e996e1466ae65a0cd9dd2d0/hypothesis-6.136.9-py3-none-any.whl", hash = "sha256:c052412bb8b8b5090fb00eff0a7c80bfaeab9f0364e65fd3f4d08a002e478346", size = 526167, upload-time = "2025-08-04T21:54:44.718Z" }, ] [[package]] @@ -674,7 +674,7 @@ wheels = [ [[package]] name = "ipykernel" -version = "6.30.0" +version = "6.30.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "appnope", marker = "sys_platform == 'darwin'" }, @@ -691,9 +691,9 @@ dependencies = [ { name = "tornado" }, { name = "traitlets" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/38/27/9e6e30ed92f2ac53d29f70b09da8b2dc456e256148e289678fa0e825f46a/ipykernel-6.30.0.tar.gz", hash = "sha256:b7b808ddb2d261aae2df3a26ff3ff810046e6de3dfbc6f7de8c98ea0a6cb632c", size = 165125, upload-time = "2025-07-21T10:36:09.259Z" } +sdist = { url = "https://files.pythonhosted.org/packages/bb/76/11082e338e0daadc89c8ff866185de11daf67d181901038f9e139d109761/ipykernel-6.30.1.tar.gz", hash = "sha256:6abb270161896402e76b91394fcdce5d1be5d45f456671e5080572f8505be39b", size = 166260, upload-time = "2025-08-04T15:47:35.018Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/1f/3d/00813c3d9b46e3dcd88bd4530e0a3c63c0509e5d8c9eff34723ea243ab04/ipykernel-6.30.0-py3-none-any.whl", hash = "sha256:fd2936e55c4a1c2ee8b1e5fa6a372b8eecc0ab1338750dee76f48fa5cca1301e", size = 117264, upload-time = "2025-07-21T10:36:06.854Z" }, + { url = "https://files.pythonhosted.org/packages/fc/c7/b445faca8deb954fe536abebff4ece5b097b923de482b26e78448c89d1dd/ipykernel-6.30.1-py3-none-any.whl", hash = "sha256:aa6b9fb93dca949069d8b85b6c79b2518e32ac583ae9c7d37c51d119e18b3fb4", size = 117484, upload-time = "2025-08-04T15:47:32.622Z" }, ] [[package]] @@ -1558,7 +1558,7 @@ tests = [ [package.metadata] requires-dist = [ - { name = "astropy", specifier = ">=5.2,<7" }, + { name = "astropy", specifier = ">=6" }, { name = "docutils", marker = "extra == 'docs'", specifier = ">=0.20.1" }, { name = "h5py", specifier = ">=3.8" }, { name = "hypothesis", marker = "extra == 'tests'", specifier = ">=6.108.2" }, @@ -1572,7 +1572,7 @@ requires-dist = [ { name = "nbsphinx", marker = "extra == 'docs'", specifier = ">=0.9.4" }, { name = "nox", extras = ["uv"], marker = "extra == 'docs'", specifier = ">=2025.5.1" }, { name = "nox", extras = ["uv"], marker = "extra == 'tests'", specifier = ">=2025.5.1" }, - { name = "numpy", specifier = ">=1.24" }, + { name = "numpy", specifier = ">=1.25" }, { name = "numpydoc", marker = "extra == 'docs'", specifier = ">=1.7" }, { name = "packaging", specifier = ">=22" }, { name = "pandas", specifier = ">=2" }, @@ -1607,7 +1607,7 @@ requires-dist = [ { name = "tqdm", specifier = ">=4.65" }, { name = "unidecode", marker = "extra == 'docs'", specifier = ">=1.3.8" }, { name = "wrapt", specifier = ">=1.15" }, - { name = "xarray", specifier = ">=2022.12,<=2024.10" }, + { name = "xarray", specifier = ">=2023.7" }, ] provides-extras = ["docs", "tests"] @@ -1934,47 +1934,60 @@ wheels = [ [[package]] name = "pyzmq" -version = "27.0.0" +version = "27.0.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "cffi", marker = "implementation_name == 'pypy'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/f1/06/50a4e9648b3e8b992bef8eb632e457307553a89d294103213cfd47b3da69/pyzmq-27.0.0.tar.gz", hash = "sha256:b1f08eeb9ce1510e6939b6e5dcd46a17765e2333daae78ecf4606808442e52cf", size = 280478, upload-time = "2025-06-13T14:09:07.087Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/44/df/84c630654106d9bd9339cdb564aa941ed41b023a0264251d6743766bb50e/pyzmq-27.0.0-cp311-cp311-macosx_10_15_universal2.whl", hash = "sha256:21457825249b2a53834fa969c69713f8b5a79583689387a5e7aed880963ac564", size = 1332718, upload-time = "2025-06-13T14:07:16.555Z" }, - { url = "https://files.pythonhosted.org/packages/c1/8e/f6a5461a07654d9840d256476434ae0ff08340bba562a455f231969772cb/pyzmq-27.0.0-cp311-cp311-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:1958947983fef513e6e98eff9cb487b60bf14f588dc0e6bf35fa13751d2c8251", size = 908248, upload-time = "2025-06-13T14:07:18.033Z" }, - { url = "https://files.pythonhosted.org/packages/7c/93/82863e8d695a9a3ae424b63662733ae204a295a2627d52af2f62c2cd8af9/pyzmq-27.0.0-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c0dc628b5493f9a8cd9844b8bee9732ef587ab00002157c9329e4fc0ef4d3afa", size = 668647, upload-time = "2025-06-13T14:07:19.378Z" }, - { url = "https://files.pythonhosted.org/packages/f3/85/15278769b348121eacdbfcbd8c4d40f1102f32fa6af5be1ffc032ed684be/pyzmq-27.0.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f7bbe9e1ed2c8d3da736a15694d87c12493e54cc9dc9790796f0321794bbc91f", size = 856600, upload-time = "2025-06-13T14:07:20.906Z" }, - { url = "https://files.pythonhosted.org/packages/d4/af/1c469b3d479bd095edb28e27f12eee10b8f00b356acbefa6aeb14dd295d1/pyzmq-27.0.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:dc1091f59143b471d19eb64f54bae4f54bcf2a466ffb66fe45d94d8d734eb495", size = 1657748, upload-time = "2025-06-13T14:07:22.549Z" }, - { url = "https://files.pythonhosted.org/packages/8c/f4/17f965d0ee6380b1d6326da842a50e4b8b9699745161207945f3745e8cb5/pyzmq-27.0.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:7011ade88c8e535cf140f8d1a59428676fbbce7c6e54fefce58bf117aefb6667", size = 2034311, upload-time = "2025-06-13T14:07:23.966Z" }, - { url = "https://files.pythonhosted.org/packages/e0/6e/7c391d81fa3149fd759de45d298003de6cfab343fb03e92c099821c448db/pyzmq-27.0.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:2c386339d7e3f064213aede5d03d054b237937fbca6dd2197ac8cf3b25a6b14e", size = 1893630, upload-time = "2025-06-13T14:07:25.899Z" }, - { url = "https://files.pythonhosted.org/packages/0e/e0/eaffe7a86f60e556399e224229e7769b717f72fec0706b70ab2c03aa04cb/pyzmq-27.0.0-cp311-cp311-win32.whl", hash = "sha256:0546a720c1f407b2172cb04b6b094a78773491497e3644863cf5c96c42df8cff", size = 567706, upload-time = "2025-06-13T14:07:27.595Z" }, - { url = "https://files.pythonhosted.org/packages/c9/05/89354a8cffdcce6e547d48adaaf7be17007fc75572123ff4ca90a4ca04fc/pyzmq-27.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:15f39d50bd6c9091c67315ceb878a4f531957b121d2a05ebd077eb35ddc5efed", size = 630322, upload-time = "2025-06-13T14:07:28.938Z" }, - { url = "https://files.pythonhosted.org/packages/fa/07/4ab976d5e1e63976719389cc4f3bfd248a7f5f2bb2ebe727542363c61b5f/pyzmq-27.0.0-cp311-cp311-win_arm64.whl", hash = "sha256:c5817641eebb391a2268c27fecd4162448e03538387093cdbd8bf3510c316b38", size = 558435, upload-time = "2025-06-13T14:07:30.256Z" }, - { url = "https://files.pythonhosted.org/packages/93/a7/9ad68f55b8834ede477842214feba6a4c786d936c022a67625497aacf61d/pyzmq-27.0.0-cp312-abi3-macosx_10_15_universal2.whl", hash = "sha256:cbabc59dcfaac66655c040dfcb8118f133fb5dde185e5fc152628354c1598e52", size = 1305438, upload-time = "2025-06-13T14:07:31.676Z" }, - { url = "https://files.pythonhosted.org/packages/ba/ee/26aa0f98665a22bc90ebe12dced1de5f3eaca05363b717f6fb229b3421b3/pyzmq-27.0.0-cp312-abi3-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:cb0ac5179cba4b2f94f1aa208fbb77b62c4c9bf24dd446278b8b602cf85fcda3", size = 895095, upload-time = "2025-06-13T14:07:33.104Z" }, - { url = "https://files.pythonhosted.org/packages/cf/85/c57e7ab216ecd8aa4cc7e3b83b06cc4e9cf45c87b0afc095f10cd5ce87c1/pyzmq-27.0.0-cp312-abi3-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:53a48f0228eab6cbf69fde3aa3c03cbe04e50e623ef92ae395fce47ef8a76152", size = 651826, upload-time = "2025-06-13T14:07:34.831Z" }, - { url = "https://files.pythonhosted.org/packages/69/9a/9ea7e230feda9400fb0ae0d61d7d6ddda635e718d941c44eeab22a179d34/pyzmq-27.0.0-cp312-abi3-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:111db5f395e09f7e775f759d598f43cb815fc58e0147623c4816486e1a39dc22", size = 839750, upload-time = "2025-06-13T14:07:36.553Z" }, - { url = "https://files.pythonhosted.org/packages/08/66/4cebfbe71f3dfbd417011daca267539f62ed0fbc68105357b68bbb1a25b7/pyzmq-27.0.0-cp312-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:c8878011653dcdc27cc2c57e04ff96f0471e797f5c19ac3d7813a245bcb24371", size = 1641357, upload-time = "2025-06-13T14:07:38.21Z" }, - { url = "https://files.pythonhosted.org/packages/ac/f6/b0f62578c08d2471c791287149cb8c2aaea414ae98c6e995c7dbe008adfb/pyzmq-27.0.0-cp312-abi3-musllinux_1_2_i686.whl", hash = "sha256:c0ed2c1f335ba55b5fdc964622254917d6b782311c50e138863eda409fbb3b6d", size = 2020281, upload-time = "2025-06-13T14:07:39.599Z" }, - { url = "https://files.pythonhosted.org/packages/37/b9/4f670b15c7498495da9159edc374ec09c88a86d9cd5a47d892f69df23450/pyzmq-27.0.0-cp312-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:e918d70862d4cfd4b1c187310015646a14e1f5917922ab45b29f28f345eeb6be", size = 1877110, upload-time = "2025-06-13T14:07:41.027Z" }, - { url = "https://files.pythonhosted.org/packages/66/31/9dee25c226295b740609f0d46db2fe972b23b6f5cf786360980524a3ba92/pyzmq-27.0.0-cp312-abi3-win32.whl", hash = "sha256:88b4e43cab04c3c0f0d55df3b1eef62df2b629a1a369b5289a58f6fa8b07c4f4", size = 559297, upload-time = "2025-06-13T14:07:42.533Z" }, - { url = "https://files.pythonhosted.org/packages/9b/12/52da5509800f7ff2d287b2f2b4e636e7ea0f001181cba6964ff6c1537778/pyzmq-27.0.0-cp312-abi3-win_amd64.whl", hash = "sha256:dce4199bf5f648a902ce37e7b3afa286f305cd2ef7a8b6ec907470ccb6c8b371", size = 619203, upload-time = "2025-06-13T14:07:43.843Z" }, - { url = "https://files.pythonhosted.org/packages/93/6d/7f2e53b19d1edb1eb4f09ec7c3a1f945ca0aac272099eab757d15699202b/pyzmq-27.0.0-cp312-abi3-win_arm64.whl", hash = "sha256:56e46bbb85d52c1072b3f809cc1ce77251d560bc036d3a312b96db1afe76db2e", size = 551927, upload-time = "2025-06-13T14:07:45.51Z" }, - { url = "https://files.pythonhosted.org/packages/19/62/876b27c4ff777db4ceba1c69ea90d3c825bb4f8d5e7cd987ce5802e33c55/pyzmq-27.0.0-cp313-cp313t-macosx_10_15_universal2.whl", hash = "sha256:c36ad534c0c29b4afa088dc53543c525b23c0797e01b69fef59b1a9c0e38b688", size = 1340826, upload-time = "2025-06-13T14:07:46.881Z" }, - { url = "https://files.pythonhosted.org/packages/43/69/58ef8f4f59d3bcd505260c73bee87b008850f45edca40ddaba54273c35f4/pyzmq-27.0.0-cp313-cp313t-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:67855c14173aec36395d7777aaba3cc527b393821f30143fd20b98e1ff31fd38", size = 897283, upload-time = "2025-06-13T14:07:49.562Z" }, - { url = "https://files.pythonhosted.org/packages/43/15/93a0d0396700a60475ad3c5d42c5f1c308d3570bc94626b86c71ef9953e0/pyzmq-27.0.0-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8617c7d43cd8ccdb62aebe984bfed77ca8f036e6c3e46dd3dddda64b10f0ab7a", size = 660567, upload-time = "2025-06-13T14:07:51.364Z" }, - { url = "https://files.pythonhosted.org/packages/0e/b3/fe055513e498ca32f64509abae19b9c9eb4d7c829e02bd8997dd51b029eb/pyzmq-27.0.0-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:67bfbcbd0a04c575e8103a6061d03e393d9f80ffdb9beb3189261e9e9bc5d5e9", size = 847681, upload-time = "2025-06-13T14:07:52.77Z" }, - { url = "https://files.pythonhosted.org/packages/b6/4f/ff15300b00b5b602191f3df06bbc8dd4164e805fdd65bb77ffbb9c5facdc/pyzmq-27.0.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:5cd11d46d7b7e5958121b3eaf4cd8638eff3a720ec527692132f05a57f14341d", size = 1650148, upload-time = "2025-06-13T14:07:54.178Z" }, - { url = "https://files.pythonhosted.org/packages/c4/6f/84bdfff2a224a6f26a24249a342e5906993c50b0761e311e81b39aef52a7/pyzmq-27.0.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:b801c2e40c5aa6072c2f4876de8dccd100af6d9918d4d0d7aa54a1d982fd4f44", size = 2023768, upload-time = "2025-06-13T14:07:55.714Z" }, - { url = "https://files.pythonhosted.org/packages/64/39/dc2db178c26a42228c5ac94a9cc595030458aa64c8d796a7727947afbf55/pyzmq-27.0.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:20d5cb29e8c5f76a127c75b6e7a77e846bc4b655c373baa098c26a61b7ecd0ef", size = 1885199, upload-time = "2025-06-13T14:07:57.166Z" }, - { url = "https://files.pythonhosted.org/packages/c7/21/dae7b06a1f8cdee5d8e7a63d99c5d129c401acc40410bef2cbf42025e26f/pyzmq-27.0.0-cp313-cp313t-win32.whl", hash = "sha256:a20528da85c7ac7a19b7384e8c3f8fa707841fd85afc4ed56eda59d93e3d98ad", size = 575439, upload-time = "2025-06-13T14:07:58.959Z" }, - { url = "https://files.pythonhosted.org/packages/eb/bc/1709dc55f0970cf4cb8259e435e6773f9946f41a045c2cb90e870b7072da/pyzmq-27.0.0-cp313-cp313t-win_amd64.whl", hash = "sha256:d8229f2efece6a660ee211d74d91dbc2a76b95544d46c74c615e491900dc107f", size = 639933, upload-time = "2025-06-13T14:08:00.777Z" }, - { url = "https://files.pythonhosted.org/packages/98/a6/92394373b8dbc1edc9d53c951e8d3989d518185174ee54492ec27711779d/pyzmq-27.0.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:cd1dc59763effd1576f8368047c9c31468fce0af89d76b5067641137506792ae", size = 835948, upload-time = "2025-06-13T14:08:43.516Z" }, - { url = "https://files.pythonhosted.org/packages/56/f3/4dc38d75d9995bfc18773df3e41f2a2ca9b740b06f1a15dbf404077e7588/pyzmq-27.0.0-pp311-pypy311_pp73-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:60e8cc82d968174650c1860d7b716366caab9973787a1c060cf8043130f7d0f7", size = 799874, upload-time = "2025-06-13T14:08:45.017Z" }, - { url = "https://files.pythonhosted.org/packages/ab/ba/64af397e0f421453dc68e31d5e0784d554bf39013a2de0872056e96e58af/pyzmq-27.0.0-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:14fe7aaac86e4e93ea779a821967360c781d7ac5115b3f1a171ced77065a0174", size = 567400, upload-time = "2025-06-13T14:08:46.855Z" }, - { url = "https://files.pythonhosted.org/packages/63/87/ec956cbe98809270b59a22891d5758edae147a258e658bf3024a8254c855/pyzmq-27.0.0-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6ad0562d4e6abb785be3e4dd68599c41be821b521da38c402bc9ab2a8e7ebc7e", size = 747031, upload-time = "2025-06-13T14:08:48.419Z" }, - { url = "https://files.pythonhosted.org/packages/be/8a/4a3764a68abc02e2fbb0668d225b6fda5cd39586dd099cee8b2ed6ab0452/pyzmq-27.0.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:9df43a2459cd3a3563404c1456b2c4c69564daa7dbaf15724c09821a3329ce46", size = 544726, upload-time = "2025-06-13T14:08:49.903Z" }, +sdist = { url = "https://files.pythonhosted.org/packages/30/5f/557d2032a2f471edbcc227da724c24a1c05887b5cda1e3ae53af98b9e0a5/pyzmq-27.0.1.tar.gz", hash = "sha256:45c549204bc20e7484ffd2555f6cf02e572440ecf2f3bdd60d4404b20fddf64b", size = 281158, upload-time = "2025-08-03T05:05:40.352Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ae/18/a8e0da6ababbe9326116fb1c890bf1920eea880e8da621afb6bc0f39a262/pyzmq-27.0.1-cp311-cp311-macosx_10_15_universal2.whl", hash = "sha256:9729190bd770314f5fbba42476abf6abe79a746eeda11d1d68fd56dd70e5c296", size = 1332721, upload-time = "2025-08-03T05:03:15.237Z" }, + { url = "https://files.pythonhosted.org/packages/75/a4/9431ba598651d60ebd50dc25755402b770322cf8432adcc07d2906e53a54/pyzmq-27.0.1-cp311-cp311-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:696900ef6bc20bef6a242973943574f96c3f97d2183c1bd3da5eea4f559631b1", size = 908249, upload-time = "2025-08-03T05:03:16.933Z" }, + { url = "https://files.pythonhosted.org/packages/f0/7a/e624e1793689e4e685d2ee21c40277dd4024d9d730af20446d88f69be838/pyzmq-27.0.1-cp311-cp311-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f96a63aecec22d3f7fdea3c6c98df9e42973f5856bb6812c3d8d78c262fee808", size = 668649, upload-time = "2025-08-03T05:03:18.49Z" }, + { url = "https://files.pythonhosted.org/packages/6c/29/0652a39d4e876e0d61379047ecf7752685414ad2e253434348246f7a2a39/pyzmq-27.0.1-cp311-cp311-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c512824360ea7490390566ce00bee880e19b526b312b25cc0bc30a0fe95cb67f", size = 856601, upload-time = "2025-08-03T05:03:20.194Z" }, + { url = "https://files.pythonhosted.org/packages/36/2d/8d5355d7fc55bb6e9c581dd74f58b64fa78c994079e3a0ea09b1b5627cde/pyzmq-27.0.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:dfb2bb5e0f7198eaacfb6796fb0330afd28f36d985a770745fba554a5903595a", size = 1657750, upload-time = "2025-08-03T05:03:22.055Z" }, + { url = "https://files.pythonhosted.org/packages/ab/f4/cd032352d5d252dc6f5ee272a34b59718ba3af1639a8a4ef4654f9535cf5/pyzmq-27.0.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:4f6886c59ba93ffde09b957d3e857e7950c8fe818bd5494d9b4287bc6d5bc7f1", size = 2034312, upload-time = "2025-08-03T05:03:23.578Z" }, + { url = "https://files.pythonhosted.org/packages/e4/1a/c050d8b6597200e97a4bd29b93c769d002fa0b03083858227e0376ad59bc/pyzmq-27.0.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b99ea9d330e86ce1ff7f2456b33f1bf81c43862a5590faf4ef4ed3a63504bdab", size = 1893632, upload-time = "2025-08-03T05:03:25.167Z" }, + { url = "https://files.pythonhosted.org/packages/6a/29/173ce21d5097e7fcf284a090e8beb64fc683c6582b1f00fa52b1b7e867ce/pyzmq-27.0.1-cp311-cp311-win32.whl", hash = "sha256:571f762aed89025ba8cdcbe355fea56889715ec06d0264fd8b6a3f3fa38154ed", size = 566587, upload-time = "2025-08-03T05:03:26.769Z" }, + { url = "https://files.pythonhosted.org/packages/53/ab/22bd33e7086f0a2cc03a5adabff4bde414288bb62a21a7820951ef86ec20/pyzmq-27.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:ee16906c8025fa464bea1e48128c048d02359fb40bebe5333103228528506530", size = 632873, upload-time = "2025-08-03T05:03:28.685Z" }, + { url = "https://files.pythonhosted.org/packages/90/14/3e59b4a28194285ceeff725eba9aa5ba8568d1cb78aed381dec1537c705a/pyzmq-27.0.1-cp311-cp311-win_arm64.whl", hash = "sha256:ba068f28028849da725ff9185c24f832ccf9207a40f9b28ac46ab7c04994bd41", size = 558918, upload-time = "2025-08-03T05:03:30.085Z" }, + { url = "https://files.pythonhosted.org/packages/0e/9b/c0957041067c7724b310f22c398be46399297c12ed834c3bc42200a2756f/pyzmq-27.0.1-cp312-abi3-macosx_10_15_universal2.whl", hash = "sha256:af7ebce2a1e7caf30c0bb64a845f63a69e76a2fadbc1cac47178f7bb6e657bdd", size = 1305432, upload-time = "2025-08-03T05:03:32.177Z" }, + { url = "https://files.pythonhosted.org/packages/8e/55/bd3a312790858f16b7def3897a0c3eb1804e974711bf7b9dcb5f47e7f82c/pyzmq-27.0.1-cp312-abi3-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:8f617f60a8b609a13099b313e7e525e67f84ef4524b6acad396d9ff153f6e4cd", size = 895095, upload-time = "2025-08-03T05:03:33.918Z" }, + { url = "https://files.pythonhosted.org/packages/20/50/fc384631d8282809fb1029a4460d2fe90fa0370a0e866a8318ed75c8d3bb/pyzmq-27.0.1-cp312-abi3-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1d59dad4173dc2a111f03e59315c7bd6e73da1a9d20a84a25cf08325b0582b1a", size = 651826, upload-time = "2025-08-03T05:03:35.818Z" }, + { url = "https://files.pythonhosted.org/packages/7e/0a/2356305c423a975000867de56888b79e44ec2192c690ff93c3109fd78081/pyzmq-27.0.1-cp312-abi3-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f5b6133c8d313bde8bd0d123c169d22525300ff164c2189f849de495e1344577", size = 839751, upload-time = "2025-08-03T05:03:37.265Z" }, + { url = "https://files.pythonhosted.org/packages/d7/1b/81e95ad256ca7e7ccd47f5294c1c6da6e2b64fbace65b84fe8a41470342e/pyzmq-27.0.1-cp312-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:58cca552567423f04d06a075f4b473e78ab5bdb906febe56bf4797633f54aa4e", size = 1641359, upload-time = "2025-08-03T05:03:38.799Z" }, + { url = "https://files.pythonhosted.org/packages/50/63/9f50ec965285f4e92c265c8f18344e46b12803666d8b73b65d254d441435/pyzmq-27.0.1-cp312-abi3-musllinux_1_2_i686.whl", hash = "sha256:4b9d8e26fb600d0d69cc9933e20af08552e97cc868a183d38a5c0d661e40dfbb", size = 2020281, upload-time = "2025-08-03T05:03:40.338Z" }, + { url = "https://files.pythonhosted.org/packages/02/4a/19e3398d0dc66ad2b463e4afa1fc541d697d7bc090305f9dfb948d3dfa29/pyzmq-27.0.1-cp312-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:2329f0c87f0466dce45bba32b63f47018dda5ca40a0085cc5c8558fea7d9fc55", size = 1877112, upload-time = "2025-08-03T05:03:42.012Z" }, + { url = "https://files.pythonhosted.org/packages/bf/42/c562e9151aa90ed1d70aac381ea22a929d6b3a2ce4e1d6e2e135d34fd9c6/pyzmq-27.0.1-cp312-abi3-win32.whl", hash = "sha256:57bb92abdb48467b89c2d21da1ab01a07d0745e536d62afd2e30d5acbd0092eb", size = 558177, upload-time = "2025-08-03T05:03:43.979Z" }, + { url = "https://files.pythonhosted.org/packages/40/96/5c50a7d2d2b05b19994bf7336b97db254299353dd9b49b565bb71b485f03/pyzmq-27.0.1-cp312-abi3-win_amd64.whl", hash = "sha256:ff3f8757570e45da7a5bedaa140489846510014f7a9d5ee9301c61f3f1b8a686", size = 618923, upload-time = "2025-08-03T05:03:45.438Z" }, + { url = "https://files.pythonhosted.org/packages/13/33/1ec89c8f21c89d21a2eaff7def3676e21d8248d2675705e72554fb5a6f3f/pyzmq-27.0.1-cp312-abi3-win_arm64.whl", hash = "sha256:df2c55c958d3766bdb3e9d858b911288acec09a9aab15883f384fc7180df5bed", size = 552358, upload-time = "2025-08-03T05:03:46.887Z" }, + { url = "https://files.pythonhosted.org/packages/6c/a0/f26e276211ec8090a4d11e4ec70eb8a8b15781e591c1d44ce62f372963a0/pyzmq-27.0.1-cp313-cp313-android_24_arm64_v8a.whl", hash = "sha256:497bd8af534ae55dc4ef67eebd1c149ff2a0b0f1e146db73c8b5a53d83c1a5f5", size = 1122287, upload-time = "2025-08-03T05:03:48.838Z" }, + { url = "https://files.pythonhosted.org/packages/9c/d8/af4b507e4f7eeea478cc8ee873995a6fd55582bfb99140593ed460e1db3c/pyzmq-27.0.1-cp313-cp313-android_24_x86_64.whl", hash = "sha256:a066ea6ad6218b4c233906adf0ae67830f451ed238419c0db609310dd781fbe7", size = 1155756, upload-time = "2025-08-03T05:03:50.907Z" }, + { url = "https://files.pythonhosted.org/packages/ac/55/37fae0013e11f88681da42698e550b08a316d608242551f65095cc99232a/pyzmq-27.0.1-cp313-cp313t-macosx_10_15_universal2.whl", hash = "sha256:72d235d6365ca73d8ce92f7425065d70f5c1e19baa458eb3f0d570e425b73a96", size = 1340826, upload-time = "2025-08-03T05:03:52.568Z" }, + { url = "https://files.pythonhosted.org/packages/f2/e4/3a87854c64b26fcf63a9d1b6f4382bd727d4797c772ceb334a97b7489be9/pyzmq-27.0.1-cp313-cp313t-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:313a7b374e3dc64848644ca348a51004b41726f768b02e17e689f1322366a4d9", size = 897283, upload-time = "2025-08-03T05:03:54.167Z" }, + { url = "https://files.pythonhosted.org/packages/17/3e/4296c6b0ad2d07be11ae1395dccf9cae48a0a655cf9be1c3733ad2b591d1/pyzmq-27.0.1-cp313-cp313t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:119ce8590409702394f959c159d048002cbed2f3c0645ec9d6a88087fc70f0f1", size = 660565, upload-time = "2025-08-03T05:03:56.152Z" }, + { url = "https://files.pythonhosted.org/packages/72/41/a33ba3aa48b45b23c4cd4ac49aafde46f3e0f81939f2bfb3b6171a437122/pyzmq-27.0.1-cp313-cp313t-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:45c3e00ce16896ace2cd770ab9057a7cf97d4613ea5f2a13f815141d8b6894b9", size = 847680, upload-time = "2025-08-03T05:03:57.696Z" }, + { url = "https://files.pythonhosted.org/packages/3f/8c/bf2350bb25b3b58d2e5b5d2290ffab0e923f0cc6d02288d3fbf4baa6e4d1/pyzmq-27.0.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:678e50ec112bdc6df5a83ac259a55a4ba97a8b314c325ab26b3b5b071151bc61", size = 1650151, upload-time = "2025-08-03T05:03:59.387Z" }, + { url = "https://files.pythonhosted.org/packages/f7/1a/a5a07c54890891344a8ddc3d5ab320dd3c4e39febb6e4472546e456d5157/pyzmq-27.0.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:d0b96c30be9f9387b18b18b6133c75a7b1b0065da64e150fe1feb5ebf31ece1c", size = 2023766, upload-time = "2025-08-03T05:04:01.883Z" }, + { url = "https://files.pythonhosted.org/packages/62/5e/514dcff08f02c6c8a45a6e23621901139cf853be7ac5ccd0b9407c3aa3de/pyzmq-27.0.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:88dc92d9eb5ea4968123e74db146d770b0c8d48f0e2bfb1dbc6c50a8edb12d64", size = 1885195, upload-time = "2025-08-03T05:04:03.923Z" }, + { url = "https://files.pythonhosted.org/packages/c8/91/87f74f98a487fbef0b115f6025e4a295129fd56b2b633a03ba7d5816ecc2/pyzmq-27.0.1-cp313-cp313t-win32.whl", hash = "sha256:6dcbcb34f5c9b0cefdfc71ff745459241b7d3cda5b27c7ad69d45afc0821d1e1", size = 574213, upload-time = "2025-08-03T05:04:05.905Z" }, + { url = "https://files.pythonhosted.org/packages/e6/d7/07f7d0d7f4c81e08be7b60e52ff2591c557377c017f96204d33d5fca1b07/pyzmq-27.0.1-cp313-cp313t-win_amd64.whl", hash = "sha256:b9fd0fda730461f510cfd9a40fafa5355d65f5e3dbdd8d6dfa342b5b3f5d1949", size = 640202, upload-time = "2025-08-03T05:04:07.439Z" }, + { url = "https://files.pythonhosted.org/packages/ab/83/21d66bcef6fb803647a223cbde95111b099e2176277c0cbc8b099c485510/pyzmq-27.0.1-cp313-cp313t-win_arm64.whl", hash = "sha256:56a3b1853f3954ec1f0e91085f1350cc57d18f11205e4ab6e83e4b7c414120e0", size = 561514, upload-time = "2025-08-03T05:04:09.071Z" }, + { url = "https://files.pythonhosted.org/packages/5a/0b/d5ea75cf46b52cdce85a85200c963cb498932953df443892238be49b1a01/pyzmq-27.0.1-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:f98f6b7787bd2beb1f0dde03f23a0621a0c978edf673b7d8f5e7bc039cbe1b60", size = 1340836, upload-time = "2025-08-03T05:04:10.774Z" }, + { url = "https://files.pythonhosted.org/packages/be/4c/0dbce882550e17db6846b29e9dc242aea7590e7594e1ca5043e8e58fff2d/pyzmq-27.0.1-cp314-cp314t-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:351bf5d8ca0788ca85327fda45843b6927593ff4c807faee368cc5aaf9f809c2", size = 897236, upload-time = "2025-08-03T05:04:13.221Z" }, + { url = "https://files.pythonhosted.org/packages/1b/22/461e131cf16b8814f3c356fa1ea0912697dbc4c64cddf01f7756ec704c1e/pyzmq-27.0.1-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5268a5a9177afff53dc6d70dffe63114ba2a6e7b20d9411cc3adeba09eeda403", size = 660374, upload-time = "2025-08-03T05:04:15.032Z" }, + { url = "https://files.pythonhosted.org/packages/3f/0c/bbd65a814395bf4fc3e57c6c13af27601c07e4009bdfb75ebcf500537bbd/pyzmq-27.0.1-cp314-cp314t-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a4aca06ba295aa78bec9b33ec028d1ca08744c36294338c41432b7171060c808", size = 847497, upload-time = "2025-08-03T05:04:16.967Z" }, + { url = "https://files.pythonhosted.org/packages/1e/df/3d1f4a03b561d824cbd491394f67591957e2f1acf6dc85d96f970312a76a/pyzmq-27.0.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:1c363c6dc66352331d5ad64bb838765c6692766334a6a02fdb05e76bd408ae18", size = 1650028, upload-time = "2025-08-03T05:04:19.398Z" }, + { url = "https://files.pythonhosted.org/packages/41/c9/a3987540f59a412bdaae3f362f78e00e6769557a598c63b7e32956aade5a/pyzmq-27.0.1-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:87aebf4acd7249bdff8d3df03aed4f09e67078e6762cfe0aecf8d0748ff94cde", size = 2023808, upload-time = "2025-08-03T05:04:21.145Z" }, + { url = "https://files.pythonhosted.org/packages/b0/a5/c388f4cd80498a8eaef7535f2a8eaca0a35b82b87a0b47fa1856fc135004/pyzmq-27.0.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:e4f22d67756518d71901edf73b38dc0eb4765cce22c8fe122cc81748d425262b", size = 1884970, upload-time = "2025-08-03T05:04:22.908Z" }, + { url = "https://files.pythonhosted.org/packages/9a/ac/b2a89a1ed90526a1b9a260cdc5cd42f055fd44ee8d2a59902b5ac35ddeb1/pyzmq-27.0.1-cp314-cp314t-win32.whl", hash = "sha256:8c62297bc7aea2147b472ca5ca2b4389377ad82898c87cabab2a94aedd75e337", size = 586905, upload-time = "2025-08-03T05:04:24.492Z" }, + { url = "https://files.pythonhosted.org/packages/68/62/7aa5ea04e836f7a788b2a67405f83011cef59ca76d7bac91d1fc9a0476da/pyzmq-27.0.1-cp314-cp314t-win_amd64.whl", hash = "sha256:bee5248d5ec9223545f8cc4f368c2d571477ae828c99409125c3911511d98245", size = 660503, upload-time = "2025-08-03T05:04:26.382Z" }, + { url = "https://files.pythonhosted.org/packages/89/32/3836ed85947b06f1d67c07ce16c00b0cf8c053ab0b249d234f9f81ff95ff/pyzmq-27.0.1-cp314-cp314t-win_arm64.whl", hash = "sha256:0fc24bf45e4a454e55ef99d7f5c8b8712539200ce98533af25a5bfa954b6b390", size = 575098, upload-time = "2025-08-03T05:04:27.974Z" }, + { url = "https://files.pythonhosted.org/packages/b4/1a/49f66fe0bc2b2568dd4280f1f520ac8fafd73f8d762140e278d48aeaf7b9/pyzmq-27.0.1-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:7fb0ee35845bef1e8c4a152d766242164e138c239e3182f558ae15cb4a891f94", size = 835949, upload-time = "2025-08-03T05:05:13.798Z" }, + { url = "https://files.pythonhosted.org/packages/49/94/443c1984b397eab59b14dd7ae8bc2ac7e8f32dbc646474453afcaa6508c4/pyzmq-27.0.1-pp311-pypy311_pp73-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:f379f11e138dfd56c3f24a04164f871a08281194dd9ddf656a278d7d080c8ad0", size = 799875, upload-time = "2025-08-03T05:05:15.632Z" }, + { url = "https://files.pythonhosted.org/packages/30/f1/fd96138a0f152786a2ba517e9c6a8b1b3516719e412a90bb5d8eea6b660c/pyzmq-27.0.1-pp311-pypy311_pp73-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b978c0678cffbe8860ec9edc91200e895c29ae1ac8a7085f947f8e8864c489fb", size = 567403, upload-time = "2025-08-03T05:05:17.326Z" }, + { url = "https://files.pythonhosted.org/packages/16/57/34e53ef2b55b1428dac5aabe3a974a16c8bda3bf20549ba500e3ff6cb426/pyzmq-27.0.1-pp311-pypy311_pp73-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7ebccf0d760bc92a4a7c751aeb2fef6626144aace76ee8f5a63abeb100cae87f", size = 747032, upload-time = "2025-08-03T05:05:19.074Z" }, + { url = "https://files.pythonhosted.org/packages/81/b7/769598c5ae336fdb657946950465569cf18803140fe89ce466d7f0a57c11/pyzmq-27.0.1-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:77fed80e30fa65708546c4119840a46691290efc231f6bfb2ac2a39b52e15811", size = 544566, upload-time = "2025-08-03T05:05:20.798Z" }, ] [[package]] @@ -2677,16 +2690,16 @@ wheels = [ [[package]] name = "virtualenv" -version = "20.32.0" +version = "20.33.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "distlib" }, { name = "filelock" }, { name = "platformdirs" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/a9/96/0834f30fa08dca3738614e6a9d42752b6420ee94e58971d702118f7cfd30/virtualenv-20.32.0.tar.gz", hash = "sha256:886bf75cadfdc964674e6e33eb74d787dff31ca314ceace03ca5810620f4ecf0", size = 6076970, upload-time = "2025-07-21T04:09:50.985Z" } +sdist = { url = "https://files.pythonhosted.org/packages/db/2e/8a70dcbe8bf15213a08f9b0325ede04faca5d362922ae0d62ef0fa4b069d/virtualenv-20.33.0.tar.gz", hash = "sha256:47e0c0d2ef1801fce721708ccdf2a28b9403fa2307c3268aebd03225976f61d2", size = 6082069, upload-time = "2025-08-03T08:09:19.014Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/5c/c6/f8f28009920a736d0df434b52e9feebfb4d702ba942f15338cb4a83eafc1/virtualenv-20.32.0-py3-none-any.whl", hash = "sha256:2c310aecb62e5aa1b06103ed7c2977b81e042695de2697d01017ff0f1034af56", size = 6057761, upload-time = "2025-07-21T04:09:48.059Z" }, + { url = "https://files.pythonhosted.org/packages/43/87/b22cf40cdf7e2b2bf83f38a94d2c90c5ad6c304896e5a12d0c08a602eb59/virtualenv-20.33.0-py3-none-any.whl", hash = "sha256:106b6baa8ab1b526d5a9b71165c85c456fbd49b16976c88e2bc9352ee3bc5d3f", size = 6060205, upload-time = "2025-08-03T08:09:16.674Z" }, ] [[package]] @@ -2771,14 +2784,14 @@ wheels = [ [[package]] name = "xarray" -version = "2024.10.0" +version = "2025.7.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "numpy" }, { name = "packaging" }, { name = "pandas" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/b7/f2/a3e3ec1ffd29b0b5be800d2606c229f04f303ee9e61a1377dc5c1996cf8a/xarray-2024.10.0.tar.gz", hash = "sha256:e369e2bac430e418c2448e5b96f07da4635f98c1319aa23cfeb3fbcb9a01d2e0", size = 3788358, upload-time = "2024-10-24T21:45:48.532Z" } +sdist = { url = "https://files.pythonhosted.org/packages/e8/c5/a31ba8605005ef080c3d35efc696ddd851aee0a7a22420f9afebec386281/xarray-2025.7.1.tar.gz", hash = "sha256:2884bf5672b540fcc6ff8c20a3196bda0d78fbfb4d67398d60526e97c2faceef", size = 3013717, upload-time = "2025-07-10T04:53:07.01Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/a9/b7/9830def68e5575a24ca6d6f46b285d35ed27860beaa4f72848cd82870253/xarray-2024.10.0-py3-none-any.whl", hash = "sha256:ae1d38cb44a0324dfb61e492394158ae22389bf7de9f3c174309c17376df63a0", size = 1212984, upload-time = "2024-10-24T21:45:46.566Z" }, + { url = "https://files.pythonhosted.org/packages/b2/ea/9554e5fb78eda4dbc9e9ccaf23034166fe3e9ea9af82ea6204b9578434bc/xarray-2025.7.1-py3-none-any.whl", hash = "sha256:e8647b659e53bd350d7c5a91c34dd4122ad6a3ca0bc41399d424a7c0273c7635", size = 1324464, upload-time = "2025-07-10T04:53:05.104Z" }, ] From 4031b63565eb8c1eb74597f816dbd26d20ad6c58 Mon Sep 17 00:00:00 2001 From: Nick Murphy Date: Mon, 4 Aug 2025 21:47:20 -0400 Subject: [PATCH 437/521] Enable new rules for `ruff check` (#3077) * Update some ruff rules * Enable RUF102 * Remove RUF102 since it's in preview * Enable refurb and flake8-quotes --- pyproject.toml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index 5e3273e484..5a6c148464 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -177,6 +177,7 @@ lint.extend-select = [ "FBT003", # flake8-boolean-trap "FIX", # flake8-fixme "FLY", # flynt + "FURB", # refurb "G", # flake8-logging-format "I", # isort "ICN", # flake8-import-conventions @@ -196,6 +197,7 @@ lint.extend-select = [ "PT", # flake8-pytest-style "PTH", # flake8-use-pathlib "PYI", # flake8-pyi + "Q", # flake8-quotes "RET", # flake8-return "RSE", # flake8-raise "RUF001", # ambiguous-unicode-character-string @@ -219,6 +221,7 @@ lint.extend-select = [ "RUF023", # unsorted-dunder-slots "RUF024", # mutable-fromkeys-value "RUF026", # default-factory-kwarg + "RUF028", # invalid-formatter-suppression-comment "RUF030", # assert-with-print-message "RUF032", # decimal-from-float-literal "RUF033", # post-init-default @@ -227,7 +230,11 @@ lint.extend-select = [ "RUF041", # unnecessary-nested-literal "RUF046", # unnecessary-cast-to-int "RUF048", # map-int-version-parsing + "RUF049", # dataclass-enum "RUF051", # if-key-in-dict-del + "RUF053", # class-with-mixed-type-vars + "RUF057", # unnecessary-round + "RUF058", # starmap-zip "RUF100", # unused-noqa "RUF101", # redirected-noqa "RUF200", # invalid-pyproject-toml From c152b8709c38d5af6309cefa0fef573bea7ce0c0 Mon Sep 17 00:00:00 2001 From: Nick Murphy Date: Mon, 4 Aug 2025 21:56:34 -0400 Subject: [PATCH 438/521] Alphabetize CITATION.cff (#3078) --- CITATION.cff | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/CITATION.cff b/CITATION.cff index 856a3efa5e..c224fa19f8 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -256,6 +256,11 @@ authors: orcid: https://orcid.org/0000-0003-0223-7004 alias: samaiyahfarid +- given-names: Emmanuel + family-names: Ferdman + orcid: https://orcid.org/0009-0004-8953-0151 + alias: emmanuel-ferdman + - given-names: Michael family-names: Fischer @@ -282,6 +287,11 @@ authors: orcid: https://orcid.org/0009-0008-3588-0497 alias: s-gerow +- given-names: Mahlet + family-names: Getahun + affiliation: Marietta College + alias: Getahun-yw-Mahl + - given-names: Jessica family-names: Gonzalez affiliation: California Institute of Technology @@ -479,6 +489,12 @@ authors: affiliation: College of William & Mary alias: LeoMurphy037 +- given-names: Bao + family-names: Nguyen + affiliation: Imperial College London + orcid: https://orcid.org/0000-0002-1753-4223 + alias: wnguyen1312 + - given-names: Suzanne family-names: Nie alias: sznie @@ -519,6 +535,8 @@ authors: family-names: PĂ©rez alias: RoberTnf +- alias: Physics-is-awesome + - given-names: Preston family-names: Pitzer affiliation: Virginia Tech @@ -730,21 +748,3 @@ authors: - given-names: Carol family-names: Zhang alias: carolyz - -- alias: Physics-is-awesome - -- given-names: Bao - family-names: Nguyen - affiliation: Imperial College London - orcid: https://orcid.org/0000-0002-1753-4223 - alias: wnguyen1312 - -- given-names: Emmanuel - family-names: Ferdman - orcid: https://orcid.org/0009-0004-8953-0151 - alias: emmanuel-ferdman - -- given-names: Mahlet - family-names: Getahun - affiliation: Marietta College - alias: Getahun-yw-Mahl From 0c73f8045dcb06c1f33f35d5734f940a72c179e3 Mon Sep 17 00:00:00 2001 From: "plasmapy-requirements-bot[bot]" <134649236+plasmapy-requirements-bot[bot]@users.noreply.github.com> Date: Tue, 5 Aug 2025 11:24:58 -0400 Subject: [PATCH 439/521] Update requirements with 'nox -s requirements' (#3079) Co-authored-by: namurphy <8931994+namurphy@users.noreply.github.com> --- uv.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/uv.lock b/uv.lock index dfef47f8e7..2824e24bbf 100644 --- a/uv.lock +++ b/uv.lock @@ -634,15 +634,15 @@ wheels = [ [[package]] name = "hypothesis" -version = "6.136.9" +version = "6.137.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "attrs" }, { name = "sortedcontainers" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/62/fe/f872b3f29d5b59179c2b9c51e594703ab21e07dd22a354091b130cb863f2/hypothesis-6.136.9.tar.gz", hash = "sha256:8cc3c75a57cf3706249e3f7055b194648aa04a537deaa2099e28dc70d88da129", size = 459298, upload-time = "2025-08-04T21:54:48.774Z" } +sdist = { url = "https://files.pythonhosted.org/packages/65/92/70f29b04e4d7acf7f9a0c3dd52619853715ad9ae092a8e5d89bc7bdc39ec/hypothesis-6.137.1.tar.gz", hash = "sha256:b086e644456da79ad460fdaf8fbf90a41a661e8a4076232dd4ea64cfbc0d0529", size = 460593, upload-time = "2025-08-05T06:31:46.777Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/fb/3b/cfdc2e2f13decd9be1fb32ba58473b974f953e996e1466ae65a0cd9dd2d0/hypothesis-6.136.9-py3-none-any.whl", hash = "sha256:c052412bb8b8b5090fb00eff0a7c80bfaeab9f0364e65fd3f4d08a002e478346", size = 526167, upload-time = "2025-08-04T21:54:44.718Z" }, + { url = "https://files.pythonhosted.org/packages/1a/13/92753f97f70f3584a70ccbd2a678878ea43d5880c4e009664c3fe9fe7e50/hypothesis-6.137.1-py3-none-any.whl", hash = "sha256:7cbda6a98ed4d32aad31a5fc5bff5e119b9275fe2579a7b08863cba313a4b9be", size = 527566, upload-time = "2025-08-05T06:31:43.323Z" }, ] [[package]] From 2a7bef4912e993ec785c1e6bfd5d83384ae0f2df Mon Sep 17 00:00:00 2001 From: Nick Murphy Date: Tue, 5 Aug 2025 14:35:48 -0400 Subject: [PATCH 440/521] Use `GITHUB_TOKEN` in workflow to mint a release (#3080) * Update default values * Use GITHUB_TOKEN in workflow * Apply suggestions from code review --------- Co-authored-by: PlasmaPy Release Bot --- .github/workflows/mint-release.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/mint-release.yml b/.github/workflows/mint-release.yml index 7ca682dbcb..05bfa4fb1a 100644 --- a/.github/workflows/mint-release.yml +++ b/.github/workflows/mint-release.yml @@ -6,11 +6,11 @@ on: tag: description: Release tag đŸ·ïž required: true - default: 2024.5.0rc1 + default: 2025.8.0rc1 DOI: description: Reserved DOI from Zenodo required: true - default: 10.5281/zenodo.1238132 + default: 10.5281/zenodo.16747747 jobs: @@ -68,3 +68,5 @@ jobs: VERSION="v${{ github.event.inputs.tag }}" BRANCH=$(echo $VERSION | awk 'BEGIN{FS=OFS="."} {$3="x"} 1' | cut -f1,2,3 -d'.' | awk -F'rc' '{print $1 ORS $2}') git push -u origin $VERSION $BRANCH + env: + GITHUB_TOKEN: ${{ secrets.WORKFLOW_TOKEN }} From 3a591c7c9707c16c8ed124a92342c3bb21f5eb0c Mon Sep 17 00:00:00 2001 From: Nick Murphy Date: Wed, 6 Aug 2025 18:37:40 -0400 Subject: [PATCH 441/521] Restructure the workflow to mint a release (#3081) * Begin revamping workflow * Add dependency information to citation_updater.py * Continue revamping mint-release.yml * Rename variable in changelog session * Update nox command for changelog * Update command to create changelog * Update noxfile.py * Update workflow * Remove currentmodule directives in changelog entries * Update changelog session * Update workflow * Update changelog session * Text updates to changelog session * Update workflow to mint a release * Stop ignoring zizmor rules in mint-release.yml * Minor updates * Update workflow --------- Co-authored-by: PlasmaPy Release Bot --- .github/scripts/citation_updater.py | 5 ++ .github/workflows/mint-release.yml | 93 ++++++++++++++++++----------- .github/zizmor.yml | 6 -- changelog/3034.feature.rst | 4 +- changelog/3037.feature.rst | 5 +- noxfile.py | 52 ++++++---------- 6 files changed, 84 insertions(+), 81 deletions(-) diff --git a/.github/scripts/citation_updater.py b/.github/scripts/citation_updater.py index 9adea652eb..5b751eec40 100644 --- a/.github/scripts/citation_updater.py +++ b/.github/scripts/citation_updater.py @@ -1,3 +1,8 @@ +# /// script +# requires-python = ">=3.13" +# dependencies = [ "ruamel.yaml" ] +# /// + """Functionality to update citation information prior to making a release.""" import argparse diff --git a/.github/workflows/mint-release.yml b/.github/workflows/mint-release.yml index 05bfa4fb1a..649e15a94f 100644 --- a/.github/workflows/mint-release.yml +++ b/.github/workflows/mint-release.yml @@ -3,15 +3,22 @@ name: Mint release 🍬 on: workflow_dispatch: inputs: - tag: - description: Release tag đŸ·ïž + version: + description: Date-based version đŸ·ïž required: true default: 2025.8.0rc1 - DOI: + doi: description: Reserved DOI from Zenodo required: true default: 10.5281/zenodo.16747747 +permissions: + contents: write + +defaults: + run: + shell: bash + jobs: tag: @@ -19,54 +26,72 @@ jobs: steps: - - name: Checkout code - uses: actions/checkout@v4 - with: - persist-credentials: false - - - name: Set up Python - uses: actions/setup-python@v5 - with: - python-version: '3.13' + - name: Validate version input + run: | + if [[ ! ${VERSION} =~ ^2[0-9]{3}\.[0-9]+\.[0-9]+((a|b|rc)[0-9]+)?$ ]]; then + echo "::error ::Provide a calendar version like `2025.8.0` (or `2025.8.0a0`, `2025.8.0b0`, or `2025.8.0rc1` for pre-releases)" + exit 1 + fi + env: + VERSION: ${{ github.event.inputs.version }} - - name: Install dependencies + - name: Validate DOI input run: | - pip install towncrier pre-commit ruamel.yaml + if [[ ! ${DOI} =~ ^10\.[0-9]{4,9}/\S+$]]; then + echo "::error ::Provide a valid DOI reserved from Zenodo." + exit 1 + fi + env: + DOI: ${{ github.event.inputs.doi }} - name: Configure git run: | git config --global user.email "team@plasmapy.org" git config --global user.name "PlasmaPy Release Bot" - - name: Create or checkout branch + - name: Checkout code + uses: actions/checkout@v4 + with: + persist-credentials: true + fetch-depth: 0 # fetch all branches and tags prior to creating a new tag + + - name: Check out branch run: | - VERSION="v${{ github.event.inputs.tag }}" - BRANCH=$(echo $VERSION | awk 'BEGIN{FS=OFS="."} {$3="x"} 1' | cut -f1,2,3 -d'.' | awk -F'rc' '{print $1 ORS $2}') - git checkout $BRANCH 2>/dev/null || git checkout -b $BRANCH + git branch -f ${BRANCH} + git switch ${BRANCH} + env: + BRANCH: prepare-v${{ github.event.inputs.version }} - - name: Update CITATION.cff, docs/about/citation.rst with the DOI for the new version. + - name: Install the latest version of uv + uses: astral-sh/setup-uv@v6 + + - name: Update version and DOI in CITATION.cff and docs/about/citation.rst run: | - python .github/scripts/citation_updater.py CITATION.cff docs/about/citation.rst docs/changelog/index.rst --version=${{ github.event.inputs.tag}} --doi=${{ github.event.inputs.doi}} + uv run .github/scripts/citation_updater.py CITATION.cff docs/about/citation.rst docs/changelog/index.rst --version=${VERSION} --doi=${DOI} git add . - git commit -m "Update citation and changelog index entry" + git commit -m "Update version & DOI in CITATION.cff & citation.rst" - - name: Create changelog + - name: Build the changelog run: | - towncrier build --yes --version ${{ github.event.inputs.tag }} --draft | tee docs/changelog/${{ github.event.inputs.tag }}.rst - sed -i -e :a -e '/^\n*$/{$d;N;ba' -e '}' docs/changelog/${{ github.event.inputs.tag }}.rst # strip empty lines + uvx nox -s "changelog(final)" -- ${VERSION} git add . - towncrier build --yes --version ${{ github.event.inputs.tag }} - git commit --allow-empty -nm "Add changelog entries for v${{ github.event.inputs.tag }}" + git commit --allow-empty -m "Build changelog with towncrier for ${VERSION}" + env: + VERSION: ${{ github.event.inputs.version }} - - name: Tag the release + - name: Apply changes from pre-commit, if necessary run: | - git tag "v${{ github.event.inputs.tag }}" -m "Version v${{ github.event.inputs.tag }}" - git tag + pre-commit run --all-files + git commit -m "Apply changes from pre-commit" + continue-on-error: true - - name: Push tag, branch state + - name: Tag the release run: | - VERSION="v${{ github.event.inputs.tag }}" - BRANCH=$(echo $VERSION | awk 'BEGIN{FS=OFS="."} {$3="x"} 1' | cut -f1,2,3 -d'.' | awk -F'rc' '{print $1 ORS $2}') - git push -u origin $VERSION $BRANCH + git tag "v${VERSION}" -m "Version v${VERSION}" + git show "v${VERSION}" env: - GITHUB_TOKEN: ${{ secrets.WORKFLOW_TOKEN }} + VERSION: ${{ github.event.inputs.version }} + +# - name: Push tag, branch state +# run: | +# git push -u origin $VERSION $BRANCH diff --git a/.github/zizmor.yml b/.github/zizmor.yml index 18e8dd55b7..b038fdfb78 100644 --- a/.github/zizmor.yml +++ b/.github/zizmor.yml @@ -24,17 +24,11 @@ rules: - changelog.yml:9:3 - changelog.yml:10:3 - comment-on-pr.yml:8:3 - - mint-release.yml:17:3 - unlabel-pr-after-merge.yml:8:3 - update-pinned-reqs.yml:9:3 template-injection: ignore: - create-release-issue.yml:21:7 - - mint-release.yml:41:7 - - mint-release.yml:47:7 - - mint-release.yml:53:7 - - mint-release.yml:61:7 - - mint-release.yml:66:7 use-trusted-publishing: ignore: - publish-to-pypi.yml:36:7 diff --git a/changelog/3034.feature.rst b/changelog/3034.feature.rst index 32c7b1b62f..e17bd187ff 100644 --- a/changelog/3034.feature.rst +++ b/changelog/3034.feature.rst @@ -1,4 +1,2 @@ -.. currentmodule:: plasmapy.analysis.swept_langmuir - -Added helper function `~helpers.sort_sweep_arrays` to +Added helper function `~plasmapy.analysis.swept_langmuir.helpers.sort_sweep_arrays` to `plasmapy.analysis.swept_langmuir`. diff --git a/changelog/3037.feature.rst b/changelog/3037.feature.rst index af8126a8f9..7efbc5fafa 100644 --- a/changelog/3037.feature.rst +++ b/changelog/3037.feature.rst @@ -1,4 +1 @@ -.. currentmodule:: plasmapy.analysis.swept_langmuir - -Added helper function `~helpers.merge_voltage_clusters` to -`plasmapy.analysis.swept_langmuir`. +Added helper function `~plasmapy.analysis.swept_langmuir.helpers.merge_voltage_clusters` to `plasmapy.analysis.swept_langmuir`. diff --git a/noxfile.py b/noxfile.py index 516a1f177b..5a7fa29578 100644 --- a/noxfile.py +++ b/noxfile.py @@ -577,13 +577,15 @@ def build(session: nox.Session) -> None: @nox.session -@nox.parametrize("draft", [nox.param(False, id="draft"), nox.param(True, id="final")]) +@nox.parametrize("final", [nox.param(False, id="draft"), nox.param(True, id="final")]) def changelog(session: nox.Session, final: str) -> None: """ Build the changelog with towncrier. - - 'final': build the combined changelog for the release, and delete - the individual changelog entries in `changelog`. + - 'final': build the combined changelog for the release, delete + the individual changelog entries in `changelog`, and replace + `CHANGELOG.rst`. Be sure to commit changes before running this + session. - 'draft': print the draft changelog to standard output, without writing to files @@ -596,54 +598,36 @@ def changelog(session: nox.Session, final: str) -> None: if len(session.posargs) != 1: raise TypeError( "Please provide the version of PlasmaPy to be released " - "(i.e., `nox -s changelog -- 2024.9.0`" - ) - - source_directory = pathlib.Path("./changelog") - - extraneous_files = source_directory.glob("changelog/*[0-9]*.*.rst?*") - if final and extraneous_files: - session.error( - "Please delete the following extraneous files before " - "proceeding, as the presence of these files may cause " - f"towncrier errors: {extraneous_files}" + "(i.e., `nox -s changelog -- 2025.10.0`)" ) version = session.posargs[0] - year_pattern = r"(202[4-9]|20[3-9][0-9]|2[1-9][0-9]{2}|[3-9][0-9]{3,})" month_pattern = r"(1[0-2]|[1-9])" patch_pattern = r"(0?[0-9]|[1-9][0-9])" version_pattern = rf"^{year_pattern}\.{month_pattern}\.{patch_pattern}$" - if not re.match(version_pattern, version): raise ValueError( "Please provide a version of the form YYYY.M.PATCH, where " - "YYYY is the year past 2024, M is the one or two digit month, " + "YYYY is he year, M is the one or two digit month, " "and PATCH is a non-negative integer." ) session.install(".", "towncrier") - options = ("--yes",) if final else ("--draft", "--keep") + towncrier = ["towncrier", "build", "--version", version] - session.run( - "towncrier", - "build", - "--config", - "pyproject.toml", - "--dir", - ".", - "--version", - version, - *options, - *session.posargs, - ) + if not final: + session.run(*towncrier, "--draft", "--keep") + return + + original_file = pathlib.Path("./CHANGELOG.rst") + original_file.unlink() + + session.run(*towncrier, "--yes") - if final: - original_file = pathlib.Path("./CHANGELOG.rst") - destination = pathlib.Path(f"./docs/changelog/{version}.rst") - original_file.rename(destination) + destination = pathlib.Path(f"./docs/changelog/{version}.rst") + shutil.copy(original_file, destination) @nox.session From eef69c298a7d9fa157bd21fece677958d2723677 Mon Sep 17 00:00:00 2001 From: Nick Murphy Date: Wed, 6 Aug 2025 18:41:43 -0400 Subject: [PATCH 442/521] Fix typo in workflow (#3083) --- .github/workflows/mint-release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/mint-release.yml b/.github/workflows/mint-release.yml index 649e15a94f..254964e8ed 100644 --- a/.github/workflows/mint-release.yml +++ b/.github/workflows/mint-release.yml @@ -37,7 +37,7 @@ jobs: - name: Validate DOI input run: | - if [[ ! ${DOI} =~ ^10\.[0-9]{4,9}/\S+$]]; then + if [[ ! ${DOI} =~ ^10\.[0-9]{4,9}/\S+$ ]]; then echo "::error ::Provide a valid DOI reserved from Zenodo." exit 1 fi From 359cc642c9b92317d2e0a01e0f5b1d43273093e5 Mon Sep 17 00:00:00 2001 From: Nick Murphy Date: Wed, 6 Aug 2025 19:16:01 -0400 Subject: [PATCH 443/521] Fix regular expression (#3084) --- .github/workflows/mint-release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/mint-release.yml b/.github/workflows/mint-release.yml index 254964e8ed..6006bced10 100644 --- a/.github/workflows/mint-release.yml +++ b/.github/workflows/mint-release.yml @@ -37,7 +37,7 @@ jobs: - name: Validate DOI input run: | - if [[ ! ${DOI} =~ ^10\.[0-9]{4,9}/\S+$ ]]; then + if [[ ! ${DOI} =~ ^10\.[0-9]{4,9}/.*$ ]]; then echo "::error ::Provide a valid DOI reserved from Zenodo." exit 1 fi From c678e89b0fec710edd782ba4efa11ddc8739eb14 Mon Sep 17 00:00:00 2001 From: Nick Murphy Date: Wed, 6 Aug 2025 20:00:07 -0400 Subject: [PATCH 444/521] Fix changelog and pre-commit steps (#3085) --- .github/workflows/mint-release.yml | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/.github/workflows/mint-release.yml b/.github/workflows/mint-release.yml index 6006bced10..bc88fc69ea 100644 --- a/.github/workflows/mint-release.yml +++ b/.github/workflows/mint-release.yml @@ -71,18 +71,21 @@ jobs: git add . git commit -m "Update version & DOI in CITATION.cff & citation.rst" - - name: Build the changelog + - name: Build the changelog with towncrier if not a prerelease run: | + if [[ ! ${VERSION} =~ ^2[0-9]{3}\.[0-9]+\.[0-9]+$ ]]; then uvx nox -s "changelog(final)" -- ${VERSION} git add . - git commit --allow-empty -m "Build changelog with towncrier for ${VERSION}" + git commit --allow-empty -m "Build changelog for ${VERSION}" + fi env: VERSION: ${{ github.event.inputs.version }} - name: Apply changes from pre-commit, if necessary run: | - pre-commit run --all-files - git commit -m "Apply changes from pre-commit" + pre-commit run --all-files # fails if changes are needed + git add . + git commit -m "Apply any needed changes from pre-commit" # fails if no changes are needed continue-on-error: true - name: Tag the release From 4c1bc229d74067285b083a2cd8bc13ed0d5163f9 Mon Sep 17 00:00:00 2001 From: Nick Murphy Date: Wed, 6 Aug 2025 20:04:11 -0400 Subject: [PATCH 445/521] Fix regular expression in workflow (#3086) --- .github/workflows/mint-release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/mint-release.yml b/.github/workflows/mint-release.yml index bc88fc69ea..fda800532b 100644 --- a/.github/workflows/mint-release.yml +++ b/.github/workflows/mint-release.yml @@ -73,7 +73,7 @@ jobs: - name: Build the changelog with towncrier if not a prerelease run: | - if [[ ! ${VERSION} =~ ^2[0-9]{3}\.[0-9]+\.[0-9]+$ ]]; then + if [[ ${VERSION} =~ ^2[0-9]{3}\.[0-9]+\.[0-9]+$ ]]; then uvx nox -s "changelog(final)" -- ${VERSION} git add . git commit --allow-empty -m "Build changelog for ${VERSION}" From 5fa4c0ac89bd210b8349024675ef38309be8b637 Mon Sep 17 00:00:00 2001 From: Nick Murphy Date: Thu, 7 Aug 2025 16:33:33 -0400 Subject: [PATCH 446/521] Update release workflow to mint a release (#3087) * Update release workflow * Make the workflow submit a PR * Rename file * Update workflow * Ignore zizmor error --- .github/workflows/mint-release.yml | 100 ----------------------- .github/workflows/prepare-release-pr.yml | 83 +++++++++++++++++++ .github/zizmor.yml | 1 + 3 files changed, 84 insertions(+), 100 deletions(-) delete mode 100644 .github/workflows/mint-release.yml create mode 100644 .github/workflows/prepare-release-pr.yml diff --git a/.github/workflows/mint-release.yml b/.github/workflows/mint-release.yml deleted file mode 100644 index fda800532b..0000000000 --- a/.github/workflows/mint-release.yml +++ /dev/null @@ -1,100 +0,0 @@ -name: Mint release 🍬 - -on: - workflow_dispatch: - inputs: - version: - description: Date-based version đŸ·ïž - required: true - default: 2025.8.0rc1 - doi: - description: Reserved DOI from Zenodo - required: true - default: 10.5281/zenodo.16747747 - -permissions: - contents: write - -defaults: - run: - shell: bash - -jobs: - - tag: - runs-on: ubuntu-latest - - steps: - - - name: Validate version input - run: | - if [[ ! ${VERSION} =~ ^2[0-9]{3}\.[0-9]+\.[0-9]+((a|b|rc)[0-9]+)?$ ]]; then - echo "::error ::Provide a calendar version like `2025.8.0` (or `2025.8.0a0`, `2025.8.0b0`, or `2025.8.0rc1` for pre-releases)" - exit 1 - fi - env: - VERSION: ${{ github.event.inputs.version }} - - - name: Validate DOI input - run: | - if [[ ! ${DOI} =~ ^10\.[0-9]{4,9}/.*$ ]]; then - echo "::error ::Provide a valid DOI reserved from Zenodo." - exit 1 - fi - env: - DOI: ${{ github.event.inputs.doi }} - - - name: Configure git - run: | - git config --global user.email "team@plasmapy.org" - git config --global user.name "PlasmaPy Release Bot" - - - name: Checkout code - uses: actions/checkout@v4 - with: - persist-credentials: true - fetch-depth: 0 # fetch all branches and tags prior to creating a new tag - - - name: Check out branch - run: | - git branch -f ${BRANCH} - git switch ${BRANCH} - env: - BRANCH: prepare-v${{ github.event.inputs.version }} - - - name: Install the latest version of uv - uses: astral-sh/setup-uv@v6 - - - name: Update version and DOI in CITATION.cff and docs/about/citation.rst - run: | - uv run .github/scripts/citation_updater.py CITATION.cff docs/about/citation.rst docs/changelog/index.rst --version=${VERSION} --doi=${DOI} - git add . - git commit -m "Update version & DOI in CITATION.cff & citation.rst" - - - name: Build the changelog with towncrier if not a prerelease - run: | - if [[ ${VERSION} =~ ^2[0-9]{3}\.[0-9]+\.[0-9]+$ ]]; then - uvx nox -s "changelog(final)" -- ${VERSION} - git add . - git commit --allow-empty -m "Build changelog for ${VERSION}" - fi - env: - VERSION: ${{ github.event.inputs.version }} - - - name: Apply changes from pre-commit, if necessary - run: | - pre-commit run --all-files # fails if changes are needed - git add . - git commit -m "Apply any needed changes from pre-commit" # fails if no changes are needed - continue-on-error: true - - - name: Tag the release - run: | - git tag "v${VERSION}" -m "Version v${VERSION}" - git show "v${VERSION}" - env: - VERSION: ${{ github.event.inputs.version }} - -# - name: Push tag, branch state -# run: | -# git push -u origin $VERSION $BRANCH diff --git a/.github/workflows/prepare-release-pr.yml b/.github/workflows/prepare-release-pr.yml new file mode 100644 index 0000000000..fa4812cdb8 --- /dev/null +++ b/.github/workflows/prepare-release-pr.yml @@ -0,0 +1,83 @@ +name: Prepare a release + +on: + workflow_dispatch: + inputs: + version: + description: Version + required: true + default: 2025.8.0 + doi: + description: Reserved DOI from Zenodo + required: true + default: 10.5281/zenodo.16747747 + +jobs: + create-pull-request: + name: Create pull request + runs-on: ubuntu-latest + + steps: + + - name: Validate version input + run: | + if [[ ! ${VERSION} =~ ^2[0-9]{3}\.[0-9]+\.[0-9]+$ ]]; then + echo "::error ::Provide a calendar version like `2025.8.0`" + exit 1 + fi + env: + VERSION: ${{ github.event.inputs.version }} + + - name: Validate DOI input + run: | + if [[ ! ${DOI} =~ ^10\.[0-9]{4,9}/.*$ ]]; then + echo "::error ::Provide a valid DOI reserved from Zenodo." + exit 1 + fi + env: + DOI: ${{ github.event.inputs.doi }} + + - name: Checkout code + uses: actions/checkout@v4 + with: + persist-credentials: false + + - name: Install uv + uses: astral-sh/setup-uv@v6 + + - name: Update version and DOI in CITATION.cff and docs/about/citation.rst + run: | + uv run .github/scripts/citation_updater.py CITATION.cff docs/about/citation.rst docs/changelog/index.rst --version=$VERSION --doi=$DOI + env: + VERSION: ${{ github.event.inputs.version }} + DOI: ${{ github.event.inputs.doi }} + + - name: Build the changelog with towncrier + run: | + uvx nox -s "changelog(final)" -- $VERSION + env: + VERSION: ${{ github.event.inputs.version }} + + # When a PR is created by a GitHub Action, normally the checks will + # not be run. While the simplest workaround would have been to open + # and close the PR, an alternative is to authenticate with GitHub + # App generated tokens (as done below). The instructions for how to + # do this are in the documentation for the create-pull-request + # action. + + - name: Generate token + uses: tibdex/github-app-token@3beb63f4bd073e61482598c45c71c1019b59b73a # v2.1.0 + id: generate_token + with: + app_id: ${{ secrets.APP_ID }} + private_key: ${{ secrets.APP_PRIVATE_KEY }} + + - name: Create pull request + uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7.0.8 + with: + title: Build changelog and update package metadata prior to a release + commit-message: Build changelog & update citation info + body: This automated pull request builds the changelog with towncrier and updates package metadata prior to a forthcoming release. Merge this pull request prior to drafting the release. + labels: skip changelog checks + delete-branch: true + token: ${{ steps.generate_token.outputs.token }} diff --git a/.github/zizmor.yml b/.github/zizmor.yml index b038fdfb78..21e5ede1f8 100644 --- a/.github/zizmor.yml +++ b/.github/zizmor.yml @@ -24,6 +24,7 @@ rules: - changelog.yml:9:3 - changelog.yml:10:3 - comment-on-pr.yml:8:3 + - prepare-release-pr.yml:16:3 - unlabel-pr-after-merge.yml:8:3 - update-pinned-reqs.yml:9:3 template-injection: From b48a6d0861ce02f8c01c8dd91552d95b252e4c28 Mon Sep 17 00:00:00 2001 From: "plasmapy-requirements-bot[bot]" <134649236+plasmapy-requirements-bot[bot]@users.noreply.github.com> Date: Thu, 7 Aug 2025 17:04:22 -0400 Subject: [PATCH 447/521] Build changelog and update package metadata prior to a release (#3088) * Build changelog & update citation info * nox -s requirements * Make minor edits to the changelog * pre-commit --------- Co-authored-by: namurphy <8931994+namurphy@users.noreply.github.com> Co-authored-by: Nick Murphy Co-authored-by: Nick Murphy --- CHANGELOG.rst | 440 ++++++++++++++++------------------ CITATION.cff | 6 +- changelog/1643.doc.1.rst | 2 - changelog/1643.doc.2.rst | 1 - changelog/1643.doc.3.rst | 2 - changelog/1643.doc.4.rst | 2 - changelog/1643.doc.5.rst | 2 - changelog/1643.doc.6.rst | 3 - changelog/2790.feature.rst | 2 - changelog/2880.internal.rst | 2 - changelog/2886.internal.rst | 1 - changelog/2887.internal.rst | 1 - changelog/2890.doc.rst | 1 - changelog/2892.doc.rst | 1 - changelog/2895.doc.rst | 1 - changelog/2897.removal.rst | 1 - changelog/2901.doc.rst | 1 - changelog/2906.internal.rst | 1 - changelog/2911.breaking.1.rst | 3 - changelog/2911.breaking.2.rst | 4 - changelog/2911.breaking.3.rst | 4 - changelog/2911.feature.rst | 3 - changelog/2911.internal.1.rst | 8 - changelog/2911.trivial.1.rst | 2 - changelog/2915.doc.rst | 4 - changelog/2915.internal.rst | 2 - changelog/2919.internal.rst | 1 - changelog/2932.doc.rst | 1 - changelog/2935.doc.rst | 1 - changelog/2937.internal.rst | 8 - changelog/2938.doc.rst | 1 - changelog/2943.doc.rst | 1 - changelog/2959.internal.rst | 1 - changelog/2961.internal.rst | 2 - changelog/2964.internal.rst | 3 - changelog/2968.feature.1.rst | 2 - changelog/2968.feature.2.rst | 3 - changelog/2974.internal.rst | 1 - changelog/2975.internal.rst | 1 - changelog/2981.internal.rst | 1 - changelog/2984.trivial.rst | 1 - changelog/2985.internal.rst | 1 - changelog/2997.internal.rst | 3 - changelog/2998.internal.rst | 1 - changelog/2999.doc.rst | 1 - changelog/3013.doc.rst | 1 - changelog/3021.feature.rst | 1 - changelog/3024.doc.rst | 1 - changelog/3032.feature.rst | 1 - changelog/3034.feature.rst | 2 - changelog/3036.feature.rst | 1 - changelog/3037.feature.rst | 1 - changelog/3039.internal.rst | 1 - changelog/3045.bugfix.rst | 1 - changelog/3056.doc.rst | 1 - changelog/3059.doc.rst | 1 - changelog/3060.breaking.rst | 2 - changelog/3065.bugfix.rst | 2 - changelog/3065.internal.1.rst | 1 - changelog/3065.internal.2.rst | 2 - changelog/3065.internal.3.rst | 1 - changelog/3068.doc.rst | 2 - changelog/3069.doc.rst | 2 - changelog/3070.doc.rst | 1 - changelog/3073.doc.rst | 3 - docs/about/citation.rst | 6 +- docs/changelog/2025.8.0.rst | 232 ++++++++++++++++++ uv.lock | 281 +++++++++++----------- 68 files changed, 583 insertions(+), 498 deletions(-) delete mode 100644 changelog/1643.doc.1.rst delete mode 100644 changelog/1643.doc.2.rst delete mode 100644 changelog/1643.doc.3.rst delete mode 100644 changelog/1643.doc.4.rst delete mode 100644 changelog/1643.doc.5.rst delete mode 100644 changelog/1643.doc.6.rst delete mode 100644 changelog/2790.feature.rst delete mode 100644 changelog/2880.internal.rst delete mode 100644 changelog/2886.internal.rst delete mode 100644 changelog/2887.internal.rst delete mode 100644 changelog/2890.doc.rst delete mode 100644 changelog/2892.doc.rst delete mode 100644 changelog/2895.doc.rst delete mode 100644 changelog/2897.removal.rst delete mode 100644 changelog/2901.doc.rst delete mode 100644 changelog/2906.internal.rst delete mode 100644 changelog/2911.breaking.1.rst delete mode 100644 changelog/2911.breaking.2.rst delete mode 100644 changelog/2911.breaking.3.rst delete mode 100644 changelog/2911.feature.rst delete mode 100644 changelog/2911.internal.1.rst delete mode 100644 changelog/2911.trivial.1.rst delete mode 100644 changelog/2915.doc.rst delete mode 100644 changelog/2915.internal.rst delete mode 100644 changelog/2919.internal.rst delete mode 100644 changelog/2932.doc.rst delete mode 100644 changelog/2935.doc.rst delete mode 100644 changelog/2937.internal.rst delete mode 100644 changelog/2938.doc.rst delete mode 100644 changelog/2943.doc.rst delete mode 100644 changelog/2959.internal.rst delete mode 100644 changelog/2961.internal.rst delete mode 100644 changelog/2964.internal.rst delete mode 100644 changelog/2968.feature.1.rst delete mode 100644 changelog/2968.feature.2.rst delete mode 100644 changelog/2974.internal.rst delete mode 100644 changelog/2975.internal.rst delete mode 100644 changelog/2981.internal.rst delete mode 100644 changelog/2984.trivial.rst delete mode 100644 changelog/2985.internal.rst delete mode 100644 changelog/2997.internal.rst delete mode 100644 changelog/2998.internal.rst delete mode 100644 changelog/2999.doc.rst delete mode 100644 changelog/3013.doc.rst delete mode 100644 changelog/3021.feature.rst delete mode 100644 changelog/3024.doc.rst delete mode 100644 changelog/3032.feature.rst delete mode 100644 changelog/3034.feature.rst delete mode 100644 changelog/3036.feature.rst delete mode 100644 changelog/3037.feature.rst delete mode 100644 changelog/3039.internal.rst delete mode 100644 changelog/3045.bugfix.rst delete mode 100644 changelog/3056.doc.rst delete mode 100644 changelog/3059.doc.rst delete mode 100644 changelog/3060.breaking.rst delete mode 100644 changelog/3065.bugfix.rst delete mode 100644 changelog/3065.internal.1.rst delete mode 100644 changelog/3065.internal.2.rst delete mode 100644 changelog/3065.internal.3.rst delete mode 100644 changelog/3068.doc.rst delete mode 100644 changelog/3069.doc.rst delete mode 100644 changelog/3070.doc.rst delete mode 100644 changelog/3073.doc.rst create mode 100644 docs/changelog/2025.8.0.rst diff --git a/CHANGELOG.rst b/CHANGELOG.rst index dabd3c7674..4498c4938d 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,272 +1,234 @@ -PlasmaPy v2024.10.0 (2024-10-30) -================================ +PlasmaPy v2025.8.0 (2025-08-07) +=============================== New Features ------------ -- Added the option to pass |inf| to the - `~plasmapy.particles.particle_class.Particle.ionize` method of |Particle| to - return the nucleus of the particle. (:pr:`2800`) -- Implemented - `~plasmapy.simulation.resolution_constraints.CFL_limit_electromagnetic_yee` - to calculate the CFL condition for electromagnetic simulations. (:pr:`2832`) -- - `~plasmapy.diagnostics.charged_particle_radiography.synthetic_radiography.synthetic_radiograph` - now accepts a file path to an - HDF5 file saved by +- Enabled |particle_input| to convert |particle-list-like| arguments passed + to parameters decorated with |ParticleListLike| into |ParticleList| + instances. (:pr:`2790`) +- The new method `~plasmapy.plasma.grids.CartesianGrid.soften_edges` applies an + error function mask + to the edges of all quantities on a grid. This is useful for any application + where the grid must + go to zero smoothly at the edges (e.g., for particle tracking with + |ParticleTracker|). (:pr:`2911`) +- Added the ``source_vdir`` keyword to the + `~plasmapy.diagnostics.charged_particle_radiography.synthetic_radiography.Tracker.create_particles` + method of `~plasmapy.diagnostics.charged_particle_radiography.synthetic_radiography.Tracker` - as input to create - a synthetic radiograph. (:pr:`2868`) -- Save routines in `~plasmapy.simulation.particle_tracker.save_routines` now - take an optional keyword argument ``output_basename`` - that sets the basename of the saved file(s). + to explicitly define the + orientation of the mean velocity of the source particles. (:pr:`2968`) +- Added the ``detector_vdir`` keyword to `~plasmapy.diagnostics.charged_particle_radiography.synthetic_radiography.Tracker` - now - also accepts an ``output_basename`` keyword, which is passed to the save - routine. (:pr:`2868`) + to explicitly define the detector's vertical surface vector. (:pr:`2968`) +- Added a new module, `plasmapy.formulary.laser`, to make calculations related + to laser pulses. Added the first function, + `~plasmapy.formulary.laser.electric_field_amplitude`, which calculates the + electric field strength from intensity. (:pr:`3021`) +- Added `plasmapy.formulary.laser.intensity` to calculate intensity from the + electric field amplitude for a laser. (:pr:`3032`) +- Added helper function + `~plasmapy.analysis.swept_langmuir.helpers.sort_sweep_arrays` to + `plasmapy.analysis.swept_langmuir`. (:pr:`3034`) +- Added `~plasmapy.formulary.laser.em_wavelength`, + `~plasmapy.formulary.laser.em_angular_frequency`, + `~plasmapy.formulary.laser.Gaussian_beam_waist_radius`, + `~plasmapy.formulary.laser.Gaussian_spot_size_FWHM`, + `~plasmapy.formulary.laser.Gaussian_power`, + `~plasmapy.formulary.laser.Gaussian_Rayleigh_length`, and + `~plasmapy.formulary.laser.normalized_vector_potential` to + `plasmapy.formulary.laser`. (:pr:`3036`) +- Added helper function + `~plasmapy.analysis.swept_langmuir.helpers.merge_voltage_clusters` to + `plasmapy.analysis.swept_langmuir`. (:pr:`3037`) Documentation Improvements -------------------------- -- Updated the docstring of `~plasmapy.formulary.dimensionless.beta` to - explicitly - use definitions of :math:`p_{th}` and :math:`p_{mag}`, and added links - to `~plasmapy.formulary.misc.thermal_pressure` - and `~plasmapy.formulary.misc.magnetic_pressure`. (:pr:`2822`) -- Restructured sections in the `~plasmapy.formulary.mathematics.rot_a_to_b` - docstring to be consistent with other docstrings, and added 'Raises' and - 'Examples' sections. (:pr:`2824`) -- Added the :term:`force-free` definition to the |glossary|. (:pr:`2830`) -- Updated docstrings in `plasmapy.formulary` to follow the numpydoc standard. - (:pr:`2831`) -- Added examples to the |ParticleTracker| docstring. (:pr:`2833`) -- Added a section in the installation instructions for installing PlasmaPy with - |uv|. (:pr:`2861`) +- Incorporated the ``plasmapy_theme`` via the `plasmapy_sphinx.theme` + extension. (:pr:`1643`) +- Removed :file:`docs/plasmapy_sphinx` and put `plasmapy_sphinx` into its own + repository at https://github.com/PlasmaPy/plasmapy_sphinx\ . (:pr:`1643`) +- Added `plasmapy_sphinx` as a ``docs`` dependency. (:pr:`1643`) +- Removed upper dependency limit on `sphinx`, and added lower limit of + ``>=8.2.3``. (:pr:`1643`) +- Created a GitHub workflow (in :file:`weekly.yml` and :file:`noxfile.py`) + to build documentation using the latest development version of + `plasmapy_sphinx` on a weekly basis. (:pr:`1643`) +- Incorporated `sphinx` extensions `plasmapy_sphinx.ext.autodoc` and + `plasmapy_sphinx.ext.directives`. (:pr:`1643`) +- Updated author metadata in :file:`CITATION.cff`. (:pr:`2890`) +- Removed duplicate section headers for example notebooks in the documentation + for `plasmapy.formulary`. (:pr:`2892`) +- Added acknowledgements to several organizations that have supported PlasmaPy + or are aligned with its mission. (:pr:`2895`) +- Fixed formatting problems and improved verb tense consistency in prior + changelog entries. (:pr:`2901`) +- Fixed references to the ``astropy.units.equivalencies`` module in the docs. + Astropy now considers + this file to be private API (which broke PlasmaPy's intersphinx links), and + recommends that its contents be imported through the `astropy.units` + namespace. + This pull request changes those links to a direct URL to |Astropy + Equivalencies|. (:pr:`2915`) +- Added a sentence to the documentation for `plasmapy.dispersion` to describe + dispersion relations and their usefulness. (:pr:`2932`) +- Updated the instructions for accessing test results and documentation + previews in the |contributor guide| after recent changes to GitHub's user + interface. (:pr:`2935`) +- Expanded the docstring of `~plasmapy.formulary.dimensionless.Hall_parameter`. + (:pr:`2938`) +- Bumped the Python version for documentation builds from 3.12 to 3.13. + (:pr:`2943`) +- Updated the instructions on how to install PlasmaPy. (:pr:`2999`) +- Put office hours an an indefinite hiatus due to the conclusion of the NSF + collaborative awards supporting the development and growth of PlasmaPy. + (:pr:`3013`) +- Removed the `sphinx-hoverxref + `_ |Sphinx| extension, since + it has been deprecated in favor of the |Read the Docs| add-on for `Link + Previews `_\ + . (:pr:`3024`) +- Fixed broken hyperlinks and permanent redirects. (:pr:`3056`) +- Summarized the dependency support policy from |SPEC 0| at the end of the + installation instructions. (:pr:`3059`) +- Updated the |contributor guide| pages on the |code contribution workflow| + and :ref:`using pre-commit `. (:pr:`3068`) +- Upgraded :ref:`PlasmaPy's Code of Conduct ` to + version 3.0 of the Contributor Covenant. (:pr:`3069`) +- Updated the :ref:`Feedback and Communication ` page. + (:pr:`3070`) +- Limited the allowed version of |Sphinx| to ``sphinx>=8.2.3,<8.3`` + because planned breaking changes to Sphinx are causing documentation + build errors due to incompatibilities with some extensions. (:pr:`3073`) Backwards Incompatible Changes ------------------------------ -- Removed the ``optical_density`` keyword argument in - `~plasmapy.diagnostics.charged_particle_radiography.synthetic_radiography`. - (:pr:`2843`) -- The property `~plasmapy.plasma.grids.AbstractGrid.recognized_quantities` of - `~plasmapy.plasma.grids.AbstractGrid` is now a class method - instead of a class property, as using `classmethod` and `property` decorators - together is no longer - allowed in Python 3.13. The syntax for accessing this dictionary has - therefore changed - from :py:`AbstractGrid.recognized_quantities` to - :py:`AbstractGrid.recognized_quantities()`. (:pr:`2871`) - - -Bug Fixes ---------- - -- Patched a bug in - `~plasmapy.diagnostics.charged_particle_radiography.synthetic_radiography` in - which particles stopped - before the detector were still included in synthetic radiographs. - (:pr:`2843`) - - -Internal Changes and Refactorings +- Variables in |ParticleTracker| + and + `~plasmapy.diagnostics.charged_particle_radiography.synthetic_radiography.Tracker` + have been updated + such that ``n*`` is now ``num_*`` (e.g., ``nparticles`` is now + ``num_particles``). Similarly, ``v_init`` is + now ``v0`` to be consistent with ``x0``. (:pr:`2911`) +- The method + `~plasmapy.simulation.particle_tracker.particle_tracker.ParticleTracker.add_stopping` + requires that the argument ``I`` must now be a list of |Quantity| objects + rather than a single + |Quantity| array. This change is needed because `None` entries are now also + accepted to that + keyword as placeholders for grids on which stopping will not be applied. + (:pr:`2911`) +- |ParticleTracker| no longer accepts the parameter ``req_quantities``, but + instead automatically requires + quantities required by the tracker for the given setup. Users wishing to + require quantities + may use the method `~plasmapy.plasma.grids.AbstractGrid.require_quantities`. + (:pr:`2911`) +- Removed the prototype plasma calculator from PlasmaPy so that it can be + included in the |plasmapy-calculator| standalone package. (:pr:`3060`) + + +Deprecations and Planned Removals --------------------------------- -- Updated the release checklist. (:pr:`2784`) -- Added a |Nox| session to verify that the pinned requirements files used in - continuous integration tests are consistent with the requirements in - :file:`pyproject.toml`. (:pr:`2794`) -- Fixed a bug in the |Nox| session for running tests that prevented - doctests from being run, and fixed doctest errors that were introduced - while doctests were not enabled. (:pr:`2834`) -- Removed Numba as a project dependency. Consequently, - `~plasmapy.formulary.frequencies.plasma_frequency_lite` and - `~plasmapy.formulary.speeds.thermal_speed_lite` are no longer just-in-time - compiled by Numba. (:pr:`2841`) -- Adjusted the Sphinx configuration to account for recent deprecations in Read - the Docs. (:pr:`2857`) -- Added testing support for Python 3.13. (:pr:`2869`) -- Updated the versions of Python used in continuous integration workflows. - (:pr:`2879`) - - -Additional Changes ------------------- - -- Tentatively reverted :pr:`2715` because it introduced doctest errors during a - time when doctests were not enabled. (:pr:`2834`) - - -PlasmaPy v2024.7.0 (2024-07-21) -=============================== - -New Features ------------- - -- Implemented `~plasmapy.particles.atomic.stopping_power` to calculate stopping - powers using the NIST's ASTAR and PSTAR data. (:pr:`2555`) -- Added ionization energy data from NIST to the |Particle| class. - This can now be accessed using the - `~plasmapy.particles.particle_class.Particle.ionization_energy` attribute - from the |Particle| class. (:pr:`2657`) -- Renamed the `~plasmapy.particles.particle_class.Particle.binding_energy` - attribute of |Particle| to - `~plasmapy.particles.particle_class.Particle.nuclear_binding_energy` to avoid - confusion with - `~plasmapy.particles.particle_class.Particle.electron_binding_energy`. - (:pr:`2693`) -- Added electron binding energy data, relying on ionization energy data from - NIST, to the |Particle| class. - This can now be accessed using the - `~plasmapy.particles.particle_class.Particle.electron_binding_energy` - attribute - from the |Particle| class. (:pr:`2693`) -- Added a ``return_interpolator`` keyword to - `~plasmapy.particles.atomic.stopping_power` to allow the user to specify the - return of an interpolator function (`~scipy.interpolate.CubicSpline` under - the hood). (:pr:`2712`) -- Added the `~plasmapy.formulary.collisions.misc.Bethe_stopping` function to - the `~plasmapy.formulary.collisions` subpackage. (:pr:`2712`) -- Added the ability to enable particle stopping in the |ParticleTracker|. - (:pr:`2712`) - - -Documentation Improvements --------------------------- - -- Updated the |coding guide| with information on |static type checking| - with |mypy|. (:pr:`2454`) -- Updated the section in the |coding guide| about requirements and - dependencies. (:pr:`2720`) -- Updated docstrings in `plasmapy.dispersion`. (:pr:`2735`) -- Updated docstrings in `plasmapy.formulary.collisions`. (:pr:`2736`) -- Updated docstrings in `plasmapy.formulary`. (:pr:`2737`) -- Updated docstrings for `plasmapy.diagnostics` and `plasmapy.plasma.grids`. - (:pr:`2738`) -- Added :file:`README.md` files in the :file:`src/plasmapy`, :file:`tests`, - :file:`docs`, :file:`type_stubs`, :file:`.github/content`, - :file:`.github/scripts`, and :file:`.github/workflows` directories. The - contents of these files now appear as local documentation for each of these - directories in |PlasmaPy's GitHub repository|. (:pr:`2742`) -- Automated creation of the index file for the release changelogs. The page for - unreleased changes is included in the table of contents only if there are - unreleased changes. (:pr:`2754`) -- Re-wrote the "Test independence and parametrization" section of the |testing - guide| to use extremely simple math. (:pr:`2763`) -- Added functionality to generate a table of global substitutions in the - |documentation guide|. (:pr:`2766`) -- Renamed :file:`docs/_cff_to_rst.py` to :file:`docs/_author_list_from_cff.py`. - (:pr:`2766`) -- Based the version of PlasmaPy that gets included in development documentation - builds on the current date and most recent git hash. (:pr:`2775`) -- Merged the release guide into the |coding guide|. (:pr:`2777`) -- Added a new page to the |contributor guide| on |many ways to contribute| to - an open source project. (:pr:`2777`) -- Updated the |coding guide|, |testing guide|, and |documentation guide| - within the |contributor guide|. (:pr:`2777`) -- Moved the |contributor guide| section on example Jupyter notebooks from the - |coding guide| to the |documentation guide|. (:pr:`2777`) -- Added ``sphinxemoji`` as a |Sphinx| extension. (:pr:`2781`) - -Backwards Incompatible Changes ------------------------------- - -- Added a ``__str__`` method to the |CustomParticle| - class that returns the symbol of the particle if provided, and - otherwise falls back to using ``__repr__``. (:pr:`2702`) -- Changed default keyword argument for the ``fraction_exited_threshold`` in - `~plasmapy.diagnostics.charged_particle_radiography.synthetic_radiography.Tracker` - and - `~plasmapy.simulation.particle_tracker.termination_conditions.AllParticlesOffGridTerminationCondition` - to correspond with the fraction of particles that have entered and - subsequently exited the grids. Previously this keyword was a misnomer, - causing the simulation to instead terminate when the specified fraction of - particles remaining on the grids was less than or equal to the provided - ``fraction_exited_threshold``. (:pr:`2712`) -- Convert ``particle`` to a required argument of the - `~plasmapy.simulation.particle_tracker.particle_tracker.ParticleTracker.load_particles` - method of |ParticleTracker|. (:pr:`2746`) +- Removed :file:`src/plasmapy/dispersion/dispersionfunction.py`, which was + deprecated in ``v2023.10.0``. The functionality for the plasma dispersion + function is in `plasmapy.dispersion.dispersion_functions`. (:pr:`2897`) Bug Fixes --------- -- - Enabled |validate_quantities| to be compatible with postponed evaluation of - annotations (see :pep:`563`). (:pr:`2479`) (:pr:`2506`) -- Changed the |charge number| (:math:`Z`) dependence of the ion contribution to - the optical Thomson scattering - spectral density function in - `~plasmapy.diagnostics.thomson.spectral_density_lite` from :math:`Z` - to :math:`z^2 / \bar{z}` to match Eq. 5.1.2 and following equations in - :cite:t:`sheffield:2011`. - The result is a small change in the ion acoustic wave spectrum for plasmas - with multiple ion species. (:pr:`2699`) -- Add axes removed by `numpy.squeeze` to arrays in - `~plasmapy.dispersion.analytical.mhd_waves_` (:pr:`2715`) +- Enabled |Particle| to accept a `numpy.integer` object as the first argument + to indicate the atomic number. (:pr:`3045`) +- Fixed a possible bug when using + `plasmapy.plasma.grids.AbstractGrid.add_quantities` + alongside newer versions of |xarray|. (:pr:`3065`) Internal Changes and Refactorings --------------------------------- -- Converted the tox environment for regenerating the requirements files - used in continuous integration checks to |Nox|. (:pr:`2664`) -- Created a parametrized |Nox| session to run tests. (:pr:`2681`) -- Added |Nox| sessions to test importing PlasmaPy, validating - :file:`CITATION.cff`, - and building a source distribution and wheel. (:pr:`2682`) -- Switched the GitHub workflows for running tests from using tox environments - to using |Nox| sessions. (:pr:`2685`) -- Added ``pytest-filter-subpackage`` to the ``tests`` dependency set. This - dependency enables - us to run, for example, ``pytest -P particles`` to invoke tests for - `plasmapy.particles`. (:pr:`2688`) -- Added |Nox| sessions to run tests and build documentation against unreleased - versions - of major dependencies. (:pr:`2694`) -- Deleted :file:`tox.ini`, since all tox environments defined therein - have been converted to |Nox| sessions. (:pr:`2694`) -- Removed :file:`requirements.txt`, along with the requirements files - in :file:`ci_requirements/` that were used in tox environments - that have since been replaced with |Nox| sessions. (:pr:`2694`) -- Switched over weekly tests to use |Nox| sessions rather than tox - environments. (:pr:`2694`) -- Added the ``lint`` and ``manifest`` sessions for |Nox| to run |pre-commit| on - all files - and verify :file:`MANIFEST.in` with ``check-manifest``, respectively. - (:pr:`2695`) -- Added a |Nox| session that invokes ``autotyping`` to automatically - add |type hint annotations|, using either the ``--safe`` or - ``--aggressive`` options. (:pr:`2696`) -- Added ``typos`` as a |pre-commit| hook to perform spellchecking. (:pr:`2700`) -- Added a condition to check if the GitHub API can be reached to be used by the - `~plasmapy.utils.data.downloader.Downloader` object. (:pr:`2710`) -- Applied |type hint annotations| using ``autotyping``, and made other updates - to type - hint annotations and docstrings. (:pr:`2728`) -- Added |type hint annotations| to `plasmapy.utils.roman`. (:pr:`2733`) -- Added |type hint annotations| to ``plasmapy.utils._units_helpers``. - (:pr:`2734`) -- Added a |Nox| session for building the changelog. (:pr:`2744`) -- Added an experimental |Nox| session for adding |type hint annotations| using - `MonkeyType `__. - This session creates a database of variable types from running pytest, and - then applies the observed types to a particular module. (:pr:`2747`) -- Updated |Nox| sessions, including docstrings and troubleshooting messages. - (:pr:`2750`) -- Enabled tests to pass with ``numpy == 2.0.0``. (:pr:`2772`) +- Dropped support for Python 3.10 and bumped the minimum required + versions of several dependencies following |SPEC 0|. (:pr:`2880`) +- Updated the release checklist following the ``v2024.10.0`` release. + (:pr:`2886`) +- Used `typing.Self` for type hint annotations for |Particle| and + |CustomParticle|. (:pr:`2887`) +- Modified tests for `~plasmapy.diagnostics.thomson.spectral_density` to cover + the case of multiple electron species. (:pr:`2906`) +- The internal structure of + `~plasmapy.simulation.particle_tracker.particle_tracker.ParticleTracker` was + optimized by caching some variables (e.g., ``tracked_particle_mask``) which + are then reset after every + push cycle by a ``_reset_cache`` method. Instead of adding zero arrays for + missing quantities, only + quantities provided on the grid are interpolated, and other required + quantities are filled in with an + array of zeros automatically. Particle stopping can now be enabled on a + subset of the provided grids. + Adaptive time steps do not include magnetic field candidates if a magnetic + field does not exist on the grid. + The adaptive timestep is now set to that of the highest resolution grid for + particles that are not + currently on any grid. (:pr:`2911`) +- Added ``User-Agent`` to the header of + `~plasmapy.utils.data.downloader.Downloader` to + resolve an issue with GitHub blocking API access. (:pr:`2915`) +- Updated :file:`validators.py`. (:pr:`2919`) +- Began using :file:`uv.lock` to pin the versions of dependencies used + in tests and documentation builds. Previously, pinned requirements had + been stored in :file:`requirements.txt` style files in + :file:`ci_requirements/` that were generated with ``uv pip compile`` + for each operating system, Python version, and dependency set. Using + :file:`uv.lock` lets us store requirements information for + different operating systems, Python versions, and dependency sets in + a single file. (:pr:`2937`) +- Switched from using ``actions/setup-python`` to ``astral-sh/setup-uv`` in + GitHub workflows. (:pr:`2959`) +- Enabled :file:`noxfile.py` to be run as a script. + The commands ``python noxfile.py -s 'tests-3.13(all)'`` and ``nox -s + 'tests-3.13(all)'`` can now both be used to run all tests for Python 3.13. + (:pr:`2961`) +- Updated the ``requirements`` session for Nox so that the GitHub workflow + now includes a table of the old and new versions of dependencies in the + body of the pull request. (:pr:`2964`) +- Enabled ``pyproject-fmt`` as an autoformatter and ``validate-pyproject`` as a + validator for :file:`pyproject.toml` via |pre-commit|. (:pr:`2974`) +- Added a |Nox| session to perform security audits of GitHub workflows with + ``zizmor`` in CI. (:pr:`2975`) +- Enabled a |pre-commit| hook for ``mdformat`` to automatically format + GitHub-flavored Markdown files. (:pr:`2981`) +- Added a security policy at :file:`.github/SECURITY.md` and enabled private + security reporting through GitHub. (:pr:`2985`) +- Reorganized :file:`.gitignore` to put content that is custom or + PlasmaPy-specific + at the top of the file, followed by content adapted from :file:`.gitignore` + templates at the bottom. (:pr:`2997`) +- Set |uv| as the sole backend to Nox, and changed the ``docs`` and ``tests`` + dependency sets to include ``nox[uv]`` instead of ``nox``. (:pr:`2998`) +- Refactored tests for the `~plasmapy.diagnostics.charged_particle_radiography` + module to reduce test runtime. (:pr:`3039`) +- Removed upper limits on the allowed versions of Astropy and xarray. + (:pr:`3065`) +- Parametrized tests within :file:`tests/utils/decorators.test_checks.py`. + (:pr:`3065`) +- Updated :file:`tests/utils/decorators/test_checks.py` for compatibility with + updates to how `astropy.units.Equivalency` handles equality comparisons. + (:pr:`3065`) Additional Changes ------------------ -- Refactored - `~plasmapy.diagnostics.charged_particle_radiography.synthetic_radiography.Tracker` - to use |ParticleTracker|. (:pr:`2704`) -- Included :file:`src/plasmapy/_version.py` in :file:`MANIFEST.in`. This file - is automatically generated using ``setuptools_scm``, but is necessary for the - version to be correct in the titles of pages in development documentation - builds. (:pr:`2756`) -- Updated the comment that gets posted to new pull requests via a GitHub - workflow. (:pr:`2765`) +- The ``ax#``, ``dx#`` and ``*_si`` properties of + `~plasmapy.plasma.grids.AbstractGrid` are now + cached properties for faster access, since these attributes do not change + after the grid has been initialized. (:pr:`2911`) +- Updated the configuration to automatically label pull requests on GitHub. + (:pr:`2984`) diff --git a/CITATION.cff b/CITATION.cff index c224fa19f8..08ccfb6491 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -1,10 +1,10 @@ title: PlasmaPy type: software -version: 2024.10.0 +version: 2025.8.0 identifiers: - type: doi - value: 10.5281/zenodo.14010450 -date-released: '2024-10-30' + value: 10.5281/zenodo.16747747 +date-released: '2025-08-07' message: >- Please cite the specific version of PlasmaPy used during a research project. diff --git a/changelog/1643.doc.1.rst b/changelog/1643.doc.1.rst deleted file mode 100644 index b845c4a749..0000000000 --- a/changelog/1643.doc.1.rst +++ /dev/null @@ -1,2 +0,0 @@ -Removed :file:`docs/plasmapy_sphinx` and put `plasmapy_sphinx` into its own -repository at https://github.com/PlasmaPy/plasmapy_sphinx\ . diff --git a/changelog/1643.doc.2.rst b/changelog/1643.doc.2.rst deleted file mode 100644 index e747f50a9e..0000000000 --- a/changelog/1643.doc.2.rst +++ /dev/null @@ -1 +0,0 @@ -Added `plasmapy_sphinx` as a ``docs`` dependency. diff --git a/changelog/1643.doc.3.rst b/changelog/1643.doc.3.rst deleted file mode 100644 index 30faabde0b..0000000000 --- a/changelog/1643.doc.3.rst +++ /dev/null @@ -1,2 +0,0 @@ -Removed upper dependency limit on `sphinx`, and added lower limit of -``>=8.2.3``. diff --git a/changelog/1643.doc.4.rst b/changelog/1643.doc.4.rst deleted file mode 100644 index 2da2208275..0000000000 --- a/changelog/1643.doc.4.rst +++ /dev/null @@ -1,2 +0,0 @@ -Incorporated the ``plasmapy_theme`` via the `plasmapy_sphinx.theme` -extension. diff --git a/changelog/1643.doc.5.rst b/changelog/1643.doc.5.rst deleted file mode 100644 index b9e1f29de8..0000000000 --- a/changelog/1643.doc.5.rst +++ /dev/null @@ -1,2 +0,0 @@ -Incorporated `sphinx` extensions `plasmapy_sphinx.ext.autodoc` and -`plasmapy_sphinx.ext.directives`. diff --git a/changelog/1643.doc.6.rst b/changelog/1643.doc.6.rst deleted file mode 100644 index 430039de79..0000000000 --- a/changelog/1643.doc.6.rst +++ /dev/null @@ -1,3 +0,0 @@ -Created a GitHub workflow (in :file:`weekly.yml` and :file:`noxfile.py`) -to build documentation using the latest development version of -`plasmapy_sphinx` on a weekly basis. diff --git a/changelog/2790.feature.rst b/changelog/2790.feature.rst deleted file mode 100644 index 467dc308e2..0000000000 --- a/changelog/2790.feature.rst +++ /dev/null @@ -1,2 +0,0 @@ -Enabled |particle_input| to convert |particle-list-like| arguments passed -to parameters decorated with |ParticleListLike| into |ParticleList| instances. diff --git a/changelog/2880.internal.rst b/changelog/2880.internal.rst deleted file mode 100644 index 025073363d..0000000000 --- a/changelog/2880.internal.rst +++ /dev/null @@ -1,2 +0,0 @@ -Dropped support for Python 3.10 and bumped the minimum required -versions of several dependencies following |SPEC 0|. diff --git a/changelog/2886.internal.rst b/changelog/2886.internal.rst deleted file mode 100644 index 4b48c9b1c7..0000000000 --- a/changelog/2886.internal.rst +++ /dev/null @@ -1 +0,0 @@ -Updated the release checklist following the ``v2024.10.0`` release. diff --git a/changelog/2887.internal.rst b/changelog/2887.internal.rst deleted file mode 100644 index e21d9ae539..0000000000 --- a/changelog/2887.internal.rst +++ /dev/null @@ -1 +0,0 @@ -Used `typing.Self` for type hint annotations for |Particle| and |CustomParticle|. diff --git a/changelog/2890.doc.rst b/changelog/2890.doc.rst deleted file mode 100644 index 0581b02b9c..0000000000 --- a/changelog/2890.doc.rst +++ /dev/null @@ -1 +0,0 @@ -Updated author metadata in :file:`CITATION.cff`. diff --git a/changelog/2892.doc.rst b/changelog/2892.doc.rst deleted file mode 100644 index 9d94509771..0000000000 --- a/changelog/2892.doc.rst +++ /dev/null @@ -1 +0,0 @@ -Removed duplicate section headers for example notebooks in the documentation for `plasmapy.formulary`. diff --git a/changelog/2895.doc.rst b/changelog/2895.doc.rst deleted file mode 100644 index c67705c12b..0000000000 --- a/changelog/2895.doc.rst +++ /dev/null @@ -1 +0,0 @@ -Added acknowledgements to several organizations that have supported PlasmaPy or are aligned with its mission. diff --git a/changelog/2897.removal.rst b/changelog/2897.removal.rst deleted file mode 100644 index ccf3072b59..0000000000 --- a/changelog/2897.removal.rst +++ /dev/null @@ -1 +0,0 @@ -Removed :file:`src/plasmapy/dispersion/dispersionfunction.py`, which was deprecated in ``v2023.10.0``. The functionality for the plasma dispersion function is in `plasmapy.dispersion.dispersion_functions`. diff --git a/changelog/2901.doc.rst b/changelog/2901.doc.rst deleted file mode 100644 index 1a1e8374d6..0000000000 --- a/changelog/2901.doc.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed formatting problems and improved verb tense consistency in prior changelog entries. diff --git a/changelog/2906.internal.rst b/changelog/2906.internal.rst deleted file mode 100644 index fabe66c508..0000000000 --- a/changelog/2906.internal.rst +++ /dev/null @@ -1 +0,0 @@ -Modified tests for `~plasmapy.diagnostics.thomson.spectral_density` to cover the case of multiple electron species. diff --git a/changelog/2911.breaking.1.rst b/changelog/2911.breaking.1.rst deleted file mode 100644 index f433c7577a..0000000000 --- a/changelog/2911.breaking.1.rst +++ /dev/null @@ -1,3 +0,0 @@ -|ParticleTracker| no longer accepts the parameter ``req_quantities``, but instead automatically requires -quantities required by the tracker for the given setup. Users wishing to require quantities -may use the method `~plasmapy.plasma.grids.AbstractGrid.require_quantities`. diff --git a/changelog/2911.breaking.2.rst b/changelog/2911.breaking.2.rst deleted file mode 100644 index ac1f1b8116..0000000000 --- a/changelog/2911.breaking.2.rst +++ /dev/null @@ -1,4 +0,0 @@ -The method `~plasmapy.simulation.particle_tracker.particle_tracker.ParticleTracker.add_stopping` -requires that the argument ``I`` must now be a list of |Quantity| objects rather than a single -|Quantity| array. This change is needed because `None` entries are now also accepted to that -keyword as placeholders for grids on which stopping will not be applied. diff --git a/changelog/2911.breaking.3.rst b/changelog/2911.breaking.3.rst deleted file mode 100644 index c80e8b2128..0000000000 --- a/changelog/2911.breaking.3.rst +++ /dev/null @@ -1,4 +0,0 @@ -Variables in |ParticleTracker| -and `~plasmapy.diagnostics.charged_particle_radiography.synthetic_radiography.Tracker` have been updated -such that ``n*`` is now ``num_*`` (e.g., ``nparticles`` is now ``num_particles``). Similarly, ``v_init`` is -now ``v0`` to be consistent with ``x0``. diff --git a/changelog/2911.feature.rst b/changelog/2911.feature.rst deleted file mode 100644 index 7b4b46cfd5..0000000000 --- a/changelog/2911.feature.rst +++ /dev/null @@ -1,3 +0,0 @@ -The new method `~plasmapy.plasma.grids.CartesianGrid.soften_edges` applies an error function mask -to the edges of all quantities on a grid. This is useful for any application where the grid must -go to zero smoothly at the edges (e.g., for particle tracking with |ParticleTracker|). diff --git a/changelog/2911.internal.1.rst b/changelog/2911.internal.1.rst deleted file mode 100644 index f414a34e26..0000000000 --- a/changelog/2911.internal.1.rst +++ /dev/null @@ -1,8 +0,0 @@ -The internal structure of `~plasmapy.simulation.particle_tracker.particle_tracker.ParticleTracker` was -optimized by caching some variables (e.g., ``tracked_particle_mask``) which are then reset after every -push cycle by a ``_reset_cache`` method. Instead of adding zero arrays for missing quantities, only -quantities provided on the grid are interpolated, and other required quantities are filled in with an -array of zeros automatically. Particle stopping can now be enabled on a subset of the provided grids. -Adaptive time steps do not include magnetic field candidates if a magnetic field does not exist on the grid. -The adaptive timestep is now set to that of the highest resolution grid for particles that are not -currently on any grid. diff --git a/changelog/2911.trivial.1.rst b/changelog/2911.trivial.1.rst deleted file mode 100644 index 7cf79aff95..0000000000 --- a/changelog/2911.trivial.1.rst +++ /dev/null @@ -1,2 +0,0 @@ -The ``ax#``, ``dx#`` and ``*_si`` properties of `~plasmapy.plasma.grids.AbstractGrid` are now -cached properties for faster access, since these attributes do not change after the grid has been initialized. diff --git a/changelog/2915.doc.rst b/changelog/2915.doc.rst deleted file mode 100644 index 39d91c6220..0000000000 --- a/changelog/2915.doc.rst +++ /dev/null @@ -1,4 +0,0 @@ -Fixed references to the ``astropy.units.equivalencies`` module in the docs. Astropy now considers -this file to be private API (which broke PlasmaPy's intersphinx links), and -recommends that its contents be imported through the `astropy.units` namespace. -This pull request changes those links to a direct URL to |Astropy Equivalencies|. diff --git a/changelog/2915.internal.rst b/changelog/2915.internal.rst deleted file mode 100644 index 6192cfbdbf..0000000000 --- a/changelog/2915.internal.rst +++ /dev/null @@ -1,2 +0,0 @@ -Added ``User-Agent`` to the header of `~plasmapy.utils.data.downloader.Downloader` to -resolve an issue with GitHub blocking API access. diff --git a/changelog/2919.internal.rst b/changelog/2919.internal.rst deleted file mode 100644 index 86b984e03e..0000000000 --- a/changelog/2919.internal.rst +++ /dev/null @@ -1 +0,0 @@ -Updated :file:`validators.py`. diff --git a/changelog/2932.doc.rst b/changelog/2932.doc.rst deleted file mode 100644 index f71c94fbfe..0000000000 --- a/changelog/2932.doc.rst +++ /dev/null @@ -1 +0,0 @@ -Added a sentence to the documentation for `plasmapy.dispersion` to describe dispersion relations and their usefulness. diff --git a/changelog/2935.doc.rst b/changelog/2935.doc.rst deleted file mode 100644 index f92d54631f..0000000000 --- a/changelog/2935.doc.rst +++ /dev/null @@ -1 +0,0 @@ -Updated the instructions for accessing test results and documentation previews in the |contributor guide| after recent changes to GitHub's user interface. diff --git a/changelog/2937.internal.rst b/changelog/2937.internal.rst deleted file mode 100644 index 9c97b63952..0000000000 --- a/changelog/2937.internal.rst +++ /dev/null @@ -1,8 +0,0 @@ -Began using :file:`uv.lock` to pin the versions of dependencies used -in tests and documentation builds. Previously, pinned requirements had -been stored in :file:`requirements.txt` style files in -:file:`ci_requirements/` that were generated with ``uv pip compile`` -for each operating system, Python version, and dependency set. Using -:file:`uv.lock` lets us store requirements information for -different operating systems, Python versions, and dependency sets in -a single file. diff --git a/changelog/2938.doc.rst b/changelog/2938.doc.rst deleted file mode 100644 index 7fa5027e1d..0000000000 --- a/changelog/2938.doc.rst +++ /dev/null @@ -1 +0,0 @@ -Expanded the docstring of `~plasmapy.formulary.dimensionless.Hall_parameter`. diff --git a/changelog/2943.doc.rst b/changelog/2943.doc.rst deleted file mode 100644 index 36ce0e6835..0000000000 --- a/changelog/2943.doc.rst +++ /dev/null @@ -1 +0,0 @@ -Bumped the Python version for documentation builds from 3.12 to 3.13. diff --git a/changelog/2959.internal.rst b/changelog/2959.internal.rst deleted file mode 100644 index 25d77f62a1..0000000000 --- a/changelog/2959.internal.rst +++ /dev/null @@ -1 +0,0 @@ -Switched from using ``actions/setup-python`` to ``astral-sh/setup-uv`` in GitHub workflows. diff --git a/changelog/2961.internal.rst b/changelog/2961.internal.rst deleted file mode 100644 index b616afeca8..0000000000 --- a/changelog/2961.internal.rst +++ /dev/null @@ -1,2 +0,0 @@ -Enabled :file:`noxfile.py` to be run as a script. -The commands ``python noxfile.py -s 'tests-3.13(all)'`` and ``nox -s 'tests-3.13(all)'`` can now both be used to run all tests for Python 3.13. diff --git a/changelog/2964.internal.rst b/changelog/2964.internal.rst deleted file mode 100644 index 52002f8f94..0000000000 --- a/changelog/2964.internal.rst +++ /dev/null @@ -1,3 +0,0 @@ -Updated the ``requirements`` session for Nox so that the GitHub workflow -now includes a table of the old and new versions of dependencies in the -body of the pull request. diff --git a/changelog/2968.feature.1.rst b/changelog/2968.feature.1.rst deleted file mode 100644 index 91cb360471..0000000000 --- a/changelog/2968.feature.1.rst +++ /dev/null @@ -1,2 +0,0 @@ -Added the ``detector_vdir`` keyword to `~plasmapy.diagnostics.charged_particle_radiography.synthetic_radiography.Tracker` -to explicitly define the detector's vertical surface vector. diff --git a/changelog/2968.feature.2.rst b/changelog/2968.feature.2.rst deleted file mode 100644 index 48a243cbd5..0000000000 --- a/changelog/2968.feature.2.rst +++ /dev/null @@ -1,3 +0,0 @@ -Added the ``source_vdir`` keyword to the `~plasmapy.diagnostics.charged_particle_radiography.synthetic_radiography.Tracker.create_particles` -method of `~plasmapy.diagnostics.charged_particle_radiography.synthetic_radiography.Tracker` to explicitly define the -orientation of the mean velocity of the source particles. diff --git a/changelog/2974.internal.rst b/changelog/2974.internal.rst deleted file mode 100644 index ed3a1ad769..0000000000 --- a/changelog/2974.internal.rst +++ /dev/null @@ -1 +0,0 @@ -Enabled ``pyproject-fmt`` as an autoformatter and ``validate-pyproject`` as a validator for :file:`pyproject.toml` via |pre-commit|. diff --git a/changelog/2975.internal.rst b/changelog/2975.internal.rst deleted file mode 100644 index 813a11881b..0000000000 --- a/changelog/2975.internal.rst +++ /dev/null @@ -1 +0,0 @@ -Added a |Nox| session to perform security audits of GitHub workflows with ``zizmor`` in CI. diff --git a/changelog/2981.internal.rst b/changelog/2981.internal.rst deleted file mode 100644 index 34fd0496d7..0000000000 --- a/changelog/2981.internal.rst +++ /dev/null @@ -1 +0,0 @@ -Enabled a |pre-commit| hook for ``mdformat`` to automatically format GitHub-flavored Markdown files. diff --git a/changelog/2984.trivial.rst b/changelog/2984.trivial.rst deleted file mode 100644 index 412642b25a..0000000000 --- a/changelog/2984.trivial.rst +++ /dev/null @@ -1 +0,0 @@ -Updated the configuration to automatically label pull requests on GitHub. diff --git a/changelog/2985.internal.rst b/changelog/2985.internal.rst deleted file mode 100644 index 6f020ed08a..0000000000 --- a/changelog/2985.internal.rst +++ /dev/null @@ -1 +0,0 @@ -Added a security policy at :file:`.github/SECURITY.md` and enabled private security reporting through GitHub. diff --git a/changelog/2997.internal.rst b/changelog/2997.internal.rst deleted file mode 100644 index b34f7f8d3d..0000000000 --- a/changelog/2997.internal.rst +++ /dev/null @@ -1,3 +0,0 @@ -Reorganized :file:`.gitignore` to put content that is custom or PlasmaPy-specific -at the top of the file, followed by content adapted from :file:`.gitignore` -templates at the bottom. diff --git a/changelog/2998.internal.rst b/changelog/2998.internal.rst deleted file mode 100644 index 7bc0e273ef..0000000000 --- a/changelog/2998.internal.rst +++ /dev/null @@ -1 +0,0 @@ -Set |uv| as the sole backend to Nox, and changed the ``docs`` and ``tests`` dependency sets to include ``nox[uv]`` instead of ``nox``. diff --git a/changelog/2999.doc.rst b/changelog/2999.doc.rst deleted file mode 100644 index 7ed5175d5d..0000000000 --- a/changelog/2999.doc.rst +++ /dev/null @@ -1 +0,0 @@ -Updated the instructions on how to install PlasmaPy. diff --git a/changelog/3013.doc.rst b/changelog/3013.doc.rst deleted file mode 100644 index 7becef25b8..0000000000 --- a/changelog/3013.doc.rst +++ /dev/null @@ -1 +0,0 @@ -Put office hours an an indefinite hiatus due to the conclusion of the NSF collaborative awards supporting the development and growth of PlasmaPy. diff --git a/changelog/3021.feature.rst b/changelog/3021.feature.rst deleted file mode 100644 index 419c0ee6fb..0000000000 --- a/changelog/3021.feature.rst +++ /dev/null @@ -1 +0,0 @@ -Added a new module, `plasmapy.formulary.laser`, to make calculations related to laser pulses. Added the first function, `~plasmapy.formulary.laser.electric_field_amplitude`, which calculates the electric field strength from intensity. diff --git a/changelog/3024.doc.rst b/changelog/3024.doc.rst deleted file mode 100644 index de76d23c0e..0000000000 --- a/changelog/3024.doc.rst +++ /dev/null @@ -1 +0,0 @@ -Removed the `sphinx-hoverxref `_ |Sphinx| extension, since it has been deprecated in favor of the |Read the Docs| add-on for `Link Previews `_\ . diff --git a/changelog/3032.feature.rst b/changelog/3032.feature.rst deleted file mode 100644 index e28ded4fc3..0000000000 --- a/changelog/3032.feature.rst +++ /dev/null @@ -1 +0,0 @@ -Added `plasmapy.formulary.laser.intensity` to calculate intensity from the electric field amplitude for a laser. diff --git a/changelog/3034.feature.rst b/changelog/3034.feature.rst deleted file mode 100644 index e17bd187ff..0000000000 --- a/changelog/3034.feature.rst +++ /dev/null @@ -1,2 +0,0 @@ -Added helper function `~plasmapy.analysis.swept_langmuir.helpers.sort_sweep_arrays` to -`plasmapy.analysis.swept_langmuir`. diff --git a/changelog/3036.feature.rst b/changelog/3036.feature.rst deleted file mode 100644 index 34c510a353..0000000000 --- a/changelog/3036.feature.rst +++ /dev/null @@ -1 +0,0 @@ -Added `~plasmapy.formulary.laser.em_wavelength`, `~plasmapy.formulary.laser.em_angular_frequency`, `~plasmapy.formulary.laser.Gaussian_beam_waist_radius`, `~plasmapy.formulary.laser.Gaussian_spot_size_FWHM`, `~plasmapy.formulary.laser.Gaussian_power`, `~plasmapy.formulary.laser.Gaussian_Rayleigh_length`, and `~plasmapy.formulary.laser.normalized_vector_potential` to `plasmapy.formulary.laser`. diff --git a/changelog/3037.feature.rst b/changelog/3037.feature.rst deleted file mode 100644 index 7efbc5fafa..0000000000 --- a/changelog/3037.feature.rst +++ /dev/null @@ -1 +0,0 @@ -Added helper function `~plasmapy.analysis.swept_langmuir.helpers.merge_voltage_clusters` to `plasmapy.analysis.swept_langmuir`. diff --git a/changelog/3039.internal.rst b/changelog/3039.internal.rst deleted file mode 100644 index 5c777113e7..0000000000 --- a/changelog/3039.internal.rst +++ /dev/null @@ -1 +0,0 @@ -Refactored tests for the `~plasmapy.diagnostics.charged_particle_radiography` module to reduce test runtime. diff --git a/changelog/3045.bugfix.rst b/changelog/3045.bugfix.rst deleted file mode 100644 index ad511cf299..0000000000 --- a/changelog/3045.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Enabled |Particle| to accept a `numpy.integer` object as the first argument to indicate the atomic number. diff --git a/changelog/3056.doc.rst b/changelog/3056.doc.rst deleted file mode 100644 index ba3c9eab98..0000000000 --- a/changelog/3056.doc.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed broken hyperlinks and permanent redirects. diff --git a/changelog/3059.doc.rst b/changelog/3059.doc.rst deleted file mode 100644 index cea1bae984..0000000000 --- a/changelog/3059.doc.rst +++ /dev/null @@ -1 +0,0 @@ -Summarized the dependency support policy from |SPEC 0| at the end of the installation instructions. diff --git a/changelog/3060.breaking.rst b/changelog/3060.breaking.rst deleted file mode 100644 index f916a9523c..0000000000 --- a/changelog/3060.breaking.rst +++ /dev/null @@ -1,2 +0,0 @@ -Removed the prototype plasma calculator from PlasmaPy so that it can be -included in the |plasmapy-calculator| standalone package. diff --git a/changelog/3065.bugfix.rst b/changelog/3065.bugfix.rst deleted file mode 100644 index 0ae4911d17..0000000000 --- a/changelog/3065.bugfix.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fixed a possible bug when using `plasmapy.plasma.grids.AbstractGrid.add_quantities` -alongside newer versions of |xarray|. diff --git a/changelog/3065.internal.1.rst b/changelog/3065.internal.1.rst deleted file mode 100644 index fd0e6c3c07..0000000000 --- a/changelog/3065.internal.1.rst +++ /dev/null @@ -1 +0,0 @@ -Removed upper limits on the allowed versions of Astropy and xarray. diff --git a/changelog/3065.internal.2.rst b/changelog/3065.internal.2.rst deleted file mode 100644 index cbd4f2a6e3..0000000000 --- a/changelog/3065.internal.2.rst +++ /dev/null @@ -1,2 +0,0 @@ -Updated :file:`tests/utils/decorators/test_checks.py` for compatibility with -updates to how `astropy.units.Equivalency` handles equality comparisons. diff --git a/changelog/3065.internal.3.rst b/changelog/3065.internal.3.rst deleted file mode 100644 index b7ba187190..0000000000 --- a/changelog/3065.internal.3.rst +++ /dev/null @@ -1 +0,0 @@ -Parametrized tests within :file:`tests/utils/decorators.test_checks.py`. diff --git a/changelog/3068.doc.rst b/changelog/3068.doc.rst deleted file mode 100644 index 70608c4066..0000000000 --- a/changelog/3068.doc.rst +++ /dev/null @@ -1,2 +0,0 @@ -Updated the |contributor guide| pages on the |code contribution workflow| -and :ref:`using pre-commit `. diff --git a/changelog/3069.doc.rst b/changelog/3069.doc.rst deleted file mode 100644 index e08f29a51f..0000000000 --- a/changelog/3069.doc.rst +++ /dev/null @@ -1,2 +0,0 @@ -Upgraded :ref:`PlasmaPy's Code of Conduct ` to -version 3.0 of the Contributor Covenant. diff --git a/changelog/3070.doc.rst b/changelog/3070.doc.rst deleted file mode 100644 index 4a0704d831..0000000000 --- a/changelog/3070.doc.rst +++ /dev/null @@ -1 +0,0 @@ -Updated the :ref:`Feedback and Communication ` page. diff --git a/changelog/3073.doc.rst b/changelog/3073.doc.rst deleted file mode 100644 index f590c41e8c..0000000000 --- a/changelog/3073.doc.rst +++ /dev/null @@ -1,3 +0,0 @@ -Limited the allowed version of |Sphinx| to ``sphinx>=8.2.3,<8.3`` -because planned breaking changes to Sphinx are causing documentation -build errors due to incompatibilities with some extensions. diff --git a/docs/about/citation.rst b/docs/about/citation.rst index 95ae9aa27f..cdb43730a6 100644 --- a/docs/about/citation.rst +++ b/docs/about/citation.rst @@ -3,9 +3,9 @@ Acknowledging and Citing PlasmaPy ================================= -.. |version_to_cite| replace:: 2024.10.0 -.. |doi_hyperlink| replace:: https://doi.org/10.5281/zenodo.14010450 -.. |citation_year| replace:: 2024 +.. |version_to_cite| replace:: 2025.8.0 +.. |doi_hyperlink| replace:: https://doi.org/10.5281/zenodo.16747747 +.. |citation_year| replace:: 2025 .. These substitutions are automatically updated by the GitHub Action to mint a release. diff --git a/docs/changelog/2025.8.0.rst b/docs/changelog/2025.8.0.rst new file mode 100644 index 0000000000..eb1f81f35b --- /dev/null +++ b/docs/changelog/2025.8.0.rst @@ -0,0 +1,232 @@ +PlasmaPy v2025.8.0 (2025-08-07) +=============================== + +New Features +------------ + +- Enabled |particle_input| to convert |particle-list-like| arguments passed + to parameters decorated with |ParticleListLike| into |ParticleList| + instances. (:pr:`2790`) +- The new method `plasmapy.plasma.grids.CartesianGrid.soften_edges` applies an + error function mask + to the edges of all quantities on a grid. This is useful for any application + where the grid must + go to zero smoothly at the edges (e.g., for particle tracking with + |ParticleTracker|). (:pr:`2911`) +- Added the ``source_vdir`` keyword to the + `~plasmapy.diagnostics.charged_particle_radiography.synthetic_radiography.Tracker.create_particles` + method of + `~plasmapy.diagnostics.charged_particle_radiography.synthetic_radiography.Tracker` + to explicitly define the + orientation of the mean velocity of the source particles. (:pr:`2968`) +- Added the ``detector_vdir`` keyword to + `~plasmapy.diagnostics.charged_particle_radiography.synthetic_radiography.Tracker` + to explicitly define the detector's vertical surface vector. (:pr:`2968`) +- Added a new module, `plasmapy.formulary.laser`, to make calculations related + to laser pulses. Added the first function, + `~plasmapy.formulary.laser.electric_field_amplitude`, which calculates the + electric field strength from intensity. (:pr:`3021`) +- Added `plasmapy.formulary.laser.intensity` to calculate intensity from the + electric field amplitude for a laser. (:pr:`3032`) +- Added helper function + `~plasmapy.analysis.swept_langmuir.helpers.sort_sweep_arrays` to + `plasmapy.analysis.swept_langmuir`. (:pr:`3034`) +- Added `~plasmapy.formulary.laser.em_wavelength`, + `~plasmapy.formulary.laser.em_angular_frequency`, + `~plasmapy.formulary.laser.Gaussian_beam_waist_radius`, + `~plasmapy.formulary.laser.Gaussian_spot_size_FWHM`, + `~plasmapy.formulary.laser.Gaussian_power`, + `~plasmapy.formulary.laser.Gaussian_Rayleigh_length`, and + `~plasmapy.formulary.laser.normalized_vector_potential` to + `plasmapy.formulary.laser`. (:pr:`3036`) +- Added helper function + `~plasmapy.analysis.swept_langmuir.helpers.merge_voltage_clusters` to + `plasmapy.analysis.swept_langmuir`. (:pr:`3037`) + + +Documentation Improvements +-------------------------- + +- Incorporated the ``plasmapy_theme`` via the `plasmapy_sphinx.theme` + extension. (:pr:`1643`) +- Removed :file:`docs/plasmapy_sphinx` and put `plasmapy_sphinx` into its own + repository at https://github.com/PlasmaPy/plasmapy_sphinx\ . (:pr:`1643`) +- Added `plasmapy_sphinx` as a ``docs`` dependency. (:pr:`1643`) +- Removed upper dependency limit on `sphinx`, and added lower limit of + ``>=8.2.3``. (:pr:`1643`) +- Created a GitHub workflow (in :file:`weekly.yml` and :file:`noxfile.py`) + to build documentation using the latest development version of + `plasmapy_sphinx` on a weekly basis. (:pr:`1643`) +- Incorporated `sphinx` extensions `plasmapy_sphinx.ext.autodoc` and + `plasmapy_sphinx.ext.directives`. (:pr:`1643`) +- Updated author metadata in :file:`CITATION.cff`. (:pr:`2890`) +- Removed duplicate section headers for example notebooks in the documentation + for `plasmapy.formulary`. (:pr:`2892`) +- Added acknowledgements to several organizations that have supported PlasmaPy + or are aligned with its mission. (:pr:`2895`) +- Fixed formatting problems and improved verb tense consistency in prior + changelog entries. (:pr:`2901`) +- Fixed references to the ``astropy.units.equivalencies`` module in the docs. + Astropy now considers + this file to be private API (which broke PlasmaPy's intersphinx links), and + recommends that its contents be imported through the `astropy.units` + namespace. + This pull request changes those links to a direct URL to + |Astropy Equivalencies|. (:pr:`2915`) +- Added a sentence to the documentation for `plasmapy.dispersion` to describe + dispersion relations and their usefulness. (:pr:`2932`) +- Updated the instructions for accessing test results and documentation + previews in the |contributor guide| after recent changes to GitHub's user + interface. (:pr:`2935`) +- Expanded the docstring of `~plasmapy.formulary.dimensionless.Hall_parameter`. + (:pr:`2938`) +- Bumped the Python version for documentation builds from 3.12 to 3.13. + (:pr:`2943`) +- Updated the instructions on how to install PlasmaPy. (:pr:`2999`) +- Put office hours on an indefinite hiatus. (:pr:`3013`) +- Removed the `sphinx-hoverxref + `_ |Sphinx| extension, since + it has been deprecated in favor of the |Read the Docs| add-on for `Link + Previews `_\ + . (:pr:`3024`) +- Fixed broken hyperlinks and permanent redirects. (:pr:`3056`) +- Summarized the dependency support policy from |SPEC 0| at the end of the + installation instructions. (:pr:`3059`) +- Updated the |contributor guide| pages on the |code contribution workflow| + and :ref:`using pre-commit `. (:pr:`3068`) +- Upgraded :ref:`PlasmaPy's Code of Conduct ` to + version 3.0 of the Contributor Covenant. (:pr:`3069`) +- Updated the :ref:`Feedback and Communication ` page. + (:pr:`3070`) +- Limited the allowed version of |Sphinx| to ``sphinx>=8.2.3,<8.3`` + because planned breaking changes to Sphinx are causing documentation + build errors due to incompatibilities with some extensions. (:pr:`3073`) + + +Backwards Incompatible Changes +------------------------------ + +- Variables in |ParticleTracker| + and + `~plasmapy.diagnostics.charged_particle_radiography.synthetic_radiography.Tracker` + have been updated + such that ``n*`` is now ``num_*`` (e.g., ``nparticles`` is now + ``num_particles``). Similarly, ``v_init`` is + now ``v0`` to be consistent with ``x0``. (:pr:`2911`) +- The method + `plasmapy.simulation.particle_tracker.particle_tracker.ParticleTracker.add_stopping` + requires that the argument ``I`` must now be a list of |Quantity| objects + rather than a single + |Quantity| array. This change is needed because `None` entries are now also + accepted to that + keyword as placeholders for grids on which stopping will not be applied. + (:pr:`2911`) +- |ParticleTracker| no longer accepts the parameter ``req_quantities``, but + instead automatically requires + quantities required by the tracker for the given setup. Users wishing to + require quantities + may use the method `~plasmapy.plasma.grids.AbstractGrid.require_quantities`. + (:pr:`2911`) +- Removed the prototype plasma calculator from PlasmaPy so that it can be + included in the |plasmapy-calculator| standalone package. (:pr:`3060`) + + +Deprecations and Planned Removals +--------------------------------- + +- Removed :file:`src/plasmapy/dispersion/dispersionfunction.py`, which was + deprecated in ``v2023.10.0``. The functionality for the plasma dispersion + function is in `plasmapy.dispersion.dispersion_functions`. (:pr:`2897`) + + +Bug Fixes +--------- + +- Enabled |Particle| to accept a `numpy.integer` object as the first argument + to indicate the atomic number. (:pr:`3045`) +- Fixed a possible bug when using + `plasmapy.plasma.grids.AbstractGrid.add_quantities` + alongside newer versions of |xarray|. (:pr:`3065`) + + +Internal Changes and Refactorings +--------------------------------- + +- Dropped support for Python 3.10 and bumped the minimum required + versions of several dependencies following |SPEC 0|. (:pr:`2880`) +- Updated the release checklist following the ``v2024.10.0`` release. + (:pr:`2886`) +- Used `typing.Self` for type hint annotations for |Particle| and + |CustomParticle|. (:pr:`2887`) +- Modified tests for `~plasmapy.diagnostics.thomson.spectral_density` to cover + the case of multiple electron species. (:pr:`2906`) +- The internal structure of + `~plasmapy.simulation.particle_tracker.particle_tracker.ParticleTracker` was + optimized by caching some variables (e.g., ``tracked_particle_mask``) which + are then reset after every + push cycle by a ``_reset_cache`` method. Instead of adding zero arrays for + missing quantities, only + quantities provided on the grid are interpolated, and other required + quantities are filled in with an + array of zeros automatically. Particle stopping can now be enabled on a + subset of the provided grids. + Adaptive time steps do not include magnetic field candidates if a magnetic + field does not exist on the grid. + The adaptive timestep is now set to that of the highest resolution grid for + particles that are not + currently on any grid. (:pr:`2911`) +- Added ``User-Agent`` to the header of + `~plasmapy.utils.data.downloader.Downloader` to + resolve an issue with GitHub blocking API access. (:pr:`2915`) +- Updated :file:`validators.py`. (:pr:`2919`) +- Began using :file:`uv.lock` to pin the versions of dependencies used + in tests and documentation builds. Previously, pinned requirements had + been stored in :file:`requirements.txt` style files in + :file:`ci_requirements/` that were generated with ``uv pip compile`` + for each operating system, Python version, and dependency set. Using + :file:`uv.lock` lets us store requirements information for + different operating systems, Python versions, and dependency sets in + a single file. (:pr:`2937`) +- Switched from using ``actions/setup-python`` to ``astral-sh/setup-uv`` in + GitHub workflows. (:pr:`2959`) +- Enabled :file:`noxfile.py` to be run as a script. + The commands ``python noxfile.py -s 'tests-3.13(all)'`` and ``nox -s + 'tests-3.13(all)'`` can now both be used to run all tests for Python 3.13. + (:pr:`2961`) +- Updated the ``requirements`` session for Nox so that the GitHub workflow + now includes a table of the old and new versions of dependencies in the + body of the pull request. (:pr:`2964`) +- Enabled ``pyproject-fmt`` as an autoformatter and ``validate-pyproject`` as a + validator for :file:`pyproject.toml` via |pre-commit|. (:pr:`2974`) +- Added a |Nox| session to perform security audits of GitHub workflows with + ``zizmor`` in CI. (:pr:`2975`) +- Enabled a |pre-commit| hook for ``mdformat`` to automatically format + GitHub-flavored Markdown files. (:pr:`2981`) +- Added a security policy at :file:`.github/SECURITY.md` and enabled private + security reporting through GitHub. (:pr:`2985`) +- Reorganized :file:`.gitignore` to put content that is custom or + PlasmaPy-specific + at the top of the file, followed by content adapted from :file:`.gitignore` + templates at the bottom. (:pr:`2997`) +- Set |uv| as the sole backend to Nox, and changed the ``docs`` and ``tests`` + dependency sets to include ``nox[uv]`` instead of ``nox``. (:pr:`2998`) +- Refactored tests for the `~plasmapy.diagnostics.charged_particle_radiography` + module to reduce test runtime. (:pr:`3039`) +- Removed upper limits on the allowed versions of Astropy and xarray. + (:pr:`3065`) +- Parametrized tests within :file:`tests/utils/decorators.test_checks.py`. + (:pr:`3065`) +- Updated :file:`tests/utils/decorators/test_checks.py` for compatibility with + updates to how `astropy.units.Equivalency` handles equality comparisons. + (:pr:`3065`) + + +Additional Changes +------------------ + +- The ``ax#``, ``dx#`` and ``*_si`` properties of + `~plasmapy.plasma.grids.AbstractGrid` are now + cached properties for faster access, since these attributes do not change + after the grid has been initialized. (:pr:`2911`) +- Updated the configuration to automatically label pull requests on GitHub. + (:pr:`2984`) diff --git a/uv.lock b/uv.lock index 2824e24bbf..ef756e292b 100644 --- a/uv.lock +++ b/uv.lock @@ -461,23 +461,23 @@ wheels = [ [[package]] name = "debugpy" -version = "1.8.15" +version = "1.8.16" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/8c/8b/3a9a28ddb750a76eaec445c7f4d3147ea2c579a97dbd9e25d39001b92b21/debugpy-1.8.15.tar.gz", hash = "sha256:58d7a20b7773ab5ee6bdfb2e6cf622fdf1e40c9d5aef2857d85391526719ac00", size = 1643279, upload-time = "2025-07-15T16:43:29.135Z" } +sdist = { url = "https://files.pythonhosted.org/packages/ca/d4/722d0bcc7986172ac2ef3c979ad56a1030e3afd44ced136d45f8142b1f4a/debugpy-1.8.16.tar.gz", hash = "sha256:31e69a1feb1cf6b51efbed3f6c9b0ef03bc46ff050679c4be7ea6d2e23540870", size = 1643809, upload-time = "2025-08-06T18:00:02.647Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/d2/b3/1c44a2ed311199ab11c2299c9474a6c7cd80d19278defd333aeb7c287995/debugpy-1.8.15-cp311-cp311-macosx_14_0_universal2.whl", hash = "sha256:babc4fb1962dd6a37e94d611280e3d0d11a1f5e6c72ac9b3d87a08212c4b6dd3", size = 2183442, upload-time = "2025-07-15T16:43:36.733Z" }, - { url = "https://files.pythonhosted.org/packages/f6/69/e2dcb721491e1c294d348681227c9b44fb95218f379aa88e12a19d85528d/debugpy-1.8.15-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f778e68f2986a58479d0ac4f643e0b8c82fdd97c2e200d4d61e7c2d13838eb53", size = 3134215, upload-time = "2025-07-15T16:43:38.116Z" }, - { url = "https://files.pythonhosted.org/packages/17/76/4ce63b95d8294dcf2fd1820860b300a420d077df4e93afcaa25a984c2ca7/debugpy-1.8.15-cp311-cp311-win32.whl", hash = "sha256:f9d1b5abd75cd965e2deabb1a06b0e93a1546f31f9f621d2705e78104377c702", size = 5154037, upload-time = "2025-07-15T16:43:39.471Z" }, - { url = "https://files.pythonhosted.org/packages/c2/a7/e5a7c784465eb9c976d84408873d597dc7ce74a0fc69ed009548a1a94813/debugpy-1.8.15-cp311-cp311-win_amd64.whl", hash = "sha256:62954fb904bec463e2b5a415777f6d1926c97febb08ef1694da0e5d1463c5c3b", size = 5178133, upload-time = "2025-07-15T16:43:40.969Z" }, - { url = "https://files.pythonhosted.org/packages/ab/4a/4508d256e52897f5cdfee6a6d7580974811e911c6d01321df3264508a5ac/debugpy-1.8.15-cp312-cp312-macosx_14_0_universal2.whl", hash = "sha256:3dcc7225cb317469721ab5136cda9ff9c8b6e6fb43e87c9e15d5b108b99d01ba", size = 2511197, upload-time = "2025-07-15T16:43:42.343Z" }, - { url = "https://files.pythonhosted.org/packages/99/8d/7f6ef1097e7fecf26b4ef72338d08e41644a41b7ee958a19f494ffcffc29/debugpy-1.8.15-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:047a493ca93c85ccede1dbbaf4e66816794bdc214213dde41a9a61e42d27f8fc", size = 4229517, upload-time = "2025-07-15T16:43:44.14Z" }, - { url = "https://files.pythonhosted.org/packages/3f/e8/e8c6a9aa33a9c9c6dacbf31747384f6ed2adde4de2e9693c766bdf323aa3/debugpy-1.8.15-cp312-cp312-win32.whl", hash = "sha256:b08e9b0bc260cf324c890626961dad4ffd973f7568fbf57feb3c3a65ab6b6327", size = 5276132, upload-time = "2025-07-15T16:43:45.529Z" }, - { url = "https://files.pythonhosted.org/packages/e9/ad/231050c6177b3476b85fcea01e565dac83607b5233d003ff067e2ee44d8f/debugpy-1.8.15-cp312-cp312-win_amd64.whl", hash = "sha256:e2a4fe357c92334272eb2845fcfcdbec3ef9f22c16cf613c388ac0887aed15fa", size = 5317645, upload-time = "2025-07-15T16:43:46.968Z" }, - { url = "https://files.pythonhosted.org/packages/28/70/2928aad2310726d5920b18ed9f54b9f06df5aa4c10cf9b45fa18ff0ab7e8/debugpy-1.8.15-cp313-cp313-macosx_14_0_universal2.whl", hash = "sha256:f5e01291ad7d6649aed5773256c5bba7a1a556196300232de1474c3c372592bf", size = 2495538, upload-time = "2025-07-15T16:43:48.927Z" }, - { url = "https://files.pythonhosted.org/packages/9e/c6/9b8ffb4ca91fac8b2877eef63c9cc0e87dd2570b1120054c272815ec4cd0/debugpy-1.8.15-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:94dc0f0d00e528d915e0ce1c78e771475b2335b376c49afcc7382ee0b146bab6", size = 4221874, upload-time = "2025-07-15T16:43:50.282Z" }, - { url = "https://files.pythonhosted.org/packages/55/8a/9b8d59674b4bf489318c7c46a1aab58e606e583651438084b7e029bf3c43/debugpy-1.8.15-cp313-cp313-win32.whl", hash = "sha256:fcf0748d4f6e25f89dc5e013d1129ca6f26ad4da405e0723a4f704583896a709", size = 5275949, upload-time = "2025-07-15T16:43:52.079Z" }, - { url = "https://files.pythonhosted.org/packages/72/83/9e58e6fdfa8710a5e6ec06c2401241b9ad48b71c0a7eb99570a1f1edb1d3/debugpy-1.8.15-cp313-cp313-win_amd64.whl", hash = "sha256:73c943776cb83e36baf95e8f7f8da765896fd94b05991e7bc162456d25500683", size = 5317720, upload-time = "2025-07-15T16:43:53.703Z" }, - { url = "https://files.pythonhosted.org/packages/07/d5/98748d9860e767a1248b5e31ffa7ce8cb7006e97bf8abbf3d891d0a8ba4e/debugpy-1.8.15-py2.py3-none-any.whl", hash = "sha256:bce2e6c5ff4f2e00b98d45e7e01a49c7b489ff6df5f12d881c67d2f1ac635f3d", size = 5282697, upload-time = "2025-07-15T16:44:07.996Z" }, + { url = "https://files.pythonhosted.org/packages/63/d6/ad70ba8b49b23fa286fb21081cf732232cc19374af362051da9c7537ae52/debugpy-1.8.16-cp311-cp311-macosx_14_0_universal2.whl", hash = "sha256:67371b28b79a6a12bcc027d94a06158f2fde223e35b5c4e0783b6f9d3b39274a", size = 2184063, upload-time = "2025-08-06T18:00:11.885Z" }, + { url = "https://files.pythonhosted.org/packages/aa/49/7b03e88dea9759a4c7910143f87f92beb494daaae25560184ff4ae883f9e/debugpy-1.8.16-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b2abae6dd02523bec2dee16bd6b0781cccb53fd4995e5c71cc659b5f45581898", size = 3134837, upload-time = "2025-08-06T18:00:13.782Z" }, + { url = "https://files.pythonhosted.org/packages/5d/52/b348930316921de7565fbe37a487d15409041713004f3d74d03eb077dbd4/debugpy-1.8.16-cp311-cp311-win32.whl", hash = "sha256:f8340a3ac2ed4f5da59e064aa92e39edd52729a88fbde7bbaa54e08249a04493", size = 5159142, upload-time = "2025-08-06T18:00:15.391Z" }, + { url = "https://files.pythonhosted.org/packages/d8/ef/9aa9549ce1e10cea696d980292e71672a91ee4a6a691ce5f8629e8f48c49/debugpy-1.8.16-cp311-cp311-win_amd64.whl", hash = "sha256:70f5fcd6d4d0c150a878d2aa37391c52de788c3dc680b97bdb5e529cb80df87a", size = 5183117, upload-time = "2025-08-06T18:00:17.251Z" }, + { url = "https://files.pythonhosted.org/packages/61/fb/0387c0e108d842c902801bc65ccc53e5b91d8c169702a9bbf4f7efcedf0c/debugpy-1.8.16-cp312-cp312-macosx_14_0_universal2.whl", hash = "sha256:b202e2843e32e80b3b584bcebfe0e65e0392920dc70df11b2bfe1afcb7a085e4", size = 2511822, upload-time = "2025-08-06T18:00:18.526Z" }, + { url = "https://files.pythonhosted.org/packages/37/44/19e02745cae22bf96440141f94e15a69a1afaa3a64ddfc38004668fcdebf/debugpy-1.8.16-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:64473c4a306ba11a99fe0bb14622ba4fbd943eb004847d9b69b107bde45aa9ea", size = 4230135, upload-time = "2025-08-06T18:00:19.997Z" }, + { url = "https://files.pythonhosted.org/packages/f3/0b/19b1ba5ee4412f303475a2c7ad5858efb99c90eae5ec627aa6275c439957/debugpy-1.8.16-cp312-cp312-win32.whl", hash = "sha256:833a61ed446426e38b0dd8be3e9d45ae285d424f5bf6cd5b2b559c8f12305508", size = 5281271, upload-time = "2025-08-06T18:00:21.281Z" }, + { url = "https://files.pythonhosted.org/packages/b1/e0/bc62e2dc141de53bd03e2c7cb9d7011de2e65e8bdcdaa26703e4d28656ba/debugpy-1.8.16-cp312-cp312-win_amd64.whl", hash = "sha256:75f204684581e9ef3dc2f67687c3c8c183fde2d6675ab131d94084baf8084121", size = 5323149, upload-time = "2025-08-06T18:00:23.033Z" }, + { url = "https://files.pythonhosted.org/packages/62/66/607ab45cc79e60624df386e233ab64a6d8d39ea02e7f80e19c1d451345bb/debugpy-1.8.16-cp313-cp313-macosx_14_0_universal2.whl", hash = "sha256:85df3adb1de5258dca910ae0bb185e48c98801ec15018a263a92bb06be1c8787", size = 2496157, upload-time = "2025-08-06T18:00:24.361Z" }, + { url = "https://files.pythonhosted.org/packages/4d/a0/c95baae08a75bceabb79868d663a0736655e427ab9c81fb848da29edaeac/debugpy-1.8.16-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bee89e948bc236a5c43c4214ac62d28b29388453f5fd328d739035e205365f0b", size = 4222491, upload-time = "2025-08-06T18:00:25.806Z" }, + { url = "https://files.pythonhosted.org/packages/5b/2f/1c8db6ddd8a257c3cd2c46413b267f1d5fa3df910401c899513ce30392d6/debugpy-1.8.16-cp313-cp313-win32.whl", hash = "sha256:cf358066650439847ec5ff3dae1da98b5461ea5da0173d93d5e10f477c94609a", size = 5281126, upload-time = "2025-08-06T18:00:27.207Z" }, + { url = "https://files.pythonhosted.org/packages/d3/ba/c3e154ab307366d6c5a9c1b68de04914e2ce7fa2f50d578311d8cc5074b2/debugpy-1.8.16-cp313-cp313-win_amd64.whl", hash = "sha256:b5aea1083f6f50023e8509399d7dc6535a351cc9f2e8827d1e093175e4d9fa4c", size = 5323094, upload-time = "2025-08-06T18:00:29.03Z" }, + { url = "https://files.pythonhosted.org/packages/52/57/ecc9ae29fa5b2d90107cd1d9bf8ed19aacb74b2264d986ae9d44fe9bdf87/debugpy-1.8.16-py2.py3-none-any.whl", hash = "sha256:19c9521962475b87da6f673514f7fd610328757ec993bf7ec0d8c96f9a325f9e", size = 5287700, upload-time = "2025-08-06T18:00:42.333Z" }, ] [[package]] @@ -2030,103 +2030,110 @@ wheels = [ [[package]] name = "rpds-py" -version = "0.26.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/a5/aa/4456d84bbb54adc6a916fb10c9b374f78ac840337644e4a5eda229c81275/rpds_py-0.26.0.tar.gz", hash = "sha256:20dae58a859b0906f0685642e591056f1e787f3a8b39c8e8749a45dc7d26bdb0", size = 27385, upload-time = "2025-07-01T15:57:13.958Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/09/4c/4ee8f7e512030ff79fda1df3243c88d70fc874634e2dbe5df13ba4210078/rpds_py-0.26.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:9e8cb77286025bdb21be2941d64ac6ca016130bfdcd228739e8ab137eb4406ed", size = 372610, upload-time = "2025-07-01T15:53:58.844Z" }, - { url = "https://files.pythonhosted.org/packages/fa/9d/3dc16be00f14fc1f03c71b1d67c8df98263ab2710a2fbd65a6193214a527/rpds_py-0.26.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5e09330b21d98adc8ccb2dbb9fc6cb434e8908d4c119aeaa772cb1caab5440a0", size = 358032, upload-time = "2025-07-01T15:53:59.985Z" }, - { url = "https://files.pythonhosted.org/packages/e7/5a/7f1bf8f045da2866324a08ae80af63e64e7bfaf83bd31f865a7b91a58601/rpds_py-0.26.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2c9c1b92b774b2e68d11193dc39620d62fd8ab33f0a3c77ecdabe19c179cdbc1", size = 381525, upload-time = "2025-07-01T15:54:01.162Z" }, - { url = "https://files.pythonhosted.org/packages/45/8a/04479398c755a066ace10e3d158866beb600867cacae194c50ffa783abd0/rpds_py-0.26.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:824e6d3503ab990d7090768e4dfd9e840837bae057f212ff9f4f05ec6d1975e7", size = 397089, upload-time = "2025-07-01T15:54:02.319Z" }, - { url = "https://files.pythonhosted.org/packages/72/88/9203f47268db488a1b6d469d69c12201ede776bb728b9d9f29dbfd7df406/rpds_py-0.26.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8ad7fd2258228bf288f2331f0a6148ad0186b2e3643055ed0db30990e59817a6", size = 514255, upload-time = "2025-07-01T15:54:03.38Z" }, - { url = "https://files.pythonhosted.org/packages/f5/b4/01ce5d1e853ddf81fbbd4311ab1eff0b3cf162d559288d10fd127e2588b5/rpds_py-0.26.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0dc23bbb3e06ec1ea72d515fb572c1fea59695aefbffb106501138762e1e915e", size = 402283, upload-time = "2025-07-01T15:54:04.923Z" }, - { url = "https://files.pythonhosted.org/packages/34/a2/004c99936997bfc644d590a9defd9e9c93f8286568f9c16cdaf3e14429a7/rpds_py-0.26.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d80bf832ac7b1920ee29a426cdca335f96a2b5caa839811803e999b41ba9030d", size = 383881, upload-time = "2025-07-01T15:54:06.482Z" }, - { url = "https://files.pythonhosted.org/packages/05/1b/ef5fba4a8f81ce04c427bfd96223f92f05e6cd72291ce9d7523db3b03a6c/rpds_py-0.26.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0919f38f5542c0a87e7b4afcafab6fd2c15386632d249e9a087498571250abe3", size = 415822, upload-time = "2025-07-01T15:54:07.605Z" }, - { url = "https://files.pythonhosted.org/packages/16/80/5c54195aec456b292f7bd8aa61741c8232964063fd8a75fdde9c1e982328/rpds_py-0.26.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d422b945683e409000c888e384546dbab9009bb92f7c0b456e217988cf316107", size = 558347, upload-time = "2025-07-01T15:54:08.591Z" }, - { url = "https://files.pythonhosted.org/packages/f2/1c/1845c1b1fd6d827187c43afe1841d91678d7241cbdb5420a4c6de180a538/rpds_py-0.26.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:77a7711fa562ba2da1aa757e11024ad6d93bad6ad7ede5afb9af144623e5f76a", size = 587956, upload-time = "2025-07-01T15:54:09.963Z" }, - { url = "https://files.pythonhosted.org/packages/2e/ff/9e979329dd131aa73a438c077252ddabd7df6d1a7ad7b9aacf6261f10faa/rpds_py-0.26.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:238e8c8610cb7c29460e37184f6799547f7e09e6a9bdbdab4e8edb90986a2318", size = 554363, upload-time = "2025-07-01T15:54:11.073Z" }, - { url = "https://files.pythonhosted.org/packages/00/8b/d78cfe034b71ffbe72873a136e71acc7a831a03e37771cfe59f33f6de8a2/rpds_py-0.26.0-cp311-cp311-win32.whl", hash = "sha256:893b022bfbdf26d7bedb083efeea624e8550ca6eb98bf7fea30211ce95b9201a", size = 220123, upload-time = "2025-07-01T15:54:12.382Z" }, - { url = "https://files.pythonhosted.org/packages/94/c1/3c8c94c7dd3905dbfde768381ce98778500a80db9924731d87ddcdb117e9/rpds_py-0.26.0-cp311-cp311-win_amd64.whl", hash = "sha256:87a5531de9f71aceb8af041d72fc4cab4943648d91875ed56d2e629bef6d4c03", size = 231732, upload-time = "2025-07-01T15:54:13.434Z" }, - { url = "https://files.pythonhosted.org/packages/67/93/e936fbed1b734eabf36ccb5d93c6a2e9246fbb13c1da011624b7286fae3e/rpds_py-0.26.0-cp311-cp311-win_arm64.whl", hash = "sha256:de2713f48c1ad57f89ac25b3cb7daed2156d8e822cf0eca9b96a6f990718cc41", size = 221917, upload-time = "2025-07-01T15:54:14.559Z" }, - { url = "https://files.pythonhosted.org/packages/ea/86/90eb87c6f87085868bd077c7a9938006eb1ce19ed4d06944a90d3560fce2/rpds_py-0.26.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:894514d47e012e794f1350f076c427d2347ebf82f9b958d554d12819849a369d", size = 363933, upload-time = "2025-07-01T15:54:15.734Z" }, - { url = "https://files.pythonhosted.org/packages/63/78/4469f24d34636242c924626082b9586f064ada0b5dbb1e9d096ee7a8e0c6/rpds_py-0.26.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:fc921b96fa95a097add244da36a1d9e4f3039160d1d30f1b35837bf108c21136", size = 350447, upload-time = "2025-07-01T15:54:16.922Z" }, - { url = "https://files.pythonhosted.org/packages/ad/91/c448ed45efdfdade82348d5e7995e15612754826ea640afc20915119734f/rpds_py-0.26.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e1157659470aa42a75448b6e943c895be8c70531c43cb78b9ba990778955582", size = 384711, upload-time = "2025-07-01T15:54:18.101Z" }, - { url = "https://files.pythonhosted.org/packages/ec/43/e5c86fef4be7f49828bdd4ecc8931f0287b1152c0bb0163049b3218740e7/rpds_py-0.26.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:521ccf56f45bb3a791182dc6b88ae5f8fa079dd705ee42138c76deb1238e554e", size = 400865, upload-time = "2025-07-01T15:54:19.295Z" }, - { url = "https://files.pythonhosted.org/packages/55/34/e00f726a4d44f22d5c5fe2e5ddd3ac3d7fd3f74a175607781fbdd06fe375/rpds_py-0.26.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9def736773fd56b305c0eef698be5192c77bfa30d55a0e5885f80126c4831a15", size = 517763, upload-time = "2025-07-01T15:54:20.858Z" }, - { url = "https://files.pythonhosted.org/packages/52/1c/52dc20c31b147af724b16104500fba13e60123ea0334beba7b40e33354b4/rpds_py-0.26.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cdad4ea3b4513b475e027be79e5a0ceac8ee1c113a1a11e5edc3c30c29f964d8", size = 406651, upload-time = "2025-07-01T15:54:22.508Z" }, - { url = "https://files.pythonhosted.org/packages/2e/77/87d7bfabfc4e821caa35481a2ff6ae0b73e6a391bb6b343db2c91c2b9844/rpds_py-0.26.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:82b165b07f416bdccf5c84546a484cc8f15137ca38325403864bfdf2b5b72f6a", size = 386079, upload-time = "2025-07-01T15:54:23.987Z" }, - { url = "https://files.pythonhosted.org/packages/e3/d4/7f2200c2d3ee145b65b3cddc4310d51f7da6a26634f3ac87125fd789152a/rpds_py-0.26.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d04cab0a54b9dba4d278fe955a1390da3cf71f57feb78ddc7cb67cbe0bd30323", size = 421379, upload-time = "2025-07-01T15:54:25.073Z" }, - { url = "https://files.pythonhosted.org/packages/ae/13/9fdd428b9c820869924ab62236b8688b122baa22d23efdd1c566938a39ba/rpds_py-0.26.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:79061ba1a11b6a12743a2b0f72a46aa2758613d454aa6ba4f5a265cc48850158", size = 562033, upload-time = "2025-07-01T15:54:26.225Z" }, - { url = "https://files.pythonhosted.org/packages/f3/e1/b69686c3bcbe775abac3a4c1c30a164a2076d28df7926041f6c0eb5e8d28/rpds_py-0.26.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:f405c93675d8d4c5ac87364bb38d06c988e11028a64b52a47158a355079661f3", size = 591639, upload-time = "2025-07-01T15:54:27.424Z" }, - { url = "https://files.pythonhosted.org/packages/5c/c9/1e3d8c8863c84a90197ac577bbc3d796a92502124c27092413426f670990/rpds_py-0.26.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:dafd4c44b74aa4bed4b250f1aed165b8ef5de743bcca3b88fc9619b6087093d2", size = 557105, upload-time = "2025-07-01T15:54:29.93Z" }, - { url = "https://files.pythonhosted.org/packages/9f/c5/90c569649057622959f6dcc40f7b516539608a414dfd54b8d77e3b201ac0/rpds_py-0.26.0-cp312-cp312-win32.whl", hash = "sha256:3da5852aad63fa0c6f836f3359647870e21ea96cf433eb393ffa45263a170d44", size = 223272, upload-time = "2025-07-01T15:54:31.128Z" }, - { url = "https://files.pythonhosted.org/packages/7d/16/19f5d9f2a556cfed454eebe4d354c38d51c20f3db69e7b4ce6cff904905d/rpds_py-0.26.0-cp312-cp312-win_amd64.whl", hash = "sha256:cf47cfdabc2194a669dcf7a8dbba62e37a04c5041d2125fae0233b720da6f05c", size = 234995, upload-time = "2025-07-01T15:54:32.195Z" }, - { url = "https://files.pythonhosted.org/packages/83/f0/7935e40b529c0e752dfaa7880224771b51175fce08b41ab4a92eb2fbdc7f/rpds_py-0.26.0-cp312-cp312-win_arm64.whl", hash = "sha256:20ab1ae4fa534f73647aad289003f1104092890849e0266271351922ed5574f8", size = 223198, upload-time = "2025-07-01T15:54:33.271Z" }, - { url = "https://files.pythonhosted.org/packages/6a/67/bb62d0109493b12b1c6ab00de7a5566aa84c0e44217c2d94bee1bd370da9/rpds_py-0.26.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:696764a5be111b036256c0b18cd29783fab22154690fc698062fc1b0084b511d", size = 363917, upload-time = "2025-07-01T15:54:34.755Z" }, - { url = "https://files.pythonhosted.org/packages/4b/f3/34e6ae1925a5706c0f002a8d2d7f172373b855768149796af87bd65dcdb9/rpds_py-0.26.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1e6c15d2080a63aaed876e228efe4f814bc7889c63b1e112ad46fdc8b368b9e1", size = 350073, upload-time = "2025-07-01T15:54:36.292Z" }, - { url = "https://files.pythonhosted.org/packages/75/83/1953a9d4f4e4de7fd0533733e041c28135f3c21485faaef56a8aadbd96b5/rpds_py-0.26.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:390e3170babf42462739a93321e657444f0862c6d722a291accc46f9d21ed04e", size = 384214, upload-time = "2025-07-01T15:54:37.469Z" }, - { url = "https://files.pythonhosted.org/packages/48/0e/983ed1b792b3322ea1d065e67f4b230f3b96025f5ce3878cc40af09b7533/rpds_py-0.26.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7da84c2c74c0f5bc97d853d9e17bb83e2dcafcff0dc48286916001cc114379a1", size = 400113, upload-time = "2025-07-01T15:54:38.954Z" }, - { url = "https://files.pythonhosted.org/packages/69/7f/36c0925fff6f660a80be259c5b4f5e53a16851f946eb080351d057698528/rpds_py-0.26.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4c5fe114a6dd480a510b6d3661d09d67d1622c4bf20660a474507aaee7eeeee9", size = 515189, upload-time = "2025-07-01T15:54:40.57Z" }, - { url = "https://files.pythonhosted.org/packages/13/45/cbf07fc03ba7a9b54662c9badb58294ecfb24f828b9732970bd1a431ed5c/rpds_py-0.26.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3100b3090269f3a7ea727b06a6080d4eb7439dca4c0e91a07c5d133bb1727ea7", size = 406998, upload-time = "2025-07-01T15:54:43.025Z" }, - { url = "https://files.pythonhosted.org/packages/6c/b0/8fa5e36e58657997873fd6a1cf621285ca822ca75b4b3434ead047daa307/rpds_py-0.26.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2c03c9b0c64afd0320ae57de4c982801271c0c211aa2d37f3003ff5feb75bb04", size = 385903, upload-time = "2025-07-01T15:54:44.752Z" }, - { url = "https://files.pythonhosted.org/packages/4b/f7/b25437772f9f57d7a9fbd73ed86d0dcd76b4c7c6998348c070d90f23e315/rpds_py-0.26.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5963b72ccd199ade6ee493723d18a3f21ba7d5b957017607f815788cef50eaf1", size = 419785, upload-time = "2025-07-01T15:54:46.043Z" }, - { url = "https://files.pythonhosted.org/packages/a7/6b/63ffa55743dfcb4baf2e9e77a0b11f7f97ed96a54558fcb5717a4b2cd732/rpds_py-0.26.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:9da4e873860ad5bab3291438525cae80169daecbfafe5657f7f5fb4d6b3f96b9", size = 561329, upload-time = "2025-07-01T15:54:47.64Z" }, - { url = "https://files.pythonhosted.org/packages/2f/07/1f4f5e2886c480a2346b1e6759c00278b8a69e697ae952d82ae2e6ee5db0/rpds_py-0.26.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:5afaddaa8e8c7f1f7b4c5c725c0070b6eed0228f705b90a1732a48e84350f4e9", size = 590875, upload-time = "2025-07-01T15:54:48.9Z" }, - { url = "https://files.pythonhosted.org/packages/cc/bc/e6639f1b91c3a55f8c41b47d73e6307051b6e246254a827ede730624c0f8/rpds_py-0.26.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4916dc96489616a6f9667e7526af8fa693c0fdb4f3acb0e5d9f4400eb06a47ba", size = 556636, upload-time = "2025-07-01T15:54:50.619Z" }, - { url = "https://files.pythonhosted.org/packages/05/4c/b3917c45566f9f9a209d38d9b54a1833f2bb1032a3e04c66f75726f28876/rpds_py-0.26.0-cp313-cp313-win32.whl", hash = "sha256:2a343f91b17097c546b93f7999976fd6c9d5900617aa848c81d794e062ab302b", size = 222663, upload-time = "2025-07-01T15:54:52.023Z" }, - { url = "https://files.pythonhosted.org/packages/e0/0b/0851bdd6025775aaa2365bb8de0697ee2558184c800bfef8d7aef5ccde58/rpds_py-0.26.0-cp313-cp313-win_amd64.whl", hash = "sha256:0a0b60701f2300c81b2ac88a5fb893ccfa408e1c4a555a77f908a2596eb875a5", size = 234428, upload-time = "2025-07-01T15:54:53.692Z" }, - { url = "https://files.pythonhosted.org/packages/ed/e8/a47c64ed53149c75fb581e14a237b7b7cd18217e969c30d474d335105622/rpds_py-0.26.0-cp313-cp313-win_arm64.whl", hash = "sha256:257d011919f133a4746958257f2c75238e3ff54255acd5e3e11f3ff41fd14256", size = 222571, upload-time = "2025-07-01T15:54:54.822Z" }, - { url = "https://files.pythonhosted.org/packages/89/bf/3d970ba2e2bcd17d2912cb42874107390f72873e38e79267224110de5e61/rpds_py-0.26.0-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:529c8156d7506fba5740e05da8795688f87119cce330c244519cf706a4a3d618", size = 360475, upload-time = "2025-07-01T15:54:56.228Z" }, - { url = "https://files.pythonhosted.org/packages/82/9f/283e7e2979fc4ec2d8ecee506d5a3675fce5ed9b4b7cb387ea5d37c2f18d/rpds_py-0.26.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:f53ec51f9d24e9638a40cabb95078ade8c99251945dad8d57bf4aabe86ecee35", size = 346692, upload-time = "2025-07-01T15:54:58.561Z" }, - { url = "https://files.pythonhosted.org/packages/e3/03/7e50423c04d78daf391da3cc4330bdb97042fc192a58b186f2d5deb7befd/rpds_py-0.26.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7ab504c4d654e4a29558eaa5bb8cea5fdc1703ea60a8099ffd9c758472cf913f", size = 379415, upload-time = "2025-07-01T15:54:59.751Z" }, - { url = "https://files.pythonhosted.org/packages/57/00/d11ee60d4d3b16808432417951c63df803afb0e0fc672b5e8d07e9edaaae/rpds_py-0.26.0-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fd0641abca296bc1a00183fe44f7fced8807ed49d501f188faa642d0e4975b83", size = 391783, upload-time = "2025-07-01T15:55:00.898Z" }, - { url = "https://files.pythonhosted.org/packages/08/b3/1069c394d9c0d6d23c5b522e1f6546b65793a22950f6e0210adcc6f97c3e/rpds_py-0.26.0-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:69b312fecc1d017b5327afa81d4da1480f51c68810963a7336d92203dbb3d4f1", size = 512844, upload-time = "2025-07-01T15:55:02.201Z" }, - { url = "https://files.pythonhosted.org/packages/08/3b/c4fbf0926800ed70b2c245ceca99c49f066456755f5d6eb8863c2c51e6d0/rpds_py-0.26.0-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c741107203954f6fc34d3066d213d0a0c40f7bb5aafd698fb39888af277c70d8", size = 402105, upload-time = "2025-07-01T15:55:03.698Z" }, - { url = "https://files.pythonhosted.org/packages/1c/b0/db69b52ca07413e568dae9dc674627a22297abb144c4d6022c6d78f1e5cc/rpds_py-0.26.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc3e55a7db08dc9a6ed5fb7103019d2c1a38a349ac41901f9f66d7f95750942f", size = 383440, upload-time = "2025-07-01T15:55:05.398Z" }, - { url = "https://files.pythonhosted.org/packages/4c/e1/c65255ad5b63903e56b3bb3ff9dcc3f4f5c3badde5d08c741ee03903e951/rpds_py-0.26.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9e851920caab2dbcae311fd28f4313c6953993893eb5c1bb367ec69d9a39e7ed", size = 412759, upload-time = "2025-07-01T15:55:08.316Z" }, - { url = "https://files.pythonhosted.org/packages/e4/22/bb731077872377a93c6e93b8a9487d0406c70208985831034ccdeed39c8e/rpds_py-0.26.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:dfbf280da5f876d0b00c81f26bedce274e72a678c28845453885a9b3c22ae632", size = 556032, upload-time = "2025-07-01T15:55:09.52Z" }, - { url = "https://files.pythonhosted.org/packages/e0/8b/393322ce7bac5c4530fb96fc79cc9ea2f83e968ff5f6e873f905c493e1c4/rpds_py-0.26.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:1cc81d14ddfa53d7f3906694d35d54d9d3f850ef8e4e99ee68bc0d1e5fed9a9c", size = 585416, upload-time = "2025-07-01T15:55:11.216Z" }, - { url = "https://files.pythonhosted.org/packages/49/ae/769dc372211835bf759319a7aae70525c6eb523e3371842c65b7ef41c9c6/rpds_py-0.26.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:dca83c498b4650a91efcf7b88d669b170256bf8017a5db6f3e06c2bf031f57e0", size = 554049, upload-time = "2025-07-01T15:55:13.004Z" }, - { url = "https://files.pythonhosted.org/packages/6b/f9/4c43f9cc203d6ba44ce3146246cdc38619d92c7bd7bad4946a3491bd5b70/rpds_py-0.26.0-cp313-cp313t-win32.whl", hash = "sha256:4d11382bcaf12f80b51d790dee295c56a159633a8e81e6323b16e55d81ae37e9", size = 218428, upload-time = "2025-07-01T15:55:14.486Z" }, - { url = "https://files.pythonhosted.org/packages/7e/8b/9286b7e822036a4a977f2f1e851c7345c20528dbd56b687bb67ed68a8ede/rpds_py-0.26.0-cp313-cp313t-win_amd64.whl", hash = "sha256:ff110acded3c22c033e637dd8896e411c7d3a11289b2edf041f86663dbc791e9", size = 231524, upload-time = "2025-07-01T15:55:15.745Z" }, - { url = "https://files.pythonhosted.org/packages/55/07/029b7c45db910c74e182de626dfdae0ad489a949d84a468465cd0ca36355/rpds_py-0.26.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:da619979df60a940cd434084355c514c25cf8eb4cf9a508510682f6c851a4f7a", size = 364292, upload-time = "2025-07-01T15:55:17.001Z" }, - { url = "https://files.pythonhosted.org/packages/13/d1/9b3d3f986216b4d1f584878dca15ce4797aaf5d372d738974ba737bf68d6/rpds_py-0.26.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:ea89a2458a1a75f87caabefe789c87539ea4e43b40f18cff526052e35bbb4fdf", size = 350334, upload-time = "2025-07-01T15:55:18.922Z" }, - { url = "https://files.pythonhosted.org/packages/18/98/16d5e7bc9ec715fa9668731d0cf97f6b032724e61696e2db3d47aeb89214/rpds_py-0.26.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:feac1045b3327a45944e7dcbeb57530339f6b17baff154df51ef8b0da34c8c12", size = 384875, upload-time = "2025-07-01T15:55:20.399Z" }, - { url = "https://files.pythonhosted.org/packages/f9/13/aa5e2b1ec5ab0e86a5c464d53514c0467bec6ba2507027d35fc81818358e/rpds_py-0.26.0-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b818a592bd69bfe437ee8368603d4a2d928c34cffcdf77c2e761a759ffd17d20", size = 399993, upload-time = "2025-07-01T15:55:21.729Z" }, - { url = "https://files.pythonhosted.org/packages/17/03/8021810b0e97923abdbab6474c8b77c69bcb4b2c58330777df9ff69dc559/rpds_py-0.26.0-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1a8b0dd8648709b62d9372fc00a57466f5fdeefed666afe3fea5a6c9539a0331", size = 516683, upload-time = "2025-07-01T15:55:22.918Z" }, - { url = "https://files.pythonhosted.org/packages/dc/b1/da8e61c87c2f3d836954239fdbbfb477bb7b54d74974d8f6fcb34342d166/rpds_py-0.26.0-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6d3498ad0df07d81112aa6ec6c95a7e7b1ae00929fb73e7ebee0f3faaeabad2f", size = 408825, upload-time = "2025-07-01T15:55:24.207Z" }, - { url = "https://files.pythonhosted.org/packages/38/bc/1fc173edaaa0e52c94b02a655db20697cb5fa954ad5a8e15a2c784c5cbdd/rpds_py-0.26.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:24a4146ccb15be237fdef10f331c568e1b0e505f8c8c9ed5d67759dac58ac246", size = 387292, upload-time = "2025-07-01T15:55:25.554Z" }, - { url = "https://files.pythonhosted.org/packages/7c/eb/3a9bb4bd90867d21916f253caf4f0d0be7098671b6715ad1cead9fe7bab9/rpds_py-0.26.0-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a9a63785467b2d73635957d32a4f6e73d5e4df497a16a6392fa066b753e87387", size = 420435, upload-time = "2025-07-01T15:55:27.798Z" }, - { url = "https://files.pythonhosted.org/packages/cd/16/e066dcdb56f5632713445271a3f8d3d0b426d51ae9c0cca387799df58b02/rpds_py-0.26.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:de4ed93a8c91debfd5a047be327b7cc8b0cc6afe32a716bbbc4aedca9e2a83af", size = 562410, upload-time = "2025-07-01T15:55:29.057Z" }, - { url = "https://files.pythonhosted.org/packages/60/22/ddbdec7eb82a0dc2e455be44c97c71c232983e21349836ce9f272e8a3c29/rpds_py-0.26.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:caf51943715b12af827696ec395bfa68f090a4c1a1d2509eb4e2cb69abbbdb33", size = 590724, upload-time = "2025-07-01T15:55:30.719Z" }, - { url = "https://files.pythonhosted.org/packages/2c/b4/95744085e65b7187d83f2fcb0bef70716a1ea0a9e5d8f7f39a86e5d83424/rpds_py-0.26.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:4a59e5bc386de021f56337f757301b337d7ab58baa40174fb150accd480bc953", size = 558285, upload-time = "2025-07-01T15:55:31.981Z" }, - { url = "https://files.pythonhosted.org/packages/37/37/6309a75e464d1da2559446f9c811aa4d16343cebe3dbb73701e63f760caa/rpds_py-0.26.0-cp314-cp314-win32.whl", hash = "sha256:92c8db839367ef16a662478f0a2fe13e15f2227da3c1430a782ad0f6ee009ec9", size = 223459, upload-time = "2025-07-01T15:55:33.312Z" }, - { url = "https://files.pythonhosted.org/packages/d9/6f/8e9c11214c46098b1d1391b7e02b70bb689ab963db3b19540cba17315291/rpds_py-0.26.0-cp314-cp314-win_amd64.whl", hash = "sha256:b0afb8cdd034150d4d9f53926226ed27ad15b7f465e93d7468caaf5eafae0d37", size = 236083, upload-time = "2025-07-01T15:55:34.933Z" }, - { url = "https://files.pythonhosted.org/packages/47/af/9c4638994dd623d51c39892edd9d08e8be8220a4b7e874fa02c2d6e91955/rpds_py-0.26.0-cp314-cp314-win_arm64.whl", hash = "sha256:ca3f059f4ba485d90c8dc75cb5ca897e15325e4e609812ce57f896607c1c0867", size = 223291, upload-time = "2025-07-01T15:55:36.202Z" }, - { url = "https://files.pythonhosted.org/packages/4d/db/669a241144460474aab03e254326b32c42def83eb23458a10d163cb9b5ce/rpds_py-0.26.0-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:5afea17ab3a126006dc2f293b14ffc7ef3c85336cf451564a0515ed7648033da", size = 361445, upload-time = "2025-07-01T15:55:37.483Z" }, - { url = "https://files.pythonhosted.org/packages/3b/2d/133f61cc5807c6c2fd086a46df0eb8f63a23f5df8306ff9f6d0fd168fecc/rpds_py-0.26.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:69f0c0a3df7fd3a7eec50a00396104bb9a843ea6d45fcc31c2d5243446ffd7a7", size = 347206, upload-time = "2025-07-01T15:55:38.828Z" }, - { url = "https://files.pythonhosted.org/packages/05/bf/0e8fb4c05f70273469eecf82f6ccf37248558526a45321644826555db31b/rpds_py-0.26.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:801a71f70f9813e82d2513c9a96532551fce1e278ec0c64610992c49c04c2dad", size = 380330, upload-time = "2025-07-01T15:55:40.175Z" }, - { url = "https://files.pythonhosted.org/packages/d4/a8/060d24185d8b24d3923322f8d0ede16df4ade226a74e747b8c7c978e3dd3/rpds_py-0.26.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:df52098cde6d5e02fa75c1f6244f07971773adb4a26625edd5c18fee906fa84d", size = 392254, upload-time = "2025-07-01T15:55:42.015Z" }, - { url = "https://files.pythonhosted.org/packages/b9/7b/7c2e8a9ee3e6bc0bae26bf29f5219955ca2fbb761dca996a83f5d2f773fe/rpds_py-0.26.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9bc596b30f86dc6f0929499c9e574601679d0341a0108c25b9b358a042f51bca", size = 516094, upload-time = "2025-07-01T15:55:43.603Z" }, - { url = "https://files.pythonhosted.org/packages/75/d6/f61cafbed8ba1499b9af9f1777a2a199cd888f74a96133d8833ce5eaa9c5/rpds_py-0.26.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9dfbe56b299cf5875b68eb6f0ebaadc9cac520a1989cac0db0765abfb3709c19", size = 402889, upload-time = "2025-07-01T15:55:45.275Z" }, - { url = "https://files.pythonhosted.org/packages/92/19/c8ac0a8a8df2dd30cdec27f69298a5c13e9029500d6d76718130f5e5be10/rpds_py-0.26.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ac64f4b2bdb4ea622175c9ab7cf09444e412e22c0e02e906978b3b488af5fde8", size = 384301, upload-time = "2025-07-01T15:55:47.098Z" }, - { url = "https://files.pythonhosted.org/packages/41/e1/6b1859898bc292a9ce5776016c7312b672da00e25cec74d7beced1027286/rpds_py-0.26.0-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:181ef9b6bbf9845a264f9aa45c31836e9f3c1f13be565d0d010e964c661d1e2b", size = 412891, upload-time = "2025-07-01T15:55:48.412Z" }, - { url = "https://files.pythonhosted.org/packages/ef/b9/ceb39af29913c07966a61367b3c08b4f71fad841e32c6b59a129d5974698/rpds_py-0.26.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:49028aa684c144ea502a8e847d23aed5e4c2ef7cadfa7d5eaafcb40864844b7a", size = 557044, upload-time = "2025-07-01T15:55:49.816Z" }, - { url = "https://files.pythonhosted.org/packages/2f/27/35637b98380731a521f8ec4f3fd94e477964f04f6b2f8f7af8a2d889a4af/rpds_py-0.26.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:e5d524d68a474a9688336045bbf76cb0def88549c1b2ad9dbfec1fb7cfbe9170", size = 585774, upload-time = "2025-07-01T15:55:51.192Z" }, - { url = "https://files.pythonhosted.org/packages/52/d9/3f0f105420fecd18551b678c9a6ce60bd23986098b252a56d35781b3e7e9/rpds_py-0.26.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:c1851f429b822831bd2edcbe0cfd12ee9ea77868f8d3daf267b189371671c80e", size = 554886, upload-time = "2025-07-01T15:55:52.541Z" }, - { url = "https://files.pythonhosted.org/packages/6b/c5/347c056a90dc8dd9bc240a08c527315008e1b5042e7a4cf4ac027be9d38a/rpds_py-0.26.0-cp314-cp314t-win32.whl", hash = "sha256:7bdb17009696214c3b66bb3590c6d62e14ac5935e53e929bcdbc5a495987a84f", size = 219027, upload-time = "2025-07-01T15:55:53.874Z" }, - { url = "https://files.pythonhosted.org/packages/75/04/5302cea1aa26d886d34cadbf2dc77d90d7737e576c0065f357b96dc7a1a6/rpds_py-0.26.0-cp314-cp314t-win_amd64.whl", hash = "sha256:f14440b9573a6f76b4ee4770c13f0b5921f71dde3b6fcb8dabbefd13b7fe05d7", size = 232821, upload-time = "2025-07-01T15:55:55.167Z" }, - { url = "https://files.pythonhosted.org/packages/51/f2/b5c85b758a00c513bb0389f8fc8e61eb5423050c91c958cdd21843faa3e6/rpds_py-0.26.0-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:f61a9326f80ca59214d1cceb0a09bb2ece5b2563d4e0cd37bfd5515c28510674", size = 373505, upload-time = "2025-07-01T15:56:34.716Z" }, - { url = "https://files.pythonhosted.org/packages/23/e0/25db45e391251118e915e541995bb5f5ac5691a3b98fb233020ba53afc9b/rpds_py-0.26.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:183f857a53bcf4b1b42ef0f57ca553ab56bdd170e49d8091e96c51c3d69ca696", size = 359468, upload-time = "2025-07-01T15:56:36.219Z" }, - { url = "https://files.pythonhosted.org/packages/0b/73/dd5ee6075bb6491be3a646b301dfd814f9486d924137a5098e61f0487e16/rpds_py-0.26.0-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:941c1cfdf4799d623cf3aa1d326a6b4fdb7a5799ee2687f3516738216d2262fb", size = 382680, upload-time = "2025-07-01T15:56:37.644Z" }, - { url = "https://files.pythonhosted.org/packages/2f/10/84b522ff58763a5c443f5bcedc1820240e454ce4e620e88520f04589e2ea/rpds_py-0.26.0-pp311-pypy311_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:72a8d9564a717ee291f554eeb4bfeafe2309d5ec0aa6c475170bdab0f9ee8e88", size = 397035, upload-time = "2025-07-01T15:56:39.241Z" }, - { url = "https://files.pythonhosted.org/packages/06/ea/8667604229a10a520fcbf78b30ccc278977dcc0627beb7ea2c96b3becef0/rpds_py-0.26.0-pp311-pypy311_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:511d15193cbe013619dd05414c35a7dedf2088fcee93c6bbb7c77859765bd4e8", size = 514922, upload-time = "2025-07-01T15:56:40.645Z" }, - { url = "https://files.pythonhosted.org/packages/24/e6/9ed5b625c0661c4882fc8cdf302bf8e96c73c40de99c31e0b95ed37d508c/rpds_py-0.26.0-pp311-pypy311_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:aea1f9741b603a8d8fedb0ed5502c2bc0accbc51f43e2ad1337fe7259c2b77a5", size = 402822, upload-time = "2025-07-01T15:56:42.137Z" }, - { url = "https://files.pythonhosted.org/packages/8a/58/212c7b6fd51946047fb45d3733da27e2fa8f7384a13457c874186af691b1/rpds_py-0.26.0-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4019a9d473c708cf2f16415688ef0b4639e07abaa569d72f74745bbeffafa2c7", size = 384336, upload-time = "2025-07-01T15:56:44.239Z" }, - { url = "https://files.pythonhosted.org/packages/aa/f5/a40ba78748ae8ebf4934d4b88e77b98497378bc2c24ba55ebe87a4e87057/rpds_py-0.26.0-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:093d63b4b0f52d98ebae33b8c50900d3d67e0666094b1be7a12fffd7f65de74b", size = 416871, upload-time = "2025-07-01T15:56:46.284Z" }, - { url = "https://files.pythonhosted.org/packages/d5/a6/33b1fc0c9f7dcfcfc4a4353daa6308b3ece22496ceece348b3e7a7559a09/rpds_py-0.26.0-pp311-pypy311_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:2abe21d8ba64cded53a2a677e149ceb76dcf44284202d737178afe7ba540c1eb", size = 559439, upload-time = "2025-07-01T15:56:48.549Z" }, - { url = "https://files.pythonhosted.org/packages/71/2d/ceb3f9c12f8cfa56d34995097f6cd99da1325642c60d1b6680dd9df03ed8/rpds_py-0.26.0-pp311-pypy311_pp73-musllinux_1_2_i686.whl", hash = "sha256:4feb7511c29f8442cbbc28149a92093d32e815a28aa2c50d333826ad2a20fdf0", size = 588380, upload-time = "2025-07-01T15:56:50.086Z" }, - { url = "https://files.pythonhosted.org/packages/c8/ed/9de62c2150ca8e2e5858acf3f4f4d0d180a38feef9fdab4078bea63d8dba/rpds_py-0.26.0-pp311-pypy311_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:e99685fc95d386da368013e7fb4269dd39c30d99f812a8372d62f244f662709c", size = 555334, upload-time = "2025-07-01T15:56:51.703Z" }, +version = "0.27.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/1e/d9/991a0dee12d9fc53ed027e26a26a64b151d77252ac477e22666b9688bc16/rpds_py-0.27.0.tar.gz", hash = "sha256:8b23cf252f180cda89220b378d917180f29d313cd6a07b2431c0d3b776aae86f", size = 27420, upload-time = "2025-08-07T08:26:39.624Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b4/c1/49d515434c1752e40f5e35b985260cf27af052593378580a2f139a5be6b8/rpds_py-0.27.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:dbc2ab5d10544eb485baa76c63c501303b716a5c405ff2469a1d8ceffaabf622", size = 371577, upload-time = "2025-08-07T08:23:25.379Z" }, + { url = "https://files.pythonhosted.org/packages/e1/6d/bf2715b2fee5087fa13b752b5fd573f1a93e4134c74d275f709e38e54fe7/rpds_py-0.27.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7ec85994f96a58cf7ed288caa344b7fe31fd1d503bdf13d7331ead5f70ab60d5", size = 354959, upload-time = "2025-08-07T08:23:26.767Z" }, + { url = "https://files.pythonhosted.org/packages/a3/5c/e7762808c746dd19733a81373c10da43926f6a6adcf4920a21119697a60a/rpds_py-0.27.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:190d7285cd3bb6d31d37a0534d7359c1ee191eb194c511c301f32a4afa5a1dd4", size = 381485, upload-time = "2025-08-07T08:23:27.869Z" }, + { url = "https://files.pythonhosted.org/packages/40/51/0d308eb0b558309ca0598bcba4243f52c4cd20e15fe991b5bd75824f2e61/rpds_py-0.27.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c10d92fb6d7fd827e44055fcd932ad93dac6a11e832d51534d77b97d1d85400f", size = 396816, upload-time = "2025-08-07T08:23:29.424Z" }, + { url = "https://files.pythonhosted.org/packages/5c/aa/2d585ec911d78f66458b2c91252134ca0c7c70f687a72c87283173dc0c96/rpds_py-0.27.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dd2c1d27ebfe6a015cfa2005b7fe8c52d5019f7bbdd801bc6f7499aab9ae739e", size = 514950, upload-time = "2025-08-07T08:23:30.576Z" }, + { url = "https://files.pythonhosted.org/packages/0b/ef/aced551cc1148179557aed84343073adadf252c91265263ee6203458a186/rpds_py-0.27.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4790c9d5dd565ddb3e9f656092f57268951398cef52e364c405ed3112dc7c7c1", size = 402132, upload-time = "2025-08-07T08:23:32.428Z" }, + { url = "https://files.pythonhosted.org/packages/4b/ac/cf644803d8d417653fe2b3604186861d62ea6afaef1b2284045741baef17/rpds_py-0.27.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4300e15e7d03660f04be84a125d1bdd0e6b2f674bc0723bc0fd0122f1a4585dc", size = 383660, upload-time = "2025-08-07T08:23:33.829Z" }, + { url = "https://files.pythonhosted.org/packages/c9/ec/caf47c55ce02b76cbaeeb2d3b36a73da9ca2e14324e3d75cf72b59dcdac5/rpds_py-0.27.0-cp311-cp311-manylinux_2_31_riscv64.whl", hash = "sha256:59195dc244fc183209cf8a93406889cadde47dfd2f0a6b137783aa9c56d67c85", size = 401730, upload-time = "2025-08-07T08:23:34.97Z" }, + { url = "https://files.pythonhosted.org/packages/0b/71/c1f355afdcd5b99ffc253422aa4bdcb04ccf1491dcd1bda3688a0c07fd61/rpds_py-0.27.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fae4a01ef8c4cb2bbe92ef2063149596907dc4a881a8d26743b3f6b304713171", size = 416122, upload-time = "2025-08-07T08:23:36.062Z" }, + { url = "https://files.pythonhosted.org/packages/38/0f/f4b5b1eda724ed0e04d2b26d8911cdc131451a7ee4c4c020a1387e5c6ded/rpds_py-0.27.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:e3dc8d4ede2dbae6c0fc2b6c958bf51ce9fd7e9b40c0f5b8835c3fde44f5807d", size = 558771, upload-time = "2025-08-07T08:23:37.478Z" }, + { url = "https://files.pythonhosted.org/packages/93/c0/5f8b834db2289ab48d5cffbecbb75e35410103a77ac0b8da36bf9544ec1c/rpds_py-0.27.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:c3782fb753aa825b4ccabc04292e07897e2fd941448eabf666856c5530277626", size = 587876, upload-time = "2025-08-07T08:23:38.662Z" }, + { url = "https://files.pythonhosted.org/packages/d2/dd/1a1df02ab8eb970115cff2ae31a6f73916609b900dc86961dc382b8c2e5e/rpds_py-0.27.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:887ab1f12b0d227e9260558a4a2320024b20102207ada65c43e1ffc4546df72e", size = 554359, upload-time = "2025-08-07T08:23:39.897Z" }, + { url = "https://files.pythonhosted.org/packages/a1/e4/95a014ab0d51ab6e3bebbdb476a42d992d2bbf9c489d24cff9fda998e925/rpds_py-0.27.0-cp311-cp311-win32.whl", hash = "sha256:5d6790ff400254137b81b8053b34417e2c46921e302d655181d55ea46df58cf7", size = 218084, upload-time = "2025-08-07T08:23:41.086Z" }, + { url = "https://files.pythonhosted.org/packages/49/78/f8d5b71ec65a0376b0de31efcbb5528ce17a9b7fdd19c3763303ccfdedec/rpds_py-0.27.0-cp311-cp311-win_amd64.whl", hash = "sha256:e24d8031a2c62f34853756d9208eeafa6b940a1efcbfe36e8f57d99d52bb7261", size = 230085, upload-time = "2025-08-07T08:23:42.143Z" }, + { url = "https://files.pythonhosted.org/packages/e7/d3/84429745184091e06b4cc70f8597408e314c2d2f7f5e13249af9ffab9e3d/rpds_py-0.27.0-cp311-cp311-win_arm64.whl", hash = "sha256:08680820d23df1df0a0260f714d12966bc6c42d02e8055a91d61e03f0c47dda0", size = 222112, upload-time = "2025-08-07T08:23:43.233Z" }, + { url = "https://files.pythonhosted.org/packages/cd/17/e67309ca1ac993fa1888a0d9b2f5ccc1f67196ace32e76c9f8e1dbbbd50c/rpds_py-0.27.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:19c990fdf5acecbf0623e906ae2e09ce1c58947197f9bced6bbd7482662231c4", size = 362611, upload-time = "2025-08-07T08:23:44.773Z" }, + { url = "https://files.pythonhosted.org/packages/93/2e/28c2fb84aa7aa5d75933d1862d0f7de6198ea22dfd9a0cca06e8a4e7509e/rpds_py-0.27.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6c27a7054b5224710fcfb1a626ec3ff4f28bcb89b899148c72873b18210e446b", size = 347680, upload-time = "2025-08-07T08:23:46.014Z" }, + { url = "https://files.pythonhosted.org/packages/44/3e/9834b4c8f4f5fe936b479e623832468aa4bd6beb8d014fecaee9eac6cdb1/rpds_py-0.27.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:09965b314091829b378b60607022048953e25f0b396c2b70e7c4c81bcecf932e", size = 384600, upload-time = "2025-08-07T08:23:48Z" }, + { url = "https://files.pythonhosted.org/packages/19/78/744123c7b38865a965cd9e6f691fde7ef989a00a256fa8bf15b75240d12f/rpds_py-0.27.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:14f028eb47f59e9169bfdf9f7ceafd29dd64902141840633683d0bad5b04ff34", size = 400697, upload-time = "2025-08-07T08:23:49.407Z" }, + { url = "https://files.pythonhosted.org/packages/32/97/3c3d32fe7daee0a1f1a678b6d4dfb8c4dcf88197fa2441f9da7cb54a8466/rpds_py-0.27.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6168af0be75bba990a39f9431cdfae5f0ad501f4af32ae62e8856307200517b8", size = 517781, upload-time = "2025-08-07T08:23:50.557Z" }, + { url = "https://files.pythonhosted.org/packages/b2/be/28f0e3e733680aa13ecec1212fc0f585928a206292f14f89c0b8a684cad1/rpds_py-0.27.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ab47fe727c13c09d0e6f508e3a49e545008e23bf762a245b020391b621f5b726", size = 406449, upload-time = "2025-08-07T08:23:51.732Z" }, + { url = "https://files.pythonhosted.org/packages/95/ae/5d15c83e337c082d0367053baeb40bfba683f42459f6ebff63a2fd7e5518/rpds_py-0.27.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5fa01b3d5e3b7d97efab65bd3d88f164e289ec323a8c033c5c38e53ee25c007e", size = 386150, upload-time = "2025-08-07T08:23:52.822Z" }, + { url = "https://files.pythonhosted.org/packages/bf/65/944e95f95d5931112829e040912b25a77b2e7ed913ea5fe5746aa5c1ce75/rpds_py-0.27.0-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:6c135708e987f46053e0a1246a206f53717f9fadfba27174a9769ad4befba5c3", size = 406100, upload-time = "2025-08-07T08:23:54.339Z" }, + { url = "https://files.pythonhosted.org/packages/21/a4/1664b83fae02894533cd11dc0b9f91d673797c2185b7be0f7496107ed6c5/rpds_py-0.27.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fc327f4497b7087d06204235199daf208fd01c82d80465dc5efa4ec9df1c5b4e", size = 421345, upload-time = "2025-08-07T08:23:55.832Z" }, + { url = "https://files.pythonhosted.org/packages/7c/26/b7303941c2b0823bfb34c71378249f8beedce57301f400acb04bb345d025/rpds_py-0.27.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:7e57906e38583a2cba67046a09c2637e23297618dc1f3caddbc493f2be97c93f", size = 561891, upload-time = "2025-08-07T08:23:56.951Z" }, + { url = "https://files.pythonhosted.org/packages/9b/c8/48623d64d4a5a028fa99576c768a6159db49ab907230edddc0b8468b998b/rpds_py-0.27.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:0f4f69d7a4300fbf91efb1fb4916421bd57804c01ab938ab50ac9c4aa2212f03", size = 591756, upload-time = "2025-08-07T08:23:58.146Z" }, + { url = "https://files.pythonhosted.org/packages/b3/51/18f62617e8e61cc66334c9fb44b1ad7baae3438662098efbc55fb3fda453/rpds_py-0.27.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b4c4fbbcff474e1e5f38be1bf04511c03d492d42eec0babda5d03af3b5589374", size = 557088, upload-time = "2025-08-07T08:23:59.6Z" }, + { url = "https://files.pythonhosted.org/packages/bd/4c/e84c3a276e2496a93d245516be6b49e20499aa8ca1c94d59fada0d79addc/rpds_py-0.27.0-cp312-cp312-win32.whl", hash = "sha256:27bac29bbbf39601b2aab474daf99dbc8e7176ca3389237a23944b17f8913d97", size = 221926, upload-time = "2025-08-07T08:24:00.695Z" }, + { url = "https://files.pythonhosted.org/packages/83/89/9d0fbcef64340db0605eb0a0044f258076f3ae0a3b108983b2c614d96212/rpds_py-0.27.0-cp312-cp312-win_amd64.whl", hash = "sha256:8a06aa1197ec0281eb1d7daf6073e199eb832fe591ffa329b88bae28f25f5fe5", size = 233235, upload-time = "2025-08-07T08:24:01.846Z" }, + { url = "https://files.pythonhosted.org/packages/c9/b0/e177aa9f39cbab060f96de4a09df77d494f0279604dc2f509263e21b05f9/rpds_py-0.27.0-cp312-cp312-win_arm64.whl", hash = "sha256:e14aab02258cb776a108107bd15f5b5e4a1bbaa61ef33b36693dfab6f89d54f9", size = 223315, upload-time = "2025-08-07T08:24:03.337Z" }, + { url = "https://files.pythonhosted.org/packages/81/d2/dfdfd42565a923b9e5a29f93501664f5b984a802967d48d49200ad71be36/rpds_py-0.27.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:443d239d02d9ae55b74015234f2cd8eb09e59fbba30bf60baeb3123ad4c6d5ff", size = 362133, upload-time = "2025-08-07T08:24:04.508Z" }, + { url = "https://files.pythonhosted.org/packages/ac/4a/0a2e2460c4b66021d349ce9f6331df1d6c75d7eea90df9785d333a49df04/rpds_py-0.27.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:b8a7acf04fda1f30f1007f3cc96d29d8cf0a53e626e4e1655fdf4eabc082d367", size = 347128, upload-time = "2025-08-07T08:24:05.695Z" }, + { url = "https://files.pythonhosted.org/packages/35/8d/7d1e4390dfe09d4213b3175a3f5a817514355cb3524593380733204f20b9/rpds_py-0.27.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9d0f92b78cfc3b74a42239fdd8c1266f4715b573204c234d2f9fc3fc7a24f185", size = 384027, upload-time = "2025-08-07T08:24:06.841Z" }, + { url = "https://files.pythonhosted.org/packages/c1/65/78499d1a62172891c8cd45de737b2a4b84a414b6ad8315ab3ac4945a5b61/rpds_py-0.27.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ce4ed8e0c7dbc5b19352b9c2c6131dd23b95fa8698b5cdd076307a33626b72dc", size = 399973, upload-time = "2025-08-07T08:24:08.143Z" }, + { url = "https://files.pythonhosted.org/packages/10/a1/1c67c1d8cc889107b19570bb01f75cf49852068e95e6aee80d22915406fc/rpds_py-0.27.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fde355b02934cc6b07200cc3b27ab0c15870a757d1a72fd401aa92e2ea3c6bfe", size = 515295, upload-time = "2025-08-07T08:24:09.711Z" }, + { url = "https://files.pythonhosted.org/packages/df/27/700ec88e748436b6c7c4a2262d66e80f8c21ab585d5e98c45e02f13f21c0/rpds_py-0.27.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:13bbc4846ae4c993f07c93feb21a24d8ec637573d567a924b1001e81c8ae80f9", size = 406737, upload-time = "2025-08-07T08:24:11.182Z" }, + { url = "https://files.pythonhosted.org/packages/33/cc/6b0ee8f0ba3f2df2daac1beda17fde5cf10897a7d466f252bd184ef20162/rpds_py-0.27.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:be0744661afbc4099fef7f4e604e7f1ea1be1dd7284f357924af12a705cc7d5c", size = 385898, upload-time = "2025-08-07T08:24:12.798Z" }, + { url = "https://files.pythonhosted.org/packages/e8/7e/c927b37d7d33c0a0ebf249cc268dc2fcec52864c1b6309ecb960497f2285/rpds_py-0.27.0-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:069e0384a54f427bd65d7fda83b68a90606a3835901aaff42185fcd94f5a9295", size = 405785, upload-time = "2025-08-07T08:24:14.906Z" }, + { url = "https://files.pythonhosted.org/packages/5b/d2/8ed50746d909dcf402af3fa58b83d5a590ed43e07251d6b08fad1a535ba6/rpds_py-0.27.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4bc262ace5a1a7dc3e2eac2fa97b8257ae795389f688b5adf22c5db1e2431c43", size = 419760, upload-time = "2025-08-07T08:24:16.129Z" }, + { url = "https://files.pythonhosted.org/packages/d3/60/2b2071aee781cb3bd49f94d5d35686990b925e9b9f3e3d149235a6f5d5c1/rpds_py-0.27.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:2fe6e18e5c8581f0361b35ae575043c7029d0a92cb3429e6e596c2cdde251432", size = 561201, upload-time = "2025-08-07T08:24:17.645Z" }, + { url = "https://files.pythonhosted.org/packages/98/1f/27b67304272521aaea02be293fecedce13fa351a4e41cdb9290576fc6d81/rpds_py-0.27.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:d93ebdb82363d2e7bec64eecdc3632b59e84bd270d74fe5be1659f7787052f9b", size = 591021, upload-time = "2025-08-07T08:24:18.999Z" }, + { url = "https://files.pythonhosted.org/packages/db/9b/a2fadf823164dd085b1f894be6443b0762a54a7af6f36e98e8fcda69ee50/rpds_py-0.27.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:0954e3a92e1d62e83a54ea7b3fdc9efa5d61acef8488a8a3d31fdafbfb00460d", size = 556368, upload-time = "2025-08-07T08:24:20.54Z" }, + { url = "https://files.pythonhosted.org/packages/24/f3/6d135d46a129cda2e3e6d4c5e91e2cc26ea0428c6cf152763f3f10b6dd05/rpds_py-0.27.0-cp313-cp313-win32.whl", hash = "sha256:2cff9bdd6c7b906cc562a505c04a57d92e82d37200027e8d362518df427f96cd", size = 221236, upload-time = "2025-08-07T08:24:22.144Z" }, + { url = "https://files.pythonhosted.org/packages/c5/44/65d7494f5448ecc755b545d78b188440f81da98b50ea0447ab5ebfdf9bd6/rpds_py-0.27.0-cp313-cp313-win_amd64.whl", hash = "sha256:dc79d192fb76fc0c84f2c58672c17bbbc383fd26c3cdc29daae16ce3d927e8b2", size = 232634, upload-time = "2025-08-07T08:24:23.642Z" }, + { url = "https://files.pythonhosted.org/packages/70/d9/23852410fadab2abb611733933401de42a1964ce6600a3badae35fbd573e/rpds_py-0.27.0-cp313-cp313-win_arm64.whl", hash = "sha256:5b3a5c8089eed498a3af23ce87a80805ff98f6ef8f7bdb70bd1b7dae5105f6ac", size = 222783, upload-time = "2025-08-07T08:24:25.098Z" }, + { url = "https://files.pythonhosted.org/packages/15/75/03447917f78512b34463f4ef11066516067099a0c466545655503bed0c77/rpds_py-0.27.0-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:90fb790138c1a89a2e58c9282fe1089638401f2f3b8dddd758499041bc6e0774", size = 359154, upload-time = "2025-08-07T08:24:26.249Z" }, + { url = "https://files.pythonhosted.org/packages/6b/fc/4dac4fa756451f2122ddaf136e2c6aeb758dc6fdbe9ccc4bc95c98451d50/rpds_py-0.27.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:010c4843a3b92b54373e3d2291a7447d6c3fc29f591772cc2ea0e9f5c1da434b", size = 343909, upload-time = "2025-08-07T08:24:27.405Z" }, + { url = "https://files.pythonhosted.org/packages/7b/81/723c1ed8e6f57ed9d8c0c07578747a2d3d554aaefc1ab89f4e42cfeefa07/rpds_py-0.27.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c9ce7a9e967afc0a2af7caa0d15a3e9c1054815f73d6a8cb9225b61921b419bd", size = 379340, upload-time = "2025-08-07T08:24:28.714Z" }, + { url = "https://files.pythonhosted.org/packages/98/16/7e3740413de71818ce1997df82ba5f94bae9fff90c0a578c0e24658e6201/rpds_py-0.27.0-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:aa0bf113d15e8abdfee92aa4db86761b709a09954083afcb5bf0f952d6065fdb", size = 391655, upload-time = "2025-08-07T08:24:30.223Z" }, + { url = "https://files.pythonhosted.org/packages/e0/63/2a9f510e124d80660f60ecce07953f3f2d5f0b96192c1365443859b9c87f/rpds_py-0.27.0-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:eb91d252b35004a84670dfeafadb042528b19842a0080d8b53e5ec1128e8f433", size = 513017, upload-time = "2025-08-07T08:24:31.446Z" }, + { url = "https://files.pythonhosted.org/packages/2c/4e/cf6ff311d09776c53ea1b4f2e6700b9d43bb4e99551006817ade4bbd6f78/rpds_py-0.27.0-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:db8a6313dbac934193fc17fe7610f70cd8181c542a91382531bef5ed785e5615", size = 402058, upload-time = "2025-08-07T08:24:32.613Z" }, + { url = "https://files.pythonhosted.org/packages/88/11/5e36096d474cb10f2a2d68b22af60a3bc4164fd8db15078769a568d9d3ac/rpds_py-0.27.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce96ab0bdfcef1b8c371ada2100767ace6804ea35aacce0aef3aeb4f3f499ca8", size = 383474, upload-time = "2025-08-07T08:24:33.767Z" }, + { url = "https://files.pythonhosted.org/packages/db/a2/3dff02805b06058760b5eaa6d8cb8db3eb3e46c9e452453ad5fc5b5ad9fe/rpds_py-0.27.0-cp313-cp313t-manylinux_2_31_riscv64.whl", hash = "sha256:7451ede3560086abe1aa27dcdcf55cd15c96b56f543fb12e5826eee6f721f858", size = 400067, upload-time = "2025-08-07T08:24:35.021Z" }, + { url = "https://files.pythonhosted.org/packages/67/87/eed7369b0b265518e21ea836456a4ed4a6744c8c12422ce05bce760bb3cf/rpds_py-0.27.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:32196b5a99821476537b3f7732432d64d93a58d680a52c5e12a190ee0135d8b5", size = 412085, upload-time = "2025-08-07T08:24:36.267Z" }, + { url = "https://files.pythonhosted.org/packages/8b/48/f50b2ab2fbb422fbb389fe296e70b7a6b5ea31b263ada5c61377e710a924/rpds_py-0.27.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:a029be818059870664157194e46ce0e995082ac49926f1423c1f058534d2aaa9", size = 555928, upload-time = "2025-08-07T08:24:37.573Z" }, + { url = "https://files.pythonhosted.org/packages/98/41/b18eb51045d06887666c3560cd4bbb6819127b43d758f5adb82b5f56f7d1/rpds_py-0.27.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:3841f66c1ffdc6cebce8aed64e36db71466f1dc23c0d9a5592e2a782a3042c79", size = 585527, upload-time = "2025-08-07T08:24:39.391Z" }, + { url = "https://files.pythonhosted.org/packages/be/03/a3dd6470fc76499959b00ae56295b76b4bdf7c6ffc60d62006b1217567e1/rpds_py-0.27.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:42894616da0fc0dcb2ec08a77896c3f56e9cb2f4b66acd76fc8992c3557ceb1c", size = 554211, upload-time = "2025-08-07T08:24:40.6Z" }, + { url = "https://files.pythonhosted.org/packages/bf/d1/ee5fd1be395a07423ac4ca0bcc05280bf95db2b155d03adefeb47d5ebf7e/rpds_py-0.27.0-cp313-cp313t-win32.whl", hash = "sha256:b1fef1f13c842a39a03409e30ca0bf87b39a1e2a305a9924deadb75a43105d23", size = 216624, upload-time = "2025-08-07T08:24:42.204Z" }, + { url = "https://files.pythonhosted.org/packages/1c/94/4814c4c858833bf46706f87349c37ca45e154da7dbbec9ff09f1abeb08cc/rpds_py-0.27.0-cp313-cp313t-win_amd64.whl", hash = "sha256:183f5e221ba3e283cd36fdfbe311d95cd87699a083330b4f792543987167eff1", size = 230007, upload-time = "2025-08-07T08:24:43.329Z" }, + { url = "https://files.pythonhosted.org/packages/0e/a5/8fffe1c7dc7c055aa02df310f9fb71cfc693a4d5ccc5de2d3456ea5fb022/rpds_py-0.27.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:f3cd110e02c5bf17d8fb562f6c9df5c20e73029d587cf8602a2da6c5ef1e32cb", size = 362595, upload-time = "2025-08-07T08:24:44.478Z" }, + { url = "https://files.pythonhosted.org/packages/bc/c7/4e4253fd2d4bb0edbc0b0b10d9f280612ca4f0f990e3c04c599000fe7d71/rpds_py-0.27.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:8d0e09cf4863c74106b5265c2c310f36146e2b445ff7b3018a56799f28f39f6f", size = 347252, upload-time = "2025-08-07T08:24:45.678Z" }, + { url = "https://files.pythonhosted.org/packages/f3/c8/3d1a954d30f0174dd6baf18b57c215da03cf7846a9d6e0143304e784cddc/rpds_py-0.27.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:64f689ab822f9b5eb6dfc69893b4b9366db1d2420f7db1f6a2adf2a9ca15ad64", size = 384886, upload-time = "2025-08-07T08:24:46.86Z" }, + { url = "https://files.pythonhosted.org/packages/e0/52/3c5835f2df389832b28f9276dd5395b5a965cea34226e7c88c8fbec2093c/rpds_py-0.27.0-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e36c80c49853b3ffda7aa1831bf175c13356b210c73128c861f3aa93c3cc4015", size = 399716, upload-time = "2025-08-07T08:24:48.174Z" }, + { url = "https://files.pythonhosted.org/packages/40/73/176e46992461a1749686a2a441e24df51ff86b99c2d34bf39f2a5273b987/rpds_py-0.27.0-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6de6a7f622860af0146cb9ee148682ff4d0cea0b8fd3ad51ce4d40efb2f061d0", size = 517030, upload-time = "2025-08-07T08:24:49.52Z" }, + { url = "https://files.pythonhosted.org/packages/79/2a/7266c75840e8c6e70effeb0d38922a45720904f2cd695e68a0150e5407e2/rpds_py-0.27.0-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4045e2fc4b37ec4b48e8907a5819bdd3380708c139d7cc358f03a3653abedb89", size = 408448, upload-time = "2025-08-07T08:24:50.727Z" }, + { url = "https://files.pythonhosted.org/packages/e6/5f/a7efc572b8e235093dc6cf39f4dbc8a7f08e65fdbcec7ff4daeb3585eef1/rpds_py-0.27.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9da162b718b12c4219eeeeb68a5b7552fbc7aadedf2efee440f88b9c0e54b45d", size = 387320, upload-time = "2025-08-07T08:24:52.004Z" }, + { url = "https://files.pythonhosted.org/packages/a2/eb/9ff6bc92efe57cf5a2cb74dee20453ba444b6fdc85275d8c99e0d27239d1/rpds_py-0.27.0-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:0665be515767dc727ffa5f74bd2ef60b0ff85dad6bb8f50d91eaa6b5fb226f51", size = 407414, upload-time = "2025-08-07T08:24:53.664Z" }, + { url = "https://files.pythonhosted.org/packages/fb/bd/3b9b19b00d5c6e1bd0f418c229ab0f8d3b110ddf7ec5d9d689ef783d0268/rpds_py-0.27.0-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:203f581accef67300a942e49a37d74c12ceeef4514874c7cede21b012613ca2c", size = 420766, upload-time = "2025-08-07T08:24:55.917Z" }, + { url = "https://files.pythonhosted.org/packages/17/6b/521a7b1079ce16258c70805166e3ac6ec4ee2139d023fe07954dc9b2d568/rpds_py-0.27.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7873b65686a6471c0037139aa000d23fe94628e0daaa27b6e40607c90e3f5ec4", size = 562409, upload-time = "2025-08-07T08:24:57.17Z" }, + { url = "https://files.pythonhosted.org/packages/8b/bf/65db5bfb14ccc55e39de8419a659d05a2a9cd232f0a699a516bb0991da7b/rpds_py-0.27.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:249ab91ceaa6b41abc5f19513cb95b45c6f956f6b89f1fe3d99c81255a849f9e", size = 590793, upload-time = "2025-08-07T08:24:58.388Z" }, + { url = "https://files.pythonhosted.org/packages/db/b8/82d368b378325191ba7aae8f40f009b78057b598d4394d1f2cdabaf67b3f/rpds_py-0.27.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:d2f184336bc1d6abfaaa1262ed42739c3789b1e3a65a29916a615307d22ffd2e", size = 558178, upload-time = "2025-08-07T08:24:59.756Z" }, + { url = "https://files.pythonhosted.org/packages/f6/ff/f270bddbfbc3812500f8131b1ebbd97afd014cd554b604a3f73f03133a36/rpds_py-0.27.0-cp314-cp314-win32.whl", hash = "sha256:d3c622c39f04d5751408f5b801ecb527e6e0a471b367f420a877f7a660d583f6", size = 222355, upload-time = "2025-08-07T08:25:01.027Z" }, + { url = "https://files.pythonhosted.org/packages/bf/20/fdab055b1460c02ed356a0e0b0a78c1dd32dc64e82a544f7b31c9ac643dc/rpds_py-0.27.0-cp314-cp314-win_amd64.whl", hash = "sha256:cf824aceaeffff029ccfba0da637d432ca71ab21f13e7f6f5179cd88ebc77a8a", size = 234007, upload-time = "2025-08-07T08:25:02.268Z" }, + { url = "https://files.pythonhosted.org/packages/4d/a8/694c060005421797a3be4943dab8347c76c2b429a9bef68fb2c87c9e70c7/rpds_py-0.27.0-cp314-cp314-win_arm64.whl", hash = "sha256:86aca1616922b40d8ac1b3073a1ead4255a2f13405e5700c01f7c8d29a03972d", size = 223527, upload-time = "2025-08-07T08:25:03.45Z" }, + { url = "https://files.pythonhosted.org/packages/1e/f9/77f4c90f79d2c5ca8ce6ec6a76cb4734ee247de6b3a4f337e289e1f00372/rpds_py-0.27.0-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:341d8acb6724c0c17bdf714319c393bb27f6d23d39bc74f94221b3e59fc31828", size = 359469, upload-time = "2025-08-07T08:25:04.648Z" }, + { url = "https://files.pythonhosted.org/packages/c0/22/b97878d2f1284286fef4172069e84b0b42b546ea7d053e5fb7adb9ac6494/rpds_py-0.27.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:6b96b0b784fe5fd03beffff2b1533dc0d85e92bab8d1b2c24ef3a5dc8fac5669", size = 343960, upload-time = "2025-08-07T08:25:05.863Z" }, + { url = "https://files.pythonhosted.org/packages/b1/b0/dfd55b5bb480eda0578ae94ef256d3061d20b19a0f5e18c482f03e65464f/rpds_py-0.27.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0c431bfb91478d7cbe368d0a699978050d3b112d7f1d440a41e90faa325557fd", size = 380201, upload-time = "2025-08-07T08:25:07.513Z" }, + { url = "https://files.pythonhosted.org/packages/28/22/e1fa64e50d58ad2b2053077e3ec81a979147c43428de9e6de68ddf6aff4e/rpds_py-0.27.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:20e222a44ae9f507d0f2678ee3dd0c45ec1e930f6875d99b8459631c24058aec", size = 392111, upload-time = "2025-08-07T08:25:09.149Z" }, + { url = "https://files.pythonhosted.org/packages/49/f9/43ab7a43e97aedf6cea6af70fdcbe18abbbc41d4ae6cdec1bfc23bbad403/rpds_py-0.27.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:184f0d7b342967f6cda94a07d0e1fae177d11d0b8f17d73e06e36ac02889f303", size = 515863, upload-time = "2025-08-07T08:25:10.431Z" }, + { url = "https://files.pythonhosted.org/packages/38/9b/9bd59dcc636cd04d86a2d20ad967770bf348f5eb5922a8f29b547c074243/rpds_py-0.27.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a00c91104c173c9043bc46f7b30ee5e6d2f6b1149f11f545580f5d6fdff42c0b", size = 402398, upload-time = "2025-08-07T08:25:11.819Z" }, + { url = "https://files.pythonhosted.org/packages/71/bf/f099328c6c85667aba6b66fa5c35a8882db06dcd462ea214be72813a0dd2/rpds_py-0.27.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f7a37dd208f0d658e0487522078b1ed68cd6bce20ef4b5a915d2809b9094b410", size = 384665, upload-time = "2025-08-07T08:25:13.194Z" }, + { url = "https://files.pythonhosted.org/packages/a9/c5/9c1f03121ece6634818490bd3c8be2c82a70928a19de03467fb25a3ae2a8/rpds_py-0.27.0-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:92f3b3ec3e6008a1fe00b7c0946a170f161ac00645cde35e3c9a68c2475e8156", size = 400405, upload-time = "2025-08-07T08:25:14.417Z" }, + { url = "https://files.pythonhosted.org/packages/b5/b8/e25d54af3e63ac94f0c16d8fe143779fe71ff209445a0c00d0f6984b6b2c/rpds_py-0.27.0-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a1b3db5fae5cbce2131b7420a3f83553d4d89514c03d67804ced36161fe8b6b2", size = 413179, upload-time = "2025-08-07T08:25:15.664Z" }, + { url = "https://files.pythonhosted.org/packages/f9/d1/406b3316433fe49c3021546293a04bc33f1478e3ec7950215a7fce1a1208/rpds_py-0.27.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:5355527adaa713ab693cbce7c1e0ec71682f599f61b128cf19d07e5c13c9b1f1", size = 556895, upload-time = "2025-08-07T08:25:17.061Z" }, + { url = "https://files.pythonhosted.org/packages/5f/bc/3697c0c21fcb9a54d46ae3b735eb2365eea0c2be076b8f770f98e07998de/rpds_py-0.27.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:fcc01c57ce6e70b728af02b2401c5bc853a9e14eb07deda30624374f0aebfe42", size = 585464, upload-time = "2025-08-07T08:25:18.406Z" }, + { url = "https://files.pythonhosted.org/packages/63/09/ee1bb5536f99f42c839b177d552f6114aa3142d82f49cef49261ed28dbe0/rpds_py-0.27.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:3001013dae10f806380ba739d40dee11db1ecb91684febb8406a87c2ded23dae", size = 555090, upload-time = "2025-08-07T08:25:20.461Z" }, + { url = "https://files.pythonhosted.org/packages/7d/2c/363eada9e89f7059199d3724135a86c47082cbf72790d6ba2f336d146ddb/rpds_py-0.27.0-cp314-cp314t-win32.whl", hash = "sha256:0f401c369186a5743694dd9fc08cba66cf70908757552e1f714bfc5219c655b5", size = 218001, upload-time = "2025-08-07T08:25:21.761Z" }, + { url = "https://files.pythonhosted.org/packages/e2/3f/d6c216ed5199c9ef79e2a33955601f454ed1e7420a93b89670133bca5ace/rpds_py-0.27.0-cp314-cp314t-win_amd64.whl", hash = "sha256:8a1dca5507fa1337f75dcd5070218b20bc68cf8844271c923c1b79dfcbc20391", size = 230993, upload-time = "2025-08-07T08:25:23.34Z" }, + { url = "https://files.pythonhosted.org/packages/59/64/72ab5b911fdcc48058359b0e786e5363e3fde885156116026f1a2ba9a5b5/rpds_py-0.27.0-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:e6491658dd2569f05860bad645569145c8626ac231877b0fb2d5f9bcb7054089", size = 371658, upload-time = "2025-08-07T08:26:02.369Z" }, + { url = "https://files.pythonhosted.org/packages/6c/4b/90ff04b4da055db53d8fea57640d8d5d55456343a1ec9a866c0ecfe10fd1/rpds_py-0.27.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:bec77545d188f8bdd29d42bccb9191682a46fb2e655e3d1fb446d47c55ac3b8d", size = 355529, upload-time = "2025-08-07T08:26:03.83Z" }, + { url = "https://files.pythonhosted.org/packages/a4/be/527491fb1afcd86fc5ce5812eb37bc70428ee017d77fee20de18155c3937/rpds_py-0.27.0-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:25a4aebf8ca02bbb90a9b3e7a463bbf3bee02ab1c446840ca07b1695a68ce424", size = 382822, upload-time = "2025-08-07T08:26:05.52Z" }, + { url = "https://files.pythonhosted.org/packages/e0/a5/dcdb8725ce11e6d0913e6fcf782a13f4b8a517e8acc70946031830b98441/rpds_py-0.27.0-pp311-pypy311_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:44524b96481a4c9b8e6c46d6afe43fa1fb485c261e359fbe32b63ff60e3884d8", size = 397233, upload-time = "2025-08-07T08:26:07.179Z" }, + { url = "https://files.pythonhosted.org/packages/33/f9/0947920d1927e9f144660590cc38cadb0795d78fe0d9aae0ef71c1513b7c/rpds_py-0.27.0-pp311-pypy311_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:45d04a73c54b6a5fd2bab91a4b5bc8b426949586e61340e212a8484919183859", size = 514892, upload-time = "2025-08-07T08:26:08.622Z" }, + { url = "https://files.pythonhosted.org/packages/1d/ed/d1343398c1417c68f8daa1afce56ef6ce5cc587daaf98e29347b00a80ff2/rpds_py-0.27.0-pp311-pypy311_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:343cf24de9ed6c728abefc5d5c851d5de06497caa7ac37e5e65dd572921ed1b5", size = 402733, upload-time = "2025-08-07T08:26:10.433Z" }, + { url = "https://files.pythonhosted.org/packages/1d/0b/646f55442cd14014fb64d143428f25667a100f82092c90087b9ea7101c74/rpds_py-0.27.0-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7aed8118ae20515974650d08eb724150dc2e20c2814bcc307089569995e88a14", size = 384447, upload-time = "2025-08-07T08:26:11.847Z" }, + { url = "https://files.pythonhosted.org/packages/4b/15/0596ef7529828e33a6c81ecf5013d1dd33a511a3e0be0561f83079cda227/rpds_py-0.27.0-pp311-pypy311_pp73-manylinux_2_31_riscv64.whl", hash = "sha256:af9d4fd79ee1cc8e7caf693ee02737daabfc0fcf2773ca0a4735b356c8ad6f7c", size = 402502, upload-time = "2025-08-07T08:26:13.537Z" }, + { url = "https://files.pythonhosted.org/packages/c3/8d/986af3c42f8454a6cafff8729d99fb178ae9b08a9816325ac7a8fa57c0c0/rpds_py-0.27.0-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f0396e894bd1e66c74ecbc08b4f6a03dc331140942c4b1d345dd131b68574a60", size = 416651, upload-time = "2025-08-07T08:26:14.923Z" }, + { url = "https://files.pythonhosted.org/packages/e9/9a/b4ec3629b7b447e896eec574469159b5b60b7781d3711c914748bf32de05/rpds_py-0.27.0-pp311-pypy311_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:59714ab0a5af25d723d8e9816638faf7f4254234decb7d212715c1aa71eee7be", size = 559460, upload-time = "2025-08-07T08:26:16.295Z" }, + { url = "https://files.pythonhosted.org/packages/61/63/d1e127b40c3e4733b3a6f26ae7a063cdf2bc1caa5272c89075425c7d397a/rpds_py-0.27.0-pp311-pypy311_pp73-musllinux_1_2_i686.whl", hash = "sha256:88051c3b7d5325409f433c5a40328fcb0685fc04e5db49ff936e910901d10114", size = 588072, upload-time = "2025-08-07T08:26:17.776Z" }, + { url = "https://files.pythonhosted.org/packages/04/7e/8ffc71a8f6833d9c9fb999f5b0ee736b8b159fd66968e05c7afc2dbcd57e/rpds_py-0.27.0-pp311-pypy311_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:181bc29e59e5e5e6e9d63b143ff4d5191224d355e246b5a48c88ce6b35c4e466", size = 555083, upload-time = "2025-08-07T08:26:19.301Z" }, ] [[package]] @@ -2664,42 +2671,42 @@ wheels = [ [[package]] name = "uv" -version = "0.8.4" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/71/05/779581d8e5cd8d12dc3e2297280a03293f7b465bb5f53308479e508c5c44/uv-0.8.4.tar.gz", hash = "sha256:2ab21c32a28dbe434c9074f899ed8084955f7b09ac5e7ffac548d3454f77516f", size = 3442716, upload-time = "2025-07-30T17:10:56.404Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/96/10/4d52b081defca3cfb4a11d6af3af4314fe7f289ba19e40d6cfab778f9257/uv-0.8.4-py3-none-linux_armv6l.whl", hash = "sha256:f9a5da616ca0d2bbe79367db9cf339cbaf1affee5d6b130a3be2779a917c14fa", size = 18077025, upload-time = "2025-07-30T17:10:13.016Z" }, - { url = "https://files.pythonhosted.org/packages/36/fa/7847373d214de987e96ef6b820a4ed2fa5e1c392ecc73cd53e94013d6074/uv-0.8.4-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:4d8422b3058998d87fee46d4d1a437e202407cafca8b8ac69e01c6479fbe0271", size = 18143542, upload-time = "2025-07-30T17:10:18.006Z" }, - { url = "https://files.pythonhosted.org/packages/16/39/7d4b68132868c550ae97c3b2c348c55db47a987dff05ab0e5f577bf0e197/uv-0.8.4-py3-none-macosx_11_0_arm64.whl", hash = "sha256:edc813645348665a3b4716a7d5e961cf7c8d1d3bfb9d907a4f18cf87c712a430", size = 16860749, upload-time = "2025-07-30T17:10:20.417Z" }, - { url = "https://files.pythonhosted.org/packages/e3/8f/f703e4ba41aae195d4958b701c2ee6cdbbbb8cdccb082845d6abfe834cf9/uv-0.8.4-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:c2323e915ae562db4ebcdf5e20d3dd37a14959d07cc54939d86ab0dcdbf08f58", size = 17469507, upload-time = "2025-07-30T17:10:22.779Z" }, - { url = "https://files.pythonhosted.org/packages/59/f8/9366ceeb63f9dd6aa11375047762c1033d36521722e748b65a24e435f459/uv-0.8.4-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:96d7a68c360383d638c283811d57558fbf7b5f769ff4bdbc99ee2a3bf9a6e574", size = 17766700, upload-time = "2025-07-30T17:10:24.903Z" }, - { url = "https://files.pythonhosted.org/packages/f2/e3/190eb0ca91b8a0e5f80f93aeb7924b12be89656066170d6e1244e90c5e80/uv-0.8.4-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:385dec5a0c0909d5a24af5b02db24b49b025cbed59c6225e4c794ff40069d9aa", size = 18432996, upload-time = "2025-07-30T17:10:27.239Z" }, - { url = "https://files.pythonhosted.org/packages/ab/f6/b5fc5fe6e93e0294cbd8ba228d10b12e46a5e27b143565e868da758e0209/uv-0.8.4-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:b2230310ca303328c9fd351044fb81349f3ccfaa2863f135d37bfcee707adfd1", size = 19842168, upload-time = "2025-07-30T17:10:29.958Z" }, - { url = "https://files.pythonhosted.org/packages/f5/f0/d01779df4ac2ae39bf440c97f53346f1b9eef17cc84a45ed66206e348650/uv-0.8.4-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:86d64c66993eb0d9821caea27920175a27cd24df1eba8a340d8b3ae4074fac77", size = 19497445, upload-time = "2025-07-30T17:10:32.064Z" }, - { url = "https://files.pythonhosted.org/packages/80/ca/48c78393cb3a73940e768b74f74c30ca7719de6f83457a125b9cfa0c37e0/uv-0.8.4-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:624cf5b7bdc5cc0253115fefaad40008205d4acf34b77b294479dfe4eacb9697", size = 18852025, upload-time = "2025-07-30T17:10:34.34Z" }, - { url = "https://files.pythonhosted.org/packages/42/e2/5cf11c85fb48276b49979ea06e92c1e95524e1e4c5bccbd591a334c8de68/uv-0.8.4-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f9cd287982f62419f98ca7182fbbc2fd0fad1a04008b956a88eb85ce1d522611", size = 18806944, upload-time = "2025-07-30T17:10:36.819Z" }, - { url = "https://files.pythonhosted.org/packages/1c/b1/773dcd5ef4947a5bd7c183f1cc8afb9e761488ff1b48b46cb0d95bc5c8cf/uv-0.8.4-py3-none-manylinux_2_28_aarch64.whl", hash = "sha256:e6fa3754a2b965dceecfce8c38cacf7cd6b76a2787b9e189cf33acdb64a7472a", size = 17706599, upload-time = "2025-07-30T17:10:38.976Z" }, - { url = "https://files.pythonhosted.org/packages/e6/8f/20dcb6aaa9c9d7e16320b5143b1fdaa5fd1ebc42a99e2d5f4283aafc59f1/uv-0.8.4-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:9f2a7042553e85c66884a6a3c1b88e116bc5fe5e5d1c9b62f025b1de41534734", size = 18564686, upload-time = "2025-07-30T17:10:41.163Z" }, - { url = "https://files.pythonhosted.org/packages/8a/19/9f9df99259d6725fc269d5394606919f32c3e0d21f486277c040cb7c5dad/uv-0.8.4-py3-none-musllinux_1_1_armv7l.whl", hash = "sha256:2c80470d7253bd26c5990f4914cfddc68a6bb4da7c7da316a29e99feafe272a1", size = 17722213, upload-time = "2025-07-30T17:10:43.354Z" }, - { url = "https://files.pythonhosted.org/packages/00/f4/358576eea98eb4ba58135690a60f8052dbd8b50173a5c0e93e59c8797c2c/uv-0.8.4-py3-none-musllinux_1_1_i686.whl", hash = "sha256:b90eb86019ff92922dea54b8772074909ce7ab3359b2e8f8f3fe4d0658d3a898", size = 17997363, upload-time = "2025-07-30T17:10:45.631Z" }, - { url = "https://files.pythonhosted.org/packages/51/0f/9e5ff7d73846d8c924a5ef262dee247b453b7b2bd2ba5db1a819c72bd176/uv-0.8.4-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:cad63a02a735ba591679d713376767fc7649ad1e7097a95d0d267a68c2e803fc", size = 18954586, upload-time = "2025-07-30T17:10:47.789Z" }, - { url = "https://files.pythonhosted.org/packages/3c/fa/58c416c634253bdd7ec50baa5d79010f887453425a62e6a23f9668a75305/uv-0.8.4-py3-none-win32.whl", hash = "sha256:b83cd9eeb4c63ab69c6e8d0e26e57b5a9a8b1dca4015f4ddf088ed4a234e7018", size = 17907610, upload-time = "2025-07-30T17:10:49.966Z" }, - { url = "https://files.pythonhosted.org/packages/76/8e/2d6f5bce0f41074122caed1672f90f7ed5df2bd9827c8723c73a657bea7b/uv-0.8.4-py3-none-win_amd64.whl", hash = "sha256:ad056c8f6568d9f495e402753e79a092f28d513e6b5146d1c8dc2bdea668adb1", size = 19704945, upload-time = "2025-07-30T17:10:52.145Z" }, - { url = "https://files.pythonhosted.org/packages/58/de/196e862af4c3b2ff8cb4a7a3ad38ecf0306fa87d03ec9275f16e2f5dc416/uv-0.8.4-py3-none-win_arm64.whl", hash = "sha256:41f3a22550811bf7a0980b3d4dfce09e2c93aec7c42c92313ae3d3d0b97e1054", size = 18316402, upload-time = "2025-07-30T17:10:54.507Z" }, +version = "0.8.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b5/3b/1140dbbca9fb3ca32be38e01c670a5980a4ee4874366d70438317876d40a/uv-0.8.6.tar.gz", hash = "sha256:4d4e042f6bd9f143094051a05de758684028f451e563846cbc0c6f505b530cca", size = 3463644, upload-time = "2025-08-07T15:43:34.206Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/71/64/a96f40f95626c6e353e66f6bc5a5ca7c1399e95caf0dcb56cae38754e073/uv-0.8.6-py3-none-linux_armv6l.whl", hash = "sha256:d96ff3a1d06a6a00ed94dfb2996228153b3b5bfc892174b7556216ab872a91b1", size = 18437310, upload-time = "2025-08-07T15:42:49.611Z" }, + { url = "https://files.pythonhosted.org/packages/41/30/b2fed99d5a6b16410669f223767f6d65bc6595858622f5f36386892ed963/uv-0.8.6-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:fdceb1ef554df0ddc620bfe83fdcf740829e489c62f78ba1f089abd62c71c63e", size = 18615884, upload-time = "2025-08-07T15:42:53.452Z" }, + { url = "https://files.pythonhosted.org/packages/d7/82/a53684eadb9cb169eab32ab71f2bdaf7c382819d6de44d4e8df91ca14a00/uv-0.8.6-py3-none-macosx_11_0_arm64.whl", hash = "sha256:7c1f48279ff61940143c78b969094e13324988eabcfcd4799f4350d9d36c1d48", size = 17173005, upload-time = "2025-08-07T15:42:55.571Z" }, + { url = "https://files.pythonhosted.org/packages/e7/4a/2890d9ccaf4b383fea43ae6362252870dcd97dda7412f34f20d80ccf7a39/uv-0.8.6-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:1913f5627c57076c88dd38b0173bdb006ae9b8dbd92b1798a1acc9d744c1a7cc", size = 17813305, upload-time = "2025-08-07T15:42:57.998Z" }, + { url = "https://files.pythonhosted.org/packages/9b/c3/33a10049728ffbcde673b75b9a73cd61bfab5e1598d935d1f1b2556b07a4/uv-0.8.6-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7796acc3c5b84d5ee5e10cc6cf92eb61c19f6551855d0aa89ef5925e4a371fbf", size = 18159834, upload-time = "2025-08-07T15:43:00.207Z" }, + { url = "https://files.pythonhosted.org/packages/81/28/ff884f7007a6b9d0e3368dbe4ae7d28acacbaaf1b3a583640e5af6dc5360/uv-0.8.6-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:57a98367bfad38e870e1a8a6626464796ffcee6e937d429fbd7b25ddf46bb36f", size = 18954223, upload-time = "2025-08-07T15:43:03.577Z" }, + { url = "https://files.pythonhosted.org/packages/78/1d/a4ed2da913ecacc1c976e97dff905979c13359834eeeac8bbaf5ed0b2fca/uv-0.8.6-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:2ac28509db2e52613a59264bdb150d13274ed13e5b305f7e274da8cd83033985", size = 20215802, upload-time = "2025-08-07T15:43:06.181Z" }, + { url = "https://files.pythonhosted.org/packages/2c/12/c9ca1cc8bdbecd54db4a7c1a44808f15271da60838dfa9f180ce8171407a/uv-0.8.6-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:deab2ce32d2dd7a1c0de459aa23470c60feb0ea24e67c9c5c5988d8bf4eb4a09", size = 19898210, upload-time = "2025-08-07T15:43:09.008Z" }, + { url = "https://files.pythonhosted.org/packages/c0/15/e10347768b2929ae9c65abbfd0867a736e6227f6d63da1f86fe6bdcbcdca/uv-0.8.6-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5b201ebc1c5c76c3a415fa4edcb25a0e06263d2255319d6d52275c775e926e23", size = 19247208, upload-time = "2025-08-07T15:43:11.578Z" }, + { url = "https://files.pythonhosted.org/packages/62/8d/dc290df05d1820d003f30e2fb7853496eec43bcb986c5e35aaea2f5343d3/uv-0.8.6-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6acdc77099906ba64bc1b725bef973c10905d7e9596d1b25f271db772bc9e8e4", size = 19261881, upload-time = "2025-08-07T15:43:13.815Z" }, + { url = "https://files.pythonhosted.org/packages/20/bd/6c3b9c87e4ed323f72de6ece7d51a6179091f0ff6e0c9c6ed29e28efe17c/uv-0.8.6-py3-none-manylinux_2_28_aarch64.whl", hash = "sha256:4e81380549151e34ae96d56499438444ba58591ca9f2fc6ba0a867152601849e", size = 18037135, upload-time = "2025-08-07T15:43:15.941Z" }, + { url = "https://files.pythonhosted.org/packages/7d/e1/b3e825ad9cc3f03f0f3e232286f91aef985d8029db69fd7091c2f332212b/uv-0.8.6-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:c9de4adac36a62e4bddd959ce65fb4bb09b0cbfd95946d50390f2a9c186ecb9c", size = 19040739, upload-time = "2025-08-07T15:43:18.092Z" }, + { url = "https://files.pythonhosted.org/packages/c5/14/921e2e7b2a4be0bac17f9d04a126546b89828bb33aa56368af7f00538fe3/uv-0.8.6-py3-none-musllinux_1_1_armv7l.whl", hash = "sha256:993af2c295856c5ca053678a8dadc11ce2f85485513ed1568c16e98d5dfa88bf", size = 18060742, upload-time = "2025-08-07T15:43:20.39Z" }, + { url = "https://files.pythonhosted.org/packages/81/54/0b1ecc64353725b62f02d3739a67a567faa70c76c4ea19a21253df1c4d99/uv-0.8.6-py3-none-musllinux_1_1_i686.whl", hash = "sha256:132e73f1e9fe05edc6c06c00416f7c721c48298786fd7293be6c584793170bbc", size = 18430300, upload-time = "2025-08-07T15:43:22.797Z" }, + { url = "https://files.pythonhosted.org/packages/da/be/a1a249eacb9b1e397292106250490ec1546a90c0e19de19f0b36f52aecea/uv-0.8.6-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:ee67acf1b211be2cfbeaec16cde13c8325810d32ff85963a9dedd1f9d7c61ef7", size = 19407124, upload-time = "2025-08-07T15:43:25.915Z" }, + { url = "https://files.pythonhosted.org/packages/11/18/552bb94bb931ea9d09a0e98e5c3d8cefc8c8db25549af88d1484e52d6cdd/uv-0.8.6-py3-none-win32.whl", hash = "sha256:e35cc1ef79d3dce2b6aeffbfb280d02d5ad741d4ca07874bdf0a4d85c841d9de", size = 18324229, upload-time = "2025-08-07T15:43:28.029Z" }, + { url = "https://files.pythonhosted.org/packages/fd/df/b7d1171579e2cc821aafc38a86393104e5426ac1ebc4e95be79ac705a11f/uv-0.8.6-py3-none-win_amd64.whl", hash = "sha256:37227aaf1e41c7eda3d7f0028e747a2a2eed3f3506b0adc121a4366e8281115b", size = 20279856, upload-time = "2025-08-07T15:43:30.07Z" }, + { url = "https://files.pythonhosted.org/packages/09/1b/2629d605e101db6a52397e6ea8859a51af0207cf254051b2a621c683ee07/uv-0.8.6-py3-none-win_arm64.whl", hash = "sha256:0b524de39f317bd8733c38cf100b6f8091d44e06b23f7752523ad1ad1454ede3", size = 18839643, upload-time = "2025-08-07T15:43:32.332Z" }, ] [[package]] name = "virtualenv" -version = "20.33.0" +version = "20.33.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "distlib" }, { name = "filelock" }, { name = "platformdirs" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/db/2e/8a70dcbe8bf15213a08f9b0325ede04faca5d362922ae0d62ef0fa4b069d/virtualenv-20.33.0.tar.gz", hash = "sha256:47e0c0d2ef1801fce721708ccdf2a28b9403fa2307c3268aebd03225976f61d2", size = 6082069, upload-time = "2025-08-03T08:09:19.014Z" } +sdist = { url = "https://files.pythonhosted.org/packages/8b/60/4f20960df6c7b363a18a55ab034c8f2bcd5d9770d1f94f9370ec104c1855/virtualenv-20.33.1.tar.gz", hash = "sha256:1b44478d9e261b3fb8baa5e74a0ca3bc0e05f21aa36167bf9cbf850e542765b8", size = 6082160, upload-time = "2025-08-05T16:10:55.605Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/43/87/b22cf40cdf7e2b2bf83f38a94d2c90c5ad6c304896e5a12d0c08a602eb59/virtualenv-20.33.0-py3-none-any.whl", hash = "sha256:106b6baa8ab1b526d5a9b71165c85c456fbd49b16976c88e2bc9352ee3bc5d3f", size = 6060205, upload-time = "2025-08-03T08:09:16.674Z" }, + { url = "https://files.pythonhosted.org/packages/ca/ff/ded57ac5ff40a09e6e198550bab075d780941e0b0f83cbeabd087c59383a/virtualenv-20.33.1-py3-none-any.whl", hash = "sha256:07c19bc66c11acab6a5958b815cbcee30891cd1c2ccf53785a28651a0d8d8a67", size = 6060362, upload-time = "2025-08-05T16:10:52.81Z" }, ] [[package]] From e4bda5dae97a374d2c5feba1759f67610e07d4c1 Mon Sep 17 00:00:00 2001 From: Nick Murphy Date: Mon, 11 Aug 2025 17:46:07 -0400 Subject: [PATCH 448/521] Update labeler (#3092) --- .github/labeler.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/labeler.yml b/.github/labeler.yml index 3e53fcf664..c5a04d16ff 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -197,8 +197,6 @@ release: - changed-files: - any-glob-to-any-file: [ '.github/workflows/*weekly*.yml', - 'docs/conf.py', - 'noxfile.py', ] 'static type checking': From e0ecab55eac64ed059f3543e2345cc0518d2c462 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 12 Aug 2025 16:18:41 -0400 Subject: [PATCH 449/521] Bump actions/checkout from 4 to 5 in /.github/workflows (#3093) Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 5. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v4...v5) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: '5' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/check-author-included.yml | 2 +- .github/workflows/ci.yml | 2 +- .github/workflows/create-release-issue.yml | 2 +- .github/workflows/linkcheck.yml | 2 +- .github/workflows/prepare-release-pr.yml | 2 +- .github/workflows/publish-to-pypi.yml | 2 +- .github/workflows/update-pinned-reqs.yml | 2 +- .github/workflows/weekly.yml | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/check-author-included.yml b/.github/workflows/check-author-included.yml index f9f9846415..de5ffde5fe 100644 --- a/.github/workflows/check-author-included.yml +++ b/.github/workflows/check-author-included.yml @@ -13,7 +13,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: persist-credentials: false diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d6d739ef28..422988f76f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -82,7 +82,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: persist-credentials: false diff --git a/.github/workflows/create-release-issue.yml b/.github/workflows/create-release-issue.yml index e079695b17..f41de5874b 100644 --- a/.github/workflows/create-release-issue.yml +++ b/.github/workflows/create-release-issue.yml @@ -14,7 +14,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: persist-credentials: false diff --git a/.github/workflows/linkcheck.yml b/.github/workflows/linkcheck.yml index f85619e4dd..d933b69600 100644 --- a/.github/workflows/linkcheck.yml +++ b/.github/workflows/linkcheck.yml @@ -27,7 +27,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: persist-credentials: false diff --git a/.github/workflows/prepare-release-pr.yml b/.github/workflows/prepare-release-pr.yml index fa4812cdb8..e6ee0a90fd 100644 --- a/.github/workflows/prepare-release-pr.yml +++ b/.github/workflows/prepare-release-pr.yml @@ -38,7 +38,7 @@ jobs: DOI: ${{ github.event.inputs.doi }} - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: persist-credentials: false diff --git a/.github/workflows/publish-to-pypi.yml b/.github/workflows/publish-to-pypi.yml index 39cff5876d..acf9d91c47 100644 --- a/.github/workflows/publish-to-pypi.yml +++ b/.github/workflows/publish-to-pypi.yml @@ -15,7 +15,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: persist-credentials: false diff --git a/.github/workflows/update-pinned-reqs.yml b/.github/workflows/update-pinned-reqs.yml index 2617c4c3da..bc96095ae2 100644 --- a/.github/workflows/update-pinned-reqs.yml +++ b/.github/workflows/update-pinned-reqs.yml @@ -14,7 +14,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: persist-credentials: false diff --git a/.github/workflows/weekly.yml b/.github/workflows/weekly.yml index 2884ed6df2..4519023981 100644 --- a/.github/workflows/weekly.yml +++ b/.github/workflows/weekly.yml @@ -148,7 +148,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: persist-credentials: false From 6899c30a492b7cd60bb01bde9224b1f15d439bd5 Mon Sep 17 00:00:00 2001 From: "plasmapy-requirements-bot[bot]" <134649236+plasmapy-requirements-bot[bot]@users.noreply.github.com> Date: Fri, 15 Aug 2025 09:55:07 -0400 Subject: [PATCH 450/521] Update requirements with 'nox -s requirements' (#3095) Co-authored-by: namurphy <8931994+namurphy@users.noreply.github.com> --- uv.lock | 581 ++++++++++++++++++++++++++++++-------------------------- 1 file changed, 308 insertions(+), 273 deletions(-) diff --git a/uv.lock b/uv.lock index ef756e292b..a089d5892a 100644 --- a/uv.lock +++ b/uv.lock @@ -80,11 +80,11 @@ wheels = [ [[package]] name = "astropy-iers-data" -version = "0.2025.8.4.0.42.59" +version = "0.2025.8.11.0.41.9" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/07/f7/d6404e1a96eb71e7f5df2f52e135ceb15b43c1a7aff3173ff128e68c3fda/astropy_iers_data-0.2025.8.4.0.42.59.tar.gz", hash = "sha256:a6e8723fe962e2b4103aa7837d021e6857d0bf2b4de28a891cd4c8d1919d4129", size = 1904207, upload-time = "2025-08-04T00:43:44.386Z" } +sdist = { url = "https://files.pythonhosted.org/packages/92/97/e4bcef70ee3a3a76d6888ac5da07ceabba7ed6bc0414a79fbdb1383fd5a5/astropy_iers_data-0.2025.8.11.0.41.9.tar.gz", hash = "sha256:029c3237993fa9689f8543872dfe750393227261111edad8173fdd06d59f1c84", size = 1904623, upload-time = "2025-08-11T00:41:48.52Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/eb/4e/905209e3b347a9d781623ac092ce7fc6ab55b67ae09d46fd5274b2d6eeba/astropy_iers_data-0.2025.8.4.0.42.59-py3-none-any.whl", hash = "sha256:b3cc6795083e7efed1d335d24534f0ca204e5950132e41a24b178ea1d659ded9", size = 1959667, upload-time = "2025-08-04T00:43:42.822Z" }, + { url = "https://files.pythonhosted.org/packages/3d/c2/419f11d191c4c0e880c07550d2c764e3bb79fe6dec492a0d850808d31cc3/astropy_iers_data-0.2025.8.11.0.41.9-py3-none-any.whl", hash = "sha256:e5419d191259932413f89609315ad9f185a2977fac219333e23476d4491bfabd", size = 1960190, upload-time = "2025-08-11T00:41:46.797Z" }, ] [[package]] @@ -200,50 +200,55 @@ wheels = [ [[package]] name = "charset-normalizer" -version = "3.4.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e4/33/89c2ced2b67d1c2a61c19c6751aa8902d46ce3dacb23600a283619f5a12d/charset_normalizer-3.4.2.tar.gz", hash = "sha256:5baececa9ecba31eff645232d59845c07aa030f0c81ee70184a90d35099a0e63", size = 126367, upload-time = "2025-05-02T08:34:42.01Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/05/85/4c40d00dcc6284a1c1ad5de5e0996b06f39d8232f1031cd23c2f5c07ee86/charset_normalizer-3.4.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:be1e352acbe3c78727a16a455126d9ff83ea2dfdcbc83148d2982305a04714c2", size = 198794, upload-time = "2025-05-02T08:32:11.945Z" }, - { url = "https://files.pythonhosted.org/packages/41/d9/7a6c0b9db952598e97e93cbdfcb91bacd89b9b88c7c983250a77c008703c/charset_normalizer-3.4.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aa88ca0b1932e93f2d961bf3addbb2db902198dca337d88c89e1559e066e7645", size = 142846, upload-time = "2025-05-02T08:32:13.946Z" }, - { url = "https://files.pythonhosted.org/packages/66/82/a37989cda2ace7e37f36c1a8ed16c58cf48965a79c2142713244bf945c89/charset_normalizer-3.4.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d524ba3f1581b35c03cb42beebab4a13e6cdad7b36246bd22541fa585a56cccd", size = 153350, upload-time = "2025-05-02T08:32:15.873Z" }, - { url = "https://files.pythonhosted.org/packages/df/68/a576b31b694d07b53807269d05ec3f6f1093e9545e8607121995ba7a8313/charset_normalizer-3.4.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28a1005facc94196e1fb3e82a3d442a9d9110b8434fc1ded7a24a2983c9888d8", size = 145657, upload-time = "2025-05-02T08:32:17.283Z" }, - { url = "https://files.pythonhosted.org/packages/92/9b/ad67f03d74554bed3aefd56fe836e1623a50780f7c998d00ca128924a499/charset_normalizer-3.4.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fdb20a30fe1175ecabed17cbf7812f7b804b8a315a25f24678bcdf120a90077f", size = 147260, upload-time = "2025-05-02T08:32:18.807Z" }, - { url = "https://files.pythonhosted.org/packages/a6/e6/8aebae25e328160b20e31a7e9929b1578bbdc7f42e66f46595a432f8539e/charset_normalizer-3.4.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0f5d9ed7f254402c9e7d35d2f5972c9bbea9040e99cd2861bd77dc68263277c7", size = 149164, upload-time = "2025-05-02T08:32:20.333Z" }, - { url = "https://files.pythonhosted.org/packages/8b/f2/b3c2f07dbcc248805f10e67a0262c93308cfa149a4cd3d1fe01f593e5fd2/charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:efd387a49825780ff861998cd959767800d54f8308936b21025326de4b5a42b9", size = 144571, upload-time = "2025-05-02T08:32:21.86Z" }, - { url = "https://files.pythonhosted.org/packages/60/5b/c3f3a94bc345bc211622ea59b4bed9ae63c00920e2e8f11824aa5708e8b7/charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:f0aa37f3c979cf2546b73e8222bbfa3dc07a641585340179d768068e3455e544", size = 151952, upload-time = "2025-05-02T08:32:23.434Z" }, - { url = "https://files.pythonhosted.org/packages/e2/4d/ff460c8b474122334c2fa394a3f99a04cf11c646da895f81402ae54f5c42/charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:e70e990b2137b29dc5564715de1e12701815dacc1d056308e2b17e9095372a82", size = 155959, upload-time = "2025-05-02T08:32:24.993Z" }, - { url = "https://files.pythonhosted.org/packages/a2/2b/b964c6a2fda88611a1fe3d4c400d39c66a42d6c169c924818c848f922415/charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:0c8c57f84ccfc871a48a47321cfa49ae1df56cd1d965a09abe84066f6853b9c0", size = 153030, upload-time = "2025-05-02T08:32:26.435Z" }, - { url = "https://files.pythonhosted.org/packages/59/2e/d3b9811db26a5ebf444bc0fa4f4be5aa6d76fc6e1c0fd537b16c14e849b6/charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:6b66f92b17849b85cad91259efc341dce9c1af48e2173bf38a85c6329f1033e5", size = 148015, upload-time = "2025-05-02T08:32:28.376Z" }, - { url = "https://files.pythonhosted.org/packages/90/07/c5fd7c11eafd561bb51220d600a788f1c8d77c5eef37ee49454cc5c35575/charset_normalizer-3.4.2-cp311-cp311-win32.whl", hash = "sha256:daac4765328a919a805fa5e2720f3e94767abd632ae410a9062dff5412bae65a", size = 98106, upload-time = "2025-05-02T08:32:30.281Z" }, - { url = "https://files.pythonhosted.org/packages/a8/05/5e33dbef7e2f773d672b6d79f10ec633d4a71cd96db6673625838a4fd532/charset_normalizer-3.4.2-cp311-cp311-win_amd64.whl", hash = "sha256:e53efc7c7cee4c1e70661e2e112ca46a575f90ed9ae3fef200f2a25e954f4b28", size = 105402, upload-time = "2025-05-02T08:32:32.191Z" }, - { url = "https://files.pythonhosted.org/packages/d7/a4/37f4d6035c89cac7930395a35cc0f1b872e652eaafb76a6075943754f095/charset_normalizer-3.4.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:0c29de6a1a95f24b9a1aa7aefd27d2487263f00dfd55a77719b530788f75cff7", size = 199936, upload-time = "2025-05-02T08:32:33.712Z" }, - { url = "https://files.pythonhosted.org/packages/ee/8a/1a5e33b73e0d9287274f899d967907cd0bf9c343e651755d9307e0dbf2b3/charset_normalizer-3.4.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cddf7bd982eaa998934a91f69d182aec997c6c468898efe6679af88283b498d3", size = 143790, upload-time = "2025-05-02T08:32:35.768Z" }, - { url = "https://files.pythonhosted.org/packages/66/52/59521f1d8e6ab1482164fa21409c5ef44da3e9f653c13ba71becdd98dec3/charset_normalizer-3.4.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fcbe676a55d7445b22c10967bceaaf0ee69407fbe0ece4d032b6eb8d4565982a", size = 153924, upload-time = "2025-05-02T08:32:37.284Z" }, - { url = "https://files.pythonhosted.org/packages/86/2d/fb55fdf41964ec782febbf33cb64be480a6b8f16ded2dbe8db27a405c09f/charset_normalizer-3.4.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d41c4d287cfc69060fa91cae9683eacffad989f1a10811995fa309df656ec214", size = 146626, upload-time = "2025-05-02T08:32:38.803Z" }, - { url = "https://files.pythonhosted.org/packages/8c/73/6ede2ec59bce19b3edf4209d70004253ec5f4e319f9a2e3f2f15601ed5f7/charset_normalizer-3.4.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4e594135de17ab3866138f496755f302b72157d115086d100c3f19370839dd3a", size = 148567, upload-time = "2025-05-02T08:32:40.251Z" }, - { url = "https://files.pythonhosted.org/packages/09/14/957d03c6dc343c04904530b6bef4e5efae5ec7d7990a7cbb868e4595ee30/charset_normalizer-3.4.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cf713fe9a71ef6fd5adf7a79670135081cd4431c2943864757f0fa3a65b1fafd", size = 150957, upload-time = "2025-05-02T08:32:41.705Z" }, - { url = "https://files.pythonhosted.org/packages/0d/c8/8174d0e5c10ccebdcb1b53cc959591c4c722a3ad92461a273e86b9f5a302/charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a370b3e078e418187da8c3674eddb9d983ec09445c99a3a263c2011993522981", size = 145408, upload-time = "2025-05-02T08:32:43.709Z" }, - { url = "https://files.pythonhosted.org/packages/58/aa/8904b84bc8084ac19dc52feb4f5952c6df03ffb460a887b42615ee1382e8/charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:a955b438e62efdf7e0b7b52a64dc5c3396e2634baa62471768a64bc2adb73d5c", size = 153399, upload-time = "2025-05-02T08:32:46.197Z" }, - { url = "https://files.pythonhosted.org/packages/c2/26/89ee1f0e264d201cb65cf054aca6038c03b1a0c6b4ae998070392a3ce605/charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:7222ffd5e4de8e57e03ce2cef95a4c43c98fcb72ad86909abdfc2c17d227fc1b", size = 156815, upload-time = "2025-05-02T08:32:48.105Z" }, - { url = "https://files.pythonhosted.org/packages/fd/07/68e95b4b345bad3dbbd3a8681737b4338ff2c9df29856a6d6d23ac4c73cb/charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:bee093bf902e1d8fc0ac143c88902c3dfc8941f7ea1d6a8dd2bcb786d33db03d", size = 154537, upload-time = "2025-05-02T08:32:49.719Z" }, - { url = "https://files.pythonhosted.org/packages/77/1a/5eefc0ce04affb98af07bc05f3bac9094513c0e23b0562d64af46a06aae4/charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:dedb8adb91d11846ee08bec4c8236c8549ac721c245678282dcb06b221aab59f", size = 149565, upload-time = "2025-05-02T08:32:51.404Z" }, - { url = "https://files.pythonhosted.org/packages/37/a0/2410e5e6032a174c95e0806b1a6585eb21e12f445ebe239fac441995226a/charset_normalizer-3.4.2-cp312-cp312-win32.whl", hash = "sha256:db4c7bf0e07fc3b7d89ac2a5880a6a8062056801b83ff56d8464b70f65482b6c", size = 98357, upload-time = "2025-05-02T08:32:53.079Z" }, - { url = "https://files.pythonhosted.org/packages/6c/4f/c02d5c493967af3eda9c771ad4d2bbc8df6f99ddbeb37ceea6e8716a32bc/charset_normalizer-3.4.2-cp312-cp312-win_amd64.whl", hash = "sha256:5a9979887252a82fefd3d3ed2a8e3b937a7a809f65dcb1e068b090e165bbe99e", size = 105776, upload-time = "2025-05-02T08:32:54.573Z" }, - { url = "https://files.pythonhosted.org/packages/ea/12/a93df3366ed32db1d907d7593a94f1fe6293903e3e92967bebd6950ed12c/charset_normalizer-3.4.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:926ca93accd5d36ccdabd803392ddc3e03e6d4cd1cf17deff3b989ab8e9dbcf0", size = 199622, upload-time = "2025-05-02T08:32:56.363Z" }, - { url = "https://files.pythonhosted.org/packages/04/93/bf204e6f344c39d9937d3c13c8cd5bbfc266472e51fc8c07cb7f64fcd2de/charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eba9904b0f38a143592d9fc0e19e2df0fa2e41c3c3745554761c5f6447eedabf", size = 143435, upload-time = "2025-05-02T08:32:58.551Z" }, - { url = "https://files.pythonhosted.org/packages/22/2a/ea8a2095b0bafa6c5b5a55ffdc2f924455233ee7b91c69b7edfcc9e02284/charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3fddb7e2c84ac87ac3a947cb4e66d143ca5863ef48e4a5ecb83bd48619e4634e", size = 153653, upload-time = "2025-05-02T08:33:00.342Z" }, - { url = "https://files.pythonhosted.org/packages/b6/57/1b090ff183d13cef485dfbe272e2fe57622a76694061353c59da52c9a659/charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:98f862da73774290f251b9df8d11161b6cf25b599a66baf087c1ffe340e9bfd1", size = 146231, upload-time = "2025-05-02T08:33:02.081Z" }, - { url = "https://files.pythonhosted.org/packages/e2/28/ffc026b26f441fc67bd21ab7f03b313ab3fe46714a14b516f931abe1a2d8/charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c9379d65defcab82d07b2a9dfbfc2e95bc8fe0ebb1b176a3190230a3ef0e07c", size = 148243, upload-time = "2025-05-02T08:33:04.063Z" }, - { url = "https://files.pythonhosted.org/packages/c0/0f/9abe9bd191629c33e69e47c6ef45ef99773320e9ad8e9cb08b8ab4a8d4cb/charset_normalizer-3.4.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e635b87f01ebc977342e2697d05b56632f5f879a4f15955dfe8cef2448b51691", size = 150442, upload-time = "2025-05-02T08:33:06.418Z" }, - { url = "https://files.pythonhosted.org/packages/67/7c/a123bbcedca91d5916c056407f89a7f5e8fdfce12ba825d7d6b9954a1a3c/charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:1c95a1e2902a8b722868587c0e1184ad5c55631de5afc0eb96bc4b0d738092c0", size = 145147, upload-time = "2025-05-02T08:33:08.183Z" }, - { url = "https://files.pythonhosted.org/packages/ec/fe/1ac556fa4899d967b83e9893788e86b6af4d83e4726511eaaad035e36595/charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ef8de666d6179b009dce7bcb2ad4c4a779f113f12caf8dc77f0162c29d20490b", size = 153057, upload-time = "2025-05-02T08:33:09.986Z" }, - { url = "https://files.pythonhosted.org/packages/2b/ff/acfc0b0a70b19e3e54febdd5301a98b72fa07635e56f24f60502e954c461/charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:32fc0341d72e0f73f80acb0a2c94216bd704f4f0bce10aedea38f30502b271ff", size = 156454, upload-time = "2025-05-02T08:33:11.814Z" }, - { url = "https://files.pythonhosted.org/packages/92/08/95b458ce9c740d0645feb0e96cea1f5ec946ea9c580a94adfe0b617f3573/charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:289200a18fa698949d2b39c671c2cc7a24d44096784e76614899a7ccf2574b7b", size = 154174, upload-time = "2025-05-02T08:33:13.707Z" }, - { url = "https://files.pythonhosted.org/packages/78/be/8392efc43487ac051eee6c36d5fbd63032d78f7728cb37aebcc98191f1ff/charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4a476b06fbcf359ad25d34a057b7219281286ae2477cc5ff5e3f70a246971148", size = 149166, upload-time = "2025-05-02T08:33:15.458Z" }, - { url = "https://files.pythonhosted.org/packages/44/96/392abd49b094d30b91d9fbda6a69519e95802250b777841cf3bda8fe136c/charset_normalizer-3.4.2-cp313-cp313-win32.whl", hash = "sha256:aaeeb6a479c7667fbe1099af9617c83aaca22182d6cf8c53966491a0f1b7ffb7", size = 98064, upload-time = "2025-05-02T08:33:17.06Z" }, - { url = "https://files.pythonhosted.org/packages/e9/b0/0200da600134e001d91851ddc797809e2fe0ea72de90e09bec5a2fbdaccb/charset_normalizer-3.4.2-cp313-cp313-win_amd64.whl", hash = "sha256:aa6af9e7d59f9c12b33ae4e9450619cf2488e2bbe9b44030905877f0b2324980", size = 105641, upload-time = "2025-05-02T08:33:18.753Z" }, - { url = "https://files.pythonhosted.org/packages/20/94/c5790835a017658cbfabd07f3bfb549140c3ac458cfc196323996b10095a/charset_normalizer-3.4.2-py3-none-any.whl", hash = "sha256:7f56930ab0abd1c45cd15be65cc741c28b1c9a34876ce8c17a2fa107810c0af0", size = 52626, upload-time = "2025-05-02T08:34:40.053Z" }, +version = "3.4.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/83/2d/5fd176ceb9b2fc619e63405525573493ca23441330fcdaee6bef9460e924/charset_normalizer-3.4.3.tar.gz", hash = "sha256:6fce4b8500244f6fcb71465d4a4930d132ba9ab8e71a7859e6a5d59851068d14", size = 122371, upload-time = "2025-08-09T07:57:28.46Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7f/b5/991245018615474a60965a7c9cd2b4efbaabd16d582a5547c47ee1c7730b/charset_normalizer-3.4.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:b256ee2e749283ef3ddcff51a675ff43798d92d746d1a6e4631bf8c707d22d0b", size = 204483, upload-time = "2025-08-09T07:55:53.12Z" }, + { url = "https://files.pythonhosted.org/packages/c7/2a/ae245c41c06299ec18262825c1569c5d3298fc920e4ddf56ab011b417efd/charset_normalizer-3.4.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:13faeacfe61784e2559e690fc53fa4c5ae97c6fcedb8eb6fb8d0a15b475d2c64", size = 145520, upload-time = "2025-08-09T07:55:54.712Z" }, + { url = "https://files.pythonhosted.org/packages/3a/a4/b3b6c76e7a635748c4421d2b92c7b8f90a432f98bda5082049af37ffc8e3/charset_normalizer-3.4.3-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:00237675befef519d9af72169d8604a067d92755e84fe76492fef5441db05b91", size = 158876, upload-time = "2025-08-09T07:55:56.024Z" }, + { url = "https://files.pythonhosted.org/packages/e2/e6/63bb0e10f90a8243c5def74b5b105b3bbbfb3e7bb753915fe333fb0c11ea/charset_normalizer-3.4.3-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:585f3b2a80fbd26b048a0be90c5aae8f06605d3c92615911c3a2b03a8a3b796f", size = 156083, upload-time = "2025-08-09T07:55:57.582Z" }, + { url = "https://files.pythonhosted.org/packages/87/df/b7737ff046c974b183ea9aa111b74185ac8c3a326c6262d413bd5a1b8c69/charset_normalizer-3.4.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0e78314bdc32fa80696f72fa16dc61168fda4d6a0c014e0380f9d02f0e5d8a07", size = 150295, upload-time = "2025-08-09T07:55:59.147Z" }, + { url = "https://files.pythonhosted.org/packages/61/f1/190d9977e0084d3f1dc169acd060d479bbbc71b90bf3e7bf7b9927dec3eb/charset_normalizer-3.4.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:96b2b3d1a83ad55310de8c7b4a2d04d9277d5591f40761274856635acc5fcb30", size = 148379, upload-time = "2025-08-09T07:56:00.364Z" }, + { url = "https://files.pythonhosted.org/packages/4c/92/27dbe365d34c68cfe0ca76f1edd70e8705d82b378cb54ebbaeabc2e3029d/charset_normalizer-3.4.3-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:939578d9d8fd4299220161fdd76e86c6a251987476f5243e8864a7844476ba14", size = 160018, upload-time = "2025-08-09T07:56:01.678Z" }, + { url = "https://files.pythonhosted.org/packages/99/04/baae2a1ea1893a01635d475b9261c889a18fd48393634b6270827869fa34/charset_normalizer-3.4.3-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:fd10de089bcdcd1be95a2f73dbe6254798ec1bda9f450d5828c96f93e2536b9c", size = 157430, upload-time = "2025-08-09T07:56:02.87Z" }, + { url = "https://files.pythonhosted.org/packages/2f/36/77da9c6a328c54d17b960c89eccacfab8271fdaaa228305330915b88afa9/charset_normalizer-3.4.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1e8ac75d72fa3775e0b7cb7e4629cec13b7514d928d15ef8ea06bca03ef01cae", size = 151600, upload-time = "2025-08-09T07:56:04.089Z" }, + { url = "https://files.pythonhosted.org/packages/64/d4/9eb4ff2c167edbbf08cdd28e19078bf195762e9bd63371689cab5ecd3d0d/charset_normalizer-3.4.3-cp311-cp311-win32.whl", hash = "sha256:6cf8fd4c04756b6b60146d98cd8a77d0cdae0e1ca20329da2ac85eed779b6849", size = 99616, upload-time = "2025-08-09T07:56:05.658Z" }, + { url = "https://files.pythonhosted.org/packages/f4/9c/996a4a028222e7761a96634d1820de8a744ff4327a00ada9c8942033089b/charset_normalizer-3.4.3-cp311-cp311-win_amd64.whl", hash = "sha256:31a9a6f775f9bcd865d88ee350f0ffb0e25936a7f930ca98995c05abf1faf21c", size = 107108, upload-time = "2025-08-09T07:56:07.176Z" }, + { url = "https://files.pythonhosted.org/packages/e9/5e/14c94999e418d9b87682734589404a25854d5f5d0408df68bc15b6ff54bb/charset_normalizer-3.4.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:e28e334d3ff134e88989d90ba04b47d84382a828c061d0d1027b1b12a62b39b1", size = 205655, upload-time = "2025-08-09T07:56:08.475Z" }, + { url = "https://files.pythonhosted.org/packages/7d/a8/c6ec5d389672521f644505a257f50544c074cf5fc292d5390331cd6fc9c3/charset_normalizer-3.4.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0cacf8f7297b0c4fcb74227692ca46b4a5852f8f4f24b3c766dd94a1075c4884", size = 146223, upload-time = "2025-08-09T07:56:09.708Z" }, + { url = "https://files.pythonhosted.org/packages/fc/eb/a2ffb08547f4e1e5415fb69eb7db25932c52a52bed371429648db4d84fb1/charset_normalizer-3.4.3-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c6fd51128a41297f5409deab284fecbe5305ebd7e5a1f959bee1c054622b7018", size = 159366, upload-time = "2025-08-09T07:56:11.326Z" }, + { url = "https://files.pythonhosted.org/packages/82/10/0fd19f20c624b278dddaf83b8464dcddc2456cb4b02bb902a6da126b87a1/charset_normalizer-3.4.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3cfb2aad70f2c6debfbcb717f23b7eb55febc0bb23dcffc0f076009da10c6392", size = 157104, upload-time = "2025-08-09T07:56:13.014Z" }, + { url = "https://files.pythonhosted.org/packages/16/ab/0233c3231af734f5dfcf0844aa9582d5a1466c985bbed6cedab85af9bfe3/charset_normalizer-3.4.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1606f4a55c0fd363d754049cdf400175ee96c992b1f8018b993941f221221c5f", size = 151830, upload-time = "2025-08-09T07:56:14.428Z" }, + { url = "https://files.pythonhosted.org/packages/ae/02/e29e22b4e02839a0e4a06557b1999d0a47db3567e82989b5bb21f3fbbd9f/charset_normalizer-3.4.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:027b776c26d38b7f15b26a5da1044f376455fb3766df8fc38563b4efbc515154", size = 148854, upload-time = "2025-08-09T07:56:16.051Z" }, + { url = "https://files.pythonhosted.org/packages/05/6b/e2539a0a4be302b481e8cafb5af8792da8093b486885a1ae4d15d452bcec/charset_normalizer-3.4.3-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:42e5088973e56e31e4fa58eb6bd709e42fc03799c11c42929592889a2e54c491", size = 160670, upload-time = "2025-08-09T07:56:17.314Z" }, + { url = "https://files.pythonhosted.org/packages/31/e7/883ee5676a2ef217a40ce0bffcc3d0dfbf9e64cbcfbdf822c52981c3304b/charset_normalizer-3.4.3-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:cc34f233c9e71701040d772aa7490318673aa7164a0efe3172b2981218c26d93", size = 158501, upload-time = "2025-08-09T07:56:18.641Z" }, + { url = "https://files.pythonhosted.org/packages/c1/35/6525b21aa0db614cf8b5792d232021dca3df7f90a1944db934efa5d20bb1/charset_normalizer-3.4.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:320e8e66157cc4e247d9ddca8e21f427efc7a04bbd0ac8a9faf56583fa543f9f", size = 153173, upload-time = "2025-08-09T07:56:20.289Z" }, + { url = "https://files.pythonhosted.org/packages/50/ee/f4704bad8201de513fdc8aac1cabc87e38c5818c93857140e06e772b5892/charset_normalizer-3.4.3-cp312-cp312-win32.whl", hash = "sha256:fb6fecfd65564f208cbf0fba07f107fb661bcd1a7c389edbced3f7a493f70e37", size = 99822, upload-time = "2025-08-09T07:56:21.551Z" }, + { url = "https://files.pythonhosted.org/packages/39/f5/3b3836ca6064d0992c58c7561c6b6eee1b3892e9665d650c803bd5614522/charset_normalizer-3.4.3-cp312-cp312-win_amd64.whl", hash = "sha256:86df271bf921c2ee3818f0522e9a5b8092ca2ad8b065ece5d7d9d0e9f4849bcc", size = 107543, upload-time = "2025-08-09T07:56:23.115Z" }, + { url = "https://files.pythonhosted.org/packages/65/ca/2135ac97709b400c7654b4b764daf5c5567c2da45a30cdd20f9eefe2d658/charset_normalizer-3.4.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:14c2a87c65b351109f6abfc424cab3927b3bdece6f706e4d12faaf3d52ee5efe", size = 205326, upload-time = "2025-08-09T07:56:24.721Z" }, + { url = "https://files.pythonhosted.org/packages/71/11/98a04c3c97dd34e49c7d247083af03645ca3730809a5509443f3c37f7c99/charset_normalizer-3.4.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:41d1fc408ff5fdfb910200ec0e74abc40387bccb3252f3f27c0676731df2b2c8", size = 146008, upload-time = "2025-08-09T07:56:26.004Z" }, + { url = "https://files.pythonhosted.org/packages/60/f5/4659a4cb3c4ec146bec80c32d8bb16033752574c20b1252ee842a95d1a1e/charset_normalizer-3.4.3-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:1bb60174149316da1c35fa5233681f7c0f9f514509b8e399ab70fea5f17e45c9", size = 159196, upload-time = "2025-08-09T07:56:27.25Z" }, + { url = "https://files.pythonhosted.org/packages/86/9e/f552f7a00611f168b9a5865a1414179b2c6de8235a4fa40189f6f79a1753/charset_normalizer-3.4.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:30d006f98569de3459c2fc1f2acde170b7b2bd265dc1943e87e1a4efe1b67c31", size = 156819, upload-time = "2025-08-09T07:56:28.515Z" }, + { url = "https://files.pythonhosted.org/packages/7e/95/42aa2156235cbc8fa61208aded06ef46111c4d3f0de233107b3f38631803/charset_normalizer-3.4.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:416175faf02e4b0810f1f38bcb54682878a4af94059a1cd63b8747244420801f", size = 151350, upload-time = "2025-08-09T07:56:29.716Z" }, + { url = "https://files.pythonhosted.org/packages/c2/a9/3865b02c56f300a6f94fc631ef54f0a8a29da74fb45a773dfd3dcd380af7/charset_normalizer-3.4.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:6aab0f181c486f973bc7262a97f5aca3ee7e1437011ef0c2ec04b5a11d16c927", size = 148644, upload-time = "2025-08-09T07:56:30.984Z" }, + { url = "https://files.pythonhosted.org/packages/77/d9/cbcf1a2a5c7d7856f11e7ac2d782aec12bdfea60d104e60e0aa1c97849dc/charset_normalizer-3.4.3-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:fdabf8315679312cfa71302f9bd509ded4f2f263fb5b765cf1433b39106c3cc9", size = 160468, upload-time = "2025-08-09T07:56:32.252Z" }, + { url = "https://files.pythonhosted.org/packages/f6/42/6f45efee8697b89fda4d50580f292b8f7f9306cb2971d4b53f8914e4d890/charset_normalizer-3.4.3-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:bd28b817ea8c70215401f657edef3a8aa83c29d447fb0b622c35403780ba11d5", size = 158187, upload-time = "2025-08-09T07:56:33.481Z" }, + { url = "https://files.pythonhosted.org/packages/70/99/f1c3bdcfaa9c45b3ce96f70b14f070411366fa19549c1d4832c935d8e2c3/charset_normalizer-3.4.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:18343b2d246dc6761a249ba1fb13f9ee9a2bcd95decc767319506056ea4ad4dc", size = 152699, upload-time = "2025-08-09T07:56:34.739Z" }, + { url = "https://files.pythonhosted.org/packages/a3/ad/b0081f2f99a4b194bcbb1934ef3b12aa4d9702ced80a37026b7607c72e58/charset_normalizer-3.4.3-cp313-cp313-win32.whl", hash = "sha256:6fb70de56f1859a3f71261cbe41005f56a7842cc348d3aeb26237560bfa5e0ce", size = 99580, upload-time = "2025-08-09T07:56:35.981Z" }, + { url = "https://files.pythonhosted.org/packages/9a/8f/ae790790c7b64f925e5c953b924aaa42a243fb778fed9e41f147b2a5715a/charset_normalizer-3.4.3-cp313-cp313-win_amd64.whl", hash = "sha256:cf1ebb7d78e1ad8ec2a8c4732c7be2e736f6e5123a4146c5b89c9d1f585f8cef", size = 107366, upload-time = "2025-08-09T07:56:37.339Z" }, + { url = "https://files.pythonhosted.org/packages/8e/91/b5a06ad970ddc7a0e513112d40113e834638f4ca1120eb727a249fb2715e/charset_normalizer-3.4.3-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:3cd35b7e8aedeb9e34c41385fda4f73ba609e561faedfae0a9e75e44ac558a15", size = 204342, upload-time = "2025-08-09T07:56:38.687Z" }, + { url = "https://files.pythonhosted.org/packages/ce/ec/1edc30a377f0a02689342f214455c3f6c2fbedd896a1d2f856c002fc3062/charset_normalizer-3.4.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b89bc04de1d83006373429975f8ef9e7932534b8cc9ca582e4db7d20d91816db", size = 145995, upload-time = "2025-08-09T07:56:40.048Z" }, + { url = "https://files.pythonhosted.org/packages/17/e5/5e67ab85e6d22b04641acb5399c8684f4d37caf7558a53859f0283a650e9/charset_normalizer-3.4.3-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2001a39612b241dae17b4687898843f254f8748b796a2e16f1051a17078d991d", size = 158640, upload-time = "2025-08-09T07:56:41.311Z" }, + { url = "https://files.pythonhosted.org/packages/f1/e5/38421987f6c697ee3722981289d554957c4be652f963d71c5e46a262e135/charset_normalizer-3.4.3-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:8dcfc373f888e4fb39a7bc57e93e3b845e7f462dacc008d9749568b1c4ece096", size = 156636, upload-time = "2025-08-09T07:56:43.195Z" }, + { url = "https://files.pythonhosted.org/packages/a0/e4/5a075de8daa3ec0745a9a3b54467e0c2967daaaf2cec04c845f73493e9a1/charset_normalizer-3.4.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:18b97b8404387b96cdbd30ad660f6407799126d26a39ca65729162fd810a99aa", size = 150939, upload-time = "2025-08-09T07:56:44.819Z" }, + { url = "https://files.pythonhosted.org/packages/02/f7/3611b32318b30974131db62b4043f335861d4d9b49adc6d57c1149cc49d4/charset_normalizer-3.4.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:ccf600859c183d70eb47e05a44cd80a4ce77394d1ac0f79dbd2dd90a69a3a049", size = 148580, upload-time = "2025-08-09T07:56:46.684Z" }, + { url = "https://files.pythonhosted.org/packages/7e/61/19b36f4bd67f2793ab6a99b979b4e4f3d8fc754cbdffb805335df4337126/charset_normalizer-3.4.3-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:53cd68b185d98dde4ad8990e56a58dea83a4162161b1ea9272e5c9182ce415e0", size = 159870, upload-time = "2025-08-09T07:56:47.941Z" }, + { url = "https://files.pythonhosted.org/packages/06/57/84722eefdd338c04cf3030ada66889298eaedf3e7a30a624201e0cbe424a/charset_normalizer-3.4.3-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:30a96e1e1f865f78b030d65241c1ee850cdf422d869e9028e2fc1d5e4db73b92", size = 157797, upload-time = "2025-08-09T07:56:49.756Z" }, + { url = "https://files.pythonhosted.org/packages/72/2a/aff5dd112b2f14bcc3462c312dce5445806bfc8ab3a7328555da95330e4b/charset_normalizer-3.4.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:d716a916938e03231e86e43782ca7878fb602a125a91e7acb8b5112e2e96ac16", size = 152224, upload-time = "2025-08-09T07:56:51.369Z" }, + { url = "https://files.pythonhosted.org/packages/b7/8c/9839225320046ed279c6e839d51f028342eb77c91c89b8ef2549f951f3ec/charset_normalizer-3.4.3-cp314-cp314-win32.whl", hash = "sha256:c6dbd0ccdda3a2ba7c2ecd9d77b37f3b5831687d8dc1b6ca5f56a4880cc7b7ce", size = 100086, upload-time = "2025-08-09T07:56:52.722Z" }, + { url = "https://files.pythonhosted.org/packages/ee/7a/36fbcf646e41f710ce0a563c1c9a343c6edf9be80786edeb15b6f62e17db/charset_normalizer-3.4.3-cp314-cp314-win_amd64.whl", hash = "sha256:73dc19b562516fc9bcf6e5d6e596df0b4eb98d87e4f79f3ae71840e6ed21361c", size = 107400, upload-time = "2025-08-09T07:56:55.172Z" }, + { url = "https://files.pythonhosted.org/packages/8a/1f/f041989e93b001bc4e44bb1669ccdcf54d3f00e628229a85b08d330615c5/charset_normalizer-3.4.3-py3-none-any.whl", hash = "sha256:ce571ab16d890d23b5c278547ba694193a45011ff86a9162a71307ed9f86759a", size = 53175, upload-time = "2025-08-09T07:57:26.864Z" }, ] [[package]] @@ -372,77 +377,77 @@ wheels = [ [[package]] name = "coverage" -version = "7.10.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/ee/76/17780846fc7aade1e66712e1e27dd28faa0a5d987a1f433610974959eaa8/coverage-7.10.2.tar.gz", hash = "sha256:5d6e6d84e6dd31a8ded64759626627247d676a23c1b892e1326f7c55c8d61055", size = 820754, upload-time = "2025-08-04T00:35:17.511Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/6e/53/0125a6fc0af4f2687b4e08b0fb332cd0d5e60f3ca849e7456f995d022656/coverage-7.10.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2c3b210d79925a476dfc8d74c7d53224888421edebf3a611f3adae923e212b27", size = 215119, upload-time = "2025-08-04T00:33:19.101Z" }, - { url = "https://files.pythonhosted.org/packages/0e/2e/960d9871de9152dbc9ff950913c6a6e9cf2eb4cc80d5bc8f93029f9f2f9f/coverage-7.10.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:bf67d1787cd317c3f8b2e4c6ed1ae93497be7e30605a0d32237ac37a37a8a322", size = 215511, upload-time = "2025-08-04T00:33:20.32Z" }, - { url = "https://files.pythonhosted.org/packages/3f/34/68509e44995b9cad806d81b76c22bc5181f3535bca7cd9c15791bfd8951e/coverage-7.10.2-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:069b779d03d458602bc0e27189876e7d8bdf6b24ac0f12900de22dd2154e6ad7", size = 245513, upload-time = "2025-08-04T00:33:21.896Z" }, - { url = "https://files.pythonhosted.org/packages/ef/d4/9b12f357413248ce40804b0f58030b55a25b28a5c02db95fb0aa50c5d62c/coverage-7.10.2-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:4c2de4cb80b9990e71c62c2d3e9f3ec71b804b1f9ca4784ec7e74127e0f42468", size = 247350, upload-time = "2025-08-04T00:33:23.917Z" }, - { url = "https://files.pythonhosted.org/packages/b6/40/257945eda1f72098e4a3c350b1d68fdc5d7d032684a0aeb6c2391153ecf4/coverage-7.10.2-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:75bf7ab2374a7eb107602f1e07310cda164016cd60968abf817b7a0b5703e288", size = 249516, upload-time = "2025-08-04T00:33:25.5Z" }, - { url = "https://files.pythonhosted.org/packages/ff/55/8987f852ece378cecbf39a367f3f7ec53351e39a9151b130af3a3045b83f/coverage-7.10.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:3f37516458ec1550815134937f73d6d15b434059cd10f64678a2068f65c62406", size = 247241, upload-time = "2025-08-04T00:33:26.767Z" }, - { url = "https://files.pythonhosted.org/packages/df/ae/da397de7a42a18cea6062ed9c3b72c50b39e0b9e7b2893d7172d3333a9a1/coverage-7.10.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:de3c6271c482c250d3303fb5c6bdb8ca025fff20a67245e1425df04dc990ece9", size = 245274, upload-time = "2025-08-04T00:33:28.494Z" }, - { url = "https://files.pythonhosted.org/packages/4e/64/7baa895eb55ec0e1ec35b988687ecd5d4475ababb0d7ae5ca3874dd90ee7/coverage-7.10.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:98a838101321ac3089c9bb1d4bfa967e8afed58021fda72d7880dc1997f20ae1", size = 245882, upload-time = "2025-08-04T00:33:30.048Z" }, - { url = "https://files.pythonhosted.org/packages/24/6c/1fd76a0bd09ae75220ae9775a8290416d726f0e5ba26ea72346747161240/coverage-7.10.2-cp311-cp311-win32.whl", hash = "sha256:f2a79145a531a0e42df32d37be5af069b4a914845b6f686590739b786f2f7bce", size = 217541, upload-time = "2025-08-04T00:33:31.376Z" }, - { url = "https://files.pythonhosted.org/packages/5f/2d/8c18fb7a6e74c79fd4661e82535bc8c68aee12f46c204eabf910b097ccc9/coverage-7.10.2-cp311-cp311-win_amd64.whl", hash = "sha256:e4f5f1320f8ee0d7cfa421ceb257bef9d39fd614dd3ddcfcacd284d4824ed2c2", size = 218426, upload-time = "2025-08-04T00:33:32.976Z" }, - { url = "https://files.pythonhosted.org/packages/da/40/425bb35e4ff7c7af177edf5dffd4154bc2a677b27696afe6526d75c77fec/coverage-7.10.2-cp311-cp311-win_arm64.whl", hash = "sha256:d8f2d83118f25328552c728b8e91babf93217db259ca5c2cd4dd4220b8926293", size = 217116, upload-time = "2025-08-04T00:33:34.302Z" }, - { url = "https://files.pythonhosted.org/packages/4e/1e/2c752bdbbf6f1199c59b1a10557fbb6fb3dc96b3c0077b30bd41a5922c1f/coverage-7.10.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:890ad3a26da9ec7bf69255b9371800e2a8da9bc223ae5d86daeb940b42247c83", size = 215311, upload-time = "2025-08-04T00:33:35.524Z" }, - { url = "https://files.pythonhosted.org/packages/68/6a/84277d73a2cafb96e24be81b7169372ba7ff28768ebbf98e55c85a491b0f/coverage-7.10.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:38fd1ccfca7838c031d7a7874d4353e2f1b98eb5d2a80a2fe5732d542ae25e9c", size = 215550, upload-time = "2025-08-04T00:33:37.109Z" }, - { url = "https://files.pythonhosted.org/packages/b5/e7/5358b73b46ac76f56cc2de921eeabd44fabd0b7ff82ea4f6b8c159c4d5dc/coverage-7.10.2-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:76c1ffaaf4f6f0f6e8e9ca06f24bb6454a7a5d4ced97a1bc466f0d6baf4bd518", size = 246564, upload-time = "2025-08-04T00:33:38.33Z" }, - { url = "https://files.pythonhosted.org/packages/7c/0e/b0c901dd411cb7fc0cfcb28ef0dc6f3049030f616bfe9fc4143aecd95901/coverage-7.10.2-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:86da8a3a84b79ead5c7d0e960c34f580bc3b231bb546627773a3f53c532c2f21", size = 248993, upload-time = "2025-08-04T00:33:39.555Z" }, - { url = "https://files.pythonhosted.org/packages/0e/4e/a876db272072a9e0df93f311e187ccdd5f39a190c6d1c1f0b6e255a0d08e/coverage-7.10.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:99cef9731c8a39801830a604cc53c93c9e57ea8b44953d26589499eded9576e0", size = 250454, upload-time = "2025-08-04T00:33:41.023Z" }, - { url = "https://files.pythonhosted.org/packages/64/d6/1222dc69f8dd1be208d55708a9f4a450ad582bf4fa05320617fea1eaa6d8/coverage-7.10.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:ea58b112f2966a8b91eb13f5d3b1f8bb43c180d624cd3283fb33b1cedcc2dd75", size = 248365, upload-time = "2025-08-04T00:33:42.376Z" }, - { url = "https://files.pythonhosted.org/packages/62/e3/40fd71151064fc315c922dd9a35e15b30616f00146db1d6a0b590553a75a/coverage-7.10.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:20f405188d28da9522b7232e51154e1b884fc18d0b3a10f382d54784715bbe01", size = 246562, upload-time = "2025-08-04T00:33:43.663Z" }, - { url = "https://files.pythonhosted.org/packages/fc/14/8aa93ddcd6623ddaef5d8966268ac9545b145bce4fe7b1738fd1c3f0d957/coverage-7.10.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:64586ce42bbe0da4d9f76f97235c545d1abb9b25985a8791857690f96e23dc3b", size = 247772, upload-time = "2025-08-04T00:33:45.068Z" }, - { url = "https://files.pythonhosted.org/packages/07/4e/dcb1c01490623c61e2f2ea85cb185fa6a524265bb70eeb897d3c193efeb9/coverage-7.10.2-cp312-cp312-win32.whl", hash = "sha256:bc2e69b795d97ee6d126e7e22e78a509438b46be6ff44f4dccbb5230f550d340", size = 217710, upload-time = "2025-08-04T00:33:46.378Z" }, - { url = "https://files.pythonhosted.org/packages/79/16/e8aab4162b5f80ad2e5e1f54b1826e2053aa2f4db508b864af647f00c239/coverage-7.10.2-cp312-cp312-win_amd64.whl", hash = "sha256:adda2268b8cf0d11f160fad3743b4dfe9813cd6ecf02c1d6397eceaa5b45b388", size = 218499, upload-time = "2025-08-04T00:33:48.048Z" }, - { url = "https://files.pythonhosted.org/packages/06/7f/c112ec766e8f1131ce8ce26254be028772757b2d1e63e4f6a4b0ad9a526c/coverage-7.10.2-cp312-cp312-win_arm64.whl", hash = "sha256:164429decd0d6b39a0582eaa30c67bf482612c0330572343042d0ed9e7f15c20", size = 217154, upload-time = "2025-08-04T00:33:49.299Z" }, - { url = "https://files.pythonhosted.org/packages/8d/04/9b7a741557f93c0ed791b854d27aa8d9fe0b0ce7bb7c52ca1b0f2619cb74/coverage-7.10.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:aca7b5645afa688de6d4f8e89d30c577f62956fefb1bad021490d63173874186", size = 215337, upload-time = "2025-08-04T00:33:50.61Z" }, - { url = "https://files.pythonhosted.org/packages/02/a4/8d1088cd644750c94bc305d3cf56082b4cdf7fb854a25abb23359e74892f/coverage-7.10.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:96e5921342574a14303dfdb73de0019e1ac041c863743c8fe1aa6c2b4a257226", size = 215596, upload-time = "2025-08-04T00:33:52.33Z" }, - { url = "https://files.pythonhosted.org/packages/01/2f/643a8d73343f70e162d8177a3972b76e306b96239026bc0c12cfde4f7c7a/coverage-7.10.2-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:11333094c1bff621aa811b67ed794865cbcaa99984dedea4bd9cf780ad64ecba", size = 246145, upload-time = "2025-08-04T00:33:53.641Z" }, - { url = "https://files.pythonhosted.org/packages/1f/4a/722098d1848db4072cda71b69ede1e55730d9063bf868375264d0d302bc9/coverage-7.10.2-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:6eb586fa7d2aee8d65d5ae1dd71414020b2f447435c57ee8de8abea0a77d5074", size = 248492, upload-time = "2025-08-04T00:33:55.366Z" }, - { url = "https://files.pythonhosted.org/packages/3f/b0/8a6d7f326f6e3e6ed398cde27f9055e860a1e858317001835c521673fb60/coverage-7.10.2-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2d358f259d8019d4ef25d8c5b78aca4c7af25e28bd4231312911c22a0e824a57", size = 249927, upload-time = "2025-08-04T00:33:57.042Z" }, - { url = "https://files.pythonhosted.org/packages/bb/21/1aaadd3197b54d1e61794475379ecd0f68d8fc5c2ebd352964dc6f698a3d/coverage-7.10.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:5250bda76e30382e0a2dcd68d961afcab92c3a7613606e6269855c6979a1b0bb", size = 248138, upload-time = "2025-08-04T00:33:58.329Z" }, - { url = "https://files.pythonhosted.org/packages/48/65/be75bafb2bdd22fd8bf9bf63cd5873b91bb26ec0d68f02d4b8b09c02decb/coverage-7.10.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:a91e027d66eff214d88d9afbe528e21c9ef1ecdf4956c46e366c50f3094696d0", size = 246111, upload-time = "2025-08-04T00:33:59.899Z" }, - { url = "https://files.pythonhosted.org/packages/5e/30/a4f0c5e249c3cc60e6c6f30d8368e372f2d380eda40e0434c192ac27ccf5/coverage-7.10.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:228946da741558904e2c03ce870ba5efd9cd6e48cbc004d9a27abee08100a15a", size = 247493, upload-time = "2025-08-04T00:34:01.619Z" }, - { url = "https://files.pythonhosted.org/packages/85/99/f09b9493e44a75cf99ca834394c12f8cb70da6c1711ee296534f97b52729/coverage-7.10.2-cp313-cp313-win32.whl", hash = "sha256:95e23987b52d02e7c413bf2d6dc6288bd5721beb518052109a13bfdc62c8033b", size = 217756, upload-time = "2025-08-04T00:34:03.277Z" }, - { url = "https://files.pythonhosted.org/packages/2d/bb/cbcb09103be330c7d26ff0ab05c4a8861dd2e254656fdbd3eb7600af4336/coverage-7.10.2-cp313-cp313-win_amd64.whl", hash = "sha256:f35481d42c6d146d48ec92d4e239c23f97b53a3f1fbd2302e7c64336f28641fe", size = 218526, upload-time = "2025-08-04T00:34:04.635Z" }, - { url = "https://files.pythonhosted.org/packages/37/8f/8bfb4e0bca52c00ab680767c0dd8cfd928a2a72d69897d9b2d5d8b5f63f5/coverage-7.10.2-cp313-cp313-win_arm64.whl", hash = "sha256:65b451949cb789c346f9f9002441fc934d8ccedcc9ec09daabc2139ad13853f7", size = 217176, upload-time = "2025-08-04T00:34:05.973Z" }, - { url = "https://files.pythonhosted.org/packages/1e/25/d458ba0bf16a8204a88d74dbb7ec5520f29937ffcbbc12371f931c11efd2/coverage-7.10.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:e8415918856a3e7d57a4e0ad94651b761317de459eb74d34cc1bb51aad80f07e", size = 216058, upload-time = "2025-08-04T00:34:07.368Z" }, - { url = "https://files.pythonhosted.org/packages/0b/1c/af4dfd2d7244dc7610fed6d59d57a23ea165681cd764445dc58d71ed01a6/coverage-7.10.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:f287a25a8ca53901c613498e4a40885b19361a2fe8fbfdbb7f8ef2cad2a23f03", size = 216273, upload-time = "2025-08-04T00:34:09.073Z" }, - { url = "https://files.pythonhosted.org/packages/8e/67/ec5095d4035c6e16368226fa9cb15f77f891194c7e3725aeefd08e7a3e5a/coverage-7.10.2-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:75cc1a3f8c88c69bf16a871dab1fe5a7303fdb1e9f285f204b60f1ee539b8fc0", size = 257513, upload-time = "2025-08-04T00:34:10.403Z" }, - { url = "https://files.pythonhosted.org/packages/1c/47/be5550b57a3a8ba797de4236b0fd31031f88397b2afc84ab3c2d4cf265f6/coverage-7.10.2-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:ca07fa78cc9d26bc8c4740de1abd3489cf9c47cc06d9a8ab3d552ff5101af4c0", size = 259377, upload-time = "2025-08-04T00:34:12.138Z" }, - { url = "https://files.pythonhosted.org/packages/37/50/b12a4da1382e672305c2d17cd3029dc16b8a0470de2191dbf26b91431378/coverage-7.10.2-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c2e117e64c26300032755d4520cd769f2623cde1a1d1c3515b05a3b8add0ade1", size = 261516, upload-time = "2025-08-04T00:34:13.608Z" }, - { url = "https://files.pythonhosted.org/packages/db/41/4d3296dbd33dd8da178171540ca3391af7c0184c0870fd4d4574ac290290/coverage-7.10.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:daaf98009977f577b71f8800208f4d40d4dcf5c2db53d4d822787cdc198d76e1", size = 259110, upload-time = "2025-08-04T00:34:15.089Z" }, - { url = "https://files.pythonhosted.org/packages/ea/f1/b409959ecbc0cec0e61e65683b22bacaa4a3b11512f834e16dd8ffbc37db/coverage-7.10.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:ea8d8fe546c528535c761ba424410bbeb36ba8a0f24be653e94b70c93fd8a8ca", size = 257248, upload-time = "2025-08-04T00:34:16.501Z" }, - { url = "https://files.pythonhosted.org/packages/48/ab/7076dc1c240412e9267d36ec93e9e299d7659f6a5c1e958f87e998b0fb6d/coverage-7.10.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:fe024d40ac31eb8d5aae70215b41dafa264676caa4404ae155f77d2fa95c37bb", size = 258063, upload-time = "2025-08-04T00:34:18.338Z" }, - { url = "https://files.pythonhosted.org/packages/1e/77/f6b51a0288f8f5f7dcc7c89abdd22cf514f3bc5151284f5cd628917f8e10/coverage-7.10.2-cp313-cp313t-win32.whl", hash = "sha256:8f34b09f68bdadec122ffad312154eda965ade433559cc1eadd96cca3de5c824", size = 218433, upload-time = "2025-08-04T00:34:19.71Z" }, - { url = "https://files.pythonhosted.org/packages/7b/6d/547a86493e25270ce8481543e77f3a0aa3aa872c1374246b7b76273d66eb/coverage-7.10.2-cp313-cp313t-win_amd64.whl", hash = "sha256:71d40b3ac0f26fa9ffa6ee16219a714fed5c6ec197cdcd2018904ab5e75bcfa3", size = 219523, upload-time = "2025-08-04T00:34:21.171Z" }, - { url = "https://files.pythonhosted.org/packages/ff/d5/3c711e38eaf9ab587edc9bed232c0298aed84e751a9f54aaa556ceaf7da6/coverage-7.10.2-cp313-cp313t-win_arm64.whl", hash = "sha256:abb57fdd38bf6f7dcc66b38dafb7af7c5fdc31ac6029ce373a6f7f5331d6f60f", size = 217739, upload-time = "2025-08-04T00:34:22.514Z" }, - { url = "https://files.pythonhosted.org/packages/71/53/83bafa669bb9d06d4c8c6a055d8d05677216f9480c4698fb183ba7ec5e47/coverage-7.10.2-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:a3e853cc04987c85ec410905667eed4bf08b1d84d80dfab2684bb250ac8da4f6", size = 215328, upload-time = "2025-08-04T00:34:23.991Z" }, - { url = "https://files.pythonhosted.org/packages/1d/6c/30827a9c5a48a813e865fbaf91e2db25cce990bd223a022650ef2293fe11/coverage-7.10.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:0100b19f230df72c90fdb36db59d3f39232391e8d89616a7de30f677da4f532b", size = 215608, upload-time = "2025-08-04T00:34:25.437Z" }, - { url = "https://files.pythonhosted.org/packages/bb/a0/c92d85948056ddc397b72a3d79d36d9579c53cb25393ed3c40db7d33b193/coverage-7.10.2-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:9c1cd71483ea78331bdfadb8dcec4f4edfb73c7002c1206d8e0af6797853f5be", size = 246111, upload-time = "2025-08-04T00:34:26.857Z" }, - { url = "https://files.pythonhosted.org/packages/c2/cf/d695cf86b2559aadd072c91720a7844be4fb82cb4a3b642a2c6ce075692d/coverage-7.10.2-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:9f75dbf4899e29a37d74f48342f29279391668ef625fdac6d2f67363518056a1", size = 248419, upload-time = "2025-08-04T00:34:28.726Z" }, - { url = "https://files.pythonhosted.org/packages/ce/0a/03206aec4a05986e039418c038470d874045f6e00426b0c3879adc1f9251/coverage-7.10.2-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a7df481e7508de1c38b9b8043da48d94931aefa3e32b47dd20277e4978ed5b95", size = 250038, upload-time = "2025-08-04T00:34:30.061Z" }, - { url = "https://files.pythonhosted.org/packages/ab/9b/b3bd6bd52118c12bc4cf319f5baba65009c9beea84e665b6b9f03fa3f180/coverage-7.10.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:835f39e618099325e7612b3406f57af30ab0a0af350490eff6421e2e5f608e46", size = 248066, upload-time = "2025-08-04T00:34:31.53Z" }, - { url = "https://files.pythonhosted.org/packages/80/cc/bfa92e261d3e055c851a073e87ba6a3bff12a1f7134233e48a8f7d855875/coverage-7.10.2-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:12e52b5aa00aa720097d6947d2eb9e404e7c1101ad775f9661ba165ed0a28303", size = 245909, upload-time = "2025-08-04T00:34:32.943Z" }, - { url = "https://files.pythonhosted.org/packages/12/80/c8df15db4847710c72084164f615ae900af1ec380dce7f74a5678ccdf5e1/coverage-7.10.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:718044729bf1fe3e9eb9f31b52e44ddae07e434ec050c8c628bf5adc56fe4bdd", size = 247329, upload-time = "2025-08-04T00:34:34.388Z" }, - { url = "https://files.pythonhosted.org/packages/04/6f/cb66e1f7124d5dd9ced69f889f02931419cb448125e44a89a13f4e036124/coverage-7.10.2-cp314-cp314-win32.whl", hash = "sha256:f256173b48cc68486299d510a3e729a96e62c889703807482dbf56946befb5c8", size = 218007, upload-time = "2025-08-04T00:34:35.846Z" }, - { url = "https://files.pythonhosted.org/packages/8c/e1/3d4be307278ce32c1b9d95cc02ee60d54ddab784036101d053ec9e4fe7f5/coverage-7.10.2-cp314-cp314-win_amd64.whl", hash = "sha256:2e980e4179f33d9b65ac4acb86c9c0dde904098853f27f289766657ed16e07b3", size = 218802, upload-time = "2025-08-04T00:34:37.35Z" }, - { url = "https://files.pythonhosted.org/packages/ec/66/1e43bbeb66c55a5a5efec70f1c153cf90cfc7f1662ab4ebe2d844de9122c/coverage-7.10.2-cp314-cp314-win_arm64.whl", hash = "sha256:14fb5b6641ab5b3c4161572579f0f2ea8834f9d3af2f7dd8fbaecd58ef9175cc", size = 217397, upload-time = "2025-08-04T00:34:39.15Z" }, - { url = "https://files.pythonhosted.org/packages/81/01/ae29c129217f6110dc694a217475b8aecbb1b075d8073401f868c825fa99/coverage-7.10.2-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:e96649ac34a3d0e6491e82a2af71098e43be2874b619547c3282fc11d3840a4b", size = 216068, upload-time = "2025-08-04T00:34:40.648Z" }, - { url = "https://files.pythonhosted.org/packages/a2/50/6e9221d4139f357258f36dfa1d8cac4ec56d9d5acf5fdcc909bb016954d7/coverage-7.10.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1a2e934e9da26341d342d30bfe91422bbfdb3f1f069ec87f19b2909d10d8dcc4", size = 216285, upload-time = "2025-08-04T00:34:42.441Z" }, - { url = "https://files.pythonhosted.org/packages/eb/ec/89d1d0c0ece0d296b4588e0ef4df185200456d42a47f1141335f482c2fc5/coverage-7.10.2-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:651015dcd5fd9b5a51ca79ece60d353cacc5beaf304db750407b29c89f72fe2b", size = 257603, upload-time = "2025-08-04T00:34:43.899Z" }, - { url = "https://files.pythonhosted.org/packages/82/06/c830af66734671c778fc49d35b58339e8f0687fbd2ae285c3f96c94da092/coverage-7.10.2-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:81bf6a32212f9f66da03d63ecb9cd9bd48e662050a937db7199dbf47d19831de", size = 259568, upload-time = "2025-08-04T00:34:45.519Z" }, - { url = "https://files.pythonhosted.org/packages/60/57/f280dd6f1c556ecc744fbf39e835c33d3ae987d040d64d61c6f821e87829/coverage-7.10.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d800705f6951f75a905ea6feb03fff8f3ea3468b81e7563373ddc29aa3e5d1ca", size = 261691, upload-time = "2025-08-04T00:34:47.019Z" }, - { url = "https://files.pythonhosted.org/packages/54/2b/c63a0acbd19d99ec32326164c23df3a4e18984fb86e902afdd66ff7b3d83/coverage-7.10.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:248b5394718e10d067354448dc406d651709c6765669679311170da18e0e9af8", size = 259166, upload-time = "2025-08-04T00:34:48.792Z" }, - { url = "https://files.pythonhosted.org/packages/fd/c5/cd2997dcfcbf0683634da9df52d3967bc1f1741c1475dd0e4722012ba9ef/coverage-7.10.2-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:5c61675a922b569137cf943770d7ad3edd0202d992ce53ac328c5ff68213ccf4", size = 257241, upload-time = "2025-08-04T00:34:51.038Z" }, - { url = "https://files.pythonhosted.org/packages/16/26/c9e30f82fdad8d47aee90af4978b18c88fa74369ae0f0ba0dbf08cee3a80/coverage-7.10.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:52d708b5fd65589461381fa442d9905f5903d76c086c6a4108e8e9efdca7a7ed", size = 258139, upload-time = "2025-08-04T00:34:52.533Z" }, - { url = "https://files.pythonhosted.org/packages/c9/99/bdb7bd00bebcd3dedfb895fa9af8e46b91422993e4a37ac634a5f1113790/coverage-7.10.2-cp314-cp314t-win32.whl", hash = "sha256:916369b3b914186b2c5e5ad2f7264b02cff5df96cdd7cdad65dccd39aa5fd9f0", size = 218809, upload-time = "2025-08-04T00:34:54.075Z" }, - { url = "https://files.pythonhosted.org/packages/eb/5e/56a7852e38a04d1520dda4dfbfbf74a3d6dec932c20526968f7444763567/coverage-7.10.2-cp314-cp314t-win_amd64.whl", hash = "sha256:5b9d538e8e04916a5df63052d698b30c74eb0174f2ca9cd942c981f274a18eaf", size = 219926, upload-time = "2025-08-04T00:34:55.643Z" }, - { url = "https://files.pythonhosted.org/packages/e0/12/7fbe6b9c52bb9d627e9556f9f2edfdbe88b315e084cdecc9afead0c3b36a/coverage-7.10.2-cp314-cp314t-win_arm64.whl", hash = "sha256:04c74f9ef1f925456a9fd23a7eef1103126186d0500ef9a0acb0bd2514bdc7cc", size = 217925, upload-time = "2025-08-04T00:34:57.564Z" }, - { url = "https://files.pythonhosted.org/packages/18/d8/9b768ac73a8ac2d10c080af23937212434a958c8d2a1c84e89b450237942/coverage-7.10.2-py3-none-any.whl", hash = "sha256:95db3750dd2e6e93d99fa2498f3a1580581e49c494bddccc6f85c5c21604921f", size = 206973, upload-time = "2025-08-04T00:35:15.918Z" }, +version = "7.10.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f4/2c/253cc41cd0f40b84c1c34c5363e0407d73d4a1cae005fed6db3b823175bd/coverage-7.10.3.tar.gz", hash = "sha256:812ba9250532e4a823b070b0420a36499859542335af3dca8f47fc6aa1a05619", size = 822936, upload-time = "2025-08-10T21:27:39.968Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/87/04/810e506d7a19889c244d35199cbf3239a2f952b55580aa42ca4287409424/coverage-7.10.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f2ff2e2afdf0d51b9b8301e542d9c21a8d084fd23d4c8ea2b3a1b3c96f5f7397", size = 216075, upload-time = "2025-08-10T21:25:39.891Z" }, + { url = "https://files.pythonhosted.org/packages/2e/50/6b3fbab034717b4af3060bdaea6b13dfdc6b1fad44b5082e2a95cd378a9a/coverage-7.10.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:18ecc5d1b9a8c570f6c9b808fa9a2b16836b3dd5414a6d467ae942208b095f85", size = 216476, upload-time = "2025-08-10T21:25:41.137Z" }, + { url = "https://files.pythonhosted.org/packages/c7/96/4368c624c1ed92659812b63afc76c492be7867ac8e64b7190b88bb26d43c/coverage-7.10.3-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:1af4461b25fe92889590d438905e1fc79a95680ec2a1ff69a591bb3fdb6c7157", size = 246865, upload-time = "2025-08-10T21:25:42.408Z" }, + { url = "https://files.pythonhosted.org/packages/34/12/5608f76070939395c17053bf16e81fd6c06cf362a537ea9d07e281013a27/coverage-7.10.3-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:3966bc9a76b09a40dc6063c8b10375e827ea5dfcaffae402dd65953bef4cba54", size = 248800, upload-time = "2025-08-10T21:25:44.098Z" }, + { url = "https://files.pythonhosted.org/packages/ce/52/7cc90c448a0ad724283cbcdfd66b8d23a598861a6a22ac2b7b8696491798/coverage-7.10.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:205a95b87ef4eb303b7bc5118b47b6b6604a644bcbdb33c336a41cfc0a08c06a", size = 250904, upload-time = "2025-08-10T21:25:45.384Z" }, + { url = "https://files.pythonhosted.org/packages/e6/70/9967b847063c1c393b4f4d6daab1131558ebb6b51f01e7df7150aa99f11d/coverage-7.10.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:5b3801b79fb2ad61e3c7e2554bab754fc5f105626056980a2b9cf3aef4f13f84", size = 248597, upload-time = "2025-08-10T21:25:47.059Z" }, + { url = "https://files.pythonhosted.org/packages/2d/fe/263307ce6878b9ed4865af42e784b42bb82d066bcf10f68defa42931c2c7/coverage-7.10.3-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:b0dc69c60224cda33d384572da945759756e3f06b9cdac27f302f53961e63160", size = 246647, upload-time = "2025-08-10T21:25:48.334Z" }, + { url = "https://files.pythonhosted.org/packages/8e/27/d27af83ad162eba62c4eb7844a1de6cf7d9f6b185df50b0a3514a6f80ddd/coverage-7.10.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a83d4f134bab2c7ff758e6bb1541dd72b54ba295ced6a63d93efc2e20cb9b124", size = 247290, upload-time = "2025-08-10T21:25:49.945Z" }, + { url = "https://files.pythonhosted.org/packages/28/83/904ff27e15467a5622dbe9ad2ed5831b4a616a62570ec5924d06477dff5a/coverage-7.10.3-cp311-cp311-win32.whl", hash = "sha256:54e409dd64e5302b2a8fdf44ec1c26f47abd1f45a2dcf67bd161873ee05a59b8", size = 218521, upload-time = "2025-08-10T21:25:51.208Z" }, + { url = "https://files.pythonhosted.org/packages/b8/29/bc717b8902faaccf0ca486185f0dcab4778561a529dde51cb157acaafa16/coverage-7.10.3-cp311-cp311-win_amd64.whl", hash = "sha256:30c601610a9b23807c5e9e2e442054b795953ab85d525c3de1b1b27cebeb2117", size = 219412, upload-time = "2025-08-10T21:25:52.494Z" }, + { url = "https://files.pythonhosted.org/packages/7b/7a/5a1a7028c11bb589268c656c6b3f2bbf06e0aced31bbdf7a4e94e8442cc0/coverage-7.10.3-cp311-cp311-win_arm64.whl", hash = "sha256:dabe662312a97958e932dee056f2659051d822552c0b866823e8ba1c2fe64770", size = 218091, upload-time = "2025-08-10T21:25:54.102Z" }, + { url = "https://files.pythonhosted.org/packages/b8/62/13c0b66e966c43d7aa64dadc8cd2afa1f5a2bf9bb863bdabc21fb94e8b63/coverage-7.10.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:449c1e2d3a84d18bd204258a897a87bc57380072eb2aded6a5b5226046207b42", size = 216262, upload-time = "2025-08-10T21:25:55.367Z" }, + { url = "https://files.pythonhosted.org/packages/b5/f0/59fdf79be7ac2f0206fc739032f482cfd3f66b18f5248108ff192741beae/coverage-7.10.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1d4f9ce50b9261ad196dc2b2e9f1fbbee21651b54c3097a25ad783679fd18294", size = 216496, upload-time = "2025-08-10T21:25:56.759Z" }, + { url = "https://files.pythonhosted.org/packages/34/b1/bc83788ba31bde6a0c02eb96bbc14b2d1eb083ee073beda18753fa2c4c66/coverage-7.10.3-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:4dd4564207b160d0d45c36a10bc0a3d12563028e8b48cd6459ea322302a156d7", size = 247989, upload-time = "2025-08-10T21:25:58.067Z" }, + { url = "https://files.pythonhosted.org/packages/0c/29/f8bdf88357956c844bd872e87cb16748a37234f7f48c721dc7e981145eb7/coverage-7.10.3-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:5ca3c9530ee072b7cb6a6ea7b640bcdff0ad3b334ae9687e521e59f79b1d0437", size = 250738, upload-time = "2025-08-10T21:25:59.406Z" }, + { url = "https://files.pythonhosted.org/packages/ae/df/6396301d332b71e42bbe624670af9376f63f73a455cc24723656afa95796/coverage-7.10.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b6df359e59fa243c9925ae6507e27f29c46698359f45e568fd51b9315dbbe587", size = 251868, upload-time = "2025-08-10T21:26:00.65Z" }, + { url = "https://files.pythonhosted.org/packages/91/21/d760b2df6139b6ef62c9cc03afb9bcdf7d6e36ed4d078baacffa618b4c1c/coverage-7.10.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a181e4c2c896c2ff64c6312db3bda38e9ade2e1aa67f86a5628ae85873786cea", size = 249790, upload-time = "2025-08-10T21:26:02.009Z" }, + { url = "https://files.pythonhosted.org/packages/69/91/5dcaa134568202397fa4023d7066d4318dc852b53b428052cd914faa05e1/coverage-7.10.3-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:a374d4e923814e8b72b205ef6b3d3a647bb50e66f3558582eda074c976923613", size = 247907, upload-time = "2025-08-10T21:26:03.757Z" }, + { url = "https://files.pythonhosted.org/packages/38/ed/70c0e871cdfef75f27faceada461206c1cc2510c151e1ef8d60a6fedda39/coverage-7.10.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:daeefff05993e5e8c6e7499a8508e7bd94502b6b9a9159c84fd1fe6bce3151cb", size = 249344, upload-time = "2025-08-10T21:26:05.11Z" }, + { url = "https://files.pythonhosted.org/packages/5f/55/c8a273ed503cedc07f8a00dcd843daf28e849f0972e4c6be4c027f418ad6/coverage-7.10.3-cp312-cp312-win32.whl", hash = "sha256:187ecdcac21f9636d570e419773df7bd2fda2e7fa040f812e7f95d0bddf5f79a", size = 218693, upload-time = "2025-08-10T21:26:06.534Z" }, + { url = "https://files.pythonhosted.org/packages/94/58/dd3cfb2473b85be0b6eb8c5b6d80b6fc3f8f23611e69ef745cef8cf8bad5/coverage-7.10.3-cp312-cp312-win_amd64.whl", hash = "sha256:4a50ad2524ee7e4c2a95e60d2b0b83283bdfc745fe82359d567e4f15d3823eb5", size = 219501, upload-time = "2025-08-10T21:26:08.195Z" }, + { url = "https://files.pythonhosted.org/packages/56/af/7cbcbf23d46de6f24246e3f76b30df099d05636b30c53c158a196f7da3ad/coverage-7.10.3-cp312-cp312-win_arm64.whl", hash = "sha256:c112f04e075d3495fa3ed2200f71317da99608cbb2e9345bdb6de8819fc30571", size = 218135, upload-time = "2025-08-10T21:26:09.584Z" }, + { url = "https://files.pythonhosted.org/packages/0a/ff/239e4de9cc149c80e9cc359fab60592365b8c4cbfcad58b8a939d18c6898/coverage-7.10.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:b99e87304ffe0eb97c5308447328a584258951853807afdc58b16143a530518a", size = 216298, upload-time = "2025-08-10T21:26:10.973Z" }, + { url = "https://files.pythonhosted.org/packages/56/da/28717da68f8ba68f14b9f558aaa8f3e39ada8b9a1ae4f4977c8f98b286d5/coverage-7.10.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:4af09c7574d09afbc1ea7da9dcea23665c01f3bc1b1feb061dac135f98ffc53a", size = 216546, upload-time = "2025-08-10T21:26:12.616Z" }, + { url = "https://files.pythonhosted.org/packages/de/bb/e1ade16b9e3f2d6c323faeb6bee8e6c23f3a72760a5d9af102ef56a656cb/coverage-7.10.3-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:488e9b50dc5d2aa9521053cfa706209e5acf5289e81edc28291a24f4e4488f46", size = 247538, upload-time = "2025-08-10T21:26:14.455Z" }, + { url = "https://files.pythonhosted.org/packages/ea/2f/6ae1db51dc34db499bfe340e89f79a63bd115fc32513a7bacdf17d33cd86/coverage-7.10.3-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:913ceddb4289cbba3a310704a424e3fb7aac2bc0c3a23ea473193cb290cf17d4", size = 250141, upload-time = "2025-08-10T21:26:15.787Z" }, + { url = "https://files.pythonhosted.org/packages/4f/ed/33efd8819895b10c66348bf26f011dd621e804866c996ea6893d682218df/coverage-7.10.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6b1f91cbc78c7112ab84ed2a8defbccd90f888fcae40a97ddd6466b0bec6ae8a", size = 251415, upload-time = "2025-08-10T21:26:17.535Z" }, + { url = "https://files.pythonhosted.org/packages/26/04/cb83826f313d07dc743359c9914d9bc460e0798da9a0e38b4f4fabc207ed/coverage-7.10.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:b0bac054d45af7cd938834b43a9878b36ea92781bcb009eab040a5b09e9927e3", size = 249575, upload-time = "2025-08-10T21:26:18.921Z" }, + { url = "https://files.pythonhosted.org/packages/2d/fd/ae963c7a8e9581c20fa4355ab8940ca272554d8102e872dbb932a644e410/coverage-7.10.3-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:fe72cbdd12d9e0f4aca873fa6d755e103888a7f9085e4a62d282d9d5b9f7928c", size = 247466, upload-time = "2025-08-10T21:26:20.263Z" }, + { url = "https://files.pythonhosted.org/packages/99/e8/b68d1487c6af370b8d5ef223c6d7e250d952c3acfbfcdbf1a773aa0da9d2/coverage-7.10.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:c1e2e927ab3eadd7c244023927d646e4c15c65bb2ac7ae3c3e9537c013700d21", size = 249084, upload-time = "2025-08-10T21:26:21.638Z" }, + { url = "https://files.pythonhosted.org/packages/66/4d/a0bcb561645c2c1e21758d8200443669d6560d2a2fb03955291110212ec4/coverage-7.10.3-cp313-cp313-win32.whl", hash = "sha256:24d0c13de473b04920ddd6e5da3c08831b1170b8f3b17461d7429b61cad59ae0", size = 218735, upload-time = "2025-08-10T21:26:23.009Z" }, + { url = "https://files.pythonhosted.org/packages/6a/c3/78b4adddbc0feb3b223f62761e5f9b4c5a758037aaf76e0a5845e9e35e48/coverage-7.10.3-cp313-cp313-win_amd64.whl", hash = "sha256:3564aae76bce4b96e2345cf53b4c87e938c4985424a9be6a66ee902626edec4c", size = 219531, upload-time = "2025-08-10T21:26:24.474Z" }, + { url = "https://files.pythonhosted.org/packages/70/1b/1229c0b2a527fa5390db58d164aa896d513a1fbb85a1b6b6676846f00552/coverage-7.10.3-cp313-cp313-win_arm64.whl", hash = "sha256:f35580f19f297455f44afcd773c9c7a058e52eb6eb170aa31222e635f2e38b87", size = 218162, upload-time = "2025-08-10T21:26:25.847Z" }, + { url = "https://files.pythonhosted.org/packages/fc/26/1c1f450e15a3bf3eaecf053ff64538a2612a23f05b21d79ce03be9ff5903/coverage-7.10.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:07009152f497a0464ffdf2634586787aea0e69ddd023eafb23fc38267db94b84", size = 217003, upload-time = "2025-08-10T21:26:27.231Z" }, + { url = "https://files.pythonhosted.org/packages/29/96/4b40036181d8c2948454b458750960956a3c4785f26a3c29418bbbee1666/coverage-7.10.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:8dd2ba5f0c7e7e8cc418be2f0c14c4d9e3f08b8fb8e4c0f83c2fe87d03eb655e", size = 217238, upload-time = "2025-08-10T21:26:28.83Z" }, + { url = "https://files.pythonhosted.org/packages/62/23/8dfc52e95da20957293fb94d97397a100e63095ec1e0ef5c09dd8c6f591a/coverage-7.10.3-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:1ae22b97003c74186e034a93e4f946c75fad8c0ce8d92fbbc168b5e15ee2841f", size = 258561, upload-time = "2025-08-10T21:26:30.475Z" }, + { url = "https://files.pythonhosted.org/packages/59/95/00e7fcbeda3f632232f4c07dde226afe3511a7781a000aa67798feadc535/coverage-7.10.3-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:eb329f1046888a36b1dc35504d3029e1dd5afe2196d94315d18c45ee380f67d5", size = 260735, upload-time = "2025-08-10T21:26:32.333Z" }, + { url = "https://files.pythonhosted.org/packages/9e/4c/f4666cbc4571804ba2a65b078ff0de600b0b577dc245389e0bc9b69ae7ca/coverage-7.10.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ce01048199a91f07f96ca3074b0c14021f4fe7ffd29a3e6a188ac60a5c3a4af8", size = 262960, upload-time = "2025-08-10T21:26:33.701Z" }, + { url = "https://files.pythonhosted.org/packages/c1/a5/8a9e8a7b12a290ed98b60f73d1d3e5e9ced75a4c94a0d1a671ce3ddfff2a/coverage-7.10.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:08b989a06eb9dfacf96d42b7fb4c9a22bafa370d245dc22fa839f2168c6f9fa1", size = 260515, upload-time = "2025-08-10T21:26:35.16Z" }, + { url = "https://files.pythonhosted.org/packages/86/11/bb59f7f33b2cac0c5b17db0d9d0abba9c90d9eda51a6e727b43bd5fce4ae/coverage-7.10.3-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:669fe0d4e69c575c52148511029b722ba8d26e8a3129840c2ce0522e1452b256", size = 258278, upload-time = "2025-08-10T21:26:36.539Z" }, + { url = "https://files.pythonhosted.org/packages/cc/22/3646f8903743c07b3e53fded0700fed06c580a980482f04bf9536657ac17/coverage-7.10.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:3262d19092771c83f3413831d9904b1ccc5f98da5de4ffa4ad67f5b20c7aaf7b", size = 259408, upload-time = "2025-08-10T21:26:37.954Z" }, + { url = "https://files.pythonhosted.org/packages/d2/5c/6375e9d905da22ddea41cd85c30994b8b6f6c02e44e4c5744b76d16b026f/coverage-7.10.3-cp313-cp313t-win32.whl", hash = "sha256:cc0ee4b2ccd42cab7ee6be46d8a67d230cb33a0a7cd47a58b587a7063b6c6b0e", size = 219396, upload-time = "2025-08-10T21:26:39.426Z" }, + { url = "https://files.pythonhosted.org/packages/33/3b/7da37fd14412b8c8b6e73c3e7458fef6b1b05a37f990a9776f88e7740c89/coverage-7.10.3-cp313-cp313t-win_amd64.whl", hash = "sha256:03db599f213341e2960430984e04cf35fb179724e052a3ee627a068653cf4a7c", size = 220458, upload-time = "2025-08-10T21:26:40.905Z" }, + { url = "https://files.pythonhosted.org/packages/28/cc/59a9a70f17edab513c844ee7a5c63cf1057041a84cc725b46a51c6f8301b/coverage-7.10.3-cp313-cp313t-win_arm64.whl", hash = "sha256:46eae7893ba65f53c71284585a262f083ef71594f05ec5c85baf79c402369098", size = 218722, upload-time = "2025-08-10T21:26:42.362Z" }, + { url = "https://files.pythonhosted.org/packages/2d/84/bb773b51a06edbf1231b47dc810a23851f2796e913b335a0fa364773b842/coverage-7.10.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:bce8b8180912914032785850d8f3aacb25ec1810f5f54afc4a8b114e7a9b55de", size = 216280, upload-time = "2025-08-10T21:26:44.132Z" }, + { url = "https://files.pythonhosted.org/packages/92/a8/4d8ca9c111d09865f18d56facff64d5fa076a5593c290bd1cfc5dceb8dba/coverage-7.10.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:07790b4b37d56608536f7c1079bd1aa511567ac2966d33d5cec9cf520c50a7c8", size = 216557, upload-time = "2025-08-10T21:26:45.598Z" }, + { url = "https://files.pythonhosted.org/packages/fe/b2/eb668bfc5060194bc5e1ccd6f664e8e045881cfee66c42a2aa6e6c5b26e8/coverage-7.10.3-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:e79367ef2cd9166acedcbf136a458dfe9a4a2dd4d1ee95738fb2ee581c56f667", size = 247598, upload-time = "2025-08-10T21:26:47.081Z" }, + { url = "https://files.pythonhosted.org/packages/fd/b0/9faa4ac62c8822219dd83e5d0e73876398af17d7305968aed8d1606d1830/coverage-7.10.3-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:419d2a0f769f26cb1d05e9ccbc5eab4cb5d70231604d47150867c07822acbdf4", size = 250131, upload-time = "2025-08-10T21:26:48.65Z" }, + { url = "https://files.pythonhosted.org/packages/4e/90/203537e310844d4bf1bdcfab89c1e05c25025c06d8489b9e6f937ad1a9e2/coverage-7.10.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ee221cf244757cdc2ac882e3062ab414b8464ad9c884c21e878517ea64b3fa26", size = 251485, upload-time = "2025-08-10T21:26:50.368Z" }, + { url = "https://files.pythonhosted.org/packages/b9/b2/9d894b26bc53c70a1fe503d62240ce6564256d6d35600bdb86b80e516e7d/coverage-7.10.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c2079d8cdd6f7373d628e14b3357f24d1db02c9dc22e6a007418ca7a2be0435a", size = 249488, upload-time = "2025-08-10T21:26:52.045Z" }, + { url = "https://files.pythonhosted.org/packages/b4/28/af167dbac5281ba6c55c933a0ca6675d68347d5aee39cacc14d44150b922/coverage-7.10.3-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:bd8df1f83c0703fa3ca781b02d36f9ec67ad9cb725b18d486405924f5e4270bd", size = 247419, upload-time = "2025-08-10T21:26:53.533Z" }, + { url = "https://files.pythonhosted.org/packages/f4/1c/9a4ddc9f0dcb150d4cd619e1c4bb39bcf694c6129220bdd1e5895d694dda/coverage-7.10.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:6b4e25e0fa335c8aa26e42a52053f3786a61cc7622b4d54ae2dad994aa754fec", size = 248917, upload-time = "2025-08-10T21:26:55.11Z" }, + { url = "https://files.pythonhosted.org/packages/92/27/c6a60c7cbe10dbcdcd7fc9ee89d531dc04ea4c073800279bb269954c5a9f/coverage-7.10.3-cp314-cp314-win32.whl", hash = "sha256:d7c3d02c2866deb217dce664c71787f4b25420ea3eaf87056f44fb364a3528f5", size = 218999, upload-time = "2025-08-10T21:26:56.637Z" }, + { url = "https://files.pythonhosted.org/packages/36/09/a94c1369964ab31273576615d55e7d14619a1c47a662ed3e2a2fe4dee7d4/coverage-7.10.3-cp314-cp314-win_amd64.whl", hash = "sha256:9c8916d44d9e0fe6cdb2227dc6b0edd8bc6c8ef13438bbbf69af7482d9bb9833", size = 219801, upload-time = "2025-08-10T21:26:58.207Z" }, + { url = "https://files.pythonhosted.org/packages/23/59/f5cd2a80f401c01cf0f3add64a7b791b7d53fd6090a4e3e9ea52691cf3c4/coverage-7.10.3-cp314-cp314-win_arm64.whl", hash = "sha256:1007d6a2b3cf197c57105cc1ba390d9ff7f0bee215ced4dea530181e49c65ab4", size = 218381, upload-time = "2025-08-10T21:26:59.707Z" }, + { url = "https://files.pythonhosted.org/packages/73/3d/89d65baf1ea39e148ee989de6da601469ba93c1d905b17dfb0b83bd39c96/coverage-7.10.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:ebc8791d346410d096818788877d675ca55c91db87d60e8f477bd41c6970ffc6", size = 217019, upload-time = "2025-08-10T21:27:01.242Z" }, + { url = "https://files.pythonhosted.org/packages/7d/7d/d9850230cd9c999ce3a1e600f85c2fff61a81c301334d7a1faa1a5ba19c8/coverage-7.10.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1f4e4d8e75f6fd3c6940ebeed29e3d9d632e1f18f6fb65d33086d99d4d073241", size = 217237, upload-time = "2025-08-10T21:27:03.442Z" }, + { url = "https://files.pythonhosted.org/packages/36/51/b87002d417202ab27f4a1cd6bd34ee3b78f51b3ddbef51639099661da991/coverage-7.10.3-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:24581ed69f132b6225a31b0228ae4885731cddc966f8a33fe5987288bdbbbd5e", size = 258735, upload-time = "2025-08-10T21:27:05.124Z" }, + { url = "https://files.pythonhosted.org/packages/1c/02/1f8612bfcb46fc7ca64a353fff1cd4ed932bb6e0b4e0bb88b699c16794b8/coverage-7.10.3-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:ec151569ddfccbf71bac8c422dce15e176167385a00cd86e887f9a80035ce8a5", size = 260901, upload-time = "2025-08-10T21:27:06.68Z" }, + { url = "https://files.pythonhosted.org/packages/aa/3a/fe39e624ddcb2373908bd922756384bb70ac1c5009b0d1674eb326a3e428/coverage-7.10.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2ae8e7c56290b908ee817200c0b65929b8050bc28530b131fe7c6dfee3e7d86b", size = 263157, upload-time = "2025-08-10T21:27:08.398Z" }, + { url = "https://files.pythonhosted.org/packages/5e/89/496b6d5a10fa0d0691a633bb2b2bcf4f38f0bdfcbde21ad9e32d1af328ed/coverage-7.10.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:5fb742309766d7e48e9eb4dc34bc95a424707bc6140c0e7d9726e794f11b92a0", size = 260597, upload-time = "2025-08-10T21:27:10.237Z" }, + { url = "https://files.pythonhosted.org/packages/b6/a6/8b5bf6a9e8c6aaeb47d5fe9687014148efc05c3588110246d5fdeef9b492/coverage-7.10.3-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:c65e2a5b32fbe1e499f1036efa6eb9cb4ea2bf6f7168d0e7a5852f3024f471b1", size = 258353, upload-time = "2025-08-10T21:27:11.773Z" }, + { url = "https://files.pythonhosted.org/packages/c3/6d/ad131be74f8afd28150a07565dfbdc86592fd61d97e2dc83383d9af219f0/coverage-7.10.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:d48d2cb07d50f12f4f18d2bb75d9d19e3506c26d96fffabf56d22936e5ed8f7c", size = 259504, upload-time = "2025-08-10T21:27:13.254Z" }, + { url = "https://files.pythonhosted.org/packages/ec/30/fc9b5097092758cba3375a8cc4ff61774f8cd733bcfb6c9d21a60077a8d8/coverage-7.10.3-cp314-cp314t-win32.whl", hash = "sha256:dec0d9bc15ee305e09fe2cd1911d3f0371262d3cfdae05d79515d8cb712b4869", size = 219782, upload-time = "2025-08-10T21:27:14.736Z" }, + { url = "https://files.pythonhosted.org/packages/72/9b/27fbf79451b1fac15c4bda6ec6e9deae27cf7c0648c1305aa21a3454f5c4/coverage-7.10.3-cp314-cp314t-win_amd64.whl", hash = "sha256:424ea93a323aa0f7f01174308ea78bde885c3089ec1bef7143a6d93c3e24ef64", size = 220898, upload-time = "2025-08-10T21:27:16.297Z" }, + { url = "https://files.pythonhosted.org/packages/d1/cf/a32bbf92869cbf0b7c8b84325327bfc718ad4b6d2c63374fef3d58e39306/coverage-7.10.3-cp314-cp314t-win_arm64.whl", hash = "sha256:f5983c132a62d93d71c9ef896a0b9bf6e6828d8d2ea32611f58684fba60bba35", size = 218922, upload-time = "2025-08-10T21:27:18.22Z" }, + { url = "https://files.pythonhosted.org/packages/84/19/e67f4ae24e232c7f713337f3f4f7c9c58afd0c02866fb07c7b9255a19ed7/coverage-7.10.3-py3-none-any.whl", hash = "sha256:416a8d74dc0adfd33944ba2f405897bab87b7e9e84a391e09d241956bd953ce1", size = 207921, upload-time = "2025-08-10T21:27:38.254Z" }, ] [package.optional-dependencies] @@ -634,15 +639,15 @@ wheels = [ [[package]] name = "hypothesis" -version = "6.137.1" +version = "6.138.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "attrs" }, { name = "sortedcontainers" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/65/92/70f29b04e4d7acf7f9a0c3dd52619853715ad9ae092a8e5d89bc7bdc39ec/hypothesis-6.137.1.tar.gz", hash = "sha256:b086e644456da79ad460fdaf8fbf90a41a661e8a4076232dd4ea64cfbc0d0529", size = 460593, upload-time = "2025-08-05T06:31:46.777Z" } +sdist = { url = "https://files.pythonhosted.org/packages/b2/06/a6076eb444d961da88c76eb5ac55e4d46171eaa1dd93b06b514dd0f602a7/hypothesis-6.138.0.tar.gz", hash = "sha256:0169339db3fb27fe8229fb2c4c9fe0691536769b59e3e974c061e83362d4e057", size = 462995, upload-time = "2025-08-13T01:56:38.6Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/1a/13/92753f97f70f3584a70ccbd2a678878ea43d5880c4e009664c3fe9fe7e50/hypothesis-6.137.1-py3-none-any.whl", hash = "sha256:7cbda6a98ed4d32aad31a5fc5bff5e119b9275fe2579a7b08863cba313a4b9be", size = 527566, upload-time = "2025-08-05T06:31:43.323Z" }, + { url = "https://files.pythonhosted.org/packages/59/fb/049563700c9a5dcd03293b5320c1bfb6316acd1d9eea6d8719218a56cff1/hypothesis-6.138.0-py3-none-any.whl", hash = "sha256:3c3da60c1e3bc7ec766461373c5d5c32e13262f17739f794ad764323ab644544", size = 529863, upload-time = "2025-08-13T01:56:34.395Z" }, ] [[package]] @@ -847,68 +852,92 @@ wheels = [ [[package]] name = "kiwisolver" -version = "1.4.8" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/82/59/7c91426a8ac292e1cdd53a63b6d9439abd573c875c3f92c146767dd33faf/kiwisolver-1.4.8.tar.gz", hash = "sha256:23d5f023bdc8c7e54eb65f03ca5d5bb25b601eac4d7f1a042888a1f45237987e", size = 97538, upload-time = "2024-12-24T18:30:51.519Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/da/ed/c913ee28936c371418cb167b128066ffb20bbf37771eecc2c97edf8a6e4c/kiwisolver-1.4.8-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:a4d3601908c560bdf880f07d94f31d734afd1bb71e96585cace0e38ef44c6d84", size = 124635, upload-time = "2024-12-24T18:28:51.826Z" }, - { url = "https://files.pythonhosted.org/packages/4c/45/4a7f896f7467aaf5f56ef093d1f329346f3b594e77c6a3c327b2d415f521/kiwisolver-1.4.8-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:856b269c4d28a5c0d5e6c1955ec36ebfd1651ac00e1ce0afa3e28da95293b561", size = 66717, upload-time = "2024-12-24T18:28:54.256Z" }, - { url = "https://files.pythonhosted.org/packages/5f/b4/c12b3ac0852a3a68f94598d4c8d569f55361beef6159dce4e7b624160da2/kiwisolver-1.4.8-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c2b9a96e0f326205af81a15718a9073328df1173a2619a68553decb7097fd5d7", size = 65413, upload-time = "2024-12-24T18:28:55.184Z" }, - { url = "https://files.pythonhosted.org/packages/a9/98/1df4089b1ed23d83d410adfdc5947245c753bddfbe06541c4aae330e9e70/kiwisolver-1.4.8-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c5020c83e8553f770cb3b5fc13faac40f17e0b205bd237aebd21d53d733adb03", size = 1343994, upload-time = "2024-12-24T18:28:57.493Z" }, - { url = "https://files.pythonhosted.org/packages/8d/bf/b4b169b050c8421a7c53ea1ea74e4ef9c335ee9013216c558a047f162d20/kiwisolver-1.4.8-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dace81d28c787956bfbfbbfd72fdcef014f37d9b48830829e488fdb32b49d954", size = 1434804, upload-time = "2024-12-24T18:29:00.077Z" }, - { url = "https://files.pythonhosted.org/packages/66/5a/e13bd341fbcf73325ea60fdc8af752addf75c5079867af2e04cc41f34434/kiwisolver-1.4.8-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:11e1022b524bd48ae56c9b4f9296bce77e15a2e42a502cceba602f804b32bb79", size = 1450690, upload-time = "2024-12-24T18:29:01.401Z" }, - { url = "https://files.pythonhosted.org/packages/9b/4f/5955dcb376ba4a830384cc6fab7d7547bd6759fe75a09564910e9e3bb8ea/kiwisolver-1.4.8-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3b9b4d2892fefc886f30301cdd80debd8bb01ecdf165a449eb6e78f79f0fabd6", size = 1376839, upload-time = "2024-12-24T18:29:02.685Z" }, - { url = "https://files.pythonhosted.org/packages/3a/97/5edbed69a9d0caa2e4aa616ae7df8127e10f6586940aa683a496c2c280b9/kiwisolver-1.4.8-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a96c0e790ee875d65e340ab383700e2b4891677b7fcd30a699146f9384a2bb0", size = 1435109, upload-time = "2024-12-24T18:29:04.113Z" }, - { url = "https://files.pythonhosted.org/packages/13/fc/e756382cb64e556af6c1809a1bbb22c141bbc2445049f2da06b420fe52bf/kiwisolver-1.4.8-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:23454ff084b07ac54ca8be535f4174170c1094a4cff78fbae4f73a4bcc0d4dab", size = 2245269, upload-time = "2024-12-24T18:29:05.488Z" }, - { url = "https://files.pythonhosted.org/packages/76/15/e59e45829d7f41c776d138245cabae6515cb4eb44b418f6d4109c478b481/kiwisolver-1.4.8-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:87b287251ad6488e95b4f0b4a79a6d04d3ea35fde6340eb38fbd1ca9cd35bbbc", size = 2393468, upload-time = "2024-12-24T18:29:06.79Z" }, - { url = "https://files.pythonhosted.org/packages/e9/39/483558c2a913ab8384d6e4b66a932406f87c95a6080112433da5ed668559/kiwisolver-1.4.8-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:b21dbe165081142b1232a240fc6383fd32cdd877ca6cc89eab93e5f5883e1c25", size = 2355394, upload-time = "2024-12-24T18:29:08.24Z" }, - { url = "https://files.pythonhosted.org/packages/01/aa/efad1fbca6570a161d29224f14b082960c7e08268a133fe5dc0f6906820e/kiwisolver-1.4.8-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:768cade2c2df13db52475bd28d3a3fac8c9eff04b0e9e2fda0f3760f20b3f7fc", size = 2490901, upload-time = "2024-12-24T18:29:09.653Z" }, - { url = "https://files.pythonhosted.org/packages/c9/4f/15988966ba46bcd5ab9d0c8296914436720dd67fca689ae1a75b4ec1c72f/kiwisolver-1.4.8-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:d47cfb2650f0e103d4bf68b0b5804c68da97272c84bb12850d877a95c056bd67", size = 2312306, upload-time = "2024-12-24T18:29:12.644Z" }, - { url = "https://files.pythonhosted.org/packages/2d/27/bdf1c769c83f74d98cbc34483a972f221440703054894a37d174fba8aa68/kiwisolver-1.4.8-cp311-cp311-win_amd64.whl", hash = "sha256:ed33ca2002a779a2e20eeb06aea7721b6e47f2d4b8a8ece979d8ba9e2a167e34", size = 71966, upload-time = "2024-12-24T18:29:14.089Z" }, - { url = "https://files.pythonhosted.org/packages/4a/c9/9642ea855604aeb2968a8e145fc662edf61db7632ad2e4fb92424be6b6c0/kiwisolver-1.4.8-cp311-cp311-win_arm64.whl", hash = "sha256:16523b40aab60426ffdebe33ac374457cf62863e330a90a0383639ce14bf44b2", size = 65311, upload-time = "2024-12-24T18:29:15.892Z" }, - { url = "https://files.pythonhosted.org/packages/fc/aa/cea685c4ab647f349c3bc92d2daf7ae34c8e8cf405a6dcd3a497f58a2ac3/kiwisolver-1.4.8-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:d6af5e8815fd02997cb6ad9bbed0ee1e60014438ee1a5c2444c96f87b8843502", size = 124152, upload-time = "2024-12-24T18:29:16.85Z" }, - { url = "https://files.pythonhosted.org/packages/c5/0b/8db6d2e2452d60d5ebc4ce4b204feeb16176a851fd42462f66ade6808084/kiwisolver-1.4.8-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:bade438f86e21d91e0cf5dd7c0ed00cda0f77c8c1616bd83f9fc157fa6760d31", size = 66555, upload-time = "2024-12-24T18:29:19.146Z" }, - { url = "https://files.pythonhosted.org/packages/60/26/d6a0db6785dd35d3ba5bf2b2df0aedc5af089962c6eb2cbf67a15b81369e/kiwisolver-1.4.8-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b83dc6769ddbc57613280118fb4ce3cd08899cc3369f7d0e0fab518a7cf37fdb", size = 65067, upload-time = "2024-12-24T18:29:20.096Z" }, - { url = "https://files.pythonhosted.org/packages/c9/ed/1d97f7e3561e09757a196231edccc1bcf59d55ddccefa2afc9c615abd8e0/kiwisolver-1.4.8-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:111793b232842991be367ed828076b03d96202c19221b5ebab421ce8bcad016f", size = 1378443, upload-time = "2024-12-24T18:29:22.843Z" }, - { url = "https://files.pythonhosted.org/packages/29/61/39d30b99954e6b46f760e6289c12fede2ab96a254c443639052d1b573fbc/kiwisolver-1.4.8-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:257af1622860e51b1a9d0ce387bf5c2c4f36a90594cb9514f55b074bcc787cfc", size = 1472728, upload-time = "2024-12-24T18:29:24.463Z" }, - { url = "https://files.pythonhosted.org/packages/0c/3e/804163b932f7603ef256e4a715e5843a9600802bb23a68b4e08c8c0ff61d/kiwisolver-1.4.8-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:69b5637c3f316cab1ec1c9a12b8c5f4750a4c4b71af9157645bf32830e39c03a", size = 1478388, upload-time = "2024-12-24T18:29:25.776Z" }, - { url = "https://files.pythonhosted.org/packages/8a/9e/60eaa75169a154700be74f875a4d9961b11ba048bef315fbe89cb6999056/kiwisolver-1.4.8-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:782bb86f245ec18009890e7cb8d13a5ef54dcf2ebe18ed65f795e635a96a1c6a", size = 1413849, upload-time = "2024-12-24T18:29:27.202Z" }, - { url = "https://files.pythonhosted.org/packages/bc/b3/9458adb9472e61a998c8c4d95cfdfec91c73c53a375b30b1428310f923e4/kiwisolver-1.4.8-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cc978a80a0db3a66d25767b03688f1147a69e6237175c0f4ffffaaedf744055a", size = 1475533, upload-time = "2024-12-24T18:29:28.638Z" }, - { url = "https://files.pythonhosted.org/packages/e4/7a/0a42d9571e35798de80aef4bb43a9b672aa7f8e58643d7bd1950398ffb0a/kiwisolver-1.4.8-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:36dbbfd34838500a31f52c9786990d00150860e46cd5041386f217101350f0d3", size = 2268898, upload-time = "2024-12-24T18:29:30.368Z" }, - { url = "https://files.pythonhosted.org/packages/d9/07/1255dc8d80271400126ed8db35a1795b1a2c098ac3a72645075d06fe5c5d/kiwisolver-1.4.8-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:eaa973f1e05131de5ff3569bbba7f5fd07ea0595d3870ed4a526d486fe57fa1b", size = 2425605, upload-time = "2024-12-24T18:29:33.151Z" }, - { url = "https://files.pythonhosted.org/packages/84/df/5a3b4cf13780ef6f6942df67b138b03b7e79e9f1f08f57c49957d5867f6e/kiwisolver-1.4.8-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:a66f60f8d0c87ab7f59b6fb80e642ebb29fec354a4dfad687ca4092ae69d04f4", size = 2375801, upload-time = "2024-12-24T18:29:34.584Z" }, - { url = "https://files.pythonhosted.org/packages/8f/10/2348d068e8b0f635c8c86892788dac7a6b5c0cb12356620ab575775aad89/kiwisolver-1.4.8-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:858416b7fb777a53f0c59ca08190ce24e9abbd3cffa18886a5781b8e3e26f65d", size = 2520077, upload-time = "2024-12-24T18:29:36.138Z" }, - { url = "https://files.pythonhosted.org/packages/32/d8/014b89fee5d4dce157d814303b0fce4d31385a2af4c41fed194b173b81ac/kiwisolver-1.4.8-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:085940635c62697391baafaaeabdf3dd7a6c3643577dde337f4d66eba021b2b8", size = 2338410, upload-time = "2024-12-24T18:29:39.991Z" }, - { url = "https://files.pythonhosted.org/packages/bd/72/dfff0cc97f2a0776e1c9eb5bef1ddfd45f46246c6533b0191887a427bca5/kiwisolver-1.4.8-cp312-cp312-win_amd64.whl", hash = "sha256:01c3d31902c7db5fb6182832713d3b4122ad9317c2c5877d0539227d96bb2e50", size = 71853, upload-time = "2024-12-24T18:29:42.006Z" }, - { url = "https://files.pythonhosted.org/packages/dc/85/220d13d914485c0948a00f0b9eb419efaf6da81b7d72e88ce2391f7aed8d/kiwisolver-1.4.8-cp312-cp312-win_arm64.whl", hash = "sha256:a3c44cb68861de93f0c4a8175fbaa691f0aa22550c331fefef02b618a9dcb476", size = 65424, upload-time = "2024-12-24T18:29:44.38Z" }, - { url = "https://files.pythonhosted.org/packages/79/b3/e62464a652f4f8cd9006e13d07abad844a47df1e6537f73ddfbf1bc997ec/kiwisolver-1.4.8-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:1c8ceb754339793c24aee1c9fb2485b5b1f5bb1c2c214ff13368431e51fc9a09", size = 124156, upload-time = "2024-12-24T18:29:45.368Z" }, - { url = "https://files.pythonhosted.org/packages/8d/2d/f13d06998b546a2ad4f48607a146e045bbe48030774de29f90bdc573df15/kiwisolver-1.4.8-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:54a62808ac74b5e55a04a408cda6156f986cefbcf0ada13572696b507cc92fa1", size = 66555, upload-time = "2024-12-24T18:29:46.37Z" }, - { url = "https://files.pythonhosted.org/packages/59/e3/b8bd14b0a54998a9fd1e8da591c60998dc003618cb19a3f94cb233ec1511/kiwisolver-1.4.8-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:68269e60ee4929893aad82666821aaacbd455284124817af45c11e50a4b42e3c", size = 65071, upload-time = "2024-12-24T18:29:47.333Z" }, - { url = "https://files.pythonhosted.org/packages/f0/1c/6c86f6d85ffe4d0ce04228d976f00674f1df5dc893bf2dd4f1928748f187/kiwisolver-1.4.8-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:34d142fba9c464bc3bbfeff15c96eab0e7310343d6aefb62a79d51421fcc5f1b", size = 1378053, upload-time = "2024-12-24T18:29:49.636Z" }, - { url = "https://files.pythonhosted.org/packages/4e/b9/1c6e9f6dcb103ac5cf87cb695845f5fa71379021500153566d8a8a9fc291/kiwisolver-1.4.8-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3ddc373e0eef45b59197de815b1b28ef89ae3955e7722cc9710fb91cd77b7f47", size = 1472278, upload-time = "2024-12-24T18:29:51.164Z" }, - { url = "https://files.pythonhosted.org/packages/ee/81/aca1eb176de671f8bda479b11acdc42c132b61a2ac861c883907dde6debb/kiwisolver-1.4.8-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:77e6f57a20b9bd4e1e2cedda4d0b986ebd0216236f0106e55c28aea3d3d69b16", size = 1478139, upload-time = "2024-12-24T18:29:52.594Z" }, - { url = "https://files.pythonhosted.org/packages/49/f4/e081522473671c97b2687d380e9e4c26f748a86363ce5af48b4a28e48d06/kiwisolver-1.4.8-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:08e77738ed7538f036cd1170cbed942ef749137b1311fa2bbe2a7fda2f6bf3cc", size = 1413517, upload-time = "2024-12-24T18:29:53.941Z" }, - { url = "https://files.pythonhosted.org/packages/8f/e9/6a7d025d8da8c4931522922cd706105aa32b3291d1add8c5427cdcd66e63/kiwisolver-1.4.8-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a5ce1e481a74b44dd5e92ff03ea0cb371ae7a0268318e202be06c8f04f4f1246", size = 1474952, upload-time = "2024-12-24T18:29:56.523Z" }, - { url = "https://files.pythonhosted.org/packages/82/13/13fa685ae167bee5d94b415991c4fc7bb0a1b6ebea6e753a87044b209678/kiwisolver-1.4.8-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:fc2ace710ba7c1dfd1a3b42530b62b9ceed115f19a1656adefce7b1782a37794", size = 2269132, upload-time = "2024-12-24T18:29:57.989Z" }, - { url = "https://files.pythonhosted.org/packages/ef/92/bb7c9395489b99a6cb41d502d3686bac692586db2045adc19e45ee64ed23/kiwisolver-1.4.8-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:3452046c37c7692bd52b0e752b87954ef86ee2224e624ef7ce6cb21e8c41cc1b", size = 2425997, upload-time = "2024-12-24T18:29:59.393Z" }, - { url = "https://files.pythonhosted.org/packages/ed/12/87f0e9271e2b63d35d0d8524954145837dd1a6c15b62a2d8c1ebe0f182b4/kiwisolver-1.4.8-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:7e9a60b50fe8b2ec6f448fe8d81b07e40141bfced7f896309df271a0b92f80f3", size = 2376060, upload-time = "2024-12-24T18:30:01.338Z" }, - { url = "https://files.pythonhosted.org/packages/02/6e/c8af39288edbce8bf0fa35dee427b082758a4b71e9c91ef18fa667782138/kiwisolver-1.4.8-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:918139571133f366e8362fa4a297aeba86c7816b7ecf0bc79168080e2bd79957", size = 2520471, upload-time = "2024-12-24T18:30:04.574Z" }, - { url = "https://files.pythonhosted.org/packages/13/78/df381bc7b26e535c91469f77f16adcd073beb3e2dd25042efd064af82323/kiwisolver-1.4.8-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e063ef9f89885a1d68dd8b2e18f5ead48653176d10a0e324e3b0030e3a69adeb", size = 2338793, upload-time = "2024-12-24T18:30:06.25Z" }, - { url = "https://files.pythonhosted.org/packages/d0/dc/c1abe38c37c071d0fc71c9a474fd0b9ede05d42f5a458d584619cfd2371a/kiwisolver-1.4.8-cp313-cp313-win_amd64.whl", hash = "sha256:a17b7c4f5b2c51bb68ed379defd608a03954a1845dfed7cc0117f1cc8a9b7fd2", size = 71855, upload-time = "2024-12-24T18:30:07.535Z" }, - { url = "https://files.pythonhosted.org/packages/a0/b6/21529d595b126ac298fdd90b705d87d4c5693de60023e0efcb4f387ed99e/kiwisolver-1.4.8-cp313-cp313-win_arm64.whl", hash = "sha256:3cd3bc628b25f74aedc6d374d5babf0166a92ff1317f46267f12d2ed54bc1d30", size = 65430, upload-time = "2024-12-24T18:30:08.504Z" }, - { url = "https://files.pythonhosted.org/packages/34/bd/b89380b7298e3af9b39f49334e3e2a4af0e04819789f04b43d560516c0c8/kiwisolver-1.4.8-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:370fd2df41660ed4e26b8c9d6bbcad668fbe2560462cba151a721d49e5b6628c", size = 126294, upload-time = "2024-12-24T18:30:09.508Z" }, - { url = "https://files.pythonhosted.org/packages/83/41/5857dc72e5e4148eaac5aa76e0703e594e4465f8ab7ec0fc60e3a9bb8fea/kiwisolver-1.4.8-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:84a2f830d42707de1d191b9490ac186bf7997a9495d4e9072210a1296345f7dc", size = 67736, upload-time = "2024-12-24T18:30:11.039Z" }, - { url = "https://files.pythonhosted.org/packages/e1/d1/be059b8db56ac270489fb0b3297fd1e53d195ba76e9bbb30e5401fa6b759/kiwisolver-1.4.8-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:7a3ad337add5148cf51ce0b55642dc551c0b9d6248458a757f98796ca7348712", size = 66194, upload-time = "2024-12-24T18:30:14.886Z" }, - { url = "https://files.pythonhosted.org/packages/e1/83/4b73975f149819eb7dcf9299ed467eba068ecb16439a98990dcb12e63fdd/kiwisolver-1.4.8-cp313-cp313t-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7506488470f41169b86d8c9aeff587293f530a23a23a49d6bc64dab66bedc71e", size = 1465942, upload-time = "2024-12-24T18:30:18.927Z" }, - { url = "https://files.pythonhosted.org/packages/c7/2c/30a5cdde5102958e602c07466bce058b9d7cb48734aa7a4327261ac8e002/kiwisolver-1.4.8-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2f0121b07b356a22fb0414cec4666bbe36fd6d0d759db3d37228f496ed67c880", size = 1595341, upload-time = "2024-12-24T18:30:22.102Z" }, - { url = "https://files.pythonhosted.org/packages/ff/9b/1e71db1c000385aa069704f5990574b8244cce854ecd83119c19e83c9586/kiwisolver-1.4.8-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d6d6bd87df62c27d4185de7c511c6248040afae67028a8a22012b010bc7ad062", size = 1598455, upload-time = "2024-12-24T18:30:24.947Z" }, - { url = "https://files.pythonhosted.org/packages/85/92/c8fec52ddf06231b31cbb779af77e99b8253cd96bd135250b9498144c78b/kiwisolver-1.4.8-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:291331973c64bb9cce50bbe871fb2e675c4331dab4f31abe89f175ad7679a4d7", size = 1522138, upload-time = "2024-12-24T18:30:26.286Z" }, - { url = "https://files.pythonhosted.org/packages/0b/51/9eb7e2cd07a15d8bdd976f6190c0164f92ce1904e5c0c79198c4972926b7/kiwisolver-1.4.8-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:893f5525bb92d3d735878ec00f781b2de998333659507d29ea4466208df37bed", size = 1582857, upload-time = "2024-12-24T18:30:28.86Z" }, - { url = "https://files.pythonhosted.org/packages/0f/95/c5a00387a5405e68ba32cc64af65ce881a39b98d73cc394b24143bebc5b8/kiwisolver-1.4.8-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:b47a465040146981dc9db8647981b8cb96366fbc8d452b031e4f8fdffec3f26d", size = 2293129, upload-time = "2024-12-24T18:30:30.34Z" }, - { url = "https://files.pythonhosted.org/packages/44/83/eeb7af7d706b8347548313fa3a3a15931f404533cc54fe01f39e830dd231/kiwisolver-1.4.8-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:99cea8b9dd34ff80c521aef46a1dddb0dcc0283cf18bde6d756f1e6f31772165", size = 2421538, upload-time = "2024-12-24T18:30:33.334Z" }, - { url = "https://files.pythonhosted.org/packages/05/f9/27e94c1b3eb29e6933b6986ffc5fa1177d2cd1f0c8efc5f02c91c9ac61de/kiwisolver-1.4.8-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:151dffc4865e5fe6dafce5480fab84f950d14566c480c08a53c663a0020504b6", size = 2390661, upload-time = "2024-12-24T18:30:34.939Z" }, - { url = "https://files.pythonhosted.org/packages/d9/d4/3c9735faa36ac591a4afcc2980d2691000506050b7a7e80bcfe44048daa7/kiwisolver-1.4.8-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:577facaa411c10421314598b50413aa1ebcf5126f704f1e5d72d7e4e9f020d90", size = 2546710, upload-time = "2024-12-24T18:30:37.281Z" }, - { url = "https://files.pythonhosted.org/packages/4c/fa/be89a49c640930180657482a74970cdcf6f7072c8d2471e1babe17a222dc/kiwisolver-1.4.8-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:be4816dc51c8a471749d664161b434912eee82f2ea66bd7628bd14583a833e85", size = 2349213, upload-time = "2024-12-24T18:30:40.019Z" }, +version = "1.4.9" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/5c/3c/85844f1b0feb11ee581ac23fe5fce65cd049a200c1446708cc1b7f922875/kiwisolver-1.4.9.tar.gz", hash = "sha256:c3b22c26c6fd6811b0ae8363b95ca8ce4ea3c202d3d0975b2914310ceb1bcc4d", size = 97564, upload-time = "2025-08-10T21:27:49.279Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6f/ab/c80b0d5a9d8a1a65f4f815f2afff9798b12c3b9f31f1d304dd233dd920e2/kiwisolver-1.4.9-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:eb14a5da6dc7642b0f3a18f13654847cd8b7a2550e2645a5bda677862b03ba16", size = 124167, upload-time = "2025-08-10T21:25:53.403Z" }, + { url = "https://files.pythonhosted.org/packages/a0/c0/27fe1a68a39cf62472a300e2879ffc13c0538546c359b86f149cc19f6ac3/kiwisolver-1.4.9-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:39a219e1c81ae3b103643d2aedb90f1ef22650deb266ff12a19e7773f3e5f089", size = 66579, upload-time = "2025-08-10T21:25:54.79Z" }, + { url = "https://files.pythonhosted.org/packages/31/a2/a12a503ac1fd4943c50f9822678e8015a790a13b5490354c68afb8489814/kiwisolver-1.4.9-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2405a7d98604b87f3fc28b1716783534b1b4b8510d8142adca34ee0bc3c87543", size = 65309, upload-time = "2025-08-10T21:25:55.76Z" }, + { url = "https://files.pythonhosted.org/packages/66/e1/e533435c0be77c3f64040d68d7a657771194a63c279f55573188161e81ca/kiwisolver-1.4.9-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:dc1ae486f9abcef254b5618dfb4113dd49f94c68e3e027d03cf0143f3f772b61", size = 1435596, upload-time = "2025-08-10T21:25:56.861Z" }, + { url = "https://files.pythonhosted.org/packages/67/1e/51b73c7347f9aabdc7215aa79e8b15299097dc2f8e67dee2b095faca9cb0/kiwisolver-1.4.9-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8a1f570ce4d62d718dce3f179ee78dac3b545ac16c0c04bb363b7607a949c0d1", size = 1246548, upload-time = "2025-08-10T21:25:58.246Z" }, + { url = "https://files.pythonhosted.org/packages/21/aa/72a1c5d1e430294f2d32adb9542719cfb441b5da368d09d268c7757af46c/kiwisolver-1.4.9-cp311-cp311-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:cb27e7b78d716c591e88e0a09a2139c6577865d7f2e152488c2cc6257f460872", size = 1263618, upload-time = "2025-08-10T21:25:59.857Z" }, + { url = "https://files.pythonhosted.org/packages/a3/af/db1509a9e79dbf4c260ce0cfa3903ea8945f6240e9e59d1e4deb731b1a40/kiwisolver-1.4.9-cp311-cp311-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:15163165efc2f627eb9687ea5f3a28137217d217ac4024893d753f46bce9de26", size = 1317437, upload-time = "2025-08-10T21:26:01.105Z" }, + { url = "https://files.pythonhosted.org/packages/e0/f2/3ea5ee5d52abacdd12013a94130436e19969fa183faa1e7c7fbc89e9a42f/kiwisolver-1.4.9-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:bdee92c56a71d2b24c33a7d4c2856bd6419d017e08caa7802d2963870e315028", size = 2195742, upload-time = "2025-08-10T21:26:02.675Z" }, + { url = "https://files.pythonhosted.org/packages/6f/9b/1efdd3013c2d9a2566aa6a337e9923a00590c516add9a1e89a768a3eb2fc/kiwisolver-1.4.9-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:412f287c55a6f54b0650bd9b6dce5aceddb95864a1a90c87af16979d37c89771", size = 2290810, upload-time = "2025-08-10T21:26:04.009Z" }, + { url = "https://files.pythonhosted.org/packages/fb/e5/cfdc36109ae4e67361f9bc5b41323648cb24a01b9ade18784657e022e65f/kiwisolver-1.4.9-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:2c93f00dcba2eea70af2be5f11a830a742fe6b579a1d4e00f47760ef13be247a", size = 2461579, upload-time = "2025-08-10T21:26:05.317Z" }, + { url = "https://files.pythonhosted.org/packages/62/86/b589e5e86c7610842213994cdea5add00960076bef4ae290c5fa68589cac/kiwisolver-1.4.9-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f117e1a089d9411663a3207ba874f31be9ac8eaa5b533787024dc07aeb74f464", size = 2268071, upload-time = "2025-08-10T21:26:06.686Z" }, + { url = "https://files.pythonhosted.org/packages/3b/c6/f8df8509fd1eee6c622febe54384a96cfaf4d43bf2ccec7a0cc17e4715c9/kiwisolver-1.4.9-cp311-cp311-win_amd64.whl", hash = "sha256:be6a04e6c79819c9a8c2373317d19a96048e5a3f90bec587787e86a1153883c2", size = 73840, upload-time = "2025-08-10T21:26:07.94Z" }, + { url = "https://files.pythonhosted.org/packages/e2/2d/16e0581daafd147bc11ac53f032a2b45eabac897f42a338d0a13c1e5c436/kiwisolver-1.4.9-cp311-cp311-win_arm64.whl", hash = "sha256:0ae37737256ba2de764ddc12aed4956460277f00c4996d51a197e72f62f5eec7", size = 65159, upload-time = "2025-08-10T21:26:09.048Z" }, + { url = "https://files.pythonhosted.org/packages/86/c9/13573a747838aeb1c76e3267620daa054f4152444d1f3d1a2324b78255b5/kiwisolver-1.4.9-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:ac5a486ac389dddcc5bef4f365b6ae3ffff2c433324fb38dd35e3fab7c957999", size = 123686, upload-time = "2025-08-10T21:26:10.034Z" }, + { url = "https://files.pythonhosted.org/packages/51/ea/2ecf727927f103ffd1739271ca19c424d0e65ea473fbaeea1c014aea93f6/kiwisolver-1.4.9-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:f2ba92255faa7309d06fe44c3a4a97efe1c8d640c2a79a5ef728b685762a6fd2", size = 66460, upload-time = "2025-08-10T21:26:11.083Z" }, + { url = "https://files.pythonhosted.org/packages/5b/5a/51f5464373ce2aeb5194508298a508b6f21d3867f499556263c64c621914/kiwisolver-1.4.9-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4a2899935e724dd1074cb568ce7ac0dce28b2cd6ab539c8e001a8578eb106d14", size = 64952, upload-time = "2025-08-10T21:26:12.058Z" }, + { url = "https://files.pythonhosted.org/packages/70/90/6d240beb0f24b74371762873e9b7f499f1e02166a2d9c5801f4dbf8fa12e/kiwisolver-1.4.9-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:f6008a4919fdbc0b0097089f67a1eb55d950ed7e90ce2cc3e640abadd2757a04", size = 1474756, upload-time = "2025-08-10T21:26:13.096Z" }, + { url = "https://files.pythonhosted.org/packages/12/42/f36816eaf465220f683fb711efdd1bbf7a7005a2473d0e4ed421389bd26c/kiwisolver-1.4.9-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:67bb8b474b4181770f926f7b7d2f8c0248cbcb78b660fdd41a47054b28d2a752", size = 1276404, upload-time = "2025-08-10T21:26:14.457Z" }, + { url = "https://files.pythonhosted.org/packages/2e/64/bc2de94800adc830c476dce44e9b40fd0809cddeef1fde9fcf0f73da301f/kiwisolver-1.4.9-cp312-cp312-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2327a4a30d3ee07d2fbe2e7933e8a37c591663b96ce42a00bc67461a87d7df77", size = 1294410, upload-time = "2025-08-10T21:26:15.73Z" }, + { url = "https://files.pythonhosted.org/packages/5f/42/2dc82330a70aa8e55b6d395b11018045e58d0bb00834502bf11509f79091/kiwisolver-1.4.9-cp312-cp312-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:7a08b491ec91b1d5053ac177afe5290adacf1f0f6307d771ccac5de30592d198", size = 1343631, upload-time = "2025-08-10T21:26:17.045Z" }, + { url = "https://files.pythonhosted.org/packages/22/fd/f4c67a6ed1aab149ec5a8a401c323cee7a1cbe364381bb6c9c0d564e0e20/kiwisolver-1.4.9-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d8fc5c867c22b828001b6a38d2eaeb88160bf5783c6cb4a5e440efc981ce286d", size = 2224963, upload-time = "2025-08-10T21:26:18.737Z" }, + { url = "https://files.pythonhosted.org/packages/45/aa/76720bd4cb3713314677d9ec94dcc21ced3f1baf4830adde5bb9b2430a5f/kiwisolver-1.4.9-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:3b3115b2581ea35bb6d1f24a4c90af37e5d9b49dcff267eeed14c3893c5b86ab", size = 2321295, upload-time = "2025-08-10T21:26:20.11Z" }, + { url = "https://files.pythonhosted.org/packages/80/19/d3ec0d9ab711242f56ae0dc2fc5d70e298bb4a1f9dfab44c027668c673a1/kiwisolver-1.4.9-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:858e4c22fb075920b96a291928cb7dea5644e94c0ee4fcd5af7e865655e4ccf2", size = 2487987, upload-time = "2025-08-10T21:26:21.49Z" }, + { url = "https://files.pythonhosted.org/packages/39/e9/61e4813b2c97e86b6fdbd4dd824bf72d28bcd8d4849b8084a357bc0dd64d/kiwisolver-1.4.9-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ed0fecd28cc62c54b262e3736f8bb2512d8dcfdc2bcf08be5f47f96bf405b145", size = 2291817, upload-time = "2025-08-10T21:26:22.812Z" }, + { url = "https://files.pythonhosted.org/packages/a0/41/85d82b0291db7504da3c2defe35c9a8a5c9803a730f297bd823d11d5fb77/kiwisolver-1.4.9-cp312-cp312-win_amd64.whl", hash = "sha256:f68208a520c3d86ea51acf688a3e3002615a7f0238002cccc17affecc86a8a54", size = 73895, upload-time = "2025-08-10T21:26:24.37Z" }, + { url = "https://files.pythonhosted.org/packages/e2/92/5f3068cf15ee5cb624a0c7596e67e2a0bb2adee33f71c379054a491d07da/kiwisolver-1.4.9-cp312-cp312-win_arm64.whl", hash = "sha256:2c1a4f57df73965f3f14df20b80ee29e6a7930a57d2d9e8491a25f676e197c60", size = 64992, upload-time = "2025-08-10T21:26:25.732Z" }, + { url = "https://files.pythonhosted.org/packages/31/c1/c2686cda909742ab66c7388e9a1a8521a59eb89f8bcfbee28fc980d07e24/kiwisolver-1.4.9-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:a5d0432ccf1c7ab14f9949eec60c5d1f924f17c037e9f8b33352fa05799359b8", size = 123681, upload-time = "2025-08-10T21:26:26.725Z" }, + { url = "https://files.pythonhosted.org/packages/ca/f0/f44f50c9f5b1a1860261092e3bc91ecdc9acda848a8b8c6abfda4a24dd5c/kiwisolver-1.4.9-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efb3a45b35622bb6c16dbfab491a8f5a391fe0e9d45ef32f4df85658232ca0e2", size = 66464, upload-time = "2025-08-10T21:26:27.733Z" }, + { url = "https://files.pythonhosted.org/packages/2d/7a/9d90a151f558e29c3936b8a47ac770235f436f2120aca41a6d5f3d62ae8d/kiwisolver-1.4.9-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1a12cf6398e8a0a001a059747a1cbf24705e18fe413bc22de7b3d15c67cffe3f", size = 64961, upload-time = "2025-08-10T21:26:28.729Z" }, + { url = "https://files.pythonhosted.org/packages/e9/e9/f218a2cb3a9ffbe324ca29a9e399fa2d2866d7f348ec3a88df87fc248fc5/kiwisolver-1.4.9-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:b67e6efbf68e077dd71d1a6b37e43e1a99d0bff1a3d51867d45ee8908b931098", size = 1474607, upload-time = "2025-08-10T21:26:29.798Z" }, + { url = "https://files.pythonhosted.org/packages/d9/28/aac26d4c882f14de59041636292bc838db8961373825df23b8eeb807e198/kiwisolver-1.4.9-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5656aa670507437af0207645273ccdfee4f14bacd7f7c67a4306d0dcaeaf6eed", size = 1276546, upload-time = "2025-08-10T21:26:31.401Z" }, + { url = "https://files.pythonhosted.org/packages/8b/ad/8bfc1c93d4cc565e5069162f610ba2f48ff39b7de4b5b8d93f69f30c4bed/kiwisolver-1.4.9-cp313-cp313-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:bfc08add558155345129c7803b3671cf195e6a56e7a12f3dde7c57d9b417f525", size = 1294482, upload-time = "2025-08-10T21:26:32.721Z" }, + { url = "https://files.pythonhosted.org/packages/da/f1/6aca55ff798901d8ce403206d00e033191f63d82dd708a186e0ed2067e9c/kiwisolver-1.4.9-cp313-cp313-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:40092754720b174e6ccf9e845d0d8c7d8e12c3d71e7fc35f55f3813e96376f78", size = 1343720, upload-time = "2025-08-10T21:26:34.032Z" }, + { url = "https://files.pythonhosted.org/packages/d1/91/eed031876c595c81d90d0f6fc681ece250e14bf6998c3d7c419466b523b7/kiwisolver-1.4.9-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:497d05f29a1300d14e02e6441cf0f5ee81c1ff5a304b0d9fb77423974684e08b", size = 2224907, upload-time = "2025-08-10T21:26:35.824Z" }, + { url = "https://files.pythonhosted.org/packages/e9/ec/4d1925f2e49617b9cca9c34bfa11adefad49d00db038e692a559454dfb2e/kiwisolver-1.4.9-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:bdd1a81a1860476eb41ac4bc1e07b3f07259e6d55bbf739b79c8aaedcf512799", size = 2321334, upload-time = "2025-08-10T21:26:37.534Z" }, + { url = "https://files.pythonhosted.org/packages/43/cb/450cd4499356f68802750c6ddc18647b8ea01ffa28f50d20598e0befe6e9/kiwisolver-1.4.9-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:e6b93f13371d341afee3be9f7c5964e3fe61d5fa30f6a30eb49856935dfe4fc3", size = 2488313, upload-time = "2025-08-10T21:26:39.191Z" }, + { url = "https://files.pythonhosted.org/packages/71/67/fc76242bd99f885651128a5d4fa6083e5524694b7c88b489b1b55fdc491d/kiwisolver-1.4.9-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:d75aa530ccfaa593da12834b86a0724f58bff12706659baa9227c2ccaa06264c", size = 2291970, upload-time = "2025-08-10T21:26:40.828Z" }, + { url = "https://files.pythonhosted.org/packages/75/bd/f1a5d894000941739f2ae1b65a32892349423ad49c2e6d0771d0bad3fae4/kiwisolver-1.4.9-cp313-cp313-win_amd64.whl", hash = "sha256:dd0a578400839256df88c16abddf9ba14813ec5f21362e1fe65022e00c883d4d", size = 73894, upload-time = "2025-08-10T21:26:42.33Z" }, + { url = "https://files.pythonhosted.org/packages/95/38/dce480814d25b99a391abbddadc78f7c117c6da34be68ca8b02d5848b424/kiwisolver-1.4.9-cp313-cp313-win_arm64.whl", hash = "sha256:d4188e73af84ca82468f09cadc5ac4db578109e52acb4518d8154698d3a87ca2", size = 64995, upload-time = "2025-08-10T21:26:43.889Z" }, + { url = "https://files.pythonhosted.org/packages/e2/37/7d218ce5d92dadc5ebdd9070d903e0c7cf7edfe03f179433ac4d13ce659c/kiwisolver-1.4.9-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:5a0f2724dfd4e3b3ac5a82436a8e6fd16baa7d507117e4279b660fe8ca38a3a1", size = 126510, upload-time = "2025-08-10T21:26:44.915Z" }, + { url = "https://files.pythonhosted.org/packages/23/b0/e85a2b48233daef4b648fb657ebbb6f8367696a2d9548a00b4ee0eb67803/kiwisolver-1.4.9-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:1b11d6a633e4ed84fc0ddafd4ebfd8ea49b3f25082c04ad12b8315c11d504dc1", size = 67903, upload-time = "2025-08-10T21:26:45.934Z" }, + { url = "https://files.pythonhosted.org/packages/44/98/f2425bc0113ad7de24da6bb4dae1343476e95e1d738be7c04d31a5d037fd/kiwisolver-1.4.9-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:61874cdb0a36016354853593cffc38e56fc9ca5aa97d2c05d3dcf6922cd55a11", size = 66402, upload-time = "2025-08-10T21:26:47.101Z" }, + { url = "https://files.pythonhosted.org/packages/98/d8/594657886df9f34c4177cc353cc28ca7e6e5eb562d37ccc233bff43bbe2a/kiwisolver-1.4.9-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:60c439763a969a6af93b4881db0eed8fadf93ee98e18cbc35bc8da868d0c4f0c", size = 1582135, upload-time = "2025-08-10T21:26:48.665Z" }, + { url = "https://files.pythonhosted.org/packages/5c/c6/38a115b7170f8b306fc929e166340c24958347308ea3012c2b44e7e295db/kiwisolver-1.4.9-cp313-cp313t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:92a2f997387a1b79a75e7803aa7ded2cfbe2823852ccf1ba3bcf613b62ae3197", size = 1389409, upload-time = "2025-08-10T21:26:50.335Z" }, + { url = "https://files.pythonhosted.org/packages/bf/3b/e04883dace81f24a568bcee6eb3001da4ba05114afa622ec9b6fafdc1f5e/kiwisolver-1.4.9-cp313-cp313t-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a31d512c812daea6d8b3be3b2bfcbeb091dbb09177706569bcfc6240dcf8b41c", size = 1401763, upload-time = "2025-08-10T21:26:51.867Z" }, + { url = "https://files.pythonhosted.org/packages/9f/80/20ace48e33408947af49d7d15c341eaee69e4e0304aab4b7660e234d6288/kiwisolver-1.4.9-cp313-cp313t-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:52a15b0f35dad39862d376df10c5230155243a2c1a436e39eb55623ccbd68185", size = 1453643, upload-time = "2025-08-10T21:26:53.592Z" }, + { url = "https://files.pythonhosted.org/packages/64/31/6ce4380a4cd1f515bdda976a1e90e547ccd47b67a1546d63884463c92ca9/kiwisolver-1.4.9-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:a30fd6fdef1430fd9e1ba7b3398b5ee4e2887783917a687d86ba69985fb08748", size = 2330818, upload-time = "2025-08-10T21:26:55.051Z" }, + { url = "https://files.pythonhosted.org/packages/fa/e9/3f3fcba3bcc7432c795b82646306e822f3fd74df0ee81f0fa067a1f95668/kiwisolver-1.4.9-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:cc9617b46837c6468197b5945e196ee9ca43057bb7d9d1ae688101e4e1dddf64", size = 2419963, upload-time = "2025-08-10T21:26:56.421Z" }, + { url = "https://files.pythonhosted.org/packages/99/43/7320c50e4133575c66e9f7dadead35ab22d7c012a3b09bb35647792b2a6d/kiwisolver-1.4.9-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:0ab74e19f6a2b027ea4f845a78827969af45ce790e6cb3e1ebab71bdf9f215ff", size = 2594639, upload-time = "2025-08-10T21:26:57.882Z" }, + { url = "https://files.pythonhosted.org/packages/65/d6/17ae4a270d4a987ef8a385b906d2bdfc9fce502d6dc0d3aea865b47f548c/kiwisolver-1.4.9-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:dba5ee5d3981160c28d5490f0d1b7ed730c22470ff7f6cc26cfcfaacb9896a07", size = 2391741, upload-time = "2025-08-10T21:26:59.237Z" }, + { url = "https://files.pythonhosted.org/packages/2a/8f/8f6f491d595a9e5912971f3f863d81baddccc8a4d0c3749d6a0dd9ffc9df/kiwisolver-1.4.9-cp313-cp313t-win_arm64.whl", hash = "sha256:0749fd8f4218ad2e851e11cc4dc05c7cbc0cbc4267bdfdb31782e65aace4ee9c", size = 68646, upload-time = "2025-08-10T21:27:00.52Z" }, + { url = "https://files.pythonhosted.org/packages/6b/32/6cc0fbc9c54d06c2969faa9c1d29f5751a2e51809dd55c69055e62d9b426/kiwisolver-1.4.9-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:9928fe1eb816d11ae170885a74d074f57af3a0d65777ca47e9aeb854a1fba386", size = 123806, upload-time = "2025-08-10T21:27:01.537Z" }, + { url = "https://files.pythonhosted.org/packages/b2/dd/2bfb1d4a4823d92e8cbb420fe024b8d2167f72079b3bb941207c42570bdf/kiwisolver-1.4.9-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:d0005b053977e7b43388ddec89fa567f43d4f6d5c2c0affe57de5ebf290dc552", size = 66605, upload-time = "2025-08-10T21:27:03.335Z" }, + { url = "https://files.pythonhosted.org/packages/f7/69/00aafdb4e4509c2ca6064646cba9cd4b37933898f426756adb2cb92ebbed/kiwisolver-1.4.9-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:2635d352d67458b66fd0667c14cb1d4145e9560d503219034a18a87e971ce4f3", size = 64925, upload-time = "2025-08-10T21:27:04.339Z" }, + { url = "https://files.pythonhosted.org/packages/43/dc/51acc6791aa14e5cb6d8a2e28cefb0dc2886d8862795449d021334c0df20/kiwisolver-1.4.9-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:767c23ad1c58c9e827b649a9ab7809fd5fd9db266a9cf02b0e926ddc2c680d58", size = 1472414, upload-time = "2025-08-10T21:27:05.437Z" }, + { url = "https://files.pythonhosted.org/packages/3d/bb/93fa64a81db304ac8a246f834d5094fae4b13baf53c839d6bb6e81177129/kiwisolver-1.4.9-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:72d0eb9fba308b8311685c2268cf7d0a0639a6cd027d8128659f72bdd8a024b4", size = 1281272, upload-time = "2025-08-10T21:27:07.063Z" }, + { url = "https://files.pythonhosted.org/packages/70/e6/6df102916960fb8d05069d4bd92d6d9a8202d5a3e2444494e7cd50f65b7a/kiwisolver-1.4.9-cp314-cp314-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f68e4f3eeca8fb22cc3d731f9715a13b652795ef657a13df1ad0c7dc0e9731df", size = 1298578, upload-time = "2025-08-10T21:27:08.452Z" }, + { url = "https://files.pythonhosted.org/packages/7c/47/e142aaa612f5343736b087864dbaebc53ea8831453fb47e7521fa8658f30/kiwisolver-1.4.9-cp314-cp314-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d84cd4061ae292d8ac367b2c3fa3aad11cb8625a95d135fe93f286f914f3f5a6", size = 1345607, upload-time = "2025-08-10T21:27:10.125Z" }, + { url = "https://files.pythonhosted.org/packages/54/89/d641a746194a0f4d1a3670fb900d0dbaa786fb98341056814bc3f058fa52/kiwisolver-1.4.9-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:a60ea74330b91bd22a29638940d115df9dc00af5035a9a2a6ad9399ffb4ceca5", size = 2230150, upload-time = "2025-08-10T21:27:11.484Z" }, + { url = "https://files.pythonhosted.org/packages/aa/6b/5ee1207198febdf16ac11f78c5ae40861b809cbe0e6d2a8d5b0b3044b199/kiwisolver-1.4.9-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:ce6a3a4e106cf35c2d9c4fa17c05ce0b180db622736845d4315519397a77beaf", size = 2325979, upload-time = "2025-08-10T21:27:12.917Z" }, + { url = "https://files.pythonhosted.org/packages/fc/ff/b269eefd90f4ae14dcc74973d5a0f6d28d3b9bb1afd8c0340513afe6b39a/kiwisolver-1.4.9-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:77937e5e2a38a7b48eef0585114fe7930346993a88060d0bf886086d2aa49ef5", size = 2491456, upload-time = "2025-08-10T21:27:14.353Z" }, + { url = "https://files.pythonhosted.org/packages/fc/d4/10303190bd4d30de547534601e259a4fbf014eed94aae3e5521129215086/kiwisolver-1.4.9-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:24c175051354f4a28c5d6a31c93906dc653e2bf234e8a4bbfb964892078898ce", size = 2294621, upload-time = "2025-08-10T21:27:15.808Z" }, + { url = "https://files.pythonhosted.org/packages/28/e0/a9a90416fce5c0be25742729c2ea52105d62eda6c4be4d803c2a7be1fa50/kiwisolver-1.4.9-cp314-cp314-win_amd64.whl", hash = "sha256:0763515d4df10edf6d06a3c19734e2566368980d21ebec439f33f9eb936c07b7", size = 75417, upload-time = "2025-08-10T21:27:17.436Z" }, + { url = "https://files.pythonhosted.org/packages/1f/10/6949958215b7a9a264299a7db195564e87900f709db9245e4ebdd3c70779/kiwisolver-1.4.9-cp314-cp314-win_arm64.whl", hash = "sha256:0e4e2bf29574a6a7b7f6cb5fa69293b9f96c928949ac4a53ba3f525dffb87f9c", size = 66582, upload-time = "2025-08-10T21:27:18.436Z" }, + { url = "https://files.pythonhosted.org/packages/ec/79/60e53067903d3bc5469b369fe0dfc6b3482e2133e85dae9daa9527535991/kiwisolver-1.4.9-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:d976bbb382b202f71c67f77b0ac11244021cfa3f7dfd9e562eefcea2df711548", size = 126514, upload-time = "2025-08-10T21:27:19.465Z" }, + { url = "https://files.pythonhosted.org/packages/25/d1/4843d3e8d46b072c12a38c97c57fab4608d36e13fe47d47ee96b4d61ba6f/kiwisolver-1.4.9-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:2489e4e5d7ef9a1c300a5e0196e43d9c739f066ef23270607d45aba368b91f2d", size = 67905, upload-time = "2025-08-10T21:27:20.51Z" }, + { url = "https://files.pythonhosted.org/packages/8c/ae/29ffcbd239aea8b93108de1278271ae764dfc0d803a5693914975f200596/kiwisolver-1.4.9-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:e2ea9f7ab7fbf18fffb1b5434ce7c69a07582f7acc7717720f1d69f3e806f90c", size = 66399, upload-time = "2025-08-10T21:27:21.496Z" }, + { url = "https://files.pythonhosted.org/packages/a1/ae/d7ba902aa604152c2ceba5d352d7b62106bedbccc8e95c3934d94472bfa3/kiwisolver-1.4.9-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:b34e51affded8faee0dfdb705416153819d8ea9250bbbf7ea1b249bdeb5f1122", size = 1582197, upload-time = "2025-08-10T21:27:22.604Z" }, + { url = "https://files.pythonhosted.org/packages/f2/41/27c70d427eddb8bc7e4f16420a20fefc6f480312122a59a959fdfe0445ad/kiwisolver-1.4.9-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d8aacd3d4b33b772542b2e01beb50187536967b514b00003bdda7589722d2a64", size = 1390125, upload-time = "2025-08-10T21:27:24.036Z" }, + { url = "https://files.pythonhosted.org/packages/41/42/b3799a12bafc76d962ad69083f8b43b12bf4fe78b097b12e105d75c9b8f1/kiwisolver-1.4.9-cp314-cp314t-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:7cf974dd4e35fa315563ac99d6287a1024e4dc2077b8a7d7cd3d2fb65d283134", size = 1402612, upload-time = "2025-08-10T21:27:25.773Z" }, + { url = "https://files.pythonhosted.org/packages/d2/b5/a210ea073ea1cfaca1bb5c55a62307d8252f531beb364e18aa1e0888b5a0/kiwisolver-1.4.9-cp314-cp314t-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:85bd218b5ecfbee8c8a82e121802dcb519a86044c9c3b2e4aef02fa05c6da370", size = 1453990, upload-time = "2025-08-10T21:27:27.089Z" }, + { url = "https://files.pythonhosted.org/packages/5f/ce/a829eb8c033e977d7ea03ed32fb3c1781b4fa0433fbadfff29e39c676f32/kiwisolver-1.4.9-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:0856e241c2d3df4efef7c04a1e46b1936b6120c9bcf36dd216e3acd84bc4fb21", size = 2331601, upload-time = "2025-08-10T21:27:29.343Z" }, + { url = "https://files.pythonhosted.org/packages/e0/4b/b5e97eb142eb9cd0072dacfcdcd31b1c66dc7352b0f7c7255d339c0edf00/kiwisolver-1.4.9-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:9af39d6551f97d31a4deebeac6f45b156f9755ddc59c07b402c148f5dbb6482a", size = 2422041, upload-time = "2025-08-10T21:27:30.754Z" }, + { url = "https://files.pythonhosted.org/packages/40/be/8eb4cd53e1b85ba4edc3a9321666f12b83113a178845593307a3e7891f44/kiwisolver-1.4.9-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:bb4ae2b57fc1d8cbd1cf7b1d9913803681ffa903e7488012be5b76dedf49297f", size = 2594897, upload-time = "2025-08-10T21:27:32.803Z" }, + { url = "https://files.pythonhosted.org/packages/99/dd/841e9a66c4715477ea0abc78da039832fbb09dac5c35c58dc4c41a407b8a/kiwisolver-1.4.9-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:aedff62918805fb62d43a4aa2ecd4482c380dc76cd31bd7c8878588a61bd0369", size = 2391835, upload-time = "2025-08-10T21:27:34.23Z" }, + { url = "https://files.pythonhosted.org/packages/0c/28/4b2e5c47a0da96896fdfdb006340ade064afa1e63675d01ea5ac222b6d52/kiwisolver-1.4.9-cp314-cp314t-win_amd64.whl", hash = "sha256:1fa333e8b2ce4d9660f2cda9c0e1b6bafcfb2457a9d259faa82289e73ec24891", size = 79988, upload-time = "2025-08-10T21:27:35.587Z" }, + { url = "https://files.pythonhosted.org/packages/80/be/3578e8afd18c88cdf9cb4cffde75a96d2be38c5a903f1ed0ceec061bd09e/kiwisolver-1.4.9-cp314-cp314t-win_arm64.whl", hash = "sha256:4a48a2ce79d65d363597ef7b567ce3d14d68783d2b2263d98db3d9477805ba32", size = 70260, upload-time = "2025-08-10T21:27:36.606Z" }, + { url = "https://files.pythonhosted.org/packages/a3/0f/36d89194b5a32c054ce93e586d4049b6c2c22887b0eb229c61c68afd3078/kiwisolver-1.4.9-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:720e05574713db64c356e86732c0f3c5252818d05f9df320f0ad8380641acea5", size = 60104, upload-time = "2025-08-10T21:27:43.287Z" }, + { url = "https://files.pythonhosted.org/packages/52/ba/4ed75f59e4658fd21fe7dde1fee0ac397c678ec3befba3fe6482d987af87/kiwisolver-1.4.9-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:17680d737d5335b552994a2008fab4c851bcd7de33094a82067ef3a576ff02fa", size = 58592, upload-time = "2025-08-10T21:27:44.314Z" }, + { url = "https://files.pythonhosted.org/packages/33/01/a8ea7c5ea32a9b45ceeaee051a04c8ed4320f5add3c51bfa20879b765b70/kiwisolver-1.4.9-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:85b5352f94e490c028926ea567fc569c52ec79ce131dadb968d3853e809518c2", size = 80281, upload-time = "2025-08-10T21:27:45.369Z" }, + { url = "https://files.pythonhosted.org/packages/da/e3/dbd2ecdce306f1d07a1aaf324817ee993aab7aee9db47ceac757deabafbe/kiwisolver-1.4.9-pp311-pypy311_pp73-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:464415881e4801295659462c49461a24fb107c140de781d55518c4b80cb6790f", size = 78009, upload-time = "2025-08-10T21:27:46.376Z" }, + { url = "https://files.pythonhosted.org/packages/da/e9/0d4add7873a73e462aeb45c036a2dead2562b825aa46ba326727b3f31016/kiwisolver-1.4.9-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:fb940820c63a9590d31d88b815e7a3aa5915cad3ce735ab45f0c730b39547de1", size = 73929, upload-time = "2025-08-10T21:27:48.236Z" }, ] [[package]] @@ -1819,16 +1848,16 @@ wheels = [ [[package]] name = "pytest-regressions" -version = "2.8.1" +version = "2.8.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pytest" }, { name = "pytest-datadir" }, { name = "pyyaml" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/c9/20/f861ea5b5db791ba1f778032b294b0a454eff2f6c2b3f8a88d36d61c0a63/pytest_regressions-2.8.1.tar.gz", hash = "sha256:20080d44cf46b40407956af5e44a7f932cbc3159018de81fb51e62b97e96a5fb", size = 116486, upload-time = "2025-07-04T12:54:36.473Z" } +sdist = { url = "https://files.pythonhosted.org/packages/c1/8e/e17b12ee49a9814ad86f544225331406e3bf23849a5bc83f91e119e2b72b/pytest_regressions-2.8.2.tar.gz", hash = "sha256:1d8f4767be58b9994bfa7d60271099469ad32b8ca9f9d9ceca1c1d6827156b19", size = 116642, upload-time = "2025-08-13T15:50:37.961Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/46/6e/416d44b81b42482c2b7b553606c79d7f3e32e686d42f3f24b04a7f8cf56f/pytest_regressions-2.8.1-py3-none-any.whl", hash = "sha256:bcae249df5214225bbe4bd77c146d8f331f19b0b26805486533b1e49680950a5", size = 24861, upload-time = "2025-07-04T12:54:35.051Z" }, + { url = "https://files.pythonhosted.org/packages/b6/c9/2c3ea968876f698035b1f00dbe5cd6bff76d3e441dfb1af32111f544b6bb/pytest_regressions-2.8.2-py3-none-any.whl", hash = "sha256:a0804c1ce66d8e4d9a3c7c68f42a3d436182edca8e86565c232caeaf9e080fc2", size = 24856, upload-time = "2025-08-13T15:50:36.431Z" }, ] [[package]] @@ -2573,21 +2602,21 @@ wheels = [ [[package]] name = "tornado" -version = "6.5.1" +version = "6.5.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/51/89/c72771c81d25d53fe33e3dca61c233b665b2780f21820ba6fd2c6793c12b/tornado-6.5.1.tar.gz", hash = "sha256:84ceece391e8eb9b2b95578db65e920d2a61070260594819589609ba9bc6308c", size = 509934, upload-time = "2025-05-22T18:15:38.788Z" } +sdist = { url = "https://files.pythonhosted.org/packages/09/ce/1eb500eae19f4648281bb2186927bb062d2438c2e5093d1360391afd2f90/tornado-6.5.2.tar.gz", hash = "sha256:ab53c8f9a0fa351e2c0741284e06c7a45da86afb544133201c5cc8578eb076a0", size = 510821, upload-time = "2025-08-08T18:27:00.78Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/77/89/f4532dee6843c9e0ebc4e28d4be04c67f54f60813e4bf73d595fe7567452/tornado-6.5.1-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:d50065ba7fd11d3bd41bcad0825227cc9a95154bad83239357094c36708001f7", size = 441948, upload-time = "2025-05-22T18:15:20.862Z" }, - { url = "https://files.pythonhosted.org/packages/15/9a/557406b62cffa395d18772e0cdcf03bed2fff03b374677348eef9f6a3792/tornado-6.5.1-cp39-abi3-macosx_10_9_x86_64.whl", hash = "sha256:9e9ca370f717997cb85606d074b0e5b247282cf5e2e1611568b8821afe0342d6", size = 440112, upload-time = "2025-05-22T18:15:22.591Z" }, - { url = "https://files.pythonhosted.org/packages/55/82/7721b7319013a3cf881f4dffa4f60ceff07b31b394e459984e7a36dc99ec/tornado-6.5.1-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b77e9dfa7ed69754a54c89d82ef746398be82f749df69c4d3abe75c4d1ff4888", size = 443672, upload-time = "2025-05-22T18:15:24.027Z" }, - { url = "https://files.pythonhosted.org/packages/7d/42/d11c4376e7d101171b94e03cef0cbce43e823ed6567ceda571f54cf6e3ce/tornado-6.5.1-cp39-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:253b76040ee3bab8bcf7ba9feb136436a3787208717a1fb9f2c16b744fba7331", size = 443019, upload-time = "2025-05-22T18:15:25.735Z" }, - { url = "https://files.pythonhosted.org/packages/7d/f7/0c48ba992d875521ac761e6e04b0a1750f8150ae42ea26df1852d6a98942/tornado-6.5.1-cp39-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:308473f4cc5a76227157cdf904de33ac268af770b2c5f05ca6c1161d82fdd95e", size = 443252, upload-time = "2025-05-22T18:15:27.499Z" }, - { url = "https://files.pythonhosted.org/packages/89/46/d8d7413d11987e316df4ad42e16023cd62666a3c0dfa1518ffa30b8df06c/tornado-6.5.1-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:caec6314ce8a81cf69bd89909f4b633b9f523834dc1a352021775d45e51d9401", size = 443930, upload-time = "2025-05-22T18:15:29.299Z" }, - { url = "https://files.pythonhosted.org/packages/78/b2/f8049221c96a06df89bed68260e8ca94beca5ea532ffc63b1175ad31f9cc/tornado-6.5.1-cp39-abi3-musllinux_1_2_i686.whl", hash = "sha256:13ce6e3396c24e2808774741331638ee6c2f50b114b97a55c5b442df65fd9692", size = 443351, upload-time = "2025-05-22T18:15:31.038Z" }, - { url = "https://files.pythonhosted.org/packages/76/ff/6a0079e65b326cc222a54720a748e04a4db246870c4da54ece4577bfa702/tornado-6.5.1-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:5cae6145f4cdf5ab24744526cc0f55a17d76f02c98f4cff9daa08ae9a217448a", size = 443328, upload-time = "2025-05-22T18:15:32.426Z" }, - { url = "https://files.pythonhosted.org/packages/49/18/e3f902a1d21f14035b5bc6246a8c0f51e0eef562ace3a2cea403c1fb7021/tornado-6.5.1-cp39-abi3-win32.whl", hash = "sha256:e0a36e1bc684dca10b1aa75a31df8bdfed656831489bc1e6a6ebed05dc1ec365", size = 444396, upload-time = "2025-05-22T18:15:34.205Z" }, - { url = "https://files.pythonhosted.org/packages/7b/09/6526e32bf1049ee7de3bebba81572673b19a2a8541f795d887e92af1a8bc/tornado-6.5.1-cp39-abi3-win_amd64.whl", hash = "sha256:908e7d64567cecd4c2b458075589a775063453aeb1d2a1853eedb806922f568b", size = 444840, upload-time = "2025-05-22T18:15:36.1Z" }, - { url = "https://files.pythonhosted.org/packages/55/a7/535c44c7bea4578e48281d83c615219f3ab19e6abc67625ef637c73987be/tornado-6.5.1-cp39-abi3-win_arm64.whl", hash = "sha256:02420a0eb7bf617257b9935e2b754d1b63897525d8a289c9d65690d580b4dcf7", size = 443596, upload-time = "2025-05-22T18:15:37.433Z" }, + { url = "https://files.pythonhosted.org/packages/f6/48/6a7529df2c9cc12efd2e8f5dd219516184d703b34c06786809670df5b3bd/tornado-6.5.2-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:2436822940d37cde62771cff8774f4f00b3c8024fe482e16ca8387b8a2724db6", size = 442563, upload-time = "2025-08-08T18:26:42.945Z" }, + { url = "https://files.pythonhosted.org/packages/f2/b5/9b575a0ed3e50b00c40b08cbce82eb618229091d09f6d14bce80fc01cb0b/tornado-6.5.2-cp39-abi3-macosx_10_9_x86_64.whl", hash = "sha256:583a52c7aa94ee046854ba81d9ebb6c81ec0fd30386d96f7640c96dad45a03ef", size = 440729, upload-time = "2025-08-08T18:26:44.473Z" }, + { url = "https://files.pythonhosted.org/packages/1b/4e/619174f52b120efcf23633c817fd3fed867c30bff785e2cd5a53a70e483c/tornado-6.5.2-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b0fe179f28d597deab2842b86ed4060deec7388f1fd9c1b4a41adf8af058907e", size = 444295, upload-time = "2025-08-08T18:26:46.021Z" }, + { url = "https://files.pythonhosted.org/packages/95/fa/87b41709552bbd393c85dd18e4e3499dcd8983f66e7972926db8d96aa065/tornado-6.5.2-cp39-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b186e85d1e3536d69583d2298423744740986018e393d0321df7340e71898882", size = 443644, upload-time = "2025-08-08T18:26:47.625Z" }, + { url = "https://files.pythonhosted.org/packages/f9/41/fb15f06e33d7430ca89420283a8762a4e6b8025b800ea51796ab5e6d9559/tornado-6.5.2-cp39-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e792706668c87709709c18b353da1f7662317b563ff69f00bab83595940c7108", size = 443878, upload-time = "2025-08-08T18:26:50.599Z" }, + { url = "https://files.pythonhosted.org/packages/11/92/fe6d57da897776ad2e01e279170ea8ae726755b045fe5ac73b75357a5a3f/tornado-6.5.2-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:06ceb1300fd70cb20e43b1ad8aaee0266e69e7ced38fa910ad2e03285009ce7c", size = 444549, upload-time = "2025-08-08T18:26:51.864Z" }, + { url = "https://files.pythonhosted.org/packages/9b/02/c8f4f6c9204526daf3d760f4aa555a7a33ad0e60843eac025ccfd6ff4a93/tornado-6.5.2-cp39-abi3-musllinux_1_2_i686.whl", hash = "sha256:74db443e0f5251be86cbf37929f84d8c20c27a355dd452a5cfa2aada0d001ec4", size = 443973, upload-time = "2025-08-08T18:26:53.625Z" }, + { url = "https://files.pythonhosted.org/packages/ae/2d/f5f5707b655ce2317190183868cd0f6822a1121b4baeae509ceb9590d0bd/tornado-6.5.2-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:b5e735ab2889d7ed33b32a459cac490eda71a1ba6857b0118de476ab6c366c04", size = 443954, upload-time = "2025-08-08T18:26:55.072Z" }, + { url = "https://files.pythonhosted.org/packages/e8/59/593bd0f40f7355806bf6573b47b8c22f8e1374c9b6fd03114bd6b7a3dcfd/tornado-6.5.2-cp39-abi3-win32.whl", hash = "sha256:c6f29e94d9b37a95013bb669616352ddb82e3bfe8326fccee50583caebc8a5f0", size = 445023, upload-time = "2025-08-08T18:26:56.677Z" }, + { url = "https://files.pythonhosted.org/packages/c7/2a/f609b420c2f564a748a2d80ebfb2ee02a73ca80223af712fca591386cafb/tornado-6.5.2-cp39-abi3-win_amd64.whl", hash = "sha256:e56a5af51cc30dd2cae649429af65ca2f6571da29504a07995175df14c18f35f", size = 445427, upload-time = "2025-08-08T18:26:57.91Z" }, + { url = "https://files.pythonhosted.org/packages/5e/4f/e1f65e8f8c76d73658b33d33b81eed4322fb5085350e4328d5c956f0c8f9/tornado-6.5.2-cp39-abi3-win_arm64.whl", hash = "sha256:d6c33dc3672e3a1f3618eb63b7ef4683a7688e7b9e6e8f0d9aa5726360a004af", size = 444456, upload-time = "2025-08-08T18:26:59.207Z" }, ] [[package]] @@ -2671,42 +2700,42 @@ wheels = [ [[package]] name = "uv" -version = "0.8.6" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/b5/3b/1140dbbca9fb3ca32be38e01c670a5980a4ee4874366d70438317876d40a/uv-0.8.6.tar.gz", hash = "sha256:4d4e042f6bd9f143094051a05de758684028f451e563846cbc0c6f505b530cca", size = 3463644, upload-time = "2025-08-07T15:43:34.206Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/71/64/a96f40f95626c6e353e66f6bc5a5ca7c1399e95caf0dcb56cae38754e073/uv-0.8.6-py3-none-linux_armv6l.whl", hash = "sha256:d96ff3a1d06a6a00ed94dfb2996228153b3b5bfc892174b7556216ab872a91b1", size = 18437310, upload-time = "2025-08-07T15:42:49.611Z" }, - { url = "https://files.pythonhosted.org/packages/41/30/b2fed99d5a6b16410669f223767f6d65bc6595858622f5f36386892ed963/uv-0.8.6-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:fdceb1ef554df0ddc620bfe83fdcf740829e489c62f78ba1f089abd62c71c63e", size = 18615884, upload-time = "2025-08-07T15:42:53.452Z" }, - { url = "https://files.pythonhosted.org/packages/d7/82/a53684eadb9cb169eab32ab71f2bdaf7c382819d6de44d4e8df91ca14a00/uv-0.8.6-py3-none-macosx_11_0_arm64.whl", hash = "sha256:7c1f48279ff61940143c78b969094e13324988eabcfcd4799f4350d9d36c1d48", size = 17173005, upload-time = "2025-08-07T15:42:55.571Z" }, - { url = "https://files.pythonhosted.org/packages/e7/4a/2890d9ccaf4b383fea43ae6362252870dcd97dda7412f34f20d80ccf7a39/uv-0.8.6-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:1913f5627c57076c88dd38b0173bdb006ae9b8dbd92b1798a1acc9d744c1a7cc", size = 17813305, upload-time = "2025-08-07T15:42:57.998Z" }, - { url = "https://files.pythonhosted.org/packages/9b/c3/33a10049728ffbcde673b75b9a73cd61bfab5e1598d935d1f1b2556b07a4/uv-0.8.6-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7796acc3c5b84d5ee5e10cc6cf92eb61c19f6551855d0aa89ef5925e4a371fbf", size = 18159834, upload-time = "2025-08-07T15:43:00.207Z" }, - { url = "https://files.pythonhosted.org/packages/81/28/ff884f7007a6b9d0e3368dbe4ae7d28acacbaaf1b3a583640e5af6dc5360/uv-0.8.6-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:57a98367bfad38e870e1a8a6626464796ffcee6e937d429fbd7b25ddf46bb36f", size = 18954223, upload-time = "2025-08-07T15:43:03.577Z" }, - { url = "https://files.pythonhosted.org/packages/78/1d/a4ed2da913ecacc1c976e97dff905979c13359834eeeac8bbaf5ed0b2fca/uv-0.8.6-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:2ac28509db2e52613a59264bdb150d13274ed13e5b305f7e274da8cd83033985", size = 20215802, upload-time = "2025-08-07T15:43:06.181Z" }, - { url = "https://files.pythonhosted.org/packages/2c/12/c9ca1cc8bdbecd54db4a7c1a44808f15271da60838dfa9f180ce8171407a/uv-0.8.6-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:deab2ce32d2dd7a1c0de459aa23470c60feb0ea24e67c9c5c5988d8bf4eb4a09", size = 19898210, upload-time = "2025-08-07T15:43:09.008Z" }, - { url = "https://files.pythonhosted.org/packages/c0/15/e10347768b2929ae9c65abbfd0867a736e6227f6d63da1f86fe6bdcbcdca/uv-0.8.6-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5b201ebc1c5c76c3a415fa4edcb25a0e06263d2255319d6d52275c775e926e23", size = 19247208, upload-time = "2025-08-07T15:43:11.578Z" }, - { url = "https://files.pythonhosted.org/packages/62/8d/dc290df05d1820d003f30e2fb7853496eec43bcb986c5e35aaea2f5343d3/uv-0.8.6-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6acdc77099906ba64bc1b725bef973c10905d7e9596d1b25f271db772bc9e8e4", size = 19261881, upload-time = "2025-08-07T15:43:13.815Z" }, - { url = "https://files.pythonhosted.org/packages/20/bd/6c3b9c87e4ed323f72de6ece7d51a6179091f0ff6e0c9c6ed29e28efe17c/uv-0.8.6-py3-none-manylinux_2_28_aarch64.whl", hash = "sha256:4e81380549151e34ae96d56499438444ba58591ca9f2fc6ba0a867152601849e", size = 18037135, upload-time = "2025-08-07T15:43:15.941Z" }, - { url = "https://files.pythonhosted.org/packages/7d/e1/b3e825ad9cc3f03f0f3e232286f91aef985d8029db69fd7091c2f332212b/uv-0.8.6-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:c9de4adac36a62e4bddd959ce65fb4bb09b0cbfd95946d50390f2a9c186ecb9c", size = 19040739, upload-time = "2025-08-07T15:43:18.092Z" }, - { url = "https://files.pythonhosted.org/packages/c5/14/921e2e7b2a4be0bac17f9d04a126546b89828bb33aa56368af7f00538fe3/uv-0.8.6-py3-none-musllinux_1_1_armv7l.whl", hash = "sha256:993af2c295856c5ca053678a8dadc11ce2f85485513ed1568c16e98d5dfa88bf", size = 18060742, upload-time = "2025-08-07T15:43:20.39Z" }, - { url = "https://files.pythonhosted.org/packages/81/54/0b1ecc64353725b62f02d3739a67a567faa70c76c4ea19a21253df1c4d99/uv-0.8.6-py3-none-musllinux_1_1_i686.whl", hash = "sha256:132e73f1e9fe05edc6c06c00416f7c721c48298786fd7293be6c584793170bbc", size = 18430300, upload-time = "2025-08-07T15:43:22.797Z" }, - { url = "https://files.pythonhosted.org/packages/da/be/a1a249eacb9b1e397292106250490ec1546a90c0e19de19f0b36f52aecea/uv-0.8.6-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:ee67acf1b211be2cfbeaec16cde13c8325810d32ff85963a9dedd1f9d7c61ef7", size = 19407124, upload-time = "2025-08-07T15:43:25.915Z" }, - { url = "https://files.pythonhosted.org/packages/11/18/552bb94bb931ea9d09a0e98e5c3d8cefc8c8db25549af88d1484e52d6cdd/uv-0.8.6-py3-none-win32.whl", hash = "sha256:e35cc1ef79d3dce2b6aeffbfb280d02d5ad741d4ca07874bdf0a4d85c841d9de", size = 18324229, upload-time = "2025-08-07T15:43:28.029Z" }, - { url = "https://files.pythonhosted.org/packages/fd/df/b7d1171579e2cc821aafc38a86393104e5426ac1ebc4e95be79ac705a11f/uv-0.8.6-py3-none-win_amd64.whl", hash = "sha256:37227aaf1e41c7eda3d7f0028e747a2a2eed3f3506b0adc121a4366e8281115b", size = 20279856, upload-time = "2025-08-07T15:43:30.07Z" }, - { url = "https://files.pythonhosted.org/packages/09/1b/2629d605e101db6a52397e6ea8859a51af0207cf254051b2a621c683ee07/uv-0.8.6-py3-none-win_arm64.whl", hash = "sha256:0b524de39f317bd8733c38cf100b6f8091d44e06b23f7752523ad1ad1454ede3", size = 18839643, upload-time = "2025-08-07T15:43:32.332Z" }, +version = "0.8.10" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/01/c8/e8a279be427bc685f5f6ffcaf04ab33e119bc504bd608582325654dc9b28/uv-0.8.10.tar.gz", hash = "sha256:af8a5526b0e331775a264fa0dbccfd53c183cb974f269a208af136d7561f9eb2", size = 3484570, upload-time = "2025-08-13T20:35:24.45Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ad/00/4605a743cf18a881574442f2c2de7ef5282147f3b51601d0c91e4b6cff6e/uv-0.8.10-py3-none-linux_armv6l.whl", hash = "sha256:9ad21eeaa4156a1bf5ed85903f80db06e2c02badd3a587ba98d3171517960555", size = 18491669, upload-time = "2025-08-13T20:34:35.674Z" }, + { url = "https://files.pythonhosted.org/packages/26/e4/4d5cff7ea2eaa2c8bb8c88fd6937c5fd1e4463bca4232aa4e1ccc4e5f792/uv-0.8.10-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:defc50bb319be2d58be74a680710cd4b7697e88d5f79974eacd354df95f0b6b0", size = 18535975, upload-time = "2025-08-13T20:34:39.346Z" }, + { url = "https://files.pythonhosted.org/packages/a8/76/78f40228077514af4fa459ad9e6270de75fc89a089b3e78764ee54e0406b/uv-0.8.10-py3-none-macosx_11_0_arm64.whl", hash = "sha256:88df34c32555064fae459cce665757619fd1af7deb2dc393352b15d909d2d131", size = 17209654, upload-time = "2025-08-13T20:34:41.945Z" }, + { url = "https://files.pythonhosted.org/packages/9b/42/05c4597c98d8e3a08e352e148cb3ded08e2e7bed0eb0bf4ebacc5947a79d/uv-0.8.10-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:c4a493cd4b15b3aef11523531aff96a77a586666a63e842fa437966b7b7ee62d", size = 17800097, upload-time = "2025-08-13T20:34:44.144Z" }, + { url = "https://files.pythonhosted.org/packages/eb/7e/5225dad966f7333d37c69e02ebebd08f433b988b2b7a16d32a7ce7de1409/uv-0.8.10-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:86fe044c2be43977566a0d184a487edd7aace2febb757fd95927684b629ef50b", size = 18148771, upload-time = "2025-08-13T20:34:46.229Z" }, + { url = "https://files.pythonhosted.org/packages/90/99/380a607253fa9114d6490837faf56577c3aa3f7627cd221475ff33c847c8/uv-0.8.10-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4cc190d403a89e46d13cec83b6f8e8d7d07aaf1e5a996eac9a3f0c2a8cd92537", size = 18958576, upload-time = "2025-08-13T20:34:48.318Z" }, + { url = "https://files.pythonhosted.org/packages/a0/81/0b70cf49acb03f0b4d654d947216f9c4f6278adcaf9151b1d631faa5c6a6/uv-0.8.10-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:57b71dc79eff25a5419d3fe4a563d3b9397f55d789f685ef27f43f033b31f482", size = 20244856, upload-time = "2025-08-13T20:34:50.661Z" }, + { url = "https://files.pythonhosted.org/packages/96/a7/60a16660790065d1e4cf81b9a88450cde6095d0be242a7c8d7ad8ffaf1b6/uv-0.8.10-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:eb79a46d8099f563ef58237bf4e9009f876a40145e757ea883a92b24b724d01e", size = 19925999, upload-time = "2025-08-13T20:34:53.248Z" }, + { url = "https://files.pythonhosted.org/packages/57/c9/fdf511b55dbeed7e75811f5d44b2152f2cf977895f7af98584035adb287d/uv-0.8.10-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:38286d230daad82388469c8dc7a1d2f5dc279c11178319c886d1a88d7938e513", size = 19275418, upload-time = "2025-08-13T20:34:55.589Z" }, + { url = "https://files.pythonhosted.org/packages/e0/48/d3f1edfc5e60e0aec4a994cc3b609a29970cb5c63cf72eeb4795b465da89/uv-0.8.10-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ab072cd3bf2f9dc264659a1ff48ad91a910ac4830bcfe965e2d3f89c86646f46", size = 19256345, upload-time = "2025-08-13T20:34:58.485Z" }, + { url = "https://files.pythonhosted.org/packages/e7/7c/ddc1be8df60a421484a1f15c521618e8e887ea109adf02db281175576487/uv-0.8.10-py3-none-manylinux_2_28_aarch64.whl", hash = "sha256:3fdf89fc40af9902141c39ed943bcfca15664623363335eb032a44f22001e2b4", size = 18091725, upload-time = "2025-08-13T20:35:00.661Z" }, + { url = "https://files.pythonhosted.org/packages/6a/c3/f893d6872150ede53be6de0d7167fd2791cad11d83af46856d71ca432b57/uv-0.8.10-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:36a5ce708d52388c37043e7335f9eb3fea5a19a56166a2cc6adb365179a1cd77", size = 18973295, upload-time = "2025-08-13T20:35:03.289Z" }, + { url = "https://files.pythonhosted.org/packages/a0/43/56c902f8ebd4c13cefe7ff59d8c3ef4be33cb76f3903aed0936c2fc1f15f/uv-0.8.10-py3-none-musllinux_1_1_armv7l.whl", hash = "sha256:a5495b5a6e3111c03cf5e4dbdd598bc8fd1da887e3920d58cd5a2d4c8bc9a473", size = 18110100, upload-time = "2025-08-13T20:35:05.458Z" }, + { url = "https://files.pythonhosted.org/packages/0f/d5/44ed1228f930d530fdd013262a8fa6f4be73736f46b43a72d90561517466/uv-0.8.10-py3-none-musllinux_1_1_i686.whl", hash = "sha256:b3ff3c451fcd23ea78356d8c18e802d0e423cbe655273601e3ec039a51b33286", size = 18505545, upload-time = "2025-08-13T20:35:08.156Z" }, + { url = "https://files.pythonhosted.org/packages/63/c5/8ae29f3635b92609c294712a24659ef618c32f51e66d2b52d846a1cb487b/uv-0.8.10-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:31e4fc37ee94b94c032384a0957ad32ba7dce4ce6c04b4880fd3e31e25e51a82", size = 19393427, upload-time = "2025-08-13T20:35:11.806Z" }, + { url = "https://files.pythonhosted.org/packages/23/2c/eba3ae60b8de7062cb727cce0fb30c84e5975e1191f5fb6683b5abf73781/uv-0.8.10-py3-none-win32.whl", hash = "sha256:3e190cee3bb2b4f574a419eef87ae8e33f713e9cd6f856b83277ece70ad9ca9b", size = 18278764, upload-time = "2025-08-13T20:35:15.069Z" }, + { url = "https://files.pythonhosted.org/packages/97/ed/bce1c3833edf701a973535982ee8c38514054a4f5ebf0f69a14f652510b7/uv-0.8.10-py3-none-win_amd64.whl", hash = "sha256:b00637c63d5dfc9f879281c5c91db2bb909ab1f9ab275dab015e7fb6cac6be5b", size = 20267476, upload-time = "2025-08-13T20:35:18.52Z" }, + { url = "https://files.pythonhosted.org/packages/56/56/87859397617fd08ce513efe20f6cd6798bfafc9f675a233892449fd94d14/uv-0.8.10-py3-none-win_arm64.whl", hash = "sha256:e0a02bcec766eb0862b7082ab746b204add7d9fcaa62322502d159b5a7ccc54a", size = 18866639, upload-time = "2025-08-13T20:35:20.993Z" }, ] [[package]] name = "virtualenv" -version = "20.33.1" +version = "20.34.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "distlib" }, { name = "filelock" }, { name = "platformdirs" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/8b/60/4f20960df6c7b363a18a55ab034c8f2bcd5d9770d1f94f9370ec104c1855/virtualenv-20.33.1.tar.gz", hash = "sha256:1b44478d9e261b3fb8baa5e74a0ca3bc0e05f21aa36167bf9cbf850e542765b8", size = 6082160, upload-time = "2025-08-05T16:10:55.605Z" } +sdist = { url = "https://files.pythonhosted.org/packages/1c/14/37fcdba2808a6c615681cd216fecae00413c9dab44fb2e57805ecf3eaee3/virtualenv-20.34.0.tar.gz", hash = "sha256:44815b2c9dee7ed86e387b842a84f20b93f7f417f95886ca1996a72a4138eb1a", size = 6003808, upload-time = "2025-08-13T14:24:07.464Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ca/ff/ded57ac5ff40a09e6e198550bab075d780941e0b0f83cbeabd087c59383a/virtualenv-20.33.1-py3-none-any.whl", hash = "sha256:07c19bc66c11acab6a5958b815cbcee30891cd1c2ccf53785a28651a0d8d8a67", size = 6060362, upload-time = "2025-08-05T16:10:52.81Z" }, + { url = "https://files.pythonhosted.org/packages/76/06/04c8e804f813cf972e3262f3f8584c232de64f0cde9f703b46cf53a45090/virtualenv-20.34.0-py3-none-any.whl", hash = "sha256:341f5afa7eee943e4984a9207c025feedd768baff6753cd660c857ceb3e36026", size = 5983279, upload-time = "2025-08-13T14:24:05.111Z" }, ] [[package]] @@ -2738,55 +2767,61 @@ wheels = [ [[package]] name = "wrapt" -version = "1.17.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/c3/fc/e91cc220803d7bc4db93fb02facd8461c37364151b8494762cc88b0fbcef/wrapt-1.17.2.tar.gz", hash = "sha256:41388e9d4d1522446fe79d3213196bd9e3b301a336965b9e27ca2788ebd122f3", size = 55531, upload-time = "2025-01-14T10:35:45.465Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/cd/f7/a2aab2cbc7a665efab072344a8949a71081eed1d2f451f7f7d2b966594a2/wrapt-1.17.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ff04ef6eec3eee8a5efef2401495967a916feaa353643defcc03fc74fe213b58", size = 53308, upload-time = "2025-01-14T10:33:33.992Z" }, - { url = "https://files.pythonhosted.org/packages/50/ff/149aba8365fdacef52b31a258c4dc1c57c79759c335eff0b3316a2664a64/wrapt-1.17.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4db983e7bca53819efdbd64590ee96c9213894272c776966ca6306b73e4affda", size = 38488, upload-time = "2025-01-14T10:33:35.264Z" }, - { url = "https://files.pythonhosted.org/packages/65/46/5a917ce85b5c3b490d35c02bf71aedaa9f2f63f2d15d9949cc4ba56e8ba9/wrapt-1.17.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9abc77a4ce4c6f2a3168ff34b1da9b0f311a8f1cfd694ec96b0603dff1c79438", size = 38776, upload-time = "2025-01-14T10:33:38.28Z" }, - { url = "https://files.pythonhosted.org/packages/ca/74/336c918d2915a4943501c77566db41d1bd6e9f4dbc317f356b9a244dfe83/wrapt-1.17.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0b929ac182f5ace000d459c59c2c9c33047e20e935f8e39371fa6e3b85d56f4a", size = 83776, upload-time = "2025-01-14T10:33:40.678Z" }, - { url = "https://files.pythonhosted.org/packages/09/99/c0c844a5ccde0fe5761d4305485297f91d67cf2a1a824c5f282e661ec7ff/wrapt-1.17.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f09b286faeff3c750a879d336fb6d8713206fc97af3adc14def0cdd349df6000", size = 75420, upload-time = "2025-01-14T10:33:41.868Z" }, - { url = "https://files.pythonhosted.org/packages/b4/b0/9fc566b0fe08b282c850063591a756057c3247b2362b9286429ec5bf1721/wrapt-1.17.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1a7ed2d9d039bd41e889f6fb9364554052ca21ce823580f6a07c4ec245c1f5d6", size = 83199, upload-time = "2025-01-14T10:33:43.598Z" }, - { url = "https://files.pythonhosted.org/packages/9d/4b/71996e62d543b0a0bd95dda485219856def3347e3e9380cc0d6cf10cfb2f/wrapt-1.17.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:129a150f5c445165ff941fc02ee27df65940fcb8a22a61828b1853c98763a64b", size = 82307, upload-time = "2025-01-14T10:33:48.499Z" }, - { url = "https://files.pythonhosted.org/packages/39/35/0282c0d8789c0dc9bcc738911776c762a701f95cfe113fb8f0b40e45c2b9/wrapt-1.17.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:1fb5699e4464afe5c7e65fa51d4f99e0b2eadcc176e4aa33600a3df7801d6662", size = 75025, upload-time = "2025-01-14T10:33:51.191Z" }, - { url = "https://files.pythonhosted.org/packages/4f/6d/90c9fd2c3c6fee181feecb620d95105370198b6b98a0770cba090441a828/wrapt-1.17.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9a2bce789a5ea90e51a02dfcc39e31b7f1e662bc3317979aa7e5538e3a034f72", size = 81879, upload-time = "2025-01-14T10:33:52.328Z" }, - { url = "https://files.pythonhosted.org/packages/8f/fa/9fb6e594f2ce03ef03eddbdb5f4f90acb1452221a5351116c7c4708ac865/wrapt-1.17.2-cp311-cp311-win32.whl", hash = "sha256:4afd5814270fdf6380616b321fd31435a462019d834f83c8611a0ce7484c7317", size = 36419, upload-time = "2025-01-14T10:33:53.551Z" }, - { url = "https://files.pythonhosted.org/packages/47/f8/fb1773491a253cbc123c5d5dc15c86041f746ed30416535f2a8df1f4a392/wrapt-1.17.2-cp311-cp311-win_amd64.whl", hash = "sha256:acc130bc0375999da18e3d19e5a86403667ac0c4042a094fefb7eec8ebac7cf3", size = 38773, upload-time = "2025-01-14T10:33:56.323Z" }, - { url = "https://files.pythonhosted.org/packages/a1/bd/ab55f849fd1f9a58ed7ea47f5559ff09741b25f00c191231f9f059c83949/wrapt-1.17.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:d5e2439eecc762cd85e7bd37161d4714aa03a33c5ba884e26c81559817ca0925", size = 53799, upload-time = "2025-01-14T10:33:57.4Z" }, - { url = "https://files.pythonhosted.org/packages/53/18/75ddc64c3f63988f5a1d7e10fb204ffe5762bc663f8023f18ecaf31a332e/wrapt-1.17.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:3fc7cb4c1c744f8c05cd5f9438a3caa6ab94ce8344e952d7c45a8ed59dd88392", size = 38821, upload-time = "2025-01-14T10:33:59.334Z" }, - { url = "https://files.pythonhosted.org/packages/48/2a/97928387d6ed1c1ebbfd4efc4133a0633546bec8481a2dd5ec961313a1c7/wrapt-1.17.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8fdbdb757d5390f7c675e558fd3186d590973244fab0c5fe63d373ade3e99d40", size = 38919, upload-time = "2025-01-14T10:34:04.093Z" }, - { url = "https://files.pythonhosted.org/packages/73/54/3bfe5a1febbbccb7a2f77de47b989c0b85ed3a6a41614b104204a788c20e/wrapt-1.17.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5bb1d0dbf99411f3d871deb6faa9aabb9d4e744d67dcaaa05399af89d847a91d", size = 88721, upload-time = "2025-01-14T10:34:07.163Z" }, - { url = "https://files.pythonhosted.org/packages/25/cb/7262bc1b0300b4b64af50c2720ef958c2c1917525238d661c3e9a2b71b7b/wrapt-1.17.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d18a4865f46b8579d44e4fe1e2bcbc6472ad83d98e22a26c963d46e4c125ef0b", size = 80899, upload-time = "2025-01-14T10:34:09.82Z" }, - { url = "https://files.pythonhosted.org/packages/2a/5a/04cde32b07a7431d4ed0553a76fdb7a61270e78c5fd5a603e190ac389f14/wrapt-1.17.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc570b5f14a79734437cb7b0500376b6b791153314986074486e0b0fa8d71d98", size = 89222, upload-time = "2025-01-14T10:34:11.258Z" }, - { url = "https://files.pythonhosted.org/packages/09/28/2e45a4f4771fcfb109e244d5dbe54259e970362a311b67a965555ba65026/wrapt-1.17.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6d9187b01bebc3875bac9b087948a2bccefe464a7d8f627cf6e48b1bbae30f82", size = 86707, upload-time = "2025-01-14T10:34:12.49Z" }, - { url = "https://files.pythonhosted.org/packages/c6/d2/dcb56bf5f32fcd4bd9aacc77b50a539abdd5b6536872413fd3f428b21bed/wrapt-1.17.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:9e8659775f1adf02eb1e6f109751268e493c73716ca5761f8acb695e52a756ae", size = 79685, upload-time = "2025-01-14T10:34:15.043Z" }, - { url = "https://files.pythonhosted.org/packages/80/4e/eb8b353e36711347893f502ce91c770b0b0929f8f0bed2670a6856e667a9/wrapt-1.17.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e8b2816ebef96d83657b56306152a93909a83f23994f4b30ad4573b00bd11bb9", size = 87567, upload-time = "2025-01-14T10:34:16.563Z" }, - { url = "https://files.pythonhosted.org/packages/17/27/4fe749a54e7fae6e7146f1c7d914d28ef599dacd4416566c055564080fe2/wrapt-1.17.2-cp312-cp312-win32.whl", hash = "sha256:468090021f391fe0056ad3e807e3d9034e0fd01adcd3bdfba977b6fdf4213ea9", size = 36672, upload-time = "2025-01-14T10:34:17.727Z" }, - { url = "https://files.pythonhosted.org/packages/15/06/1dbf478ea45c03e78a6a8c4be4fdc3c3bddea5c8de8a93bc971415e47f0f/wrapt-1.17.2-cp312-cp312-win_amd64.whl", hash = "sha256:ec89ed91f2fa8e3f52ae53cd3cf640d6feff92ba90d62236a81e4e563ac0e991", size = 38865, upload-time = "2025-01-14T10:34:19.577Z" }, - { url = "https://files.pythonhosted.org/packages/ce/b9/0ffd557a92f3b11d4c5d5e0c5e4ad057bd9eb8586615cdaf901409920b14/wrapt-1.17.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:6ed6ffac43aecfe6d86ec5b74b06a5be33d5bb9243d055141e8cabb12aa08125", size = 53800, upload-time = "2025-01-14T10:34:21.571Z" }, - { url = "https://files.pythonhosted.org/packages/c0/ef/8be90a0b7e73c32e550c73cfb2fa09db62234227ece47b0e80a05073b375/wrapt-1.17.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:35621ae4c00e056adb0009f8e86e28eb4a41a4bfa8f9bfa9fca7d343fe94f998", size = 38824, upload-time = "2025-01-14T10:34:22.999Z" }, - { url = "https://files.pythonhosted.org/packages/36/89/0aae34c10fe524cce30fe5fc433210376bce94cf74d05b0d68344c8ba46e/wrapt-1.17.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a604bf7a053f8362d27eb9fefd2097f82600b856d5abe996d623babd067b1ab5", size = 38920, upload-time = "2025-01-14T10:34:25.386Z" }, - { url = "https://files.pythonhosted.org/packages/3b/24/11c4510de906d77e0cfb5197f1b1445d4fec42c9a39ea853d482698ac681/wrapt-1.17.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5cbabee4f083b6b4cd282f5b817a867cf0b1028c54d445b7ec7cfe6505057cf8", size = 88690, upload-time = "2025-01-14T10:34:28.058Z" }, - { url = "https://files.pythonhosted.org/packages/71/d7/cfcf842291267bf455b3e266c0c29dcb675b5540ee8b50ba1699abf3af45/wrapt-1.17.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:49703ce2ddc220df165bd2962f8e03b84c89fee2d65e1c24a7defff6f988f4d6", size = 80861, upload-time = "2025-01-14T10:34:29.167Z" }, - { url = "https://files.pythonhosted.org/packages/d5/66/5d973e9f3e7370fd686fb47a9af3319418ed925c27d72ce16b791231576d/wrapt-1.17.2-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8112e52c5822fc4253f3901b676c55ddf288614dc7011634e2719718eaa187dc", size = 89174, upload-time = "2025-01-14T10:34:31.702Z" }, - { url = "https://files.pythonhosted.org/packages/a7/d3/8e17bb70f6ae25dabc1aaf990f86824e4fd98ee9cadf197054e068500d27/wrapt-1.17.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:9fee687dce376205d9a494e9c121e27183b2a3df18037f89d69bd7b35bcf59e2", size = 86721, upload-time = "2025-01-14T10:34:32.91Z" }, - { url = "https://files.pythonhosted.org/packages/6f/54/f170dfb278fe1c30d0ff864513cff526d624ab8de3254b20abb9cffedc24/wrapt-1.17.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:18983c537e04d11cf027fbb60a1e8dfd5190e2b60cc27bc0808e653e7b218d1b", size = 79763, upload-time = "2025-01-14T10:34:34.903Z" }, - { url = "https://files.pythonhosted.org/packages/4a/98/de07243751f1c4a9b15c76019250210dd3486ce098c3d80d5f729cba029c/wrapt-1.17.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:703919b1633412ab54bcf920ab388735832fdcb9f9a00ae49387f0fe67dad504", size = 87585, upload-time = "2025-01-14T10:34:36.13Z" }, - { url = "https://files.pythonhosted.org/packages/f9/f0/13925f4bd6548013038cdeb11ee2cbd4e37c30f8bfd5db9e5a2a370d6e20/wrapt-1.17.2-cp313-cp313-win32.whl", hash = "sha256:abbb9e76177c35d4e8568e58650aa6926040d6a9f6f03435b7a522bf1c487f9a", size = 36676, upload-time = "2025-01-14T10:34:37.962Z" }, - { url = "https://files.pythonhosted.org/packages/bf/ae/743f16ef8c2e3628df3ddfd652b7d4c555d12c84b53f3d8218498f4ade9b/wrapt-1.17.2-cp313-cp313-win_amd64.whl", hash = "sha256:69606d7bb691b50a4240ce6b22ebb319c1cfb164e5f6569835058196e0f3a845", size = 38871, upload-time = "2025-01-14T10:34:39.13Z" }, - { url = "https://files.pythonhosted.org/packages/3d/bc/30f903f891a82d402ffb5fda27ec1d621cc97cb74c16fea0b6141f1d4e87/wrapt-1.17.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:4a721d3c943dae44f8e243b380cb645a709ba5bd35d3ad27bc2ed947e9c68192", size = 56312, upload-time = "2025-01-14T10:34:40.604Z" }, - { url = "https://files.pythonhosted.org/packages/8a/04/c97273eb491b5f1c918857cd26f314b74fc9b29224521f5b83f872253725/wrapt-1.17.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:766d8bbefcb9e00c3ac3b000d9acc51f1b399513f44d77dfe0eb026ad7c9a19b", size = 40062, upload-time = "2025-01-14T10:34:45.011Z" }, - { url = "https://files.pythonhosted.org/packages/4e/ca/3b7afa1eae3a9e7fefe499db9b96813f41828b9fdb016ee836c4c379dadb/wrapt-1.17.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:e496a8ce2c256da1eb98bd15803a79bee00fc351f5dfb9ea82594a3f058309e0", size = 40155, upload-time = "2025-01-14T10:34:47.25Z" }, - { url = "https://files.pythonhosted.org/packages/89/be/7c1baed43290775cb9030c774bc53c860db140397047cc49aedaf0a15477/wrapt-1.17.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40d615e4fe22f4ad3528448c193b218e077656ca9ccb22ce2cb20db730f8d306", size = 113471, upload-time = "2025-01-14T10:34:50.934Z" }, - { url = "https://files.pythonhosted.org/packages/32/98/4ed894cf012b6d6aae5f5cc974006bdeb92f0241775addad3f8cd6ab71c8/wrapt-1.17.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a5aaeff38654462bc4b09023918b7f21790efb807f54c000a39d41d69cf552cb", size = 101208, upload-time = "2025-01-14T10:34:52.297Z" }, - { url = "https://files.pythonhosted.org/packages/ea/fd/0c30f2301ca94e655e5e057012e83284ce8c545df7661a78d8bfca2fac7a/wrapt-1.17.2-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9a7d15bbd2bc99e92e39f49a04653062ee6085c0e18b3b7512a4f2fe91f2d681", size = 109339, upload-time = "2025-01-14T10:34:53.489Z" }, - { url = "https://files.pythonhosted.org/packages/75/56/05d000de894c4cfcb84bcd6b1df6214297b8089a7bd324c21a4765e49b14/wrapt-1.17.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:e3890b508a23299083e065f435a492b5435eba6e304a7114d2f919d400888cc6", size = 110232, upload-time = "2025-01-14T10:34:55.327Z" }, - { url = "https://files.pythonhosted.org/packages/53/f8/c3f6b2cf9b9277fb0813418e1503e68414cd036b3b099c823379c9575e6d/wrapt-1.17.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:8c8b293cd65ad716d13d8dd3624e42e5a19cc2a2f1acc74b30c2c13f15cb61a6", size = 100476, upload-time = "2025-01-14T10:34:58.055Z" }, - { url = "https://files.pythonhosted.org/packages/a7/b1/0bb11e29aa5139d90b770ebbfa167267b1fc548d2302c30c8f7572851738/wrapt-1.17.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:4c82b8785d98cdd9fed4cac84d765d234ed3251bd6afe34cb7ac523cb93e8b4f", size = 106377, upload-time = "2025-01-14T10:34:59.3Z" }, - { url = "https://files.pythonhosted.org/packages/6a/e1/0122853035b40b3f333bbb25f1939fc1045e21dd518f7f0922b60c156f7c/wrapt-1.17.2-cp313-cp313t-win32.whl", hash = "sha256:13e6afb7fe71fe7485a4550a8844cc9ffbe263c0f1a1eea569bc7091d4898555", size = 37986, upload-time = "2025-01-14T10:35:00.498Z" }, - { url = "https://files.pythonhosted.org/packages/09/5e/1655cf481e079c1f22d0cabdd4e51733679932718dc23bf2db175f329b76/wrapt-1.17.2-cp313-cp313t-win_amd64.whl", hash = "sha256:eaf675418ed6b3b31c7a989fd007fa7c3be66ce14e5c3b27336383604c9da85c", size = 40750, upload-time = "2025-01-14T10:35:03.378Z" }, - { url = "https://files.pythonhosted.org/packages/2d/82/f56956041adef78f849db6b289b282e72b55ab8045a75abad81898c28d19/wrapt-1.17.2-py3-none-any.whl", hash = "sha256:b18f2d1533a71f069c7f82d524a52599053d4c7166e9dd374ae2136b7f40f7c8", size = 23594, upload-time = "2025-01-14T10:35:44.018Z" }, +version = "1.17.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/95/8f/aeb76c5b46e273670962298c23e7ddde79916cb74db802131d49a85e4b7d/wrapt-1.17.3.tar.gz", hash = "sha256:f66eb08feaa410fe4eebd17f2a2c8e2e46d3476e9f8c783daa8e09e0faa666d0", size = 55547, upload-time = "2025-08-12T05:53:21.714Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/52/db/00e2a219213856074a213503fdac0511203dceefff26e1daa15250cc01a0/wrapt-1.17.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:273a736c4645e63ac582c60a56b0acb529ef07f78e08dc6bfadf6a46b19c0da7", size = 53482, upload-time = "2025-08-12T05:51:45.79Z" }, + { url = "https://files.pythonhosted.org/packages/5e/30/ca3c4a5eba478408572096fe9ce36e6e915994dd26a4e9e98b4f729c06d9/wrapt-1.17.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5531d911795e3f935a9c23eb1c8c03c211661a5060aab167065896bbf62a5f85", size = 38674, upload-time = "2025-08-12T05:51:34.629Z" }, + { url = "https://files.pythonhosted.org/packages/31/25/3e8cc2c46b5329c5957cec959cb76a10718e1a513309c31399a4dad07eb3/wrapt-1.17.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:0610b46293c59a3adbae3dee552b648b984176f8562ee0dba099a56cfbe4df1f", size = 38959, upload-time = "2025-08-12T05:51:56.074Z" }, + { url = "https://files.pythonhosted.org/packages/5d/8f/a32a99fc03e4b37e31b57cb9cefc65050ea08147a8ce12f288616b05ef54/wrapt-1.17.3-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:b32888aad8b6e68f83a8fdccbf3165f5469702a7544472bdf41f582970ed3311", size = 82376, upload-time = "2025-08-12T05:52:32.134Z" }, + { url = "https://files.pythonhosted.org/packages/31/57/4930cb8d9d70d59c27ee1332a318c20291749b4fba31f113c2f8ac49a72e/wrapt-1.17.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8cccf4f81371f257440c88faed6b74f1053eef90807b77e31ca057b2db74edb1", size = 83604, upload-time = "2025-08-12T05:52:11.663Z" }, + { url = "https://files.pythonhosted.org/packages/a8/f3/1afd48de81d63dd66e01b263a6fbb86e1b5053b419b9b33d13e1f6d0f7d0/wrapt-1.17.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d8a210b158a34164de8bb68b0e7780041a903d7b00c87e906fb69928bf7890d5", size = 82782, upload-time = "2025-08-12T05:52:12.626Z" }, + { url = "https://files.pythonhosted.org/packages/1e/d7/4ad5327612173b144998232f98a85bb24b60c352afb73bc48e3e0d2bdc4e/wrapt-1.17.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:79573c24a46ce11aab457b472efd8d125e5a51da2d1d24387666cd85f54c05b2", size = 82076, upload-time = "2025-08-12T05:52:33.168Z" }, + { url = "https://files.pythonhosted.org/packages/bb/59/e0adfc831674a65694f18ea6dc821f9fcb9ec82c2ce7e3d73a88ba2e8718/wrapt-1.17.3-cp311-cp311-win32.whl", hash = "sha256:c31eebe420a9a5d2887b13000b043ff6ca27c452a9a22fa71f35f118e8d4bf89", size = 36457, upload-time = "2025-08-12T05:53:03.936Z" }, + { url = "https://files.pythonhosted.org/packages/83/88/16b7231ba49861b6f75fc309b11012ede4d6b0a9c90969d9e0db8d991aeb/wrapt-1.17.3-cp311-cp311-win_amd64.whl", hash = "sha256:0b1831115c97f0663cb77aa27d381237e73ad4f721391a9bfb2fe8bc25fa6e77", size = 38745, upload-time = "2025-08-12T05:53:02.885Z" }, + { url = "https://files.pythonhosted.org/packages/9a/1e/c4d4f3398ec073012c51d1c8d87f715f56765444e1a4b11e5180577b7e6e/wrapt-1.17.3-cp311-cp311-win_arm64.whl", hash = "sha256:5a7b3c1ee8265eb4c8f1b7d29943f195c00673f5ab60c192eba2d4a7eae5f46a", size = 36806, upload-time = "2025-08-12T05:52:53.368Z" }, + { url = "https://files.pythonhosted.org/packages/9f/41/cad1aba93e752f1f9268c77270da3c469883d56e2798e7df6240dcb2287b/wrapt-1.17.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:ab232e7fdb44cdfbf55fc3afa31bcdb0d8980b9b95c38b6405df2acb672af0e0", size = 53998, upload-time = "2025-08-12T05:51:47.138Z" }, + { url = "https://files.pythonhosted.org/packages/60/f8/096a7cc13097a1869fe44efe68dace40d2a16ecb853141394047f0780b96/wrapt-1.17.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:9baa544e6acc91130e926e8c802a17f3b16fbea0fd441b5a60f5cf2cc5c3deba", size = 39020, upload-time = "2025-08-12T05:51:35.906Z" }, + { url = "https://files.pythonhosted.org/packages/33/df/bdf864b8997aab4febb96a9ae5c124f700a5abd9b5e13d2a3214ec4be705/wrapt-1.17.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6b538e31eca1a7ea4605e44f81a48aa24c4632a277431a6ed3f328835901f4fd", size = 39098, upload-time = "2025-08-12T05:51:57.474Z" }, + { url = "https://files.pythonhosted.org/packages/9f/81/5d931d78d0eb732b95dc3ddaeeb71c8bb572fb01356e9133916cd729ecdd/wrapt-1.17.3-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:042ec3bb8f319c147b1301f2393bc19dba6e176b7da446853406d041c36c7828", size = 88036, upload-time = "2025-08-12T05:52:34.784Z" }, + { url = "https://files.pythonhosted.org/packages/ca/38/2e1785df03b3d72d34fc6252d91d9d12dc27a5c89caef3335a1bbb8908ca/wrapt-1.17.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3af60380ba0b7b5aeb329bc4e402acd25bd877e98b3727b0135cb5c2efdaefe9", size = 88156, upload-time = "2025-08-12T05:52:13.599Z" }, + { url = "https://files.pythonhosted.org/packages/b3/8b/48cdb60fe0603e34e05cffda0b2a4adab81fd43718e11111a4b0100fd7c1/wrapt-1.17.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:0b02e424deef65c9f7326d8c19220a2c9040c51dc165cddb732f16198c168396", size = 87102, upload-time = "2025-08-12T05:52:14.56Z" }, + { url = "https://files.pythonhosted.org/packages/3c/51/d81abca783b58f40a154f1b2c56db1d2d9e0d04fa2d4224e357529f57a57/wrapt-1.17.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:74afa28374a3c3a11b3b5e5fca0ae03bef8450d6aa3ab3a1e2c30e3a75d023dc", size = 87732, upload-time = "2025-08-12T05:52:36.165Z" }, + { url = "https://files.pythonhosted.org/packages/9e/b1/43b286ca1392a006d5336412d41663eeef1ad57485f3e52c767376ba7e5a/wrapt-1.17.3-cp312-cp312-win32.whl", hash = "sha256:4da9f45279fff3543c371d5ababc57a0384f70be244de7759c85a7f989cb4ebe", size = 36705, upload-time = "2025-08-12T05:53:07.123Z" }, + { url = "https://files.pythonhosted.org/packages/28/de/49493f962bd3c586ab4b88066e967aa2e0703d6ef2c43aa28cb83bf7b507/wrapt-1.17.3-cp312-cp312-win_amd64.whl", hash = "sha256:e71d5c6ebac14875668a1e90baf2ea0ef5b7ac7918355850c0908ae82bcb297c", size = 38877, upload-time = "2025-08-12T05:53:05.436Z" }, + { url = "https://files.pythonhosted.org/packages/f1/48/0f7102fe9cb1e8a5a77f80d4f0956d62d97034bbe88d33e94699f99d181d/wrapt-1.17.3-cp312-cp312-win_arm64.whl", hash = "sha256:604d076c55e2fdd4c1c03d06dc1a31b95130010517b5019db15365ec4a405fc6", size = 36885, upload-time = "2025-08-12T05:52:54.367Z" }, + { url = "https://files.pythonhosted.org/packages/fc/f6/759ece88472157acb55fc195e5b116e06730f1b651b5b314c66291729193/wrapt-1.17.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:a47681378a0439215912ef542c45a783484d4dd82bac412b71e59cf9c0e1cea0", size = 54003, upload-time = "2025-08-12T05:51:48.627Z" }, + { url = "https://files.pythonhosted.org/packages/4f/a9/49940b9dc6d47027dc850c116d79b4155f15c08547d04db0f07121499347/wrapt-1.17.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:54a30837587c6ee3cd1a4d1c2ec5d24e77984d44e2f34547e2323ddb4e22eb77", size = 39025, upload-time = "2025-08-12T05:51:37.156Z" }, + { url = "https://files.pythonhosted.org/packages/45/35/6a08de0f2c96dcdd7fe464d7420ddb9a7655a6561150e5fc4da9356aeaab/wrapt-1.17.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:16ecf15d6af39246fe33e507105d67e4b81d8f8d2c6598ff7e3ca1b8a37213f7", size = 39108, upload-time = "2025-08-12T05:51:58.425Z" }, + { url = "https://files.pythonhosted.org/packages/0c/37/6faf15cfa41bf1f3dba80cd3f5ccc6622dfccb660ab26ed79f0178c7497f/wrapt-1.17.3-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:6fd1ad24dc235e4ab88cda009e19bf347aabb975e44fd5c2fb22a3f6e4141277", size = 88072, upload-time = "2025-08-12T05:52:37.53Z" }, + { url = "https://files.pythonhosted.org/packages/78/f2/efe19ada4a38e4e15b6dff39c3e3f3f73f5decf901f66e6f72fe79623a06/wrapt-1.17.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0ed61b7c2d49cee3c027372df5809a59d60cf1b6c2f81ee980a091f3afed6a2d", size = 88214, upload-time = "2025-08-12T05:52:15.886Z" }, + { url = "https://files.pythonhosted.org/packages/40/90/ca86701e9de1622b16e09689fc24b76f69b06bb0150990f6f4e8b0eeb576/wrapt-1.17.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:423ed5420ad5f5529db9ce89eac09c8a2f97da18eb1c870237e84c5a5c2d60aa", size = 87105, upload-time = "2025-08-12T05:52:17.914Z" }, + { url = "https://files.pythonhosted.org/packages/fd/e0/d10bd257c9a3e15cbf5523025252cc14d77468e8ed644aafb2d6f54cb95d/wrapt-1.17.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e01375f275f010fcbf7f643b4279896d04e571889b8a5b3f848423d91bf07050", size = 87766, upload-time = "2025-08-12T05:52:39.243Z" }, + { url = "https://files.pythonhosted.org/packages/e8/cf/7d848740203c7b4b27eb55dbfede11aca974a51c3d894f6cc4b865f42f58/wrapt-1.17.3-cp313-cp313-win32.whl", hash = "sha256:53e5e39ff71b3fc484df8a522c933ea2b7cdd0d5d15ae82e5b23fde87d44cbd8", size = 36711, upload-time = "2025-08-12T05:53:10.074Z" }, + { url = "https://files.pythonhosted.org/packages/57/54/35a84d0a4d23ea675994104e667ceff49227ce473ba6a59ba2c84f250b74/wrapt-1.17.3-cp313-cp313-win_amd64.whl", hash = "sha256:1f0b2f40cf341ee8cc1a97d51ff50dddb9fcc73241b9143ec74b30fc4f44f6cb", size = 38885, upload-time = "2025-08-12T05:53:08.695Z" }, + { url = "https://files.pythonhosted.org/packages/01/77/66e54407c59d7b02a3c4e0af3783168fff8e5d61def52cda8728439d86bc/wrapt-1.17.3-cp313-cp313-win_arm64.whl", hash = "sha256:7425ac3c54430f5fc5e7b6f41d41e704db073309acfc09305816bc6a0b26bb16", size = 36896, upload-time = "2025-08-12T05:52:55.34Z" }, + { url = "https://files.pythonhosted.org/packages/02/a2/cd864b2a14f20d14f4c496fab97802001560f9f41554eef6df201cd7f76c/wrapt-1.17.3-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:cf30f6e3c077c8e6a9a7809c94551203c8843e74ba0c960f4a98cd80d4665d39", size = 54132, upload-time = "2025-08-12T05:51:49.864Z" }, + { url = "https://files.pythonhosted.org/packages/d5/46/d011725b0c89e853dc44cceb738a307cde5d240d023d6d40a82d1b4e1182/wrapt-1.17.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:e228514a06843cae89621384cfe3a80418f3c04aadf8a3b14e46a7be704e4235", size = 39091, upload-time = "2025-08-12T05:51:38.935Z" }, + { url = "https://files.pythonhosted.org/packages/2e/9e/3ad852d77c35aae7ddebdbc3b6d35ec8013af7d7dddad0ad911f3d891dae/wrapt-1.17.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:5ea5eb3c0c071862997d6f3e02af1d055f381b1d25b286b9d6644b79db77657c", size = 39172, upload-time = "2025-08-12T05:51:59.365Z" }, + { url = "https://files.pythonhosted.org/packages/c3/f7/c983d2762bcce2326c317c26a6a1e7016f7eb039c27cdf5c4e30f4160f31/wrapt-1.17.3-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:281262213373b6d5e4bb4353bc36d1ba4084e6d6b5d242863721ef2bf2c2930b", size = 87163, upload-time = "2025-08-12T05:52:40.965Z" }, + { url = "https://files.pythonhosted.org/packages/e4/0f/f673f75d489c7f22d17fe0193e84b41540d962f75fce579cf6873167c29b/wrapt-1.17.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:dc4a8d2b25efb6681ecacad42fca8859f88092d8732b170de6a5dddd80a1c8fa", size = 87963, upload-time = "2025-08-12T05:52:20.326Z" }, + { url = "https://files.pythonhosted.org/packages/df/61/515ad6caca68995da2fac7a6af97faab8f78ebe3bf4f761e1b77efbc47b5/wrapt-1.17.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:373342dd05b1d07d752cecbec0c41817231f29f3a89aa8b8843f7b95992ed0c7", size = 86945, upload-time = "2025-08-12T05:52:21.581Z" }, + { url = "https://files.pythonhosted.org/packages/d3/bd/4e70162ce398462a467bc09e768bee112f1412e563620adc353de9055d33/wrapt-1.17.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:d40770d7c0fd5cbed9d84b2c3f2e156431a12c9a37dc6284060fb4bec0b7ffd4", size = 86857, upload-time = "2025-08-12T05:52:43.043Z" }, + { url = "https://files.pythonhosted.org/packages/2b/b8/da8560695e9284810b8d3df8a19396a6e40e7518059584a1a394a2b35e0a/wrapt-1.17.3-cp314-cp314-win32.whl", hash = "sha256:fbd3c8319de8e1dc79d346929cd71d523622da527cca14e0c1d257e31c2b8b10", size = 37178, upload-time = "2025-08-12T05:53:12.605Z" }, + { url = "https://files.pythonhosted.org/packages/db/c8/b71eeb192c440d67a5a0449aaee2310a1a1e8eca41676046f99ed2487e9f/wrapt-1.17.3-cp314-cp314-win_amd64.whl", hash = "sha256:e1a4120ae5705f673727d3253de3ed0e016f7cd78dc463db1b31e2463e1f3cf6", size = 39310, upload-time = "2025-08-12T05:53:11.106Z" }, + { url = "https://files.pythonhosted.org/packages/45/20/2cda20fd4865fa40f86f6c46ed37a2a8356a7a2fde0773269311f2af56c7/wrapt-1.17.3-cp314-cp314-win_arm64.whl", hash = "sha256:507553480670cab08a800b9463bdb881b2edeed77dc677b0a5915e6106e91a58", size = 37266, upload-time = "2025-08-12T05:52:56.531Z" }, + { url = "https://files.pythonhosted.org/packages/77/ed/dd5cf21aec36c80443c6f900449260b80e2a65cf963668eaef3b9accce36/wrapt-1.17.3-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:ed7c635ae45cfbc1a7371f708727bf74690daedc49b4dba310590ca0bd28aa8a", size = 56544, upload-time = "2025-08-12T05:51:51.109Z" }, + { url = "https://files.pythonhosted.org/packages/8d/96/450c651cc753877ad100c7949ab4d2e2ecc4d97157e00fa8f45df682456a/wrapt-1.17.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:249f88ed15503f6492a71f01442abddd73856a0032ae860de6d75ca62eed8067", size = 40283, upload-time = "2025-08-12T05:51:39.912Z" }, + { url = "https://files.pythonhosted.org/packages/d1/86/2fcad95994d9b572db57632acb6f900695a648c3e063f2cd344b3f5c5a37/wrapt-1.17.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:5a03a38adec8066d5a37bea22f2ba6bbf39fcdefbe2d91419ab864c3fb515454", size = 40366, upload-time = "2025-08-12T05:52:00.693Z" }, + { url = "https://files.pythonhosted.org/packages/64/0e/f4472f2fdde2d4617975144311f8800ef73677a159be7fe61fa50997d6c0/wrapt-1.17.3-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:5d4478d72eb61c36e5b446e375bbc49ed002430d17cdec3cecb36993398e1a9e", size = 108571, upload-time = "2025-08-12T05:52:44.521Z" }, + { url = "https://files.pythonhosted.org/packages/cc/01/9b85a99996b0a97c8a17484684f206cbb6ba73c1ce6890ac668bcf3838fb/wrapt-1.17.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:223db574bb38637e8230eb14b185565023ab624474df94d2af18f1cdb625216f", size = 113094, upload-time = "2025-08-12T05:52:22.618Z" }, + { url = "https://files.pythonhosted.org/packages/25/02/78926c1efddcc7b3aa0bc3d6b33a822f7d898059f7cd9ace8c8318e559ef/wrapt-1.17.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e405adefb53a435f01efa7ccdec012c016b5a1d3f35459990afc39b6be4d5056", size = 110659, upload-time = "2025-08-12T05:52:24.057Z" }, + { url = "https://files.pythonhosted.org/packages/dc/ee/c414501ad518ac3e6fe184753632fe5e5ecacdcf0effc23f31c1e4f7bfcf/wrapt-1.17.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:88547535b787a6c9ce4086917b6e1d291aa8ed914fdd3a838b3539dc95c12804", size = 106946, upload-time = "2025-08-12T05:52:45.976Z" }, + { url = "https://files.pythonhosted.org/packages/be/44/a1bd64b723d13bb151d6cc91b986146a1952385e0392a78567e12149c7b4/wrapt-1.17.3-cp314-cp314t-win32.whl", hash = "sha256:41b1d2bc74c2cac6f9074df52b2efbef2b30bdfe5f40cb78f8ca22963bc62977", size = 38717, upload-time = "2025-08-12T05:53:15.214Z" }, + { url = "https://files.pythonhosted.org/packages/79/d9/7cfd5a312760ac4dd8bf0184a6ee9e43c33e47f3dadc303032ce012b8fa3/wrapt-1.17.3-cp314-cp314t-win_amd64.whl", hash = "sha256:73d496de46cd2cdbdbcce4ae4bcdb4afb6a11234a1df9c085249d55166b95116", size = 41334, upload-time = "2025-08-12T05:53:14.178Z" }, + { url = "https://files.pythonhosted.org/packages/46/78/10ad9781128ed2f99dbc474f43283b13fea8ba58723e98844367531c18e9/wrapt-1.17.3-cp314-cp314t-win_arm64.whl", hash = "sha256:f38e60678850c42461d4202739f9bf1e3a737c7ad283638251e79cc49effb6b6", size = 38471, upload-time = "2025-08-12T05:52:57.784Z" }, + { url = "https://files.pythonhosted.org/packages/1f/f6/a933bd70f98e9cf3e08167fc5cd7aaaca49147e48411c0bd5ae701bb2194/wrapt-1.17.3-py3-none-any.whl", hash = "sha256:7171ae35d2c33d326ac19dd8facb1e82e5fd04ef8c6c0e394d7af55a55051c22", size = 23591, upload-time = "2025-08-12T05:53:20.674Z" }, ] [[package]] From 5bcd92cb084188337af8d7a490758fac75e336cd Mon Sep 17 00:00:00 2001 From: "plasmapy-requirements-bot[bot]" <134649236+plasmapy-requirements-bot[bot]@users.noreply.github.com> Date: Tue, 2 Sep 2025 13:08:37 -0400 Subject: [PATCH 451/521] =?UTF-8?q?Update=20pinned=20requirements=20?= =?UTF-8?q?=F0=9F=93=8D=20(#3097)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update requirements with 'nox -s requirements' * nox -s requirements * Make zizmor ignore uv caching * Update most pre-commit hooks * Add back cache suffix ...only to keep changes minimal for this PR. --------- Co-authored-by: namurphy <8931994+namurphy@users.noreply.github.com> Co-authored-by: Nick Murphy --- .github/workflows/ci.yml | 2 +- .pre-commit-config.yaml | 8 +- uv.lock | 826 ++++++++++++++++++++------------------- 3 files changed, 426 insertions(+), 410 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 422988f76f..f74706e30e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -101,7 +101,7 @@ jobs: uses: astral-sh/setup-uv@v6 with: python-version: ${{ matrix.python }} - enable-cache: true + enable-cache: true # zizmor: ignore[cache-poisoning] cache-suffix: ${{ matrix.nox_session }}-${{ matrix.python }}-${{ runner.os }} - name: Run the check diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 1e5fdc8d52..4cb408e622 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -9,7 +9,7 @@ default_language_version: repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v5.0.0 + rev: v6.0.0 hooks: - id: check-ast name: validate Python code @@ -28,7 +28,7 @@ repos: - id: check-yaml - repo: https://github.com/python-jsonschema/check-jsonschema - rev: 0.33.2 + rev: 0.33.3 hooks: - id: check-github-workflows @@ -80,14 +80,14 @@ repos: - tomli - repo: https://github.com/crate-ci/typos - rev: v1.34.0 + rev: v1.36.0 hooks: - id: typos name: typos (add false positives to _typos.toml) exclude: .pre-commit-search-and-replace.yaml - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.12.7 + rev: v0.12.11 hooks: - id: ruff name: ruff (see https://docs.astral.sh/ruff/rules) diff --git a/uv.lock b/uv.lock index a089d5892a..0e5276601e 100644 --- a/uv.lock +++ b/uv.lock @@ -80,11 +80,11 @@ wheels = [ [[package]] name = "astropy-iers-data" -version = "0.2025.8.11.0.41.9" +version = "0.2025.9.1.0.42.11" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/92/97/e4bcef70ee3a3a76d6888ac5da07ceabba7ed6bc0414a79fbdb1383fd5a5/astropy_iers_data-0.2025.8.11.0.41.9.tar.gz", hash = "sha256:029c3237993fa9689f8543872dfe750393227261111edad8173fdd06d59f1c84", size = 1904623, upload-time = "2025-08-11T00:41:48.52Z" } +sdist = { url = "https://files.pythonhosted.org/packages/2a/9b/f51e45153c47150ddcd585bd54920028d5eeb7b9c9dfdf3a5fa72baf14c3/astropy_iers_data-0.2025.9.1.0.42.11.tar.gz", hash = "sha256:72712dbae9198c2b0de4b21db682c3c678ea84c518287ffb8f13f2f7353dc181", size = 1906998, upload-time = "2025-09-01T00:42:55.757Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/3d/c2/419f11d191c4c0e880c07550d2c764e3bb79fe6dec492a0d850808d31cc3/astropy_iers_data-0.2025.8.11.0.41.9-py3-none-any.whl", hash = "sha256:e5419d191259932413f89609315ad9f185a2977fac219333e23476d4491bfabd", size = 1960190, upload-time = "2025-08-11T00:41:46.797Z" }, + { url = "https://files.pythonhosted.org/packages/0d/b3/3a1fee57e52d85a5daa67ad364300e838007e928732d99b77df3a74278b3/astropy_iers_data-0.2025.9.1.0.42.11-py3-none-any.whl", hash = "sha256:9e7f3970487f7c76115c284717775c58870a94378a6bb8a9164022074af05a4d", size = 1962512, upload-time = "2025-09-01T00:42:54.063Z" }, ] [[package]] @@ -116,15 +116,15 @@ wheels = [ [[package]] name = "beautifulsoup4" -version = "4.13.4" +version = "4.13.5" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "soupsieve" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/d8/e4/0c4c39e18fd76d6a628d4dd8da40543d136ce2d1752bd6eeeab0791f4d6b/beautifulsoup4-4.13.4.tar.gz", hash = "sha256:dbb3c4e1ceae6aefebdaf2423247260cd062430a410e38c66f2baa50a8437195", size = 621067, upload-time = "2025-04-15T17:05:13.836Z" } +sdist = { url = "https://files.pythonhosted.org/packages/85/2e/3e5079847e653b1f6dc647aa24549d68c6addb4c595cc0d902d1b19308ad/beautifulsoup4-4.13.5.tar.gz", hash = "sha256:5e70131382930e7c3de33450a2f54a63d5e4b19386eab43a5b34d594268f3695", size = 622954, upload-time = "2025-08-24T14:06:13.168Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/50/cd/30110dc0ffcf3b131156077b90e9f60ed75711223f306da4db08eff8403b/beautifulsoup4-4.13.4-py3-none-any.whl", hash = "sha256:9bbbb14bfde9d79f38b8cd5f8c7c85f4b8f2523190ebed90e950a8dea4cb1c4b", size = 187285, upload-time = "2025-04-15T17:05:12.221Z" }, + { url = "https://files.pythonhosted.org/packages/04/eb/f4151e0c7377a6e08a38108609ba5cede57986802757848688aeedd1b9e8/beautifulsoup4-4.13.5-py3-none-any.whl", hash = "sha256:642085eaa22233aceadff9c69651bc51e8bf3f874fb6d7104ece2beb24b47c4a", size = 105113, upload-time = "2025-08-24T14:06:14.884Z" }, ] [[package]] @@ -377,77 +377,77 @@ wheels = [ [[package]] name = "coverage" -version = "7.10.3" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f4/2c/253cc41cd0f40b84c1c34c5363e0407d73d4a1cae005fed6db3b823175bd/coverage-7.10.3.tar.gz", hash = "sha256:812ba9250532e4a823b070b0420a36499859542335af3dca8f47fc6aa1a05619", size = 822936, upload-time = "2025-08-10T21:27:39.968Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/87/04/810e506d7a19889c244d35199cbf3239a2f952b55580aa42ca4287409424/coverage-7.10.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f2ff2e2afdf0d51b9b8301e542d9c21a8d084fd23d4c8ea2b3a1b3c96f5f7397", size = 216075, upload-time = "2025-08-10T21:25:39.891Z" }, - { url = "https://files.pythonhosted.org/packages/2e/50/6b3fbab034717b4af3060bdaea6b13dfdc6b1fad44b5082e2a95cd378a9a/coverage-7.10.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:18ecc5d1b9a8c570f6c9b808fa9a2b16836b3dd5414a6d467ae942208b095f85", size = 216476, upload-time = "2025-08-10T21:25:41.137Z" }, - { url = "https://files.pythonhosted.org/packages/c7/96/4368c624c1ed92659812b63afc76c492be7867ac8e64b7190b88bb26d43c/coverage-7.10.3-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:1af4461b25fe92889590d438905e1fc79a95680ec2a1ff69a591bb3fdb6c7157", size = 246865, upload-time = "2025-08-10T21:25:42.408Z" }, - { url = "https://files.pythonhosted.org/packages/34/12/5608f76070939395c17053bf16e81fd6c06cf362a537ea9d07e281013a27/coverage-7.10.3-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:3966bc9a76b09a40dc6063c8b10375e827ea5dfcaffae402dd65953bef4cba54", size = 248800, upload-time = "2025-08-10T21:25:44.098Z" }, - { url = "https://files.pythonhosted.org/packages/ce/52/7cc90c448a0ad724283cbcdfd66b8d23a598861a6a22ac2b7b8696491798/coverage-7.10.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:205a95b87ef4eb303b7bc5118b47b6b6604a644bcbdb33c336a41cfc0a08c06a", size = 250904, upload-time = "2025-08-10T21:25:45.384Z" }, - { url = "https://files.pythonhosted.org/packages/e6/70/9967b847063c1c393b4f4d6daab1131558ebb6b51f01e7df7150aa99f11d/coverage-7.10.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:5b3801b79fb2ad61e3c7e2554bab754fc5f105626056980a2b9cf3aef4f13f84", size = 248597, upload-time = "2025-08-10T21:25:47.059Z" }, - { url = "https://files.pythonhosted.org/packages/2d/fe/263307ce6878b9ed4865af42e784b42bb82d066bcf10f68defa42931c2c7/coverage-7.10.3-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:b0dc69c60224cda33d384572da945759756e3f06b9cdac27f302f53961e63160", size = 246647, upload-time = "2025-08-10T21:25:48.334Z" }, - { url = "https://files.pythonhosted.org/packages/8e/27/d27af83ad162eba62c4eb7844a1de6cf7d9f6b185df50b0a3514a6f80ddd/coverage-7.10.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a83d4f134bab2c7ff758e6bb1541dd72b54ba295ced6a63d93efc2e20cb9b124", size = 247290, upload-time = "2025-08-10T21:25:49.945Z" }, - { url = "https://files.pythonhosted.org/packages/28/83/904ff27e15467a5622dbe9ad2ed5831b4a616a62570ec5924d06477dff5a/coverage-7.10.3-cp311-cp311-win32.whl", hash = "sha256:54e409dd64e5302b2a8fdf44ec1c26f47abd1f45a2dcf67bd161873ee05a59b8", size = 218521, upload-time = "2025-08-10T21:25:51.208Z" }, - { url = "https://files.pythonhosted.org/packages/b8/29/bc717b8902faaccf0ca486185f0dcab4778561a529dde51cb157acaafa16/coverage-7.10.3-cp311-cp311-win_amd64.whl", hash = "sha256:30c601610a9b23807c5e9e2e442054b795953ab85d525c3de1b1b27cebeb2117", size = 219412, upload-time = "2025-08-10T21:25:52.494Z" }, - { url = "https://files.pythonhosted.org/packages/7b/7a/5a1a7028c11bb589268c656c6b3f2bbf06e0aced31bbdf7a4e94e8442cc0/coverage-7.10.3-cp311-cp311-win_arm64.whl", hash = "sha256:dabe662312a97958e932dee056f2659051d822552c0b866823e8ba1c2fe64770", size = 218091, upload-time = "2025-08-10T21:25:54.102Z" }, - { url = "https://files.pythonhosted.org/packages/b8/62/13c0b66e966c43d7aa64dadc8cd2afa1f5a2bf9bb863bdabc21fb94e8b63/coverage-7.10.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:449c1e2d3a84d18bd204258a897a87bc57380072eb2aded6a5b5226046207b42", size = 216262, upload-time = "2025-08-10T21:25:55.367Z" }, - { url = "https://files.pythonhosted.org/packages/b5/f0/59fdf79be7ac2f0206fc739032f482cfd3f66b18f5248108ff192741beae/coverage-7.10.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1d4f9ce50b9261ad196dc2b2e9f1fbbee21651b54c3097a25ad783679fd18294", size = 216496, upload-time = "2025-08-10T21:25:56.759Z" }, - { url = "https://files.pythonhosted.org/packages/34/b1/bc83788ba31bde6a0c02eb96bbc14b2d1eb083ee073beda18753fa2c4c66/coverage-7.10.3-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:4dd4564207b160d0d45c36a10bc0a3d12563028e8b48cd6459ea322302a156d7", size = 247989, upload-time = "2025-08-10T21:25:58.067Z" }, - { url = "https://files.pythonhosted.org/packages/0c/29/f8bdf88357956c844bd872e87cb16748a37234f7f48c721dc7e981145eb7/coverage-7.10.3-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:5ca3c9530ee072b7cb6a6ea7b640bcdff0ad3b334ae9687e521e59f79b1d0437", size = 250738, upload-time = "2025-08-10T21:25:59.406Z" }, - { url = "https://files.pythonhosted.org/packages/ae/df/6396301d332b71e42bbe624670af9376f63f73a455cc24723656afa95796/coverage-7.10.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b6df359e59fa243c9925ae6507e27f29c46698359f45e568fd51b9315dbbe587", size = 251868, upload-time = "2025-08-10T21:26:00.65Z" }, - { url = "https://files.pythonhosted.org/packages/91/21/d760b2df6139b6ef62c9cc03afb9bcdf7d6e36ed4d078baacffa618b4c1c/coverage-7.10.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a181e4c2c896c2ff64c6312db3bda38e9ade2e1aa67f86a5628ae85873786cea", size = 249790, upload-time = "2025-08-10T21:26:02.009Z" }, - { url = "https://files.pythonhosted.org/packages/69/91/5dcaa134568202397fa4023d7066d4318dc852b53b428052cd914faa05e1/coverage-7.10.3-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:a374d4e923814e8b72b205ef6b3d3a647bb50e66f3558582eda074c976923613", size = 247907, upload-time = "2025-08-10T21:26:03.757Z" }, - { url = "https://files.pythonhosted.org/packages/38/ed/70c0e871cdfef75f27faceada461206c1cc2510c151e1ef8d60a6fedda39/coverage-7.10.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:daeefff05993e5e8c6e7499a8508e7bd94502b6b9a9159c84fd1fe6bce3151cb", size = 249344, upload-time = "2025-08-10T21:26:05.11Z" }, - { url = "https://files.pythonhosted.org/packages/5f/55/c8a273ed503cedc07f8a00dcd843daf28e849f0972e4c6be4c027f418ad6/coverage-7.10.3-cp312-cp312-win32.whl", hash = "sha256:187ecdcac21f9636d570e419773df7bd2fda2e7fa040f812e7f95d0bddf5f79a", size = 218693, upload-time = "2025-08-10T21:26:06.534Z" }, - { url = "https://files.pythonhosted.org/packages/94/58/dd3cfb2473b85be0b6eb8c5b6d80b6fc3f8f23611e69ef745cef8cf8bad5/coverage-7.10.3-cp312-cp312-win_amd64.whl", hash = "sha256:4a50ad2524ee7e4c2a95e60d2b0b83283bdfc745fe82359d567e4f15d3823eb5", size = 219501, upload-time = "2025-08-10T21:26:08.195Z" }, - { url = "https://files.pythonhosted.org/packages/56/af/7cbcbf23d46de6f24246e3f76b30df099d05636b30c53c158a196f7da3ad/coverage-7.10.3-cp312-cp312-win_arm64.whl", hash = "sha256:c112f04e075d3495fa3ed2200f71317da99608cbb2e9345bdb6de8819fc30571", size = 218135, upload-time = "2025-08-10T21:26:09.584Z" }, - { url = "https://files.pythonhosted.org/packages/0a/ff/239e4de9cc149c80e9cc359fab60592365b8c4cbfcad58b8a939d18c6898/coverage-7.10.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:b99e87304ffe0eb97c5308447328a584258951853807afdc58b16143a530518a", size = 216298, upload-time = "2025-08-10T21:26:10.973Z" }, - { url = "https://files.pythonhosted.org/packages/56/da/28717da68f8ba68f14b9f558aaa8f3e39ada8b9a1ae4f4977c8f98b286d5/coverage-7.10.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:4af09c7574d09afbc1ea7da9dcea23665c01f3bc1b1feb061dac135f98ffc53a", size = 216546, upload-time = "2025-08-10T21:26:12.616Z" }, - { url = "https://files.pythonhosted.org/packages/de/bb/e1ade16b9e3f2d6c323faeb6bee8e6c23f3a72760a5d9af102ef56a656cb/coverage-7.10.3-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:488e9b50dc5d2aa9521053cfa706209e5acf5289e81edc28291a24f4e4488f46", size = 247538, upload-time = "2025-08-10T21:26:14.455Z" }, - { url = "https://files.pythonhosted.org/packages/ea/2f/6ae1db51dc34db499bfe340e89f79a63bd115fc32513a7bacdf17d33cd86/coverage-7.10.3-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:913ceddb4289cbba3a310704a424e3fb7aac2bc0c3a23ea473193cb290cf17d4", size = 250141, upload-time = "2025-08-10T21:26:15.787Z" }, - { url = "https://files.pythonhosted.org/packages/4f/ed/33efd8819895b10c66348bf26f011dd621e804866c996ea6893d682218df/coverage-7.10.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6b1f91cbc78c7112ab84ed2a8defbccd90f888fcae40a97ddd6466b0bec6ae8a", size = 251415, upload-time = "2025-08-10T21:26:17.535Z" }, - { url = "https://files.pythonhosted.org/packages/26/04/cb83826f313d07dc743359c9914d9bc460e0798da9a0e38b4f4fabc207ed/coverage-7.10.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:b0bac054d45af7cd938834b43a9878b36ea92781bcb009eab040a5b09e9927e3", size = 249575, upload-time = "2025-08-10T21:26:18.921Z" }, - { url = "https://files.pythonhosted.org/packages/2d/fd/ae963c7a8e9581c20fa4355ab8940ca272554d8102e872dbb932a644e410/coverage-7.10.3-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:fe72cbdd12d9e0f4aca873fa6d755e103888a7f9085e4a62d282d9d5b9f7928c", size = 247466, upload-time = "2025-08-10T21:26:20.263Z" }, - { url = "https://files.pythonhosted.org/packages/99/e8/b68d1487c6af370b8d5ef223c6d7e250d952c3acfbfcdbf1a773aa0da9d2/coverage-7.10.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:c1e2e927ab3eadd7c244023927d646e4c15c65bb2ac7ae3c3e9537c013700d21", size = 249084, upload-time = "2025-08-10T21:26:21.638Z" }, - { url = "https://files.pythonhosted.org/packages/66/4d/a0bcb561645c2c1e21758d8200443669d6560d2a2fb03955291110212ec4/coverage-7.10.3-cp313-cp313-win32.whl", hash = "sha256:24d0c13de473b04920ddd6e5da3c08831b1170b8f3b17461d7429b61cad59ae0", size = 218735, upload-time = "2025-08-10T21:26:23.009Z" }, - { url = "https://files.pythonhosted.org/packages/6a/c3/78b4adddbc0feb3b223f62761e5f9b4c5a758037aaf76e0a5845e9e35e48/coverage-7.10.3-cp313-cp313-win_amd64.whl", hash = "sha256:3564aae76bce4b96e2345cf53b4c87e938c4985424a9be6a66ee902626edec4c", size = 219531, upload-time = "2025-08-10T21:26:24.474Z" }, - { url = "https://files.pythonhosted.org/packages/70/1b/1229c0b2a527fa5390db58d164aa896d513a1fbb85a1b6b6676846f00552/coverage-7.10.3-cp313-cp313-win_arm64.whl", hash = "sha256:f35580f19f297455f44afcd773c9c7a058e52eb6eb170aa31222e635f2e38b87", size = 218162, upload-time = "2025-08-10T21:26:25.847Z" }, - { url = "https://files.pythonhosted.org/packages/fc/26/1c1f450e15a3bf3eaecf053ff64538a2612a23f05b21d79ce03be9ff5903/coverage-7.10.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:07009152f497a0464ffdf2634586787aea0e69ddd023eafb23fc38267db94b84", size = 217003, upload-time = "2025-08-10T21:26:27.231Z" }, - { url = "https://files.pythonhosted.org/packages/29/96/4b40036181d8c2948454b458750960956a3c4785f26a3c29418bbbee1666/coverage-7.10.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:8dd2ba5f0c7e7e8cc418be2f0c14c4d9e3f08b8fb8e4c0f83c2fe87d03eb655e", size = 217238, upload-time = "2025-08-10T21:26:28.83Z" }, - { url = "https://files.pythonhosted.org/packages/62/23/8dfc52e95da20957293fb94d97397a100e63095ec1e0ef5c09dd8c6f591a/coverage-7.10.3-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:1ae22b97003c74186e034a93e4f946c75fad8c0ce8d92fbbc168b5e15ee2841f", size = 258561, upload-time = "2025-08-10T21:26:30.475Z" }, - { url = "https://files.pythonhosted.org/packages/59/95/00e7fcbeda3f632232f4c07dde226afe3511a7781a000aa67798feadc535/coverage-7.10.3-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:eb329f1046888a36b1dc35504d3029e1dd5afe2196d94315d18c45ee380f67d5", size = 260735, upload-time = "2025-08-10T21:26:32.333Z" }, - { url = "https://files.pythonhosted.org/packages/9e/4c/f4666cbc4571804ba2a65b078ff0de600b0b577dc245389e0bc9b69ae7ca/coverage-7.10.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ce01048199a91f07f96ca3074b0c14021f4fe7ffd29a3e6a188ac60a5c3a4af8", size = 262960, upload-time = "2025-08-10T21:26:33.701Z" }, - { url = "https://files.pythonhosted.org/packages/c1/a5/8a9e8a7b12a290ed98b60f73d1d3e5e9ced75a4c94a0d1a671ce3ddfff2a/coverage-7.10.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:08b989a06eb9dfacf96d42b7fb4c9a22bafa370d245dc22fa839f2168c6f9fa1", size = 260515, upload-time = "2025-08-10T21:26:35.16Z" }, - { url = "https://files.pythonhosted.org/packages/86/11/bb59f7f33b2cac0c5b17db0d9d0abba9c90d9eda51a6e727b43bd5fce4ae/coverage-7.10.3-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:669fe0d4e69c575c52148511029b722ba8d26e8a3129840c2ce0522e1452b256", size = 258278, upload-time = "2025-08-10T21:26:36.539Z" }, - { url = "https://files.pythonhosted.org/packages/cc/22/3646f8903743c07b3e53fded0700fed06c580a980482f04bf9536657ac17/coverage-7.10.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:3262d19092771c83f3413831d9904b1ccc5f98da5de4ffa4ad67f5b20c7aaf7b", size = 259408, upload-time = "2025-08-10T21:26:37.954Z" }, - { url = "https://files.pythonhosted.org/packages/d2/5c/6375e9d905da22ddea41cd85c30994b8b6f6c02e44e4c5744b76d16b026f/coverage-7.10.3-cp313-cp313t-win32.whl", hash = "sha256:cc0ee4b2ccd42cab7ee6be46d8a67d230cb33a0a7cd47a58b587a7063b6c6b0e", size = 219396, upload-time = "2025-08-10T21:26:39.426Z" }, - { url = "https://files.pythonhosted.org/packages/33/3b/7da37fd14412b8c8b6e73c3e7458fef6b1b05a37f990a9776f88e7740c89/coverage-7.10.3-cp313-cp313t-win_amd64.whl", hash = "sha256:03db599f213341e2960430984e04cf35fb179724e052a3ee627a068653cf4a7c", size = 220458, upload-time = "2025-08-10T21:26:40.905Z" }, - { url = "https://files.pythonhosted.org/packages/28/cc/59a9a70f17edab513c844ee7a5c63cf1057041a84cc725b46a51c6f8301b/coverage-7.10.3-cp313-cp313t-win_arm64.whl", hash = "sha256:46eae7893ba65f53c71284585a262f083ef71594f05ec5c85baf79c402369098", size = 218722, upload-time = "2025-08-10T21:26:42.362Z" }, - { url = "https://files.pythonhosted.org/packages/2d/84/bb773b51a06edbf1231b47dc810a23851f2796e913b335a0fa364773b842/coverage-7.10.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:bce8b8180912914032785850d8f3aacb25ec1810f5f54afc4a8b114e7a9b55de", size = 216280, upload-time = "2025-08-10T21:26:44.132Z" }, - { url = "https://files.pythonhosted.org/packages/92/a8/4d8ca9c111d09865f18d56facff64d5fa076a5593c290bd1cfc5dceb8dba/coverage-7.10.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:07790b4b37d56608536f7c1079bd1aa511567ac2966d33d5cec9cf520c50a7c8", size = 216557, upload-time = "2025-08-10T21:26:45.598Z" }, - { url = "https://files.pythonhosted.org/packages/fe/b2/eb668bfc5060194bc5e1ccd6f664e8e045881cfee66c42a2aa6e6c5b26e8/coverage-7.10.3-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:e79367ef2cd9166acedcbf136a458dfe9a4a2dd4d1ee95738fb2ee581c56f667", size = 247598, upload-time = "2025-08-10T21:26:47.081Z" }, - { url = "https://files.pythonhosted.org/packages/fd/b0/9faa4ac62c8822219dd83e5d0e73876398af17d7305968aed8d1606d1830/coverage-7.10.3-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:419d2a0f769f26cb1d05e9ccbc5eab4cb5d70231604d47150867c07822acbdf4", size = 250131, upload-time = "2025-08-10T21:26:48.65Z" }, - { url = "https://files.pythonhosted.org/packages/4e/90/203537e310844d4bf1bdcfab89c1e05c25025c06d8489b9e6f937ad1a9e2/coverage-7.10.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ee221cf244757cdc2ac882e3062ab414b8464ad9c884c21e878517ea64b3fa26", size = 251485, upload-time = "2025-08-10T21:26:50.368Z" }, - { url = "https://files.pythonhosted.org/packages/b9/b2/9d894b26bc53c70a1fe503d62240ce6564256d6d35600bdb86b80e516e7d/coverage-7.10.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c2079d8cdd6f7373d628e14b3357f24d1db02c9dc22e6a007418ca7a2be0435a", size = 249488, upload-time = "2025-08-10T21:26:52.045Z" }, - { url = "https://files.pythonhosted.org/packages/b4/28/af167dbac5281ba6c55c933a0ca6675d68347d5aee39cacc14d44150b922/coverage-7.10.3-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:bd8df1f83c0703fa3ca781b02d36f9ec67ad9cb725b18d486405924f5e4270bd", size = 247419, upload-time = "2025-08-10T21:26:53.533Z" }, - { url = "https://files.pythonhosted.org/packages/f4/1c/9a4ddc9f0dcb150d4cd619e1c4bb39bcf694c6129220bdd1e5895d694dda/coverage-7.10.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:6b4e25e0fa335c8aa26e42a52053f3786a61cc7622b4d54ae2dad994aa754fec", size = 248917, upload-time = "2025-08-10T21:26:55.11Z" }, - { url = "https://files.pythonhosted.org/packages/92/27/c6a60c7cbe10dbcdcd7fc9ee89d531dc04ea4c073800279bb269954c5a9f/coverage-7.10.3-cp314-cp314-win32.whl", hash = "sha256:d7c3d02c2866deb217dce664c71787f4b25420ea3eaf87056f44fb364a3528f5", size = 218999, upload-time = "2025-08-10T21:26:56.637Z" }, - { url = "https://files.pythonhosted.org/packages/36/09/a94c1369964ab31273576615d55e7d14619a1c47a662ed3e2a2fe4dee7d4/coverage-7.10.3-cp314-cp314-win_amd64.whl", hash = "sha256:9c8916d44d9e0fe6cdb2227dc6b0edd8bc6c8ef13438bbbf69af7482d9bb9833", size = 219801, upload-time = "2025-08-10T21:26:58.207Z" }, - { url = "https://files.pythonhosted.org/packages/23/59/f5cd2a80f401c01cf0f3add64a7b791b7d53fd6090a4e3e9ea52691cf3c4/coverage-7.10.3-cp314-cp314-win_arm64.whl", hash = "sha256:1007d6a2b3cf197c57105cc1ba390d9ff7f0bee215ced4dea530181e49c65ab4", size = 218381, upload-time = "2025-08-10T21:26:59.707Z" }, - { url = "https://files.pythonhosted.org/packages/73/3d/89d65baf1ea39e148ee989de6da601469ba93c1d905b17dfb0b83bd39c96/coverage-7.10.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:ebc8791d346410d096818788877d675ca55c91db87d60e8f477bd41c6970ffc6", size = 217019, upload-time = "2025-08-10T21:27:01.242Z" }, - { url = "https://files.pythonhosted.org/packages/7d/7d/d9850230cd9c999ce3a1e600f85c2fff61a81c301334d7a1faa1a5ba19c8/coverage-7.10.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1f4e4d8e75f6fd3c6940ebeed29e3d9d632e1f18f6fb65d33086d99d4d073241", size = 217237, upload-time = "2025-08-10T21:27:03.442Z" }, - { url = "https://files.pythonhosted.org/packages/36/51/b87002d417202ab27f4a1cd6bd34ee3b78f51b3ddbef51639099661da991/coverage-7.10.3-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:24581ed69f132b6225a31b0228ae4885731cddc966f8a33fe5987288bdbbbd5e", size = 258735, upload-time = "2025-08-10T21:27:05.124Z" }, - { url = "https://files.pythonhosted.org/packages/1c/02/1f8612bfcb46fc7ca64a353fff1cd4ed932bb6e0b4e0bb88b699c16794b8/coverage-7.10.3-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:ec151569ddfccbf71bac8c422dce15e176167385a00cd86e887f9a80035ce8a5", size = 260901, upload-time = "2025-08-10T21:27:06.68Z" }, - { url = "https://files.pythonhosted.org/packages/aa/3a/fe39e624ddcb2373908bd922756384bb70ac1c5009b0d1674eb326a3e428/coverage-7.10.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2ae8e7c56290b908ee817200c0b65929b8050bc28530b131fe7c6dfee3e7d86b", size = 263157, upload-time = "2025-08-10T21:27:08.398Z" }, - { url = "https://files.pythonhosted.org/packages/5e/89/496b6d5a10fa0d0691a633bb2b2bcf4f38f0bdfcbde21ad9e32d1af328ed/coverage-7.10.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:5fb742309766d7e48e9eb4dc34bc95a424707bc6140c0e7d9726e794f11b92a0", size = 260597, upload-time = "2025-08-10T21:27:10.237Z" }, - { url = "https://files.pythonhosted.org/packages/b6/a6/8b5bf6a9e8c6aaeb47d5fe9687014148efc05c3588110246d5fdeef9b492/coverage-7.10.3-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:c65e2a5b32fbe1e499f1036efa6eb9cb4ea2bf6f7168d0e7a5852f3024f471b1", size = 258353, upload-time = "2025-08-10T21:27:11.773Z" }, - { url = "https://files.pythonhosted.org/packages/c3/6d/ad131be74f8afd28150a07565dfbdc86592fd61d97e2dc83383d9af219f0/coverage-7.10.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:d48d2cb07d50f12f4f18d2bb75d9d19e3506c26d96fffabf56d22936e5ed8f7c", size = 259504, upload-time = "2025-08-10T21:27:13.254Z" }, - { url = "https://files.pythonhosted.org/packages/ec/30/fc9b5097092758cba3375a8cc4ff61774f8cd733bcfb6c9d21a60077a8d8/coverage-7.10.3-cp314-cp314t-win32.whl", hash = "sha256:dec0d9bc15ee305e09fe2cd1911d3f0371262d3cfdae05d79515d8cb712b4869", size = 219782, upload-time = "2025-08-10T21:27:14.736Z" }, - { url = "https://files.pythonhosted.org/packages/72/9b/27fbf79451b1fac15c4bda6ec6e9deae27cf7c0648c1305aa21a3454f5c4/coverage-7.10.3-cp314-cp314t-win_amd64.whl", hash = "sha256:424ea93a323aa0f7f01174308ea78bde885c3089ec1bef7143a6d93c3e24ef64", size = 220898, upload-time = "2025-08-10T21:27:16.297Z" }, - { url = "https://files.pythonhosted.org/packages/d1/cf/a32bbf92869cbf0b7c8b84325327bfc718ad4b6d2c63374fef3d58e39306/coverage-7.10.3-cp314-cp314t-win_arm64.whl", hash = "sha256:f5983c132a62d93d71c9ef896a0b9bf6e6828d8d2ea32611f58684fba60bba35", size = 218922, upload-time = "2025-08-10T21:27:18.22Z" }, - { url = "https://files.pythonhosted.org/packages/84/19/e67f4ae24e232c7f713337f3f4f7c9c58afd0c02866fb07c7b9255a19ed7/coverage-7.10.3-py3-none-any.whl", hash = "sha256:416a8d74dc0adfd33944ba2f405897bab87b7e9e84a391e09d241956bd953ce1", size = 207921, upload-time = "2025-08-10T21:27:38.254Z" }, +version = "7.10.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/14/70/025b179c993f019105b79575ac6edb5e084fb0f0e63f15cdebef4e454fb5/coverage-7.10.6.tar.gz", hash = "sha256:f644a3ae5933a552a29dbb9aa2f90c677a875f80ebea028e5a52a4f429044b90", size = 823736, upload-time = "2025-08-29T15:35:16.668Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d4/16/2bea27e212c4980753d6d563a0803c150edeaaddb0771a50d2afc410a261/coverage-7.10.6-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c706db3cabb7ceef779de68270150665e710b46d56372455cd741184f3868d8f", size = 217129, upload-time = "2025-08-29T15:33:13.575Z" }, + { url = "https://files.pythonhosted.org/packages/2a/51/e7159e068831ab37e31aac0969d47b8c5ee25b7d307b51e310ec34869315/coverage-7.10.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8e0c38dc289e0508ef68ec95834cb5d2e96fdbe792eaccaa1bccac3966bbadcc", size = 217532, upload-time = "2025-08-29T15:33:14.872Z" }, + { url = "https://files.pythonhosted.org/packages/e7/c0/246ccbea53d6099325d25cd208df94ea435cd55f0db38099dd721efc7a1f/coverage-7.10.6-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:752a3005a1ded28f2f3a6e8787e24f28d6abe176ca64677bcd8d53d6fe2ec08a", size = 247931, upload-time = "2025-08-29T15:33:16.142Z" }, + { url = "https://files.pythonhosted.org/packages/7d/fb/7435ef8ab9b2594a6e3f58505cc30e98ae8b33265d844007737946c59389/coverage-7.10.6-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:689920ecfd60f992cafca4f5477d55720466ad2c7fa29bb56ac8d44a1ac2b47a", size = 249864, upload-time = "2025-08-29T15:33:17.434Z" }, + { url = "https://files.pythonhosted.org/packages/51/f8/d9d64e8da7bcddb094d511154824038833c81e3a039020a9d6539bf303e9/coverage-7.10.6-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ec98435796d2624d6905820a42f82149ee9fc4f2d45c2c5bc5a44481cc50db62", size = 251969, upload-time = "2025-08-29T15:33:18.822Z" }, + { url = "https://files.pythonhosted.org/packages/43/28/c43ba0ef19f446d6463c751315140d8f2a521e04c3e79e5c5fe211bfa430/coverage-7.10.6-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:b37201ce4a458c7a758ecc4efa92fa8ed783c66e0fa3c42ae19fc454a0792153", size = 249659, upload-time = "2025-08-29T15:33:20.407Z" }, + { url = "https://files.pythonhosted.org/packages/79/3e/53635bd0b72beaacf265784508a0b386defc9ab7fad99ff95f79ce9db555/coverage-7.10.6-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:2904271c80898663c810a6b067920a61dd8d38341244a3605bd31ab55250dad5", size = 247714, upload-time = "2025-08-29T15:33:21.751Z" }, + { url = "https://files.pythonhosted.org/packages/4c/55/0964aa87126624e8c159e32b0bc4e84edef78c89a1a4b924d28dd8265625/coverage-7.10.6-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:5aea98383463d6e1fa4e95416d8de66f2d0cb588774ee20ae1b28df826bcb619", size = 248351, upload-time = "2025-08-29T15:33:23.105Z" }, + { url = "https://files.pythonhosted.org/packages/eb/ab/6cfa9dc518c6c8e14a691c54e53a9433ba67336c760607e299bfcf520cb1/coverage-7.10.6-cp311-cp311-win32.whl", hash = "sha256:e3fb1fa01d3598002777dd259c0c2e6d9d5e10e7222976fc8e03992f972a2cba", size = 219562, upload-time = "2025-08-29T15:33:24.717Z" }, + { url = "https://files.pythonhosted.org/packages/5b/18/99b25346690cbc55922e7cfef06d755d4abee803ef335baff0014268eff4/coverage-7.10.6-cp311-cp311-win_amd64.whl", hash = "sha256:f35ed9d945bece26553d5b4c8630453169672bea0050a564456eb88bdffd927e", size = 220453, upload-time = "2025-08-29T15:33:26.482Z" }, + { url = "https://files.pythonhosted.org/packages/d8/ed/81d86648a07ccb124a5cf1f1a7788712b8d7216b593562683cd5c9b0d2c1/coverage-7.10.6-cp311-cp311-win_arm64.whl", hash = "sha256:99e1a305c7765631d74b98bf7dbf54eeea931f975e80f115437d23848ee8c27c", size = 219127, upload-time = "2025-08-29T15:33:27.777Z" }, + { url = "https://files.pythonhosted.org/packages/26/06/263f3305c97ad78aab066d116b52250dd316e74fcc20c197b61e07eb391a/coverage-7.10.6-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:5b2dd6059938063a2c9fee1af729d4f2af28fd1a545e9b7652861f0d752ebcea", size = 217324, upload-time = "2025-08-29T15:33:29.06Z" }, + { url = "https://files.pythonhosted.org/packages/e9/60/1e1ded9a4fe80d843d7d53b3e395c1db3ff32d6c301e501f393b2e6c1c1f/coverage-7.10.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:388d80e56191bf846c485c14ae2bc8898aa3124d9d35903fef7d907780477634", size = 217560, upload-time = "2025-08-29T15:33:30.748Z" }, + { url = "https://files.pythonhosted.org/packages/b8/25/52136173c14e26dfed8b106ed725811bb53c30b896d04d28d74cb64318b3/coverage-7.10.6-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:90cb5b1a4670662719591aa92d0095bb41714970c0b065b02a2610172dbf0af6", size = 249053, upload-time = "2025-08-29T15:33:32.041Z" }, + { url = "https://files.pythonhosted.org/packages/cb/1d/ae25a7dc58fcce8b172d42ffe5313fc267afe61c97fa872b80ee72d9515a/coverage-7.10.6-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:961834e2f2b863a0e14260a9a273aff07ff7818ab6e66d2addf5628590c628f9", size = 251802, upload-time = "2025-08-29T15:33:33.625Z" }, + { url = "https://files.pythonhosted.org/packages/f5/7a/1f561d47743710fe996957ed7c124b421320f150f1d38523d8d9102d3e2a/coverage-7.10.6-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bf9a19f5012dab774628491659646335b1928cfc931bf8d97b0d5918dd58033c", size = 252935, upload-time = "2025-08-29T15:33:34.909Z" }, + { url = "https://files.pythonhosted.org/packages/6c/ad/8b97cd5d28aecdfde792dcbf646bac141167a5cacae2cd775998b45fabb5/coverage-7.10.6-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:99c4283e2a0e147b9c9cc6bc9c96124de9419d6044837e9799763a0e29a7321a", size = 250855, upload-time = "2025-08-29T15:33:36.922Z" }, + { url = "https://files.pythonhosted.org/packages/33/6a/95c32b558d9a61858ff9d79580d3877df3eb5bc9eed0941b1f187c89e143/coverage-7.10.6-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:282b1b20f45df57cc508c1e033403f02283adfb67d4c9c35a90281d81e5c52c5", size = 248974, upload-time = "2025-08-29T15:33:38.175Z" }, + { url = "https://files.pythonhosted.org/packages/0d/9c/8ce95dee640a38e760d5b747c10913e7a06554704d60b41e73fdea6a1ffd/coverage-7.10.6-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:8cdbe264f11afd69841bd8c0d83ca10b5b32853263ee62e6ac6a0ab63895f972", size = 250409, upload-time = "2025-08-29T15:33:39.447Z" }, + { url = "https://files.pythonhosted.org/packages/04/12/7a55b0bdde78a98e2eb2356771fd2dcddb96579e8342bb52aa5bc52e96f0/coverage-7.10.6-cp312-cp312-win32.whl", hash = "sha256:a517feaf3a0a3eca1ee985d8373135cfdedfbba3882a5eab4362bda7c7cf518d", size = 219724, upload-time = "2025-08-29T15:33:41.172Z" }, + { url = "https://files.pythonhosted.org/packages/36/4a/32b185b8b8e327802c9efce3d3108d2fe2d9d31f153a0f7ecfd59c773705/coverage-7.10.6-cp312-cp312-win_amd64.whl", hash = "sha256:856986eadf41f52b214176d894a7de05331117f6035a28ac0016c0f63d887629", size = 220536, upload-time = "2025-08-29T15:33:42.524Z" }, + { url = "https://files.pythonhosted.org/packages/08/3a/d5d8dc703e4998038c3099eaf77adddb00536a3cec08c8dcd556a36a3eb4/coverage-7.10.6-cp312-cp312-win_arm64.whl", hash = "sha256:acf36b8268785aad739443fa2780c16260ee3fa09d12b3a70f772ef100939d80", size = 219171, upload-time = "2025-08-29T15:33:43.974Z" }, + { url = "https://files.pythonhosted.org/packages/bd/e7/917e5953ea29a28c1057729c1d5af9084ab6d9c66217523fd0e10f14d8f6/coverage-7.10.6-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ffea0575345e9ee0144dfe5701aa17f3ba546f8c3bb48db62ae101afb740e7d6", size = 217351, upload-time = "2025-08-29T15:33:45.438Z" }, + { url = "https://files.pythonhosted.org/packages/eb/86/2e161b93a4f11d0ea93f9bebb6a53f113d5d6e416d7561ca41bb0a29996b/coverage-7.10.6-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:95d91d7317cde40a1c249d6b7382750b7e6d86fad9d8eaf4fa3f8f44cf171e80", size = 217600, upload-time = "2025-08-29T15:33:47.269Z" }, + { url = "https://files.pythonhosted.org/packages/0e/66/d03348fdd8df262b3a7fb4ee5727e6e4936e39e2f3a842e803196946f200/coverage-7.10.6-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:3e23dd5408fe71a356b41baa82892772a4cefcf758f2ca3383d2aa39e1b7a003", size = 248600, upload-time = "2025-08-29T15:33:48.953Z" }, + { url = "https://files.pythonhosted.org/packages/73/dd/508420fb47d09d904d962f123221bc249f64b5e56aa93d5f5f7603be475f/coverage-7.10.6-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:0f3f56e4cb573755e96a16501a98bf211f100463d70275759e73f3cbc00d4f27", size = 251206, upload-time = "2025-08-29T15:33:50.697Z" }, + { url = "https://files.pythonhosted.org/packages/e9/1f/9020135734184f439da85c70ea78194c2730e56c2d18aee6e8ff1719d50d/coverage-7.10.6-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:db4a1d897bbbe7339946ffa2fe60c10cc81c43fab8b062d3fcb84188688174a4", size = 252478, upload-time = "2025-08-29T15:33:52.303Z" }, + { url = "https://files.pythonhosted.org/packages/a4/a4/3d228f3942bb5a2051fde28c136eea23a761177dc4ff4ef54533164ce255/coverage-7.10.6-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d8fd7879082953c156d5b13c74aa6cca37f6a6f4747b39538504c3f9c63d043d", size = 250637, upload-time = "2025-08-29T15:33:53.67Z" }, + { url = "https://files.pythonhosted.org/packages/36/e3/293dce8cdb9a83de971637afc59b7190faad60603b40e32635cbd15fbf61/coverage-7.10.6-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:28395ca3f71cd103b8c116333fa9db867f3a3e1ad6a084aa3725ae002b6583bc", size = 248529, upload-time = "2025-08-29T15:33:55.022Z" }, + { url = "https://files.pythonhosted.org/packages/90/26/64eecfa214e80dd1d101e420cab2901827de0e49631d666543d0e53cf597/coverage-7.10.6-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:61c950fc33d29c91b9e18540e1aed7d9f6787cc870a3e4032493bbbe641d12fc", size = 250143, upload-time = "2025-08-29T15:33:56.386Z" }, + { url = "https://files.pythonhosted.org/packages/3e/70/bd80588338f65ea5b0d97e424b820fb4068b9cfb9597fbd91963086e004b/coverage-7.10.6-cp313-cp313-win32.whl", hash = "sha256:160c00a5e6b6bdf4e5984b0ef21fc860bc94416c41b7df4d63f536d17c38902e", size = 219770, upload-time = "2025-08-29T15:33:58.063Z" }, + { url = "https://files.pythonhosted.org/packages/a7/14/0b831122305abcc1060c008f6c97bbdc0a913ab47d65070a01dc50293c2b/coverage-7.10.6-cp313-cp313-win_amd64.whl", hash = "sha256:628055297f3e2aa181464c3808402887643405573eb3d9de060d81531fa79d32", size = 220566, upload-time = "2025-08-29T15:33:59.766Z" }, + { url = "https://files.pythonhosted.org/packages/83/c6/81a83778c1f83f1a4a168ed6673eeedc205afb562d8500175292ca64b94e/coverage-7.10.6-cp313-cp313-win_arm64.whl", hash = "sha256:df4ec1f8540b0bcbe26ca7dd0f541847cc8a108b35596f9f91f59f0c060bfdd2", size = 219195, upload-time = "2025-08-29T15:34:01.191Z" }, + { url = "https://files.pythonhosted.org/packages/d7/1c/ccccf4bf116f9517275fa85047495515add43e41dfe8e0bef6e333c6b344/coverage-7.10.6-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:c9a8b7a34a4de3ed987f636f71881cd3b8339f61118b1aa311fbda12741bff0b", size = 218059, upload-time = "2025-08-29T15:34:02.91Z" }, + { url = "https://files.pythonhosted.org/packages/92/97/8a3ceff833d27c7492af4f39d5da6761e9ff624831db9e9f25b3886ddbca/coverage-7.10.6-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:8dd5af36092430c2b075cee966719898f2ae87b636cefb85a653f1d0ba5d5393", size = 218287, upload-time = "2025-08-29T15:34:05.106Z" }, + { url = "https://files.pythonhosted.org/packages/92/d8/50b4a32580cf41ff0423777a2791aaf3269ab60c840b62009aec12d3970d/coverage-7.10.6-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:b0353b0f0850d49ada66fdd7d0c7cdb0f86b900bb9e367024fd14a60cecc1e27", size = 259625, upload-time = "2025-08-29T15:34:06.575Z" }, + { url = "https://files.pythonhosted.org/packages/7e/7e/6a7df5a6fb440a0179d94a348eb6616ed4745e7df26bf2a02bc4db72c421/coverage-7.10.6-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:d6b9ae13d5d3e8aeca9ca94198aa7b3ebbc5acfada557d724f2a1f03d2c0b0df", size = 261801, upload-time = "2025-08-29T15:34:08.006Z" }, + { url = "https://files.pythonhosted.org/packages/3a/4c/a270a414f4ed5d196b9d3d67922968e768cd971d1b251e1b4f75e9362f75/coverage-7.10.6-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:675824a363cc05781b1527b39dc2587b8984965834a748177ee3c37b64ffeafb", size = 264027, upload-time = "2025-08-29T15:34:09.806Z" }, + { url = "https://files.pythonhosted.org/packages/9c/8b/3210d663d594926c12f373c5370bf1e7c5c3a427519a8afa65b561b9a55c/coverage-7.10.6-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:692d70ea725f471a547c305f0d0fc6a73480c62fb0da726370c088ab21aed282", size = 261576, upload-time = "2025-08-29T15:34:11.585Z" }, + { url = "https://files.pythonhosted.org/packages/72/d0/e1961eff67e9e1dba3fc5eb7a4caf726b35a5b03776892da8d79ec895775/coverage-7.10.6-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:851430a9a361c7a8484a36126d1d0ff8d529d97385eacc8dfdc9bfc8c2d2cbe4", size = 259341, upload-time = "2025-08-29T15:34:13.159Z" }, + { url = "https://files.pythonhosted.org/packages/3a/06/d6478d152cd189b33eac691cba27a40704990ba95de49771285f34a5861e/coverage-7.10.6-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:d9369a23186d189b2fc95cc08b8160ba242057e887d766864f7adf3c46b2df21", size = 260468, upload-time = "2025-08-29T15:34:14.571Z" }, + { url = "https://files.pythonhosted.org/packages/ed/73/737440247c914a332f0b47f7598535b29965bf305e19bbc22d4c39615d2b/coverage-7.10.6-cp313-cp313t-win32.whl", hash = "sha256:92be86fcb125e9bda0da7806afd29a3fd33fdf58fba5d60318399adf40bf37d0", size = 220429, upload-time = "2025-08-29T15:34:16.394Z" }, + { url = "https://files.pythonhosted.org/packages/bd/76/b92d3214740f2357ef4a27c75a526eb6c28f79c402e9f20a922c295c05e2/coverage-7.10.6-cp313-cp313t-win_amd64.whl", hash = "sha256:6b3039e2ca459a70c79523d39347d83b73f2f06af5624905eba7ec34d64d80b5", size = 221493, upload-time = "2025-08-29T15:34:17.835Z" }, + { url = "https://files.pythonhosted.org/packages/fc/8e/6dcb29c599c8a1f654ec6cb68d76644fe635513af16e932d2d4ad1e5ac6e/coverage-7.10.6-cp313-cp313t-win_arm64.whl", hash = "sha256:3fb99d0786fe17b228eab663d16bee2288e8724d26a199c29325aac4b0319b9b", size = 219757, upload-time = "2025-08-29T15:34:19.248Z" }, + { url = "https://files.pythonhosted.org/packages/d3/aa/76cf0b5ec00619ef208da4689281d48b57f2c7fde883d14bf9441b74d59f/coverage-7.10.6-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:6008a021907be8c4c02f37cdc3ffb258493bdebfeaf9a839f9e71dfdc47b018e", size = 217331, upload-time = "2025-08-29T15:34:20.846Z" }, + { url = "https://files.pythonhosted.org/packages/65/91/8e41b8c7c505d398d7730206f3cbb4a875a35ca1041efc518051bfce0f6b/coverage-7.10.6-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:5e75e37f23eb144e78940b40395b42f2321951206a4f50e23cfd6e8a198d3ceb", size = 217607, upload-time = "2025-08-29T15:34:22.433Z" }, + { url = "https://files.pythonhosted.org/packages/87/7f/f718e732a423d442e6616580a951b8d1ec3575ea48bcd0e2228386805e79/coverage-7.10.6-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:0f7cb359a448e043c576f0da00aa8bfd796a01b06aa610ca453d4dde09cc1034", size = 248663, upload-time = "2025-08-29T15:34:24.425Z" }, + { url = "https://files.pythonhosted.org/packages/e6/52/c1106120e6d801ac03e12b5285e971e758e925b6f82ee9b86db3aa10045d/coverage-7.10.6-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:c68018e4fc4e14b5668f1353b41ccf4bc83ba355f0e1b3836861c6f042d89ac1", size = 251197, upload-time = "2025-08-29T15:34:25.906Z" }, + { url = "https://files.pythonhosted.org/packages/3d/ec/3a8645b1bb40e36acde9c0609f08942852a4af91a937fe2c129a38f2d3f5/coverage-7.10.6-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cd4b2b0707fc55afa160cd5fc33b27ccbf75ca11d81f4ec9863d5793fc6df56a", size = 252551, upload-time = "2025-08-29T15:34:27.337Z" }, + { url = "https://files.pythonhosted.org/packages/a1/70/09ecb68eeb1155b28a1d16525fd3a9b65fbe75337311a99830df935d62b6/coverage-7.10.6-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:4cec13817a651f8804a86e4f79d815b3b28472c910e099e4d5a0e8a3b6a1d4cb", size = 250553, upload-time = "2025-08-29T15:34:29.065Z" }, + { url = "https://files.pythonhosted.org/packages/c6/80/47df374b893fa812e953b5bc93dcb1427a7b3d7a1a7d2db33043d17f74b9/coverage-7.10.6-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:f2a6a8e06bbda06f78739f40bfb56c45d14eb8249d0f0ea6d4b3d48e1f7c695d", size = 248486, upload-time = "2025-08-29T15:34:30.897Z" }, + { url = "https://files.pythonhosted.org/packages/4a/65/9f98640979ecee1b0d1a7164b589de720ddf8100d1747d9bbdb84be0c0fb/coverage-7.10.6-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:081b98395ced0d9bcf60ada7661a0b75f36b78b9d7e39ea0790bb4ed8da14747", size = 249981, upload-time = "2025-08-29T15:34:32.365Z" }, + { url = "https://files.pythonhosted.org/packages/1f/55/eeb6603371e6629037f47bd25bef300387257ed53a3c5fdb159b7ac8c651/coverage-7.10.6-cp314-cp314-win32.whl", hash = "sha256:6937347c5d7d069ee776b2bf4e1212f912a9f1f141a429c475e6089462fcecc5", size = 220054, upload-time = "2025-08-29T15:34:34.124Z" }, + { url = "https://files.pythonhosted.org/packages/15/d1/a0912b7611bc35412e919a2cd59ae98e7ea3b475e562668040a43fb27897/coverage-7.10.6-cp314-cp314-win_amd64.whl", hash = "sha256:adec1d980fa07e60b6ef865f9e5410ba760e4e1d26f60f7e5772c73b9a5b0713", size = 220851, upload-time = "2025-08-29T15:34:35.651Z" }, + { url = "https://files.pythonhosted.org/packages/ef/2d/11880bb8ef80a45338e0b3e0725e4c2d73ffbb4822c29d987078224fd6a5/coverage-7.10.6-cp314-cp314-win_arm64.whl", hash = "sha256:a80f7aef9535442bdcf562e5a0d5a5538ce8abe6bb209cfbf170c462ac2c2a32", size = 219429, upload-time = "2025-08-29T15:34:37.16Z" }, + { url = "https://files.pythonhosted.org/packages/83/c0/1f00caad775c03a700146f55536ecd097a881ff08d310a58b353a1421be0/coverage-7.10.6-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:0de434f4fbbe5af4fa7989521c655c8c779afb61c53ab561b64dcee6149e4c65", size = 218080, upload-time = "2025-08-29T15:34:38.919Z" }, + { url = "https://files.pythonhosted.org/packages/a9/c4/b1c5d2bd7cc412cbeb035e257fd06ed4e3e139ac871d16a07434e145d18d/coverage-7.10.6-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:6e31b8155150c57e5ac43ccd289d079eb3f825187d7c66e755a055d2c85794c6", size = 218293, upload-time = "2025-08-29T15:34:40.425Z" }, + { url = "https://files.pythonhosted.org/packages/3f/07/4468d37c94724bf6ec354e4ec2f205fda194343e3e85fd2e59cec57e6a54/coverage-7.10.6-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:98cede73eb83c31e2118ae8d379c12e3e42736903a8afcca92a7218e1f2903b0", size = 259800, upload-time = "2025-08-29T15:34:41.996Z" }, + { url = "https://files.pythonhosted.org/packages/82/d8/f8fb351be5fee31690cd8da768fd62f1cfab33c31d9f7baba6cd8960f6b8/coverage-7.10.6-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:f863c08f4ff6b64fa8045b1e3da480f5374779ef187f07b82e0538c68cb4ff8e", size = 261965, upload-time = "2025-08-29T15:34:43.61Z" }, + { url = "https://files.pythonhosted.org/packages/e8/70/65d4d7cfc75c5c6eb2fed3ee5cdf420fd8ae09c4808723a89a81d5b1b9c3/coverage-7.10.6-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2b38261034fda87be356f2c3f42221fdb4171c3ce7658066ae449241485390d5", size = 264220, upload-time = "2025-08-29T15:34:45.387Z" }, + { url = "https://files.pythonhosted.org/packages/98/3c/069df106d19024324cde10e4ec379fe2fb978017d25e97ebee23002fbadf/coverage-7.10.6-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:0e93b1476b79eae849dc3872faeb0bf7948fd9ea34869590bc16a2a00b9c82a7", size = 261660, upload-time = "2025-08-29T15:34:47.288Z" }, + { url = "https://files.pythonhosted.org/packages/fc/8a/2974d53904080c5dc91af798b3a54a4ccb99a45595cc0dcec6eb9616a57d/coverage-7.10.6-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:ff8a991f70f4c0cf53088abf1e3886edcc87d53004c7bb94e78650b4d3dac3b5", size = 259417, upload-time = "2025-08-29T15:34:48.779Z" }, + { url = "https://files.pythonhosted.org/packages/30/38/9616a6b49c686394b318974d7f6e08f38b8af2270ce7488e879888d1e5db/coverage-7.10.6-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:ac765b026c9f33044419cbba1da913cfb82cca1b60598ac1c7a5ed6aac4621a0", size = 260567, upload-time = "2025-08-29T15:34:50.718Z" }, + { url = "https://files.pythonhosted.org/packages/76/16/3ed2d6312b371a8cf804abf4e14895b70e4c3491c6e53536d63fd0958a8d/coverage-7.10.6-cp314-cp314t-win32.whl", hash = "sha256:441c357d55f4936875636ef2cfb3bee36e466dcf50df9afbd398ce79dba1ebb7", size = 220831, upload-time = "2025-08-29T15:34:52.653Z" }, + { url = "https://files.pythonhosted.org/packages/d5/e5/d38d0cb830abede2adb8b147770d2a3d0e7fecc7228245b9b1ae6c24930a/coverage-7.10.6-cp314-cp314t-win_amd64.whl", hash = "sha256:073711de3181b2e204e4870ac83a7c4853115b42e9cd4d145f2231e12d670930", size = 221950, upload-time = "2025-08-29T15:34:54.212Z" }, + { url = "https://files.pythonhosted.org/packages/f4/51/e48e550f6279349895b0ffcd6d2a690e3131ba3a7f4eafccc141966d4dea/coverage-7.10.6-cp314-cp314t-win_arm64.whl", hash = "sha256:137921f2bac5559334ba66122b753db6dc5d1cf01eb7b64eb412bb0d064ef35b", size = 219969, upload-time = "2025-08-29T15:34:55.83Z" }, + { url = "https://files.pythonhosted.org/packages/44/0c/50db5379b615854b5cf89146f8f5bd1d5a9693d7f3a987e269693521c404/coverage-7.10.6-py3-none-any.whl", hash = "sha256:92c4ecf6bf11b2e85fd4d8204814dc26e6a19f0c9d938c207c5cb0eadfcabbe3", size = 208986, upload-time = "2025-08-29T15:35:14.506Z" }, ] [package.optional-dependencies] @@ -553,62 +553,78 @@ wheels = [ [[package]] name = "executing" -version = "2.2.0" +version = "2.2.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/91/50/a9d80c47ff289c611ff12e63f7c5d13942c65d68125160cefd768c73e6e4/executing-2.2.0.tar.gz", hash = "sha256:5d108c028108fe2551d1a7b2e8b713341e2cb4fc0aa7dcf966fa4327a5226755", size = 978693, upload-time = "2025-01-22T15:41:29.403Z" } +sdist = { url = "https://files.pythonhosted.org/packages/cc/28/c14e053b6762b1044f34a13aab6859bbf40456d37d23aa286ac24cfd9a5d/executing-2.2.1.tar.gz", hash = "sha256:3632cc370565f6648cc328b32435bd120a1e4ebb20c77e3fdde9a13cd1e533c4", size = 1129488, upload-time = "2025-09-01T09:48:10.866Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/7b/8f/c4d9bafc34ad7ad5d8dc16dd1347ee0e507a52c3adb6bfa8887e1c6a26ba/executing-2.2.0-py2.py3-none-any.whl", hash = "sha256:11387150cad388d62750327a53d3339fad4888b39a6fe233c3afbb54ecffd3aa", size = 26702, upload-time = "2025-01-22T15:41:25.929Z" }, + { url = "https://files.pythonhosted.org/packages/c1/ea/53f2148663b321f21b5a606bd5f191517cf40b7072c0497d3c92c4a13b1e/executing-2.2.1-py2.py3-none-any.whl", hash = "sha256:760643d3452b4d777d295bb167ccc74c64a81df23fb5e08eff250c425a4b2017", size = 28317, upload-time = "2025-09-01T09:48:08.5Z" }, ] [[package]] name = "fastjsonschema" -version = "2.21.1" +version = "2.21.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/8b/50/4b769ce1ac4071a1ef6d86b1a3fb56cdc3a37615e8c5519e1af96cdac366/fastjsonschema-2.21.1.tar.gz", hash = "sha256:794d4f0a58f848961ba16af7b9c85a3e88cd360df008c59aac6fc5ae9323b5d4", size = 373939, upload-time = "2024-12-02T10:55:15.133Z" } +sdist = { url = "https://files.pythonhosted.org/packages/20/b5/23b216d9d985a956623b6bd12d4086b60f0059b27799f23016af04a74ea1/fastjsonschema-2.21.2.tar.gz", hash = "sha256:b1eb43748041c880796cd077f1a07c3d94e93ae84bba5ed36800a33554ae05de", size = 374130, upload-time = "2025-08-14T18:49:36.666Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/90/2b/0817a2b257fe88725c25589d89aec060581aabf668707a8d03b2e9e0cb2a/fastjsonschema-2.21.1-py3-none-any.whl", hash = "sha256:c9e5b7e908310918cf494a434eeb31384dd84a98b57a30bcb1f535015b554667", size = 23924, upload-time = "2024-12-02T10:55:07.599Z" }, + { url = "https://files.pythonhosted.org/packages/cb/a8/20d0723294217e47de6d9e2e40fd4a9d2f7c4b6ef974babd482a59743694/fastjsonschema-2.21.2-py3-none-any.whl", hash = "sha256:1c797122d0a86c5cace2e54bf4e819c36223b552017172f32c5c024a6b77e463", size = 24024, upload-time = "2025-08-14T18:49:34.776Z" }, ] [[package]] name = "filelock" -version = "3.18.0" +version = "3.19.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/0a/10/c23352565a6544bdc5353e0b15fc1c563352101f30e24bf500207a54df9a/filelock-3.18.0.tar.gz", hash = "sha256:adbc88eabb99d2fec8c9c1b229b171f18afa655400173ddc653d5d01501fb9f2", size = 18075, upload-time = "2025-03-14T07:11:40.47Z" } +sdist = { url = "https://files.pythonhosted.org/packages/40/bb/0ab3e58d22305b6f5440629d20683af28959bf793d98d11950e305c1c326/filelock-3.19.1.tar.gz", hash = "sha256:66eda1888b0171c998b35be2bcc0f6d75c388a7ce20c3f3f37aa8e96c2dddf58", size = 17687, upload-time = "2025-08-14T16:56:03.016Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/4d/36/2a115987e2d8c300a974597416d9de88f2444426de9571f4b59b2cca3acc/filelock-3.18.0-py3-none-any.whl", hash = "sha256:c401f4f8377c4464e6db25fff06205fd89bdd83b65eb0488ed1b160f780e21de", size = 16215, upload-time = "2025-03-14T07:11:39.145Z" }, + { url = "https://files.pythonhosted.org/packages/42/14/42b2651a2f46b022ccd948bca9f2d5af0fd8929c4eec235b8d6d844fbe67/filelock-3.19.1-py3-none-any.whl", hash = "sha256:d38e30481def20772f5baf097c122c3babc4fcdb7e14e57049eb9d88c6dc017d", size = 15988, upload-time = "2025-08-14T16:56:01.633Z" }, ] [[package]] name = "fonttools" -version = "4.59.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/8a/27/ec3c723bfdf86f34c5c82bf6305df3e0f0d8ea798d2d3a7cb0c0a866d286/fonttools-4.59.0.tar.gz", hash = "sha256:be392ec3529e2f57faa28709d60723a763904f71a2b63aabe14fee6648fe3b14", size = 3532521, upload-time = "2025-07-16T12:04:54.613Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/06/96/520733d9602fa1bf6592e5354c6721ac6fc9ea72bc98d112d0c38b967199/fonttools-4.59.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:841b2186adce48903c0fef235421ae21549020eca942c1da773ac380b056ab3c", size = 2782387, upload-time = "2025-07-16T12:03:51.424Z" }, - { url = "https://files.pythonhosted.org/packages/87/6a/170fce30b9bce69077d8eec9bea2cfd9f7995e8911c71be905e2eba6368b/fonttools-4.59.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:9bcc1e77fbd1609198966ded6b2a9897bd6c6bcbd2287a2fc7d75f1a254179c5", size = 2342194, upload-time = "2025-07-16T12:03:53.295Z" }, - { url = "https://files.pythonhosted.org/packages/b0/b6/7c8166c0066856f1408092f7968ac744060cf72ca53aec9036106f57eeca/fonttools-4.59.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:37c377f7cb2ab2eca8a0b319c68146d34a339792f9420fca6cd49cf28d370705", size = 5032333, upload-time = "2025-07-16T12:03:55.177Z" }, - { url = "https://files.pythonhosted.org/packages/eb/0c/707c5a19598eafcafd489b73c4cb1c142102d6197e872f531512d084aa76/fonttools-4.59.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:fa39475eaccb98f9199eccfda4298abaf35ae0caec676ffc25b3a5e224044464", size = 4974422, upload-time = "2025-07-16T12:03:57.406Z" }, - { url = "https://files.pythonhosted.org/packages/f6/e7/6d33737d9fe632a0f59289b6f9743a86d2a9d0673de2a0c38c0f54729822/fonttools-4.59.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d3972b13148c1d1fbc092b27678a33b3080d1ac0ca305742b0119b75f9e87e38", size = 5010631, upload-time = "2025-07-16T12:03:59.449Z" }, - { url = "https://files.pythonhosted.org/packages/63/e1/a4c3d089ab034a578820c8f2dff21ef60daf9668034a1e4fb38bb1cc3398/fonttools-4.59.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a408c3c51358c89b29cfa5317cf11518b7ce5de1717abb55c5ae2d2921027de6", size = 5122198, upload-time = "2025-07-16T12:04:01.542Z" }, - { url = "https://files.pythonhosted.org/packages/09/77/ca82b9c12fa4de3c520b7760ee61787640cf3fde55ef1b0bfe1de38c8153/fonttools-4.59.0-cp311-cp311-win32.whl", hash = "sha256:6770d7da00f358183d8fd5c4615436189e4f683bdb6affb02cad3d221d7bb757", size = 2214216, upload-time = "2025-07-16T12:04:03.515Z" }, - { url = "https://files.pythonhosted.org/packages/ab/25/5aa7ca24b560b2f00f260acf32c4cf29d7aaf8656e159a336111c18bc345/fonttools-4.59.0-cp311-cp311-win_amd64.whl", hash = "sha256:84fc186980231a287b28560d3123bd255d3c6b6659828c642b4cf961e2b923d0", size = 2261879, upload-time = "2025-07-16T12:04:05.015Z" }, - { url = "https://files.pythonhosted.org/packages/e2/77/b1c8af22f4265e951cd2e5535dbef8859efcef4fb8dee742d368c967cddb/fonttools-4.59.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:f9b3a78f69dcbd803cf2fb3f972779875b244c1115481dfbdd567b2c22b31f6b", size = 2767562, upload-time = "2025-07-16T12:04:06.895Z" }, - { url = "https://files.pythonhosted.org/packages/ff/5a/aeb975699588176bb357e8b398dfd27e5d3a2230d92b81ab8cbb6187358d/fonttools-4.59.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:57bb7e26928573ee7c6504f54c05860d867fd35e675769f3ce01b52af38d48e2", size = 2335168, upload-time = "2025-07-16T12:04:08.695Z" }, - { url = "https://files.pythonhosted.org/packages/54/97/c6101a7e60ae138c4ef75b22434373a0da50a707dad523dd19a4889315bf/fonttools-4.59.0-cp312-cp312-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:4536f2695fe5c1ffb528d84a35a7d3967e5558d2af58b4775e7ab1449d65767b", size = 4909850, upload-time = "2025-07-16T12:04:10.761Z" }, - { url = "https://files.pythonhosted.org/packages/bd/6c/fa4d18d641054f7bff878cbea14aa9433f292b9057cb1700d8e91a4d5f4f/fonttools-4.59.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:885bde7d26e5b40e15c47bd5def48b38cbd50830a65f98122a8fb90962af7cd1", size = 4955131, upload-time = "2025-07-16T12:04:12.846Z" }, - { url = "https://files.pythonhosted.org/packages/20/5c/331947fc1377deb928a69bde49f9003364f5115e5cbe351eea99e39412a2/fonttools-4.59.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6801aeddb6acb2c42eafa45bc1cb98ba236871ae6f33f31e984670b749a8e58e", size = 4899667, upload-time = "2025-07-16T12:04:14.558Z" }, - { url = "https://files.pythonhosted.org/packages/8a/46/b66469dfa26b8ff0baa7654b2cc7851206c6d57fe3abdabbaab22079a119/fonttools-4.59.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:31003b6a10f70742a63126b80863ab48175fb8272a18ca0846c0482968f0588e", size = 5051349, upload-time = "2025-07-16T12:04:16.388Z" }, - { url = "https://files.pythonhosted.org/packages/2e/05/ebfb6b1f3a4328ab69787d106a7d92ccde77ce66e98659df0f9e3f28d93d/fonttools-4.59.0-cp312-cp312-win32.whl", hash = "sha256:fbce6dae41b692a5973d0f2158f782b9ad05babc2c2019a970a1094a23909b1b", size = 2201315, upload-time = "2025-07-16T12:04:18.557Z" }, - { url = "https://files.pythonhosted.org/packages/09/45/d2bdc9ea20bbadec1016fd0db45696d573d7a26d95ab5174ffcb6d74340b/fonttools-4.59.0-cp312-cp312-win_amd64.whl", hash = "sha256:332bfe685d1ac58ca8d62b8d6c71c2e52a6c64bc218dc8f7825c9ea51385aa01", size = 2249408, upload-time = "2025-07-16T12:04:20.489Z" }, - { url = "https://files.pythonhosted.org/packages/f3/bb/390990e7c457d377b00890d9f96a3ca13ae2517efafb6609c1756e213ba4/fonttools-4.59.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:78813b49d749e1bb4db1c57f2d4d7e6db22c253cb0a86ad819f5dc197710d4b2", size = 2758704, upload-time = "2025-07-16T12:04:22.217Z" }, - { url = "https://files.pythonhosted.org/packages/df/6f/d730d9fcc9b410a11597092bd2eb9ca53e5438c6cb90e4b3047ce1b723e9/fonttools-4.59.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:401b1941ce37e78b8fd119b419b617277c65ae9417742a63282257434fd68ea2", size = 2330764, upload-time = "2025-07-16T12:04:23.985Z" }, - { url = "https://files.pythonhosted.org/packages/75/b4/b96bb66f6f8cc4669de44a158099b249c8159231d254ab6b092909388be5/fonttools-4.59.0-cp313-cp313-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:efd7e6660674e234e29937bc1481dceb7e0336bfae75b856b4fb272b5093c5d4", size = 4890699, upload-time = "2025-07-16T12:04:25.664Z" }, - { url = "https://files.pythonhosted.org/packages/b5/57/7969af50b26408be12baa317c6147588db5b38af2759e6df94554dbc5fdb/fonttools-4.59.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:51ab1ff33c19e336c02dee1e9fd1abd974a4ca3d8f7eef2a104d0816a241ce97", size = 4952934, upload-time = "2025-07-16T12:04:27.733Z" }, - { url = "https://files.pythonhosted.org/packages/d6/e2/dd968053b6cf1f46c904f5bd409b22341477c017d8201619a265e50762d3/fonttools-4.59.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a9bf8adc9e1f3012edc8f09b08336272aec0c55bc677422273e21280db748f7c", size = 4892319, upload-time = "2025-07-16T12:04:30.074Z" }, - { url = "https://files.pythonhosted.org/packages/6b/95/a59810d8eda09129f83467a4e58f84205dc6994ebaeb9815406363e07250/fonttools-4.59.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:37e01c6ec0c98599778c2e688350d624fa4770fbd6144551bd5e032f1199171c", size = 5034753, upload-time = "2025-07-16T12:04:32.292Z" }, - { url = "https://files.pythonhosted.org/packages/a5/84/51a69ee89ff8d1fea0c6997e946657e25a3f08513de8435fe124929f3eef/fonttools-4.59.0-cp313-cp313-win32.whl", hash = "sha256:70d6b3ceaa9cc5a6ac52884f3b3d9544e8e231e95b23f138bdb78e6d4dc0eae3", size = 2199688, upload-time = "2025-07-16T12:04:34.444Z" }, - { url = "https://files.pythonhosted.org/packages/a0/ee/f626cd372932d828508137a79b85167fdcf3adab2e3bed433f295c596c6a/fonttools-4.59.0-cp313-cp313-win_amd64.whl", hash = "sha256:26731739daa23b872643f0e4072d5939960237d540c35c14e6a06d47d71ca8fe", size = 2248560, upload-time = "2025-07-16T12:04:36.034Z" }, - { url = "https://files.pythonhosted.org/packages/d0/9c/df0ef2c51845a13043e5088f7bb988ca6cd5bb82d5d4203d6a158aa58cf2/fonttools-4.59.0-py3-none-any.whl", hash = "sha256:241313683afd3baacb32a6bd124d0bce7404bc5280e12e291bae1b9bba28711d", size = 1128050, upload-time = "2025-07-16T12:04:52.687Z" }, +version = "4.59.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/0d/a5/fba25f9fbdab96e26dedcaeeba125e5f05a09043bf888e0305326e55685b/fonttools-4.59.2.tar.gz", hash = "sha256:e72c0749b06113f50bcb80332364c6be83a9582d6e3db3fe0b280f996dc2ef22", size = 3540889, upload-time = "2025-08-27T16:40:30.97Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f8/53/742fcd750ae0bdc74de4c0ff923111199cc2f90a4ee87aaddad505b6f477/fonttools-4.59.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:511946e8d7ea5c0d6c7a53c4cb3ee48eda9ab9797cd9bf5d95829a398400354f", size = 2774961, upload-time = "2025-08-27T16:38:47.536Z" }, + { url = "https://files.pythonhosted.org/packages/57/2a/976f5f9fa3b4dd911dc58d07358467bec20e813d933bc5d3db1a955dd456/fonttools-4.59.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:8e5e2682cf7be766d84f462ba8828d01e00c8751a8e8e7ce12d7784ccb69a30d", size = 2344690, upload-time = "2025-08-27T16:38:49.723Z" }, + { url = "https://files.pythonhosted.org/packages/c1/8f/b7eefc274fcf370911e292e95565c8253b0b87c82a53919ab3c795a4f50e/fonttools-4.59.2-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5729e12a982dba3eeae650de48b06f3b9ddb51e9aee2fcaf195b7d09a96250e2", size = 5026910, upload-time = "2025-08-27T16:38:51.904Z" }, + { url = "https://files.pythonhosted.org/packages/69/95/864726eaa8f9d4e053d0c462e64d5830ec7c599cbdf1db9e40f25ca3972e/fonttools-4.59.2-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c52694eae5d652361d59ecdb5a2246bff7cff13b6367a12da8499e9df56d148d", size = 4971031, upload-time = "2025-08-27T16:38:53.676Z" }, + { url = "https://files.pythonhosted.org/packages/24/4c/b8c4735ebdea20696277c70c79e0de615dbe477834e5a7c2569aa1db4033/fonttools-4.59.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:f1f1bbc23ba1312bd8959896f46f667753b90216852d2a8cfa2d07e0cb234144", size = 5006112, upload-time = "2025-08-27T16:38:55.69Z" }, + { url = "https://files.pythonhosted.org/packages/3b/23/f9ea29c292aa2fc1ea381b2e5621ac436d5e3e0a5dee24ffe5404e58eae8/fonttools-4.59.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1a1bfe5378962825dabe741720885e8b9ae9745ec7ecc4a5ec1f1ce59a6062bf", size = 5117671, upload-time = "2025-08-27T16:38:58.984Z" }, + { url = "https://files.pythonhosted.org/packages/ba/07/cfea304c555bf06e86071ff2a3916bc90f7c07ec85b23bab758d4908c33d/fonttools-4.59.2-cp311-cp311-win32.whl", hash = "sha256:e937790f3c2c18a1cbc7da101550a84319eb48023a715914477d2e7faeaba570", size = 2218157, upload-time = "2025-08-27T16:39:00.75Z" }, + { url = "https://files.pythonhosted.org/packages/d7/de/35d839aa69db737a3f9f3a45000ca24721834d40118652a5775d5eca8ebb/fonttools-4.59.2-cp311-cp311-win_amd64.whl", hash = "sha256:9836394e2f4ce5f9c0a7690ee93bd90aa1adc6b054f1a57b562c5d242c903104", size = 2265846, upload-time = "2025-08-27T16:39:02.453Z" }, + { url = "https://files.pythonhosted.org/packages/ba/3d/1f45db2df51e7bfa55492e8f23f383d372200be3a0ded4bf56a92753dd1f/fonttools-4.59.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:82906d002c349cad647a7634b004825a7335f8159d0d035ae89253b4abf6f3ea", size = 2769711, upload-time = "2025-08-27T16:39:04.423Z" }, + { url = "https://files.pythonhosted.org/packages/29/df/cd236ab32a8abfd11558f296e064424258db5edefd1279ffdbcfd4fd8b76/fonttools-4.59.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:a10c1bd7644dc58f8862d8ba0cf9fb7fef0af01ea184ba6ce3f50ab7dfe74d5a", size = 2340225, upload-time = "2025-08-27T16:39:06.143Z" }, + { url = "https://files.pythonhosted.org/packages/98/12/b6f9f964fe6d4b4dd4406bcbd3328821c3de1f909ffc3ffa558fe72af48c/fonttools-4.59.2-cp312-cp312-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:738f31f23e0339785fd67652a94bc69ea49e413dfdb14dcb8c8ff383d249464e", size = 4912766, upload-time = "2025-08-27T16:39:08.138Z" }, + { url = "https://files.pythonhosted.org/packages/73/78/82bde2f2d2c306ef3909b927363170b83df96171f74e0ccb47ad344563cd/fonttools-4.59.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0ec99f9bdfee9cdb4a9172f9e8fd578cce5feb231f598909e0aecf5418da4f25", size = 4955178, upload-time = "2025-08-27T16:39:10.094Z" }, + { url = "https://files.pythonhosted.org/packages/92/77/7de766afe2d31dda8ee46d7e479f35c7d48747e558961489a2d6e3a02bd4/fonttools-4.59.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:0476ea74161322e08c7a982f83558a2b81b491509984523a1a540baf8611cc31", size = 4897898, upload-time = "2025-08-27T16:39:12.087Z" }, + { url = "https://files.pythonhosted.org/packages/c5/77/ce0e0b905d62a06415fda9f2b2e109a24a5db54a59502b769e9e297d2242/fonttools-4.59.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:95922a922daa1f77cc72611747c156cfb38030ead72436a2c551d30ecef519b9", size = 5049144, upload-time = "2025-08-27T16:39:13.84Z" }, + { url = "https://files.pythonhosted.org/packages/d9/ea/870d93aefd23fff2e07cbeebdc332527868422a433c64062c09d4d5e7fe6/fonttools-4.59.2-cp312-cp312-win32.whl", hash = "sha256:39ad9612c6a622726a6a130e8ab15794558591f999673f1ee7d2f3d30f6a3e1c", size = 2206473, upload-time = "2025-08-27T16:39:15.854Z" }, + { url = "https://files.pythonhosted.org/packages/61/c4/e44bad000c4a4bb2e9ca11491d266e857df98ab6d7428441b173f0fe2517/fonttools-4.59.2-cp312-cp312-win_amd64.whl", hash = "sha256:980fd7388e461b19a881d35013fec32c713ffea1fc37aef2f77d11f332dfd7da", size = 2254706, upload-time = "2025-08-27T16:39:17.893Z" }, + { url = "https://files.pythonhosted.org/packages/13/7b/d0d3b9431642947b5805201fbbbe938a47b70c76685ef1f0cb5f5d7140d6/fonttools-4.59.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:381bde13216ba09489864467f6bc0c57997bd729abfbb1ce6f807ba42c06cceb", size = 2761563, upload-time = "2025-08-27T16:39:20.286Z" }, + { url = "https://files.pythonhosted.org/packages/76/be/fc5fe58dd76af7127b769b68071dbc32d4b95adc8b58d1d28d42d93c90f2/fonttools-4.59.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f33839aa091f7eef4e9078f5b7ab1b8ea4b1d8a50aeaef9fdb3611bba80869ec", size = 2335671, upload-time = "2025-08-27T16:39:22.027Z" }, + { url = "https://files.pythonhosted.org/packages/f2/9f/bf231c2a3fac99d1d7f1d89c76594f158693f981a4aa02be406e9f036832/fonttools-4.59.2-cp313-cp313-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:6235fc06bcbdb40186f483ba9d5d68f888ea68aa3c8dac347e05a7c54346fbc8", size = 4893967, upload-time = "2025-08-27T16:39:23.664Z" }, + { url = "https://files.pythonhosted.org/packages/26/a9/d46d2ad4fcb915198504d6727f83aa07f46764c64f425a861aa38756c9fd/fonttools-4.59.2-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:83ad6e5d06ef3a2884c4fa6384a20d6367b5cfe560e3b53b07c9dc65a7020e73", size = 4951986, upload-time = "2025-08-27T16:39:25.379Z" }, + { url = "https://files.pythonhosted.org/packages/07/90/1cc8d7dd8f707dfeeca472b82b898d3add0ebe85b1f645690dcd128ee63f/fonttools-4.59.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d029804c70fddf90be46ed5305c136cae15800a2300cb0f6bba96d48e770dde0", size = 4891630, upload-time = "2025-08-27T16:39:27.494Z" }, + { url = "https://files.pythonhosted.org/packages/d8/04/f0345b0d9fe67d65aa8d3f2d4cbf91d06f111bc7b8d802e65914eb06194d/fonttools-4.59.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:95807a3b5e78f2714acaa26a33bc2143005cc05c0217b322361a772e59f32b89", size = 5035116, upload-time = "2025-08-27T16:39:29.406Z" }, + { url = "https://files.pythonhosted.org/packages/d7/7d/5ba5eefffd243182fbd067cdbfeb12addd4e5aec45011b724c98a344ea33/fonttools-4.59.2-cp313-cp313-win32.whl", hash = "sha256:b3ebda00c3bb8f32a740b72ec38537d54c7c09f383a4cfefb0b315860f825b08", size = 2204907, upload-time = "2025-08-27T16:39:31.42Z" }, + { url = "https://files.pythonhosted.org/packages/ea/a9/be7219fc64a6026cc0aded17fa3720f9277001c185434230bd351bf678e6/fonttools-4.59.2-cp313-cp313-win_amd64.whl", hash = "sha256:a72155928d7053bbde499d32a9c77d3f0f3d29ae72b5a121752481bcbd71e50f", size = 2253742, upload-time = "2025-08-27T16:39:33.079Z" }, + { url = "https://files.pythonhosted.org/packages/fc/c7/486580d00be6fa5d45e41682e5ffa5c809f3d25773c6f39628d60f333521/fonttools-4.59.2-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:d09e487d6bfbe21195801323ba95c91cb3523f0fcc34016454d4d9ae9eaa57fe", size = 2762444, upload-time = "2025-08-27T16:39:34.759Z" }, + { url = "https://files.pythonhosted.org/packages/d3/9b/950ea9b7b764ceb8d18645c62191e14ce62124d8e05cb32a4dc5e65fde0b/fonttools-4.59.2-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:dec2f22486d7781087b173799567cffdcc75e9fb2f1c045f05f8317ccce76a3e", size = 2333256, upload-time = "2025-08-27T16:39:40.777Z" }, + { url = "https://files.pythonhosted.org/packages/9b/4d/8ee9d563126de9002eede950cde0051be86cc4e8c07c63eca0c9fc95734a/fonttools-4.59.2-cp314-cp314-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:1647201af10993090120da2e66e9526c4e20e88859f3e34aa05b8c24ded2a564", size = 4834846, upload-time = "2025-08-27T16:39:42.885Z" }, + { url = "https://files.pythonhosted.org/packages/03/26/f26d947b0712dce3d118e92ce30ca88f98938b066498f60d0ee000a892ae/fonttools-4.59.2-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:47742c33fe65f41eabed36eec2d7313a8082704b7b808752406452f766c573fc", size = 4930871, upload-time = "2025-08-27T16:39:44.818Z" }, + { url = "https://files.pythonhosted.org/packages/fc/7f/ebe878061a5a5e6b6502f0548489e01100f7e6c0049846e6546ba19a3ab4/fonttools-4.59.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:92ac2d45794f95d1ad4cb43fa07e7e3776d86c83dc4b9918cf82831518165b4b", size = 4876971, upload-time = "2025-08-27T16:39:47.027Z" }, + { url = "https://files.pythonhosted.org/packages/eb/0d/0d22e3a20ac566836098d30718092351935487e3271fd57385db1adb2fde/fonttools-4.59.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:fa9ecaf2dcef8941fb5719e16322345d730f4c40599bbf47c9753de40eb03882", size = 4987478, upload-time = "2025-08-27T16:39:48.774Z" }, + { url = "https://files.pythonhosted.org/packages/3b/a3/960cc83182a408ffacc795e61b5f698c6f7b0cfccf23da4451c39973f3c8/fonttools-4.59.2-cp314-cp314-win32.whl", hash = "sha256:a8d40594982ed858780e18a7e4c80415af65af0f22efa7de26bdd30bf24e1e14", size = 2208640, upload-time = "2025-08-27T16:39:50.592Z" }, + { url = "https://files.pythonhosted.org/packages/d8/74/55e5c57c414fa3965fee5fc036ed23f26a5c4e9e10f7f078a54ff9c7dfb7/fonttools-4.59.2-cp314-cp314-win_amd64.whl", hash = "sha256:9cde8b6a6b05f68516573523f2013a3574cb2c75299d7d500f44de82ba947b80", size = 2258457, upload-time = "2025-08-27T16:39:52.611Z" }, + { url = "https://files.pythonhosted.org/packages/e1/dc/8e4261dc591c5cfee68fecff3ffee2a9b29e1edc4c4d9cbafdc5aefe74ee/fonttools-4.59.2-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:036cd87a2dbd7ef72f7b68df8314ced00b8d9973aee296f2464d06a836aeb9a9", size = 2829901, upload-time = "2025-08-27T16:39:55.014Z" }, + { url = "https://files.pythonhosted.org/packages/fb/05/331538dcf21fd6331579cd628268150e85210d0d2bdae20f7598c2b36c05/fonttools-4.59.2-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:14870930181493b1d740b6f25483e20185e5aea58aec7d266d16da7be822b4bb", size = 2362717, upload-time = "2025-08-27T16:39:56.843Z" }, + { url = "https://files.pythonhosted.org/packages/60/ae/d26428ca9ede809c0a93f0af91f44c87433dc0251e2aec333da5ed00d38f/fonttools-4.59.2-cp314-cp314t-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:7ff58ea1eb8fc7e05e9a949419f031890023f8785c925b44d6da17a6a7d6e85d", size = 4835120, upload-time = "2025-08-27T16:39:59.06Z" }, + { url = "https://files.pythonhosted.org/packages/07/c4/0f6ac15895de509e07688cb1d45f1ae583adbaa0fa5a5699d73f3bd58ca0/fonttools-4.59.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6dee142b8b3096514c96ad9e2106bf039e2fe34a704c587585b569a36df08c3c", size = 5071115, upload-time = "2025-08-27T16:40:01.009Z" }, + { url = "https://files.pythonhosted.org/packages/b2/b6/147a711b7ecf7ea39f9da9422a55866f6dd5747c2f36b3b0a7a7e0c6820b/fonttools-4.59.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:8991bdbae39cf78bcc9cd3d81f6528df1f83f2e7c23ccf6f990fa1f0b6e19708", size = 4943905, upload-time = "2025-08-27T16:40:03.179Z" }, + { url = "https://files.pythonhosted.org/packages/5b/4e/2ab19006646b753855e2b02200fa1cabb75faa4eeca4ef289f269a936974/fonttools-4.59.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:53c1a411b7690042535a4f0edf2120096a39a506adeb6c51484a232e59f2aa0c", size = 4960313, upload-time = "2025-08-27T16:40:05.45Z" }, + { url = "https://files.pythonhosted.org/packages/98/3d/df77907e5be88adcca93cc2cee00646d039da220164be12bee028401e1cf/fonttools-4.59.2-cp314-cp314t-win32.whl", hash = "sha256:59d85088e29fa7a8f87d19e97a1beae2a35821ee48d8ef6d2c4f965f26cb9f8a", size = 2269719, upload-time = "2025-08-27T16:40:07.553Z" }, + { url = "https://files.pythonhosted.org/packages/2d/a0/d4c4bc5b50275449a9a908283b567caa032a94505fe1976e17f994faa6be/fonttools-4.59.2-cp314-cp314t-win_amd64.whl", hash = "sha256:7ad5d8d8cc9e43cb438b3eb4a0094dd6d4088daa767b0a24d52529361fd4c199", size = 2333169, upload-time = "2025-08-27T16:40:09.656Z" }, + { url = "https://files.pythonhosted.org/packages/65/a4/d2f7be3c86708912c02571db0b550121caab8cd88a3c0aacb9cfa15ea66e/fonttools-4.59.2-py3-none-any.whl", hash = "sha256:8bd0f759020e87bb5d323e6283914d9bf4ae35a7307dafb2cbd1e379e720ad37", size = 1132315, upload-time = "2025-08-27T16:40:28.984Z" }, ] [[package]] @@ -639,15 +655,15 @@ wheels = [ [[package]] name = "hypothesis" -version = "6.138.0" +version = "6.138.13" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "attrs" }, { name = "sortedcontainers" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/b2/06/a6076eb444d961da88c76eb5ac55e4d46171eaa1dd93b06b514dd0f602a7/hypothesis-6.138.0.tar.gz", hash = "sha256:0169339db3fb27fe8229fb2c4c9fe0691536769b59e3e974c061e83362d4e057", size = 462995, upload-time = "2025-08-13T01:56:38.6Z" } +sdist = { url = "https://files.pythonhosted.org/packages/37/42/9cd666af7fd2c3e604f055f756e80d537faba5327cc72cbd44177792d074/hypothesis-6.138.13.tar.gz", hash = "sha256:2bea91629b8b3bb103a5b51442b1037cede3aae26e56ec063c52b9d5d8eaf70b", size = 466041, upload-time = "2025-09-01T14:02:51.468Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/59/fb/049563700c9a5dcd03293b5320c1bfb6316acd1d9eea6d8719218a56cff1/hypothesis-6.138.0-py3-none-any.whl", hash = "sha256:3c3da60c1e3bc7ec766461373c5d5c32e13262f17739f794ad764323ab644544", size = 529863, upload-time = "2025-08-13T01:56:34.395Z" }, + { url = "https://files.pythonhosted.org/packages/cc/82/823c202c8b349ff31a0718e46ff98074bebfb3aa20813091cea07821c25f/hypothesis-6.138.13-py3-none-any.whl", hash = "sha256:09f1130deb08e5d12fb3b59b55c113fd79debaaab9b224ffac17be8341de4326", size = 533564, upload-time = "2025-09-01T14:02:48.15Z" }, ] [[package]] @@ -703,7 +719,7 @@ wheels = [ [[package]] name = "ipython" -version = "9.4.0" +version = "9.5.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "colorama", marker = "sys_platform == 'win32'" }, @@ -718,9 +734,9 @@ dependencies = [ { name = "traitlets" }, { name = "typing-extensions", marker = "python_full_version < '3.12'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/54/80/406f9e3bde1c1fd9bf5a0be9d090f8ae623e401b7670d8f6fdf2ab679891/ipython-9.4.0.tar.gz", hash = "sha256:c033c6d4e7914c3d9768aabe76bbe87ba1dc66a92a05db6bfa1125d81f2ee270", size = 4385338, upload-time = "2025-07-01T11:11:30.606Z" } +sdist = { url = "https://files.pythonhosted.org/packages/6e/71/a86262bf5a68bf211bcc71fe302af7e05f18a2852fdc610a854d20d085e6/ipython-9.5.0.tar.gz", hash = "sha256:129c44b941fe6d9b82d36fc7a7c18127ddb1d6f02f78f867f402e2e3adde3113", size = 4389137, upload-time = "2025-08-29T12:15:21.519Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/63/f8/0031ee2b906a15a33d6bfc12dd09c3dfa966b3cb5b284ecfb7549e6ac3c4/ipython-9.4.0-py3-none-any.whl", hash = "sha256:25850f025a446d9b359e8d296ba175a36aedd32e83ca9b5060430fe16801f066", size = 611021, upload-time = "2025-07-01T11:11:27.85Z" }, + { url = "https://files.pythonhosted.org/packages/08/2a/5628a99d04acb2d2f2e749cdf4ea571d2575e898df0528a090948018b726/ipython-9.5.0-py3-none-any.whl", hash = "sha256:88369ffa1d5817d609120daa523a6da06d02518e582347c29f8451732a9c5e72", size = 612426, upload-time = "2025-08-29T12:15:18.866Z" }, ] [[package]] @@ -777,7 +793,7 @@ wheels = [ [[package]] name = "jsonschema" -version = "4.25.0" +version = "4.25.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "attrs" }, @@ -785,9 +801,9 @@ dependencies = [ { name = "referencing" }, { name = "rpds-py" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/d5/00/a297a868e9d0784450faa7365c2172a7d6110c763e30ba861867c32ae6a9/jsonschema-4.25.0.tar.gz", hash = "sha256:e63acf5c11762c0e6672ffb61482bdf57f0876684d8d249c0fe2d730d48bc55f", size = 356830, upload-time = "2025-07-18T15:39:45.11Z" } +sdist = { url = "https://files.pythonhosted.org/packages/74/69/f7185de793a29082a9f3c7728268ffb31cb5095131a9c139a74078e27336/jsonschema-4.25.1.tar.gz", hash = "sha256:e4a9655ce0da0c0b67a085847e00a3a51449e1157f4f75e9fb5aa545e122eb85", size = 357342, upload-time = "2025-08-18T17:03:50.038Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/fe/54/c86cd8e011fe98803d7e382fd67c0df5ceab8d2b7ad8c5a81524f791551c/jsonschema-4.25.0-py3-none-any.whl", hash = "sha256:24c2e8da302de79c8b9382fee3e76b355e44d2a4364bb207159ce10b517bd716", size = 89184, upload-time = "2025-07-18T15:39:42.956Z" }, + { url = "https://files.pythonhosted.org/packages/bf/9c/8c95d856233c1f82500c2450b8c68576b4cf1c871db3afac5c34ff84e6fd/jsonschema-4.25.1-py3-none-any.whl", hash = "sha256:3fba0169e345c7175110351d456342c364814cfcf3b964ba4587f22915230a63", size = 90040, upload-time = "2025-08-18T17:03:48.373Z" }, ] [[package]] @@ -1015,7 +1031,7 @@ wheels = [ [[package]] name = "matplotlib" -version = "3.10.5" +version = "3.10.6" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "contourpy" }, @@ -1028,53 +1044,53 @@ dependencies = [ { name = "pyparsing" }, { name = "python-dateutil" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/43/91/f2939bb60b7ebf12478b030e0d7f340247390f402b3b189616aad790c366/matplotlib-3.10.5.tar.gz", hash = "sha256:352ed6ccfb7998a00881692f38b4ca083c691d3e275b4145423704c34c909076", size = 34804044, upload-time = "2025-07-31T18:09:33.805Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/aa/c7/1f2db90a1d43710478bb1e9b57b162852f79234d28e4f48a28cc415aa583/matplotlib-3.10.5-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:dcfc39c452c6a9f9028d3e44d2d721484f665304857188124b505b2c95e1eecf", size = 8239216, upload-time = "2025-07-31T18:07:51.947Z" }, - { url = "https://files.pythonhosted.org/packages/82/6d/ca6844c77a4f89b1c9e4d481c412e1d1dbabf2aae2cbc5aa2da4a1d6683e/matplotlib-3.10.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:903352681b59f3efbf4546985142a9686ea1d616bb054b09a537a06e4b892ccf", size = 8102130, upload-time = "2025-07-31T18:07:53.65Z" }, - { url = "https://files.pythonhosted.org/packages/1d/1e/5e187a30cc673a3e384f3723e5f3c416033c1d8d5da414f82e4e731128ea/matplotlib-3.10.5-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:080c3676a56b8ee1c762bcf8fca3fe709daa1ee23e6ef06ad9f3fc17332f2d2a", size = 8666471, upload-time = "2025-07-31T18:07:55.304Z" }, - { url = "https://files.pythonhosted.org/packages/03/c0/95540d584d7d645324db99a845ac194e915ef75011a0d5e19e1b5cee7e69/matplotlib-3.10.5-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4b4984d5064a35b6f66d2c11d668565f4389b1119cc64db7a4c1725bc11adffc", size = 9500518, upload-time = "2025-07-31T18:07:57.199Z" }, - { url = "https://files.pythonhosted.org/packages/ba/2e/e019352099ea58b4169adb9c6e1a2ad0c568c6377c2b677ee1f06de2adc7/matplotlib-3.10.5-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:3967424121d3a46705c9fa9bdb0931de3228f13f73d7bb03c999c88343a89d89", size = 9552372, upload-time = "2025-07-31T18:07:59.41Z" }, - { url = "https://files.pythonhosted.org/packages/b7/81/3200b792a5e8b354f31f4101ad7834743ad07b6d620259f2059317b25e4d/matplotlib-3.10.5-cp311-cp311-win_amd64.whl", hash = "sha256:33775bbeb75528555a15ac29396940128ef5613cf9a2d31fb1bfd18b3c0c0903", size = 8100634, upload-time = "2025-07-31T18:08:01.801Z" }, - { url = "https://files.pythonhosted.org/packages/52/46/a944f6f0c1f5476a0adfa501969d229ce5ae60cf9a663be0e70361381f89/matplotlib-3.10.5-cp311-cp311-win_arm64.whl", hash = "sha256:c61333a8e5e6240e73769d5826b9a31d8b22df76c0778f8480baf1b4b01c9420", size = 7978880, upload-time = "2025-07-31T18:08:03.407Z" }, - { url = "https://files.pythonhosted.org/packages/66/1e/c6f6bcd882d589410b475ca1fc22e34e34c82adff519caf18f3e6dd9d682/matplotlib-3.10.5-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:00b6feadc28a08bd3c65b2894f56cf3c94fc8f7adcbc6ab4516ae1e8ed8f62e2", size = 8253056, upload-time = "2025-07-31T18:08:05.385Z" }, - { url = "https://files.pythonhosted.org/packages/53/e6/d6f7d1b59413f233793dda14419776f5f443bcccb2dfc84b09f09fe05dbe/matplotlib-3.10.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ee98a5c5344dc7f48dc261b6ba5d9900c008fc12beb3fa6ebda81273602cc389", size = 8110131, upload-time = "2025-07-31T18:08:07.293Z" }, - { url = "https://files.pythonhosted.org/packages/66/2b/bed8a45e74957549197a2ac2e1259671cd80b55ed9e1fe2b5c94d88a9202/matplotlib-3.10.5-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:a17e57e33de901d221a07af32c08870ed4528db0b6059dce7d7e65c1122d4bea", size = 8669603, upload-time = "2025-07-31T18:08:09.064Z" }, - { url = "https://files.pythonhosted.org/packages/7e/a7/315e9435b10d057f5e52dfc603cd353167ae28bb1a4e033d41540c0067a4/matplotlib-3.10.5-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:97b9d6443419085950ee4a5b1ee08c363e5c43d7176e55513479e53669e88468", size = 9508127, upload-time = "2025-07-31T18:08:10.845Z" }, - { url = "https://files.pythonhosted.org/packages/7f/d9/edcbb1f02ca99165365d2768d517898c22c6040187e2ae2ce7294437c413/matplotlib-3.10.5-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ceefe5d40807d29a66ae916c6a3915d60ef9f028ce1927b84e727be91d884369", size = 9566926, upload-time = "2025-07-31T18:08:13.186Z" }, - { url = "https://files.pythonhosted.org/packages/3b/d9/6dd924ad5616c97b7308e6320cf392c466237a82a2040381163b7500510a/matplotlib-3.10.5-cp312-cp312-win_amd64.whl", hash = "sha256:c04cba0f93d40e45b3c187c6c52c17f24535b27d545f757a2fffebc06c12b98b", size = 8107599, upload-time = "2025-07-31T18:08:15.116Z" }, - { url = "https://files.pythonhosted.org/packages/0e/f3/522dc319a50f7b0279fbe74f86f7a3506ce414bc23172098e8d2bdf21894/matplotlib-3.10.5-cp312-cp312-win_arm64.whl", hash = "sha256:a41bcb6e2c8e79dc99c5511ae6f7787d2fb52efd3d805fff06d5d4f667db16b2", size = 7978173, upload-time = "2025-07-31T18:08:21.518Z" }, - { url = "https://files.pythonhosted.org/packages/8d/05/4f3c1f396075f108515e45cb8d334aff011a922350e502a7472e24c52d77/matplotlib-3.10.5-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:354204db3f7d5caaa10e5de74549ef6a05a4550fdd1c8f831ab9bca81efd39ed", size = 8253586, upload-time = "2025-07-31T18:08:23.107Z" }, - { url = "https://files.pythonhosted.org/packages/2f/2c/e084415775aac7016c3719fe7006cdb462582c6c99ac142f27303c56e243/matplotlib-3.10.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:b072aac0c3ad563a2b3318124756cb6112157017f7431626600ecbe890df57a1", size = 8110715, upload-time = "2025-07-31T18:08:24.675Z" }, - { url = "https://files.pythonhosted.org/packages/52/1b/233e3094b749df16e3e6cd5a44849fd33852e692ad009cf7de00cf58ddf6/matplotlib-3.10.5-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d52fd5b684d541b5a51fb276b2b97b010c75bee9aa392f96b4a07aeb491e33c7", size = 8669397, upload-time = "2025-07-31T18:08:26.778Z" }, - { url = "https://files.pythonhosted.org/packages/e8/ec/03f9e003a798f907d9f772eed9b7c6a9775d5bd00648b643ebfb88e25414/matplotlib-3.10.5-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ee7a09ae2f4676276f5a65bd9f2bd91b4f9fbaedf49f40267ce3f9b448de501f", size = 9508646, upload-time = "2025-07-31T18:08:28.848Z" }, - { url = "https://files.pythonhosted.org/packages/91/e7/c051a7a386680c28487bca27d23b02d84f63e3d2a9b4d2fc478e6a42e37e/matplotlib-3.10.5-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ba6c3c9c067b83481d647af88b4e441d532acdb5ef22178a14935b0b881188f4", size = 9567424, upload-time = "2025-07-31T18:08:30.726Z" }, - { url = "https://files.pythonhosted.org/packages/36/c2/24302e93ff431b8f4173ee1dd88976c8d80483cadbc5d3d777cef47b3a1c/matplotlib-3.10.5-cp313-cp313-win_amd64.whl", hash = "sha256:07442d2692c9bd1cceaa4afb4bbe5b57b98a7599de4dabfcca92d3eea70f9ebe", size = 8107809, upload-time = "2025-07-31T18:08:33.928Z" }, - { url = "https://files.pythonhosted.org/packages/0b/33/423ec6a668d375dad825197557ed8fbdb74d62b432c1ed8235465945475f/matplotlib-3.10.5-cp313-cp313-win_arm64.whl", hash = "sha256:48fe6d47380b68a37ccfcc94f009530e84d41f71f5dae7eda7c4a5a84aa0a674", size = 7978078, upload-time = "2025-07-31T18:08:36.764Z" }, - { url = "https://files.pythonhosted.org/packages/51/17/521fc16ec766455c7bb52cc046550cf7652f6765ca8650ff120aa2d197b6/matplotlib-3.10.5-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:3b80eb8621331449fc519541a7461987f10afa4f9cfd91afcd2276ebe19bd56c", size = 8295590, upload-time = "2025-07-31T18:08:38.521Z" }, - { url = "https://files.pythonhosted.org/packages/f8/12/23c28b2c21114c63999bae129fce7fd34515641c517ae48ce7b7dcd33458/matplotlib-3.10.5-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:47a388908e469d6ca2a6015858fa924e0e8a2345a37125948d8e93a91c47933e", size = 8158518, upload-time = "2025-07-31T18:08:40.195Z" }, - { url = "https://files.pythonhosted.org/packages/81/f8/aae4eb25e8e7190759f3cb91cbeaa344128159ac92bb6b409e24f8711f78/matplotlib-3.10.5-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:8b6b49167d208358983ce26e43aa4196073b4702858670f2eb111f9a10652b4b", size = 8691815, upload-time = "2025-07-31T18:08:42.238Z" }, - { url = "https://files.pythonhosted.org/packages/d0/ba/450c39ebdd486bd33a359fc17365ade46c6a96bf637bbb0df7824de2886c/matplotlib-3.10.5-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8a8da0453a7fd8e3da114234ba70c5ba9ef0e98f190309ddfde0f089accd46ea", size = 9522814, upload-time = "2025-07-31T18:08:44.914Z" }, - { url = "https://files.pythonhosted.org/packages/89/11/9c66f6a990e27bb9aa023f7988d2d5809cb98aa39c09cbf20fba75a542ef/matplotlib-3.10.5-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:52c6573dfcb7726a9907b482cd5b92e6b5499b284ffacb04ffbfe06b3e568124", size = 9573917, upload-time = "2025-07-31T18:08:47.038Z" }, - { url = "https://files.pythonhosted.org/packages/b3/69/8b49394de92569419e5e05e82e83df9b749a0ff550d07631ea96ed2eb35a/matplotlib-3.10.5-cp313-cp313t-win_amd64.whl", hash = "sha256:a23193db2e9d64ece69cac0c8231849db7dd77ce59c7b89948cf9d0ce655a3ce", size = 8181034, upload-time = "2025-07-31T18:08:48.943Z" }, - { url = "https://files.pythonhosted.org/packages/47/23/82dc435bb98a2fc5c20dffcac8f0b083935ac28286413ed8835df40d0baa/matplotlib-3.10.5-cp313-cp313t-win_arm64.whl", hash = "sha256:56da3b102cf6da2776fef3e71cd96fcf22103a13594a18ac9a9b31314e0be154", size = 8023337, upload-time = "2025-07-31T18:08:50.791Z" }, - { url = "https://files.pythonhosted.org/packages/ac/e0/26b6cfde31f5383503ee45dcb7e691d45dadf0b3f54639332b59316a97f8/matplotlib-3.10.5-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:96ef8f5a3696f20f55597ffa91c28e2e73088df25c555f8d4754931515512715", size = 8253591, upload-time = "2025-07-31T18:08:53.254Z" }, - { url = "https://files.pythonhosted.org/packages/c1/89/98488c7ef7ea20ea659af7499628c240a608b337af4be2066d644cfd0a0f/matplotlib-3.10.5-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:77fab633e94b9da60512d4fa0213daeb76d5a7b05156840c4fd0399b4b818837", size = 8112566, upload-time = "2025-07-31T18:08:55.116Z" }, - { url = "https://files.pythonhosted.org/packages/52/67/42294dfedc82aea55e1a767daf3263aacfb5a125f44ba189e685bab41b6f/matplotlib-3.10.5-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:27f52634315e96b1debbfdc5c416592edcd9c4221bc2f520fd39c33db5d9f202", size = 9513281, upload-time = "2025-07-31T18:08:56.885Z" }, - { url = "https://files.pythonhosted.org/packages/e7/68/f258239e0cf34c2cbc816781c7ab6fca768452e6bf1119aedd2bd4a882a3/matplotlib-3.10.5-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:525f6e28c485c769d1f07935b660c864de41c37fd716bfa64158ea646f7084bb", size = 9780873, upload-time = "2025-07-31T18:08:59.241Z" }, - { url = "https://files.pythonhosted.org/packages/89/64/f4881554006bd12e4558bd66778bdd15d47b00a1f6c6e8b50f6208eda4b3/matplotlib-3.10.5-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:1f5f3ec4c191253c5f2b7c07096a142c6a1c024d9f738247bfc8e3f9643fc975", size = 9568954, upload-time = "2025-07-31T18:09:01.244Z" }, - { url = "https://files.pythonhosted.org/packages/06/f8/42779d39c3f757e1f012f2dda3319a89fb602bd2ef98ce8faf0281f4febd/matplotlib-3.10.5-cp314-cp314-win_amd64.whl", hash = "sha256:707f9c292c4cd4716f19ab8a1f93f26598222cd931e0cd98fbbb1c5994bf7667", size = 8237465, upload-time = "2025-07-31T18:09:03.206Z" }, - { url = "https://files.pythonhosted.org/packages/cf/f8/153fd06b5160f0cd27c8b9dd797fcc9fb56ac6a0ebf3c1f765b6b68d3c8a/matplotlib-3.10.5-cp314-cp314-win_arm64.whl", hash = "sha256:21a95b9bf408178d372814de7baacd61c712a62cae560b5e6f35d791776f6516", size = 8108898, upload-time = "2025-07-31T18:09:05.231Z" }, - { url = "https://files.pythonhosted.org/packages/9a/ee/c4b082a382a225fe0d2a73f1f57cf6f6f132308805b493a54c8641006238/matplotlib-3.10.5-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:a6b310f95e1102a8c7c817ef17b60ee5d1851b8c71b63d9286b66b177963039e", size = 8295636, upload-time = "2025-07-31T18:09:07.306Z" }, - { url = "https://files.pythonhosted.org/packages/30/73/2195fa2099718b21a20da82dfc753bf2af58d596b51aefe93e359dd5915a/matplotlib-3.10.5-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:94986a242747a0605cb3ff1cb98691c736f28a59f8ffe5175acaeb7397c49a5a", size = 8158575, upload-time = "2025-07-31T18:09:09.083Z" }, - { url = "https://files.pythonhosted.org/packages/f6/e9/a08cdb34618a91fa08f75e6738541da5cacde7c307cea18ff10f0d03fcff/matplotlib-3.10.5-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1ff10ea43288f0c8bab608a305dc6c918cc729d429c31dcbbecde3b9f4d5b569", size = 9522815, upload-time = "2025-07-31T18:09:11.191Z" }, - { url = "https://files.pythonhosted.org/packages/4e/bb/34d8b7e0d1bb6d06ef45db01dfa560d5a67b1c40c0b998ce9ccde934bb09/matplotlib-3.10.5-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f6adb644c9d040ffb0d3434e440490a66cf73dbfa118a6f79cd7568431f7a012", size = 9783514, upload-time = "2025-07-31T18:09:13.307Z" }, - { url = "https://files.pythonhosted.org/packages/12/09/d330d1e55dcca2e11b4d304cc5227f52e2512e46828d6249b88e0694176e/matplotlib-3.10.5-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:4fa40a8f98428f789a9dcacd625f59b7bc4e3ef6c8c7c80187a7a709475cf592", size = 9573932, upload-time = "2025-07-31T18:09:15.335Z" }, - { url = "https://files.pythonhosted.org/packages/eb/3b/f70258ac729aa004aca673800a53a2b0a26d49ca1df2eaa03289a1c40f81/matplotlib-3.10.5-cp314-cp314t-win_amd64.whl", hash = "sha256:95672a5d628b44207aab91ec20bf59c26da99de12b88f7e0b1fb0a84a86ff959", size = 8322003, upload-time = "2025-07-31T18:09:17.416Z" }, - { url = "https://files.pythonhosted.org/packages/5b/60/3601f8ce6d76a7c81c7f25a0e15fde0d6b66226dd187aa6d2838e6374161/matplotlib-3.10.5-cp314-cp314t-win_arm64.whl", hash = "sha256:2efaf97d72629e74252e0b5e3c46813e9eeaa94e011ecf8084a971a31a97f40b", size = 8153849, upload-time = "2025-07-31T18:09:19.673Z" }, - { url = "https://files.pythonhosted.org/packages/dc/d6/e921be4e1a5f7aca5194e1f016cb67ec294548e530013251f630713e456d/matplotlib-3.10.5-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:160e125da27a749481eaddc0627962990f6029811dbeae23881833a011a0907f", size = 8233224, upload-time = "2025-07-31T18:09:27.512Z" }, - { url = "https://files.pythonhosted.org/packages/ec/74/a2b9b04824b9c349c8f1b2d21d5af43fa7010039427f2b133a034cb09e59/matplotlib-3.10.5-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:ac3d50760394d78a3c9be6b28318fe22b494c4fcf6407e8fd4794b538251899b", size = 8098539, upload-time = "2025-07-31T18:09:29.629Z" }, - { url = "https://files.pythonhosted.org/packages/fc/66/cd29ebc7f6c0d2a15d216fb572573e8fc38bd5d6dec3bd9d7d904c0949f7/matplotlib-3.10.5-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:6c49465bf689c4d59d174d0c7795fb42a21d4244d11d70e52b8011987367ac61", size = 8672192, upload-time = "2025-07-31T18:09:31.407Z" }, +sdist = { url = "https://files.pythonhosted.org/packages/a0/59/c3e6453a9676ffba145309a73c462bb407f4400de7de3f2b41af70720a3c/matplotlib-3.10.6.tar.gz", hash = "sha256:ec01b645840dd1996df21ee37f208cd8ba57644779fa20464010638013d3203c", size = 34804264, upload-time = "2025-08-30T00:14:25.137Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/80/d6/5d3665aa44c49005aaacaa68ddea6fcb27345961cd538a98bb0177934ede/matplotlib-3.10.6-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:905b60d1cb0ee604ce65b297b61cf8be9f4e6cfecf95a3fe1c388b5266bc8f4f", size = 8257527, upload-time = "2025-08-30T00:12:45.31Z" }, + { url = "https://files.pythonhosted.org/packages/8c/af/30ddefe19ca67eebd70047dabf50f899eaff6f3c5e6a1a7edaecaf63f794/matplotlib-3.10.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7bac38d816637343e53d7185d0c66677ff30ffb131044a81898b5792c956ba76", size = 8119583, upload-time = "2025-08-30T00:12:47.236Z" }, + { url = "https://files.pythonhosted.org/packages/d3/29/4a8650a3dcae97fa4f375d46efcb25920d67b512186f8a6788b896062a81/matplotlib-3.10.6-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:942a8de2b5bfff1de31d95722f702e2966b8a7e31f4e68f7cd963c7cd8861cf6", size = 8692682, upload-time = "2025-08-30T00:12:48.781Z" }, + { url = "https://files.pythonhosted.org/packages/aa/d3/b793b9cb061cfd5d42ff0f69d1822f8d5dbc94e004618e48a97a8373179a/matplotlib-3.10.6-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a3276c85370bc0dfca051ec65c5817d1e0f8f5ce1b7787528ec8ed2d524bbc2f", size = 9521065, upload-time = "2025-08-30T00:12:50.602Z" }, + { url = "https://files.pythonhosted.org/packages/f7/c5/53de5629f223c1c66668d46ac2621961970d21916a4bc3862b174eb2a88f/matplotlib-3.10.6-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9df5851b219225731f564e4b9e7f2ac1e13c9e6481f941b5631a0f8e2d9387ce", size = 9576888, upload-time = "2025-08-30T00:12:52.92Z" }, + { url = "https://files.pythonhosted.org/packages/fc/8e/0a18d6d7d2d0a2e66585032a760d13662e5250c784d53ad50434e9560991/matplotlib-3.10.6-cp311-cp311-win_amd64.whl", hash = "sha256:abb5d9478625dd9c9eb51a06d39aae71eda749ae9b3138afb23eb38824026c7e", size = 8115158, upload-time = "2025-08-30T00:12:54.863Z" }, + { url = "https://files.pythonhosted.org/packages/07/b3/1a5107bb66c261e23b9338070702597a2d374e5aa7004b7adfc754fbed02/matplotlib-3.10.6-cp311-cp311-win_arm64.whl", hash = "sha256:886f989ccfae63659183173bb3fced7fd65e9eb793c3cc21c273add368536951", size = 7992444, upload-time = "2025-08-30T00:12:57.067Z" }, + { url = "https://files.pythonhosted.org/packages/ea/1a/7042f7430055d567cc3257ac409fcf608599ab27459457f13772c2d9778b/matplotlib-3.10.6-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:31ca662df6a80bd426f871105fdd69db7543e28e73a9f2afe80de7e531eb2347", size = 8272404, upload-time = "2025-08-30T00:12:59.112Z" }, + { url = "https://files.pythonhosted.org/packages/a9/5d/1d5f33f5b43f4f9e69e6a5fe1fb9090936ae7bc8e2ff6158e7a76542633b/matplotlib-3.10.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1678bb61d897bb4ac4757b5ecfb02bfb3fddf7f808000fb81e09c510712fda75", size = 8128262, upload-time = "2025-08-30T00:13:01.141Z" }, + { url = "https://files.pythonhosted.org/packages/67/c3/135fdbbbf84e0979712df58e5e22b4f257b3f5e52a3c4aacf1b8abec0d09/matplotlib-3.10.6-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:56cd2d20842f58c03d2d6e6c1f1cf5548ad6f66b91e1e48f814e4fb5abd1cb95", size = 8697008, upload-time = "2025-08-30T00:13:03.24Z" }, + { url = "https://files.pythonhosted.org/packages/9c/be/c443ea428fb2488a3ea7608714b1bd85a82738c45da21b447dc49e2f8e5d/matplotlib-3.10.6-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:662df55604a2f9a45435566d6e2660e41efe83cd94f4288dfbf1e6d1eae4b0bb", size = 9530166, upload-time = "2025-08-30T00:13:05.951Z" }, + { url = "https://files.pythonhosted.org/packages/a9/35/48441422b044d74034aea2a3e0d1a49023f12150ebc58f16600132b9bbaf/matplotlib-3.10.6-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:08f141d55148cd1fc870c3387d70ca4df16dee10e909b3b038782bd4bda6ea07", size = 9593105, upload-time = "2025-08-30T00:13:08.356Z" }, + { url = "https://files.pythonhosted.org/packages/45/c3/994ef20eb4154ab84cc08d033834555319e4af970165e6c8894050af0b3c/matplotlib-3.10.6-cp312-cp312-win_amd64.whl", hash = "sha256:590f5925c2d650b5c9d813c5b3b5fc53f2929c3f8ef463e4ecfa7e052044fb2b", size = 8122784, upload-time = "2025-08-30T00:13:10.367Z" }, + { url = "https://files.pythonhosted.org/packages/57/b8/5c85d9ae0e40f04e71bedb053aada5d6bab1f9b5399a0937afb5d6b02d98/matplotlib-3.10.6-cp312-cp312-win_arm64.whl", hash = "sha256:f44c8d264a71609c79a78d50349e724f5d5fc3684ead7c2a473665ee63d868aa", size = 7992823, upload-time = "2025-08-30T00:13:12.24Z" }, + { url = "https://files.pythonhosted.org/packages/a0/db/18380e788bb837e724358287b08e223b32bc8dccb3b0c12fa8ca20bc7f3b/matplotlib-3.10.6-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:819e409653c1106c8deaf62e6de6b8611449c2cd9939acb0d7d4e57a3d95cc7a", size = 8273231, upload-time = "2025-08-30T00:13:13.881Z" }, + { url = "https://files.pythonhosted.org/packages/d3/0f/38dd49445b297e0d4f12a322c30779df0d43cb5873c7847df8a82e82ec67/matplotlib-3.10.6-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:59c8ac8382fefb9cb71308dde16a7c487432f5255d8f1fd32473523abecfecdf", size = 8128730, upload-time = "2025-08-30T00:13:15.556Z" }, + { url = "https://files.pythonhosted.org/packages/e5/b8/9eea6630198cb303d131d95d285a024b3b8645b1763a2916fddb44ca8760/matplotlib-3.10.6-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:84e82d9e0fd70c70bc55739defbd8055c54300750cbacf4740c9673a24d6933a", size = 8698539, upload-time = "2025-08-30T00:13:17.297Z" }, + { url = "https://files.pythonhosted.org/packages/71/34/44c7b1f075e1ea398f88aeabcc2907c01b9cc99e2afd560c1d49845a1227/matplotlib-3.10.6-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:25f7a3eb42d6c1c56e89eacd495661fc815ffc08d9da750bca766771c0fd9110", size = 9529702, upload-time = "2025-08-30T00:13:19.248Z" }, + { url = "https://files.pythonhosted.org/packages/b5/7f/e5c2dc9950c7facaf8b461858d1b92c09dd0cf174fe14e21953b3dda06f7/matplotlib-3.10.6-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:f9c862d91ec0b7842920a4cfdaaec29662195301914ea54c33e01f1a28d014b2", size = 9593742, upload-time = "2025-08-30T00:13:21.181Z" }, + { url = "https://files.pythonhosted.org/packages/ff/1d/70c28528794f6410ee2856cd729fa1f1756498b8d3126443b0a94e1a8695/matplotlib-3.10.6-cp313-cp313-win_amd64.whl", hash = "sha256:1b53bd6337eba483e2e7d29c5ab10eee644bc3a2491ec67cc55f7b44583ffb18", size = 8122753, upload-time = "2025-08-30T00:13:23.44Z" }, + { url = "https://files.pythonhosted.org/packages/e8/74/0e1670501fc7d02d981564caf7c4df42974464625935424ca9654040077c/matplotlib-3.10.6-cp313-cp313-win_arm64.whl", hash = "sha256:cbd5eb50b7058b2892ce45c2f4e92557f395c9991f5c886d1bb74a1582e70fd6", size = 7992973, upload-time = "2025-08-30T00:13:26.632Z" }, + { url = "https://files.pythonhosted.org/packages/b1/4e/60780e631d73b6b02bd7239f89c451a72970e5e7ec34f621eda55cd9a445/matplotlib-3.10.6-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:acc86dd6e0e695c095001a7fccff158c49e45e0758fdf5dcdbb0103318b59c9f", size = 8316869, upload-time = "2025-08-30T00:13:28.262Z" }, + { url = "https://files.pythonhosted.org/packages/f8/15/baa662374a579413210fc2115d40c503b7360a08e9cc254aa0d97d34b0c1/matplotlib-3.10.6-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:e228cd2ffb8f88b7d0b29e37f68ca9aaf83e33821f24a5ccc4f082dd8396bc27", size = 8178240, upload-time = "2025-08-30T00:13:30.007Z" }, + { url = "https://files.pythonhosted.org/packages/c6/3f/3c38e78d2aafdb8829fcd0857d25aaf9e7dd2dfcf7ec742765b585774931/matplotlib-3.10.6-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:658bc91894adeab669cf4bb4a186d049948262987e80f0857216387d7435d833", size = 8711719, upload-time = "2025-08-30T00:13:31.72Z" }, + { url = "https://files.pythonhosted.org/packages/96/4b/2ec2bbf8cefaa53207cc56118d1fa8a0f9b80642713ea9390235d331ede4/matplotlib-3.10.6-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8913b7474f6dd83ac444c9459c91f7f0f2859e839f41d642691b104e0af056aa", size = 9541422, upload-time = "2025-08-30T00:13:33.611Z" }, + { url = "https://files.pythonhosted.org/packages/83/7d/40255e89b3ef11c7871020563b2dd85f6cb1b4eff17c0f62b6eb14c8fa80/matplotlib-3.10.6-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:091cea22e059b89f6d7d1a18e2c33a7376c26eee60e401d92a4d6726c4e12706", size = 9594068, upload-time = "2025-08-30T00:13:35.833Z" }, + { url = "https://files.pythonhosted.org/packages/f0/a9/0213748d69dc842537a113493e1c27daf9f96bd7cc316f933dc8ec4de985/matplotlib-3.10.6-cp313-cp313t-win_amd64.whl", hash = "sha256:491e25e02a23d7207629d942c666924a6b61e007a48177fdd231a0097b7f507e", size = 8200100, upload-time = "2025-08-30T00:13:37.668Z" }, + { url = "https://files.pythonhosted.org/packages/be/15/79f9988066ce40b8a6f1759a934ea0cde8dc4adc2262255ee1bc98de6ad0/matplotlib-3.10.6-cp313-cp313t-win_arm64.whl", hash = "sha256:3d80d60d4e54cda462e2cd9a086d85cd9f20943ead92f575ce86885a43a565d5", size = 8042142, upload-time = "2025-08-30T00:13:39.426Z" }, + { url = "https://files.pythonhosted.org/packages/7c/58/e7b6d292beae6fb4283ca6fb7fa47d7c944a68062d6238c07b497dd35493/matplotlib-3.10.6-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:70aaf890ce1d0efd482df969b28a5b30ea0b891224bb315810a3940f67182899", size = 8273802, upload-time = "2025-08-30T00:13:41.006Z" }, + { url = "https://files.pythonhosted.org/packages/9f/f6/7882d05aba16a8cdd594fb9a03a9d3cca751dbb6816adf7b102945522ee9/matplotlib-3.10.6-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:1565aae810ab79cb72e402b22facfa6501365e73ebab70a0fdfb98488d2c3c0c", size = 8131365, upload-time = "2025-08-30T00:13:42.664Z" }, + { url = "https://files.pythonhosted.org/packages/94/bf/ff32f6ed76e78514e98775a53715eca4804b12bdcf35902cdd1cf759d324/matplotlib-3.10.6-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f3b23315a01981689aa4e1a179dbf6ef9fbd17143c3eea77548c2ecfb0499438", size = 9533961, upload-time = "2025-08-30T00:13:44.372Z" }, + { url = "https://files.pythonhosted.org/packages/fe/c3/6bf88c2fc2da7708a2ff8d2eeb5d68943130f50e636d5d3dcf9d4252e971/matplotlib-3.10.6-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:30fdd37edf41a4e6785f9b37969de57aea770696cb637d9946eb37470c94a453", size = 9804262, upload-time = "2025-08-30T00:13:46.614Z" }, + { url = "https://files.pythonhosted.org/packages/0f/7a/e05e6d9446d2d577b459427ad060cd2de5742d0e435db3191fea4fcc7e8b/matplotlib-3.10.6-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:bc31e693da1c08012c764b053e702c1855378e04102238e6a5ee6a7117c53a47", size = 9595508, upload-time = "2025-08-30T00:13:48.731Z" }, + { url = "https://files.pythonhosted.org/packages/39/fb/af09c463ced80b801629fd73b96f726c9f6124c3603aa2e480a061d6705b/matplotlib-3.10.6-cp314-cp314-win_amd64.whl", hash = "sha256:05be9bdaa8b242bc6ff96330d18c52f1fc59c6fb3a4dd411d953d67e7e1baf98", size = 8252742, upload-time = "2025-08-30T00:13:50.539Z" }, + { url = "https://files.pythonhosted.org/packages/b1/f9/b682f6db9396d9ab8f050c0a3bfbb5f14fb0f6518f08507c04cc02f8f229/matplotlib-3.10.6-cp314-cp314-win_arm64.whl", hash = "sha256:f56a0d1ab05d34c628592435781d185cd99630bdfd76822cd686fb5a0aecd43a", size = 8124237, upload-time = "2025-08-30T00:13:54.3Z" }, + { url = "https://files.pythonhosted.org/packages/b5/d2/b69b4a0923a3c05ab90527c60fdec899ee21ca23ede7f0fb818e6620d6f2/matplotlib-3.10.6-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:94f0b4cacb23763b64b5dace50d5b7bfe98710fed5f0cef5c08135a03399d98b", size = 8316956, upload-time = "2025-08-30T00:13:55.932Z" }, + { url = "https://files.pythonhosted.org/packages/28/e9/dc427b6f16457ffaeecb2fc4abf91e5adb8827861b869c7a7a6d1836fa73/matplotlib-3.10.6-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:cc332891306b9fb39462673d8225d1b824c89783fee82840a709f96714f17a5c", size = 8178260, upload-time = "2025-08-30T00:14:00.942Z" }, + { url = "https://files.pythonhosted.org/packages/c4/89/1fbd5ad611802c34d1c7ad04607e64a1350b7fb9c567c4ec2c19e066ed35/matplotlib-3.10.6-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ee1d607b3fb1590deb04b69f02ea1d53ed0b0bf75b2b1a5745f269afcbd3cdd3", size = 9541422, upload-time = "2025-08-30T00:14:02.664Z" }, + { url = "https://files.pythonhosted.org/packages/b0/3b/65fec8716025b22c1d72d5a82ea079934c76a547696eaa55be6866bc89b1/matplotlib-3.10.6-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:376a624a218116461696b27b2bbf7a8945053e6d799f6502fc03226d077807bf", size = 9803678, upload-time = "2025-08-30T00:14:04.741Z" }, + { url = "https://files.pythonhosted.org/packages/c7/b0/40fb2b3a1ab9381bb39a952e8390357c8be3bdadcf6d5055d9c31e1b35ae/matplotlib-3.10.6-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:83847b47f6524c34b4f2d3ce726bb0541c48c8e7692729865c3df75bfa0f495a", size = 9594077, upload-time = "2025-08-30T00:14:07.012Z" }, + { url = "https://files.pythonhosted.org/packages/76/34/c4b71b69edf5b06e635eee1ed10bfc73cf8df058b66e63e30e6a55e231d5/matplotlib-3.10.6-cp314-cp314t-win_amd64.whl", hash = "sha256:c7e0518e0d223683532a07f4b512e2e0729b62674f1b3a1a69869f98e6b1c7e3", size = 8342822, upload-time = "2025-08-30T00:14:09.041Z" }, + { url = "https://files.pythonhosted.org/packages/e8/62/aeabeef1a842b6226a30d49dd13e8a7a1e81e9ec98212c0b5169f0a12d83/matplotlib-3.10.6-cp314-cp314t-win_arm64.whl", hash = "sha256:4dd83e029f5b4801eeb87c64efd80e732452781c16a9cf7415b7b63ec8f374d7", size = 8172588, upload-time = "2025-08-30T00:14:11.166Z" }, + { url = "https://files.pythonhosted.org/packages/12/bb/02c35a51484aae5f49bd29f091286e7af5f3f677a9736c58a92b3c78baeb/matplotlib-3.10.6-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:f2d684c3204fa62421bbf770ddfebc6b50130f9cad65531eeba19236d73bb488", size = 8252296, upload-time = "2025-08-30T00:14:19.49Z" }, + { url = "https://files.pythonhosted.org/packages/7d/85/41701e3092005aee9a2445f5ee3904d9dbd4a7df7a45905ffef29b7ef098/matplotlib-3.10.6-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:6f4a69196e663a41d12a728fab8751177215357906436804217d6d9cf0d4d6cf", size = 8116749, upload-time = "2025-08-30T00:14:21.344Z" }, + { url = "https://files.pythonhosted.org/packages/16/53/8d8fa0ea32a8c8239e04d022f6c059ee5e1b77517769feccd50f1df43d6d/matplotlib-3.10.6-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:4d6ca6ef03dfd269f4ead566ec6f3fb9becf8dab146fb999022ed85ee9f6b3eb", size = 8693933, upload-time = "2025-08-30T00:14:22.942Z" }, ] [[package]] @@ -1091,11 +1107,11 @@ wheels = [ [[package]] name = "mistune" -version = "3.1.3" +version = "3.1.4" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/c4/79/bda47f7dd7c3c55770478d6d02c9960c430b0cf1773b72366ff89126ea31/mistune-3.1.3.tar.gz", hash = "sha256:a7035c21782b2becb6be62f8f25d3df81ccb4d6fa477a6525b15af06539f02a0", size = 94347, upload-time = "2025-03-19T14:27:24.955Z" } +sdist = { url = "https://files.pythonhosted.org/packages/d7/02/a7fb8b21d4d55ac93cdcde9d3638da5dd0ebdd3a4fed76c7725e10b81cbe/mistune-3.1.4.tar.gz", hash = "sha256:b5a7f801d389f724ec702840c11d8fc48f2b33519102fc7ee739e8177b672164", size = 94588, upload-time = "2025-08-29T07:20:43.594Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/01/4d/23c4e4f09da849e127e9f123241946c23c1e30f45a88366879e064211815/mistune-3.1.3-py3-none-any.whl", hash = "sha256:1a32314113cff28aa6432e99e522677c8587fd83e3d51c29b82a52409c842bd9", size = 53410, upload-time = "2025-03-19T14:27:23.451Z" }, + { url = "https://files.pythonhosted.org/packages/7a/f0/8282d9641415e9e33df173516226b404d367a0fc55e1a60424a152913abc/mistune-3.1.4-py3-none-any.whl", hash = "sha256:93691da911e5d9d2e23bc54472892aff676df27a75274962ff9edc210364266d", size = 53481, upload-time = "2025-08-29T07:20:42.218Z" }, ] [[package]] @@ -1361,7 +1377,7 @@ wheels = [ [[package]] name = "pandas" -version = "2.3.1" +version = "2.3.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "numpy" }, @@ -1369,35 +1385,35 @@ dependencies = [ { name = "pytz" }, { name = "tzdata" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/d1/6f/75aa71f8a14267117adeeed5d21b204770189c0a0025acbdc03c337b28fc/pandas-2.3.1.tar.gz", hash = "sha256:0a95b9ac964fe83ce317827f80304d37388ea77616b1425f0ae41c9d2d0d7bb2", size = 4487493, upload-time = "2025-07-07T19:20:04.079Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/76/1c/ccf70029e927e473a4476c00e0d5b32e623bff27f0402d0a92b7fc29bb9f/pandas-2.3.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2b0540963d83431f5ce8870ea02a7430adca100cec8a050f0811f8e31035541b", size = 11566608, upload-time = "2025-07-07T19:18:33.86Z" }, - { url = "https://files.pythonhosted.org/packages/ec/d3/3c37cb724d76a841f14b8f5fe57e5e3645207cc67370e4f84717e8bb7657/pandas-2.3.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fe7317f578c6a153912bd2292f02e40c1d8f253e93c599e82620c7f69755c74f", size = 10823181, upload-time = "2025-07-07T19:18:36.151Z" }, - { url = "https://files.pythonhosted.org/packages/8a/4c/367c98854a1251940edf54a4df0826dcacfb987f9068abf3e3064081a382/pandas-2.3.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e6723a27ad7b244c0c79d8e7007092d7c8f0f11305770e2f4cd778b3ad5f9f85", size = 11793570, upload-time = "2025-07-07T19:18:38.385Z" }, - { url = "https://files.pythonhosted.org/packages/07/5f/63760ff107bcf5146eee41b38b3985f9055e710a72fdd637b791dea3495c/pandas-2.3.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3462c3735fe19f2638f2c3a40bd94ec2dc5ba13abbb032dd2fa1f540a075509d", size = 12378887, upload-time = "2025-07-07T19:18:41.284Z" }, - { url = "https://files.pythonhosted.org/packages/15/53/f31a9b4dfe73fe4711c3a609bd8e60238022f48eacedc257cd13ae9327a7/pandas-2.3.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:98bcc8b5bf7afed22cc753a28bc4d9e26e078e777066bc53fac7904ddef9a678", size = 13230957, upload-time = "2025-07-07T19:18:44.187Z" }, - { url = "https://files.pythonhosted.org/packages/e0/94/6fce6bf85b5056d065e0a7933cba2616dcb48596f7ba3c6341ec4bcc529d/pandas-2.3.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:4d544806b485ddf29e52d75b1f559142514e60ef58a832f74fb38e48d757b299", size = 13883883, upload-time = "2025-07-07T19:18:46.498Z" }, - { url = "https://files.pythonhosted.org/packages/c8/7b/bdcb1ed8fccb63d04bdb7635161d0ec26596d92c9d7a6cce964e7876b6c1/pandas-2.3.1-cp311-cp311-win_amd64.whl", hash = "sha256:b3cd4273d3cb3707b6fffd217204c52ed92859533e31dc03b7c5008aa933aaab", size = 11340212, upload-time = "2025-07-07T19:18:49.293Z" }, - { url = "https://files.pythonhosted.org/packages/46/de/b8445e0f5d217a99fe0eeb2f4988070908979bec3587c0633e5428ab596c/pandas-2.3.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:689968e841136f9e542020698ee1c4fbe9caa2ed2213ae2388dc7b81721510d3", size = 11588172, upload-time = "2025-07-07T19:18:52.054Z" }, - { url = "https://files.pythonhosted.org/packages/1e/e0/801cdb3564e65a5ac041ab99ea6f1d802a6c325bb6e58c79c06a3f1cd010/pandas-2.3.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:025e92411c16cbe5bb2a4abc99732a6b132f439b8aab23a59fa593eb00704232", size = 10717365, upload-time = "2025-07-07T19:18:54.785Z" }, - { url = "https://files.pythonhosted.org/packages/51/a5/c76a8311833c24ae61a376dbf360eb1b1c9247a5d9c1e8b356563b31b80c/pandas-2.3.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9b7ff55f31c4fcb3e316e8f7fa194566b286d6ac430afec0d461163312c5841e", size = 11280411, upload-time = "2025-07-07T19:18:57.045Z" }, - { url = "https://files.pythonhosted.org/packages/da/01/e383018feba0a1ead6cf5fe8728e5d767fee02f06a3d800e82c489e5daaf/pandas-2.3.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7dcb79bf373a47d2a40cf7232928eb7540155abbc460925c2c96d2d30b006eb4", size = 11988013, upload-time = "2025-07-07T19:18:59.771Z" }, - { url = "https://files.pythonhosted.org/packages/5b/14/cec7760d7c9507f11c97d64f29022e12a6cc4fc03ac694535e89f88ad2ec/pandas-2.3.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:56a342b231e8862c96bdb6ab97170e203ce511f4d0429589c8ede1ee8ece48b8", size = 12767210, upload-time = "2025-07-07T19:19:02.944Z" }, - { url = "https://files.pythonhosted.org/packages/50/b9/6e2d2c6728ed29fb3d4d4d302504fb66f1a543e37eb2e43f352a86365cdf/pandas-2.3.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ca7ed14832bce68baef331f4d7f294411bed8efd032f8109d690df45e00c4679", size = 13440571, upload-time = "2025-07-07T19:19:06.82Z" }, - { url = "https://files.pythonhosted.org/packages/80/a5/3a92893e7399a691bad7664d977cb5e7c81cf666c81f89ea76ba2bff483d/pandas-2.3.1-cp312-cp312-win_amd64.whl", hash = "sha256:ac942bfd0aca577bef61f2bc8da8147c4ef6879965ef883d8e8d5d2dc3e744b8", size = 10987601, upload-time = "2025-07-07T19:19:09.589Z" }, - { url = "https://files.pythonhosted.org/packages/32/ed/ff0a67a2c5505e1854e6715586ac6693dd860fbf52ef9f81edee200266e7/pandas-2.3.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:9026bd4a80108fac2239294a15ef9003c4ee191a0f64b90f170b40cfb7cf2d22", size = 11531393, upload-time = "2025-07-07T19:19:12.245Z" }, - { url = "https://files.pythonhosted.org/packages/c7/db/d8f24a7cc9fb0972adab0cc80b6817e8bef888cfd0024eeb5a21c0bb5c4a/pandas-2.3.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:6de8547d4fdb12421e2d047a2c446c623ff4c11f47fddb6b9169eb98ffba485a", size = 10668750, upload-time = "2025-07-07T19:19:14.612Z" }, - { url = "https://files.pythonhosted.org/packages/0f/b0/80f6ec783313f1e2356b28b4fd8d2148c378370045da918c73145e6aab50/pandas-2.3.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:782647ddc63c83133b2506912cc6b108140a38a37292102aaa19c81c83db2928", size = 11342004, upload-time = "2025-07-07T19:19:16.857Z" }, - { url = "https://files.pythonhosted.org/packages/e9/e2/20a317688435470872885e7fc8f95109ae9683dec7c50be29b56911515a5/pandas-2.3.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2ba6aff74075311fc88504b1db890187a3cd0f887a5b10f5525f8e2ef55bfdb9", size = 12050869, upload-time = "2025-07-07T19:19:19.265Z" }, - { url = "https://files.pythonhosted.org/packages/55/79/20d746b0a96c67203a5bee5fb4e00ac49c3e8009a39e1f78de264ecc5729/pandas-2.3.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:e5635178b387bd2ba4ac040f82bc2ef6e6b500483975c4ebacd34bec945fda12", size = 12750218, upload-time = "2025-07-07T19:19:21.547Z" }, - { url = "https://files.pythonhosted.org/packages/7c/0f/145c8b41e48dbf03dd18fdd7f24f8ba95b8254a97a3379048378f33e7838/pandas-2.3.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6f3bf5ec947526106399a9e1d26d40ee2b259c66422efdf4de63c848492d91bb", size = 13416763, upload-time = "2025-07-07T19:19:23.939Z" }, - { url = "https://files.pythonhosted.org/packages/b2/c0/54415af59db5cdd86a3d3bf79863e8cc3fa9ed265f0745254061ac09d5f2/pandas-2.3.1-cp313-cp313-win_amd64.whl", hash = "sha256:1c78cf43c8fde236342a1cb2c34bcff89564a7bfed7e474ed2fffa6aed03a956", size = 10987482, upload-time = "2025-07-07T19:19:42.699Z" }, - { url = "https://files.pythonhosted.org/packages/48/64/2fd2e400073a1230e13b8cd604c9bc95d9e3b962e5d44088ead2e8f0cfec/pandas-2.3.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:8dfc17328e8da77be3cf9f47509e5637ba8f137148ed0e9b5241e1baf526e20a", size = 12029159, upload-time = "2025-07-07T19:19:26.362Z" }, - { url = "https://files.pythonhosted.org/packages/d8/0a/d84fd79b0293b7ef88c760d7dca69828d867c89b6d9bc52d6a27e4d87316/pandas-2.3.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:ec6c851509364c59a5344458ab935e6451b31b818be467eb24b0fe89bd05b6b9", size = 11393287, upload-time = "2025-07-07T19:19:29.157Z" }, - { url = "https://files.pythonhosted.org/packages/50/ae/ff885d2b6e88f3c7520bb74ba319268b42f05d7e583b5dded9837da2723f/pandas-2.3.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:911580460fc4884d9b05254b38a6bfadddfcc6aaef856fb5859e7ca202e45275", size = 11309381, upload-time = "2025-07-07T19:19:31.436Z" }, - { url = "https://files.pythonhosted.org/packages/85/86/1fa345fc17caf5d7780d2699985c03dbe186c68fee00b526813939062bb0/pandas-2.3.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2f4d6feeba91744872a600e6edbbd5b033005b431d5ae8379abee5bcfa479fab", size = 11883998, upload-time = "2025-07-07T19:19:34.267Z" }, - { url = "https://files.pythonhosted.org/packages/81/aa/e58541a49b5e6310d89474333e994ee57fea97c8aaa8fc7f00b873059bbf/pandas-2.3.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:fe37e757f462d31a9cd7580236a82f353f5713a80e059a29753cf938c6775d96", size = 12704705, upload-time = "2025-07-07T19:19:36.856Z" }, - { url = "https://files.pythonhosted.org/packages/d5/f9/07086f5b0f2a19872554abeea7658200824f5835c58a106fa8f2ae96a46c/pandas-2.3.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:5db9637dbc24b631ff3707269ae4559bce4b7fd75c1c4d7e13f40edc42df4444", size = 13189044, upload-time = "2025-07-07T19:19:39.999Z" }, +sdist = { url = "https://files.pythonhosted.org/packages/79/8e/0e90233ac205ad182bd6b422532695d2b9414944a280488105d598c70023/pandas-2.3.2.tar.gz", hash = "sha256:ab7b58f8f82706890924ccdfb5f48002b83d2b5a3845976a9fb705d36c34dcdb", size = 4488684, upload-time = "2025-08-21T10:28:29.257Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7a/59/f3e010879f118c2d400902d2d871c2226cef29b08c09fb8dc41111730400/pandas-2.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1333e9c299adcbb68ee89a9bb568fc3f20f9cbb419f1dd5225071e6cddb2a743", size = 11563308, upload-time = "2025-08-21T10:26:56.656Z" }, + { url = "https://files.pythonhosted.org/packages/38/18/48f10f1cc5c397af59571d638d211f494dba481f449c19adbd282aa8f4ca/pandas-2.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:76972bcbd7de8e91ad5f0ca884a9f2c477a2125354af624e022c49e5bd0dfff4", size = 10820319, upload-time = "2025-08-21T10:26:59.162Z" }, + { url = "https://files.pythonhosted.org/packages/95/3b/1e9b69632898b048e223834cd9702052bcf06b15e1ae716eda3196fb972e/pandas-2.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b98bdd7c456a05eef7cd21fd6b29e3ca243591fe531c62be94a2cc987efb5ac2", size = 11790097, upload-time = "2025-08-21T10:27:02.204Z" }, + { url = "https://files.pythonhosted.org/packages/8b/ef/0e2ffb30b1f7fbc9a588bd01e3c14a0d96854d09a887e15e30cc19961227/pandas-2.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1d81573b3f7db40d020983f78721e9bfc425f411e616ef019a10ebf597aedb2e", size = 12397958, upload-time = "2025-08-21T10:27:05.409Z" }, + { url = "https://files.pythonhosted.org/packages/23/82/e6b85f0d92e9afb0e7f705a51d1399b79c7380c19687bfbf3d2837743249/pandas-2.3.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:e190b738675a73b581736cc8ec71ae113d6c3768d0bd18bffa5b9a0927b0b6ea", size = 13225600, upload-time = "2025-08-21T10:27:07.791Z" }, + { url = "https://files.pythonhosted.org/packages/e8/f1/f682015893d9ed51611948bd83683670842286a8edd4f68c2c1c3b231eef/pandas-2.3.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:c253828cb08f47488d60f43c5fc95114c771bbfff085da54bfc79cb4f9e3a372", size = 13879433, upload-time = "2025-08-21T10:27:10.347Z" }, + { url = "https://files.pythonhosted.org/packages/a7/e7/ae86261695b6c8a36d6a4c8d5f9b9ede8248510d689a2f379a18354b37d7/pandas-2.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:9467697b8083f9667b212633ad6aa4ab32436dcbaf4cd57325debb0ddef2012f", size = 11336557, upload-time = "2025-08-21T10:27:12.983Z" }, + { url = "https://files.pythonhosted.org/packages/ec/db/614c20fb7a85a14828edd23f1c02db58a30abf3ce76f38806155d160313c/pandas-2.3.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:3fbb977f802156e7a3f829e9d1d5398f6192375a3e2d1a9ee0803e35fe70a2b9", size = 11587652, upload-time = "2025-08-21T10:27:15.888Z" }, + { url = "https://files.pythonhosted.org/packages/99/b0/756e52f6582cade5e746f19bad0517ff27ba9c73404607c0306585c201b3/pandas-2.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1b9b52693123dd234b7c985c68b709b0b009f4521000d0525f2b95c22f15944b", size = 10717686, upload-time = "2025-08-21T10:27:18.486Z" }, + { url = "https://files.pythonhosted.org/packages/37/4c/dd5ccc1e357abfeee8353123282de17997f90ff67855f86154e5a13b81e5/pandas-2.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0bd281310d4f412733f319a5bc552f86d62cddc5f51d2e392c8787335c994175", size = 11278722, upload-time = "2025-08-21T10:27:21.149Z" }, + { url = "https://files.pythonhosted.org/packages/d3/a4/f7edcfa47e0a88cda0be8b068a5bae710bf264f867edfdf7b71584ace362/pandas-2.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:96d31a6b4354e3b9b8a2c848af75d31da390657e3ac6f30c05c82068b9ed79b9", size = 11987803, upload-time = "2025-08-21T10:27:23.767Z" }, + { url = "https://files.pythonhosted.org/packages/f6/61/1bce4129f93ab66f1c68b7ed1c12bac6a70b1b56c5dab359c6bbcd480b52/pandas-2.3.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:df4df0b9d02bb873a106971bb85d448378ef14b86ba96f035f50bbd3688456b4", size = 12766345, upload-time = "2025-08-21T10:27:26.6Z" }, + { url = "https://files.pythonhosted.org/packages/8e/46/80d53de70fee835531da3a1dae827a1e76e77a43ad22a8cd0f8142b61587/pandas-2.3.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:213a5adf93d020b74327cb2c1b842884dbdd37f895f42dcc2f09d451d949f811", size = 13439314, upload-time = "2025-08-21T10:27:29.213Z" }, + { url = "https://files.pythonhosted.org/packages/28/30/8114832daff7489f179971dbc1d854109b7f4365a546e3ea75b6516cea95/pandas-2.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:8c13b81a9347eb8c7548f53fd9a4f08d4dfe996836543f805c987bafa03317ae", size = 10983326, upload-time = "2025-08-21T10:27:31.901Z" }, + { url = "https://files.pythonhosted.org/packages/27/64/a2f7bf678af502e16b472527735d168b22b7824e45a4d7e96a4fbb634b59/pandas-2.3.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0c6ecbac99a354a051ef21c5307601093cb9e0f4b1855984a084bfec9302699e", size = 11531061, upload-time = "2025-08-21T10:27:34.647Z" }, + { url = "https://files.pythonhosted.org/packages/54/4c/c3d21b2b7769ef2f4c2b9299fcadd601efa6729f1357a8dbce8dd949ed70/pandas-2.3.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:c6f048aa0fd080d6a06cc7e7537c09b53be6642d330ac6f54a600c3ace857ee9", size = 10668666, upload-time = "2025-08-21T10:27:37.203Z" }, + { url = "https://files.pythonhosted.org/packages/50/e2/f775ba76ecfb3424d7f5862620841cf0edb592e9abd2d2a5387d305fe7a8/pandas-2.3.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0064187b80a5be6f2f9c9d6bdde29372468751dfa89f4211a3c5871854cfbf7a", size = 11332835, upload-time = "2025-08-21T10:27:40.188Z" }, + { url = "https://files.pythonhosted.org/packages/8f/52/0634adaace9be2d8cac9ef78f05c47f3a675882e068438b9d7ec7ef0c13f/pandas-2.3.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4ac8c320bded4718b298281339c1a50fb00a6ba78cb2a63521c39bec95b0209b", size = 12057211, upload-time = "2025-08-21T10:27:43.117Z" }, + { url = "https://files.pythonhosted.org/packages/0b/9d/2df913f14b2deb9c748975fdb2491da1a78773debb25abbc7cbc67c6b549/pandas-2.3.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:114c2fe4f4328cf98ce5716d1532f3ab79c5919f95a9cfee81d9140064a2e4d6", size = 12749277, upload-time = "2025-08-21T10:27:45.474Z" }, + { url = "https://files.pythonhosted.org/packages/87/af/da1a2417026bd14d98c236dba88e39837182459d29dcfcea510b2ac9e8a1/pandas-2.3.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:48fa91c4dfb3b2b9bfdb5c24cd3567575f4e13f9636810462ffed8925352be5a", size = 13415256, upload-time = "2025-08-21T10:27:49.885Z" }, + { url = "https://files.pythonhosted.org/packages/22/3c/f2af1ce8840ef648584a6156489636b5692c162771918aa95707c165ad2b/pandas-2.3.2-cp313-cp313-win_amd64.whl", hash = "sha256:12d039facec710f7ba305786837d0225a3444af7bbd9c15c32ca2d40d157ed8b", size = 10982579, upload-time = "2025-08-21T10:28:08.435Z" }, + { url = "https://files.pythonhosted.org/packages/f3/98/8df69c4097a6719e357dc249bf437b8efbde808038268e584421696cbddf/pandas-2.3.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:c624b615ce97864eb588779ed4046186f967374185c047070545253a52ab2d57", size = 12028163, upload-time = "2025-08-21T10:27:52.232Z" }, + { url = "https://files.pythonhosted.org/packages/0e/23/f95cbcbea319f349e10ff90db488b905c6883f03cbabd34f6b03cbc3c044/pandas-2.3.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:0cee69d583b9b128823d9514171cabb6861e09409af805b54459bd0c821a35c2", size = 11391860, upload-time = "2025-08-21T10:27:54.673Z" }, + { url = "https://files.pythonhosted.org/packages/ad/1b/6a984e98c4abee22058aa75bfb8eb90dce58cf8d7296f8bc56c14bc330b0/pandas-2.3.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2319656ed81124982900b4c37f0e0c58c015af9a7bbc62342ba5ad07ace82ba9", size = 11309830, upload-time = "2025-08-21T10:27:56.957Z" }, + { url = "https://files.pythonhosted.org/packages/15/d5/f0486090eb18dd8710bf60afeaf638ba6817047c0c8ae5c6a25598665609/pandas-2.3.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b37205ad6f00d52f16b6d09f406434ba928c1a1966e2771006a9033c736d30d2", size = 11883216, upload-time = "2025-08-21T10:27:59.302Z" }, + { url = "https://files.pythonhosted.org/packages/10/86/692050c119696da19e20245bbd650d8dfca6ceb577da027c3a73c62a047e/pandas-2.3.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:837248b4fc3a9b83b9c6214699a13f069dc13510a6a6d7f9ba33145d2841a012", size = 12699743, upload-time = "2025-08-21T10:28:02.447Z" }, + { url = "https://files.pythonhosted.org/packages/cd/d7/612123674d7b17cf345aad0a10289b2a384bff404e0463a83c4a3a59d205/pandas-2.3.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:d2c3554bd31b731cd6490d94a28f3abb8dd770634a9e06eb6d2911b9827db370", size = 13186141, upload-time = "2025-08-21T10:28:05.377Z" }, ] [[package]] @@ -1411,11 +1427,11 @@ wheels = [ [[package]] name = "parso" -version = "0.8.4" +version = "0.8.5" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/66/94/68e2e17afaa9169cf6412ab0f28623903be73d1b32e208d9e8e541bb086d/parso-0.8.4.tar.gz", hash = "sha256:eb3a7b58240fb99099a345571deecc0f9540ea5f4dd2fe14c2a99d6b281ab92d", size = 400609, upload-time = "2024-04-05T09:43:55.897Z" } +sdist = { url = "https://files.pythonhosted.org/packages/d4/de/53e0bcf53d13e005bd8c92e7855142494f41171b34c2536b86187474184d/parso-0.8.5.tar.gz", hash = "sha256:034d7354a9a018bdce352f48b2a8a450f05e9d6ee85db84764e9b6bd96dafe5a", size = 401205, upload-time = "2025-08-23T15:15:28.028Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/c6/ac/dac4a63f978e4dcb3c6d3a78c4d8e0192a113d288502a1216950c41b1027/parso-0.8.4-py2.py3-none-any.whl", hash = "sha256:a418670a20291dacd2dddc80c377c5c3791378ee1e8d12bffc35420643d43f18", size = 103650, upload-time = "2024-04-05T09:43:53.299Z" }, + { url = "https://files.pythonhosted.org/packages/16/32/f8e3c85d1d5250232a5d3477a2a28cc291968ff175caeadaf3cc19ce0e4a/parso-0.8.5-py2.py3-none-any.whl", hash = "sha256:646204b5ee239c396d040b90f9e272e9a8017c630092bf59980beb62fd033887", size = 106668, upload-time = "2025-08-23T15:15:25.663Z" }, ] [[package]] @@ -1659,11 +1675,11 @@ wheels = [ [[package]] name = "platformdirs" -version = "4.3.8" +version = "4.4.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/fe/8b/3c73abc9c759ecd3f1f7ceff6685840859e8070c4d947c93fae71f6a0bf2/platformdirs-4.3.8.tar.gz", hash = "sha256:3d512d96e16bcb959a814c9f348431070822a6496326a4be0911c40b5a74c2bc", size = 21362, upload-time = "2025-05-07T22:47:42.121Z" } +sdist = { url = "https://files.pythonhosted.org/packages/23/e8/21db9c9987b0e728855bd57bff6984f67952bea55d6f75e055c46b5383e8/platformdirs-4.4.0.tar.gz", hash = "sha256:ca753cf4d81dc309bc67b0ea38fd15dc97bc30ce419a7f58d13eb3bf14c4febf", size = 21634, upload-time = "2025-08-26T14:32:04.268Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/fe/39/979e8e21520d4e47a0bbe349e2713c0aac6f3d853d0e5b34d76206c439aa/platformdirs-4.3.8-py3-none-any.whl", hash = "sha256:ff7059bb7eb1179e2685604f4aaf157cfd9535242bd23742eadc3c13542139b4", size = 18567, upload-time = "2025-05-07T22:47:40.376Z" }, + { url = "https://files.pythonhosted.org/packages/40/4b/2028861e724d3bd36227adfa20d3fd24c3fc6d52032f4a93c133be5d17ce/platformdirs-4.4.0-py3-none-any.whl", hash = "sha256:abd01743f24e5287cd7a5db3752faf1a2d65353f38ec26d98e25a6db65958c85", size = 18654, upload-time = "2025-08-26T14:32:02.735Z" }, ] [[package]] @@ -1677,14 +1693,14 @@ wheels = [ [[package]] name = "prompt-toolkit" -version = "3.0.51" +version = "3.0.52" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "wcwidth" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/bb/6e/9d084c929dfe9e3bfe0c6a47e31f78a25c54627d64a66e884a8bf5474f1c/prompt_toolkit-3.0.51.tar.gz", hash = "sha256:931a162e3b27fc90c86f1b48bb1fb2c528c2761475e57c9c06de13311c7b54ed", size = 428940, upload-time = "2025-04-15T09:18:47.731Z" } +sdist = { url = "https://files.pythonhosted.org/packages/a1/96/06e01a7b38dce6fe1db213e061a4602dd6032a8a97ef6c1a862537732421/prompt_toolkit-3.0.52.tar.gz", hash = "sha256:28cde192929c8e7321de85de1ddbe736f1375148b02f2e17edd840042b1be855", size = 434198, upload-time = "2025-08-27T15:24:02.057Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ce/4f/5249960887b1fbe561d9ff265496d170b55a735b76724f10ef19f9e40716/prompt_toolkit-3.0.51-py3-none-any.whl", hash = "sha256:52742911fde84e2d423e2f9a4cf1de7d7ac4e51958f648d9540e0fb8db077b07", size = 387810, upload-time = "2025-04-15T09:18:44.753Z" }, + { url = "https://files.pythonhosted.org/packages/84/03/0d3ce49e2505ae70cf43bc5bb3033955d2fc9f932163e84dc0779cc47f48/prompt_toolkit-3.0.52-py3-none-any.whl", hash = "sha256:9aac639a3bbd33284347de5ad8d68ecc044b91a762dc39b7c21095fcd6a19955", size = 391431, upload-time = "2025-08-27T15:23:59.498Z" }, ] [[package]] @@ -1862,15 +1878,15 @@ wheels = [ [[package]] name = "pytest-rerunfailures" -version = "15.1" +version = "16.0.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "packaging" }, { name = "pytest" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/a0/78/e6e358545537a8e82c4dc91e72ec0d6f80546a3786dd27c76b06ca09db77/pytest_rerunfailures-15.1.tar.gz", hash = "sha256:c6040368abd7b8138c5b67288be17d6e5611b7368755ce0465dda0362c8ece80", size = 26981, upload-time = "2025-05-08T06:36:33.483Z" } +sdist = { url = "https://files.pythonhosted.org/packages/26/53/a543a76f922a5337d10df22441af8bf68f1b421cadf9aedf8a77943b81f6/pytest_rerunfailures-16.0.1.tar.gz", hash = "sha256:ed4b3a6e7badb0a720ddd93f9de1e124ba99a0cb13bc88561b3c168c16062559", size = 27612, upload-time = "2025-09-02T06:48:25.193Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/f3/30/11d836ff01c938969efa319b4ebe2374ed79d28043a12bfc908577aab9f3/pytest_rerunfailures-15.1-py3-none-any.whl", hash = "sha256:f674c3594845aba8b23c78e99b1ff8068556cc6a8b277f728071fdc4f4b0b355", size = 13274, upload-time = "2025-05-08T06:36:32.029Z" }, + { url = "https://files.pythonhosted.org/packages/38/73/67dc14cda1942914e70fbb117fceaf11e259362c517bdadd76b0dd752524/pytest_rerunfailures-16.0.1-py3-none-any.whl", hash = "sha256:0bccc0e3b0e3388275c25a100f7077081318196569a121217688ed05e58984b9", size = 13610, upload-time = "2025-09-02T06:48:23.615Z" }, ] [[package]] @@ -1963,60 +1979,60 @@ wheels = [ [[package]] name = "pyzmq" -version = "27.0.1" +version = "27.0.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "cffi", marker = "implementation_name == 'pypy'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/30/5f/557d2032a2f471edbcc227da724c24a1c05887b5cda1e3ae53af98b9e0a5/pyzmq-27.0.1.tar.gz", hash = "sha256:45c549204bc20e7484ffd2555f6cf02e572440ecf2f3bdd60d4404b20fddf64b", size = 281158, upload-time = "2025-08-03T05:05:40.352Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/ae/18/a8e0da6ababbe9326116fb1c890bf1920eea880e8da621afb6bc0f39a262/pyzmq-27.0.1-cp311-cp311-macosx_10_15_universal2.whl", hash = "sha256:9729190bd770314f5fbba42476abf6abe79a746eeda11d1d68fd56dd70e5c296", size = 1332721, upload-time = "2025-08-03T05:03:15.237Z" }, - { url = "https://files.pythonhosted.org/packages/75/a4/9431ba598651d60ebd50dc25755402b770322cf8432adcc07d2906e53a54/pyzmq-27.0.1-cp311-cp311-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:696900ef6bc20bef6a242973943574f96c3f97d2183c1bd3da5eea4f559631b1", size = 908249, upload-time = "2025-08-03T05:03:16.933Z" }, - { url = "https://files.pythonhosted.org/packages/f0/7a/e624e1793689e4e685d2ee21c40277dd4024d9d730af20446d88f69be838/pyzmq-27.0.1-cp311-cp311-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f96a63aecec22d3f7fdea3c6c98df9e42973f5856bb6812c3d8d78c262fee808", size = 668649, upload-time = "2025-08-03T05:03:18.49Z" }, - { url = "https://files.pythonhosted.org/packages/6c/29/0652a39d4e876e0d61379047ecf7752685414ad2e253434348246f7a2a39/pyzmq-27.0.1-cp311-cp311-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c512824360ea7490390566ce00bee880e19b526b312b25cc0bc30a0fe95cb67f", size = 856601, upload-time = "2025-08-03T05:03:20.194Z" }, - { url = "https://files.pythonhosted.org/packages/36/2d/8d5355d7fc55bb6e9c581dd74f58b64fa78c994079e3a0ea09b1b5627cde/pyzmq-27.0.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:dfb2bb5e0f7198eaacfb6796fb0330afd28f36d985a770745fba554a5903595a", size = 1657750, upload-time = "2025-08-03T05:03:22.055Z" }, - { url = "https://files.pythonhosted.org/packages/ab/f4/cd032352d5d252dc6f5ee272a34b59718ba3af1639a8a4ef4654f9535cf5/pyzmq-27.0.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:4f6886c59ba93ffde09b957d3e857e7950c8fe818bd5494d9b4287bc6d5bc7f1", size = 2034312, upload-time = "2025-08-03T05:03:23.578Z" }, - { url = "https://files.pythonhosted.org/packages/e4/1a/c050d8b6597200e97a4bd29b93c769d002fa0b03083858227e0376ad59bc/pyzmq-27.0.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b99ea9d330e86ce1ff7f2456b33f1bf81c43862a5590faf4ef4ed3a63504bdab", size = 1893632, upload-time = "2025-08-03T05:03:25.167Z" }, - { url = "https://files.pythonhosted.org/packages/6a/29/173ce21d5097e7fcf284a090e8beb64fc683c6582b1f00fa52b1b7e867ce/pyzmq-27.0.1-cp311-cp311-win32.whl", hash = "sha256:571f762aed89025ba8cdcbe355fea56889715ec06d0264fd8b6a3f3fa38154ed", size = 566587, upload-time = "2025-08-03T05:03:26.769Z" }, - { url = "https://files.pythonhosted.org/packages/53/ab/22bd33e7086f0a2cc03a5adabff4bde414288bb62a21a7820951ef86ec20/pyzmq-27.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:ee16906c8025fa464bea1e48128c048d02359fb40bebe5333103228528506530", size = 632873, upload-time = "2025-08-03T05:03:28.685Z" }, - { url = "https://files.pythonhosted.org/packages/90/14/3e59b4a28194285ceeff725eba9aa5ba8568d1cb78aed381dec1537c705a/pyzmq-27.0.1-cp311-cp311-win_arm64.whl", hash = "sha256:ba068f28028849da725ff9185c24f832ccf9207a40f9b28ac46ab7c04994bd41", size = 558918, upload-time = "2025-08-03T05:03:30.085Z" }, - { url = "https://files.pythonhosted.org/packages/0e/9b/c0957041067c7724b310f22c398be46399297c12ed834c3bc42200a2756f/pyzmq-27.0.1-cp312-abi3-macosx_10_15_universal2.whl", hash = "sha256:af7ebce2a1e7caf30c0bb64a845f63a69e76a2fadbc1cac47178f7bb6e657bdd", size = 1305432, upload-time = "2025-08-03T05:03:32.177Z" }, - { url = "https://files.pythonhosted.org/packages/8e/55/bd3a312790858f16b7def3897a0c3eb1804e974711bf7b9dcb5f47e7f82c/pyzmq-27.0.1-cp312-abi3-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:8f617f60a8b609a13099b313e7e525e67f84ef4524b6acad396d9ff153f6e4cd", size = 895095, upload-time = "2025-08-03T05:03:33.918Z" }, - { url = "https://files.pythonhosted.org/packages/20/50/fc384631d8282809fb1029a4460d2fe90fa0370a0e866a8318ed75c8d3bb/pyzmq-27.0.1-cp312-abi3-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1d59dad4173dc2a111f03e59315c7bd6e73da1a9d20a84a25cf08325b0582b1a", size = 651826, upload-time = "2025-08-03T05:03:35.818Z" }, - { url = "https://files.pythonhosted.org/packages/7e/0a/2356305c423a975000867de56888b79e44ec2192c690ff93c3109fd78081/pyzmq-27.0.1-cp312-abi3-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f5b6133c8d313bde8bd0d123c169d22525300ff164c2189f849de495e1344577", size = 839751, upload-time = "2025-08-03T05:03:37.265Z" }, - { url = "https://files.pythonhosted.org/packages/d7/1b/81e95ad256ca7e7ccd47f5294c1c6da6e2b64fbace65b84fe8a41470342e/pyzmq-27.0.1-cp312-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:58cca552567423f04d06a075f4b473e78ab5bdb906febe56bf4797633f54aa4e", size = 1641359, upload-time = "2025-08-03T05:03:38.799Z" }, - { url = "https://files.pythonhosted.org/packages/50/63/9f50ec965285f4e92c265c8f18344e46b12803666d8b73b65d254d441435/pyzmq-27.0.1-cp312-abi3-musllinux_1_2_i686.whl", hash = "sha256:4b9d8e26fb600d0d69cc9933e20af08552e97cc868a183d38a5c0d661e40dfbb", size = 2020281, upload-time = "2025-08-03T05:03:40.338Z" }, - { url = "https://files.pythonhosted.org/packages/02/4a/19e3398d0dc66ad2b463e4afa1fc541d697d7bc090305f9dfb948d3dfa29/pyzmq-27.0.1-cp312-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:2329f0c87f0466dce45bba32b63f47018dda5ca40a0085cc5c8558fea7d9fc55", size = 1877112, upload-time = "2025-08-03T05:03:42.012Z" }, - { url = "https://files.pythonhosted.org/packages/bf/42/c562e9151aa90ed1d70aac381ea22a929d6b3a2ce4e1d6e2e135d34fd9c6/pyzmq-27.0.1-cp312-abi3-win32.whl", hash = "sha256:57bb92abdb48467b89c2d21da1ab01a07d0745e536d62afd2e30d5acbd0092eb", size = 558177, upload-time = "2025-08-03T05:03:43.979Z" }, - { url = "https://files.pythonhosted.org/packages/40/96/5c50a7d2d2b05b19994bf7336b97db254299353dd9b49b565bb71b485f03/pyzmq-27.0.1-cp312-abi3-win_amd64.whl", hash = "sha256:ff3f8757570e45da7a5bedaa140489846510014f7a9d5ee9301c61f3f1b8a686", size = 618923, upload-time = "2025-08-03T05:03:45.438Z" }, - { url = "https://files.pythonhosted.org/packages/13/33/1ec89c8f21c89d21a2eaff7def3676e21d8248d2675705e72554fb5a6f3f/pyzmq-27.0.1-cp312-abi3-win_arm64.whl", hash = "sha256:df2c55c958d3766bdb3e9d858b911288acec09a9aab15883f384fc7180df5bed", size = 552358, upload-time = "2025-08-03T05:03:46.887Z" }, - { url = "https://files.pythonhosted.org/packages/6c/a0/f26e276211ec8090a4d11e4ec70eb8a8b15781e591c1d44ce62f372963a0/pyzmq-27.0.1-cp313-cp313-android_24_arm64_v8a.whl", hash = "sha256:497bd8af534ae55dc4ef67eebd1c149ff2a0b0f1e146db73c8b5a53d83c1a5f5", size = 1122287, upload-time = "2025-08-03T05:03:48.838Z" }, - { url = "https://files.pythonhosted.org/packages/9c/d8/af4b507e4f7eeea478cc8ee873995a6fd55582bfb99140593ed460e1db3c/pyzmq-27.0.1-cp313-cp313-android_24_x86_64.whl", hash = "sha256:a066ea6ad6218b4c233906adf0ae67830f451ed238419c0db609310dd781fbe7", size = 1155756, upload-time = "2025-08-03T05:03:50.907Z" }, - { url = "https://files.pythonhosted.org/packages/ac/55/37fae0013e11f88681da42698e550b08a316d608242551f65095cc99232a/pyzmq-27.0.1-cp313-cp313t-macosx_10_15_universal2.whl", hash = "sha256:72d235d6365ca73d8ce92f7425065d70f5c1e19baa458eb3f0d570e425b73a96", size = 1340826, upload-time = "2025-08-03T05:03:52.568Z" }, - { url = "https://files.pythonhosted.org/packages/f2/e4/3a87854c64b26fcf63a9d1b6f4382bd727d4797c772ceb334a97b7489be9/pyzmq-27.0.1-cp313-cp313t-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:313a7b374e3dc64848644ca348a51004b41726f768b02e17e689f1322366a4d9", size = 897283, upload-time = "2025-08-03T05:03:54.167Z" }, - { url = "https://files.pythonhosted.org/packages/17/3e/4296c6b0ad2d07be11ae1395dccf9cae48a0a655cf9be1c3733ad2b591d1/pyzmq-27.0.1-cp313-cp313t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:119ce8590409702394f959c159d048002cbed2f3c0645ec9d6a88087fc70f0f1", size = 660565, upload-time = "2025-08-03T05:03:56.152Z" }, - { url = "https://files.pythonhosted.org/packages/72/41/a33ba3aa48b45b23c4cd4ac49aafde46f3e0f81939f2bfb3b6171a437122/pyzmq-27.0.1-cp313-cp313t-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:45c3e00ce16896ace2cd770ab9057a7cf97d4613ea5f2a13f815141d8b6894b9", size = 847680, upload-time = "2025-08-03T05:03:57.696Z" }, - { url = "https://files.pythonhosted.org/packages/3f/8c/bf2350bb25b3b58d2e5b5d2290ffab0e923f0cc6d02288d3fbf4baa6e4d1/pyzmq-27.0.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:678e50ec112bdc6df5a83ac259a55a4ba97a8b314c325ab26b3b5b071151bc61", size = 1650151, upload-time = "2025-08-03T05:03:59.387Z" }, - { url = "https://files.pythonhosted.org/packages/f7/1a/a5a07c54890891344a8ddc3d5ab320dd3c4e39febb6e4472546e456d5157/pyzmq-27.0.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:d0b96c30be9f9387b18b18b6133c75a7b1b0065da64e150fe1feb5ebf31ece1c", size = 2023766, upload-time = "2025-08-03T05:04:01.883Z" }, - { url = "https://files.pythonhosted.org/packages/62/5e/514dcff08f02c6c8a45a6e23621901139cf853be7ac5ccd0b9407c3aa3de/pyzmq-27.0.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:88dc92d9eb5ea4968123e74db146d770b0c8d48f0e2bfb1dbc6c50a8edb12d64", size = 1885195, upload-time = "2025-08-03T05:04:03.923Z" }, - { url = "https://files.pythonhosted.org/packages/c8/91/87f74f98a487fbef0b115f6025e4a295129fd56b2b633a03ba7d5816ecc2/pyzmq-27.0.1-cp313-cp313t-win32.whl", hash = "sha256:6dcbcb34f5c9b0cefdfc71ff745459241b7d3cda5b27c7ad69d45afc0821d1e1", size = 574213, upload-time = "2025-08-03T05:04:05.905Z" }, - { url = "https://files.pythonhosted.org/packages/e6/d7/07f7d0d7f4c81e08be7b60e52ff2591c557377c017f96204d33d5fca1b07/pyzmq-27.0.1-cp313-cp313t-win_amd64.whl", hash = "sha256:b9fd0fda730461f510cfd9a40fafa5355d65f5e3dbdd8d6dfa342b5b3f5d1949", size = 640202, upload-time = "2025-08-03T05:04:07.439Z" }, - { url = "https://files.pythonhosted.org/packages/ab/83/21d66bcef6fb803647a223cbde95111b099e2176277c0cbc8b099c485510/pyzmq-27.0.1-cp313-cp313t-win_arm64.whl", hash = "sha256:56a3b1853f3954ec1f0e91085f1350cc57d18f11205e4ab6e83e4b7c414120e0", size = 561514, upload-time = "2025-08-03T05:04:09.071Z" }, - { url = "https://files.pythonhosted.org/packages/5a/0b/d5ea75cf46b52cdce85a85200c963cb498932953df443892238be49b1a01/pyzmq-27.0.1-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:f98f6b7787bd2beb1f0dde03f23a0621a0c978edf673b7d8f5e7bc039cbe1b60", size = 1340836, upload-time = "2025-08-03T05:04:10.774Z" }, - { url = "https://files.pythonhosted.org/packages/be/4c/0dbce882550e17db6846b29e9dc242aea7590e7594e1ca5043e8e58fff2d/pyzmq-27.0.1-cp314-cp314t-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:351bf5d8ca0788ca85327fda45843b6927593ff4c807faee368cc5aaf9f809c2", size = 897236, upload-time = "2025-08-03T05:04:13.221Z" }, - { url = "https://files.pythonhosted.org/packages/1b/22/461e131cf16b8814f3c356fa1ea0912697dbc4c64cddf01f7756ec704c1e/pyzmq-27.0.1-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5268a5a9177afff53dc6d70dffe63114ba2a6e7b20d9411cc3adeba09eeda403", size = 660374, upload-time = "2025-08-03T05:04:15.032Z" }, - { url = "https://files.pythonhosted.org/packages/3f/0c/bbd65a814395bf4fc3e57c6c13af27601c07e4009bdfb75ebcf500537bbd/pyzmq-27.0.1-cp314-cp314t-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a4aca06ba295aa78bec9b33ec028d1ca08744c36294338c41432b7171060c808", size = 847497, upload-time = "2025-08-03T05:04:16.967Z" }, - { url = "https://files.pythonhosted.org/packages/1e/df/3d1f4a03b561d824cbd491394f67591957e2f1acf6dc85d96f970312a76a/pyzmq-27.0.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:1c363c6dc66352331d5ad64bb838765c6692766334a6a02fdb05e76bd408ae18", size = 1650028, upload-time = "2025-08-03T05:04:19.398Z" }, - { url = "https://files.pythonhosted.org/packages/41/c9/a3987540f59a412bdaae3f362f78e00e6769557a598c63b7e32956aade5a/pyzmq-27.0.1-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:87aebf4acd7249bdff8d3df03aed4f09e67078e6762cfe0aecf8d0748ff94cde", size = 2023808, upload-time = "2025-08-03T05:04:21.145Z" }, - { url = "https://files.pythonhosted.org/packages/b0/a5/c388f4cd80498a8eaef7535f2a8eaca0a35b82b87a0b47fa1856fc135004/pyzmq-27.0.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:e4f22d67756518d71901edf73b38dc0eb4765cce22c8fe122cc81748d425262b", size = 1884970, upload-time = "2025-08-03T05:04:22.908Z" }, - { url = "https://files.pythonhosted.org/packages/9a/ac/b2a89a1ed90526a1b9a260cdc5cd42f055fd44ee8d2a59902b5ac35ddeb1/pyzmq-27.0.1-cp314-cp314t-win32.whl", hash = "sha256:8c62297bc7aea2147b472ca5ca2b4389377ad82898c87cabab2a94aedd75e337", size = 586905, upload-time = "2025-08-03T05:04:24.492Z" }, - { url = "https://files.pythonhosted.org/packages/68/62/7aa5ea04e836f7a788b2a67405f83011cef59ca76d7bac91d1fc9a0476da/pyzmq-27.0.1-cp314-cp314t-win_amd64.whl", hash = "sha256:bee5248d5ec9223545f8cc4f368c2d571477ae828c99409125c3911511d98245", size = 660503, upload-time = "2025-08-03T05:04:26.382Z" }, - { url = "https://files.pythonhosted.org/packages/89/32/3836ed85947b06f1d67c07ce16c00b0cf8c053ab0b249d234f9f81ff95ff/pyzmq-27.0.1-cp314-cp314t-win_arm64.whl", hash = "sha256:0fc24bf45e4a454e55ef99d7f5c8b8712539200ce98533af25a5bfa954b6b390", size = 575098, upload-time = "2025-08-03T05:04:27.974Z" }, - { url = "https://files.pythonhosted.org/packages/b4/1a/49f66fe0bc2b2568dd4280f1f520ac8fafd73f8d762140e278d48aeaf7b9/pyzmq-27.0.1-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:7fb0ee35845bef1e8c4a152d766242164e138c239e3182f558ae15cb4a891f94", size = 835949, upload-time = "2025-08-03T05:05:13.798Z" }, - { url = "https://files.pythonhosted.org/packages/49/94/443c1984b397eab59b14dd7ae8bc2ac7e8f32dbc646474453afcaa6508c4/pyzmq-27.0.1-pp311-pypy311_pp73-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:f379f11e138dfd56c3f24a04164f871a08281194dd9ddf656a278d7d080c8ad0", size = 799875, upload-time = "2025-08-03T05:05:15.632Z" }, - { url = "https://files.pythonhosted.org/packages/30/f1/fd96138a0f152786a2ba517e9c6a8b1b3516719e412a90bb5d8eea6b660c/pyzmq-27.0.1-pp311-pypy311_pp73-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b978c0678cffbe8860ec9edc91200e895c29ae1ac8a7085f947f8e8864c489fb", size = 567403, upload-time = "2025-08-03T05:05:17.326Z" }, - { url = "https://files.pythonhosted.org/packages/16/57/34e53ef2b55b1428dac5aabe3a974a16c8bda3bf20549ba500e3ff6cb426/pyzmq-27.0.1-pp311-pypy311_pp73-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7ebccf0d760bc92a4a7c751aeb2fef6626144aace76ee8f5a63abeb100cae87f", size = 747032, upload-time = "2025-08-03T05:05:19.074Z" }, - { url = "https://files.pythonhosted.org/packages/81/b7/769598c5ae336fdb657946950465569cf18803140fe89ce466d7f0a57c11/pyzmq-27.0.1-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:77fed80e30fa65708546c4119840a46691290efc231f6bfb2ac2a39b52e15811", size = 544566, upload-time = "2025-08-03T05:05:20.798Z" }, +sdist = { url = "https://files.pythonhosted.org/packages/f8/66/159f38d184f08b5f971b467f87b1ab142ab1320d5200825c824b32b84b66/pyzmq-27.0.2.tar.gz", hash = "sha256:b398dd713b18de89730447347e96a0240225e154db56e35b6bb8447ffdb07798", size = 281440, upload-time = "2025-08-21T04:23:26.334Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/42/73/034429ab0f4316bf433eb6c20c3f49d1dc13b2ed4e4d951b283d300a0f35/pyzmq-27.0.2-cp311-cp311-macosx_10_15_universal2.whl", hash = "sha256:063845960df76599ad4fad69fa4d884b3ba38304272104fdcd7e3af33faeeb1d", size = 1333169, upload-time = "2025-08-21T04:21:12.483Z" }, + { url = "https://files.pythonhosted.org/packages/35/02/c42b3b526eb03a570c889eea85a5602797f800a50ba8b09ddbf7db568b78/pyzmq-27.0.2-cp311-cp311-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:845a35fb21b88786aeb38af8b271d41ab0967985410f35411a27eebdc578a076", size = 909176, upload-time = "2025-08-21T04:21:13.835Z" }, + { url = "https://files.pythonhosted.org/packages/1b/35/a1c0b988fabbdf2dc5fe94b7c2bcfd61e3533e5109297b8e0daf1d7a8d2d/pyzmq-27.0.2-cp311-cp311-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:515d20b5c3c86db95503faa989853a8ab692aab1e5336db011cd6d35626c4cb1", size = 668972, upload-time = "2025-08-21T04:21:15.315Z" }, + { url = "https://files.pythonhosted.org/packages/a0/63/908ac865da32ceaeecea72adceadad28ca25b23a2ca5ff018e5bff30116f/pyzmq-27.0.2-cp311-cp311-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:862aedec0b0684a5050cdb5ec13c2da96d2f8dffda48657ed35e312a4e31553b", size = 856962, upload-time = "2025-08-21T04:21:16.652Z" }, + { url = "https://files.pythonhosted.org/packages/2f/5a/90b3cc20b65cdf9391896fcfc15d8db21182eab810b7ea05a2986912fbe2/pyzmq-27.0.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:2cb5bcfc51c7a4fce335d3bc974fd1d6a916abbcdd2b25f6e89d37b8def25f57", size = 1657712, upload-time = "2025-08-21T04:21:18.666Z" }, + { url = "https://files.pythonhosted.org/packages/c4/3c/32a5a80f9be4759325b8d7b22ce674bb87e586b4c80c6a9d77598b60d6f0/pyzmq-27.0.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:38ff75b2a36e3a032e9fef29a5871e3e1301a37464e09ba364e3c3193f62982a", size = 2035054, upload-time = "2025-08-21T04:21:20.073Z" }, + { url = "https://files.pythonhosted.org/packages/13/61/71084fe2ff2d7dc5713f8740d735336e87544845dae1207a8e2e16d9af90/pyzmq-27.0.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:7a5709abe8d23ca158a9d0a18c037f4193f5b6afeb53be37173a41e9fb885792", size = 1894010, upload-time = "2025-08-21T04:21:21.96Z" }, + { url = "https://files.pythonhosted.org/packages/cb/6b/77169cfb13b696e50112ca496b2ed23c4b7d8860a1ec0ff3e4b9f9926221/pyzmq-27.0.2-cp311-cp311-win32.whl", hash = "sha256:47c5dda2018c35d87be9b83de0890cb92ac0791fd59498847fc4eca6ff56671d", size = 566819, upload-time = "2025-08-21T04:21:23.31Z" }, + { url = "https://files.pythonhosted.org/packages/37/cd/86c4083e0f811f48f11bc0ddf1e7d13ef37adfd2fd4f78f2445f1cc5dec0/pyzmq-27.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:f54ca3e98f8f4d23e989c7d0edcf9da7a514ff261edaf64d1d8653dd5feb0a8b", size = 633264, upload-time = "2025-08-21T04:21:24.761Z" }, + { url = "https://files.pythonhosted.org/packages/a0/69/5b8bb6a19a36a569fac02153a9e083738785892636270f5f68a915956aea/pyzmq-27.0.2-cp311-cp311-win_arm64.whl", hash = "sha256:2ef3067cb5b51b090fb853f423ad7ed63836ec154374282780a62eb866bf5768", size = 559316, upload-time = "2025-08-21T04:21:26.1Z" }, + { url = "https://files.pythonhosted.org/packages/68/69/b3a729e7b03e412bee2b1823ab8d22e20a92593634f664afd04c6c9d9ac0/pyzmq-27.0.2-cp312-abi3-macosx_10_15_universal2.whl", hash = "sha256:5da05e3c22c95e23bfc4afeee6ff7d4be9ff2233ad6cb171a0e8257cd46b169a", size = 1305910, upload-time = "2025-08-21T04:21:27.609Z" }, + { url = "https://files.pythonhosted.org/packages/15/b7/f6a6a285193d489b223c340b38ee03a673467cb54914da21c3d7849f1b10/pyzmq-27.0.2-cp312-abi3-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:4e4520577971d01d47e2559bb3175fce1be9103b18621bf0b241abe0a933d040", size = 895507, upload-time = "2025-08-21T04:21:29.005Z" }, + { url = "https://files.pythonhosted.org/packages/17/e6/c4ed2da5ef9182cde1b1f5d0051a986e76339d71720ec1a00be0b49275ad/pyzmq-27.0.2-cp312-abi3-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:56d7de7bf73165b90bd25a8668659ccb134dd28449116bf3c7e9bab5cf8a8ec9", size = 652670, upload-time = "2025-08-21T04:21:30.71Z" }, + { url = "https://files.pythonhosted.org/packages/0e/66/d781ab0636570d32c745c4e389b1c6b713115905cca69ab6233508622edd/pyzmq-27.0.2-cp312-abi3-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:340e7cddc32f147c6c00d116a3f284ab07ee63dbd26c52be13b590520434533c", size = 840581, upload-time = "2025-08-21T04:21:32.008Z" }, + { url = "https://files.pythonhosted.org/packages/a6/df/f24790caf565d72544f5c8d8500960b9562c1dc848d6f22f3c7e122e73d4/pyzmq-27.0.2-cp312-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:ba95693f9df8bb4a9826464fb0fe89033936f35fd4a8ff1edff09a473570afa0", size = 1641931, upload-time = "2025-08-21T04:21:33.371Z" }, + { url = "https://files.pythonhosted.org/packages/65/65/77d27b19fc5e845367f9100db90b9fce924f611b14770db480615944c9c9/pyzmq-27.0.2-cp312-abi3-musllinux_1_2_i686.whl", hash = "sha256:ca42a6ce2d697537da34f77a1960d21476c6a4af3e539eddb2b114c3cf65a78c", size = 2021226, upload-time = "2025-08-21T04:21:35.301Z" }, + { url = "https://files.pythonhosted.org/packages/5b/65/1ed14421ba27a4207fa694772003a311d1142b7f543179e4d1099b7eb746/pyzmq-27.0.2-cp312-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:3e44e665d78a07214b2772ccbd4b9bcc6d848d7895f1b2d7653f047b6318a4f6", size = 1878047, upload-time = "2025-08-21T04:21:36.749Z" }, + { url = "https://files.pythonhosted.org/packages/dd/dc/e578549b89b40dc78a387ec471c2a360766690c0a045cd8d1877d401012d/pyzmq-27.0.2-cp312-abi3-win32.whl", hash = "sha256:272d772d116615397d2be2b1417b3b8c8bc8671f93728c2f2c25002a4530e8f6", size = 558757, upload-time = "2025-08-21T04:21:38.2Z" }, + { url = "https://files.pythonhosted.org/packages/b5/89/06600980aefcc535c758414da969f37a5194ea4cdb73b745223f6af3acfb/pyzmq-27.0.2-cp312-abi3-win_amd64.whl", hash = "sha256:734be4f44efba0aa69bf5f015ed13eb69ff29bf0d17ea1e21588b095a3147b8e", size = 619281, upload-time = "2025-08-21T04:21:39.909Z" }, + { url = "https://files.pythonhosted.org/packages/30/84/df8a5c089552d17c9941d1aea4314b606edf1b1622361dae89aacedc6467/pyzmq-27.0.2-cp312-abi3-win_arm64.whl", hash = "sha256:41f0bd56d9279392810950feb2785a419c2920bbf007fdaaa7f4a07332ae492d", size = 552680, upload-time = "2025-08-21T04:21:41.571Z" }, + { url = "https://files.pythonhosted.org/packages/b4/7b/b79e976508517ab80dc800f7021ef1fb602a6d55e4caa2d47fb3dca5d8b6/pyzmq-27.0.2-cp313-cp313-android_24_arm64_v8a.whl", hash = "sha256:7f01118133427cd7f34ee133b5098e2af5f70303fa7519785c007bca5aa6f96a", size = 1122259, upload-time = "2025-08-21T04:21:43.063Z" }, + { url = "https://files.pythonhosted.org/packages/2b/1c/777217b9940ebcb7e71c924184ca5f31e410580a58d9fd93798589f0d31c/pyzmq-27.0.2-cp313-cp313-android_24_x86_64.whl", hash = "sha256:e4b860edf6379a7234ccbb19b4ed2c57e3ff569c3414fadfb49ae72b61a8ef07", size = 1156113, upload-time = "2025-08-21T04:21:44.566Z" }, + { url = "https://files.pythonhosted.org/packages/59/7d/654657a4c6435f41538182e71b61eac386a789a2bbb6f30171915253a9a7/pyzmq-27.0.2-cp313-cp313t-macosx_10_15_universal2.whl", hash = "sha256:cb77923ea163156da14295c941930bd525df0d29c96c1ec2fe3c3806b1e17cb3", size = 1341437, upload-time = "2025-08-21T04:21:46.019Z" }, + { url = "https://files.pythonhosted.org/packages/20/a0/5ed7710037f9c096017adc748bcb1698674a2d297f8b9422d38816f7b56a/pyzmq-27.0.2-cp313-cp313t-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:61678b7407b04df8f9423f188156355dc94d0fb52d360ae79d02ed7e0d431eea", size = 897888, upload-time = "2025-08-21T04:21:47.362Z" }, + { url = "https://files.pythonhosted.org/packages/2c/8a/6e4699a60931c17e7406641d201d7f2c121e2a38979bc83226a6d8f1ba32/pyzmq-27.0.2-cp313-cp313t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e3c824b70925963bdc8e39a642672c15ffaa67e7d4b491f64662dd56d6271263", size = 660727, upload-time = "2025-08-21T04:21:48.734Z" }, + { url = "https://files.pythonhosted.org/packages/7b/d8/d761e438c186451bd89ce63a665cde5690c084b61cd8f5d7b51e966e875a/pyzmq-27.0.2-cp313-cp313t-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c4833e02fcf2751975457be1dfa2f744d4d09901a8cc106acaa519d868232175", size = 848136, upload-time = "2025-08-21T04:21:50.416Z" }, + { url = "https://files.pythonhosted.org/packages/43/f1/a0f31684efdf3eb92f46b7dd2117e752208115e89d278f8ca5f413c5bb85/pyzmq-27.0.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:b18045668d09cf0faa44918af2a67f0dbbef738c96f61c2f1b975b1ddb92ccfc", size = 1650402, upload-time = "2025-08-21T04:21:52.235Z" }, + { url = "https://files.pythonhosted.org/packages/41/fd/0d7f2a1732812df02c85002770da4a7864c79b210084bcdab01ea57e8d92/pyzmq-27.0.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:bbbb7e2f3ac5a22901324e7b086f398b8e16d343879a77b15ca3312e8cd8e6d5", size = 2024587, upload-time = "2025-08-21T04:21:54.07Z" }, + { url = "https://files.pythonhosted.org/packages/f1/73/358be69e279a382dd09e46dda29df8446365cddee4f79ef214e71e5b2b5a/pyzmq-27.0.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:b751914a73604d40d88a061bab042a11d4511b3ddbb7624cd83c39c8a498564c", size = 1885493, upload-time = "2025-08-21T04:21:55.588Z" }, + { url = "https://files.pythonhosted.org/packages/c5/7b/e9951ad53b3dfed8cfb4c2cfd6e0097c9b454e5c0d0e6df5f2b60d7c8c3d/pyzmq-27.0.2-cp313-cp313t-win32.whl", hash = "sha256:3e8f833dd82af11db5321c414638045c70f61009f72dd61c88db4a713c1fb1d2", size = 574934, upload-time = "2025-08-21T04:21:57.52Z" }, + { url = "https://files.pythonhosted.org/packages/55/33/1a7fc3a92f2124a63e6e2a6afa0af471a5c0c713e776b476d4eda5111b13/pyzmq-27.0.2-cp313-cp313t-win_amd64.whl", hash = "sha256:5b45153cb8eadcab14139970643a84f7a7b08dda541fbc1f6f4855c49334b549", size = 640932, upload-time = "2025-08-21T04:21:59.527Z" }, + { url = "https://files.pythonhosted.org/packages/2a/52/2598a94ac251a7c83f3887866225eea1952b0d4463a68df5032eb00ff052/pyzmq-27.0.2-cp313-cp313t-win_arm64.whl", hash = "sha256:86898f5c9730df23427c1ee0097d8aa41aa5f89539a79e48cd0d2c22d059f1b7", size = 561315, upload-time = "2025-08-21T04:22:01.295Z" }, + { url = "https://files.pythonhosted.org/packages/42/7d/10ef02ea36590b29d48ef88eb0831f0af3eb240cccca2752556faec55f59/pyzmq-27.0.2-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:d2b4b261dce10762be5c116b6ad1f267a9429765b493c454f049f33791dd8b8a", size = 1341463, upload-time = "2025-08-21T04:22:02.712Z" }, + { url = "https://files.pythonhosted.org/packages/94/36/115d18dade9a3d4d3d08dd8bfe5459561b8e02815f99df040555fdd7768e/pyzmq-27.0.2-cp314-cp314t-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:4e4d88b6cff156fed468903006b24bbd85322612f9c2f7b96e72d5016fd3f543", size = 897840, upload-time = "2025-08-21T04:22:04.845Z" }, + { url = "https://files.pythonhosted.org/packages/39/66/083b37839b95c386a95f1537bb41bdbf0c002b7c55b75ee737949cecb11f/pyzmq-27.0.2-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8426c0ebbc11ed8416a6e9409c194142d677c2c5c688595f2743664e356d9e9b", size = 660704, upload-time = "2025-08-21T04:22:06.389Z" }, + { url = "https://files.pythonhosted.org/packages/76/5a/196ab46e549ba35bf3268f575e10cfac0dc86b78dcaa7a3e36407ecda752/pyzmq-27.0.2-cp314-cp314t-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:565bee96a155fe6452caed5fb5f60c9862038e6b51a59f4f632562081cdb4004", size = 848037, upload-time = "2025-08-21T04:22:07.817Z" }, + { url = "https://files.pythonhosted.org/packages/70/ea/a27b9eb44b2e615a9ecb8510ebb023cc1d2d251181e4a1e50366bfbf94d6/pyzmq-27.0.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:5de735c745ca5cefe9c2d1547d8f28cfe1b1926aecb7483ab1102fd0a746c093", size = 1650278, upload-time = "2025-08-21T04:22:09.269Z" }, + { url = "https://files.pythonhosted.org/packages/62/ac/3e9af036bfaf718ab5e69ded8f6332da392c5450ad43e8e3ca66797f145a/pyzmq-27.0.2-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:ea4f498f8115fd90d7bf03a3e83ae3e9898e43362f8e8e8faec93597206e15cc", size = 2024504, upload-time = "2025-08-21T04:22:10.778Z" }, + { url = "https://files.pythonhosted.org/packages/ae/e9/3202d31788df8ebaa176b23d846335eb9c768d8b43c0506bbd6265ad36a0/pyzmq-27.0.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:d00e81cb0afd672915257a3927124ee2ad117ace3c256d39cd97ca3f190152ad", size = 1885381, upload-time = "2025-08-21T04:22:12.718Z" }, + { url = "https://files.pythonhosted.org/packages/4b/ed/42de80b7ab4e8fcf13376f81206cf8041740672ac1fd2e1c598d63f595bf/pyzmq-27.0.2-cp314-cp314t-win32.whl", hash = "sha256:0f6e9b00d81b58f859fffc112365d50413954e02aefe36c5b4c8fb4af79f8cc3", size = 587526, upload-time = "2025-08-21T04:22:14.18Z" }, + { url = "https://files.pythonhosted.org/packages/ed/c8/8f3c72d6f0bfbf090aa5e283576073ca5c59839b85a5cc8c66ddb9b59801/pyzmq-27.0.2-cp314-cp314t-win_amd64.whl", hash = "sha256:2e73cf3b127a437fef4100eb3ac2ebe6b49e655bb721329f667f59eca0a26221", size = 661368, upload-time = "2025-08-21T04:22:15.677Z" }, + { url = "https://files.pythonhosted.org/packages/69/a4/7ee652ea1c77d872f5d99ed937fa8bbd1f6f4b7a39a6d3a0076c286e0c3e/pyzmq-27.0.2-cp314-cp314t-win_arm64.whl", hash = "sha256:4108785f2e5ac865d06f678a07a1901e3465611356df21a545eeea8b45f56265", size = 574901, upload-time = "2025-08-21T04:22:17.423Z" }, + { url = "https://files.pythonhosted.org/packages/c7/60/027d0032a1e3b1aabcef0e309b9ff8a4099bdd5a60ab38b36a676ff2bd7b/pyzmq-27.0.2-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:e297784aea724294fe95e442e39a4376c2f08aa4fae4161c669f047051e31b02", size = 836007, upload-time = "2025-08-21T04:23:00.447Z" }, + { url = "https://files.pythonhosted.org/packages/25/20/2ed1e6168aaea323df9bb2c451309291f53ba3af372ffc16edd4ce15b9e5/pyzmq-27.0.2-pp311-pypy311_pp73-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:e3659a79ded9745bc9c2aef5b444ac8805606e7bc50d2d2eb16dc3ab5483d91f", size = 799932, upload-time = "2025-08-21T04:23:02.052Z" }, + { url = "https://files.pythonhosted.org/packages/fd/25/5c147307de546b502c9373688ce5b25dc22288d23a1ebebe5d587bf77610/pyzmq-27.0.2-pp311-pypy311_pp73-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f3dba49ff037d02373a9306b58d6c1e0be031438f822044e8767afccfdac4c6b", size = 567459, upload-time = "2025-08-21T04:23:03.593Z" }, + { url = "https://files.pythonhosted.org/packages/71/06/0dc56ffc615c8095cd089c9b98ce5c733e990f09ce4e8eea4aaf1041a532/pyzmq-27.0.2-pp311-pypy311_pp73-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:de84e1694f9507b29e7b263453a2255a73e3d099d258db0f14539bad258abe41", size = 747088, upload-time = "2025-08-21T04:23:05.334Z" }, + { url = "https://files.pythonhosted.org/packages/06/f6/4a50187e023b8848edd3f0a8e197b1a7fb08d261d8c60aae7cb6c3d71612/pyzmq-27.0.2-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:f0944d65ba2b872b9fcece08411d6347f15a874c775b4c3baae7f278550da0fb", size = 544639, upload-time = "2025-08-21T04:23:07.279Z" }, ] [[package]] @@ -2035,7 +2051,7 @@ wheels = [ [[package]] name = "requests" -version = "2.32.4" +version = "2.32.5" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "certifi" }, @@ -2043,9 +2059,9 @@ dependencies = [ { name = "idna" }, { name = "urllib3" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/e1/0a/929373653770d8a0d7ea76c37de6e41f11eb07559b103b1c02cafb3f7cf8/requests-2.32.4.tar.gz", hash = "sha256:27d0316682c8a29834d3264820024b62a36942083d52caf2f14c0591336d3422", size = 135258, upload-time = "2025-06-09T16:43:07.34Z" } +sdist = { url = "https://files.pythonhosted.org/packages/c9/74/b3ff8e6c8446842c3f5c837e9c3dfcfe2018ea6ecef224c710c85ef728f4/requests-2.32.5.tar.gz", hash = "sha256:dbba0bac56e100853db0ea71b82b4dfd5fe2bf6d3754a8893c3af500cec7d7cf", size = 134517, upload-time = "2025-08-18T20:46:02.573Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/7c/e4/56027c4a6b4ae70ca9de302488c5ca95ad4a39e190093d6c1a8ace08341b/requests-2.32.4-py3-none-any.whl", hash = "sha256:27babd3cda2a6d50b30443204ee89830707d396671944c998b5975b031ac2b2c", size = 64847, upload-time = "2025-06-09T16:43:05.728Z" }, + { url = "https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl", hash = "sha256:2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6", size = 64738, upload-time = "2025-08-18T20:46:00.542Z" }, ] [[package]] @@ -2059,110 +2075,110 @@ wheels = [ [[package]] name = "rpds-py" -version = "0.27.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/1e/d9/991a0dee12d9fc53ed027e26a26a64b151d77252ac477e22666b9688bc16/rpds_py-0.27.0.tar.gz", hash = "sha256:8b23cf252f180cda89220b378d917180f29d313cd6a07b2431c0d3b776aae86f", size = 27420, upload-time = "2025-08-07T08:26:39.624Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/b4/c1/49d515434c1752e40f5e35b985260cf27af052593378580a2f139a5be6b8/rpds_py-0.27.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:dbc2ab5d10544eb485baa76c63c501303b716a5c405ff2469a1d8ceffaabf622", size = 371577, upload-time = "2025-08-07T08:23:25.379Z" }, - { url = "https://files.pythonhosted.org/packages/e1/6d/bf2715b2fee5087fa13b752b5fd573f1a93e4134c74d275f709e38e54fe7/rpds_py-0.27.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7ec85994f96a58cf7ed288caa344b7fe31fd1d503bdf13d7331ead5f70ab60d5", size = 354959, upload-time = "2025-08-07T08:23:26.767Z" }, - { url = "https://files.pythonhosted.org/packages/a3/5c/e7762808c746dd19733a81373c10da43926f6a6adcf4920a21119697a60a/rpds_py-0.27.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:190d7285cd3bb6d31d37a0534d7359c1ee191eb194c511c301f32a4afa5a1dd4", size = 381485, upload-time = "2025-08-07T08:23:27.869Z" }, - { url = "https://files.pythonhosted.org/packages/40/51/0d308eb0b558309ca0598bcba4243f52c4cd20e15fe991b5bd75824f2e61/rpds_py-0.27.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c10d92fb6d7fd827e44055fcd932ad93dac6a11e832d51534d77b97d1d85400f", size = 396816, upload-time = "2025-08-07T08:23:29.424Z" }, - { url = "https://files.pythonhosted.org/packages/5c/aa/2d585ec911d78f66458b2c91252134ca0c7c70f687a72c87283173dc0c96/rpds_py-0.27.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dd2c1d27ebfe6a015cfa2005b7fe8c52d5019f7bbdd801bc6f7499aab9ae739e", size = 514950, upload-time = "2025-08-07T08:23:30.576Z" }, - { url = "https://files.pythonhosted.org/packages/0b/ef/aced551cc1148179557aed84343073adadf252c91265263ee6203458a186/rpds_py-0.27.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4790c9d5dd565ddb3e9f656092f57268951398cef52e364c405ed3112dc7c7c1", size = 402132, upload-time = "2025-08-07T08:23:32.428Z" }, - { url = "https://files.pythonhosted.org/packages/4b/ac/cf644803d8d417653fe2b3604186861d62ea6afaef1b2284045741baef17/rpds_py-0.27.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4300e15e7d03660f04be84a125d1bdd0e6b2f674bc0723bc0fd0122f1a4585dc", size = 383660, upload-time = "2025-08-07T08:23:33.829Z" }, - { url = "https://files.pythonhosted.org/packages/c9/ec/caf47c55ce02b76cbaeeb2d3b36a73da9ca2e14324e3d75cf72b59dcdac5/rpds_py-0.27.0-cp311-cp311-manylinux_2_31_riscv64.whl", hash = "sha256:59195dc244fc183209cf8a93406889cadde47dfd2f0a6b137783aa9c56d67c85", size = 401730, upload-time = "2025-08-07T08:23:34.97Z" }, - { url = "https://files.pythonhosted.org/packages/0b/71/c1f355afdcd5b99ffc253422aa4bdcb04ccf1491dcd1bda3688a0c07fd61/rpds_py-0.27.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fae4a01ef8c4cb2bbe92ef2063149596907dc4a881a8d26743b3f6b304713171", size = 416122, upload-time = "2025-08-07T08:23:36.062Z" }, - { url = "https://files.pythonhosted.org/packages/38/0f/f4b5b1eda724ed0e04d2b26d8911cdc131451a7ee4c4c020a1387e5c6ded/rpds_py-0.27.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:e3dc8d4ede2dbae6c0fc2b6c958bf51ce9fd7e9b40c0f5b8835c3fde44f5807d", size = 558771, upload-time = "2025-08-07T08:23:37.478Z" }, - { url = "https://files.pythonhosted.org/packages/93/c0/5f8b834db2289ab48d5cffbecbb75e35410103a77ac0b8da36bf9544ec1c/rpds_py-0.27.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:c3782fb753aa825b4ccabc04292e07897e2fd941448eabf666856c5530277626", size = 587876, upload-time = "2025-08-07T08:23:38.662Z" }, - { url = "https://files.pythonhosted.org/packages/d2/dd/1a1df02ab8eb970115cff2ae31a6f73916609b900dc86961dc382b8c2e5e/rpds_py-0.27.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:887ab1f12b0d227e9260558a4a2320024b20102207ada65c43e1ffc4546df72e", size = 554359, upload-time = "2025-08-07T08:23:39.897Z" }, - { url = "https://files.pythonhosted.org/packages/a1/e4/95a014ab0d51ab6e3bebbdb476a42d992d2bbf9c489d24cff9fda998e925/rpds_py-0.27.0-cp311-cp311-win32.whl", hash = "sha256:5d6790ff400254137b81b8053b34417e2c46921e302d655181d55ea46df58cf7", size = 218084, upload-time = "2025-08-07T08:23:41.086Z" }, - { url = "https://files.pythonhosted.org/packages/49/78/f8d5b71ec65a0376b0de31efcbb5528ce17a9b7fdd19c3763303ccfdedec/rpds_py-0.27.0-cp311-cp311-win_amd64.whl", hash = "sha256:e24d8031a2c62f34853756d9208eeafa6b940a1efcbfe36e8f57d99d52bb7261", size = 230085, upload-time = "2025-08-07T08:23:42.143Z" }, - { url = "https://files.pythonhosted.org/packages/e7/d3/84429745184091e06b4cc70f8597408e314c2d2f7f5e13249af9ffab9e3d/rpds_py-0.27.0-cp311-cp311-win_arm64.whl", hash = "sha256:08680820d23df1df0a0260f714d12966bc6c42d02e8055a91d61e03f0c47dda0", size = 222112, upload-time = "2025-08-07T08:23:43.233Z" }, - { url = "https://files.pythonhosted.org/packages/cd/17/e67309ca1ac993fa1888a0d9b2f5ccc1f67196ace32e76c9f8e1dbbbd50c/rpds_py-0.27.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:19c990fdf5acecbf0623e906ae2e09ce1c58947197f9bced6bbd7482662231c4", size = 362611, upload-time = "2025-08-07T08:23:44.773Z" }, - { url = "https://files.pythonhosted.org/packages/93/2e/28c2fb84aa7aa5d75933d1862d0f7de6198ea22dfd9a0cca06e8a4e7509e/rpds_py-0.27.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6c27a7054b5224710fcfb1a626ec3ff4f28bcb89b899148c72873b18210e446b", size = 347680, upload-time = "2025-08-07T08:23:46.014Z" }, - { url = "https://files.pythonhosted.org/packages/44/3e/9834b4c8f4f5fe936b479e623832468aa4bd6beb8d014fecaee9eac6cdb1/rpds_py-0.27.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:09965b314091829b378b60607022048953e25f0b396c2b70e7c4c81bcecf932e", size = 384600, upload-time = "2025-08-07T08:23:48Z" }, - { url = "https://files.pythonhosted.org/packages/19/78/744123c7b38865a965cd9e6f691fde7ef989a00a256fa8bf15b75240d12f/rpds_py-0.27.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:14f028eb47f59e9169bfdf9f7ceafd29dd64902141840633683d0bad5b04ff34", size = 400697, upload-time = "2025-08-07T08:23:49.407Z" }, - { url = "https://files.pythonhosted.org/packages/32/97/3c3d32fe7daee0a1f1a678b6d4dfb8c4dcf88197fa2441f9da7cb54a8466/rpds_py-0.27.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6168af0be75bba990a39f9431cdfae5f0ad501f4af32ae62e8856307200517b8", size = 517781, upload-time = "2025-08-07T08:23:50.557Z" }, - { url = "https://files.pythonhosted.org/packages/b2/be/28f0e3e733680aa13ecec1212fc0f585928a206292f14f89c0b8a684cad1/rpds_py-0.27.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ab47fe727c13c09d0e6f508e3a49e545008e23bf762a245b020391b621f5b726", size = 406449, upload-time = "2025-08-07T08:23:51.732Z" }, - { url = "https://files.pythonhosted.org/packages/95/ae/5d15c83e337c082d0367053baeb40bfba683f42459f6ebff63a2fd7e5518/rpds_py-0.27.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5fa01b3d5e3b7d97efab65bd3d88f164e289ec323a8c033c5c38e53ee25c007e", size = 386150, upload-time = "2025-08-07T08:23:52.822Z" }, - { url = "https://files.pythonhosted.org/packages/bf/65/944e95f95d5931112829e040912b25a77b2e7ed913ea5fe5746aa5c1ce75/rpds_py-0.27.0-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:6c135708e987f46053e0a1246a206f53717f9fadfba27174a9769ad4befba5c3", size = 406100, upload-time = "2025-08-07T08:23:54.339Z" }, - { url = "https://files.pythonhosted.org/packages/21/a4/1664b83fae02894533cd11dc0b9f91d673797c2185b7be0f7496107ed6c5/rpds_py-0.27.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fc327f4497b7087d06204235199daf208fd01c82d80465dc5efa4ec9df1c5b4e", size = 421345, upload-time = "2025-08-07T08:23:55.832Z" }, - { url = "https://files.pythonhosted.org/packages/7c/26/b7303941c2b0823bfb34c71378249f8beedce57301f400acb04bb345d025/rpds_py-0.27.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:7e57906e38583a2cba67046a09c2637e23297618dc1f3caddbc493f2be97c93f", size = 561891, upload-time = "2025-08-07T08:23:56.951Z" }, - { url = "https://files.pythonhosted.org/packages/9b/c8/48623d64d4a5a028fa99576c768a6159db49ab907230edddc0b8468b998b/rpds_py-0.27.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:0f4f69d7a4300fbf91efb1fb4916421bd57804c01ab938ab50ac9c4aa2212f03", size = 591756, upload-time = "2025-08-07T08:23:58.146Z" }, - { url = "https://files.pythonhosted.org/packages/b3/51/18f62617e8e61cc66334c9fb44b1ad7baae3438662098efbc55fb3fda453/rpds_py-0.27.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b4c4fbbcff474e1e5f38be1bf04511c03d492d42eec0babda5d03af3b5589374", size = 557088, upload-time = "2025-08-07T08:23:59.6Z" }, - { url = "https://files.pythonhosted.org/packages/bd/4c/e84c3a276e2496a93d245516be6b49e20499aa8ca1c94d59fada0d79addc/rpds_py-0.27.0-cp312-cp312-win32.whl", hash = "sha256:27bac29bbbf39601b2aab474daf99dbc8e7176ca3389237a23944b17f8913d97", size = 221926, upload-time = "2025-08-07T08:24:00.695Z" }, - { url = "https://files.pythonhosted.org/packages/83/89/9d0fbcef64340db0605eb0a0044f258076f3ae0a3b108983b2c614d96212/rpds_py-0.27.0-cp312-cp312-win_amd64.whl", hash = "sha256:8a06aa1197ec0281eb1d7daf6073e199eb832fe591ffa329b88bae28f25f5fe5", size = 233235, upload-time = "2025-08-07T08:24:01.846Z" }, - { url = "https://files.pythonhosted.org/packages/c9/b0/e177aa9f39cbab060f96de4a09df77d494f0279604dc2f509263e21b05f9/rpds_py-0.27.0-cp312-cp312-win_arm64.whl", hash = "sha256:e14aab02258cb776a108107bd15f5b5e4a1bbaa61ef33b36693dfab6f89d54f9", size = 223315, upload-time = "2025-08-07T08:24:03.337Z" }, - { url = "https://files.pythonhosted.org/packages/81/d2/dfdfd42565a923b9e5a29f93501664f5b984a802967d48d49200ad71be36/rpds_py-0.27.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:443d239d02d9ae55b74015234f2cd8eb09e59fbba30bf60baeb3123ad4c6d5ff", size = 362133, upload-time = "2025-08-07T08:24:04.508Z" }, - { url = "https://files.pythonhosted.org/packages/ac/4a/0a2e2460c4b66021d349ce9f6331df1d6c75d7eea90df9785d333a49df04/rpds_py-0.27.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:b8a7acf04fda1f30f1007f3cc96d29d8cf0a53e626e4e1655fdf4eabc082d367", size = 347128, upload-time = "2025-08-07T08:24:05.695Z" }, - { url = "https://files.pythonhosted.org/packages/35/8d/7d1e4390dfe09d4213b3175a3f5a817514355cb3524593380733204f20b9/rpds_py-0.27.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9d0f92b78cfc3b74a42239fdd8c1266f4715b573204c234d2f9fc3fc7a24f185", size = 384027, upload-time = "2025-08-07T08:24:06.841Z" }, - { url = "https://files.pythonhosted.org/packages/c1/65/78499d1a62172891c8cd45de737b2a4b84a414b6ad8315ab3ac4945a5b61/rpds_py-0.27.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ce4ed8e0c7dbc5b19352b9c2c6131dd23b95fa8698b5cdd076307a33626b72dc", size = 399973, upload-time = "2025-08-07T08:24:08.143Z" }, - { url = "https://files.pythonhosted.org/packages/10/a1/1c67c1d8cc889107b19570bb01f75cf49852068e95e6aee80d22915406fc/rpds_py-0.27.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fde355b02934cc6b07200cc3b27ab0c15870a757d1a72fd401aa92e2ea3c6bfe", size = 515295, upload-time = "2025-08-07T08:24:09.711Z" }, - { url = "https://files.pythonhosted.org/packages/df/27/700ec88e748436b6c7c4a2262d66e80f8c21ab585d5e98c45e02f13f21c0/rpds_py-0.27.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:13bbc4846ae4c993f07c93feb21a24d8ec637573d567a924b1001e81c8ae80f9", size = 406737, upload-time = "2025-08-07T08:24:11.182Z" }, - { url = "https://files.pythonhosted.org/packages/33/cc/6b0ee8f0ba3f2df2daac1beda17fde5cf10897a7d466f252bd184ef20162/rpds_py-0.27.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:be0744661afbc4099fef7f4e604e7f1ea1be1dd7284f357924af12a705cc7d5c", size = 385898, upload-time = "2025-08-07T08:24:12.798Z" }, - { url = "https://files.pythonhosted.org/packages/e8/7e/c927b37d7d33c0a0ebf249cc268dc2fcec52864c1b6309ecb960497f2285/rpds_py-0.27.0-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:069e0384a54f427bd65d7fda83b68a90606a3835901aaff42185fcd94f5a9295", size = 405785, upload-time = "2025-08-07T08:24:14.906Z" }, - { url = "https://files.pythonhosted.org/packages/5b/d2/8ed50746d909dcf402af3fa58b83d5a590ed43e07251d6b08fad1a535ba6/rpds_py-0.27.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4bc262ace5a1a7dc3e2eac2fa97b8257ae795389f688b5adf22c5db1e2431c43", size = 419760, upload-time = "2025-08-07T08:24:16.129Z" }, - { url = "https://files.pythonhosted.org/packages/d3/60/2b2071aee781cb3bd49f94d5d35686990b925e9b9f3e3d149235a6f5d5c1/rpds_py-0.27.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:2fe6e18e5c8581f0361b35ae575043c7029d0a92cb3429e6e596c2cdde251432", size = 561201, upload-time = "2025-08-07T08:24:17.645Z" }, - { url = "https://files.pythonhosted.org/packages/98/1f/27b67304272521aaea02be293fecedce13fa351a4e41cdb9290576fc6d81/rpds_py-0.27.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:d93ebdb82363d2e7bec64eecdc3632b59e84bd270d74fe5be1659f7787052f9b", size = 591021, upload-time = "2025-08-07T08:24:18.999Z" }, - { url = "https://files.pythonhosted.org/packages/db/9b/a2fadf823164dd085b1f894be6443b0762a54a7af6f36e98e8fcda69ee50/rpds_py-0.27.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:0954e3a92e1d62e83a54ea7b3fdc9efa5d61acef8488a8a3d31fdafbfb00460d", size = 556368, upload-time = "2025-08-07T08:24:20.54Z" }, - { url = "https://files.pythonhosted.org/packages/24/f3/6d135d46a129cda2e3e6d4c5e91e2cc26ea0428c6cf152763f3f10b6dd05/rpds_py-0.27.0-cp313-cp313-win32.whl", hash = "sha256:2cff9bdd6c7b906cc562a505c04a57d92e82d37200027e8d362518df427f96cd", size = 221236, upload-time = "2025-08-07T08:24:22.144Z" }, - { url = "https://files.pythonhosted.org/packages/c5/44/65d7494f5448ecc755b545d78b188440f81da98b50ea0447ab5ebfdf9bd6/rpds_py-0.27.0-cp313-cp313-win_amd64.whl", hash = "sha256:dc79d192fb76fc0c84f2c58672c17bbbc383fd26c3cdc29daae16ce3d927e8b2", size = 232634, upload-time = "2025-08-07T08:24:23.642Z" }, - { url = "https://files.pythonhosted.org/packages/70/d9/23852410fadab2abb611733933401de42a1964ce6600a3badae35fbd573e/rpds_py-0.27.0-cp313-cp313-win_arm64.whl", hash = "sha256:5b3a5c8089eed498a3af23ce87a80805ff98f6ef8f7bdb70bd1b7dae5105f6ac", size = 222783, upload-time = "2025-08-07T08:24:25.098Z" }, - { url = "https://files.pythonhosted.org/packages/15/75/03447917f78512b34463f4ef11066516067099a0c466545655503bed0c77/rpds_py-0.27.0-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:90fb790138c1a89a2e58c9282fe1089638401f2f3b8dddd758499041bc6e0774", size = 359154, upload-time = "2025-08-07T08:24:26.249Z" }, - { url = "https://files.pythonhosted.org/packages/6b/fc/4dac4fa756451f2122ddaf136e2c6aeb758dc6fdbe9ccc4bc95c98451d50/rpds_py-0.27.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:010c4843a3b92b54373e3d2291a7447d6c3fc29f591772cc2ea0e9f5c1da434b", size = 343909, upload-time = "2025-08-07T08:24:27.405Z" }, - { url = "https://files.pythonhosted.org/packages/7b/81/723c1ed8e6f57ed9d8c0c07578747a2d3d554aaefc1ab89f4e42cfeefa07/rpds_py-0.27.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c9ce7a9e967afc0a2af7caa0d15a3e9c1054815f73d6a8cb9225b61921b419bd", size = 379340, upload-time = "2025-08-07T08:24:28.714Z" }, - { url = "https://files.pythonhosted.org/packages/98/16/7e3740413de71818ce1997df82ba5f94bae9fff90c0a578c0e24658e6201/rpds_py-0.27.0-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:aa0bf113d15e8abdfee92aa4db86761b709a09954083afcb5bf0f952d6065fdb", size = 391655, upload-time = "2025-08-07T08:24:30.223Z" }, - { url = "https://files.pythonhosted.org/packages/e0/63/2a9f510e124d80660f60ecce07953f3f2d5f0b96192c1365443859b9c87f/rpds_py-0.27.0-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:eb91d252b35004a84670dfeafadb042528b19842a0080d8b53e5ec1128e8f433", size = 513017, upload-time = "2025-08-07T08:24:31.446Z" }, - { url = "https://files.pythonhosted.org/packages/2c/4e/cf6ff311d09776c53ea1b4f2e6700b9d43bb4e99551006817ade4bbd6f78/rpds_py-0.27.0-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:db8a6313dbac934193fc17fe7610f70cd8181c542a91382531bef5ed785e5615", size = 402058, upload-time = "2025-08-07T08:24:32.613Z" }, - { url = "https://files.pythonhosted.org/packages/88/11/5e36096d474cb10f2a2d68b22af60a3bc4164fd8db15078769a568d9d3ac/rpds_py-0.27.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce96ab0bdfcef1b8c371ada2100767ace6804ea35aacce0aef3aeb4f3f499ca8", size = 383474, upload-time = "2025-08-07T08:24:33.767Z" }, - { url = "https://files.pythonhosted.org/packages/db/a2/3dff02805b06058760b5eaa6d8cb8db3eb3e46c9e452453ad5fc5b5ad9fe/rpds_py-0.27.0-cp313-cp313t-manylinux_2_31_riscv64.whl", hash = "sha256:7451ede3560086abe1aa27dcdcf55cd15c96b56f543fb12e5826eee6f721f858", size = 400067, upload-time = "2025-08-07T08:24:35.021Z" }, - { url = "https://files.pythonhosted.org/packages/67/87/eed7369b0b265518e21ea836456a4ed4a6744c8c12422ce05bce760bb3cf/rpds_py-0.27.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:32196b5a99821476537b3f7732432d64d93a58d680a52c5e12a190ee0135d8b5", size = 412085, upload-time = "2025-08-07T08:24:36.267Z" }, - { url = "https://files.pythonhosted.org/packages/8b/48/f50b2ab2fbb422fbb389fe296e70b7a6b5ea31b263ada5c61377e710a924/rpds_py-0.27.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:a029be818059870664157194e46ce0e995082ac49926f1423c1f058534d2aaa9", size = 555928, upload-time = "2025-08-07T08:24:37.573Z" }, - { url = "https://files.pythonhosted.org/packages/98/41/b18eb51045d06887666c3560cd4bbb6819127b43d758f5adb82b5f56f7d1/rpds_py-0.27.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:3841f66c1ffdc6cebce8aed64e36db71466f1dc23c0d9a5592e2a782a3042c79", size = 585527, upload-time = "2025-08-07T08:24:39.391Z" }, - { url = "https://files.pythonhosted.org/packages/be/03/a3dd6470fc76499959b00ae56295b76b4bdf7c6ffc60d62006b1217567e1/rpds_py-0.27.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:42894616da0fc0dcb2ec08a77896c3f56e9cb2f4b66acd76fc8992c3557ceb1c", size = 554211, upload-time = "2025-08-07T08:24:40.6Z" }, - { url = "https://files.pythonhosted.org/packages/bf/d1/ee5fd1be395a07423ac4ca0bcc05280bf95db2b155d03adefeb47d5ebf7e/rpds_py-0.27.0-cp313-cp313t-win32.whl", hash = "sha256:b1fef1f13c842a39a03409e30ca0bf87b39a1e2a305a9924deadb75a43105d23", size = 216624, upload-time = "2025-08-07T08:24:42.204Z" }, - { url = "https://files.pythonhosted.org/packages/1c/94/4814c4c858833bf46706f87349c37ca45e154da7dbbec9ff09f1abeb08cc/rpds_py-0.27.0-cp313-cp313t-win_amd64.whl", hash = "sha256:183f5e221ba3e283cd36fdfbe311d95cd87699a083330b4f792543987167eff1", size = 230007, upload-time = "2025-08-07T08:24:43.329Z" }, - { url = "https://files.pythonhosted.org/packages/0e/a5/8fffe1c7dc7c055aa02df310f9fb71cfc693a4d5ccc5de2d3456ea5fb022/rpds_py-0.27.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:f3cd110e02c5bf17d8fb562f6c9df5c20e73029d587cf8602a2da6c5ef1e32cb", size = 362595, upload-time = "2025-08-07T08:24:44.478Z" }, - { url = "https://files.pythonhosted.org/packages/bc/c7/4e4253fd2d4bb0edbc0b0b10d9f280612ca4f0f990e3c04c599000fe7d71/rpds_py-0.27.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:8d0e09cf4863c74106b5265c2c310f36146e2b445ff7b3018a56799f28f39f6f", size = 347252, upload-time = "2025-08-07T08:24:45.678Z" }, - { url = "https://files.pythonhosted.org/packages/f3/c8/3d1a954d30f0174dd6baf18b57c215da03cf7846a9d6e0143304e784cddc/rpds_py-0.27.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:64f689ab822f9b5eb6dfc69893b4b9366db1d2420f7db1f6a2adf2a9ca15ad64", size = 384886, upload-time = "2025-08-07T08:24:46.86Z" }, - { url = "https://files.pythonhosted.org/packages/e0/52/3c5835f2df389832b28f9276dd5395b5a965cea34226e7c88c8fbec2093c/rpds_py-0.27.0-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e36c80c49853b3ffda7aa1831bf175c13356b210c73128c861f3aa93c3cc4015", size = 399716, upload-time = "2025-08-07T08:24:48.174Z" }, - { url = "https://files.pythonhosted.org/packages/40/73/176e46992461a1749686a2a441e24df51ff86b99c2d34bf39f2a5273b987/rpds_py-0.27.0-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6de6a7f622860af0146cb9ee148682ff4d0cea0b8fd3ad51ce4d40efb2f061d0", size = 517030, upload-time = "2025-08-07T08:24:49.52Z" }, - { url = "https://files.pythonhosted.org/packages/79/2a/7266c75840e8c6e70effeb0d38922a45720904f2cd695e68a0150e5407e2/rpds_py-0.27.0-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4045e2fc4b37ec4b48e8907a5819bdd3380708c139d7cc358f03a3653abedb89", size = 408448, upload-time = "2025-08-07T08:24:50.727Z" }, - { url = "https://files.pythonhosted.org/packages/e6/5f/a7efc572b8e235093dc6cf39f4dbc8a7f08e65fdbcec7ff4daeb3585eef1/rpds_py-0.27.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9da162b718b12c4219eeeeb68a5b7552fbc7aadedf2efee440f88b9c0e54b45d", size = 387320, upload-time = "2025-08-07T08:24:52.004Z" }, - { url = "https://files.pythonhosted.org/packages/a2/eb/9ff6bc92efe57cf5a2cb74dee20453ba444b6fdc85275d8c99e0d27239d1/rpds_py-0.27.0-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:0665be515767dc727ffa5f74bd2ef60b0ff85dad6bb8f50d91eaa6b5fb226f51", size = 407414, upload-time = "2025-08-07T08:24:53.664Z" }, - { url = "https://files.pythonhosted.org/packages/fb/bd/3b9b19b00d5c6e1bd0f418c229ab0f8d3b110ddf7ec5d9d689ef783d0268/rpds_py-0.27.0-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:203f581accef67300a942e49a37d74c12ceeef4514874c7cede21b012613ca2c", size = 420766, upload-time = "2025-08-07T08:24:55.917Z" }, - { url = "https://files.pythonhosted.org/packages/17/6b/521a7b1079ce16258c70805166e3ac6ec4ee2139d023fe07954dc9b2d568/rpds_py-0.27.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7873b65686a6471c0037139aa000d23fe94628e0daaa27b6e40607c90e3f5ec4", size = 562409, upload-time = "2025-08-07T08:24:57.17Z" }, - { url = "https://files.pythonhosted.org/packages/8b/bf/65db5bfb14ccc55e39de8419a659d05a2a9cd232f0a699a516bb0991da7b/rpds_py-0.27.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:249ab91ceaa6b41abc5f19513cb95b45c6f956f6b89f1fe3d99c81255a849f9e", size = 590793, upload-time = "2025-08-07T08:24:58.388Z" }, - { url = "https://files.pythonhosted.org/packages/db/b8/82d368b378325191ba7aae8f40f009b78057b598d4394d1f2cdabaf67b3f/rpds_py-0.27.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:d2f184336bc1d6abfaaa1262ed42739c3789b1e3a65a29916a615307d22ffd2e", size = 558178, upload-time = "2025-08-07T08:24:59.756Z" }, - { url = "https://files.pythonhosted.org/packages/f6/ff/f270bddbfbc3812500f8131b1ebbd97afd014cd554b604a3f73f03133a36/rpds_py-0.27.0-cp314-cp314-win32.whl", hash = "sha256:d3c622c39f04d5751408f5b801ecb527e6e0a471b367f420a877f7a660d583f6", size = 222355, upload-time = "2025-08-07T08:25:01.027Z" }, - { url = "https://files.pythonhosted.org/packages/bf/20/fdab055b1460c02ed356a0e0b0a78c1dd32dc64e82a544f7b31c9ac643dc/rpds_py-0.27.0-cp314-cp314-win_amd64.whl", hash = "sha256:cf824aceaeffff029ccfba0da637d432ca71ab21f13e7f6f5179cd88ebc77a8a", size = 234007, upload-time = "2025-08-07T08:25:02.268Z" }, - { url = "https://files.pythonhosted.org/packages/4d/a8/694c060005421797a3be4943dab8347c76c2b429a9bef68fb2c87c9e70c7/rpds_py-0.27.0-cp314-cp314-win_arm64.whl", hash = "sha256:86aca1616922b40d8ac1b3073a1ead4255a2f13405e5700c01f7c8d29a03972d", size = 223527, upload-time = "2025-08-07T08:25:03.45Z" }, - { url = "https://files.pythonhosted.org/packages/1e/f9/77f4c90f79d2c5ca8ce6ec6a76cb4734ee247de6b3a4f337e289e1f00372/rpds_py-0.27.0-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:341d8acb6724c0c17bdf714319c393bb27f6d23d39bc74f94221b3e59fc31828", size = 359469, upload-time = "2025-08-07T08:25:04.648Z" }, - { url = "https://files.pythonhosted.org/packages/c0/22/b97878d2f1284286fef4172069e84b0b42b546ea7d053e5fb7adb9ac6494/rpds_py-0.27.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:6b96b0b784fe5fd03beffff2b1533dc0d85e92bab8d1b2c24ef3a5dc8fac5669", size = 343960, upload-time = "2025-08-07T08:25:05.863Z" }, - { url = "https://files.pythonhosted.org/packages/b1/b0/dfd55b5bb480eda0578ae94ef256d3061d20b19a0f5e18c482f03e65464f/rpds_py-0.27.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0c431bfb91478d7cbe368d0a699978050d3b112d7f1d440a41e90faa325557fd", size = 380201, upload-time = "2025-08-07T08:25:07.513Z" }, - { url = "https://files.pythonhosted.org/packages/28/22/e1fa64e50d58ad2b2053077e3ec81a979147c43428de9e6de68ddf6aff4e/rpds_py-0.27.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:20e222a44ae9f507d0f2678ee3dd0c45ec1e930f6875d99b8459631c24058aec", size = 392111, upload-time = "2025-08-07T08:25:09.149Z" }, - { url = "https://files.pythonhosted.org/packages/49/f9/43ab7a43e97aedf6cea6af70fdcbe18abbbc41d4ae6cdec1bfc23bbad403/rpds_py-0.27.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:184f0d7b342967f6cda94a07d0e1fae177d11d0b8f17d73e06e36ac02889f303", size = 515863, upload-time = "2025-08-07T08:25:10.431Z" }, - { url = "https://files.pythonhosted.org/packages/38/9b/9bd59dcc636cd04d86a2d20ad967770bf348f5eb5922a8f29b547c074243/rpds_py-0.27.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a00c91104c173c9043bc46f7b30ee5e6d2f6b1149f11f545580f5d6fdff42c0b", size = 402398, upload-time = "2025-08-07T08:25:11.819Z" }, - { url = "https://files.pythonhosted.org/packages/71/bf/f099328c6c85667aba6b66fa5c35a8882db06dcd462ea214be72813a0dd2/rpds_py-0.27.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f7a37dd208f0d658e0487522078b1ed68cd6bce20ef4b5a915d2809b9094b410", size = 384665, upload-time = "2025-08-07T08:25:13.194Z" }, - { url = "https://files.pythonhosted.org/packages/a9/c5/9c1f03121ece6634818490bd3c8be2c82a70928a19de03467fb25a3ae2a8/rpds_py-0.27.0-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:92f3b3ec3e6008a1fe00b7c0946a170f161ac00645cde35e3c9a68c2475e8156", size = 400405, upload-time = "2025-08-07T08:25:14.417Z" }, - { url = "https://files.pythonhosted.org/packages/b5/b8/e25d54af3e63ac94f0c16d8fe143779fe71ff209445a0c00d0f6984b6b2c/rpds_py-0.27.0-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a1b3db5fae5cbce2131b7420a3f83553d4d89514c03d67804ced36161fe8b6b2", size = 413179, upload-time = "2025-08-07T08:25:15.664Z" }, - { url = "https://files.pythonhosted.org/packages/f9/d1/406b3316433fe49c3021546293a04bc33f1478e3ec7950215a7fce1a1208/rpds_py-0.27.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:5355527adaa713ab693cbce7c1e0ec71682f599f61b128cf19d07e5c13c9b1f1", size = 556895, upload-time = "2025-08-07T08:25:17.061Z" }, - { url = "https://files.pythonhosted.org/packages/5f/bc/3697c0c21fcb9a54d46ae3b735eb2365eea0c2be076b8f770f98e07998de/rpds_py-0.27.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:fcc01c57ce6e70b728af02b2401c5bc853a9e14eb07deda30624374f0aebfe42", size = 585464, upload-time = "2025-08-07T08:25:18.406Z" }, - { url = "https://files.pythonhosted.org/packages/63/09/ee1bb5536f99f42c839b177d552f6114aa3142d82f49cef49261ed28dbe0/rpds_py-0.27.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:3001013dae10f806380ba739d40dee11db1ecb91684febb8406a87c2ded23dae", size = 555090, upload-time = "2025-08-07T08:25:20.461Z" }, - { url = "https://files.pythonhosted.org/packages/7d/2c/363eada9e89f7059199d3724135a86c47082cbf72790d6ba2f336d146ddb/rpds_py-0.27.0-cp314-cp314t-win32.whl", hash = "sha256:0f401c369186a5743694dd9fc08cba66cf70908757552e1f714bfc5219c655b5", size = 218001, upload-time = "2025-08-07T08:25:21.761Z" }, - { url = "https://files.pythonhosted.org/packages/e2/3f/d6c216ed5199c9ef79e2a33955601f454ed1e7420a93b89670133bca5ace/rpds_py-0.27.0-cp314-cp314t-win_amd64.whl", hash = "sha256:8a1dca5507fa1337f75dcd5070218b20bc68cf8844271c923c1b79dfcbc20391", size = 230993, upload-time = "2025-08-07T08:25:23.34Z" }, - { url = "https://files.pythonhosted.org/packages/59/64/72ab5b911fdcc48058359b0e786e5363e3fde885156116026f1a2ba9a5b5/rpds_py-0.27.0-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:e6491658dd2569f05860bad645569145c8626ac231877b0fb2d5f9bcb7054089", size = 371658, upload-time = "2025-08-07T08:26:02.369Z" }, - { url = "https://files.pythonhosted.org/packages/6c/4b/90ff04b4da055db53d8fea57640d8d5d55456343a1ec9a866c0ecfe10fd1/rpds_py-0.27.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:bec77545d188f8bdd29d42bccb9191682a46fb2e655e3d1fb446d47c55ac3b8d", size = 355529, upload-time = "2025-08-07T08:26:03.83Z" }, - { url = "https://files.pythonhosted.org/packages/a4/be/527491fb1afcd86fc5ce5812eb37bc70428ee017d77fee20de18155c3937/rpds_py-0.27.0-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:25a4aebf8ca02bbb90a9b3e7a463bbf3bee02ab1c446840ca07b1695a68ce424", size = 382822, upload-time = "2025-08-07T08:26:05.52Z" }, - { url = "https://files.pythonhosted.org/packages/e0/a5/dcdb8725ce11e6d0913e6fcf782a13f4b8a517e8acc70946031830b98441/rpds_py-0.27.0-pp311-pypy311_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:44524b96481a4c9b8e6c46d6afe43fa1fb485c261e359fbe32b63ff60e3884d8", size = 397233, upload-time = "2025-08-07T08:26:07.179Z" }, - { url = "https://files.pythonhosted.org/packages/33/f9/0947920d1927e9f144660590cc38cadb0795d78fe0d9aae0ef71c1513b7c/rpds_py-0.27.0-pp311-pypy311_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:45d04a73c54b6a5fd2bab91a4b5bc8b426949586e61340e212a8484919183859", size = 514892, upload-time = "2025-08-07T08:26:08.622Z" }, - { url = "https://files.pythonhosted.org/packages/1d/ed/d1343398c1417c68f8daa1afce56ef6ce5cc587daaf98e29347b00a80ff2/rpds_py-0.27.0-pp311-pypy311_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:343cf24de9ed6c728abefc5d5c851d5de06497caa7ac37e5e65dd572921ed1b5", size = 402733, upload-time = "2025-08-07T08:26:10.433Z" }, - { url = "https://files.pythonhosted.org/packages/1d/0b/646f55442cd14014fb64d143428f25667a100f82092c90087b9ea7101c74/rpds_py-0.27.0-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7aed8118ae20515974650d08eb724150dc2e20c2814bcc307089569995e88a14", size = 384447, upload-time = "2025-08-07T08:26:11.847Z" }, - { url = "https://files.pythonhosted.org/packages/4b/15/0596ef7529828e33a6c81ecf5013d1dd33a511a3e0be0561f83079cda227/rpds_py-0.27.0-pp311-pypy311_pp73-manylinux_2_31_riscv64.whl", hash = "sha256:af9d4fd79ee1cc8e7caf693ee02737daabfc0fcf2773ca0a4735b356c8ad6f7c", size = 402502, upload-time = "2025-08-07T08:26:13.537Z" }, - { url = "https://files.pythonhosted.org/packages/c3/8d/986af3c42f8454a6cafff8729d99fb178ae9b08a9816325ac7a8fa57c0c0/rpds_py-0.27.0-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f0396e894bd1e66c74ecbc08b4f6a03dc331140942c4b1d345dd131b68574a60", size = 416651, upload-time = "2025-08-07T08:26:14.923Z" }, - { url = "https://files.pythonhosted.org/packages/e9/9a/b4ec3629b7b447e896eec574469159b5b60b7781d3711c914748bf32de05/rpds_py-0.27.0-pp311-pypy311_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:59714ab0a5af25d723d8e9816638faf7f4254234decb7d212715c1aa71eee7be", size = 559460, upload-time = "2025-08-07T08:26:16.295Z" }, - { url = "https://files.pythonhosted.org/packages/61/63/d1e127b40c3e4733b3a6f26ae7a063cdf2bc1caa5272c89075425c7d397a/rpds_py-0.27.0-pp311-pypy311_pp73-musllinux_1_2_i686.whl", hash = "sha256:88051c3b7d5325409f433c5a40328fcb0685fc04e5db49ff936e910901d10114", size = 588072, upload-time = "2025-08-07T08:26:17.776Z" }, - { url = "https://files.pythonhosted.org/packages/04/7e/8ffc71a8f6833d9c9fb999f5b0ee736b8b159fd66968e05c7afc2dbcd57e/rpds_py-0.27.0-pp311-pypy311_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:181bc29e59e5e5e6e9d63b143ff4d5191224d355e246b5a48c88ce6b35c4e466", size = 555083, upload-time = "2025-08-07T08:26:19.301Z" }, +version = "0.27.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e9/dd/2c0cbe774744272b0ae725f44032c77bdcab6e8bcf544bffa3b6e70c8dba/rpds_py-0.27.1.tar.gz", hash = "sha256:26a1c73171d10b7acccbded82bf6a586ab8203601e565badc74bbbf8bc5a10f8", size = 27479, upload-time = "2025-08-27T12:16:36.024Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b5/c1/7907329fbef97cbd49db6f7303893bd1dd5a4a3eae415839ffdfb0762cae/rpds_py-0.27.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:be898f271f851f68b318872ce6ebebbc62f303b654e43bf72683dbdc25b7c881", size = 371063, upload-time = "2025-08-27T12:12:47.856Z" }, + { url = "https://files.pythonhosted.org/packages/11/94/2aab4bc86228bcf7c48760990273653a4900de89c7537ffe1b0d6097ed39/rpds_py-0.27.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:62ac3d4e3e07b58ee0ddecd71d6ce3b1637de2d373501412df395a0ec5f9beb5", size = 353210, upload-time = "2025-08-27T12:12:49.187Z" }, + { url = "https://files.pythonhosted.org/packages/3a/57/f5eb3ecf434342f4f1a46009530e93fd201a0b5b83379034ebdb1d7c1a58/rpds_py-0.27.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4708c5c0ceb2d034f9991623631d3d23cb16e65c83736ea020cdbe28d57c0a0e", size = 381636, upload-time = "2025-08-27T12:12:50.492Z" }, + { url = "https://files.pythonhosted.org/packages/ae/f4/ef95c5945e2ceb5119571b184dd5a1cc4b8541bbdf67461998cfeac9cb1e/rpds_py-0.27.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:abfa1171a9952d2e0002aba2ad3780820b00cc3d9c98c6630f2e93271501f66c", size = 394341, upload-time = "2025-08-27T12:12:52.024Z" }, + { url = "https://files.pythonhosted.org/packages/5a/7e/4bd610754bf492d398b61725eb9598ddd5eb86b07d7d9483dbcd810e20bc/rpds_py-0.27.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4b507d19f817ebaca79574b16eb2ae412e5c0835542c93fe9983f1e432aca195", size = 523428, upload-time = "2025-08-27T12:12:53.779Z" }, + { url = "https://files.pythonhosted.org/packages/9f/e5/059b9f65a8c9149361a8b75094864ab83b94718344db511fd6117936ed2a/rpds_py-0.27.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:168b025f8fd8d8d10957405f3fdcef3dc20f5982d398f90851f4abc58c566c52", size = 402923, upload-time = "2025-08-27T12:12:55.15Z" }, + { url = "https://files.pythonhosted.org/packages/f5/48/64cabb7daced2968dd08e8a1b7988bf358d7bd5bcd5dc89a652f4668543c/rpds_py-0.27.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cb56c6210ef77caa58e16e8c17d35c63fe3f5b60fd9ba9d424470c3400bcf9ed", size = 384094, upload-time = "2025-08-27T12:12:57.194Z" }, + { url = "https://files.pythonhosted.org/packages/ae/e1/dc9094d6ff566bff87add8a510c89b9e158ad2ecd97ee26e677da29a9e1b/rpds_py-0.27.1-cp311-cp311-manylinux_2_31_riscv64.whl", hash = "sha256:d252f2d8ca0195faa707f8eb9368955760880b2b42a8ee16d382bf5dd807f89a", size = 401093, upload-time = "2025-08-27T12:12:58.985Z" }, + { url = "https://files.pythonhosted.org/packages/37/8e/ac8577e3ecdd5593e283d46907d7011618994e1d7ab992711ae0f78b9937/rpds_py-0.27.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6e5e54da1e74b91dbc7996b56640f79b195d5925c2b78efaa8c5d53e1d88edde", size = 417969, upload-time = "2025-08-27T12:13:00.367Z" }, + { url = "https://files.pythonhosted.org/packages/66/6d/87507430a8f74a93556fe55c6485ba9c259949a853ce407b1e23fea5ba31/rpds_py-0.27.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:ffce0481cc6e95e5b3f0a47ee17ffbd234399e6d532f394c8dce320c3b089c21", size = 558302, upload-time = "2025-08-27T12:13:01.737Z" }, + { url = "https://files.pythonhosted.org/packages/3a/bb/1db4781ce1dda3eecc735e3152659a27b90a02ca62bfeea17aee45cc0fbc/rpds_py-0.27.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:a205fdfe55c90c2cd8e540ca9ceba65cbe6629b443bc05db1f590a3db8189ff9", size = 589259, upload-time = "2025-08-27T12:13:03.127Z" }, + { url = "https://files.pythonhosted.org/packages/7b/0e/ae1c8943d11a814d01b482e1f8da903f88047a962dff9bbdadf3bd6e6fd1/rpds_py-0.27.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:689fb5200a749db0415b092972e8eba85847c23885c8543a8b0f5c009b1a5948", size = 554983, upload-time = "2025-08-27T12:13:04.516Z" }, + { url = "https://files.pythonhosted.org/packages/b2/d5/0b2a55415931db4f112bdab072443ff76131b5ac4f4dc98d10d2d357eb03/rpds_py-0.27.1-cp311-cp311-win32.whl", hash = "sha256:3182af66048c00a075010bc7f4860f33913528a4b6fc09094a6e7598e462fe39", size = 217154, upload-time = "2025-08-27T12:13:06.278Z" }, + { url = "https://files.pythonhosted.org/packages/24/75/3b7ffe0d50dc86a6a964af0d1cc3a4a2cdf437cb7b099a4747bbb96d1819/rpds_py-0.27.1-cp311-cp311-win_amd64.whl", hash = "sha256:b4938466c6b257b2f5c4ff98acd8128ec36b5059e5c8f8372d79316b1c36bb15", size = 228627, upload-time = "2025-08-27T12:13:07.625Z" }, + { url = "https://files.pythonhosted.org/packages/8d/3f/4fd04c32abc02c710f09a72a30c9a55ea3cc154ef8099078fd50a0596f8e/rpds_py-0.27.1-cp311-cp311-win_arm64.whl", hash = "sha256:2f57af9b4d0793e53266ee4325535a31ba48e2f875da81a9177c9926dfa60746", size = 220998, upload-time = "2025-08-27T12:13:08.972Z" }, + { url = "https://files.pythonhosted.org/packages/bd/fe/38de28dee5df58b8198c743fe2bea0c785c6d40941b9950bac4cdb71a014/rpds_py-0.27.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:ae2775c1973e3c30316892737b91f9283f9908e3cc7625b9331271eaaed7dc90", size = 361887, upload-time = "2025-08-27T12:13:10.233Z" }, + { url = "https://files.pythonhosted.org/packages/7c/9a/4b6c7eedc7dd90986bf0fab6ea2a091ec11c01b15f8ba0a14d3f80450468/rpds_py-0.27.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2643400120f55c8a96f7c9d858f7be0c88d383cd4653ae2cf0d0c88f668073e5", size = 345795, upload-time = "2025-08-27T12:13:11.65Z" }, + { url = "https://files.pythonhosted.org/packages/6f/0e/e650e1b81922847a09cca820237b0edee69416a01268b7754d506ade11ad/rpds_py-0.27.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:16323f674c089b0360674a4abd28d5042947d54ba620f72514d69be4ff64845e", size = 385121, upload-time = "2025-08-27T12:13:13.008Z" }, + { url = "https://files.pythonhosted.org/packages/1b/ea/b306067a712988e2bff00dcc7c8f31d26c29b6d5931b461aa4b60a013e33/rpds_py-0.27.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9a1f4814b65eacac94a00fc9a526e3fdafd78e439469644032032d0d63de4881", size = 398976, upload-time = "2025-08-27T12:13:14.368Z" }, + { url = "https://files.pythonhosted.org/packages/2c/0a/26dc43c8840cb8fe239fe12dbc8d8de40f2365e838f3d395835dde72f0e5/rpds_py-0.27.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7ba32c16b064267b22f1850a34051121d423b6f7338a12b9459550eb2096e7ec", size = 525953, upload-time = "2025-08-27T12:13:15.774Z" }, + { url = "https://files.pythonhosted.org/packages/22/14/c85e8127b573aaf3a0cbd7fbb8c9c99e735a4a02180c84da2a463b766e9e/rpds_py-0.27.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e5c20f33fd10485b80f65e800bbe5f6785af510b9f4056c5a3c612ebc83ba6cb", size = 407915, upload-time = "2025-08-27T12:13:17.379Z" }, + { url = "https://files.pythonhosted.org/packages/ed/7b/8f4fee9ba1fb5ec856eb22d725a4efa3deb47f769597c809e03578b0f9d9/rpds_py-0.27.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:466bfe65bd932da36ff279ddd92de56b042f2266d752719beb97b08526268ec5", size = 386883, upload-time = "2025-08-27T12:13:18.704Z" }, + { url = "https://files.pythonhosted.org/packages/86/47/28fa6d60f8b74fcdceba81b272f8d9836ac0340570f68f5df6b41838547b/rpds_py-0.27.1-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:41e532bbdcb57c92ba3be62c42e9f096431b4cf478da9bc3bc6ce5c38ab7ba7a", size = 405699, upload-time = "2025-08-27T12:13:20.089Z" }, + { url = "https://files.pythonhosted.org/packages/d0/fd/c5987b5e054548df56953a21fe2ebed51fc1ec7c8f24fd41c067b68c4a0a/rpds_py-0.27.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f149826d742b406579466283769a8ea448eed82a789af0ed17b0cd5770433444", size = 423713, upload-time = "2025-08-27T12:13:21.436Z" }, + { url = "https://files.pythonhosted.org/packages/ac/ba/3c4978b54a73ed19a7d74531be37a8bcc542d917c770e14d372b8daea186/rpds_py-0.27.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:80c60cfb5310677bd67cb1e85a1e8eb52e12529545441b43e6f14d90b878775a", size = 562324, upload-time = "2025-08-27T12:13:22.789Z" }, + { url = "https://files.pythonhosted.org/packages/b5/6c/6943a91768fec16db09a42b08644b960cff540c66aab89b74be6d4a144ba/rpds_py-0.27.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:7ee6521b9baf06085f62ba9c7a3e5becffbc32480d2f1b351559c001c38ce4c1", size = 593646, upload-time = "2025-08-27T12:13:24.122Z" }, + { url = "https://files.pythonhosted.org/packages/11/73/9d7a8f4be5f4396f011a6bb7a19fe26303a0dac9064462f5651ced2f572f/rpds_py-0.27.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a512c8263249a9d68cac08b05dd59d2b3f2061d99b322813cbcc14c3c7421998", size = 558137, upload-time = "2025-08-27T12:13:25.557Z" }, + { url = "https://files.pythonhosted.org/packages/6e/96/6772cbfa0e2485bcceef8071de7821f81aeac8bb45fbfd5542a3e8108165/rpds_py-0.27.1-cp312-cp312-win32.whl", hash = "sha256:819064fa048ba01b6dadc5116f3ac48610435ac9a0058bbde98e569f9e785c39", size = 221343, upload-time = "2025-08-27T12:13:26.967Z" }, + { url = "https://files.pythonhosted.org/packages/67/b6/c82f0faa9af1c6a64669f73a17ee0eeef25aff30bb9a1c318509efe45d84/rpds_py-0.27.1-cp312-cp312-win_amd64.whl", hash = "sha256:d9199717881f13c32c4046a15f024971a3b78ad4ea029e8da6b86e5aa9cf4594", size = 232497, upload-time = "2025-08-27T12:13:28.326Z" }, + { url = "https://files.pythonhosted.org/packages/e1/96/2817b44bd2ed11aebacc9251da03689d56109b9aba5e311297b6902136e2/rpds_py-0.27.1-cp312-cp312-win_arm64.whl", hash = "sha256:33aa65b97826a0e885ef6e278fbd934e98cdcfed80b63946025f01e2f5b29502", size = 222790, upload-time = "2025-08-27T12:13:29.71Z" }, + { url = "https://files.pythonhosted.org/packages/cc/77/610aeee8d41e39080c7e14afa5387138e3c9fa9756ab893d09d99e7d8e98/rpds_py-0.27.1-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:e4b9fcfbc021633863a37e92571d6f91851fa656f0180246e84cbd8b3f6b329b", size = 361741, upload-time = "2025-08-27T12:13:31.039Z" }, + { url = "https://files.pythonhosted.org/packages/3a/fc/c43765f201c6a1c60be2043cbdb664013def52460a4c7adace89d6682bf4/rpds_py-0.27.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1441811a96eadca93c517d08df75de45e5ffe68aa3089924f963c782c4b898cf", size = 345574, upload-time = "2025-08-27T12:13:32.902Z" }, + { url = "https://files.pythonhosted.org/packages/20/42/ee2b2ca114294cd9847d0ef9c26d2b0851b2e7e00bf14cc4c0b581df0fc3/rpds_py-0.27.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:55266dafa22e672f5a4f65019015f90336ed31c6383bd53f5e7826d21a0e0b83", size = 385051, upload-time = "2025-08-27T12:13:34.228Z" }, + { url = "https://files.pythonhosted.org/packages/fd/e8/1e430fe311e4799e02e2d1af7c765f024e95e17d651612425b226705f910/rpds_py-0.27.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d78827d7ac08627ea2c8e02c9e5b41180ea5ea1f747e9db0915e3adf36b62dcf", size = 398395, upload-time = "2025-08-27T12:13:36.132Z" }, + { url = "https://files.pythonhosted.org/packages/82/95/9dc227d441ff2670651c27a739acb2535ccaf8b351a88d78c088965e5996/rpds_py-0.27.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae92443798a40a92dc5f0b01d8a7c93adde0c4dc965310a29ae7c64d72b9fad2", size = 524334, upload-time = "2025-08-27T12:13:37.562Z" }, + { url = "https://files.pythonhosted.org/packages/87/01/a670c232f401d9ad461d9a332aa4080cd3cb1d1df18213dbd0d2a6a7ab51/rpds_py-0.27.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c46c9dd2403b66a2a3b9720ec4b74d4ab49d4fabf9f03dfdce2d42af913fe8d0", size = 407691, upload-time = "2025-08-27T12:13:38.94Z" }, + { url = "https://files.pythonhosted.org/packages/03/36/0a14aebbaa26fe7fab4780c76f2239e76cc95a0090bdb25e31d95c492fcd/rpds_py-0.27.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2efe4eb1d01b7f5f1939f4ef30ecea6c6b3521eec451fb93191bf84b2a522418", size = 386868, upload-time = "2025-08-27T12:13:40.192Z" }, + { url = "https://files.pythonhosted.org/packages/3b/03/8c897fb8b5347ff6c1cc31239b9611c5bf79d78c984430887a353e1409a1/rpds_py-0.27.1-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:15d3b4d83582d10c601f481eca29c3f138d44c92187d197aff663a269197c02d", size = 405469, upload-time = "2025-08-27T12:13:41.496Z" }, + { url = "https://files.pythonhosted.org/packages/da/07/88c60edc2df74850d496d78a1fdcdc7b54360a7f610a4d50008309d41b94/rpds_py-0.27.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4ed2e16abbc982a169d30d1a420274a709949e2cbdef119fe2ec9d870b42f274", size = 422125, upload-time = "2025-08-27T12:13:42.802Z" }, + { url = "https://files.pythonhosted.org/packages/6b/86/5f4c707603e41b05f191a749984f390dabcbc467cf833769b47bf14ba04f/rpds_py-0.27.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a75f305c9b013289121ec0f1181931975df78738cdf650093e6b86d74aa7d8dd", size = 562341, upload-time = "2025-08-27T12:13:44.472Z" }, + { url = "https://files.pythonhosted.org/packages/b2/92/3c0cb2492094e3cd9baf9e49bbb7befeceb584ea0c1a8b5939dca4da12e5/rpds_py-0.27.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:67ce7620704745881a3d4b0ada80ab4d99df390838839921f99e63c474f82cf2", size = 592511, upload-time = "2025-08-27T12:13:45.898Z" }, + { url = "https://files.pythonhosted.org/packages/10/bb/82e64fbb0047c46a168faa28d0d45a7851cd0582f850b966811d30f67ad8/rpds_py-0.27.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9d992ac10eb86d9b6f369647b6a3f412fc0075cfd5d799530e84d335e440a002", size = 557736, upload-time = "2025-08-27T12:13:47.408Z" }, + { url = "https://files.pythonhosted.org/packages/00/95/3c863973d409210da7fb41958172c6b7dbe7fc34e04d3cc1f10bb85e979f/rpds_py-0.27.1-cp313-cp313-win32.whl", hash = "sha256:4f75e4bd8ab8db624e02c8e2fc4063021b58becdbe6df793a8111d9343aec1e3", size = 221462, upload-time = "2025-08-27T12:13:48.742Z" }, + { url = "https://files.pythonhosted.org/packages/ce/2c/5867b14a81dc217b56d95a9f2a40fdbc56a1ab0181b80132beeecbd4b2d6/rpds_py-0.27.1-cp313-cp313-win_amd64.whl", hash = "sha256:f9025faafc62ed0b75a53e541895ca272815bec18abe2249ff6501c8f2e12b83", size = 232034, upload-time = "2025-08-27T12:13:50.11Z" }, + { url = "https://files.pythonhosted.org/packages/c7/78/3958f3f018c01923823f1e47f1cc338e398814b92d83cd278364446fac66/rpds_py-0.27.1-cp313-cp313-win_arm64.whl", hash = "sha256:ed10dc32829e7d222b7d3b93136d25a406ba9788f6a7ebf6809092da1f4d279d", size = 222392, upload-time = "2025-08-27T12:13:52.587Z" }, + { url = "https://files.pythonhosted.org/packages/01/76/1cdf1f91aed5c3a7bf2eba1f1c4e4d6f57832d73003919a20118870ea659/rpds_py-0.27.1-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:92022bbbad0d4426e616815b16bc4127f83c9a74940e1ccf3cfe0b387aba0228", size = 358355, upload-time = "2025-08-27T12:13:54.012Z" }, + { url = "https://files.pythonhosted.org/packages/c3/6f/bf142541229374287604caf3bb2a4ae17f0a580798fd72d3b009b532db4e/rpds_py-0.27.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:47162fdab9407ec3f160805ac3e154df042e577dd53341745fc7fb3f625e6d92", size = 342138, upload-time = "2025-08-27T12:13:55.791Z" }, + { url = "https://files.pythonhosted.org/packages/1a/77/355b1c041d6be40886c44ff5e798b4e2769e497b790f0f7fd1e78d17e9a8/rpds_py-0.27.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb89bec23fddc489e5d78b550a7b773557c9ab58b7946154a10a6f7a214a48b2", size = 380247, upload-time = "2025-08-27T12:13:57.683Z" }, + { url = "https://files.pythonhosted.org/packages/d6/a4/d9cef5c3946ea271ce2243c51481971cd6e34f21925af2783dd17b26e815/rpds_py-0.27.1-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e48af21883ded2b3e9eb48cb7880ad8598b31ab752ff3be6457001d78f416723", size = 390699, upload-time = "2025-08-27T12:13:59.137Z" }, + { url = "https://files.pythonhosted.org/packages/3a/06/005106a7b8c6c1a7e91b73169e49870f4af5256119d34a361ae5240a0c1d/rpds_py-0.27.1-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6f5b7bd8e219ed50299e58551a410b64daafb5017d54bbe822e003856f06a802", size = 521852, upload-time = "2025-08-27T12:14:00.583Z" }, + { url = "https://files.pythonhosted.org/packages/e5/3e/50fb1dac0948e17a02eb05c24510a8fe12d5ce8561c6b7b7d1339ab7ab9c/rpds_py-0.27.1-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:08f1e20bccf73b08d12d804d6e1c22ca5530e71659e6673bce31a6bb71c1e73f", size = 402582, upload-time = "2025-08-27T12:14:02.034Z" }, + { url = "https://files.pythonhosted.org/packages/cb/b0/f4e224090dc5b0ec15f31a02d746ab24101dd430847c4d99123798661bfc/rpds_py-0.27.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0dc5dceeaefcc96dc192e3a80bbe1d6c410c469e97bdd47494a7d930987f18b2", size = 384126, upload-time = "2025-08-27T12:14:03.437Z" }, + { url = "https://files.pythonhosted.org/packages/54/77/ac339d5f82b6afff1df8f0fe0d2145cc827992cb5f8eeb90fc9f31ef7a63/rpds_py-0.27.1-cp313-cp313t-manylinux_2_31_riscv64.whl", hash = "sha256:d76f9cc8665acdc0c9177043746775aa7babbf479b5520b78ae4002d889f5c21", size = 399486, upload-time = "2025-08-27T12:14:05.443Z" }, + { url = "https://files.pythonhosted.org/packages/d6/29/3e1c255eee6ac358c056a57d6d6869baa00a62fa32eea5ee0632039c50a3/rpds_py-0.27.1-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:134fae0e36022edad8290a6661edf40c023562964efea0cc0ec7f5d392d2aaef", size = 414832, upload-time = "2025-08-27T12:14:06.902Z" }, + { url = "https://files.pythonhosted.org/packages/3f/db/6d498b844342deb3fa1d030598db93937a9964fcf5cb4da4feb5f17be34b/rpds_py-0.27.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:eb11a4f1b2b63337cfd3b4d110af778a59aae51c81d195768e353d8b52f88081", size = 557249, upload-time = "2025-08-27T12:14:08.37Z" }, + { url = "https://files.pythonhosted.org/packages/60/f3/690dd38e2310b6f68858a331399b4d6dbb9132c3e8ef8b4333b96caf403d/rpds_py-0.27.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:13e608ac9f50a0ed4faec0e90ece76ae33b34c0e8656e3dceb9a7db994c692cd", size = 587356, upload-time = "2025-08-27T12:14:10.034Z" }, + { url = "https://files.pythonhosted.org/packages/86/e3/84507781cccd0145f35b1dc32c72675200c5ce8d5b30f813e49424ef68fc/rpds_py-0.27.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:dd2135527aa40f061350c3f8f89da2644de26cd73e4de458e79606384f4f68e7", size = 555300, upload-time = "2025-08-27T12:14:11.783Z" }, + { url = "https://files.pythonhosted.org/packages/e5/ee/375469849e6b429b3516206b4580a79e9ef3eb12920ddbd4492b56eaacbe/rpds_py-0.27.1-cp313-cp313t-win32.whl", hash = "sha256:3020724ade63fe320a972e2ffd93b5623227e684315adce194941167fee02688", size = 216714, upload-time = "2025-08-27T12:14:13.629Z" }, + { url = "https://files.pythonhosted.org/packages/21/87/3fc94e47c9bd0742660e84706c311a860dcae4374cf4a03c477e23ce605a/rpds_py-0.27.1-cp313-cp313t-win_amd64.whl", hash = "sha256:8ee50c3e41739886606388ba3ab3ee2aae9f35fb23f833091833255a31740797", size = 228943, upload-time = "2025-08-27T12:14:14.937Z" }, + { url = "https://files.pythonhosted.org/packages/70/36/b6e6066520a07cf029d385de869729a895917b411e777ab1cde878100a1d/rpds_py-0.27.1-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:acb9aafccaae278f449d9c713b64a9e68662e7799dbd5859e2c6b3c67b56d334", size = 362472, upload-time = "2025-08-27T12:14:16.333Z" }, + { url = "https://files.pythonhosted.org/packages/af/07/b4646032e0dcec0df9c73a3bd52f63bc6c5f9cda992f06bd0e73fe3fbebd/rpds_py-0.27.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:b7fb801aa7f845ddf601c49630deeeccde7ce10065561d92729bfe81bd21fb33", size = 345676, upload-time = "2025-08-27T12:14:17.764Z" }, + { url = "https://files.pythonhosted.org/packages/b0/16/2f1003ee5d0af4bcb13c0cf894957984c32a6751ed7206db2aee7379a55e/rpds_py-0.27.1-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fe0dd05afb46597b9a2e11c351e5e4283c741237e7f617ffb3252780cca9336a", size = 385313, upload-time = "2025-08-27T12:14:19.829Z" }, + { url = "https://files.pythonhosted.org/packages/05/cd/7eb6dd7b232e7f2654d03fa07f1414d7dfc980e82ba71e40a7c46fd95484/rpds_py-0.27.1-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b6dfb0e058adb12d8b1d1b25f686e94ffa65d9995a5157afe99743bf7369d62b", size = 399080, upload-time = "2025-08-27T12:14:21.531Z" }, + { url = "https://files.pythonhosted.org/packages/20/51/5829afd5000ec1cb60f304711f02572d619040aa3ec033d8226817d1e571/rpds_py-0.27.1-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ed090ccd235f6fa8bb5861684567f0a83e04f52dfc2e5c05f2e4b1309fcf85e7", size = 523868, upload-time = "2025-08-27T12:14:23.485Z" }, + { url = "https://files.pythonhosted.org/packages/05/2c/30eebca20d5db95720ab4d2faec1b5e4c1025c473f703738c371241476a2/rpds_py-0.27.1-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bf876e79763eecf3e7356f157540d6a093cef395b65514f17a356f62af6cc136", size = 408750, upload-time = "2025-08-27T12:14:24.924Z" }, + { url = "https://files.pythonhosted.org/packages/90/1a/cdb5083f043597c4d4276eae4e4c70c55ab5accec078da8611f24575a367/rpds_py-0.27.1-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:12ed005216a51b1d6e2b02a7bd31885fe317e45897de81d86dcce7d74618ffff", size = 387688, upload-time = "2025-08-27T12:14:27.537Z" }, + { url = "https://files.pythonhosted.org/packages/7c/92/cf786a15320e173f945d205ab31585cc43969743bb1a48b6888f7a2b0a2d/rpds_py-0.27.1-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:ee4308f409a40e50593c7e3bb8cbe0b4d4c66d1674a316324f0c2f5383b486f9", size = 407225, upload-time = "2025-08-27T12:14:28.981Z" }, + { url = "https://files.pythonhosted.org/packages/33/5c/85ee16df5b65063ef26017bef33096557a4c83fbe56218ac7cd8c235f16d/rpds_py-0.27.1-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0b08d152555acf1f455154d498ca855618c1378ec810646fcd7c76416ac6dc60", size = 423361, upload-time = "2025-08-27T12:14:30.469Z" }, + { url = "https://files.pythonhosted.org/packages/4b/8e/1c2741307fcabd1a334ecf008e92c4f47bb6f848712cf15c923becfe82bb/rpds_py-0.27.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:dce51c828941973a5684d458214d3a36fcd28da3e1875d659388f4f9f12cc33e", size = 562493, upload-time = "2025-08-27T12:14:31.987Z" }, + { url = "https://files.pythonhosted.org/packages/04/03/5159321baae9b2222442a70c1f988cbbd66b9be0675dd3936461269be360/rpds_py-0.27.1-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:c1476d6f29eb81aa4151c9a31219b03f1f798dc43d8af1250a870735516a1212", size = 592623, upload-time = "2025-08-27T12:14:33.543Z" }, + { url = "https://files.pythonhosted.org/packages/ff/39/c09fd1ad28b85bc1d4554a8710233c9f4cefd03d7717a1b8fbfd171d1167/rpds_py-0.27.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:3ce0cac322b0d69b63c9cdb895ee1b65805ec9ffad37639f291dd79467bee675", size = 558800, upload-time = "2025-08-27T12:14:35.436Z" }, + { url = "https://files.pythonhosted.org/packages/c5/d6/99228e6bbcf4baa764b18258f519a9035131d91b538d4e0e294313462a98/rpds_py-0.27.1-cp314-cp314-win32.whl", hash = "sha256:dfbfac137d2a3d0725758cd141f878bf4329ba25e34979797c89474a89a8a3a3", size = 221943, upload-time = "2025-08-27T12:14:36.898Z" }, + { url = "https://files.pythonhosted.org/packages/be/07/c802bc6b8e95be83b79bdf23d1aa61d68324cb1006e245d6c58e959e314d/rpds_py-0.27.1-cp314-cp314-win_amd64.whl", hash = "sha256:a6e57b0abfe7cc513450fcf529eb486b6e4d3f8aee83e92eb5f1ef848218d456", size = 233739, upload-time = "2025-08-27T12:14:38.386Z" }, + { url = "https://files.pythonhosted.org/packages/c8/89/3e1b1c16d4c2d547c5717377a8df99aee8099ff050f87c45cb4d5fa70891/rpds_py-0.27.1-cp314-cp314-win_arm64.whl", hash = "sha256:faf8d146f3d476abfee026c4ae3bdd9ca14236ae4e4c310cbd1cf75ba33d24a3", size = 223120, upload-time = "2025-08-27T12:14:39.82Z" }, + { url = "https://files.pythonhosted.org/packages/62/7e/dc7931dc2fa4a6e46b2a4fa744a9fe5c548efd70e0ba74f40b39fa4a8c10/rpds_py-0.27.1-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:ba81d2b56b6d4911ce735aad0a1d4495e808b8ee4dc58715998741a26874e7c2", size = 358944, upload-time = "2025-08-27T12:14:41.199Z" }, + { url = "https://files.pythonhosted.org/packages/e6/22/4af76ac4e9f336bfb1a5f240d18a33c6b2fcaadb7472ac7680576512b49a/rpds_py-0.27.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:84f7d509870098de0e864cad0102711c1e24e9b1a50ee713b65928adb22269e4", size = 342283, upload-time = "2025-08-27T12:14:42.699Z" }, + { url = "https://files.pythonhosted.org/packages/1c/15/2a7c619b3c2272ea9feb9ade67a45c40b3eeb500d503ad4c28c395dc51b4/rpds_py-0.27.1-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a9e960fc78fecd1100539f14132425e1d5fe44ecb9239f8f27f079962021523e", size = 380320, upload-time = "2025-08-27T12:14:44.157Z" }, + { url = "https://files.pythonhosted.org/packages/a2/7d/4c6d243ba4a3057e994bb5bedd01b5c963c12fe38dde707a52acdb3849e7/rpds_py-0.27.1-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:62f85b665cedab1a503747617393573995dac4600ff51869d69ad2f39eb5e817", size = 391760, upload-time = "2025-08-27T12:14:45.845Z" }, + { url = "https://files.pythonhosted.org/packages/b4/71/b19401a909b83bcd67f90221330bc1ef11bc486fe4e04c24388d28a618ae/rpds_py-0.27.1-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fed467af29776f6556250c9ed85ea5a4dd121ab56a5f8b206e3e7a4c551e48ec", size = 522476, upload-time = "2025-08-27T12:14:47.364Z" }, + { url = "https://files.pythonhosted.org/packages/e4/44/1a3b9715c0455d2e2f0f6df5ee6d6f5afdc423d0773a8a682ed2b43c566c/rpds_py-0.27.1-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f2729615f9d430af0ae6b36cf042cb55c0936408d543fb691e1a9e36648fd35a", size = 403418, upload-time = "2025-08-27T12:14:49.991Z" }, + { url = "https://files.pythonhosted.org/packages/1c/4b/fb6c4f14984eb56673bc868a66536f53417ddb13ed44b391998100a06a96/rpds_py-0.27.1-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1b207d881a9aef7ba753d69c123a35d96ca7cb808056998f6b9e8747321f03b8", size = 384771, upload-time = "2025-08-27T12:14:52.159Z" }, + { url = "https://files.pythonhosted.org/packages/c0/56/d5265d2d28b7420d7b4d4d85cad8ef891760f5135102e60d5c970b976e41/rpds_py-0.27.1-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:639fd5efec029f99b79ae47e5d7e00ad8a773da899b6309f6786ecaf22948c48", size = 400022, upload-time = "2025-08-27T12:14:53.859Z" }, + { url = "https://files.pythonhosted.org/packages/8f/e9/9f5fc70164a569bdd6ed9046486c3568d6926e3a49bdefeeccfb18655875/rpds_py-0.27.1-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fecc80cb2a90e28af8a9b366edacf33d7a91cbfe4c2c4544ea1246e949cfebeb", size = 416787, upload-time = "2025-08-27T12:14:55.673Z" }, + { url = "https://files.pythonhosted.org/packages/d4/64/56dd03430ba491db943a81dcdef115a985aac5f44f565cd39a00c766d45c/rpds_py-0.27.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:42a89282d711711d0a62d6f57d81aa43a1368686c45bc1c46b7f079d55692734", size = 557538, upload-time = "2025-08-27T12:14:57.245Z" }, + { url = "https://files.pythonhosted.org/packages/3f/36/92cc885a3129993b1d963a2a42ecf64e6a8e129d2c7cc980dbeba84e55fb/rpds_py-0.27.1-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:cf9931f14223de59551ab9d38ed18d92f14f055a5f78c1d8ad6493f735021bbb", size = 588512, upload-time = "2025-08-27T12:14:58.728Z" }, + { url = "https://files.pythonhosted.org/packages/dd/10/6b283707780a81919f71625351182b4f98932ac89a09023cb61865136244/rpds_py-0.27.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:f39f58a27cc6e59f432b568ed8429c7e1641324fbe38131de852cd77b2d534b0", size = 555813, upload-time = "2025-08-27T12:15:00.334Z" }, + { url = "https://files.pythonhosted.org/packages/04/2e/30b5ea18c01379da6272a92825dd7e53dc9d15c88a19e97932d35d430ef7/rpds_py-0.27.1-cp314-cp314t-win32.whl", hash = "sha256:d5fa0ee122dc09e23607a28e6d7b150da16c662e66409bbe85230e4c85bb528a", size = 217385, upload-time = "2025-08-27T12:15:01.937Z" }, + { url = "https://files.pythonhosted.org/packages/32/7d/97119da51cb1dd3f2f3c0805f155a3aa4a95fa44fe7d78ae15e69edf4f34/rpds_py-0.27.1-cp314-cp314t-win_amd64.whl", hash = "sha256:6567d2bb951e21232c2f660c24cf3470bb96de56cdcb3f071a83feeaff8a2772", size = 230097, upload-time = "2025-08-27T12:15:03.961Z" }, + { url = "https://files.pythonhosted.org/packages/0c/ed/e1fba02de17f4f76318b834425257c8ea297e415e12c68b4361f63e8ae92/rpds_py-0.27.1-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:cdfe4bb2f9fe7458b7453ad3c33e726d6d1c7c0a72960bcc23800d77384e42df", size = 371402, upload-time = "2025-08-27T12:15:51.561Z" }, + { url = "https://files.pythonhosted.org/packages/af/7c/e16b959b316048b55585a697e94add55a4ae0d984434d279ea83442e460d/rpds_py-0.27.1-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:8fabb8fd848a5f75a2324e4a84501ee3a5e3c78d8603f83475441866e60b94a3", size = 354084, upload-time = "2025-08-27T12:15:53.219Z" }, + { url = "https://files.pythonhosted.org/packages/de/c1/ade645f55de76799fdd08682d51ae6724cb46f318573f18be49b1e040428/rpds_py-0.27.1-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eda8719d598f2f7f3e0f885cba8646644b55a187762bec091fa14a2b819746a9", size = 383090, upload-time = "2025-08-27T12:15:55.158Z" }, + { url = "https://files.pythonhosted.org/packages/1f/27/89070ca9b856e52960da1472efcb6c20ba27cfe902f4f23ed095b9cfc61d/rpds_py-0.27.1-pp311-pypy311_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3c64d07e95606ec402a0a1c511fe003873fa6af630bda59bac77fac8b4318ebc", size = 394519, upload-time = "2025-08-27T12:15:57.238Z" }, + { url = "https://files.pythonhosted.org/packages/b3/28/be120586874ef906aa5aeeae95ae8df4184bc757e5b6bd1c729ccff45ed5/rpds_py-0.27.1-pp311-pypy311_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:93a2ed40de81bcff59aabebb626562d48332f3d028ca2036f1d23cbb52750be4", size = 523817, upload-time = "2025-08-27T12:15:59.237Z" }, + { url = "https://files.pythonhosted.org/packages/a8/ef/70cc197bc11cfcde02a86f36ac1eed15c56667c2ebddbdb76a47e90306da/rpds_py-0.27.1-pp311-pypy311_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:387ce8c44ae94e0ec50532d9cb0edce17311024c9794eb196b90e1058aadeb66", size = 403240, upload-time = "2025-08-27T12:16:00.923Z" }, + { url = "https://files.pythonhosted.org/packages/cf/35/46936cca449f7f518f2f4996e0e8344db4b57e2081e752441154089d2a5f/rpds_py-0.27.1-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aaf94f812c95b5e60ebaf8bfb1898a7d7cb9c1af5744d4a67fa47796e0465d4e", size = 385194, upload-time = "2025-08-27T12:16:02.802Z" }, + { url = "https://files.pythonhosted.org/packages/e1/62/29c0d3e5125c3270b51415af7cbff1ec587379c84f55a5761cc9efa8cd06/rpds_py-0.27.1-pp311-pypy311_pp73-manylinux_2_31_riscv64.whl", hash = "sha256:4848ca84d6ded9b58e474dfdbad4b8bfb450344c0551ddc8d958bf4b36aa837c", size = 402086, upload-time = "2025-08-27T12:16:04.806Z" }, + { url = "https://files.pythonhosted.org/packages/8f/66/03e1087679227785474466fdd04157fb793b3b76e3fcf01cbf4c693c1949/rpds_py-0.27.1-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2bde09cbcf2248b73c7c323be49b280180ff39fadcfe04e7b6f54a678d02a7cf", size = 419272, upload-time = "2025-08-27T12:16:06.471Z" }, + { url = "https://files.pythonhosted.org/packages/6a/24/e3e72d265121e00b063aef3e3501e5b2473cf1b23511d56e529531acf01e/rpds_py-0.27.1-pp311-pypy311_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:94c44ee01fd21c9058f124d2d4f0c9dc7634bec93cd4b38eefc385dabe71acbf", size = 560003, upload-time = "2025-08-27T12:16:08.06Z" }, + { url = "https://files.pythonhosted.org/packages/26/ca/f5a344c534214cc2d41118c0699fffbdc2c1bc7046f2a2b9609765ab9c92/rpds_py-0.27.1-pp311-pypy311_pp73-musllinux_1_2_i686.whl", hash = "sha256:df8b74962e35c9249425d90144e721eed198e6555a0e22a563d29fe4486b51f6", size = 590482, upload-time = "2025-08-27T12:16:10.137Z" }, + { url = "https://files.pythonhosted.org/packages/ce/08/4349bdd5c64d9d193c360aa9db89adeee6f6682ab8825dca0a3f535f434f/rpds_py-0.27.1-pp311-pypy311_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:dc23e6820e3b40847e2f4a7726462ba0cf53089512abe9ee16318c366494c17a", size = 556523, upload-time = "2025-08-27T12:16:12.188Z" }, ] [[package]] @@ -2268,11 +2284,11 @@ wheels = [ [[package]] name = "soupsieve" -version = "2.7" +version = "2.8" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/3f/f4/4a80cd6ef364b2e8b65b15816a843c0980f7a5a2b4dc701fc574952aa19f/soupsieve-2.7.tar.gz", hash = "sha256:ad282f9b6926286d2ead4750552c8a6142bc4c783fd66b0293547c8fe6ae126a", size = 103418, upload-time = "2025-04-20T18:50:08.518Z" } +sdist = { url = "https://files.pythonhosted.org/packages/6d/e6/21ccce3262dd4889aa3332e5a119a3491a95e8f60939870a3a035aabac0d/soupsieve-2.8.tar.gz", hash = "sha256:e2dd4a40a628cb5f28f6d4b0db8800b8f581b65bb380b97de22ba5ca8d72572f", size = 103472, upload-time = "2025-08-27T15:39:51.78Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/e7/9c/0e6afc12c269578be5c0c1c9f4b49a8d32770a080260c333ac04cc1c832d/soupsieve-2.7-py3-none-any.whl", hash = "sha256:6e60cc5c1ffaf1cebcc12e8188320b72071e922c2e897f737cadce79ad5d30c4", size = 36677, upload-time = "2025-04-20T18:50:07.196Z" }, + { url = "https://files.pythonhosted.org/packages/14/a0/bb38d3b76b8cae341dad93a2dd83ab7462e6dbcdd84d43f54ee60a8dc167/soupsieve-2.8-py3-none-any.whl", hash = "sha256:0cc76456a30e20f5d7f2e14a98a4ae2ee4e5abdc7c5ea0aafe795f344bc7984c", size = 36679, upload-time = "2025-08-27T15:39:50.179Z" }, ] [[package]] @@ -2655,11 +2671,11 @@ wheels = [ [[package]] name = "typing-extensions" -version = "4.14.1" +version = "4.15.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/98/5a/da40306b885cc8c09109dc2e1abd358d5684b1425678151cdaed4731c822/typing_extensions-4.14.1.tar.gz", hash = "sha256:38b39f4aeeab64884ce9f74c94263ef78f3c22467c8724005483154c26648d36", size = 107673, upload-time = "2025-07-04T13:28:34.16Z" } +sdist = { url = "https://files.pythonhosted.org/packages/72/94/1a15dd82efb362ac84269196e94cf00f187f7ed21c242792a923cdb1c61f/typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466", size = 109391, upload-time = "2025-08-25T13:49:26.313Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/b5/00/d631e67a838026495268c2f6884f3711a15a9a2a96cd244fdaea53b823fb/typing_extensions-4.14.1-py3-none-any.whl", hash = "sha256:d1e1e3b58374dc93031d6eda2420a48ea44a36c2b4766a4fdeb3710755731d76", size = 43906, upload-time = "2025-07-04T13:28:32.743Z" }, + { url = "https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548", size = 44614, upload-time = "2025-08-25T13:49:24.86Z" }, ] [[package]] @@ -2700,28 +2716,28 @@ wheels = [ [[package]] name = "uv" -version = "0.8.10" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/01/c8/e8a279be427bc685f5f6ffcaf04ab33e119bc504bd608582325654dc9b28/uv-0.8.10.tar.gz", hash = "sha256:af8a5526b0e331775a264fa0dbccfd53c183cb974f269a208af136d7561f9eb2", size = 3484570, upload-time = "2025-08-13T20:35:24.45Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/ad/00/4605a743cf18a881574442f2c2de7ef5282147f3b51601d0c91e4b6cff6e/uv-0.8.10-py3-none-linux_armv6l.whl", hash = "sha256:9ad21eeaa4156a1bf5ed85903f80db06e2c02badd3a587ba98d3171517960555", size = 18491669, upload-time = "2025-08-13T20:34:35.674Z" }, - { url = "https://files.pythonhosted.org/packages/26/e4/4d5cff7ea2eaa2c8bb8c88fd6937c5fd1e4463bca4232aa4e1ccc4e5f792/uv-0.8.10-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:defc50bb319be2d58be74a680710cd4b7697e88d5f79974eacd354df95f0b6b0", size = 18535975, upload-time = "2025-08-13T20:34:39.346Z" }, - { url = "https://files.pythonhosted.org/packages/a8/76/78f40228077514af4fa459ad9e6270de75fc89a089b3e78764ee54e0406b/uv-0.8.10-py3-none-macosx_11_0_arm64.whl", hash = "sha256:88df34c32555064fae459cce665757619fd1af7deb2dc393352b15d909d2d131", size = 17209654, upload-time = "2025-08-13T20:34:41.945Z" }, - { url = "https://files.pythonhosted.org/packages/9b/42/05c4597c98d8e3a08e352e148cb3ded08e2e7bed0eb0bf4ebacc5947a79d/uv-0.8.10-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:c4a493cd4b15b3aef11523531aff96a77a586666a63e842fa437966b7b7ee62d", size = 17800097, upload-time = "2025-08-13T20:34:44.144Z" }, - { url = "https://files.pythonhosted.org/packages/eb/7e/5225dad966f7333d37c69e02ebebd08f433b988b2b7a16d32a7ce7de1409/uv-0.8.10-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:86fe044c2be43977566a0d184a487edd7aace2febb757fd95927684b629ef50b", size = 18148771, upload-time = "2025-08-13T20:34:46.229Z" }, - { url = "https://files.pythonhosted.org/packages/90/99/380a607253fa9114d6490837faf56577c3aa3f7627cd221475ff33c847c8/uv-0.8.10-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4cc190d403a89e46d13cec83b6f8e8d7d07aaf1e5a996eac9a3f0c2a8cd92537", size = 18958576, upload-time = "2025-08-13T20:34:48.318Z" }, - { url = "https://files.pythonhosted.org/packages/a0/81/0b70cf49acb03f0b4d654d947216f9c4f6278adcaf9151b1d631faa5c6a6/uv-0.8.10-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:57b71dc79eff25a5419d3fe4a563d3b9397f55d789f685ef27f43f033b31f482", size = 20244856, upload-time = "2025-08-13T20:34:50.661Z" }, - { url = "https://files.pythonhosted.org/packages/96/a7/60a16660790065d1e4cf81b9a88450cde6095d0be242a7c8d7ad8ffaf1b6/uv-0.8.10-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:eb79a46d8099f563ef58237bf4e9009f876a40145e757ea883a92b24b724d01e", size = 19925999, upload-time = "2025-08-13T20:34:53.248Z" }, - { url = "https://files.pythonhosted.org/packages/57/c9/fdf511b55dbeed7e75811f5d44b2152f2cf977895f7af98584035adb287d/uv-0.8.10-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:38286d230daad82388469c8dc7a1d2f5dc279c11178319c886d1a88d7938e513", size = 19275418, upload-time = "2025-08-13T20:34:55.589Z" }, - { url = "https://files.pythonhosted.org/packages/e0/48/d3f1edfc5e60e0aec4a994cc3b609a29970cb5c63cf72eeb4795b465da89/uv-0.8.10-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ab072cd3bf2f9dc264659a1ff48ad91a910ac4830bcfe965e2d3f89c86646f46", size = 19256345, upload-time = "2025-08-13T20:34:58.485Z" }, - { url = "https://files.pythonhosted.org/packages/e7/7c/ddc1be8df60a421484a1f15c521618e8e887ea109adf02db281175576487/uv-0.8.10-py3-none-manylinux_2_28_aarch64.whl", hash = "sha256:3fdf89fc40af9902141c39ed943bcfca15664623363335eb032a44f22001e2b4", size = 18091725, upload-time = "2025-08-13T20:35:00.661Z" }, - { url = "https://files.pythonhosted.org/packages/6a/c3/f893d6872150ede53be6de0d7167fd2791cad11d83af46856d71ca432b57/uv-0.8.10-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:36a5ce708d52388c37043e7335f9eb3fea5a19a56166a2cc6adb365179a1cd77", size = 18973295, upload-time = "2025-08-13T20:35:03.289Z" }, - { url = "https://files.pythonhosted.org/packages/a0/43/56c902f8ebd4c13cefe7ff59d8c3ef4be33cb76f3903aed0936c2fc1f15f/uv-0.8.10-py3-none-musllinux_1_1_armv7l.whl", hash = "sha256:a5495b5a6e3111c03cf5e4dbdd598bc8fd1da887e3920d58cd5a2d4c8bc9a473", size = 18110100, upload-time = "2025-08-13T20:35:05.458Z" }, - { url = "https://files.pythonhosted.org/packages/0f/d5/44ed1228f930d530fdd013262a8fa6f4be73736f46b43a72d90561517466/uv-0.8.10-py3-none-musllinux_1_1_i686.whl", hash = "sha256:b3ff3c451fcd23ea78356d8c18e802d0e423cbe655273601e3ec039a51b33286", size = 18505545, upload-time = "2025-08-13T20:35:08.156Z" }, - { url = "https://files.pythonhosted.org/packages/63/c5/8ae29f3635b92609c294712a24659ef618c32f51e66d2b52d846a1cb487b/uv-0.8.10-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:31e4fc37ee94b94c032384a0957ad32ba7dce4ce6c04b4880fd3e31e25e51a82", size = 19393427, upload-time = "2025-08-13T20:35:11.806Z" }, - { url = "https://files.pythonhosted.org/packages/23/2c/eba3ae60b8de7062cb727cce0fb30c84e5975e1191f5fb6683b5abf73781/uv-0.8.10-py3-none-win32.whl", hash = "sha256:3e190cee3bb2b4f574a419eef87ae8e33f713e9cd6f856b83277ece70ad9ca9b", size = 18278764, upload-time = "2025-08-13T20:35:15.069Z" }, - { url = "https://files.pythonhosted.org/packages/97/ed/bce1c3833edf701a973535982ee8c38514054a4f5ebf0f69a14f652510b7/uv-0.8.10-py3-none-win_amd64.whl", hash = "sha256:b00637c63d5dfc9f879281c5c91db2bb909ab1f9ab275dab015e7fb6cac6be5b", size = 20267476, upload-time = "2025-08-13T20:35:18.52Z" }, - { url = "https://files.pythonhosted.org/packages/56/56/87859397617fd08ce513efe20f6cd6798bfafc9f675a233892449fd94d14/uv-0.8.10-py3-none-win_arm64.whl", hash = "sha256:e0a02bcec766eb0862b7082ab746b204add7d9fcaa62322502d159b5a7ccc54a", size = 18866639, upload-time = "2025-08-13T20:35:20.993Z" }, +version = "0.8.14" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e2/b0/c3bc06ba5f6b72ba3ad278e854292d81b7aaaea2b6988e40fdb892f813f8/uv-0.8.14.tar.gz", hash = "sha256:7c68e0cde3d048500c073696881c07c2bd97503fc77d7091e1454d3fd58febb4", size = 3543853, upload-time = "2025-08-28T21:55:59.769Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e8/a3/bf0a80a7770f5c11a735345073fdf085a031ecd0525ae229ceb3ed7496f5/uv-0.8.14-py3-none-linux_armv6l.whl", hash = "sha256:bae6621a72e6643f140c4e62f10d3a52d210ccdec48bf4f733e6a25d5739e533", size = 18810682, upload-time = "2025-08-28T21:55:07.027Z" }, + { url = "https://files.pythonhosted.org/packages/61/de/e8d3c1669edb70ae165ad6c06598ff237ddbc1dc743cc590a2c30c245b93/uv-0.8.14-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:2334945ef3dba395067164c7e25b0c1420d8fdab9637d33cb753b5dbe0499b2c", size = 18939300, upload-time = "2025-08-28T21:55:11.244Z" }, + { url = "https://files.pythonhosted.org/packages/dc/61/9e4c3382f79cef69229f4f301ce1b391121f5a9d1015dd82487e08f0d718/uv-0.8.14-py3-none-macosx_11_0_arm64.whl", hash = "sha256:9a65096847d3341713be92e98cb35d5315d172690032405e8ae4e1b0c366a19a", size = 17555624, upload-time = "2025-08-28T21:55:14.107Z" }, + { url = "https://files.pythonhosted.org/packages/03/6d/5200cba528844e33586fadae78c06c054774e7702063356795f6cc124331/uv-0.8.14-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:f7a5d72e4fefae57f675cf0ac0adb9e68fb638f3f95be142b7f072fc6fddfe3e", size = 18151749, upload-time = "2025-08-28T21:55:16.904Z" }, + { url = "https://files.pythonhosted.org/packages/5a/b6/6f9407a792f0ca566b61276cadbffa032cff4039847ac77c47959151f753/uv-0.8.14-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:935b602d40f0c6a41337de81a02850d6892b0c8c6b5d98543fa229d5bb247364", size = 18472626, upload-time = "2025-08-28T21:55:19.994Z" }, + { url = "https://files.pythonhosted.org/packages/14/a2/2eadfccb1d6aa3672c947071b18c50cee41bdb9c9dba6d8af011a5c44e50/uv-0.8.14-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:34286de8d1244f06124c5bd7b4bfb5ef5791c147e0aa4473c7856c02fedc58ff", size = 19292728, upload-time = "2025-08-28T21:55:22.441Z" }, + { url = "https://files.pythonhosted.org/packages/b6/db/96071cddd37e4bfc9bd10c4daab0942c3d610da92f32c74de07621990455/uv-0.8.14-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:d26ea49a595992bc58d31bb6a10660a8015d902b6845c8ceed1e011866013593", size = 20577332, upload-time = "2025-08-28T21:55:25.774Z" }, + { url = "https://files.pythonhosted.org/packages/c9/4c/8e0da19b4bd5612bd782a82a1869c71e8ea059b59c547230146d36583a39/uv-0.8.14-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2aa721841812e9a74cad883dbd0f6cf908309cc40a86ab33d3576a8b369595a9", size = 20317704, upload-time = "2025-08-28T21:55:28.537Z" }, + { url = "https://files.pythonhosted.org/packages/1c/f2/4ad6abe850e31663d3971eb4af4a3b6ef216870f4f2115ae65e72917ea02/uv-0.8.14-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5088fa0ceff698a3fb2464f5cd7ebb4af59aa85db4ba83150d4c3af027251228", size = 19615504, upload-time = "2025-08-28T21:55:31.695Z" }, + { url = "https://files.pythonhosted.org/packages/ed/6c/b86f5f2f5aeebb0028034ea180399af23c8cbc42748bba0672c9cabdde38/uv-0.8.14-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3853202f4eb0bedbe31b0b62b1323521e97306f44f8f4b6ed4bb13b636797873", size = 19605107, upload-time = "2025-08-28T21:55:34.33Z" }, + { url = "https://files.pythonhosted.org/packages/b4/04/7b019c63d26d296bf6dfd8ad9b86e51f84b2ec7f37d68f8b93138a3fa404/uv-0.8.14-py3-none-manylinux_2_28_aarch64.whl", hash = "sha256:e45047a89592a5b38c88caa6da5d1b70a05c9762ff1c5100f9700f85f533dc99", size = 18412515, upload-time = "2025-08-28T21:55:37.185Z" }, + { url = "https://files.pythonhosted.org/packages/59/b8/c277b6ff1e4fc6d2c4f000ebccef9c2879603875ab092390f7073b911bdf/uv-0.8.14-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:72971573f21e617267b3737750cdb8a9ae99862b06d23df7fde60fc9f8ef78d6", size = 19290057, upload-time = "2025-08-28T21:55:39.769Z" }, + { url = "https://files.pythonhosted.org/packages/ed/09/59f84ea996bc3bf52c88bc7ba2d988bc5edfd7d0a9aee7cc0500f77d83ce/uv-0.8.14-py3-none-musllinux_1_1_armv7l.whl", hash = "sha256:ab22d9712f6b06b04359cfaf625722a81fcd0f2335868738dbee26a79a93bd99", size = 18433918, upload-time = "2025-08-28T21:55:42.262Z" }, + { url = "https://files.pythonhosted.org/packages/fa/2c/8a76455ea1f578fab8a88457c4d50c28928860335d3420956b75661f5e7b/uv-0.8.14-py3-none-musllinux_1_1_i686.whl", hash = "sha256:b5003c30c44065b70e03f083d73af45c094f1f96d9c394acafd8f547c2aee4d0", size = 18800856, upload-time = "2025-08-28T21:55:44.697Z" }, + { url = "https://files.pythonhosted.org/packages/f7/87/16699c592d816325554702d771024fbe5ec39127bfbc06d5cb54843673bb/uv-0.8.14-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:dacfad1193c7facd3a414cc2f3468b4a79a07c565c776a3136f97527a628b960", size = 19704752, upload-time = "2025-08-28T21:55:47.375Z" }, + { url = "https://files.pythonhosted.org/packages/ce/e9/0cdeed22e6c540db493ea364040b17af09fabaa7a56c8ff02b9152819442/uv-0.8.14-py3-none-win32.whl", hash = "sha256:0a4abb2a327e3709ef02765dc392ee10e204275bdb107b492977f88633a1e6b0", size = 18630132, upload-time = "2025-08-28T21:55:51.988Z" }, + { url = "https://files.pythonhosted.org/packages/45/5e/9bf7004bd53e9279265d73a131fe2a6c7d74c1125c53e805b5e9f4047f37/uv-0.8.14-py3-none-win_amd64.whl", hash = "sha256:5091d588753bbbd1f120f13311ede2ae113d7ec2760e149fc502a237f2516075", size = 20672637, upload-time = "2025-08-28T21:55:55.341Z" }, + { url = "https://files.pythonhosted.org/packages/d8/7f/41074c81faa36a34d44524997c345a857bd82d7f73ea60e24dca606306ec/uv-0.8.14-py3-none-win_arm64.whl", hash = "sha256:7c424fd4561f4528d8b52fc8c16991d0ad0000d3ad12c82e01e722f314b2669d", size = 19171656, upload-time = "2025-08-28T21:55:57.799Z" }, ] [[package]] @@ -2826,14 +2842,14 @@ wheels = [ [[package]] name = "xarray" -version = "2025.7.1" +version = "2025.8.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "numpy" }, { name = "packaging" }, { name = "pandas" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/e8/c5/a31ba8605005ef080c3d35efc696ddd851aee0a7a22420f9afebec386281/xarray-2025.7.1.tar.gz", hash = "sha256:2884bf5672b540fcc6ff8c20a3196bda0d78fbfb4d67398d60526e97c2faceef", size = 3013717, upload-time = "2025-07-10T04:53:07.01Z" } +sdist = { url = "https://files.pythonhosted.org/packages/d2/55/18055bc943029d25fb8f260b7e3b1485c30646ccf503a5e4a744d31a3b78/xarray-2025.8.0.tar.gz", hash = "sha256:323d4169ce72d4ef849de2b0bd122f9cd2905b82c7558169930dc16070982bab", size = 3034425, upload-time = "2025-08-14T16:52:13.872Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/b2/ea/9554e5fb78eda4dbc9e9ccaf23034166fe3e9ea9af82ea6204b9578434bc/xarray-2025.7.1-py3-none-any.whl", hash = "sha256:e8647b659e53bd350d7c5a91c34dd4122ad6a3ca0bc41399d424a7c0273c7635", size = 1324464, upload-time = "2025-07-10T04:53:05.104Z" }, + { url = "https://files.pythonhosted.org/packages/e6/c8/0f8db9d9478de8d70cbcae2056588401e26168e269d6d9919bf2ecb01f78/xarray-2025.8.0-py3-none-any.whl", hash = "sha256:1c454f32b38c93df68e450238c9473fe21248b8572d42ddd58c5170bb30934ee", size = 1342279, upload-time = "2025-08-14T16:52:10.956Z" }, ] From 538e0da5f31607169cdead5e7a11d8f97b2bac24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Robert?= Date: Tue, 2 Sep 2025 19:21:53 +0200 Subject: [PATCH 452/521] DEP: drop unused runtime dependency on setuptools (#3098) * DEP: drop unused runtime dependency on setuptools * add myself to CITATION.cff --------- Co-authored-by: Nick Murphy --- CITATION.cff | 5 +++++ pyproject.toml | 1 - uv.lock | 11 ----------- 3 files changed, 5 insertions(+), 12 deletions(-) diff --git a/CITATION.cff b/CITATION.cff index 08ccfb6491..9e6ac99dc8 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -748,3 +748,8 @@ authors: - given-names: Carol family-names: Zhang alias: carolyz + +- given-names: ClĂ©ment + family-names: Robert + orcid: https://orcid.org/0000-0001-8629-7068 + alias: neutrinoceros diff --git a/pyproject.toml b/pyproject.toml index 5a6c148464..d72cddfc6f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -66,7 +66,6 @@ dependencies = [ "pandas>=2", "requests>=2.28", "scipy>=1.10", - "setuptools>=66", "tqdm>=4.65", "wrapt>=1.15", "xarray>=2023.7", diff --git a/uv.lock b/uv.lock index 0e5276601e..dbf92f9437 100644 --- a/uv.lock +++ b/uv.lock @@ -1553,7 +1553,6 @@ dependencies = [ { name = "pandas" }, { name = "requests" }, { name = "scipy" }, - { name = "setuptools" }, { name = "tqdm" }, { name = "wrapt" }, { name = "xarray" }, @@ -1632,7 +1631,6 @@ requires-dist = [ { name = "pytest-xdist", marker = "extra == 'tests'", specifier = ">=3.6.1" }, { name = "requests", specifier = ">=2.28" }, { name = "scipy", specifier = ">=1.10" }, - { name = "setuptools", specifier = ">=66" }, { name = "sphinx", marker = "extra == 'docs'", specifier = ">=8.2.3,<8.3" }, { name = "sphinx-changelog", marker = "extra == 'docs'", specifier = ">=1.5" }, { name = "sphinx-codeautolink", marker = "extra == 'docs'", specifier = "==0.15.2" }, @@ -2246,15 +2244,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/6e/6c/a76329897a7cae4937d403e623aa6aaea616a0bb5b36588f0b9d1c9a3739/scipy-1.16.1-cp314-cp314t-win_amd64.whl", hash = "sha256:c0c804d60492a0aad7f5b2bb1862f4548b990049e27e828391ff2bf6f7199998", size = 39427705, upload-time = "2025-07-27T16:31:53.96Z" }, ] -[[package]] -name = "setuptools" -version = "80.9.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/18/5d/3bf57dcd21979b887f014ea83c24ae194cfcd12b9e0fda66b957c69d1fca/setuptools-80.9.0.tar.gz", hash = "sha256:f36b47402ecde768dbfafc46e8e4207b4360c654f1f3bb84475f0a28628fb19c", size = 1319958, upload-time = "2025-05-27T00:56:51.443Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/a3/dc/17031897dae0efacfea57dfd3a82fdd2a2aeb58e0ff71b77b87e44edc772/setuptools-80.9.0-py3-none-any.whl", hash = "sha256:062d34222ad13e0cc312a4c02d73f059e86a4acbfbdea8f8f76b28c99f306922", size = 1201486, upload-time = "2025-05-27T00:56:49.664Z" }, -] - [[package]] name = "six" version = "1.17.0" From 3b03d7fae88c3a838cefd711da7b8f6ecbcc61d4 Mon Sep 17 00:00:00 2001 From: "plasmapy-requirements-bot[bot]" <134649236+plasmapy-requirements-bot[bot]@users.noreply.github.com> Date: Thu, 4 Sep 2025 12:18:43 -0400 Subject: [PATCH 453/521] Update requirements with 'nox -s requirements' (#3102) Co-authored-by: namurphy <8931994+namurphy@users.noreply.github.com> --- uv.lock | 56 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/uv.lock b/uv.lock index dbf92f9437..29255230b8 100644 --- a/uv.lock +++ b/uv.lock @@ -655,15 +655,15 @@ wheels = [ [[package]] name = "hypothesis" -version = "6.138.13" +version = "6.138.14" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "attrs" }, { name = "sortedcontainers" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/37/42/9cd666af7fd2c3e604f055f756e80d537faba5327cc72cbd44177792d074/hypothesis-6.138.13.tar.gz", hash = "sha256:2bea91629b8b3bb103a5b51442b1037cede3aae26e56ec063c52b9d5d8eaf70b", size = 466041, upload-time = "2025-09-01T14:02:51.468Z" } +sdist = { url = "https://files.pythonhosted.org/packages/67/ed/2f65a358dd6b5bf3cee99dd2d3473eb9c5d5e50b50f83bbf8ef89ea96e39/hypothesis-6.138.14.tar.gz", hash = "sha256:5c1aa1ce3f1094b5c04ea03476017695bda408a174330e5275e40ddd06d3307a", size = 466152, upload-time = "2025-09-02T21:37:20.883Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/cc/82/823c202c8b349ff31a0718e46ff98074bebfb3aa20813091cea07821c25f/hypothesis-6.138.13-py3-none-any.whl", hash = "sha256:09f1130deb08e5d12fb3b59b55c113fd79debaaab9b224ffac17be8341de4326", size = 533564, upload-time = "2025-09-01T14:02:48.15Z" }, + { url = "https://files.pythonhosted.org/packages/55/2e/fcf7371887f45083472165b21b68a7f552049334e01dc3febe484bbb7bc4/hypothesis-6.138.14-py3-none-any.whl", hash = "sha256:1a702ecfff7034b3252d7a83328093388641cdba863197169559839e841c2154", size = 533626, upload-time = "2025-09-02T21:37:17.318Z" }, ] [[package]] @@ -2705,28 +2705,28 @@ wheels = [ [[package]] name = "uv" -version = "0.8.14" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e2/b0/c3bc06ba5f6b72ba3ad278e854292d81b7aaaea2b6988e40fdb892f813f8/uv-0.8.14.tar.gz", hash = "sha256:7c68e0cde3d048500c073696881c07c2bd97503fc77d7091e1454d3fd58febb4", size = 3543853, upload-time = "2025-08-28T21:55:59.769Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/e8/a3/bf0a80a7770f5c11a735345073fdf085a031ecd0525ae229ceb3ed7496f5/uv-0.8.14-py3-none-linux_armv6l.whl", hash = "sha256:bae6621a72e6643f140c4e62f10d3a52d210ccdec48bf4f733e6a25d5739e533", size = 18810682, upload-time = "2025-08-28T21:55:07.027Z" }, - { url = "https://files.pythonhosted.org/packages/61/de/e8d3c1669edb70ae165ad6c06598ff237ddbc1dc743cc590a2c30c245b93/uv-0.8.14-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:2334945ef3dba395067164c7e25b0c1420d8fdab9637d33cb753b5dbe0499b2c", size = 18939300, upload-time = "2025-08-28T21:55:11.244Z" }, - { url = "https://files.pythonhosted.org/packages/dc/61/9e4c3382f79cef69229f4f301ce1b391121f5a9d1015dd82487e08f0d718/uv-0.8.14-py3-none-macosx_11_0_arm64.whl", hash = "sha256:9a65096847d3341713be92e98cb35d5315d172690032405e8ae4e1b0c366a19a", size = 17555624, upload-time = "2025-08-28T21:55:14.107Z" }, - { url = "https://files.pythonhosted.org/packages/03/6d/5200cba528844e33586fadae78c06c054774e7702063356795f6cc124331/uv-0.8.14-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:f7a5d72e4fefae57f675cf0ac0adb9e68fb638f3f95be142b7f072fc6fddfe3e", size = 18151749, upload-time = "2025-08-28T21:55:16.904Z" }, - { url = "https://files.pythonhosted.org/packages/5a/b6/6f9407a792f0ca566b61276cadbffa032cff4039847ac77c47959151f753/uv-0.8.14-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:935b602d40f0c6a41337de81a02850d6892b0c8c6b5d98543fa229d5bb247364", size = 18472626, upload-time = "2025-08-28T21:55:19.994Z" }, - { url = "https://files.pythonhosted.org/packages/14/a2/2eadfccb1d6aa3672c947071b18c50cee41bdb9c9dba6d8af011a5c44e50/uv-0.8.14-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:34286de8d1244f06124c5bd7b4bfb5ef5791c147e0aa4473c7856c02fedc58ff", size = 19292728, upload-time = "2025-08-28T21:55:22.441Z" }, - { url = "https://files.pythonhosted.org/packages/b6/db/96071cddd37e4bfc9bd10c4daab0942c3d610da92f32c74de07621990455/uv-0.8.14-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:d26ea49a595992bc58d31bb6a10660a8015d902b6845c8ceed1e011866013593", size = 20577332, upload-time = "2025-08-28T21:55:25.774Z" }, - { url = "https://files.pythonhosted.org/packages/c9/4c/8e0da19b4bd5612bd782a82a1869c71e8ea059b59c547230146d36583a39/uv-0.8.14-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2aa721841812e9a74cad883dbd0f6cf908309cc40a86ab33d3576a8b369595a9", size = 20317704, upload-time = "2025-08-28T21:55:28.537Z" }, - { url = "https://files.pythonhosted.org/packages/1c/f2/4ad6abe850e31663d3971eb4af4a3b6ef216870f4f2115ae65e72917ea02/uv-0.8.14-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5088fa0ceff698a3fb2464f5cd7ebb4af59aa85db4ba83150d4c3af027251228", size = 19615504, upload-time = "2025-08-28T21:55:31.695Z" }, - { url = "https://files.pythonhosted.org/packages/ed/6c/b86f5f2f5aeebb0028034ea180399af23c8cbc42748bba0672c9cabdde38/uv-0.8.14-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3853202f4eb0bedbe31b0b62b1323521e97306f44f8f4b6ed4bb13b636797873", size = 19605107, upload-time = "2025-08-28T21:55:34.33Z" }, - { url = "https://files.pythonhosted.org/packages/b4/04/7b019c63d26d296bf6dfd8ad9b86e51f84b2ec7f37d68f8b93138a3fa404/uv-0.8.14-py3-none-manylinux_2_28_aarch64.whl", hash = "sha256:e45047a89592a5b38c88caa6da5d1b70a05c9762ff1c5100f9700f85f533dc99", size = 18412515, upload-time = "2025-08-28T21:55:37.185Z" }, - { url = "https://files.pythonhosted.org/packages/59/b8/c277b6ff1e4fc6d2c4f000ebccef9c2879603875ab092390f7073b911bdf/uv-0.8.14-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:72971573f21e617267b3737750cdb8a9ae99862b06d23df7fde60fc9f8ef78d6", size = 19290057, upload-time = "2025-08-28T21:55:39.769Z" }, - { url = "https://files.pythonhosted.org/packages/ed/09/59f84ea996bc3bf52c88bc7ba2d988bc5edfd7d0a9aee7cc0500f77d83ce/uv-0.8.14-py3-none-musllinux_1_1_armv7l.whl", hash = "sha256:ab22d9712f6b06b04359cfaf625722a81fcd0f2335868738dbee26a79a93bd99", size = 18433918, upload-time = "2025-08-28T21:55:42.262Z" }, - { url = "https://files.pythonhosted.org/packages/fa/2c/8a76455ea1f578fab8a88457c4d50c28928860335d3420956b75661f5e7b/uv-0.8.14-py3-none-musllinux_1_1_i686.whl", hash = "sha256:b5003c30c44065b70e03f083d73af45c094f1f96d9c394acafd8f547c2aee4d0", size = 18800856, upload-time = "2025-08-28T21:55:44.697Z" }, - { url = "https://files.pythonhosted.org/packages/f7/87/16699c592d816325554702d771024fbe5ec39127bfbc06d5cb54843673bb/uv-0.8.14-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:dacfad1193c7facd3a414cc2f3468b4a79a07c565c776a3136f97527a628b960", size = 19704752, upload-time = "2025-08-28T21:55:47.375Z" }, - { url = "https://files.pythonhosted.org/packages/ce/e9/0cdeed22e6c540db493ea364040b17af09fabaa7a56c8ff02b9152819442/uv-0.8.14-py3-none-win32.whl", hash = "sha256:0a4abb2a327e3709ef02765dc392ee10e204275bdb107b492977f88633a1e6b0", size = 18630132, upload-time = "2025-08-28T21:55:51.988Z" }, - { url = "https://files.pythonhosted.org/packages/45/5e/9bf7004bd53e9279265d73a131fe2a6c7d74c1125c53e805b5e9f4047f37/uv-0.8.14-py3-none-win_amd64.whl", hash = "sha256:5091d588753bbbd1f120f13311ede2ae113d7ec2760e149fc502a237f2516075", size = 20672637, upload-time = "2025-08-28T21:55:55.341Z" }, - { url = "https://files.pythonhosted.org/packages/d8/7f/41074c81faa36a34d44524997c345a857bd82d7f73ea60e24dca606306ec/uv-0.8.14-py3-none-win_arm64.whl", hash = "sha256:7c424fd4561f4528d8b52fc8c16991d0ad0000d3ad12c82e01e722f314b2669d", size = 19171656, upload-time = "2025-08-28T21:55:57.799Z" }, +version = "0.8.15" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/4f/7c/ab905b0425f88842f3d8e5da50491524f45a231b7a3dc9c988608162adb2/uv-0.8.15.tar.gz", hash = "sha256:8ea57b78be9f0911a2a50b6814d15aec7d1f8aa6517059dc8250b1414156f93a", size = 3602914, upload-time = "2025-09-03T14:32:15.552Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/67/1d/794352a01b40f2b0a0abe02f4f020219b3f59ee6ed900561be3b2b47a82b/uv-0.8.15-py3-none-linux_armv6l.whl", hash = "sha256:f02e6b8be08b840f86b8d5997b658b657acdda95bc216ecf62fce6c71414bdc7", size = 20136396, upload-time = "2025-09-03T14:31:30.404Z" }, + { url = "https://files.pythonhosted.org/packages/8f/89/528f01cff01eb8d10dd396f437656266443e399dda2fe4787b2cf6983698/uv-0.8.15-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:b0461bb1ad616c8bcb59c9b39ae9363245ca33815ebb1d11130385236eca21b9", size = 19297422, upload-time = "2025-09-03T14:31:34.412Z" }, + { url = "https://files.pythonhosted.org/packages/94/03/532af32a64d162894a1daebb7bc5028ba00225ea720cf0f287e934dc2bd5/uv-0.8.15-py3-none-macosx_11_0_arm64.whl", hash = "sha256:069eed78b79d1e88bced23e3d4303348edb0a0209e7cae0f20024c42430bf50f", size = 17882409, upload-time = "2025-09-03T14:31:36.993Z" }, + { url = "https://files.pythonhosted.org/packages/25/21/57df6d53fbadfa947d9d65a0926e5d8540199f49aa958d23be2707262a80/uv-0.8.15-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:333a93bb6af64f3b95ee99e82b4ea227e2af6362c45f91c89a24e2bfefb628f9", size = 19557216, upload-time = "2025-09-03T14:31:39.245Z" }, + { url = "https://files.pythonhosted.org/packages/68/22/c3784749e1c78119e5375ec34c6ea29e944192a601f17c746339611db237/uv-0.8.15-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7d5b19ac2bdda3d1456b5d6013af50b443ffb0e40c66d42874f71190a5364711", size = 19781097, upload-time = "2025-09-03T14:31:42.314Z" }, + { url = "https://files.pythonhosted.org/packages/00/28/0597599fb35408dd73e0a7d25108dca1fa6ce8f8d570c8f24151b0016eef/uv-0.8.15-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3330bb4f206a6180679a75a8b2e77ff0f933fcb06c028b6f4da877b10a5e4f95", size = 20741549, upload-time = "2025-09-03T14:31:44.574Z" }, + { url = "https://files.pythonhosted.org/packages/4f/61/98fa07981722660f5a3c28b987df99c2486f63d01b1256e6cca05a43bdce/uv-0.8.15-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:de9896ad4fa724ab317a8048f4891b9b23df1403b3724e96606f3be2dbbbf009", size = 22193727, upload-time = "2025-09-03T14:31:46.915Z" }, + { url = "https://files.pythonhosted.org/packages/fa/65/523188e11a759144b00f0fe48943f6d00706fcd9b5f561a54a07b9fd4541/uv-0.8.15-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:226360003e71084e0a73cbec72170e88634b045e95529654d067ea3741bba242", size = 21817550, upload-time = "2025-09-03T14:31:49.548Z" }, + { url = "https://files.pythonhosted.org/packages/99/3c/7898acf3d9ed2d3a2986cccc8209c14d3e9ac72dfaa616e49d329423b1d3/uv-0.8.15-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9488260536b35b94a79962fea76837f279c0cd0ae5021c761e66b311f47ffa70", size = 21024011, upload-time = "2025-09-03T14:31:51.789Z" }, + { url = "https://files.pythonhosted.org/packages/13/fc/e0da45ee179367dcc1e1040ad00ed8a99b78355d43024b0b5fc2edf5c389/uv-0.8.15-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:07765f99fd5fd3b257d7e210e8d0844c0a8fd111612e31fcca66a85656cc728e", size = 21009338, upload-time = "2025-09-03T14:31:54.104Z" }, + { url = "https://files.pythonhosted.org/packages/ce/5d/180904fa7ed49081b27f00e86f7220ca62cc098d7ef6459f0c69a8ae8f74/uv-0.8.15-py3-none-manylinux_2_28_aarch64.whl", hash = "sha256:c4868e6a4e1a8c777a5ba3cff452c405837318fb0b272ff203bfda0e1b8fc54d", size = 19799578, upload-time = "2025-09-03T14:31:56.47Z" }, + { url = "https://files.pythonhosted.org/packages/b6/09/fed823212e695b6765bdb8462850abffbe685cd965c4de905efed5e2e5c9/uv-0.8.15-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:3ec78a54a8eb0bbb9a9c653982390af84673657c8a48a0be6cdcb81d7d3e95c3", size = 20845428, upload-time = "2025-09-03T14:31:59.475Z" }, + { url = "https://files.pythonhosted.org/packages/b9/f3/9c4211897c00f79b7973a10800166e0580eaad20fe27f7c06adb7b248ac7/uv-0.8.15-py3-none-musllinux_1_1_armv7l.whl", hash = "sha256:a022a752d20da80d2a49fc0721522a81e3a32efe539152d756d84ebdba29dbc3", size = 19728113, upload-time = "2025-09-03T14:32:01.686Z" }, + { url = "https://files.pythonhosted.org/packages/3b/43/4ec6047150e2fba494d80d36b881a1a973835afa497ae9ccdf51828cae4f/uv-0.8.15-py3-none-musllinux_1_1_i686.whl", hash = "sha256:3780d2f3951d83e55812fdeb7eee233787b70c774497dbfc55b0fdf6063aa345", size = 20169115, upload-time = "2025-09-03T14:32:03.995Z" }, + { url = "https://files.pythonhosted.org/packages/ea/98/b4220bf462fb225c4a2d74ef4f105020238472b4b0da94ebc17a310d7b4e/uv-0.8.15-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:56f2451c9193ee1754ce1d8390ded68e9cb8dee0aaf7e2f38a9bd04d99be1be7", size = 21129804, upload-time = "2025-09-03T14:32:06.204Z" }, + { url = "https://files.pythonhosted.org/packages/5e/b8/40ce3d385254ac87a664a5d9a4664fac697e2734352f404382b81d03235b/uv-0.8.15-py3-none-win32.whl", hash = "sha256:89c7c10089e07d944c72d388fd88666c650dec2f8c79ca541e365f32843882c6", size = 19077103, upload-time = "2025-09-03T14:32:08.628Z" }, + { url = "https://files.pythonhosted.org/packages/2b/9d/081a0af395c0e307c0c930e80161a2aa551c25064cfb636d060574566fa4/uv-0.8.15-py3-none-win_amd64.whl", hash = "sha256:6aa824ab933dfafe11efe32e6541c6bcd65ecaa927e8e834ea6b14d3821020f6", size = 21179816, upload-time = "2025-09-03T14:32:11.42Z" }, + { url = "https://files.pythonhosted.org/packages/30/47/d8f50264a8c8ebbb9a44a8fed08b6e873d943adf299d944fe3a776ff5fbf/uv-0.8.15-py3-none-win_arm64.whl", hash = "sha256:a395fa1fc8948eacdd18e4592ed489fad13558b13fea6b3544cb16e5006c5b02", size = 19448833, upload-time = "2025-09-03T14:32:13.639Z" }, ] [[package]] @@ -2831,14 +2831,14 @@ wheels = [ [[package]] name = "xarray" -version = "2025.8.0" +version = "2025.9.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "numpy" }, { name = "packaging" }, { name = "pandas" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/d2/55/18055bc943029d25fb8f260b7e3b1485c30646ccf503a5e4a744d31a3b78/xarray-2025.8.0.tar.gz", hash = "sha256:323d4169ce72d4ef849de2b0bd122f9cd2905b82c7558169930dc16070982bab", size = 3034425, upload-time = "2025-08-14T16:52:13.872Z" } +sdist = { url = "https://files.pythonhosted.org/packages/4e/0b/bbb76e05c8e2099baf90e259c29cafe6a525524b1d1da8bfbc39577c043e/xarray-2025.9.0.tar.gz", hash = "sha256:7dd6816fe0062c49c5e9370dd483843bc13e5ed80a47a9ff10baff2b51e070fb", size = 3040318, upload-time = "2025-09-04T04:20:26.296Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/e6/c8/0f8db9d9478de8d70cbcae2056588401e26168e269d6d9919bf2ecb01f78/xarray-2025.8.0-py3-none-any.whl", hash = "sha256:1c454f32b38c93df68e450238c9473fe21248b8572d42ddd58c5170bb30934ee", size = 1342279, upload-time = "2025-08-14T16:52:10.956Z" }, + { url = "https://files.pythonhosted.org/packages/8d/f0/73c24457c941b8b08f7d090853e40f4b2cdde88b5da721f3f28e98df77c9/xarray-2025.9.0-py3-none-any.whl", hash = "sha256:79f0e25fb39571f612526ee998ee5404d8725a1db3951aabffdb287388885df0", size = 1349595, upload-time = "2025-09-04T04:20:24.36Z" }, ] From dacd57b792cbda2f6e886190df4b541e1193954a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 4 Sep 2025 14:02:43 -0400 Subject: [PATCH 454/521] Bump pypa/gh-action-pypi-publish in /.github/workflows (#3101) Bumps [pypa/gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish) from 1.12.4 to 1.13.0. - [Release notes](https://github.com/pypa/gh-action-pypi-publish/releases) - [Commits](https://github.com/pypa/gh-action-pypi-publish/compare/v1.12.4...v1.13.0) --- updated-dependencies: - dependency-name: pypa/gh-action-pypi-publish dependency-version: 1.13.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/publish-to-pypi.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/publish-to-pypi.yml b/.github/workflows/publish-to-pypi.yml index acf9d91c47..b649fe9b94 100644 --- a/.github/workflows/publish-to-pypi.yml +++ b/.github/workflows/publish-to-pypi.yml @@ -33,7 +33,7 @@ jobs: run: python -m build - name: Upload package to PyPI - uses: pypa/gh-action-pypi-publish@v1.12.4 + uses: pypa/gh-action-pypi-publish@v1.13.0 with: user: __token__ password: ${{ secrets.PYPI_API_TOKEN }} From 5080f0d67a93ec2320d87e246db05da3e5af0802 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 5 Sep 2025 12:05:49 -0400 Subject: [PATCH 455/521] Bump actions/github-script from 7 to 8 in /.github/workflows (#3103) Bumps [actions/github-script](https://github.com/actions/github-script) from 7 to 8. - [Release notes](https://github.com/actions/github-script/releases) - [Commits](https://github.com/actions/github-script/compare/v7...v8) --- updated-dependencies: - dependency-name: actions/github-script dependency-version: '8' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/changelog.yml | 2 +- .github/workflows/comment-on-pr.yml | 2 +- .github/workflows/unlabel-pr-after-merge.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/changelog.yml b/.github/workflows/changelog.yml index 622db2fe80..57e51104b5 100644 --- a/.github/workflows/changelog.yml +++ b/.github/workflows/changelog.yml @@ -25,7 +25,7 @@ jobs: steps: - name: Add no changelog label - uses: actions/github-script@v7 + uses: actions/github-script@v8 with: github-token: ${{ secrets.GITHUB_TOKEN }} script: | diff --git a/.github/workflows/comment-on-pr.yml b/.github/workflows/comment-on-pr.yml index 9566345a60..3eecbcf351 100644 --- a/.github/workflows/comment-on-pr.yml +++ b/.github/workflows/comment-on-pr.yml @@ -13,7 +13,7 @@ jobs: steps: - - uses: actions/github-script@v7 + - uses: actions/github-script@v8 with: script: | github.rest.issues.createComment({ diff --git a/.github/workflows/unlabel-pr-after-merge.yml b/.github/workflows/unlabel-pr-after-merge.yml index 03c0c5bdd5..be11f4457e 100644 --- a/.github/workflows/unlabel-pr-after-merge.yml +++ b/.github/workflows/unlabel-pr-after-merge.yml @@ -11,7 +11,7 @@ jobs: steps: - name: Remove specific labels - uses: actions/github-script@v7 + uses: actions/github-script@v8 with: github-token: ${{secrets.GITHUB_TOKEN}} script: | From 8f482cc6b33a5d0c73ff3c96ce85bb5f2622ad6d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 5 Sep 2025 12:17:40 -0400 Subject: [PATCH 456/521] Bump actions/setup-python from 5 to 6 in /.github/workflows (#3106) Bumps [actions/setup-python](https://github.com/actions/setup-python) from 5 to 6. - [Release notes](https://github.com/actions/setup-python/releases) - [Commits](https://github.com/actions/setup-python/compare/v5...v6) --- updated-dependencies: - dependency-name: actions/setup-python dependency-version: '6' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/publish-to-pypi.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/publish-to-pypi.yml b/.github/workflows/publish-to-pypi.yml index b649fe9b94..acd8317b44 100644 --- a/.github/workflows/publish-to-pypi.yml +++ b/.github/workflows/publish-to-pypi.yml @@ -20,7 +20,7 @@ jobs: persist-credentials: false - name: Set up Python - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 with: python-version: 3.13 From d9d77a205d481157af51d62acff65bb93af42629 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 9 Sep 2025 15:36:39 -0400 Subject: [PATCH 457/521] Bump actions/labeler from 5 to 6 in /.github/workflows (#3105) Bumps [actions/labeler](https://github.com/actions/labeler) from 5 to 6. - [Release notes](https://github.com/actions/labeler/releases) - [Commits](https://github.com/actions/labeler/compare/v5...v6) --- updated-dependencies: - dependency-name: actions/labeler dependency-version: '6' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/labeler.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml index f934e900e7..cdafddf72f 100644 --- a/.github/workflows/labeler.yml +++ b/.github/workflows/labeler.yml @@ -11,6 +11,6 @@ jobs: pull-requests: write runs-on: ubuntu-latest steps: - - uses: actions/labeler@v5 + - uses: actions/labeler@v6 with: configuration-path: .github/labeler.yml From 5ae7d5fde9d4e3a884783a3e75b3091d33987df1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 9 Sep 2025 15:37:51 -0400 Subject: [PATCH 458/521] Bump actions/stale from 9 to 10 in /.github/workflows (#3104) Bumps [actions/stale](https://github.com/actions/stale) from 9 to 10. - [Release notes](https://github.com/actions/stale/releases) - [Changelog](https://github.com/actions/stale/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/stale/compare/v9...v10) --- updated-dependencies: - dependency-name: actions/stale dependency-version: '10' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/stale.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index e37c3ae42a..ddbda67c2a 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -16,7 +16,7 @@ jobs: steps: - - uses: actions/stale@v9 + - uses: actions/stale@v10 with: repo-token: ${{ secrets.GITHUB_TOKEN }} stale-issue-message: This issue will be closed in 90 days due to five years of inactivity unless the stale label or comment is removed. From 3268b6f70c2f86e889ad5e7ff2c9405d95bbe8bb Mon Sep 17 00:00:00 2001 From: "plasmapy-requirements-bot[bot]" <134649236+plasmapy-requirements-bot[bot]@users.noreply.github.com> Date: Thu, 11 Sep 2025 13:31:49 -0400 Subject: [PATCH 459/521] Update requirements with 'nox -s requirements' (#3108) Co-authored-by: namurphy <8931994+namurphy@users.noreply.github.com> --- uv.lock | 443 ++++++++++++++++++++++++++++++-------------------------- 1 file changed, 234 insertions(+), 209 deletions(-) diff --git a/uv.lock b/uv.lock index 29255230b8..3156c2715b 100644 --- a/uv.lock +++ b/uv.lock @@ -80,11 +80,11 @@ wheels = [ [[package]] name = "astropy-iers-data" -version = "0.2025.9.1.0.42.11" +version = "0.2025.9.8.0.36.17" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/2a/9b/f51e45153c47150ddcd585bd54920028d5eeb7b9c9dfdf3a5fa72baf14c3/astropy_iers_data-0.2025.9.1.0.42.11.tar.gz", hash = "sha256:72712dbae9198c2b0de4b21db682c3c678ea84c518287ffb8f13f2f7353dc181", size = 1906998, upload-time = "2025-09-01T00:42:55.757Z" } +sdist = { url = "https://files.pythonhosted.org/packages/c2/29/7716f0c3ab22f5fbc3b80d90a7687e40aab3ba32b66dd2b8ecdb09663fe1/astropy_iers_data-0.2025.9.8.0.36.17.tar.gz", hash = "sha256:63c1d647b5a2b82b67b5b923e6d4c60fd2ee6f6d88903438b701bfe302750df0", size = 1907563, upload-time = "2025-09-08T00:37:09.833Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/0d/b3/3a1fee57e52d85a5daa67ad364300e838007e928732d99b77df3a74278b3/astropy_iers_data-0.2025.9.1.0.42.11-py3-none-any.whl", hash = "sha256:9e7f3970487f7c76115c284717775c58870a94378a6bb8a9164022074af05a4d", size = 1962512, upload-time = "2025-09-01T00:42:54.063Z" }, + { url = "https://files.pythonhosted.org/packages/85/25/40a8354d8c062955593d1323051c1c8dfd02609e2d1041ef4ae36d745f95/astropy_iers_data-0.2025.9.8.0.36.17-py3-none-any.whl", hash = "sha256:926719b70dafd0e27eeabebb6bb38df3a2d784e1e934c094bf75d954a21423fe", size = 1963139, upload-time = "2025-09-08T00:37:07.762Z" }, ] [[package]] @@ -155,47 +155,72 @@ wheels = [ [[package]] name = "cffi" -version = "1.17.1" +version = "2.0.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "pycparser" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/fc/97/c783634659c2920c3fc70419e3af40972dbaf758daa229a7d6ea6135c90d/cffi-1.17.1.tar.gz", hash = "sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824", size = 516621, upload-time = "2024-09-04T20:45:21.852Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/6b/f4/927e3a8899e52a27fa57a48607ff7dc91a9ebe97399b357b85a0c7892e00/cffi-1.17.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a45e3c6913c5b87b3ff120dcdc03f6131fa0065027d0ed7ee6190736a74cd401", size = 182264, upload-time = "2024-09-04T20:43:51.124Z" }, - { url = "https://files.pythonhosted.org/packages/6c/f5/6c3a8efe5f503175aaddcbea6ad0d2c96dad6f5abb205750d1b3df44ef29/cffi-1.17.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:30c5e0cb5ae493c04c8b42916e52ca38079f1b235c2f8ae5f4527b963c401caf", size = 178651, upload-time = "2024-09-04T20:43:52.872Z" }, - { url = "https://files.pythonhosted.org/packages/94/dd/a3f0118e688d1b1a57553da23b16bdade96d2f9bcda4d32e7d2838047ff7/cffi-1.17.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f75c7ab1f9e4aca5414ed4d8e5c0e303a34f4421f8a0d47a4d019ceff0ab6af4", size = 445259, upload-time = "2024-09-04T20:43:56.123Z" }, - { url = "https://files.pythonhosted.org/packages/2e/ea/70ce63780f096e16ce8588efe039d3c4f91deb1dc01e9c73a287939c79a6/cffi-1.17.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a1ed2dd2972641495a3ec98445e09766f077aee98a1c896dcb4ad0d303628e41", size = 469200, upload-time = "2024-09-04T20:43:57.891Z" }, - { url = "https://files.pythonhosted.org/packages/1c/a0/a4fa9f4f781bda074c3ddd57a572b060fa0df7655d2a4247bbe277200146/cffi-1.17.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:46bf43160c1a35f7ec506d254e5c890f3c03648a4dbac12d624e4490a7046cd1", size = 477235, upload-time = "2024-09-04T20:44:00.18Z" }, - { url = "https://files.pythonhosted.org/packages/62/12/ce8710b5b8affbcdd5c6e367217c242524ad17a02fe5beec3ee339f69f85/cffi-1.17.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a24ed04c8ffd54b0729c07cee15a81d964e6fee0e3d4d342a27b020d22959dc6", size = 459721, upload-time = "2024-09-04T20:44:01.585Z" }, - { url = "https://files.pythonhosted.org/packages/ff/6b/d45873c5e0242196f042d555526f92aa9e0c32355a1be1ff8c27f077fd37/cffi-1.17.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:610faea79c43e44c71e1ec53a554553fa22321b65fae24889706c0a84d4ad86d", size = 467242, upload-time = "2024-09-04T20:44:03.467Z" }, - { url = "https://files.pythonhosted.org/packages/1a/52/d9a0e523a572fbccf2955f5abe883cfa8bcc570d7faeee06336fbd50c9fc/cffi-1.17.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a9b15d491f3ad5d692e11f6b71f7857e7835eb677955c00cc0aefcd0669adaf6", size = 477999, upload-time = "2024-09-04T20:44:05.023Z" }, - { url = "https://files.pythonhosted.org/packages/44/74/f2a2460684a1a2d00ca799ad880d54652841a780c4c97b87754f660c7603/cffi-1.17.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:de2ea4b5833625383e464549fec1bc395c1bdeeb5f25c4a3a82b5a8c756ec22f", size = 454242, upload-time = "2024-09-04T20:44:06.444Z" }, - { url = "https://files.pythonhosted.org/packages/f8/4a/34599cac7dfcd888ff54e801afe06a19c17787dfd94495ab0c8d35fe99fb/cffi-1.17.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:fc48c783f9c87e60831201f2cce7f3b2e4846bf4d8728eabe54d60700b318a0b", size = 478604, upload-time = "2024-09-04T20:44:08.206Z" }, - { url = "https://files.pythonhosted.org/packages/34/33/e1b8a1ba29025adbdcda5fb3a36f94c03d771c1b7b12f726ff7fef2ebe36/cffi-1.17.1-cp311-cp311-win32.whl", hash = "sha256:85a950a4ac9c359340d5963966e3e0a94a676bd6245a4b55bc43949eee26a655", size = 171727, upload-time = "2024-09-04T20:44:09.481Z" }, - { url = "https://files.pythonhosted.org/packages/3d/97/50228be003bb2802627d28ec0627837ac0bf35c90cf769812056f235b2d1/cffi-1.17.1-cp311-cp311-win_amd64.whl", hash = "sha256:caaf0640ef5f5517f49bc275eca1406b0ffa6aa184892812030f04c2abf589a0", size = 181400, upload-time = "2024-09-04T20:44:10.873Z" }, - { url = "https://files.pythonhosted.org/packages/5a/84/e94227139ee5fb4d600a7a4927f322e1d4aea6fdc50bd3fca8493caba23f/cffi-1.17.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:805b4371bf7197c329fcb3ead37e710d1bca9da5d583f5073b799d5c5bd1eee4", size = 183178, upload-time = "2024-09-04T20:44:12.232Z" }, - { url = "https://files.pythonhosted.org/packages/da/ee/fb72c2b48656111c4ef27f0f91da355e130a923473bf5ee75c5643d00cca/cffi-1.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:733e99bc2df47476e3848417c5a4540522f234dfd4ef3ab7fafdf555b082ec0c", size = 178840, upload-time = "2024-09-04T20:44:13.739Z" }, - { url = "https://files.pythonhosted.org/packages/cc/b6/db007700f67d151abadf508cbfd6a1884f57eab90b1bb985c4c8c02b0f28/cffi-1.17.1-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1257bdabf294dceb59f5e70c64a3e2f462c30c7ad68092d01bbbfb1c16b1ba36", size = 454803, upload-time = "2024-09-04T20:44:15.231Z" }, - { url = "https://files.pythonhosted.org/packages/1a/df/f8d151540d8c200eb1c6fba8cd0dfd40904f1b0682ea705c36e6c2e97ab3/cffi-1.17.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da95af8214998d77a98cc14e3a3bd00aa191526343078b530ceb0bd710fb48a5", size = 478850, upload-time = "2024-09-04T20:44:17.188Z" }, - { url = "https://files.pythonhosted.org/packages/28/c0/b31116332a547fd2677ae5b78a2ef662dfc8023d67f41b2a83f7c2aa78b1/cffi-1.17.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d63afe322132c194cf832bfec0dc69a99fb9bb6bbd550f161a49e9e855cc78ff", size = 485729, upload-time = "2024-09-04T20:44:18.688Z" }, - { url = "https://files.pythonhosted.org/packages/91/2b/9a1ddfa5c7f13cab007a2c9cc295b70fbbda7cb10a286aa6810338e60ea1/cffi-1.17.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f79fc4fc25f1c8698ff97788206bb3c2598949bfe0fef03d299eb1b5356ada99", size = 471256, upload-time = "2024-09-04T20:44:20.248Z" }, - { url = "https://files.pythonhosted.org/packages/b2/d5/da47df7004cb17e4955df6a43d14b3b4ae77737dff8bf7f8f333196717bf/cffi-1.17.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b62ce867176a75d03a665bad002af8e6d54644fad99a3c70905c543130e39d93", size = 479424, upload-time = "2024-09-04T20:44:21.673Z" }, - { url = "https://files.pythonhosted.org/packages/0b/ac/2a28bcf513e93a219c8a4e8e125534f4f6db03e3179ba1c45e949b76212c/cffi-1.17.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:386c8bf53c502fff58903061338ce4f4950cbdcb23e2902d86c0f722b786bbe3", size = 484568, upload-time = "2024-09-04T20:44:23.245Z" }, - { url = "https://files.pythonhosted.org/packages/d4/38/ca8a4f639065f14ae0f1d9751e70447a261f1a30fa7547a828ae08142465/cffi-1.17.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4ceb10419a9adf4460ea14cfd6bc43d08701f0835e979bf821052f1805850fe8", size = 488736, upload-time = "2024-09-04T20:44:24.757Z" }, - { url = "https://files.pythonhosted.org/packages/86/c5/28b2d6f799ec0bdecf44dced2ec5ed43e0eb63097b0f58c293583b406582/cffi-1.17.1-cp312-cp312-win32.whl", hash = "sha256:a08d7e755f8ed21095a310a693525137cfe756ce62d066e53f502a83dc550f65", size = 172448, upload-time = "2024-09-04T20:44:26.208Z" }, - { url = "https://files.pythonhosted.org/packages/50/b9/db34c4755a7bd1cb2d1603ac3863f22bcecbd1ba29e5ee841a4bc510b294/cffi-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:51392eae71afec0d0c8fb1a53b204dbb3bcabcb3c9b807eedf3e1e6ccf2de903", size = 181976, upload-time = "2024-09-04T20:44:27.578Z" }, - { url = "https://files.pythonhosted.org/packages/8d/f8/dd6c246b148639254dad4d6803eb6a54e8c85c6e11ec9df2cffa87571dbe/cffi-1.17.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f3a2b4222ce6b60e2e8b337bb9596923045681d71e5a082783484d845390938e", size = 182989, upload-time = "2024-09-04T20:44:28.956Z" }, - { url = "https://files.pythonhosted.org/packages/8b/f1/672d303ddf17c24fc83afd712316fda78dc6fce1cd53011b839483e1ecc8/cffi-1.17.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0984a4925a435b1da406122d4d7968dd861c1385afe3b45ba82b750f229811e2", size = 178802, upload-time = "2024-09-04T20:44:30.289Z" }, - { url = "https://files.pythonhosted.org/packages/0e/2d/eab2e858a91fdff70533cab61dcff4a1f55ec60425832ddfdc9cd36bc8af/cffi-1.17.1-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d01b12eeeb4427d3110de311e1774046ad344f5b1a7403101878976ecd7a10f3", size = 454792, upload-time = "2024-09-04T20:44:32.01Z" }, - { url = "https://files.pythonhosted.org/packages/75/b2/fbaec7c4455c604e29388d55599b99ebcc250a60050610fadde58932b7ee/cffi-1.17.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:706510fe141c86a69c8ddc029c7910003a17353970cff3b904ff0686a5927683", size = 478893, upload-time = "2024-09-04T20:44:33.606Z" }, - { url = "https://files.pythonhosted.org/packages/4f/b7/6e4a2162178bf1935c336d4da8a9352cccab4d3a5d7914065490f08c0690/cffi-1.17.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de55b766c7aa2e2a3092c51e0483d700341182f08e67c63630d5b6f200bb28e5", size = 485810, upload-time = "2024-09-04T20:44:35.191Z" }, - { url = "https://files.pythonhosted.org/packages/c7/8a/1d0e4a9c26e54746dc08c2c6c037889124d4f59dffd853a659fa545f1b40/cffi-1.17.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c59d6e989d07460165cc5ad3c61f9fd8f1b4796eacbd81cee78957842b834af4", size = 471200, upload-time = "2024-09-04T20:44:36.743Z" }, - { url = "https://files.pythonhosted.org/packages/26/9f/1aab65a6c0db35f43c4d1b4f580e8df53914310afc10ae0397d29d697af4/cffi-1.17.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd398dbc6773384a17fe0d3e7eeb8d1a21c2200473ee6806bb5e6a8e62bb73dd", size = 479447, upload-time = "2024-09-04T20:44:38.492Z" }, - { url = "https://files.pythonhosted.org/packages/5f/e4/fb8b3dd8dc0e98edf1135ff067ae070bb32ef9d509d6cb0f538cd6f7483f/cffi-1.17.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:3edc8d958eb099c634dace3c7e16560ae474aa3803a5df240542b305d14e14ed", size = 484358, upload-time = "2024-09-04T20:44:40.046Z" }, - { url = "https://files.pythonhosted.org/packages/f1/47/d7145bf2dc04684935d57d67dff9d6d795b2ba2796806bb109864be3a151/cffi-1.17.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:72e72408cad3d5419375fc87d289076ee319835bdfa2caad331e377589aebba9", size = 488469, upload-time = "2024-09-04T20:44:41.616Z" }, - { url = "https://files.pythonhosted.org/packages/bf/ee/f94057fa6426481d663b88637a9a10e859e492c73d0384514a17d78ee205/cffi-1.17.1-cp313-cp313-win32.whl", hash = "sha256:e03eab0a8677fa80d646b5ddece1cbeaf556c313dcfac435ba11f107ba117b5d", size = 172475, upload-time = "2024-09-04T20:44:43.733Z" }, - { url = "https://files.pythonhosted.org/packages/7c/fc/6a8cb64e5f0324877d503c854da15d76c1e50eb722e320b15345c4d0c6de/cffi-1.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:f6a16c31041f09ead72d69f583767292f750d24913dadacf5756b966aacb3f1a", size = 182009, upload-time = "2024-09-04T20:44:45.309Z" }, + { name = "pycparser", marker = "implementation_name != 'PyPy'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/eb/56/b1ba7935a17738ae8453301356628e8147c79dbb825bcbc73dc7401f9846/cffi-2.0.0.tar.gz", hash = "sha256:44d1b5909021139fe36001ae048dbdde8214afa20200eda0f64c068cac5d5529", size = 523588, upload-time = "2025-09-08T23:24:04.541Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/12/4a/3dfd5f7850cbf0d06dc84ba9aa00db766b52ca38d8b86e3a38314d52498c/cffi-2.0.0-cp311-cp311-macosx_10_13_x86_64.whl", hash = "sha256:b4c854ef3adc177950a8dfc81a86f5115d2abd545751a304c5bcf2c2c7283cfe", size = 184344, upload-time = "2025-09-08T23:22:26.456Z" }, + { url = "https://files.pythonhosted.org/packages/4f/8b/f0e4c441227ba756aafbe78f117485b25bb26b1c059d01f137fa6d14896b/cffi-2.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2de9a304e27f7596cd03d16f1b7c72219bd944e99cc52b84d0145aefb07cbd3c", size = 180560, upload-time = "2025-09-08T23:22:28.197Z" }, + { url = "https://files.pythonhosted.org/packages/b1/b7/1200d354378ef52ec227395d95c2576330fd22a869f7a70e88e1447eb234/cffi-2.0.0-cp311-cp311-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:baf5215e0ab74c16e2dd324e8ec067ef59e41125d3eade2b863d294fd5035c92", size = 209613, upload-time = "2025-09-08T23:22:29.475Z" }, + { url = "https://files.pythonhosted.org/packages/b8/56/6033f5e86e8cc9bb629f0077ba71679508bdf54a9a5e112a3c0b91870332/cffi-2.0.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:730cacb21e1bdff3ce90babf007d0a0917cc3e6492f336c2f0134101e0944f93", size = 216476, upload-time = "2025-09-08T23:22:31.063Z" }, + { url = "https://files.pythonhosted.org/packages/dc/7f/55fecd70f7ece178db2f26128ec41430d8720f2d12ca97bf8f0a628207d5/cffi-2.0.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:6824f87845e3396029f3820c206e459ccc91760e8fa24422f8b0c3d1731cbec5", size = 203374, upload-time = "2025-09-08T23:22:32.507Z" }, + { url = "https://files.pythonhosted.org/packages/84/ef/a7b77c8bdc0f77adc3b46888f1ad54be8f3b7821697a7b89126e829e676a/cffi-2.0.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:9de40a7b0323d889cf8d23d1ef214f565ab154443c42737dfe52ff82cf857664", size = 202597, upload-time = "2025-09-08T23:22:34.132Z" }, + { url = "https://files.pythonhosted.org/packages/d7/91/500d892b2bf36529a75b77958edfcd5ad8e2ce4064ce2ecfeab2125d72d1/cffi-2.0.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:8941aaadaf67246224cee8c3803777eed332a19d909b47e29c9842ef1e79ac26", size = 215574, upload-time = "2025-09-08T23:22:35.443Z" }, + { url = "https://files.pythonhosted.org/packages/44/64/58f6255b62b101093d5df22dcb752596066c7e89dd725e0afaed242a61be/cffi-2.0.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:a05d0c237b3349096d3981b727493e22147f934b20f6f125a3eba8f994bec4a9", size = 218971, upload-time = "2025-09-08T23:22:36.805Z" }, + { url = "https://files.pythonhosted.org/packages/ab/49/fa72cebe2fd8a55fbe14956f9970fe8eb1ac59e5df042f603ef7c8ba0adc/cffi-2.0.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:94698a9c5f91f9d138526b48fe26a199609544591f859c870d477351dc7b2414", size = 211972, upload-time = "2025-09-08T23:22:38.436Z" }, + { url = "https://files.pythonhosted.org/packages/0b/28/dd0967a76aab36731b6ebfe64dec4e981aff7e0608f60c2d46b46982607d/cffi-2.0.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:5fed36fccc0612a53f1d4d9a816b50a36702c28a2aa880cb8a122b3466638743", size = 217078, upload-time = "2025-09-08T23:22:39.776Z" }, + { url = "https://files.pythonhosted.org/packages/2b/c0/015b25184413d7ab0a410775fdb4a50fca20f5589b5dab1dbbfa3baad8ce/cffi-2.0.0-cp311-cp311-win32.whl", hash = "sha256:c649e3a33450ec82378822b3dad03cc228b8f5963c0c12fc3b1e0ab940f768a5", size = 172076, upload-time = "2025-09-08T23:22:40.95Z" }, + { url = "https://files.pythonhosted.org/packages/ae/8f/dc5531155e7070361eb1b7e4c1a9d896d0cb21c49f807a6c03fd63fc877e/cffi-2.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:66f011380d0e49ed280c789fbd08ff0d40968ee7b665575489afa95c98196ab5", size = 182820, upload-time = "2025-09-08T23:22:42.463Z" }, + { url = "https://files.pythonhosted.org/packages/95/5c/1b493356429f9aecfd56bc171285a4c4ac8697f76e9bbbbb105e537853a1/cffi-2.0.0-cp311-cp311-win_arm64.whl", hash = "sha256:c6638687455baf640e37344fe26d37c404db8b80d037c3d29f58fe8d1c3b194d", size = 177635, upload-time = "2025-09-08T23:22:43.623Z" }, + { url = "https://files.pythonhosted.org/packages/ea/47/4f61023ea636104d4f16ab488e268b93008c3d0bb76893b1b31db1f96802/cffi-2.0.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:6d02d6655b0e54f54c4ef0b94eb6be0607b70853c45ce98bd278dc7de718be5d", size = 185271, upload-time = "2025-09-08T23:22:44.795Z" }, + { url = "https://files.pythonhosted.org/packages/df/a2/781b623f57358e360d62cdd7a8c681f074a71d445418a776eef0aadb4ab4/cffi-2.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8eca2a813c1cb7ad4fb74d368c2ffbbb4789d377ee5bb8df98373c2cc0dee76c", size = 181048, upload-time = "2025-09-08T23:22:45.938Z" }, + { url = "https://files.pythonhosted.org/packages/ff/df/a4f0fbd47331ceeba3d37c2e51e9dfc9722498becbeec2bd8bc856c9538a/cffi-2.0.0-cp312-cp312-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:21d1152871b019407d8ac3985f6775c079416c282e431a4da6afe7aefd2bccbe", size = 212529, upload-time = "2025-09-08T23:22:47.349Z" }, + { url = "https://files.pythonhosted.org/packages/d5/72/12b5f8d3865bf0f87cf1404d8c374e7487dcf097a1c91c436e72e6badd83/cffi-2.0.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:b21e08af67b8a103c71a250401c78d5e0893beff75e28c53c98f4de42f774062", size = 220097, upload-time = "2025-09-08T23:22:48.677Z" }, + { url = "https://files.pythonhosted.org/packages/c2/95/7a135d52a50dfa7c882ab0ac17e8dc11cec9d55d2c18dda414c051c5e69e/cffi-2.0.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:1e3a615586f05fc4065a8b22b8152f0c1b00cdbc60596d187c2a74f9e3036e4e", size = 207983, upload-time = "2025-09-08T23:22:50.06Z" }, + { url = "https://files.pythonhosted.org/packages/3a/c8/15cb9ada8895957ea171c62dc78ff3e99159ee7adb13c0123c001a2546c1/cffi-2.0.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:81afed14892743bbe14dacb9e36d9e0e504cd204e0b165062c488942b9718037", size = 206519, upload-time = "2025-09-08T23:22:51.364Z" }, + { url = "https://files.pythonhosted.org/packages/78/2d/7fa73dfa841b5ac06c7b8855cfc18622132e365f5b81d02230333ff26e9e/cffi-2.0.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:3e17ed538242334bf70832644a32a7aae3d83b57567f9fd60a26257e992b79ba", size = 219572, upload-time = "2025-09-08T23:22:52.902Z" }, + { url = "https://files.pythonhosted.org/packages/07/e0/267e57e387b4ca276b90f0434ff88b2c2241ad72b16d31836adddfd6031b/cffi-2.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3925dd22fa2b7699ed2617149842d2e6adde22b262fcbfada50e3d195e4b3a94", size = 222963, upload-time = "2025-09-08T23:22:54.518Z" }, + { url = "https://files.pythonhosted.org/packages/b6/75/1f2747525e06f53efbd878f4d03bac5b859cbc11c633d0fb81432d98a795/cffi-2.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:2c8f814d84194c9ea681642fd164267891702542f028a15fc97d4674b6206187", size = 221361, upload-time = "2025-09-08T23:22:55.867Z" }, + { url = "https://files.pythonhosted.org/packages/7b/2b/2b6435f76bfeb6bbf055596976da087377ede68df465419d192acf00c437/cffi-2.0.0-cp312-cp312-win32.whl", hash = "sha256:da902562c3e9c550df360bfa53c035b2f241fed6d9aef119048073680ace4a18", size = 172932, upload-time = "2025-09-08T23:22:57.188Z" }, + { url = "https://files.pythonhosted.org/packages/f8/ed/13bd4418627013bec4ed6e54283b1959cf6db888048c7cf4b4c3b5b36002/cffi-2.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:da68248800ad6320861f129cd9c1bf96ca849a2771a59e0344e88681905916f5", size = 183557, upload-time = "2025-09-08T23:22:58.351Z" }, + { url = "https://files.pythonhosted.org/packages/95/31/9f7f93ad2f8eff1dbc1c3656d7ca5bfd8fb52c9d786b4dcf19b2d02217fa/cffi-2.0.0-cp312-cp312-win_arm64.whl", hash = "sha256:4671d9dd5ec934cb9a73e7ee9676f9362aba54f7f34910956b84d727b0d73fb6", size = 177762, upload-time = "2025-09-08T23:22:59.668Z" }, + { url = "https://files.pythonhosted.org/packages/4b/8d/a0a47a0c9e413a658623d014e91e74a50cdd2c423f7ccfd44086ef767f90/cffi-2.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:00bdf7acc5f795150faa6957054fbbca2439db2f775ce831222b66f192f03beb", size = 185230, upload-time = "2025-09-08T23:23:00.879Z" }, + { url = "https://files.pythonhosted.org/packages/4a/d2/a6c0296814556c68ee32009d9c2ad4f85f2707cdecfd7727951ec228005d/cffi-2.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:45d5e886156860dc35862657e1494b9bae8dfa63bf56796f2fb56e1679fc0bca", size = 181043, upload-time = "2025-09-08T23:23:02.231Z" }, + { url = "https://files.pythonhosted.org/packages/b0/1e/d22cc63332bd59b06481ceaac49d6c507598642e2230f201649058a7e704/cffi-2.0.0-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:07b271772c100085dd28b74fa0cd81c8fb1a3ba18b21e03d7c27f3436a10606b", size = 212446, upload-time = "2025-09-08T23:23:03.472Z" }, + { url = "https://files.pythonhosted.org/packages/a9/f5/a2c23eb03b61a0b8747f211eb716446c826ad66818ddc7810cc2cc19b3f2/cffi-2.0.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d48a880098c96020b02d5a1f7d9251308510ce8858940e6fa99ece33f610838b", size = 220101, upload-time = "2025-09-08T23:23:04.792Z" }, + { url = "https://files.pythonhosted.org/packages/f2/7f/e6647792fc5850d634695bc0e6ab4111ae88e89981d35ac269956605feba/cffi-2.0.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:f93fd8e5c8c0a4aa1f424d6173f14a892044054871c771f8566e4008eaa359d2", size = 207948, upload-time = "2025-09-08T23:23:06.127Z" }, + { url = "https://files.pythonhosted.org/packages/cb/1e/a5a1bd6f1fb30f22573f76533de12a00bf274abcdc55c8edab639078abb6/cffi-2.0.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:dd4f05f54a52fb558f1ba9f528228066954fee3ebe629fc1660d874d040ae5a3", size = 206422, upload-time = "2025-09-08T23:23:07.753Z" }, + { url = "https://files.pythonhosted.org/packages/98/df/0a1755e750013a2081e863e7cd37e0cdd02664372c754e5560099eb7aa44/cffi-2.0.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c8d3b5532fc71b7a77c09192b4a5a200ea992702734a2e9279a37f2478236f26", size = 219499, upload-time = "2025-09-08T23:23:09.648Z" }, + { url = "https://files.pythonhosted.org/packages/50/e1/a969e687fcf9ea58e6e2a928ad5e2dd88cc12f6f0ab477e9971f2309b57c/cffi-2.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d9b29c1f0ae438d5ee9acb31cadee00a58c46cc9c0b2f9038c6b0b3470877a8c", size = 222928, upload-time = "2025-09-08T23:23:10.928Z" }, + { url = "https://files.pythonhosted.org/packages/36/54/0362578dd2c9e557a28ac77698ed67323ed5b9775ca9d3fe73fe191bb5d8/cffi-2.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6d50360be4546678fc1b79ffe7a66265e28667840010348dd69a314145807a1b", size = 221302, upload-time = "2025-09-08T23:23:12.42Z" }, + { url = "https://files.pythonhosted.org/packages/eb/6d/bf9bda840d5f1dfdbf0feca87fbdb64a918a69bca42cfa0ba7b137c48cb8/cffi-2.0.0-cp313-cp313-win32.whl", hash = "sha256:74a03b9698e198d47562765773b4a8309919089150a0bb17d829ad7b44b60d27", size = 172909, upload-time = "2025-09-08T23:23:14.32Z" }, + { url = "https://files.pythonhosted.org/packages/37/18/6519e1ee6f5a1e579e04b9ddb6f1676c17368a7aba48299c3759bbc3c8b3/cffi-2.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:19f705ada2530c1167abacb171925dd886168931e0a7b78f5bffcae5c6b5be75", size = 183402, upload-time = "2025-09-08T23:23:15.535Z" }, + { url = "https://files.pythonhosted.org/packages/cb/0e/02ceeec9a7d6ee63bb596121c2c8e9b3a9e150936f4fbef6ca1943e6137c/cffi-2.0.0-cp313-cp313-win_arm64.whl", hash = "sha256:256f80b80ca3853f90c21b23ee78cd008713787b1b1e93eae9f3d6a7134abd91", size = 177780, upload-time = "2025-09-08T23:23:16.761Z" }, + { url = "https://files.pythonhosted.org/packages/92/c4/3ce07396253a83250ee98564f8d7e9789fab8e58858f35d07a9a2c78de9f/cffi-2.0.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:fc33c5141b55ed366cfaad382df24fe7dcbc686de5be719b207bb248e3053dc5", size = 185320, upload-time = "2025-09-08T23:23:18.087Z" }, + { url = "https://files.pythonhosted.org/packages/59/dd/27e9fa567a23931c838c6b02d0764611c62290062a6d4e8ff7863daf9730/cffi-2.0.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c654de545946e0db659b3400168c9ad31b5d29593291482c43e3564effbcee13", size = 181487, upload-time = "2025-09-08T23:23:19.622Z" }, + { url = "https://files.pythonhosted.org/packages/d6/43/0e822876f87ea8a4ef95442c3d766a06a51fc5298823f884ef87aaad168c/cffi-2.0.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:24b6f81f1983e6df8db3adc38562c83f7d4a0c36162885ec7f7b77c7dcbec97b", size = 220049, upload-time = "2025-09-08T23:23:20.853Z" }, + { url = "https://files.pythonhosted.org/packages/b4/89/76799151d9c2d2d1ead63c2429da9ea9d7aac304603de0c6e8764e6e8e70/cffi-2.0.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:12873ca6cb9b0f0d3a0da705d6086fe911591737a59f28b7936bdfed27c0d47c", size = 207793, upload-time = "2025-09-08T23:23:22.08Z" }, + { url = "https://files.pythonhosted.org/packages/bb/dd/3465b14bb9e24ee24cb88c9e3730f6de63111fffe513492bf8c808a3547e/cffi-2.0.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:d9b97165e8aed9272a6bb17c01e3cc5871a594a446ebedc996e2397a1c1ea8ef", size = 206300, upload-time = "2025-09-08T23:23:23.314Z" }, + { url = "https://files.pythonhosted.org/packages/47/d9/d83e293854571c877a92da46fdec39158f8d7e68da75bf73581225d28e90/cffi-2.0.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:afb8db5439b81cf9c9d0c80404b60c3cc9c3add93e114dcae767f1477cb53775", size = 219244, upload-time = "2025-09-08T23:23:24.541Z" }, + { url = "https://files.pythonhosted.org/packages/2b/0f/1f177e3683aead2bb00f7679a16451d302c436b5cbf2505f0ea8146ef59e/cffi-2.0.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:737fe7d37e1a1bffe70bd5754ea763a62a066dc5913ca57e957824b72a85e205", size = 222828, upload-time = "2025-09-08T23:23:26.143Z" }, + { url = "https://files.pythonhosted.org/packages/c6/0f/cafacebd4b040e3119dcb32fed8bdef8dfe94da653155f9d0b9dc660166e/cffi-2.0.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:38100abb9d1b1435bc4cc340bb4489635dc2f0da7456590877030c9b3d40b0c1", size = 220926, upload-time = "2025-09-08T23:23:27.873Z" }, + { url = "https://files.pythonhosted.org/packages/3e/aa/df335faa45b395396fcbc03de2dfcab242cd61a9900e914fe682a59170b1/cffi-2.0.0-cp314-cp314-win32.whl", hash = "sha256:087067fa8953339c723661eda6b54bc98c5625757ea62e95eb4898ad5e776e9f", size = 175328, upload-time = "2025-09-08T23:23:44.61Z" }, + { url = "https://files.pythonhosted.org/packages/bb/92/882c2d30831744296ce713f0feb4c1cd30f346ef747b530b5318715cc367/cffi-2.0.0-cp314-cp314-win_amd64.whl", hash = "sha256:203a48d1fb583fc7d78a4c6655692963b860a417c0528492a6bc21f1aaefab25", size = 185650, upload-time = "2025-09-08T23:23:45.848Z" }, + { url = "https://files.pythonhosted.org/packages/9f/2c/98ece204b9d35a7366b5b2c6539c350313ca13932143e79dc133ba757104/cffi-2.0.0-cp314-cp314-win_arm64.whl", hash = "sha256:dbd5c7a25a7cb98f5ca55d258b103a2054f859a46ae11aaf23134f9cc0d356ad", size = 180687, upload-time = "2025-09-08T23:23:47.105Z" }, + { url = "https://files.pythonhosted.org/packages/3e/61/c768e4d548bfa607abcda77423448df8c471f25dbe64fb2ef6d555eae006/cffi-2.0.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:9a67fc9e8eb39039280526379fb3a70023d77caec1852002b4da7e8b270c4dd9", size = 188773, upload-time = "2025-09-08T23:23:29.347Z" }, + { url = "https://files.pythonhosted.org/packages/2c/ea/5f76bce7cf6fcd0ab1a1058b5af899bfbef198bea4d5686da88471ea0336/cffi-2.0.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7a66c7204d8869299919db4d5069a82f1561581af12b11b3c9f48c584eb8743d", size = 185013, upload-time = "2025-09-08T23:23:30.63Z" }, + { url = "https://files.pythonhosted.org/packages/be/b4/c56878d0d1755cf9caa54ba71e5d049479c52f9e4afc230f06822162ab2f/cffi-2.0.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:7cc09976e8b56f8cebd752f7113ad07752461f48a58cbba644139015ac24954c", size = 221593, upload-time = "2025-09-08T23:23:31.91Z" }, + { url = "https://files.pythonhosted.org/packages/e0/0d/eb704606dfe8033e7128df5e90fee946bbcb64a04fcdaa97321309004000/cffi-2.0.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:92b68146a71df78564e4ef48af17551a5ddd142e5190cdf2c5624d0c3ff5b2e8", size = 209354, upload-time = "2025-09-08T23:23:33.214Z" }, + { url = "https://files.pythonhosted.org/packages/d8/19/3c435d727b368ca475fb8742ab97c9cb13a0de600ce86f62eab7fa3eea60/cffi-2.0.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:b1e74d11748e7e98e2f426ab176d4ed720a64412b6a15054378afdb71e0f37dc", size = 208480, upload-time = "2025-09-08T23:23:34.495Z" }, + { url = "https://files.pythonhosted.org/packages/d0/44/681604464ed9541673e486521497406fadcc15b5217c3e326b061696899a/cffi-2.0.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:28a3a209b96630bca57cce802da70c266eb08c6e97e5afd61a75611ee6c64592", size = 221584, upload-time = "2025-09-08T23:23:36.096Z" }, + { url = "https://files.pythonhosted.org/packages/25/8e/342a504ff018a2825d395d44d63a767dd8ebc927ebda557fecdaca3ac33a/cffi-2.0.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:7553fb2090d71822f02c629afe6042c299edf91ba1bf94951165613553984512", size = 224443, upload-time = "2025-09-08T23:23:37.328Z" }, + { url = "https://files.pythonhosted.org/packages/e1/5e/b666bacbbc60fbf415ba9988324a132c9a7a0448a9a8f125074671c0f2c3/cffi-2.0.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:6c6c373cfc5c83a975506110d17457138c8c63016b563cc9ed6e056a82f13ce4", size = 223437, upload-time = "2025-09-08T23:23:38.945Z" }, + { url = "https://files.pythonhosted.org/packages/a0/1d/ec1a60bd1a10daa292d3cd6bb0b359a81607154fb8165f3ec95fe003b85c/cffi-2.0.0-cp314-cp314t-win32.whl", hash = "sha256:1fc9ea04857caf665289b7a75923f2c6ed559b8298a1b8c49e59f7dd95c8481e", size = 180487, upload-time = "2025-09-08T23:23:40.423Z" }, + { url = "https://files.pythonhosted.org/packages/bf/41/4c1168c74fac325c0c8156f04b6749c8b6a8f405bbf91413ba088359f60d/cffi-2.0.0-cp314-cp314t-win_amd64.whl", hash = "sha256:d68b6cef7827e8641e8ef16f4494edda8b36104d79773a334beaa1e3521430f6", size = 191726, upload-time = "2025-09-08T23:23:41.742Z" }, + { url = "https://files.pythonhosted.org/packages/ae/3a/dbeec9d1ee0844c679f6bb5d6ad4e9f198b1224f4e7a32825f47f6192b0c/cffi-2.0.0-cp314-cp314t-win_arm64.whl", hash = "sha256:0a1527a803f0a659de1af2e1fd700213caba79377e27e4693648c2923da066f9", size = 184195, upload-time = "2025-09-08T23:23:43.004Z" }, ] [[package]] @@ -655,15 +680,15 @@ wheels = [ [[package]] name = "hypothesis" -version = "6.138.14" +version = "6.138.15" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "attrs" }, { name = "sortedcontainers" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/67/ed/2f65a358dd6b5bf3cee99dd2d3473eb9c5d5e50b50f83bbf8ef89ea96e39/hypothesis-6.138.14.tar.gz", hash = "sha256:5c1aa1ce3f1094b5c04ea03476017695bda408a174330e5275e40ddd06d3307a", size = 466152, upload-time = "2025-09-02T21:37:20.883Z" } +sdist = { url = "https://files.pythonhosted.org/packages/3b/68/adc338edec178cf6c08b4843ea2b2d639d47bed4b06ea9331433b71acc0a/hypothesis-6.138.15.tar.gz", hash = "sha256:6b0e1aa182eacde87110995a3543530d69ef411f642162a656efcd46c2823ad1", size = 466116, upload-time = "2025-09-08T05:34:15.956Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/55/2e/fcf7371887f45083472165b21b68a7f552049334e01dc3febe484bbb7bc4/hypothesis-6.138.14-py3-none-any.whl", hash = "sha256:1a702ecfff7034b3252d7a83328093388641cdba863197169559839e841c2154", size = 533626, upload-time = "2025-09-02T21:37:17.318Z" }, + { url = "https://files.pythonhosted.org/packages/39/49/911eb0cd17884a7a6f510e78acf0a70592e414d194695a0c7c1db91645b2/hypothesis-6.138.15-py3-none-any.whl", hash = "sha256:b7cf743d461c319eb251a13c8e1dcf00f4ef7085e4ab5bf5abf102b2a5ffd694", size = 533621, upload-time = "2025-09-08T05:34:12.272Z" }, ] [[package]] @@ -808,14 +833,14 @@ wheels = [ [[package]] name = "jsonschema-specifications" -version = "2025.4.1" +version = "2025.9.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "referencing" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/bf/ce/46fbd9c8119cfc3581ee5643ea49464d168028cfb5caff5fc0596d0cf914/jsonschema_specifications-2025.4.1.tar.gz", hash = "sha256:630159c9f4dbea161a6a2205c3011cc4f18ff381b189fff48bb39b9bf26ae608", size = 15513, upload-time = "2025-04-23T12:34:07.418Z" } +sdist = { url = "https://files.pythonhosted.org/packages/19/74/a633ee74eb36c44aa6d1095e7cc5569bebf04342ee146178e2d36600708b/jsonschema_specifications-2025.9.1.tar.gz", hash = "sha256:b540987f239e745613c7a9176f3edb72b832a4ac465cf02712288397832b5e8d", size = 32855, upload-time = "2025-09-08T01:34:59.186Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/01/0e/b27cdbaccf30b890c40ed1da9fd4a3593a5cf94dae54fb34f8a4b74fcd3f/jsonschema_specifications-2025.4.1-py3-none-any.whl", hash = "sha256:4653bffbd6584f7de83a67e0d620ef16900b390ddc7939d56684d6c81e33f1af", size = 18437, upload-time = "2025-04-23T12:34:05.422Z" }, + { url = "https://files.pythonhosted.org/packages/41/45/1a4ed80516f02155c51f51e8cedb3c1902296743db0bbc66608a0db2814f/jsonschema_specifications-2025.9.1-py3-none-any.whl", hash = "sha256:98802fee3a11ee76ecaca44429fda8a41bff98b00a0f2838151b113f210cc6fe", size = 18437, upload-time = "2025-09-08T01:34:57.871Z" }, ] [[package]] @@ -1275,83 +1300,83 @@ uv = [ [[package]] name = "numpy" -version = "2.3.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/37/7d/3fec4199c5ffb892bed55cff901e4f39a58c81df9c44c280499e92cad264/numpy-2.3.2.tar.gz", hash = "sha256:e0486a11ec30cdecb53f184d496d1c6a20786c81e55e41640270130056f8ee48", size = 20489306, upload-time = "2025-07-24T21:32:07.553Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/96/26/1320083986108998bd487e2931eed2aeedf914b6e8905431487543ec911d/numpy-2.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:852ae5bed3478b92f093e30f785c98e0cb62fa0a939ed057c31716e18a7a22b9", size = 21259016, upload-time = "2025-07-24T20:24:35.214Z" }, - { url = "https://files.pythonhosted.org/packages/c4/2b/792b341463fa93fc7e55abbdbe87dac316c5b8cb5e94fb7a59fb6fa0cda5/numpy-2.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7a0e27186e781a69959d0230dd9909b5e26024f8da10683bd6344baea1885168", size = 14451158, upload-time = "2025-07-24T20:24:58.397Z" }, - { url = "https://files.pythonhosted.org/packages/b7/13/e792d7209261afb0c9f4759ffef6135b35c77c6349a151f488f531d13595/numpy-2.3.2-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:f0a1a8476ad77a228e41619af2fa9505cf69df928e9aaa165746584ea17fed2b", size = 5379817, upload-time = "2025-07-24T20:25:07.746Z" }, - { url = "https://files.pythonhosted.org/packages/49/ce/055274fcba4107c022b2113a213c7287346563f48d62e8d2a5176ad93217/numpy-2.3.2-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:cbc95b3813920145032412f7e33d12080f11dc776262df1712e1638207dde9e8", size = 6913606, upload-time = "2025-07-24T20:25:18.84Z" }, - { url = "https://files.pythonhosted.org/packages/17/f2/e4d72e6bc5ff01e2ab613dc198d560714971900c03674b41947e38606502/numpy-2.3.2-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f75018be4980a7324edc5930fe39aa391d5734531b1926968605416ff58c332d", size = 14589652, upload-time = "2025-07-24T20:25:40.356Z" }, - { url = "https://files.pythonhosted.org/packages/c8/b0/fbeee3000a51ebf7222016e2939b5c5ecf8000a19555d04a18f1e02521b8/numpy-2.3.2-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:20b8200721840f5621b7bd03f8dcd78de33ec522fc40dc2641aa09537df010c3", size = 16938816, upload-time = "2025-07-24T20:26:05.721Z" }, - { url = "https://files.pythonhosted.org/packages/a9/ec/2f6c45c3484cc159621ea8fc000ac5a86f1575f090cac78ac27193ce82cd/numpy-2.3.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1f91e5c028504660d606340a084db4b216567ded1056ea2b4be4f9d10b67197f", size = 16370512, upload-time = "2025-07-24T20:26:30.545Z" }, - { url = "https://files.pythonhosted.org/packages/b5/01/dd67cf511850bd7aefd6347aaae0956ed415abea741ae107834aae7d6d4e/numpy-2.3.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:fb1752a3bb9a3ad2d6b090b88a9a0ae1cd6f004ef95f75825e2f382c183b2097", size = 18884947, upload-time = "2025-07-24T20:26:58.24Z" }, - { url = "https://files.pythonhosted.org/packages/a7/17/2cf60fd3e6a61d006778735edf67a222787a8c1a7842aed43ef96d777446/numpy-2.3.2-cp311-cp311-win32.whl", hash = "sha256:4ae6863868aaee2f57503c7a5052b3a2807cf7a3914475e637a0ecd366ced220", size = 6599494, upload-time = "2025-07-24T20:27:09.786Z" }, - { url = "https://files.pythonhosted.org/packages/d5/03/0eade211c504bda872a594f045f98ddcc6caef2b7c63610946845e304d3f/numpy-2.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:240259d6564f1c65424bcd10f435145a7644a65a6811cfc3201c4a429ba79170", size = 13087889, upload-time = "2025-07-24T20:27:29.558Z" }, - { url = "https://files.pythonhosted.org/packages/13/32/2c7979d39dafb2a25087e12310fc7f3b9d3c7d960df4f4bc97955ae0ce1d/numpy-2.3.2-cp311-cp311-win_arm64.whl", hash = "sha256:4209f874d45f921bde2cff1ffcd8a3695f545ad2ffbef6d3d3c6768162efab89", size = 10459560, upload-time = "2025-07-24T20:27:46.803Z" }, - { url = "https://files.pythonhosted.org/packages/00/6d/745dd1c1c5c284d17725e5c802ca4d45cfc6803519d777f087b71c9f4069/numpy-2.3.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:bc3186bea41fae9d8e90c2b4fb5f0a1f5a690682da79b92574d63f56b529080b", size = 20956420, upload-time = "2025-07-24T20:28:18.002Z" }, - { url = "https://files.pythonhosted.org/packages/bc/96/e7b533ea5740641dd62b07a790af5d9d8fec36000b8e2d0472bd7574105f/numpy-2.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2f4f0215edb189048a3c03bd5b19345bdfa7b45a7a6f72ae5945d2a28272727f", size = 14184660, upload-time = "2025-07-24T20:28:39.522Z" }, - { url = "https://files.pythonhosted.org/packages/2b/53/102c6122db45a62aa20d1b18c9986f67e6b97e0d6fbc1ae13e3e4c84430c/numpy-2.3.2-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:8b1224a734cd509f70816455c3cffe13a4f599b1bf7130f913ba0e2c0b2006c0", size = 5113382, upload-time = "2025-07-24T20:28:48.544Z" }, - { url = "https://files.pythonhosted.org/packages/2b/21/376257efcbf63e624250717e82b4fae93d60178f09eb03ed766dbb48ec9c/numpy-2.3.2-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:3dcf02866b977a38ba3ec10215220609ab9667378a9e2150615673f3ffd6c73b", size = 6647258, upload-time = "2025-07-24T20:28:59.104Z" }, - { url = "https://files.pythonhosted.org/packages/91/ba/f4ebf257f08affa464fe6036e13f2bf9d4642a40228781dc1235da81be9f/numpy-2.3.2-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:572d5512df5470f50ada8d1972c5f1082d9a0b7aa5944db8084077570cf98370", size = 14281409, upload-time = "2025-07-24T20:40:30.298Z" }, - { url = "https://files.pythonhosted.org/packages/59/ef/f96536f1df42c668cbacb727a8c6da7afc9c05ece6d558927fb1722693e1/numpy-2.3.2-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8145dd6d10df13c559d1e4314df29695613575183fa2e2d11fac4c208c8a1f73", size = 16641317, upload-time = "2025-07-24T20:40:56.625Z" }, - { url = "https://files.pythonhosted.org/packages/f6/a7/af813a7b4f9a42f498dde8a4c6fcbff8100eed00182cc91dbaf095645f38/numpy-2.3.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:103ea7063fa624af04a791c39f97070bf93b96d7af7eb23530cd087dc8dbe9dc", size = 16056262, upload-time = "2025-07-24T20:41:20.797Z" }, - { url = "https://files.pythonhosted.org/packages/8b/5d/41c4ef8404caaa7f05ed1cfb06afe16a25895260eacbd29b4d84dff2920b/numpy-2.3.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fc927d7f289d14f5e037be917539620603294454130b6de200091e23d27dc9be", size = 18579342, upload-time = "2025-07-24T20:41:50.753Z" }, - { url = "https://files.pythonhosted.org/packages/a1/4f/9950e44c5a11636f4a3af6e825ec23003475cc9a466edb7a759ed3ea63bd/numpy-2.3.2-cp312-cp312-win32.whl", hash = "sha256:d95f59afe7f808c103be692175008bab926b59309ade3e6d25009e9a171f7036", size = 6320610, upload-time = "2025-07-24T20:42:01.551Z" }, - { url = "https://files.pythonhosted.org/packages/7c/2f/244643a5ce54a94f0a9a2ab578189c061e4a87c002e037b0829dd77293b6/numpy-2.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:9e196ade2400c0c737d93465327d1ae7c06c7cb8a1756121ebf54b06ca183c7f", size = 12786292, upload-time = "2025-07-24T20:42:20.738Z" }, - { url = "https://files.pythonhosted.org/packages/54/cd/7b5f49d5d78db7badab22d8323c1b6ae458fbf86c4fdfa194ab3cd4eb39b/numpy-2.3.2-cp312-cp312-win_arm64.whl", hash = "sha256:ee807923782faaf60d0d7331f5e86da7d5e3079e28b291973c545476c2b00d07", size = 10194071, upload-time = "2025-07-24T20:42:36.657Z" }, - { url = "https://files.pythonhosted.org/packages/1c/c0/c6bb172c916b00700ed3bf71cb56175fd1f7dbecebf8353545d0b5519f6c/numpy-2.3.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:c8d9727f5316a256425892b043736d63e89ed15bbfe6556c5ff4d9d4448ff3b3", size = 20949074, upload-time = "2025-07-24T20:43:07.813Z" }, - { url = "https://files.pythonhosted.org/packages/20/4e/c116466d22acaf4573e58421c956c6076dc526e24a6be0903219775d862e/numpy-2.3.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:efc81393f25f14d11c9d161e46e6ee348637c0a1e8a54bf9dedc472a3fae993b", size = 14177311, upload-time = "2025-07-24T20:43:29.335Z" }, - { url = "https://files.pythonhosted.org/packages/78/45/d4698c182895af189c463fc91d70805d455a227261d950e4e0f1310c2550/numpy-2.3.2-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:dd937f088a2df683cbb79dda9a772b62a3e5a8a7e76690612c2737f38c6ef1b6", size = 5106022, upload-time = "2025-07-24T20:43:37.999Z" }, - { url = "https://files.pythonhosted.org/packages/9f/76/3e6880fef4420179309dba72a8c11f6166c431cf6dee54c577af8906f914/numpy-2.3.2-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:11e58218c0c46c80509186e460d79fbdc9ca1eb8d8aee39d8f2dc768eb781089", size = 6640135, upload-time = "2025-07-24T20:43:49.28Z" }, - { url = "https://files.pythonhosted.org/packages/34/fa/87ff7f25b3c4ce9085a62554460b7db686fef1e0207e8977795c7b7d7ba1/numpy-2.3.2-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5ad4ebcb683a1f99f4f392cc522ee20a18b2bb12a2c1c42c3d48d5a1adc9d3d2", size = 14278147, upload-time = "2025-07-24T20:44:10.328Z" }, - { url = "https://files.pythonhosted.org/packages/1d/0f/571b2c7a3833ae419fe69ff7b479a78d313581785203cc70a8db90121b9a/numpy-2.3.2-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:938065908d1d869c7d75d8ec45f735a034771c6ea07088867f713d1cd3bbbe4f", size = 16635989, upload-time = "2025-07-24T20:44:34.88Z" }, - { url = "https://files.pythonhosted.org/packages/24/5a/84ae8dca9c9a4c592fe11340b36a86ffa9fd3e40513198daf8a97839345c/numpy-2.3.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:66459dccc65d8ec98cc7df61307b64bf9e08101f9598755d42d8ae65d9a7a6ee", size = 16053052, upload-time = "2025-07-24T20:44:58.872Z" }, - { url = "https://files.pythonhosted.org/packages/57/7c/e5725d99a9133b9813fcf148d3f858df98511686e853169dbaf63aec6097/numpy-2.3.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a7af9ed2aa9ec5950daf05bb11abc4076a108bd3c7db9aa7251d5f107079b6a6", size = 18577955, upload-time = "2025-07-24T20:45:26.714Z" }, - { url = "https://files.pythonhosted.org/packages/ae/11/7c546fcf42145f29b71e4d6f429e96d8d68e5a7ba1830b2e68d7418f0bbd/numpy-2.3.2-cp313-cp313-win32.whl", hash = "sha256:906a30249315f9c8e17b085cc5f87d3f369b35fedd0051d4a84686967bdbbd0b", size = 6311843, upload-time = "2025-07-24T20:49:24.444Z" }, - { url = "https://files.pythonhosted.org/packages/aa/6f/a428fd1cb7ed39b4280d057720fed5121b0d7754fd2a9768640160f5517b/numpy-2.3.2-cp313-cp313-win_amd64.whl", hash = "sha256:c63d95dc9d67b676e9108fe0d2182987ccb0f11933c1e8959f42fa0da8d4fa56", size = 12782876, upload-time = "2025-07-24T20:49:43.227Z" }, - { url = "https://files.pythonhosted.org/packages/65/85/4ea455c9040a12595fb6c43f2c217257c7b52dd0ba332c6a6c1d28b289fe/numpy-2.3.2-cp313-cp313-win_arm64.whl", hash = "sha256:b05a89f2fb84d21235f93de47129dd4f11c16f64c87c33f5e284e6a3a54e43f2", size = 10192786, upload-time = "2025-07-24T20:49:59.443Z" }, - { url = "https://files.pythonhosted.org/packages/80/23/8278f40282d10c3f258ec3ff1b103d4994bcad78b0cba9208317f6bb73da/numpy-2.3.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:4e6ecfeddfa83b02318f4d84acf15fbdbf9ded18e46989a15a8b6995dfbf85ab", size = 21047395, upload-time = "2025-07-24T20:45:58.821Z" }, - { url = "https://files.pythonhosted.org/packages/1f/2d/624f2ce4a5df52628b4ccd16a4f9437b37c35f4f8a50d00e962aae6efd7a/numpy-2.3.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:508b0eada3eded10a3b55725b40806a4b855961040180028f52580c4729916a2", size = 14300374, upload-time = "2025-07-24T20:46:20.207Z" }, - { url = "https://files.pythonhosted.org/packages/f6/62/ff1e512cdbb829b80a6bd08318a58698867bca0ca2499d101b4af063ee97/numpy-2.3.2-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:754d6755d9a7588bdc6ac47dc4ee97867271b17cee39cb87aef079574366db0a", size = 5228864, upload-time = "2025-07-24T20:46:30.58Z" }, - { url = "https://files.pythonhosted.org/packages/7d/8e/74bc18078fff03192d4032cfa99d5a5ca937807136d6f5790ce07ca53515/numpy-2.3.2-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:a9f66e7d2b2d7712410d3bc5684149040ef5f19856f20277cd17ea83e5006286", size = 6737533, upload-time = "2025-07-24T20:46:46.111Z" }, - { url = "https://files.pythonhosted.org/packages/19/ea/0731efe2c9073ccca5698ef6a8c3667c4cf4eea53fcdcd0b50140aba03bc/numpy-2.3.2-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:de6ea4e5a65d5a90c7d286ddff2b87f3f4ad61faa3db8dabe936b34c2275b6f8", size = 14352007, upload-time = "2025-07-24T20:47:07.1Z" }, - { url = "https://files.pythonhosted.org/packages/cf/90/36be0865f16dfed20f4bc7f75235b963d5939707d4b591f086777412ff7b/numpy-2.3.2-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a3ef07ec8cbc8fc9e369c8dcd52019510c12da4de81367d8b20bc692aa07573a", size = 16701914, upload-time = "2025-07-24T20:47:32.459Z" }, - { url = "https://files.pythonhosted.org/packages/94/30/06cd055e24cb6c38e5989a9e747042b4e723535758e6153f11afea88c01b/numpy-2.3.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:27c9f90e7481275c7800dc9c24b7cc40ace3fdb970ae4d21eaff983a32f70c91", size = 16132708, upload-time = "2025-07-24T20:47:58.129Z" }, - { url = "https://files.pythonhosted.org/packages/9a/14/ecede608ea73e58267fd7cb78f42341b3b37ba576e778a1a06baffbe585c/numpy-2.3.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:07b62978075b67eee4065b166d000d457c82a1efe726cce608b9db9dd66a73a5", size = 18651678, upload-time = "2025-07-24T20:48:25.402Z" }, - { url = "https://files.pythonhosted.org/packages/40/f3/2fe6066b8d07c3685509bc24d56386534c008b462a488b7f503ba82b8923/numpy-2.3.2-cp313-cp313t-win32.whl", hash = "sha256:c771cfac34a4f2c0de8e8c97312d07d64fd8f8ed45bc9f5726a7e947270152b5", size = 6441832, upload-time = "2025-07-24T20:48:37.181Z" }, - { url = "https://files.pythonhosted.org/packages/0b/ba/0937d66d05204d8f28630c9c60bc3eda68824abde4cf756c4d6aad03b0c6/numpy-2.3.2-cp313-cp313t-win_amd64.whl", hash = "sha256:72dbebb2dcc8305c431b2836bcc66af967df91be793d63a24e3d9b741374c450", size = 12927049, upload-time = "2025-07-24T20:48:56.24Z" }, - { url = "https://files.pythonhosted.org/packages/e9/ed/13542dd59c104d5e654dfa2ac282c199ba64846a74c2c4bcdbc3a0f75df1/numpy-2.3.2-cp313-cp313t-win_arm64.whl", hash = "sha256:72c6df2267e926a6d5286b0a6d556ebe49eae261062059317837fda12ddf0c1a", size = 10262935, upload-time = "2025-07-24T20:49:13.136Z" }, - { url = "https://files.pythonhosted.org/packages/c9/7c/7659048aaf498f7611b783e000c7268fcc4dcf0ce21cd10aad7b2e8f9591/numpy-2.3.2-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:448a66d052d0cf14ce9865d159bfc403282c9bc7bb2a31b03cc18b651eca8b1a", size = 20950906, upload-time = "2025-07-24T20:50:30.346Z" }, - { url = "https://files.pythonhosted.org/packages/80/db/984bea9d4ddf7112a04cfdfb22b1050af5757864cfffe8e09e44b7f11a10/numpy-2.3.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:546aaf78e81b4081b2eba1d105c3b34064783027a06b3ab20b6eba21fb64132b", size = 14185607, upload-time = "2025-07-24T20:50:51.923Z" }, - { url = "https://files.pythonhosted.org/packages/e4/76/b3d6f414f4eca568f469ac112a3b510938d892bc5a6c190cb883af080b77/numpy-2.3.2-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:87c930d52f45df092f7578889711a0768094debf73cfcde105e2d66954358125", size = 5114110, upload-time = "2025-07-24T20:51:01.041Z" }, - { url = "https://files.pythonhosted.org/packages/9e/d2/6f5e6826abd6bca52392ed88fe44a4b52aacb60567ac3bc86c67834c3a56/numpy-2.3.2-cp314-cp314-macosx_14_0_x86_64.whl", hash = "sha256:8dc082ea901a62edb8f59713c6a7e28a85daddcb67454c839de57656478f5b19", size = 6642050, upload-time = "2025-07-24T20:51:11.64Z" }, - { url = "https://files.pythonhosted.org/packages/c4/43/f12b2ade99199e39c73ad182f103f9d9791f48d885c600c8e05927865baf/numpy-2.3.2-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:af58de8745f7fa9ca1c0c7c943616c6fe28e75d0c81f5c295810e3c83b5be92f", size = 14296292, upload-time = "2025-07-24T20:51:33.488Z" }, - { url = "https://files.pythonhosted.org/packages/5d/f9/77c07d94bf110a916b17210fac38680ed8734c236bfed9982fd8524a7b47/numpy-2.3.2-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fed5527c4cf10f16c6d0b6bee1f89958bccb0ad2522c8cadc2efd318bcd545f5", size = 16638913, upload-time = "2025-07-24T20:51:58.517Z" }, - { url = "https://files.pythonhosted.org/packages/9b/d1/9d9f2c8ea399cc05cfff8a7437453bd4e7d894373a93cdc46361bbb49a7d/numpy-2.3.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:095737ed986e00393ec18ec0b21b47c22889ae4b0cd2d5e88342e08b01141f58", size = 16071180, upload-time = "2025-07-24T20:52:22.827Z" }, - { url = "https://files.pythonhosted.org/packages/4c/41/82e2c68aff2a0c9bf315e47d61951099fed65d8cb2c8d9dc388cb87e947e/numpy-2.3.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:b5e40e80299607f597e1a8a247ff8d71d79c5b52baa11cc1cce30aa92d2da6e0", size = 18576809, upload-time = "2025-07-24T20:52:51.015Z" }, - { url = "https://files.pythonhosted.org/packages/14/14/4b4fd3efb0837ed252d0f583c5c35a75121038a8c4e065f2c259be06d2d8/numpy-2.3.2-cp314-cp314-win32.whl", hash = "sha256:7d6e390423cc1f76e1b8108c9b6889d20a7a1f59d9a60cac4a050fa734d6c1e2", size = 6366410, upload-time = "2025-07-24T20:56:44.949Z" }, - { url = "https://files.pythonhosted.org/packages/11/9e/b4c24a6b8467b61aced5c8dc7dcfce23621baa2e17f661edb2444a418040/numpy-2.3.2-cp314-cp314-win_amd64.whl", hash = "sha256:b9d0878b21e3918d76d2209c924ebb272340da1fb51abc00f986c258cd5e957b", size = 12918821, upload-time = "2025-07-24T20:57:06.479Z" }, - { url = "https://files.pythonhosted.org/packages/0e/0f/0dc44007c70b1007c1cef86b06986a3812dd7106d8f946c09cfa75782556/numpy-2.3.2-cp314-cp314-win_arm64.whl", hash = "sha256:2738534837c6a1d0c39340a190177d7d66fdf432894f469728da901f8f6dc910", size = 10477303, upload-time = "2025-07-24T20:57:22.879Z" }, - { url = "https://files.pythonhosted.org/packages/8b/3e/075752b79140b78ddfc9c0a1634d234cfdbc6f9bbbfa6b7504e445ad7d19/numpy-2.3.2-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:4d002ecf7c9b53240be3bb69d80f86ddbd34078bae04d87be81c1f58466f264e", size = 21047524, upload-time = "2025-07-24T20:53:22.086Z" }, - { url = "https://files.pythonhosted.org/packages/fe/6d/60e8247564a72426570d0e0ea1151b95ce5bd2f1597bb878a18d32aec855/numpy-2.3.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:293b2192c6bcce487dbc6326de5853787f870aeb6c43f8f9c6496db5b1781e45", size = 14300519, upload-time = "2025-07-24T20:53:44.053Z" }, - { url = "https://files.pythonhosted.org/packages/4d/73/d8326c442cd428d47a067070c3ac6cc3b651a6e53613a1668342a12d4479/numpy-2.3.2-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:0a4f2021a6da53a0d580d6ef5db29947025ae8b35b3250141805ea9a32bbe86b", size = 5228972, upload-time = "2025-07-24T20:53:53.81Z" }, - { url = "https://files.pythonhosted.org/packages/34/2e/e71b2d6dad075271e7079db776196829019b90ce3ece5c69639e4f6fdc44/numpy-2.3.2-cp314-cp314t-macosx_14_0_x86_64.whl", hash = "sha256:9c144440db4bf3bb6372d2c3e49834cc0ff7bb4c24975ab33e01199e645416f2", size = 6737439, upload-time = "2025-07-24T20:54:04.742Z" }, - { url = "https://files.pythonhosted.org/packages/15/b0/d004bcd56c2c5e0500ffc65385eb6d569ffd3363cb5e593ae742749b2daa/numpy-2.3.2-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f92d6c2a8535dc4fe4419562294ff957f83a16ebdec66df0805e473ffaad8bd0", size = 14352479, upload-time = "2025-07-24T20:54:25.819Z" }, - { url = "https://files.pythonhosted.org/packages/11/e3/285142fcff8721e0c99b51686426165059874c150ea9ab898e12a492e291/numpy-2.3.2-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:cefc2219baa48e468e3db7e706305fcd0c095534a192a08f31e98d83a7d45fb0", size = 16702805, upload-time = "2025-07-24T20:54:50.814Z" }, - { url = "https://files.pythonhosted.org/packages/33/c3/33b56b0e47e604af2c7cd065edca892d180f5899599b76830652875249a3/numpy-2.3.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:76c3e9501ceb50b2ff3824c3589d5d1ab4ac857b0ee3f8f49629d0de55ecf7c2", size = 16133830, upload-time = "2025-07-24T20:55:17.306Z" }, - { url = "https://files.pythonhosted.org/packages/6e/ae/7b1476a1f4d6a48bc669b8deb09939c56dd2a439db1ab03017844374fb67/numpy-2.3.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:122bf5ed9a0221b3419672493878ba4967121514b1d7d4656a7580cd11dddcbf", size = 18652665, upload-time = "2025-07-24T20:55:46.665Z" }, - { url = "https://files.pythonhosted.org/packages/14/ba/5b5c9978c4bb161034148ade2de9db44ec316fab89ce8c400db0e0c81f86/numpy-2.3.2-cp314-cp314t-win32.whl", hash = "sha256:6f1ae3dcb840edccc45af496f312528c15b1f79ac318169d094e85e4bb35fdf1", size = 6514777, upload-time = "2025-07-24T20:55:57.66Z" }, - { url = "https://files.pythonhosted.org/packages/eb/46/3dbaf0ae7c17cdc46b9f662c56da2054887b8d9e737c1476f335c83d33db/numpy-2.3.2-cp314-cp314t-win_amd64.whl", hash = "sha256:087ffc25890d89a43536f75c5fe8770922008758e8eeeef61733957041ed2f9b", size = 13111856, upload-time = "2025-07-24T20:56:17.318Z" }, - { url = "https://files.pythonhosted.org/packages/c1/9e/1652778bce745a67b5fe05adde60ed362d38eb17d919a540e813d30f6874/numpy-2.3.2-cp314-cp314t-win_arm64.whl", hash = "sha256:092aeb3449833ea9c0bf0089d70c29ae480685dd2377ec9cdbbb620257f84631", size = 10544226, upload-time = "2025-07-24T20:56:34.509Z" }, - { url = "https://files.pythonhosted.org/packages/cf/ea/50ebc91d28b275b23b7128ef25c3d08152bc4068f42742867e07a870a42a/numpy-2.3.2-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:14a91ebac98813a49bc6aa1a0dfc09513dcec1d97eaf31ca21a87221a1cdcb15", size = 21130338, upload-time = "2025-07-24T20:57:54.37Z" }, - { url = "https://files.pythonhosted.org/packages/9f/57/cdd5eac00dd5f137277355c318a955c0d8fb8aa486020c22afd305f8b88f/numpy-2.3.2-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:71669b5daae692189540cffc4c439468d35a3f84f0c88b078ecd94337f6cb0ec", size = 14375776, upload-time = "2025-07-24T20:58:16.303Z" }, - { url = "https://files.pythonhosted.org/packages/83/85/27280c7f34fcd305c2209c0cdca4d70775e4859a9eaa92f850087f8dea50/numpy-2.3.2-pp311-pypy311_pp73-macosx_14_0_arm64.whl", hash = "sha256:69779198d9caee6e547adb933941ed7520f896fd9656834c300bdf4dd8642712", size = 5304882, upload-time = "2025-07-24T20:58:26.199Z" }, - { url = "https://files.pythonhosted.org/packages/48/b4/6500b24d278e15dd796f43824e69939d00981d37d9779e32499e823aa0aa/numpy-2.3.2-pp311-pypy311_pp73-macosx_14_0_x86_64.whl", hash = "sha256:2c3271cc4097beb5a60f010bcc1cc204b300bb3eafb4399376418a83a1c6373c", size = 6818405, upload-time = "2025-07-24T20:58:37.341Z" }, - { url = "https://files.pythonhosted.org/packages/9b/c9/142c1e03f199d202da8e980c2496213509291b6024fd2735ad28ae7065c7/numpy-2.3.2-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8446acd11fe3dc1830568c941d44449fd5cb83068e5c70bd5a470d323d448296", size = 14419651, upload-time = "2025-07-24T20:58:59.048Z" }, - { url = "https://files.pythonhosted.org/packages/8b/95/8023e87cbea31a750a6c00ff9427d65ebc5fef104a136bfa69f76266d614/numpy-2.3.2-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:aa098a5ab53fa407fded5870865c6275a5cd4101cfdef8d6fafc48286a96e981", size = 16760166, upload-time = "2025-07-24T21:28:56.38Z" }, - { url = "https://files.pythonhosted.org/packages/78/e3/6690b3f85a05506733c7e90b577e4762517404ea78bab2ca3a5cb1aeb78d/numpy-2.3.2-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:6936aff90dda378c09bea075af0d9c675fe3a977a9d2402f95a87f440f59f619", size = 12977811, upload-time = "2025-07-24T21:29:18.234Z" }, +version = "2.3.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d0/19/95b3d357407220ed24c139018d2518fab0a61a948e68286a25f1a4d049ff/numpy-2.3.3.tar.gz", hash = "sha256:ddc7c39727ba62b80dfdbedf400d1c10ddfa8eefbd7ec8dcb118be8b56d31029", size = 20576648, upload-time = "2025-09-09T16:54:12.543Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7a/45/e80d203ef6b267aa29b22714fb558930b27960a0c5ce3c19c999232bb3eb/numpy-2.3.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0ffc4f5caba7dfcbe944ed674b7eef683c7e94874046454bb79ed7ee0236f59d", size = 21259253, upload-time = "2025-09-09T15:56:02.094Z" }, + { url = "https://files.pythonhosted.org/packages/52/18/cf2c648fccf339e59302e00e5f2bc87725a3ce1992f30f3f78c9044d7c43/numpy-2.3.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e7e946c7170858a0295f79a60214424caac2ffdb0063d4d79cb681f9aa0aa569", size = 14450980, upload-time = "2025-09-09T15:56:05.926Z" }, + { url = "https://files.pythonhosted.org/packages/93/fb/9af1082bec870188c42a1c239839915b74a5099c392389ff04215dcee812/numpy-2.3.3-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:cd4260f64bc794c3390a63bf0728220dd1a68170c169088a1e0dfa2fde1be12f", size = 5379709, upload-time = "2025-09-09T15:56:07.95Z" }, + { url = "https://files.pythonhosted.org/packages/75/0f/bfd7abca52bcbf9a4a65abc83fe18ef01ccdeb37bfb28bbd6ad613447c79/numpy-2.3.3-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:f0ddb4b96a87b6728df9362135e764eac3cfa674499943ebc44ce96c478ab125", size = 6913923, upload-time = "2025-09-09T15:56:09.443Z" }, + { url = "https://files.pythonhosted.org/packages/79/55/d69adad255e87ab7afda1caf93ca997859092afeb697703e2f010f7c2e55/numpy-2.3.3-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:afd07d377f478344ec6ca2b8d4ca08ae8bd44706763d1efb56397de606393f48", size = 14589591, upload-time = "2025-09-09T15:56:11.234Z" }, + { url = "https://files.pythonhosted.org/packages/10/a2/010b0e27ddeacab7839957d7a8f00e91206e0c2c47abbb5f35a2630e5387/numpy-2.3.3-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bc92a5dedcc53857249ca51ef29f5e5f2f8c513e22cfb90faeb20343b8c6f7a6", size = 16938714, upload-time = "2025-09-09T15:56:14.637Z" }, + { url = "https://files.pythonhosted.org/packages/1c/6b/12ce8ede632c7126eb2762b9e15e18e204b81725b81f35176eac14dc5b82/numpy-2.3.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:7af05ed4dc19f308e1d9fc759f36f21921eb7bbfc82843eeec6b2a2863a0aefa", size = 16370592, upload-time = "2025-09-09T15:56:17.285Z" }, + { url = "https://files.pythonhosted.org/packages/b4/35/aba8568b2593067bb6a8fe4c52babb23b4c3b9c80e1b49dff03a09925e4a/numpy-2.3.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:433bf137e338677cebdd5beac0199ac84712ad9d630b74eceeb759eaa45ddf30", size = 18884474, upload-time = "2025-09-09T15:56:20.943Z" }, + { url = "https://files.pythonhosted.org/packages/45/fa/7f43ba10c77575e8be7b0138d107e4f44ca4a1ef322cd16980ea3e8b8222/numpy-2.3.3-cp311-cp311-win32.whl", hash = "sha256:eb63d443d7b4ffd1e873f8155260d7f58e7e4b095961b01c91062935c2491e57", size = 6599794, upload-time = "2025-09-09T15:56:23.258Z" }, + { url = "https://files.pythonhosted.org/packages/0a/a2/a4f78cb2241fe5664a22a10332f2be886dcdea8784c9f6a01c272da9b426/numpy-2.3.3-cp311-cp311-win_amd64.whl", hash = "sha256:ec9d249840f6a565f58d8f913bccac2444235025bbb13e9a4681783572ee3caa", size = 13088104, upload-time = "2025-09-09T15:56:25.476Z" }, + { url = "https://files.pythonhosted.org/packages/79/64/e424e975adbd38282ebcd4891661965b78783de893b381cbc4832fb9beb2/numpy-2.3.3-cp311-cp311-win_arm64.whl", hash = "sha256:74c2a948d02f88c11a3c075d9733f1ae67d97c6bdb97f2bb542f980458b257e7", size = 10460772, upload-time = "2025-09-09T15:56:27.679Z" }, + { url = "https://files.pythonhosted.org/packages/51/5d/bb7fc075b762c96329147799e1bcc9176ab07ca6375ea976c475482ad5b3/numpy-2.3.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:cfdd09f9c84a1a934cde1eec2267f0a43a7cd44b2cca4ff95b7c0d14d144b0bf", size = 20957014, upload-time = "2025-09-09T15:56:29.966Z" }, + { url = "https://files.pythonhosted.org/packages/6b/0e/c6211bb92af26517acd52125a237a92afe9c3124c6a68d3b9f81b62a0568/numpy-2.3.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:cb32e3cf0f762aee47ad1ddc6672988f7f27045b0783c887190545baba73aa25", size = 14185220, upload-time = "2025-09-09T15:56:32.175Z" }, + { url = "https://files.pythonhosted.org/packages/22/f2/07bb754eb2ede9073f4054f7c0286b0d9d2e23982e090a80d478b26d35ca/numpy-2.3.3-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:396b254daeb0a57b1fe0ecb5e3cff6fa79a380fa97c8f7781a6d08cd429418fe", size = 5113918, upload-time = "2025-09-09T15:56:34.175Z" }, + { url = "https://files.pythonhosted.org/packages/81/0a/afa51697e9fb74642f231ea36aca80fa17c8fb89f7a82abd5174023c3960/numpy-2.3.3-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:067e3d7159a5d8f8a0b46ee11148fc35ca9b21f61e3c49fbd0a027450e65a33b", size = 6647922, upload-time = "2025-09-09T15:56:36.149Z" }, + { url = "https://files.pythonhosted.org/packages/5d/f5/122d9cdb3f51c520d150fef6e87df9279e33d19a9611a87c0d2cf78a89f4/numpy-2.3.3-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1c02d0629d25d426585fb2e45a66154081b9fa677bc92a881ff1d216bc9919a8", size = 14281991, upload-time = "2025-09-09T15:56:40.548Z" }, + { url = "https://files.pythonhosted.org/packages/51/64/7de3c91e821a2debf77c92962ea3fe6ac2bc45d0778c1cbe15d4fce2fd94/numpy-2.3.3-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d9192da52b9745f7f0766531dcfa978b7763916f158bb63bdb8a1eca0068ab20", size = 16641643, upload-time = "2025-09-09T15:56:43.343Z" }, + { url = "https://files.pythonhosted.org/packages/30/e4/961a5fa681502cd0d68907818b69f67542695b74e3ceaa513918103b7e80/numpy-2.3.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:cd7de500a5b66319db419dc3c345244404a164beae0d0937283b907d8152e6ea", size = 16056787, upload-time = "2025-09-09T15:56:46.141Z" }, + { url = "https://files.pythonhosted.org/packages/99/26/92c912b966e47fbbdf2ad556cb17e3a3088e2e1292b9833be1dfa5361a1a/numpy-2.3.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:93d4962d8f82af58f0b2eb85daaf1b3ca23fe0a85d0be8f1f2b7bb46034e56d7", size = 18579598, upload-time = "2025-09-09T15:56:49.844Z" }, + { url = "https://files.pythonhosted.org/packages/17/b6/fc8f82cb3520768718834f310c37d96380d9dc61bfdaf05fe5c0b7653e01/numpy-2.3.3-cp312-cp312-win32.whl", hash = "sha256:5534ed6b92f9b7dca6c0a19d6df12d41c68b991cef051d108f6dbff3babc4ebf", size = 6320800, upload-time = "2025-09-09T15:56:52.499Z" }, + { url = "https://files.pythonhosted.org/packages/32/ee/de999f2625b80d043d6d2d628c07d0d5555a677a3cf78fdf868d409b8766/numpy-2.3.3-cp312-cp312-win_amd64.whl", hash = "sha256:497d7cad08e7092dba36e3d296fe4c97708c93daf26643a1ae4b03f6294d30eb", size = 12786615, upload-time = "2025-09-09T15:56:54.422Z" }, + { url = "https://files.pythonhosted.org/packages/49/6e/b479032f8a43559c383acb20816644f5f91c88f633d9271ee84f3b3a996c/numpy-2.3.3-cp312-cp312-win_arm64.whl", hash = "sha256:ca0309a18d4dfea6fc6262a66d06c26cfe4640c3926ceec90e57791a82b6eee5", size = 10195936, upload-time = "2025-09-09T15:56:56.541Z" }, + { url = "https://files.pythonhosted.org/packages/7d/b9/984c2b1ee61a8b803bf63582b4ac4242cf76e2dbd663efeafcb620cc0ccb/numpy-2.3.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f5415fb78995644253370985342cd03572ef8620b934da27d77377a2285955bf", size = 20949588, upload-time = "2025-09-09T15:56:59.087Z" }, + { url = "https://files.pythonhosted.org/packages/a6/e4/07970e3bed0b1384d22af1e9912527ecbeb47d3b26e9b6a3bced068b3bea/numpy-2.3.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d00de139a3324e26ed5b95870ce63be7ec7352171bc69a4cf1f157a48e3eb6b7", size = 14177802, upload-time = "2025-09-09T15:57:01.73Z" }, + { url = "https://files.pythonhosted.org/packages/35/c7/477a83887f9de61f1203bad89cf208b7c19cc9fef0cebef65d5a1a0619f2/numpy-2.3.3-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:9dc13c6a5829610cc07422bc74d3ac083bd8323f14e2827d992f9e52e22cd6a6", size = 5106537, upload-time = "2025-09-09T15:57:03.765Z" }, + { url = "https://files.pythonhosted.org/packages/52/47/93b953bd5866a6f6986344d045a207d3f1cfbad99db29f534ea9cee5108c/numpy-2.3.3-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:d79715d95f1894771eb4e60fb23f065663b2298f7d22945d66877aadf33d00c7", size = 6640743, upload-time = "2025-09-09T15:57:07.921Z" }, + { url = "https://files.pythonhosted.org/packages/23/83/377f84aaeb800b64c0ef4de58b08769e782edcefa4fea712910b6f0afd3c/numpy-2.3.3-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:952cfd0748514ea7c3afc729a0fc639e61655ce4c55ab9acfab14bda4f402b4c", size = 14278881, upload-time = "2025-09-09T15:57:11.349Z" }, + { url = "https://files.pythonhosted.org/packages/9a/a5/bf3db6e66c4b160d6ea10b534c381a1955dfab34cb1017ea93aa33c70ed3/numpy-2.3.3-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5b83648633d46f77039c29078751f80da65aa64d5622a3cd62aaef9d835b6c93", size = 16636301, upload-time = "2025-09-09T15:57:14.245Z" }, + { url = "https://files.pythonhosted.org/packages/a2/59/1287924242eb4fa3f9b3a2c30400f2e17eb2707020d1c5e3086fe7330717/numpy-2.3.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:b001bae8cea1c7dfdb2ae2b017ed0a6f2102d7a70059df1e338e307a4c78a8ae", size = 16053645, upload-time = "2025-09-09T15:57:16.534Z" }, + { url = "https://files.pythonhosted.org/packages/e6/93/b3d47ed882027c35e94ac2320c37e452a549f582a5e801f2d34b56973c97/numpy-2.3.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8e9aced64054739037d42fb84c54dd38b81ee238816c948c8f3ed134665dcd86", size = 18578179, upload-time = "2025-09-09T15:57:18.883Z" }, + { url = "https://files.pythonhosted.org/packages/20/d9/487a2bccbf7cc9d4bfc5f0f197761a5ef27ba870f1e3bbb9afc4bbe3fcc2/numpy-2.3.3-cp313-cp313-win32.whl", hash = "sha256:9591e1221db3f37751e6442850429b3aabf7026d3b05542d102944ca7f00c8a8", size = 6312250, upload-time = "2025-09-09T15:57:21.296Z" }, + { url = "https://files.pythonhosted.org/packages/1b/b5/263ebbbbcede85028f30047eab3d58028d7ebe389d6493fc95ae66c636ab/numpy-2.3.3-cp313-cp313-win_amd64.whl", hash = "sha256:f0dadeb302887f07431910f67a14d57209ed91130be0adea2f9793f1a4f817cf", size = 12783269, upload-time = "2025-09-09T15:57:23.034Z" }, + { url = "https://files.pythonhosted.org/packages/fa/75/67b8ca554bbeaaeb3fac2e8bce46967a5a06544c9108ec0cf5cece559b6c/numpy-2.3.3-cp313-cp313-win_arm64.whl", hash = "sha256:3c7cf302ac6e0b76a64c4aecf1a09e51abd9b01fc7feee80f6c43e3ab1b1dbc5", size = 10195314, upload-time = "2025-09-09T15:57:25.045Z" }, + { url = "https://files.pythonhosted.org/packages/11/d0/0d1ddec56b162042ddfafeeb293bac672de9b0cfd688383590090963720a/numpy-2.3.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:eda59e44957d272846bb407aad19f89dc6f58fecf3504bd144f4c5cf81a7eacc", size = 21048025, upload-time = "2025-09-09T15:57:27.257Z" }, + { url = "https://files.pythonhosted.org/packages/36/9e/1996ca6b6d00415b6acbdd3c42f7f03ea256e2c3f158f80bd7436a8a19f3/numpy-2.3.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:823d04112bc85ef5c4fda73ba24e6096c8f869931405a80aa8b0e604510a26bc", size = 14301053, upload-time = "2025-09-09T15:57:30.077Z" }, + { url = "https://files.pythonhosted.org/packages/05/24/43da09aa764c68694b76e84b3d3f0c44cb7c18cdc1ba80e48b0ac1d2cd39/numpy-2.3.3-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:40051003e03db4041aa325da2a0971ba41cf65714e65d296397cc0e32de6018b", size = 5229444, upload-time = "2025-09-09T15:57:32.733Z" }, + { url = "https://files.pythonhosted.org/packages/bc/14/50ffb0f22f7218ef8af28dd089f79f68289a7a05a208db9a2c5dcbe123c1/numpy-2.3.3-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:6ee9086235dd6ab7ae75aba5662f582a81ced49f0f1c6de4260a78d8f2d91a19", size = 6738039, upload-time = "2025-09-09T15:57:34.328Z" }, + { url = "https://files.pythonhosted.org/packages/55/52/af46ac0795e09657d45a7f4db961917314377edecf66db0e39fa7ab5c3d3/numpy-2.3.3-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:94fcaa68757c3e2e668ddadeaa86ab05499a70725811e582b6a9858dd472fb30", size = 14352314, upload-time = "2025-09-09T15:57:36.255Z" }, + { url = "https://files.pythonhosted.org/packages/a7/b1/dc226b4c90eb9f07a3fff95c2f0db3268e2e54e5cce97c4ac91518aee71b/numpy-2.3.3-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:da1a74b90e7483d6ce5244053399a614b1d6b7bc30a60d2f570e5071f8959d3e", size = 16701722, upload-time = "2025-09-09T15:57:38.622Z" }, + { url = "https://files.pythonhosted.org/packages/9d/9d/9d8d358f2eb5eced14dba99f110d83b5cd9a4460895230f3b396ad19a323/numpy-2.3.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:2990adf06d1ecee3b3dcbb4977dfab6e9f09807598d647f04d385d29e7a3c3d3", size = 16132755, upload-time = "2025-09-09T15:57:41.16Z" }, + { url = "https://files.pythonhosted.org/packages/b6/27/b3922660c45513f9377b3fb42240bec63f203c71416093476ec9aa0719dc/numpy-2.3.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:ed635ff692483b8e3f0fcaa8e7eb8a75ee71aa6d975388224f70821421800cea", size = 18651560, upload-time = "2025-09-09T15:57:43.459Z" }, + { url = "https://files.pythonhosted.org/packages/5b/8e/3ab61a730bdbbc201bb245a71102aa609f0008b9ed15255500a99cd7f780/numpy-2.3.3-cp313-cp313t-win32.whl", hash = "sha256:a333b4ed33d8dc2b373cc955ca57babc00cd6f9009991d9edc5ddbc1bac36bcd", size = 6442776, upload-time = "2025-09-09T15:57:45.793Z" }, + { url = "https://files.pythonhosted.org/packages/1c/3a/e22b766b11f6030dc2decdeff5c2fb1610768055603f9f3be88b6d192fb2/numpy-2.3.3-cp313-cp313t-win_amd64.whl", hash = "sha256:4384a169c4d8f97195980815d6fcad04933a7e1ab3b530921c3fef7a1c63426d", size = 12927281, upload-time = "2025-09-09T15:57:47.492Z" }, + { url = "https://files.pythonhosted.org/packages/7b/42/c2e2bc48c5e9b2a83423f99733950fbefd86f165b468a3d85d52b30bf782/numpy-2.3.3-cp313-cp313t-win_arm64.whl", hash = "sha256:75370986cc0bc66f4ce5110ad35aae6d182cc4ce6433c40ad151f53690130bf1", size = 10265275, upload-time = "2025-09-09T15:57:49.647Z" }, + { url = "https://files.pythonhosted.org/packages/6b/01/342ad585ad82419b99bcf7cebe99e61da6bedb89e213c5fd71acc467faee/numpy-2.3.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:cd052f1fa6a78dee696b58a914b7229ecfa41f0a6d96dc663c1220a55e137593", size = 20951527, upload-time = "2025-09-09T15:57:52.006Z" }, + { url = "https://files.pythonhosted.org/packages/ef/d8/204e0d73fc1b7a9ee80ab1fe1983dd33a4d64a4e30a05364b0208e9a241a/numpy-2.3.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:414a97499480067d305fcac9716c29cf4d0d76db6ebf0bf3cbce666677f12652", size = 14186159, upload-time = "2025-09-09T15:57:54.407Z" }, + { url = "https://files.pythonhosted.org/packages/22/af/f11c916d08f3a18fb8ba81ab72b5b74a6e42ead4c2846d270eb19845bf74/numpy-2.3.3-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:50a5fe69f135f88a2be9b6ca0481a68a136f6febe1916e4920e12f1a34e708a7", size = 5114624, upload-time = "2025-09-09T15:57:56.5Z" }, + { url = "https://files.pythonhosted.org/packages/fb/11/0ed919c8381ac9d2ffacd63fd1f0c34d27e99cab650f0eb6f110e6ae4858/numpy-2.3.3-cp314-cp314-macosx_14_0_x86_64.whl", hash = "sha256:b912f2ed2b67a129e6a601e9d93d4fa37bef67e54cac442a2f588a54afe5c67a", size = 6642627, upload-time = "2025-09-09T15:57:58.206Z" }, + { url = "https://files.pythonhosted.org/packages/ee/83/deb5f77cb0f7ba6cb52b91ed388b47f8f3c2e9930d4665c600408d9b90b9/numpy-2.3.3-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9e318ee0596d76d4cb3d78535dc005fa60e5ea348cd131a51e99d0bdbe0b54fe", size = 14296926, upload-time = "2025-09-09T15:58:00.035Z" }, + { url = "https://files.pythonhosted.org/packages/77/cc/70e59dcb84f2b005d4f306310ff0a892518cc0c8000a33d0e6faf7ca8d80/numpy-2.3.3-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ce020080e4a52426202bdb6f7691c65bb55e49f261f31a8f506c9f6bc7450421", size = 16638958, upload-time = "2025-09-09T15:58:02.738Z" }, + { url = "https://files.pythonhosted.org/packages/b6/5a/b2ab6c18b4257e099587d5b7f903317bd7115333ad8d4ec4874278eafa61/numpy-2.3.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:e6687dc183aa55dae4a705b35f9c0f8cb178bcaa2f029b241ac5356221d5c021", size = 16071920, upload-time = "2025-09-09T15:58:05.029Z" }, + { url = "https://files.pythonhosted.org/packages/b8/f1/8b3fdc44324a259298520dd82147ff648979bed085feeacc1250ef1656c0/numpy-2.3.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:d8f3b1080782469fdc1718c4ed1d22549b5fb12af0d57d35e992158a772a37cf", size = 18577076, upload-time = "2025-09-09T15:58:07.745Z" }, + { url = "https://files.pythonhosted.org/packages/f0/a1/b87a284fb15a42e9274e7fcea0dad259d12ddbf07c1595b26883151ca3b4/numpy-2.3.3-cp314-cp314-win32.whl", hash = "sha256:cb248499b0bc3be66ebd6578b83e5acacf1d6cb2a77f2248ce0e40fbec5a76d0", size = 6366952, upload-time = "2025-09-09T15:58:10.096Z" }, + { url = "https://files.pythonhosted.org/packages/70/5f/1816f4d08f3b8f66576d8433a66f8fa35a5acfb3bbd0bf6c31183b003f3d/numpy-2.3.3-cp314-cp314-win_amd64.whl", hash = "sha256:691808c2b26b0f002a032c73255d0bd89751425f379f7bcd22d140db593a96e8", size = 12919322, upload-time = "2025-09-09T15:58:12.138Z" }, + { url = "https://files.pythonhosted.org/packages/8c/de/072420342e46a8ea41c324a555fa90fcc11637583fb8df722936aed1736d/numpy-2.3.3-cp314-cp314-win_arm64.whl", hash = "sha256:9ad12e976ca7b10f1774b03615a2a4bab8addce37ecc77394d8e986927dc0dfe", size = 10478630, upload-time = "2025-09-09T15:58:14.64Z" }, + { url = "https://files.pythonhosted.org/packages/d5/df/ee2f1c0a9de7347f14da5dd3cd3c3b034d1b8607ccb6883d7dd5c035d631/numpy-2.3.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:9cc48e09feb11e1db00b320e9d30a4151f7369afb96bd0e48d942d09da3a0d00", size = 21047987, upload-time = "2025-09-09T15:58:16.889Z" }, + { url = "https://files.pythonhosted.org/packages/d6/92/9453bdc5a4e9e69cf4358463f25e8260e2ffc126d52e10038b9077815989/numpy-2.3.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:901bf6123879b7f251d3631967fd574690734236075082078e0571977c6a8e6a", size = 14301076, upload-time = "2025-09-09T15:58:20.343Z" }, + { url = "https://files.pythonhosted.org/packages/13/77/1447b9eb500f028bb44253105bd67534af60499588a5149a94f18f2ca917/numpy-2.3.3-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:7f025652034199c301049296b59fa7d52c7e625017cae4c75d8662e377bf487d", size = 5229491, upload-time = "2025-09-09T15:58:22.481Z" }, + { url = "https://files.pythonhosted.org/packages/3d/f9/d72221b6ca205f9736cb4b2ce3b002f6e45cd67cd6a6d1c8af11a2f0b649/numpy-2.3.3-cp314-cp314t-macosx_14_0_x86_64.whl", hash = "sha256:533ca5f6d325c80b6007d4d7fb1984c303553534191024ec6a524a4c92a5935a", size = 6737913, upload-time = "2025-09-09T15:58:24.569Z" }, + { url = "https://files.pythonhosted.org/packages/3c/5f/d12834711962ad9c46af72f79bb31e73e416ee49d17f4c797f72c96b6ca5/numpy-2.3.3-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0edd58682a399824633b66885d699d7de982800053acf20be1eaa46d92009c54", size = 14352811, upload-time = "2025-09-09T15:58:26.416Z" }, + { url = "https://files.pythonhosted.org/packages/a1/0d/fdbec6629d97fd1bebed56cd742884e4eead593611bbe1abc3eb40d304b2/numpy-2.3.3-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:367ad5d8fbec5d9296d18478804a530f1191e24ab4d75ab408346ae88045d25e", size = 16702689, upload-time = "2025-09-09T15:58:28.831Z" }, + { url = "https://files.pythonhosted.org/packages/9b/09/0a35196dc5575adde1eb97ddfbc3e1687a814f905377621d18ca9bc2b7dd/numpy-2.3.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:8f6ac61a217437946a1fa48d24c47c91a0c4f725237871117dea264982128097", size = 16133855, upload-time = "2025-09-09T15:58:31.349Z" }, + { url = "https://files.pythonhosted.org/packages/7a/ca/c9de3ea397d576f1b6753eaa906d4cdef1bf97589a6d9825a349b4729cc2/numpy-2.3.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:179a42101b845a816d464b6fe9a845dfaf308fdfc7925387195570789bb2c970", size = 18652520, upload-time = "2025-09-09T15:58:33.762Z" }, + { url = "https://files.pythonhosted.org/packages/fd/c2/e5ed830e08cd0196351db55db82f65bc0ab05da6ef2b72a836dcf1936d2f/numpy-2.3.3-cp314-cp314t-win32.whl", hash = "sha256:1250c5d3d2562ec4174bce2e3a1523041595f9b651065e4a4473f5f48a6bc8a5", size = 6515371, upload-time = "2025-09-09T15:58:36.04Z" }, + { url = "https://files.pythonhosted.org/packages/47/c7/b0f6b5b67f6788a0725f744496badbb604d226bf233ba716683ebb47b570/numpy-2.3.3-cp314-cp314t-win_amd64.whl", hash = "sha256:b37a0b2e5935409daebe82c1e42274d30d9dd355852529eab91dab8dcca7419f", size = 13112576, upload-time = "2025-09-09T15:58:37.927Z" }, + { url = "https://files.pythonhosted.org/packages/06/b9/33bba5ff6fb679aa0b1f8a07e853f002a6b04b9394db3069a1270a7784ca/numpy-2.3.3-cp314-cp314t-win_arm64.whl", hash = "sha256:78c9f6560dc7e6b3990e32df7ea1a50bbd0e2a111e05209963f5ddcab7073b0b", size = 10545953, upload-time = "2025-09-09T15:58:40.576Z" }, + { url = "https://files.pythonhosted.org/packages/b8/f2/7e0a37cfced2644c9563c529f29fa28acbd0960dde32ece683aafa6f4949/numpy-2.3.3-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:1e02c7159791cd481e1e6d5ddd766b62a4d5acf8df4d4d1afe35ee9c5c33a41e", size = 21131019, upload-time = "2025-09-09T15:58:42.838Z" }, + { url = "https://files.pythonhosted.org/packages/1a/7e/3291f505297ed63831135a6cc0f474da0c868a1f31b0dd9a9f03a7a0d2ed/numpy-2.3.3-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:dca2d0fc80b3893ae72197b39f69d55a3cd8b17ea1b50aa4c62de82419936150", size = 14376288, upload-time = "2025-09-09T15:58:45.425Z" }, + { url = "https://files.pythonhosted.org/packages/bf/4b/ae02e985bdeee73d7b5abdefeb98aef1207e96d4c0621ee0cf228ddfac3c/numpy-2.3.3-pp311-pypy311_pp73-macosx_14_0_arm64.whl", hash = "sha256:99683cbe0658f8271b333a1b1b4bb3173750ad59c0c61f5bbdc5b318918fffe3", size = 5305425, upload-time = "2025-09-09T15:58:48.6Z" }, + { url = "https://files.pythonhosted.org/packages/8b/eb/9df215d6d7250db32007941500dc51c48190be25f2401d5b2b564e467247/numpy-2.3.3-pp311-pypy311_pp73-macosx_14_0_x86_64.whl", hash = "sha256:d9d537a39cc9de668e5cd0e25affb17aec17b577c6b3ae8a3d866b479fbe88d0", size = 6819053, upload-time = "2025-09-09T15:58:50.401Z" }, + { url = "https://files.pythonhosted.org/packages/57/62/208293d7d6b2a8998a4a1f23ac758648c3c32182d4ce4346062018362e29/numpy-2.3.3-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8596ba2f8af5f93b01d97563832686d20206d303024777f6dfc2e7c7c3f1850e", size = 14420354, upload-time = "2025-09-09T15:58:52.704Z" }, + { url = "https://files.pythonhosted.org/packages/ed/0c/8e86e0ff7072e14a71b4c6af63175e40d1e7e933ce9b9e9f765a95b4e0c3/numpy-2.3.3-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e1ec5615b05369925bd1125f27df33f3b6c8bc10d788d5999ecd8769a1fa04db", size = 16760413, upload-time = "2025-09-09T15:58:55.027Z" }, + { url = "https://files.pythonhosted.org/packages/af/11/0cc63f9f321ccf63886ac203336777140011fb669e739da36d8db3c53b98/numpy-2.3.3-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:2e267c7da5bf7309670523896df97f93f6e469fb931161f483cd6882b3b1a5dc", size = 12971844, upload-time = "2025-09-09T15:58:57.359Z" }, ] [[package]] @@ -1762,11 +1787,11 @@ wheels = [ [[package]] name = "pycparser" -version = "2.22" +version = "2.23" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/1d/b2/31537cf4b1ca988837256c910a668b553fceb8f069bedc4b1c826024b52c/pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6", size = 172736, upload-time = "2024-03-30T13:22:22.564Z" } +sdist = { url = "https://files.pythonhosted.org/packages/fe/cf/d2d3b9f5699fb1e4615c8e32ff220203e43b248e1dfcc6736ad9057731ca/pycparser-2.23.tar.gz", hash = "sha256:78816d4f24add8f10a06d6f05b4d424ad9e96cfebf68a4ddc99c65c0720d00c2", size = 173734, upload-time = "2025-09-09T13:23:47.91Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/13/a3/a812df4e2dd5696d1f351d58b8fe16a405b234ad2886a0dab9183fb78109/pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc", size = 117552, upload-time = "2024-03-30T13:22:20.476Z" }, + { url = "https://files.pythonhosted.org/packages/a0/e3/59cd50310fc9b59512193629e1984c1f95e5c8ae6e5d8c69532ccc65a7fe/pycparser-2.23-py3-none-any.whl", hash = "sha256:e5c6e8d3fbad53479cab09ac03729e0a9faf2bee3db8208a550daf5af81a5934", size = 118140, upload-time = "2025-09-09T13:23:46.651Z" }, ] [[package]] @@ -1807,7 +1832,7 @@ wheels = [ [[package]] name = "pytest" -version = "8.4.1" +version = "8.4.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "colorama", marker = "sys_platform == 'win32'" }, @@ -1816,23 +1841,23 @@ dependencies = [ { name = "pluggy" }, { name = "pygments" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/08/ba/45911d754e8eba3d5a841a5ce61a65a685ff1798421ac054f85aa8747dfb/pytest-8.4.1.tar.gz", hash = "sha256:7c67fd69174877359ed9371ec3af8a3d2b04741818c51e5e99cc1742251fa93c", size = 1517714, upload-time = "2025-06-18T05:48:06.109Z" } +sdist = { url = "https://files.pythonhosted.org/packages/a3/5c/00a0e072241553e1a7496d638deababa67c5058571567b92a7eaa258397c/pytest-8.4.2.tar.gz", hash = "sha256:86c0d0b93306b961d58d62a4db4879f27fe25513d4b969df351abdddb3c30e01", size = 1519618, upload-time = "2025-09-04T14:34:22.711Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/29/16/c8a903f4c4dffe7a12843191437d7cd8e32751d5de349d45d3fe69544e87/pytest-8.4.1-py3-none-any.whl", hash = "sha256:539c70ba6fcead8e78eebbf1115e8b589e7565830d7d006a8723f19ac8a0afb7", size = 365474, upload-time = "2025-06-18T05:48:03.955Z" }, + { url = "https://files.pythonhosted.org/packages/a8/a4/20da314d277121d6534b3a980b29035dcd51e6744bd79075a6ce8fa4eb8d/pytest-8.4.2-py3-none-any.whl", hash = "sha256:872f880de3fc3a5bdc88a11b39c9710c3497a547cfa9320bc3c5e62fbf272e79", size = 365750, upload-time = "2025-09-04T14:34:20.226Z" }, ] [[package]] name = "pytest-cov" -version = "6.2.1" +version = "7.0.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "coverage", extra = ["toml"] }, { name = "pluggy" }, { name = "pytest" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/18/99/668cade231f434aaa59bbfbf49469068d2ddd945000621d3d165d2e7dd7b/pytest_cov-6.2.1.tar.gz", hash = "sha256:25cc6cc0a5358204b8108ecedc51a9b57b34cc6b8c967cc2c01a4e00d8a67da2", size = 69432, upload-time = "2025-06-12T10:47:47.684Z" } +sdist = { url = "https://files.pythonhosted.org/packages/5e/f7/c933acc76f5208b3b00089573cf6a2bc26dc80a8aece8f52bb7d6b1855ca/pytest_cov-7.0.0.tar.gz", hash = "sha256:33c97eda2e049a0c5298e91f519302a1334c26ac65c1a483d6206fd458361af1", size = 54328, upload-time = "2025-09-09T10:57:02.113Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/bc/16/4ea354101abb1287856baa4af2732be351c7bee728065aed451b678153fd/pytest_cov-6.2.1-py3-none-any.whl", hash = "sha256:f5bc4c23f42f1cdd23c70b1dab1bbaef4fc505ba950d53e0081d0730dd7e86d5", size = 24644, upload-time = "2025-06-12T10:47:45.932Z" }, + { url = "https://files.pythonhosted.org/packages/ee/49/1377b49de7d0c1ce41292161ea0f721913fa8722c19fb9c1e3aa0367eecb/pytest_cov-7.0.0-py3-none-any.whl", hash = "sha256:3b8e9558b16cc1479da72058bdecf8073661c7f57f7d3c5f22a1c23507f2d861", size = 22424, upload-time = "2025-09-09T10:57:00.695Z" }, ] [[package]] @@ -1862,16 +1887,16 @@ wheels = [ [[package]] name = "pytest-regressions" -version = "2.8.2" +version = "2.8.3" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pytest" }, { name = "pytest-datadir" }, { name = "pyyaml" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/c1/8e/e17b12ee49a9814ad86f544225331406e3bf23849a5bc83f91e119e2b72b/pytest_regressions-2.8.2.tar.gz", hash = "sha256:1d8f4767be58b9994bfa7d60271099469ad32b8ca9f9d9ceca1c1d6827156b19", size = 116642, upload-time = "2025-08-13T15:50:37.961Z" } +sdist = { url = "https://files.pythonhosted.org/packages/3a/63/cdb0ee15012a538fa07de21ec0a5c8eb113db9f28378f67b538d1c0b6d04/pytest_regressions-2.8.3.tar.gz", hash = "sha256:1ad90708bee02a3d36c78ef0b6f9692a9a30d312dd828680fd6d2a7235fcd221", size = 117168, upload-time = "2025-09-05T12:51:32.319Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/b6/c9/2c3ea968876f698035b1f00dbe5cd6bff76d3e441dfb1af32111f544b6bb/pytest_regressions-2.8.2-py3-none-any.whl", hash = "sha256:a0804c1ce66d8e4d9a3c7c68f42a3d436182edca8e86565c232caeaf9e080fc2", size = 24856, upload-time = "2025-08-13T15:50:36.431Z" }, + { url = "https://files.pythonhosted.org/packages/55/b9/7b2fe8407744cc37a74e29bed833256a305133505ea4979564911a98338b/pytest_regressions-2.8.3-py3-none-any.whl", hash = "sha256:72500dd95bde418c850f290a3108dacb56427067f364f7112cb5b16f6d6cc29c", size = 24894, upload-time = "2025-09-05T12:51:31.1Z" }, ] [[package]] @@ -1977,60 +2002,60 @@ wheels = [ [[package]] name = "pyzmq" -version = "27.0.2" +version = "27.1.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "cffi", marker = "implementation_name == 'pypy'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/f8/66/159f38d184f08b5f971b467f87b1ab142ab1320d5200825c824b32b84b66/pyzmq-27.0.2.tar.gz", hash = "sha256:b398dd713b18de89730447347e96a0240225e154db56e35b6bb8447ffdb07798", size = 281440, upload-time = "2025-08-21T04:23:26.334Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/42/73/034429ab0f4316bf433eb6c20c3f49d1dc13b2ed4e4d951b283d300a0f35/pyzmq-27.0.2-cp311-cp311-macosx_10_15_universal2.whl", hash = "sha256:063845960df76599ad4fad69fa4d884b3ba38304272104fdcd7e3af33faeeb1d", size = 1333169, upload-time = "2025-08-21T04:21:12.483Z" }, - { url = "https://files.pythonhosted.org/packages/35/02/c42b3b526eb03a570c889eea85a5602797f800a50ba8b09ddbf7db568b78/pyzmq-27.0.2-cp311-cp311-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:845a35fb21b88786aeb38af8b271d41ab0967985410f35411a27eebdc578a076", size = 909176, upload-time = "2025-08-21T04:21:13.835Z" }, - { url = "https://files.pythonhosted.org/packages/1b/35/a1c0b988fabbdf2dc5fe94b7c2bcfd61e3533e5109297b8e0daf1d7a8d2d/pyzmq-27.0.2-cp311-cp311-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:515d20b5c3c86db95503faa989853a8ab692aab1e5336db011cd6d35626c4cb1", size = 668972, upload-time = "2025-08-21T04:21:15.315Z" }, - { url = "https://files.pythonhosted.org/packages/a0/63/908ac865da32ceaeecea72adceadad28ca25b23a2ca5ff018e5bff30116f/pyzmq-27.0.2-cp311-cp311-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:862aedec0b0684a5050cdb5ec13c2da96d2f8dffda48657ed35e312a4e31553b", size = 856962, upload-time = "2025-08-21T04:21:16.652Z" }, - { url = "https://files.pythonhosted.org/packages/2f/5a/90b3cc20b65cdf9391896fcfc15d8db21182eab810b7ea05a2986912fbe2/pyzmq-27.0.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:2cb5bcfc51c7a4fce335d3bc974fd1d6a916abbcdd2b25f6e89d37b8def25f57", size = 1657712, upload-time = "2025-08-21T04:21:18.666Z" }, - { url = "https://files.pythonhosted.org/packages/c4/3c/32a5a80f9be4759325b8d7b22ce674bb87e586b4c80c6a9d77598b60d6f0/pyzmq-27.0.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:38ff75b2a36e3a032e9fef29a5871e3e1301a37464e09ba364e3c3193f62982a", size = 2035054, upload-time = "2025-08-21T04:21:20.073Z" }, - { url = "https://files.pythonhosted.org/packages/13/61/71084fe2ff2d7dc5713f8740d735336e87544845dae1207a8e2e16d9af90/pyzmq-27.0.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:7a5709abe8d23ca158a9d0a18c037f4193f5b6afeb53be37173a41e9fb885792", size = 1894010, upload-time = "2025-08-21T04:21:21.96Z" }, - { url = "https://files.pythonhosted.org/packages/cb/6b/77169cfb13b696e50112ca496b2ed23c4b7d8860a1ec0ff3e4b9f9926221/pyzmq-27.0.2-cp311-cp311-win32.whl", hash = "sha256:47c5dda2018c35d87be9b83de0890cb92ac0791fd59498847fc4eca6ff56671d", size = 566819, upload-time = "2025-08-21T04:21:23.31Z" }, - { url = "https://files.pythonhosted.org/packages/37/cd/86c4083e0f811f48f11bc0ddf1e7d13ef37adfd2fd4f78f2445f1cc5dec0/pyzmq-27.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:f54ca3e98f8f4d23e989c7d0edcf9da7a514ff261edaf64d1d8653dd5feb0a8b", size = 633264, upload-time = "2025-08-21T04:21:24.761Z" }, - { url = "https://files.pythonhosted.org/packages/a0/69/5b8bb6a19a36a569fac02153a9e083738785892636270f5f68a915956aea/pyzmq-27.0.2-cp311-cp311-win_arm64.whl", hash = "sha256:2ef3067cb5b51b090fb853f423ad7ed63836ec154374282780a62eb866bf5768", size = 559316, upload-time = "2025-08-21T04:21:26.1Z" }, - { url = "https://files.pythonhosted.org/packages/68/69/b3a729e7b03e412bee2b1823ab8d22e20a92593634f664afd04c6c9d9ac0/pyzmq-27.0.2-cp312-abi3-macosx_10_15_universal2.whl", hash = "sha256:5da05e3c22c95e23bfc4afeee6ff7d4be9ff2233ad6cb171a0e8257cd46b169a", size = 1305910, upload-time = "2025-08-21T04:21:27.609Z" }, - { url = "https://files.pythonhosted.org/packages/15/b7/f6a6a285193d489b223c340b38ee03a673467cb54914da21c3d7849f1b10/pyzmq-27.0.2-cp312-abi3-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:4e4520577971d01d47e2559bb3175fce1be9103b18621bf0b241abe0a933d040", size = 895507, upload-time = "2025-08-21T04:21:29.005Z" }, - { url = "https://files.pythonhosted.org/packages/17/e6/c4ed2da5ef9182cde1b1f5d0051a986e76339d71720ec1a00be0b49275ad/pyzmq-27.0.2-cp312-abi3-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:56d7de7bf73165b90bd25a8668659ccb134dd28449116bf3c7e9bab5cf8a8ec9", size = 652670, upload-time = "2025-08-21T04:21:30.71Z" }, - { url = "https://files.pythonhosted.org/packages/0e/66/d781ab0636570d32c745c4e389b1c6b713115905cca69ab6233508622edd/pyzmq-27.0.2-cp312-abi3-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:340e7cddc32f147c6c00d116a3f284ab07ee63dbd26c52be13b590520434533c", size = 840581, upload-time = "2025-08-21T04:21:32.008Z" }, - { url = "https://files.pythonhosted.org/packages/a6/df/f24790caf565d72544f5c8d8500960b9562c1dc848d6f22f3c7e122e73d4/pyzmq-27.0.2-cp312-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:ba95693f9df8bb4a9826464fb0fe89033936f35fd4a8ff1edff09a473570afa0", size = 1641931, upload-time = "2025-08-21T04:21:33.371Z" }, - { url = "https://files.pythonhosted.org/packages/65/65/77d27b19fc5e845367f9100db90b9fce924f611b14770db480615944c9c9/pyzmq-27.0.2-cp312-abi3-musllinux_1_2_i686.whl", hash = "sha256:ca42a6ce2d697537da34f77a1960d21476c6a4af3e539eddb2b114c3cf65a78c", size = 2021226, upload-time = "2025-08-21T04:21:35.301Z" }, - { url = "https://files.pythonhosted.org/packages/5b/65/1ed14421ba27a4207fa694772003a311d1142b7f543179e4d1099b7eb746/pyzmq-27.0.2-cp312-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:3e44e665d78a07214b2772ccbd4b9bcc6d848d7895f1b2d7653f047b6318a4f6", size = 1878047, upload-time = "2025-08-21T04:21:36.749Z" }, - { url = "https://files.pythonhosted.org/packages/dd/dc/e578549b89b40dc78a387ec471c2a360766690c0a045cd8d1877d401012d/pyzmq-27.0.2-cp312-abi3-win32.whl", hash = "sha256:272d772d116615397d2be2b1417b3b8c8bc8671f93728c2f2c25002a4530e8f6", size = 558757, upload-time = "2025-08-21T04:21:38.2Z" }, - { url = "https://files.pythonhosted.org/packages/b5/89/06600980aefcc535c758414da969f37a5194ea4cdb73b745223f6af3acfb/pyzmq-27.0.2-cp312-abi3-win_amd64.whl", hash = "sha256:734be4f44efba0aa69bf5f015ed13eb69ff29bf0d17ea1e21588b095a3147b8e", size = 619281, upload-time = "2025-08-21T04:21:39.909Z" }, - { url = "https://files.pythonhosted.org/packages/30/84/df8a5c089552d17c9941d1aea4314b606edf1b1622361dae89aacedc6467/pyzmq-27.0.2-cp312-abi3-win_arm64.whl", hash = "sha256:41f0bd56d9279392810950feb2785a419c2920bbf007fdaaa7f4a07332ae492d", size = 552680, upload-time = "2025-08-21T04:21:41.571Z" }, - { url = "https://files.pythonhosted.org/packages/b4/7b/b79e976508517ab80dc800f7021ef1fb602a6d55e4caa2d47fb3dca5d8b6/pyzmq-27.0.2-cp313-cp313-android_24_arm64_v8a.whl", hash = "sha256:7f01118133427cd7f34ee133b5098e2af5f70303fa7519785c007bca5aa6f96a", size = 1122259, upload-time = "2025-08-21T04:21:43.063Z" }, - { url = "https://files.pythonhosted.org/packages/2b/1c/777217b9940ebcb7e71c924184ca5f31e410580a58d9fd93798589f0d31c/pyzmq-27.0.2-cp313-cp313-android_24_x86_64.whl", hash = "sha256:e4b860edf6379a7234ccbb19b4ed2c57e3ff569c3414fadfb49ae72b61a8ef07", size = 1156113, upload-time = "2025-08-21T04:21:44.566Z" }, - { url = "https://files.pythonhosted.org/packages/59/7d/654657a4c6435f41538182e71b61eac386a789a2bbb6f30171915253a9a7/pyzmq-27.0.2-cp313-cp313t-macosx_10_15_universal2.whl", hash = "sha256:cb77923ea163156da14295c941930bd525df0d29c96c1ec2fe3c3806b1e17cb3", size = 1341437, upload-time = "2025-08-21T04:21:46.019Z" }, - { url = "https://files.pythonhosted.org/packages/20/a0/5ed7710037f9c096017adc748bcb1698674a2d297f8b9422d38816f7b56a/pyzmq-27.0.2-cp313-cp313t-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:61678b7407b04df8f9423f188156355dc94d0fb52d360ae79d02ed7e0d431eea", size = 897888, upload-time = "2025-08-21T04:21:47.362Z" }, - { url = "https://files.pythonhosted.org/packages/2c/8a/6e4699a60931c17e7406641d201d7f2c121e2a38979bc83226a6d8f1ba32/pyzmq-27.0.2-cp313-cp313t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e3c824b70925963bdc8e39a642672c15ffaa67e7d4b491f64662dd56d6271263", size = 660727, upload-time = "2025-08-21T04:21:48.734Z" }, - { url = "https://files.pythonhosted.org/packages/7b/d8/d761e438c186451bd89ce63a665cde5690c084b61cd8f5d7b51e966e875a/pyzmq-27.0.2-cp313-cp313t-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c4833e02fcf2751975457be1dfa2f744d4d09901a8cc106acaa519d868232175", size = 848136, upload-time = "2025-08-21T04:21:50.416Z" }, - { url = "https://files.pythonhosted.org/packages/43/f1/a0f31684efdf3eb92f46b7dd2117e752208115e89d278f8ca5f413c5bb85/pyzmq-27.0.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:b18045668d09cf0faa44918af2a67f0dbbef738c96f61c2f1b975b1ddb92ccfc", size = 1650402, upload-time = "2025-08-21T04:21:52.235Z" }, - { url = "https://files.pythonhosted.org/packages/41/fd/0d7f2a1732812df02c85002770da4a7864c79b210084bcdab01ea57e8d92/pyzmq-27.0.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:bbbb7e2f3ac5a22901324e7b086f398b8e16d343879a77b15ca3312e8cd8e6d5", size = 2024587, upload-time = "2025-08-21T04:21:54.07Z" }, - { url = "https://files.pythonhosted.org/packages/f1/73/358be69e279a382dd09e46dda29df8446365cddee4f79ef214e71e5b2b5a/pyzmq-27.0.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:b751914a73604d40d88a061bab042a11d4511b3ddbb7624cd83c39c8a498564c", size = 1885493, upload-time = "2025-08-21T04:21:55.588Z" }, - { url = "https://files.pythonhosted.org/packages/c5/7b/e9951ad53b3dfed8cfb4c2cfd6e0097c9b454e5c0d0e6df5f2b60d7c8c3d/pyzmq-27.0.2-cp313-cp313t-win32.whl", hash = "sha256:3e8f833dd82af11db5321c414638045c70f61009f72dd61c88db4a713c1fb1d2", size = 574934, upload-time = "2025-08-21T04:21:57.52Z" }, - { url = "https://files.pythonhosted.org/packages/55/33/1a7fc3a92f2124a63e6e2a6afa0af471a5c0c713e776b476d4eda5111b13/pyzmq-27.0.2-cp313-cp313t-win_amd64.whl", hash = "sha256:5b45153cb8eadcab14139970643a84f7a7b08dda541fbc1f6f4855c49334b549", size = 640932, upload-time = "2025-08-21T04:21:59.527Z" }, - { url = "https://files.pythonhosted.org/packages/2a/52/2598a94ac251a7c83f3887866225eea1952b0d4463a68df5032eb00ff052/pyzmq-27.0.2-cp313-cp313t-win_arm64.whl", hash = "sha256:86898f5c9730df23427c1ee0097d8aa41aa5f89539a79e48cd0d2c22d059f1b7", size = 561315, upload-time = "2025-08-21T04:22:01.295Z" }, - { url = "https://files.pythonhosted.org/packages/42/7d/10ef02ea36590b29d48ef88eb0831f0af3eb240cccca2752556faec55f59/pyzmq-27.0.2-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:d2b4b261dce10762be5c116b6ad1f267a9429765b493c454f049f33791dd8b8a", size = 1341463, upload-time = "2025-08-21T04:22:02.712Z" }, - { url = "https://files.pythonhosted.org/packages/94/36/115d18dade9a3d4d3d08dd8bfe5459561b8e02815f99df040555fdd7768e/pyzmq-27.0.2-cp314-cp314t-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:4e4d88b6cff156fed468903006b24bbd85322612f9c2f7b96e72d5016fd3f543", size = 897840, upload-time = "2025-08-21T04:22:04.845Z" }, - { url = "https://files.pythonhosted.org/packages/39/66/083b37839b95c386a95f1537bb41bdbf0c002b7c55b75ee737949cecb11f/pyzmq-27.0.2-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8426c0ebbc11ed8416a6e9409c194142d677c2c5c688595f2743664e356d9e9b", size = 660704, upload-time = "2025-08-21T04:22:06.389Z" }, - { url = "https://files.pythonhosted.org/packages/76/5a/196ab46e549ba35bf3268f575e10cfac0dc86b78dcaa7a3e36407ecda752/pyzmq-27.0.2-cp314-cp314t-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:565bee96a155fe6452caed5fb5f60c9862038e6b51a59f4f632562081cdb4004", size = 848037, upload-time = "2025-08-21T04:22:07.817Z" }, - { url = "https://files.pythonhosted.org/packages/70/ea/a27b9eb44b2e615a9ecb8510ebb023cc1d2d251181e4a1e50366bfbf94d6/pyzmq-27.0.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:5de735c745ca5cefe9c2d1547d8f28cfe1b1926aecb7483ab1102fd0a746c093", size = 1650278, upload-time = "2025-08-21T04:22:09.269Z" }, - { url = "https://files.pythonhosted.org/packages/62/ac/3e9af036bfaf718ab5e69ded8f6332da392c5450ad43e8e3ca66797f145a/pyzmq-27.0.2-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:ea4f498f8115fd90d7bf03a3e83ae3e9898e43362f8e8e8faec93597206e15cc", size = 2024504, upload-time = "2025-08-21T04:22:10.778Z" }, - { url = "https://files.pythonhosted.org/packages/ae/e9/3202d31788df8ebaa176b23d846335eb9c768d8b43c0506bbd6265ad36a0/pyzmq-27.0.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:d00e81cb0afd672915257a3927124ee2ad117ace3c256d39cd97ca3f190152ad", size = 1885381, upload-time = "2025-08-21T04:22:12.718Z" }, - { url = "https://files.pythonhosted.org/packages/4b/ed/42de80b7ab4e8fcf13376f81206cf8041740672ac1fd2e1c598d63f595bf/pyzmq-27.0.2-cp314-cp314t-win32.whl", hash = "sha256:0f6e9b00d81b58f859fffc112365d50413954e02aefe36c5b4c8fb4af79f8cc3", size = 587526, upload-time = "2025-08-21T04:22:14.18Z" }, - { url = "https://files.pythonhosted.org/packages/ed/c8/8f3c72d6f0bfbf090aa5e283576073ca5c59839b85a5cc8c66ddb9b59801/pyzmq-27.0.2-cp314-cp314t-win_amd64.whl", hash = "sha256:2e73cf3b127a437fef4100eb3ac2ebe6b49e655bb721329f667f59eca0a26221", size = 661368, upload-time = "2025-08-21T04:22:15.677Z" }, - { url = "https://files.pythonhosted.org/packages/69/a4/7ee652ea1c77d872f5d99ed937fa8bbd1f6f4b7a39a6d3a0076c286e0c3e/pyzmq-27.0.2-cp314-cp314t-win_arm64.whl", hash = "sha256:4108785f2e5ac865d06f678a07a1901e3465611356df21a545eeea8b45f56265", size = 574901, upload-time = "2025-08-21T04:22:17.423Z" }, - { url = "https://files.pythonhosted.org/packages/c7/60/027d0032a1e3b1aabcef0e309b9ff8a4099bdd5a60ab38b36a676ff2bd7b/pyzmq-27.0.2-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:e297784aea724294fe95e442e39a4376c2f08aa4fae4161c669f047051e31b02", size = 836007, upload-time = "2025-08-21T04:23:00.447Z" }, - { url = "https://files.pythonhosted.org/packages/25/20/2ed1e6168aaea323df9bb2c451309291f53ba3af372ffc16edd4ce15b9e5/pyzmq-27.0.2-pp311-pypy311_pp73-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:e3659a79ded9745bc9c2aef5b444ac8805606e7bc50d2d2eb16dc3ab5483d91f", size = 799932, upload-time = "2025-08-21T04:23:02.052Z" }, - { url = "https://files.pythonhosted.org/packages/fd/25/5c147307de546b502c9373688ce5b25dc22288d23a1ebebe5d587bf77610/pyzmq-27.0.2-pp311-pypy311_pp73-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f3dba49ff037d02373a9306b58d6c1e0be031438f822044e8767afccfdac4c6b", size = 567459, upload-time = "2025-08-21T04:23:03.593Z" }, - { url = "https://files.pythonhosted.org/packages/71/06/0dc56ffc615c8095cd089c9b98ce5c733e990f09ce4e8eea4aaf1041a532/pyzmq-27.0.2-pp311-pypy311_pp73-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:de84e1694f9507b29e7b263453a2255a73e3d099d258db0f14539bad258abe41", size = 747088, upload-time = "2025-08-21T04:23:05.334Z" }, - { url = "https://files.pythonhosted.org/packages/06/f6/4a50187e023b8848edd3f0a8e197b1a7fb08d261d8c60aae7cb6c3d71612/pyzmq-27.0.2-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:f0944d65ba2b872b9fcece08411d6347f15a874c775b4c3baae7f278550da0fb", size = 544639, upload-time = "2025-08-21T04:23:07.279Z" }, +sdist = { url = "https://files.pythonhosted.org/packages/04/0b/3c9baedbdf613ecaa7aa07027780b8867f57b6293b6ee50de316c9f3222b/pyzmq-27.1.0.tar.gz", hash = "sha256:ac0765e3d44455adb6ddbf4417dcce460fc40a05978c08efdf2948072f6db540", size = 281750, upload-time = "2025-09-08T23:10:18.157Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/06/5d/305323ba86b284e6fcb0d842d6adaa2999035f70f8c38a9b6d21ad28c3d4/pyzmq-27.1.0-cp311-cp311-macosx_10_15_universal2.whl", hash = "sha256:226b091818d461a3bef763805e75685e478ac17e9008f49fce2d3e52b3d58b86", size = 1333328, upload-time = "2025-09-08T23:07:45.946Z" }, + { url = "https://files.pythonhosted.org/packages/bd/a0/fc7e78a23748ad5443ac3275943457e8452da67fda347e05260261108cbc/pyzmq-27.1.0-cp311-cp311-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:0790a0161c281ca9723f804871b4027f2e8b5a528d357c8952d08cd1a9c15581", size = 908803, upload-time = "2025-09-08T23:07:47.551Z" }, + { url = "https://files.pythonhosted.org/packages/7e/22/37d15eb05f3bdfa4abea6f6d96eb3bb58585fbd3e4e0ded4e743bc650c97/pyzmq-27.1.0-cp311-cp311-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c895a6f35476b0c3a54e3eb6ccf41bf3018de937016e6e18748317f25d4e925f", size = 668836, upload-time = "2025-09-08T23:07:49.436Z" }, + { url = "https://files.pythonhosted.org/packages/b1/c4/2a6fe5111a01005fc7af3878259ce17684fabb8852815eda6225620f3c59/pyzmq-27.1.0-cp311-cp311-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5bbf8d3630bf96550b3be8e1fc0fea5cbdc8d5466c1192887bd94869da17a63e", size = 857038, upload-time = "2025-09-08T23:07:51.234Z" }, + { url = "https://files.pythonhosted.org/packages/cb/eb/bfdcb41d0db9cd233d6fb22dc131583774135505ada800ebf14dfb0a7c40/pyzmq-27.1.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:15c8bd0fe0dabf808e2d7a681398c4e5ded70a551ab47482067a572c054c8e2e", size = 1657531, upload-time = "2025-09-08T23:07:52.795Z" }, + { url = "https://files.pythonhosted.org/packages/ab/21/e3180ca269ed4a0de5c34417dfe71a8ae80421198be83ee619a8a485b0c7/pyzmq-27.1.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:bafcb3dd171b4ae9f19ee6380dfc71ce0390fefaf26b504c0e5f628d7c8c54f2", size = 2034786, upload-time = "2025-09-08T23:07:55.047Z" }, + { url = "https://files.pythonhosted.org/packages/3b/b1/5e21d0b517434b7f33588ff76c177c5a167858cc38ef740608898cd329f2/pyzmq-27.1.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:e829529fcaa09937189178115c49c504e69289abd39967cd8a4c215761373394", size = 1894220, upload-time = "2025-09-08T23:07:57.172Z" }, + { url = "https://files.pythonhosted.org/packages/03/f2/44913a6ff6941905efc24a1acf3d3cb6146b636c546c7406c38c49c403d4/pyzmq-27.1.0-cp311-cp311-win32.whl", hash = "sha256:6df079c47d5902af6db298ec92151db82ecb557af663098b92f2508c398bb54f", size = 567155, upload-time = "2025-09-08T23:07:59.05Z" }, + { url = "https://files.pythonhosted.org/packages/23/6d/d8d92a0eb270a925c9b4dd039c0b4dc10abc2fcbc48331788824ef113935/pyzmq-27.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:190cbf120fbc0fc4957b56866830def56628934a9d112aec0e2507aa6a032b97", size = 633428, upload-time = "2025-09-08T23:08:00.663Z" }, + { url = "https://files.pythonhosted.org/packages/ae/14/01afebc96c5abbbd713ecfc7469cfb1bc801c819a74ed5c9fad9a48801cb/pyzmq-27.1.0-cp311-cp311-win_arm64.whl", hash = "sha256:eca6b47df11a132d1745eb3b5b5e557a7dae2c303277aa0e69c6ba91b8736e07", size = 559497, upload-time = "2025-09-08T23:08:02.15Z" }, + { url = "https://files.pythonhosted.org/packages/92/e7/038aab64a946d535901103da16b953c8c9cc9c961dadcbf3609ed6428d23/pyzmq-27.1.0-cp312-abi3-macosx_10_15_universal2.whl", hash = "sha256:452631b640340c928fa343801b0d07eb0c3789a5ffa843f6e1a9cee0ba4eb4fc", size = 1306279, upload-time = "2025-09-08T23:08:03.807Z" }, + { url = "https://files.pythonhosted.org/packages/e8/5e/c3c49fdd0f535ef45eefcc16934648e9e59dace4a37ee88fc53f6cd8e641/pyzmq-27.1.0-cp312-abi3-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:1c179799b118e554b66da67d88ed66cd37a169f1f23b5d9f0a231b4e8d44a113", size = 895645, upload-time = "2025-09-08T23:08:05.301Z" }, + { url = "https://files.pythonhosted.org/packages/f8/e5/b0b2504cb4e903a74dcf1ebae157f9e20ebb6ea76095f6cfffea28c42ecd/pyzmq-27.1.0-cp312-abi3-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3837439b7f99e60312f0c926a6ad437b067356dc2bc2ec96eb395fd0fe804233", size = 652574, upload-time = "2025-09-08T23:08:06.828Z" }, + { url = "https://files.pythonhosted.org/packages/f8/9b/c108cdb55560eaf253f0cbdb61b29971e9fb34d9c3499b0e96e4e60ed8a5/pyzmq-27.1.0-cp312-abi3-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:43ad9a73e3da1fab5b0e7e13402f0b2fb934ae1c876c51d0afff0e7c052eca31", size = 840995, upload-time = "2025-09-08T23:08:08.396Z" }, + { url = "https://files.pythonhosted.org/packages/c2/bb/b79798ca177b9eb0825b4c9998c6af8cd2a7f15a6a1a4272c1d1a21d382f/pyzmq-27.1.0-cp312-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:0de3028d69d4cdc475bfe47a6128eb38d8bc0e8f4d69646adfbcd840facbac28", size = 1642070, upload-time = "2025-09-08T23:08:09.989Z" }, + { url = "https://files.pythonhosted.org/packages/9c/80/2df2e7977c4ede24c79ae39dcef3899bfc5f34d1ca7a5b24f182c9b7a9ca/pyzmq-27.1.0-cp312-abi3-musllinux_1_2_i686.whl", hash = "sha256:cf44a7763aea9298c0aa7dbf859f87ed7012de8bda0f3977b6fb1d96745df856", size = 2021121, upload-time = "2025-09-08T23:08:11.907Z" }, + { url = "https://files.pythonhosted.org/packages/46/bd/2d45ad24f5f5ae7e8d01525eb76786fa7557136555cac7d929880519e33a/pyzmq-27.1.0-cp312-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:f30f395a9e6fbca195400ce833c731e7b64c3919aa481af4d88c3759e0cb7496", size = 1878550, upload-time = "2025-09-08T23:08:13.513Z" }, + { url = "https://files.pythonhosted.org/packages/e6/2f/104c0a3c778d7c2ab8190e9db4f62f0b6957b53c9d87db77c284b69f33ea/pyzmq-27.1.0-cp312-abi3-win32.whl", hash = "sha256:250e5436a4ba13885494412b3da5d518cd0d3a278a1ae640e113c073a5f88edd", size = 559184, upload-time = "2025-09-08T23:08:15.163Z" }, + { url = "https://files.pythonhosted.org/packages/fc/7f/a21b20d577e4100c6a41795842028235998a643b1ad406a6d4163ea8f53e/pyzmq-27.1.0-cp312-abi3-win_amd64.whl", hash = "sha256:9ce490cf1d2ca2ad84733aa1d69ce6855372cb5ce9223802450c9b2a7cba0ccf", size = 619480, upload-time = "2025-09-08T23:08:17.192Z" }, + { url = "https://files.pythonhosted.org/packages/78/c2/c012beae5f76b72f007a9e91ee9401cb88c51d0f83c6257a03e785c81cc2/pyzmq-27.1.0-cp312-abi3-win_arm64.whl", hash = "sha256:75a2f36223f0d535a0c919e23615fc85a1e23b71f40c7eb43d7b1dedb4d8f15f", size = 552993, upload-time = "2025-09-08T23:08:18.926Z" }, + { url = "https://files.pythonhosted.org/packages/60/cb/84a13459c51da6cec1b7b1dc1a47e6db6da50b77ad7fd9c145842750a011/pyzmq-27.1.0-cp313-cp313-android_24_arm64_v8a.whl", hash = "sha256:93ad4b0855a664229559e45c8d23797ceac03183c7b6f5b4428152a6b06684a5", size = 1122436, upload-time = "2025-09-08T23:08:20.801Z" }, + { url = "https://files.pythonhosted.org/packages/dc/b6/94414759a69a26c3dd674570a81813c46a078767d931a6c70ad29fc585cb/pyzmq-27.1.0-cp313-cp313-android_24_x86_64.whl", hash = "sha256:fbb4f2400bfda24f12f009cba62ad5734148569ff4949b1b6ec3b519444342e6", size = 1156301, upload-time = "2025-09-08T23:08:22.47Z" }, + { url = "https://files.pythonhosted.org/packages/a5/ad/15906493fd40c316377fd8a8f6b1f93104f97a752667763c9b9c1b71d42d/pyzmq-27.1.0-cp313-cp313t-macosx_10_15_universal2.whl", hash = "sha256:e343d067f7b151cfe4eb3bb796a7752c9d369eed007b91231e817071d2c2fec7", size = 1341197, upload-time = "2025-09-08T23:08:24.286Z" }, + { url = "https://files.pythonhosted.org/packages/14/1d/d343f3ce13db53a54cb8946594e567410b2125394dafcc0268d8dda027e0/pyzmq-27.1.0-cp313-cp313t-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:08363b2011dec81c354d694bdecaef4770e0ae96b9afea70b3f47b973655cc05", size = 897275, upload-time = "2025-09-08T23:08:26.063Z" }, + { url = "https://files.pythonhosted.org/packages/69/2d/d83dd6d7ca929a2fc67d2c3005415cdf322af7751d773524809f9e585129/pyzmq-27.1.0-cp313-cp313t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d54530c8c8b5b8ddb3318f481297441af102517602b569146185fa10b63f4fa9", size = 660469, upload-time = "2025-09-08T23:08:27.623Z" }, + { url = "https://files.pythonhosted.org/packages/3e/cd/9822a7af117f4bc0f1952dbe9ef8358eb50a24928efd5edf54210b850259/pyzmq-27.1.0-cp313-cp313t-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6f3afa12c392f0a44a2414056d730eebc33ec0926aae92b5ad5cf26ebb6cc128", size = 847961, upload-time = "2025-09-08T23:08:29.672Z" }, + { url = "https://files.pythonhosted.org/packages/9a/12/f003e824a19ed73be15542f172fd0ec4ad0b60cf37436652c93b9df7c585/pyzmq-27.1.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:c65047adafe573ff023b3187bb93faa583151627bc9c51fc4fb2c561ed689d39", size = 1650282, upload-time = "2025-09-08T23:08:31.349Z" }, + { url = "https://files.pythonhosted.org/packages/d5/4a/e82d788ed58e9a23995cee70dbc20c9aded3d13a92d30d57ec2291f1e8a3/pyzmq-27.1.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:90e6e9441c946a8b0a667356f7078d96411391a3b8f80980315455574177ec97", size = 2024468, upload-time = "2025-09-08T23:08:33.543Z" }, + { url = "https://files.pythonhosted.org/packages/d9/94/2da0a60841f757481e402b34bf4c8bf57fa54a5466b965de791b1e6f747d/pyzmq-27.1.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:add071b2d25f84e8189aaf0882d39a285b42fa3853016ebab234a5e78c7a43db", size = 1885394, upload-time = "2025-09-08T23:08:35.51Z" }, + { url = "https://files.pythonhosted.org/packages/4f/6f/55c10e2e49ad52d080dc24e37adb215e5b0d64990b57598abc2e3f01725b/pyzmq-27.1.0-cp313-cp313t-win32.whl", hash = "sha256:7ccc0700cfdf7bd487bea8d850ec38f204478681ea02a582a8da8171b7f90a1c", size = 574964, upload-time = "2025-09-08T23:08:37.178Z" }, + { url = "https://files.pythonhosted.org/packages/87/4d/2534970ba63dd7c522d8ca80fb92777f362c0f321900667c615e2067cb29/pyzmq-27.1.0-cp313-cp313t-win_amd64.whl", hash = "sha256:8085a9fba668216b9b4323be338ee5437a235fe275b9d1610e422ccc279733e2", size = 641029, upload-time = "2025-09-08T23:08:40.595Z" }, + { url = "https://files.pythonhosted.org/packages/f6/fa/f8aea7a28b0641f31d40dea42d7ef003fded31e184ef47db696bc74cd610/pyzmq-27.1.0-cp313-cp313t-win_arm64.whl", hash = "sha256:6bb54ca21bcfe361e445256c15eedf083f153811c37be87e0514934d6913061e", size = 561541, upload-time = "2025-09-08T23:08:42.668Z" }, + { url = "https://files.pythonhosted.org/packages/87/45/19efbb3000956e82d0331bafca5d9ac19ea2857722fa2caacefb6042f39d/pyzmq-27.1.0-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:ce980af330231615756acd5154f29813d553ea555485ae712c491cd483df6b7a", size = 1341197, upload-time = "2025-09-08T23:08:44.973Z" }, + { url = "https://files.pythonhosted.org/packages/48/43/d72ccdbf0d73d1343936296665826350cb1e825f92f2db9db3e61c2162a2/pyzmq-27.1.0-cp314-cp314t-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:1779be8c549e54a1c38f805e56d2a2e5c009d26de10921d7d51cfd1c8d4632ea", size = 897175, upload-time = "2025-09-08T23:08:46.601Z" }, + { url = "https://files.pythonhosted.org/packages/2f/2e/a483f73a10b65a9ef0161e817321d39a770b2acf8bcf3004a28d90d14a94/pyzmq-27.1.0-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7200bb0f03345515df50d99d3db206a0a6bee1955fbb8c453c76f5bf0e08fb96", size = 660427, upload-time = "2025-09-08T23:08:48.187Z" }, + { url = "https://files.pythonhosted.org/packages/f5/d2/5f36552c2d3e5685abe60dfa56f91169f7a2d99bbaf67c5271022ab40863/pyzmq-27.1.0-cp314-cp314t-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:01c0e07d558b06a60773744ea6251f769cd79a41a97d11b8bf4ab8f034b0424d", size = 847929, upload-time = "2025-09-08T23:08:49.76Z" }, + { url = "https://files.pythonhosted.org/packages/c4/2a/404b331f2b7bf3198e9945f75c4c521f0c6a3a23b51f7a4a401b94a13833/pyzmq-27.1.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:80d834abee71f65253c91540445d37c4c561e293ba6e741b992f20a105d69146", size = 1650193, upload-time = "2025-09-08T23:08:51.7Z" }, + { url = "https://files.pythonhosted.org/packages/1c/0b/f4107e33f62a5acf60e3ded67ed33d79b4ce18de432625ce2fc5093d6388/pyzmq-27.1.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:544b4e3b7198dde4a62b8ff6685e9802a9a1ebf47e77478a5eb88eca2a82f2fd", size = 2024388, upload-time = "2025-09-08T23:08:53.393Z" }, + { url = "https://files.pythonhosted.org/packages/0d/01/add31fe76512642fd6e40e3a3bd21f4b47e242c8ba33efb6809e37076d9b/pyzmq-27.1.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:cedc4c68178e59a4046f97eca31b148ddcf51e88677de1ef4e78cf06c5376c9a", size = 1885316, upload-time = "2025-09-08T23:08:55.702Z" }, + { url = "https://files.pythonhosted.org/packages/c4/59/a5f38970f9bf07cee96128de79590bb354917914a9be11272cfc7ff26af0/pyzmq-27.1.0-cp314-cp314t-win32.whl", hash = "sha256:1f0b2a577fd770aa6f053211a55d1c47901f4d537389a034c690291485e5fe92", size = 587472, upload-time = "2025-09-08T23:08:58.18Z" }, + { url = "https://files.pythonhosted.org/packages/70/d8/78b1bad170f93fcf5e3536e70e8fadac55030002275c9a29e8f5719185de/pyzmq-27.1.0-cp314-cp314t-win_amd64.whl", hash = "sha256:19c9468ae0437f8074af379e986c5d3d7d7bfe033506af442e8c879732bedbe0", size = 661401, upload-time = "2025-09-08T23:08:59.802Z" }, + { url = "https://files.pythonhosted.org/packages/81/d6/4bfbb40c9a0b42fc53c7cf442f6385db70b40f74a783130c5d0a5aa62228/pyzmq-27.1.0-cp314-cp314t-win_arm64.whl", hash = "sha256:dc5dbf68a7857b59473f7df42650c621d7e8923fb03fa74a526890f4d33cc4d7", size = 575170, upload-time = "2025-09-08T23:09:01.418Z" }, + { url = "https://files.pythonhosted.org/packages/4c/c6/c4dcdecdbaa70969ee1fdced6d7b8f60cfabe64d25361f27ac4665a70620/pyzmq-27.1.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:18770c8d3563715387139060d37859c02ce40718d1faf299abddcdcc6a649066", size = 836265, upload-time = "2025-09-08T23:09:49.376Z" }, + { url = "https://files.pythonhosted.org/packages/3e/79/f38c92eeaeb03a2ccc2ba9866f0439593bb08c5e3b714ac1d553e5c96e25/pyzmq-27.1.0-pp311-pypy311_pp73-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:ac25465d42f92e990f8d8b0546b01c391ad431c3bf447683fdc40565941d0604", size = 800208, upload-time = "2025-09-08T23:09:51.073Z" }, + { url = "https://files.pythonhosted.org/packages/49/0e/3f0d0d335c6b3abb9b7b723776d0b21fa7f3a6c819a0db6097059aada160/pyzmq-27.1.0-pp311-pypy311_pp73-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:53b40f8ae006f2734ee7608d59ed661419f087521edbfc2149c3932e9c14808c", size = 567747, upload-time = "2025-09-08T23:09:52.698Z" }, + { url = "https://files.pythonhosted.org/packages/a1/cf/f2b3784d536250ffd4be70e049f3b60981235d70c6e8ce7e3ef21e1adb25/pyzmq-27.1.0-pp311-pypy311_pp73-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f605d884e7c8be8fe1aa94e0a783bf3f591b84c24e4bc4f3e7564c82ac25e271", size = 747371, upload-time = "2025-09-08T23:09:54.563Z" }, + { url = "https://files.pythonhosted.org/packages/01/1b/5dbe84eefc86f48473947e2f41711aded97eecef1231f4558f1f02713c12/pyzmq-27.1.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:c9f7f6e13dff2e44a6afeaf2cf54cee5929ad64afaf4d40b50f93c58fc687355", size = 544862, upload-time = "2025-09-08T23:09:56.509Z" }, ] [[package]] @@ -2705,28 +2730,28 @@ wheels = [ [[package]] name = "uv" -version = "0.8.15" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/4f/7c/ab905b0425f88842f3d8e5da50491524f45a231b7a3dc9c988608162adb2/uv-0.8.15.tar.gz", hash = "sha256:8ea57b78be9f0911a2a50b6814d15aec7d1f8aa6517059dc8250b1414156f93a", size = 3602914, upload-time = "2025-09-03T14:32:15.552Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/67/1d/794352a01b40f2b0a0abe02f4f020219b3f59ee6ed900561be3b2b47a82b/uv-0.8.15-py3-none-linux_armv6l.whl", hash = "sha256:f02e6b8be08b840f86b8d5997b658b657acdda95bc216ecf62fce6c71414bdc7", size = 20136396, upload-time = "2025-09-03T14:31:30.404Z" }, - { url = "https://files.pythonhosted.org/packages/8f/89/528f01cff01eb8d10dd396f437656266443e399dda2fe4787b2cf6983698/uv-0.8.15-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:b0461bb1ad616c8bcb59c9b39ae9363245ca33815ebb1d11130385236eca21b9", size = 19297422, upload-time = "2025-09-03T14:31:34.412Z" }, - { url = "https://files.pythonhosted.org/packages/94/03/532af32a64d162894a1daebb7bc5028ba00225ea720cf0f287e934dc2bd5/uv-0.8.15-py3-none-macosx_11_0_arm64.whl", hash = "sha256:069eed78b79d1e88bced23e3d4303348edb0a0209e7cae0f20024c42430bf50f", size = 17882409, upload-time = "2025-09-03T14:31:36.993Z" }, - { url = "https://files.pythonhosted.org/packages/25/21/57df6d53fbadfa947d9d65a0926e5d8540199f49aa958d23be2707262a80/uv-0.8.15-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:333a93bb6af64f3b95ee99e82b4ea227e2af6362c45f91c89a24e2bfefb628f9", size = 19557216, upload-time = "2025-09-03T14:31:39.245Z" }, - { url = "https://files.pythonhosted.org/packages/68/22/c3784749e1c78119e5375ec34c6ea29e944192a601f17c746339611db237/uv-0.8.15-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7d5b19ac2bdda3d1456b5d6013af50b443ffb0e40c66d42874f71190a5364711", size = 19781097, upload-time = "2025-09-03T14:31:42.314Z" }, - { url = "https://files.pythonhosted.org/packages/00/28/0597599fb35408dd73e0a7d25108dca1fa6ce8f8d570c8f24151b0016eef/uv-0.8.15-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3330bb4f206a6180679a75a8b2e77ff0f933fcb06c028b6f4da877b10a5e4f95", size = 20741549, upload-time = "2025-09-03T14:31:44.574Z" }, - { url = "https://files.pythonhosted.org/packages/4f/61/98fa07981722660f5a3c28b987df99c2486f63d01b1256e6cca05a43bdce/uv-0.8.15-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:de9896ad4fa724ab317a8048f4891b9b23df1403b3724e96606f3be2dbbbf009", size = 22193727, upload-time = "2025-09-03T14:31:46.915Z" }, - { url = "https://files.pythonhosted.org/packages/fa/65/523188e11a759144b00f0fe48943f6d00706fcd9b5f561a54a07b9fd4541/uv-0.8.15-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:226360003e71084e0a73cbec72170e88634b045e95529654d067ea3741bba242", size = 21817550, upload-time = "2025-09-03T14:31:49.548Z" }, - { url = "https://files.pythonhosted.org/packages/99/3c/7898acf3d9ed2d3a2986cccc8209c14d3e9ac72dfaa616e49d329423b1d3/uv-0.8.15-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9488260536b35b94a79962fea76837f279c0cd0ae5021c761e66b311f47ffa70", size = 21024011, upload-time = "2025-09-03T14:31:51.789Z" }, - { url = "https://files.pythonhosted.org/packages/13/fc/e0da45ee179367dcc1e1040ad00ed8a99b78355d43024b0b5fc2edf5c389/uv-0.8.15-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:07765f99fd5fd3b257d7e210e8d0844c0a8fd111612e31fcca66a85656cc728e", size = 21009338, upload-time = "2025-09-03T14:31:54.104Z" }, - { url = "https://files.pythonhosted.org/packages/ce/5d/180904fa7ed49081b27f00e86f7220ca62cc098d7ef6459f0c69a8ae8f74/uv-0.8.15-py3-none-manylinux_2_28_aarch64.whl", hash = "sha256:c4868e6a4e1a8c777a5ba3cff452c405837318fb0b272ff203bfda0e1b8fc54d", size = 19799578, upload-time = "2025-09-03T14:31:56.47Z" }, - { url = "https://files.pythonhosted.org/packages/b6/09/fed823212e695b6765bdb8462850abffbe685cd965c4de905efed5e2e5c9/uv-0.8.15-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:3ec78a54a8eb0bbb9a9c653982390af84673657c8a48a0be6cdcb81d7d3e95c3", size = 20845428, upload-time = "2025-09-03T14:31:59.475Z" }, - { url = "https://files.pythonhosted.org/packages/b9/f3/9c4211897c00f79b7973a10800166e0580eaad20fe27f7c06adb7b248ac7/uv-0.8.15-py3-none-musllinux_1_1_armv7l.whl", hash = "sha256:a022a752d20da80d2a49fc0721522a81e3a32efe539152d756d84ebdba29dbc3", size = 19728113, upload-time = "2025-09-03T14:32:01.686Z" }, - { url = "https://files.pythonhosted.org/packages/3b/43/4ec6047150e2fba494d80d36b881a1a973835afa497ae9ccdf51828cae4f/uv-0.8.15-py3-none-musllinux_1_1_i686.whl", hash = "sha256:3780d2f3951d83e55812fdeb7eee233787b70c774497dbfc55b0fdf6063aa345", size = 20169115, upload-time = "2025-09-03T14:32:03.995Z" }, - { url = "https://files.pythonhosted.org/packages/ea/98/b4220bf462fb225c4a2d74ef4f105020238472b4b0da94ebc17a310d7b4e/uv-0.8.15-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:56f2451c9193ee1754ce1d8390ded68e9cb8dee0aaf7e2f38a9bd04d99be1be7", size = 21129804, upload-time = "2025-09-03T14:32:06.204Z" }, - { url = "https://files.pythonhosted.org/packages/5e/b8/40ce3d385254ac87a664a5d9a4664fac697e2734352f404382b81d03235b/uv-0.8.15-py3-none-win32.whl", hash = "sha256:89c7c10089e07d944c72d388fd88666c650dec2f8c79ca541e365f32843882c6", size = 19077103, upload-time = "2025-09-03T14:32:08.628Z" }, - { url = "https://files.pythonhosted.org/packages/2b/9d/081a0af395c0e307c0c930e80161a2aa551c25064cfb636d060574566fa4/uv-0.8.15-py3-none-win_amd64.whl", hash = "sha256:6aa824ab933dfafe11efe32e6541c6bcd65ecaa927e8e834ea6b14d3821020f6", size = 21179816, upload-time = "2025-09-03T14:32:11.42Z" }, - { url = "https://files.pythonhosted.org/packages/30/47/d8f50264a8c8ebbb9a44a8fed08b6e873d943adf299d944fe3a776ff5fbf/uv-0.8.15-py3-none-win_arm64.whl", hash = "sha256:a395fa1fc8948eacdd18e4592ed489fad13558b13fea6b3544cb16e5006c5b02", size = 19448833, upload-time = "2025-09-03T14:32:13.639Z" }, +version = "0.8.17" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/6f/4c/c270c6b8ed3e8c7fe38ea0b99df9eff09c332421b93d55a158371f75220e/uv-0.8.17.tar.gz", hash = "sha256:2afd4525a53c8ab3a11a5a15093c503d27da67e76257a649b05e4f0bc2ebb5ae", size = 3615060, upload-time = "2025-09-10T21:51:25.067Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b9/7d/bbaa45c88b2c91e02714a8a5c9e787c47e4898bddfdd268569163492ba45/uv-0.8.17-py3-none-linux_armv6l.whl", hash = "sha256:c51c9633ca93ef63c07df2443941e6264efd2819cc9faabfd9fe11899c6a0d6a", size = 20242144, upload-time = "2025-09-10T21:50:18.081Z" }, + { url = "https://files.pythonhosted.org/packages/65/34/609b72034df0c62bcfb0c0ad4b11e2b55e537c0f0817588b5337d3dcca71/uv-0.8.17-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:c28fba6d7bb5c34ade2c8da5000faebe8425a287f42a043ca01ceb24ebc81590", size = 19363081, upload-time = "2025-09-10T21:50:22.731Z" }, + { url = "https://files.pythonhosted.org/packages/b6/bc/9417df48f0c18a9d54c2444096e03f2f56a3534c5b869f50ac620729cbc8/uv-0.8.17-py3-none-macosx_11_0_arm64.whl", hash = "sha256:b009f1ec9e28de00f76814ad66e35aaae82c98a0f24015de51943dcd1c2a1895", size = 17943513, upload-time = "2025-09-10T21:50:25.824Z" }, + { url = "https://files.pythonhosted.org/packages/63/1c/14fd54c852fd592a2b5da4b7960f3bf4a15c7e51eb20eaddabe8c8cca32d/uv-0.8.17-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:84d56ae50ca71aec032577adf9737974554a82a94e52cee57722745656c1d383", size = 19507222, upload-time = "2025-09-10T21:50:29.237Z" }, + { url = "https://files.pythonhosted.org/packages/be/47/f6a68cc310feca37c965bcbd57eb999e023d35eaeda9c9759867bf3ed232/uv-0.8.17-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:85c2140f8553b9a4387a7395dc30cd151ef94046785fe8b198f13f2c380fb39b", size = 19865652, upload-time = "2025-09-10T21:50:32.87Z" }, + { url = "https://files.pythonhosted.org/packages/ab/6a/fdeb2d4a2635a6927c6d549b07177bcaf6ce15bdef58e8253e75c1b70f54/uv-0.8.17-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2076119783e4a6d3c9e25638956cb123f0eabf4d7d407d9661cdf7f84818dcb9", size = 20831760, upload-time = "2025-09-10T21:50:37.803Z" }, + { url = "https://files.pythonhosted.org/packages/d0/4c/bd58b8a76015aa9ac49d6b4e1211ae1ca98a0aade0c49e1a5f645fb5cd38/uv-0.8.17-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:707a55660d302924fdbcb509e63dfec8842e19d35b69bcc17af76c25db15ad6f", size = 22209056, upload-time = "2025-09-10T21:50:41.749Z" }, + { url = "https://files.pythonhosted.org/packages/7e/2e/28f59c00a2ed6532502fb1e27da9394e505fb7b41cc0274475104b43561b/uv-0.8.17-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1824b76911a14aaa9eee65ad9e180e6a4d2d7c86826232c2f28ae86aee56ed0e", size = 21871684, upload-time = "2025-09-10T21:50:45.331Z" }, + { url = "https://files.pythonhosted.org/packages/5a/1d/a8a4fc08de1f767316467e7a1989bb125734b7ed9cd98ce8969386a70653/uv-0.8.17-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bb9b515cc813fb1b08f1e7592f76e437e2fb44945e53cde4fee11dee3b16d0c3", size = 21145154, upload-time = "2025-09-10T21:50:50.388Z" }, + { url = "https://files.pythonhosted.org/packages/8f/35/cb47d2d07a383c07b0e5043c6fe5555f0fd79683c6d7f9760222987c8be9/uv-0.8.17-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b6d30d02fb65193309fc12a20f9e1a9fab67f469d3e487a254ca1145fd06788f", size = 21106619, upload-time = "2025-09-10T21:50:54.5Z" }, + { url = "https://files.pythonhosted.org/packages/6e/93/c310f0153b9dfe79bdd7f7eaef6380a8545c8939dbfc4e6bdee8f3ee7050/uv-0.8.17-py3-none-manylinux_2_28_aarch64.whl", hash = "sha256:3941cecd9a6a46d3d4505753912c9cf3e8ae5eea30b9d0813f3656210f8c5d01", size = 19777591, upload-time = "2025-09-10T21:50:57.765Z" }, + { url = "https://files.pythonhosted.org/packages/6c/4f/971d3c84c2f09cf8df4536c33644e6b97e10a259d8630a0c1696c1fa6e94/uv-0.8.17-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:cd0ad366cfe4cbe9212bd660b5b9f3a827ff35a7601cefdac2d153bfc8079eb7", size = 20845039, upload-time = "2025-09-10T21:51:01.167Z" }, + { url = "https://files.pythonhosted.org/packages/4a/29/8ad9038e75cb91f54b81cc933dd14fcfa92fa6f8706117d43d4251a8a662/uv-0.8.17-py3-none-musllinux_1_1_armv7l.whl", hash = "sha256:505854bc75c497b95d2c65590291dc820999a4a7d9dfab4f44a9434a6cff7b5f", size = 19820370, upload-time = "2025-09-10T21:51:04.616Z" }, + { url = "https://files.pythonhosted.org/packages/f2/c9/fc8482d1e7dfe187c6e03dcefbac0db41a5dd72aa7b017c0f80f91a04444/uv-0.8.17-py3-none-musllinux_1_1_i686.whl", hash = "sha256:dc479f661da449df37d68b36fdffa641e89fb53ad38c16a5c9f98f3211785b63", size = 20289951, upload-time = "2025-09-10T21:51:08.605Z" }, + { url = "https://files.pythonhosted.org/packages/2d/84/ad878ed045f02aa973be46636c802d494f8270caf5ea8bd04b7bbc68aa23/uv-0.8.17-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:a1d11cd805be6d137ffef4a8227905f87f459031c645ac5031c30a3bcd08abd6", size = 21234644, upload-time = "2025-09-10T21:51:12.429Z" }, + { url = "https://files.pythonhosted.org/packages/f8/03/3fa2641513922988e641050b3adbc87de527f44c2cc8328510703616be6a/uv-0.8.17-py3-none-win32.whl", hash = "sha256:d13a616eb0b2b33c7aa09746cc85860101d595655b58653f0b499af19f33467c", size = 19216757, upload-time = "2025-09-10T21:51:16.021Z" }, + { url = "https://files.pythonhosted.org/packages/1a/c4/0082f437bac162ab95e5a3a389a184c122d45eb5593960aab92fdf80374b/uv-0.8.17-py3-none-win_amd64.whl", hash = "sha256:cf85b84b81b41d57a9b6eeded8473ec06ace8ee959ad0bb57e102b5ad023bd34", size = 21125811, upload-time = "2025-09-10T21:51:19.397Z" }, + { url = "https://files.pythonhosted.org/packages/50/a2/29f57b118b3492c9d5ab1a99ba4906e7d7f8b658881d31bc2c4408d64d07/uv-0.8.17-py3-none-win_arm64.whl", hash = "sha256:64d649a8c4c3732b05dc712544963b004cf733d95fdc5d26f43c5493553ff0a7", size = 19564631, upload-time = "2025-09-10T21:51:22.599Z" }, ] [[package]] From f2ca356af325547270f3e6d214164a0982fe25c3 Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 12 Sep 2025 12:58:27 -0700 Subject: [PATCH 460/521] add tests for namedtuple dIdVExtras --- .../test_plasma_potential_didv.py | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 tests/analysis/swept_langmuir/test_plasma_potential_didv.py diff --git a/tests/analysis/swept_langmuir/test_plasma_potential_didv.py b/tests/analysis/swept_langmuir/test_plasma_potential_didv.py new file mode 100644 index 0000000000..3be6b6edb3 --- /dev/null +++ b/tests/analysis/swept_langmuir/test_plasma_potential_didv.py @@ -0,0 +1,53 @@ +""" +Tests for functionality contained in +`plasmapy.analysis.swept_langmuir.plasma_potential` that calculates the +peak slope of the langmuir drives (i.e. peak dI/dV). +""" + +from unittest import mock + +import operator +import numpy as np +import pytest + +from plasmapy.analysis import fit_functions as ffuncs +from plasmapy.analysis import swept_langmuir as sla +from plasmapy.analysis.swept_langmuir.plasma_potential import ( + dIdVExtras, + find_didv_peak_location, +) +from plasmapy.utils.exceptions import PlasmaPyWarning + + +@pytest.mark.parametrize( + ("assert_op", "arg1", "expected"), + [ + (issubclass, dIdVExtras, tuple), + (hasattr, dIdVExtras, "_fields"), + (hasattr, dIdVExtras, "_field_defaults"), + ( + operator.eq, + set(dIdVExtras._fields), + {"std", "data_slice", "savgol_windows", "savgol_peaks"}, + ), + (operator.eq, dIdVExtras._field_defaults, dict()), + ], +) +def test_didv_namedtuple(assert_op, arg1, expected): + assert assert_op(arg1, expected) + + +@pytest.mark.parametrize( + ("index", "field_name"), + [(0, "std"), (1, "data_slice"), (2, "savgol_windows"), (3, "savgol_peaks")], +) +def test_didv_namedtuple_index_field_mapping(index, field_name): + extras = dIdVExtras( + std=0.1, + data_slice=slice(4, 20, 2), + savgol_windows=[4, 6, 8], + savgol_peaks=[1.1, 1.2, 1.3], + ) + + assert extras[index] == getattr(extras, field_name) + From 5d8bd8977dcb080e8ab0aa333c840f826e24c895 Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 15 Sep 2025 13:12:55 -0700 Subject: [PATCH 461/521] expand docstring for _condition_voltage_window --- .../analysis/swept_langmuir/helpers.py | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/plasmapy/analysis/swept_langmuir/helpers.py b/src/plasmapy/analysis/swept_langmuir/helpers.py index 334ebbea9d..b04214a6d5 100644 --- a/src/plasmapy/analysis/swept_langmuir/helpers.py +++ b/src/plasmapy/analysis/swept_langmuir/helpers.py @@ -572,6 +572,27 @@ def _condition_voltage_window(voltage, voltage_window) -> slice: """ Condition ``voltage_window`` and return resulting `slice` object to index ``voltage``. + + Parameters + ---------- + voltage : `numpy.ndarray` + 1-D numpy array of monotonically increasing probe biases + (should be in volts). + + voltage_window : `list[float | None]` | `None`, default: `None` + A two-element list ``[v_min, v_max]`` that specifies the voltage + range in which the peak slope will be looked for. Specifying + `None` for either the first or second element will result in a + window using the lower or upper bound of ``voltage`` + respectively. If set to `None` (default), then the whole + ``voltage`` window will be used. + + Returns + ------- + voltage_window : `slice` + A `slice` object representing the window originally defined + by the input ``voltage_window``. + """ if isinstance(voltage_window, np.ndarray): voltage_window = voltage_window.tolist() From bbb57607e234f9ad44f760c20cb90018e1852978 Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 15 Sep 2025 13:13:48 -0700 Subject: [PATCH 462/521] _condition_voltage_window: handle case where voltage_window is a string --- src/plasmapy/analysis/swept_langmuir/helpers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plasmapy/analysis/swept_langmuir/helpers.py b/src/plasmapy/analysis/swept_langmuir/helpers.py index b04214a6d5..80080d33da 100644 --- a/src/plasmapy/analysis/swept_langmuir/helpers.py +++ b/src/plasmapy/analysis/swept_langmuir/helpers.py @@ -599,7 +599,7 @@ def _condition_voltage_window(voltage, voltage_window) -> slice: if voltage_window is None: voltage_window = [None, None] - elif not isinstance(voltage_window, Sequence): + elif not isinstance(voltage_window, Sequence) or isinstance(voltage_window, str): raise TypeError( f"Expected a 2-element list of floats or None for 'voltage_window', " f"but got type {type(voltage_window)}." From 66fb53f9f393f92c52ce94ccc82abdd19ceb749e Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 15 Sep 2025 13:14:20 -0700 Subject: [PATCH 463/521] _condition_voltage_window: if first_index is 0 set to None --- src/plasmapy/analysis/swept_langmuir/helpers.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/plasmapy/analysis/swept_langmuir/helpers.py b/src/plasmapy/analysis/swept_langmuir/helpers.py index 80080d33da..5f669a1d2f 100644 --- a/src/plasmapy/analysis/swept_langmuir/helpers.py +++ b/src/plasmapy/analysis/swept_langmuir/helpers.py @@ -640,6 +640,8 @@ def _condition_voltage_window(voltage, voltage_window) -> slice: if voltage_window[0] is None else int(np.where(voltage >= voltage_window[0])[0][0]) ) + if first_index == 0: + first_index = None last_index = ( None From bd25c14b0b78f4a5508a9eb4e4f24b4d6ada0958 Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 15 Sep 2025 13:14:52 -0700 Subject: [PATCH 464/521] _condition_voltage_window: for last_index handle the +1 for the slice object --- src/plasmapy/analysis/swept_langmuir/helpers.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/plasmapy/analysis/swept_langmuir/helpers.py b/src/plasmapy/analysis/swept_langmuir/helpers.py index 5f669a1d2f..d3e11189a0 100644 --- a/src/plasmapy/analysis/swept_langmuir/helpers.py +++ b/src/plasmapy/analysis/swept_langmuir/helpers.py @@ -648,5 +648,11 @@ def _condition_voltage_window(voltage, voltage_window) -> slice: if voltage_window[1] is None else int(np.where(voltage <= voltage_window[1])[0][-1]) ) + if last_index is None: + pass + elif last_index == voltage.size-1: + last_index = None + else: + last_index += 1 return slice(first_index, last_index, 1) From 201f597036fe698d249192f1fe06ac644a05a0ca Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 15 Sep 2025 13:15:14 -0700 Subject: [PATCH 465/521] add tests for _condition_voltage_window --- .../test_helpers__condition_voltage_window.py | 65 +++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 tests/analysis/swept_langmuir/test_helpers__condition_voltage_window.py diff --git a/tests/analysis/swept_langmuir/test_helpers__condition_voltage_window.py b/tests/analysis/swept_langmuir/test_helpers__condition_voltage_window.py new file mode 100644 index 0000000000..47955a3111 --- /dev/null +++ b/tests/analysis/swept_langmuir/test_helpers__condition_voltage_window.py @@ -0,0 +1,65 @@ +""" +Tests for +`plasmapy.analysis.swept_langmuir.helpers._condition_voltage_window`. +""" + +from unittest import mock + +import operator +import numpy as np +import pytest + +from plasmapy.analysis import fit_functions as ffuncs +from plasmapy.analysis import swept_langmuir as sla +from plasmapy.analysis.swept_langmuir.helpers import _condition_voltage_window + + +class TestConditionVoltageWindow: + + @pytest.mark.parametrize( + ("_raises", "voltage", "voltage_window"), + [ + # voltage_window is not a list-like or None + (pytest.raises(TypeError), np.arange(10.), {"one": 1, "two": 2}), + (pytest.raises(TypeError), np.arange(10.), "invalid window"), + (pytest.raises(TypeError), np.arange(10.), 5.0), + # voltage_window is wrong size + (pytest.raises(ValueError), np.arange(10.), []), + (pytest.raises(ValueError), np.arange(10.), [5.0]), + (pytest.raises(ValueError), np.arange(10.), (-1.0, 2.0, 5.0)), + # voltage_window does not have Real numbers or None + (pytest.raises(TypeError), np.arange(10.), ["one", 2]), + (pytest.raises(TypeError), np.arange(10.), ["one", "two"]), + (pytest.raises(TypeError), np.arange(10.), [(1., 2.), 2.0]), + # voltage_window is out of range + (pytest.raises(ValueError), np.arange(10.), [-5, -2]), + (pytest.raises(ValueError), np.arange(10.), [11, 18]), + ] + ) + def test_raises(self, _raises, voltage, voltage_window): + with _raises: + _condition_voltage_window(voltage, voltage_window) + + @pytest.mark.parametrize( + ("voltage", "voltage_window", "expected"), + [ + # voltage_window as list and numpy array + (np.arange(10), [3.3, 4.5], slice(4, 5, 1)), + (np.arange(10), np.array([3.3, 4.5]), slice(4, 5, 1)), + (np.arange(10), [3.3, 7.2], slice(4, 8, 1)), + (np.arange(10), np.array([3.3, 7.2]), slice(4, 8, 1)), + # voltage_window has None values + (np.arange(10), None, slice(None, None, 1)), + (np.arange(10), [None, None], slice(None, None, 1)), + (np.arange(10), [3.3, None], slice(4, None, 1)), + (np.arange(10), [None, 7.2], slice(None, 8, 1)), + # voltage_window is unsorted + (np.arange(10), [7.2, 3.3], slice(4, 8, 1)), + # voltage_window has one index out of bounds + (np.arange(10), [-5, 7.2], slice(None, 8, 1)), + (np.arange(10), [3.3, 20], slice(4, None, 1)), + ], + ) + def test_expected(self, voltage, voltage_window, expected): + result = _condition_voltage_window(voltage, voltage_window) + assert result == expected From 4efb1b94c3e3e6b7bad9add16a423cf90a5588e7 Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 15 Sep 2025 13:23:30 -0700 Subject: [PATCH 466/521] remove unused imports --- .../test_helpers__condition_voltage_window.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/tests/analysis/swept_langmuir/test_helpers__condition_voltage_window.py b/tests/analysis/swept_langmuir/test_helpers__condition_voltage_window.py index 47955a3111..4f24419173 100644 --- a/tests/analysis/swept_langmuir/test_helpers__condition_voltage_window.py +++ b/tests/analysis/swept_langmuir/test_helpers__condition_voltage_window.py @@ -2,15 +2,9 @@ Tests for `plasmapy.analysis.swept_langmuir.helpers._condition_voltage_window`. """ - -from unittest import mock - -import operator import numpy as np import pytest -from plasmapy.analysis import fit_functions as ffuncs -from plasmapy.analysis import swept_langmuir as sla from plasmapy.analysis.swept_langmuir.helpers import _condition_voltage_window From 29215906627044174bd1b119c88b718d1705a786 Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 15 Sep 2025 13:24:08 -0700 Subject: [PATCH 467/521] appease grumpy ruff format --- .../test_helpers__condition_voltage_window.py | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/tests/analysis/swept_langmuir/test_helpers__condition_voltage_window.py b/tests/analysis/swept_langmuir/test_helpers__condition_voltage_window.py index 4f24419173..d99cd8f5e0 100644 --- a/tests/analysis/swept_langmuir/test_helpers__condition_voltage_window.py +++ b/tests/analysis/swept_langmuir/test_helpers__condition_voltage_window.py @@ -2,6 +2,7 @@ Tests for `plasmapy.analysis.swept_langmuir.helpers._condition_voltage_window`. """ + import numpy as np import pytest @@ -9,26 +10,25 @@ class TestConditionVoltageWindow: - @pytest.mark.parametrize( ("_raises", "voltage", "voltage_window"), [ # voltage_window is not a list-like or None - (pytest.raises(TypeError), np.arange(10.), {"one": 1, "two": 2}), - (pytest.raises(TypeError), np.arange(10.), "invalid window"), - (pytest.raises(TypeError), np.arange(10.), 5.0), + (pytest.raises(TypeError), np.arange(10.0), {"one": 1, "two": 2}), + (pytest.raises(TypeError), np.arange(10.0), "invalid window"), + (pytest.raises(TypeError), np.arange(10.0), 5.0), # voltage_window is wrong size - (pytest.raises(ValueError), np.arange(10.), []), - (pytest.raises(ValueError), np.arange(10.), [5.0]), - (pytest.raises(ValueError), np.arange(10.), (-1.0, 2.0, 5.0)), + (pytest.raises(ValueError), np.arange(10.0), []), + (pytest.raises(ValueError), np.arange(10.0), [5.0]), + (pytest.raises(ValueError), np.arange(10.0), (-1.0, 2.0, 5.0)), # voltage_window does not have Real numbers or None - (pytest.raises(TypeError), np.arange(10.), ["one", 2]), - (pytest.raises(TypeError), np.arange(10.), ["one", "two"]), - (pytest.raises(TypeError), np.arange(10.), [(1., 2.), 2.0]), + (pytest.raises(TypeError), np.arange(10.0), ["one", 2]), + (pytest.raises(TypeError), np.arange(10.0), ["one", "two"]), + (pytest.raises(TypeError), np.arange(10.0), [(1.0, 2.0), 2.0]), # voltage_window is out of range - (pytest.raises(ValueError), np.arange(10.), [-5, -2]), - (pytest.raises(ValueError), np.arange(10.), [11, 18]), - ] + (pytest.raises(ValueError), np.arange(10.0), [-5, -2]), + (pytest.raises(ValueError), np.arange(10.0), [11, 18]), + ], ) def test_raises(self, _raises, voltage, voltage_window): with _raises: From 405528aec528a62759adcafcf1d096caaa0667d2 Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 15 Sep 2025 13:25:55 -0700 Subject: [PATCH 468/521] add noqa to _condition_voltage_window --- src/plasmapy/analysis/swept_langmuir/helpers.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/plasmapy/analysis/swept_langmuir/helpers.py b/src/plasmapy/analysis/swept_langmuir/helpers.py index d3e11189a0..94f8e49ac8 100644 --- a/src/plasmapy/analysis/swept_langmuir/helpers.py +++ b/src/plasmapy/analysis/swept_langmuir/helpers.py @@ -568,7 +568,9 @@ def merge_voltage_clusters( # noqa: C901, PLR0912 return new_voltage, new_current -def _condition_voltage_window(voltage, voltage_window) -> slice: +def _condition_voltage_window( # noqa: C901, PLR0912 + voltage, voltage_window +) -> slice: """ Condition ``voltage_window`` and return resulting `slice` object to index ``voltage``. From 755cb567f7263563660d0f6d246fcdda22fb04ed Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 15 Sep 2025 13:27:08 -0700 Subject: [PATCH 469/521] replace dict() with {} --- tests/analysis/swept_langmuir/test_plasma_potential_didv.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/analysis/swept_langmuir/test_plasma_potential_didv.py b/tests/analysis/swept_langmuir/test_plasma_potential_didv.py index 3be6b6edb3..9150ee54b6 100644 --- a/tests/analysis/swept_langmuir/test_plasma_potential_didv.py +++ b/tests/analysis/swept_langmuir/test_plasma_potential_didv.py @@ -30,7 +30,7 @@ set(dIdVExtras._fields), {"std", "data_slice", "savgol_windows", "savgol_peaks"}, ), - (operator.eq, dIdVExtras._field_defaults, dict()), + (operator.eq, dIdVExtras._field_defaults, {}), ], ) def test_didv_namedtuple(assert_op, arg1, expected): From f363aa60c8129c0ad92bc60f9779318f42f8ca96 Mon Sep 17 00:00:00 2001 From: "plasmapy-requirements-bot[bot]" <134649236+plasmapy-requirements-bot[bot]@users.noreply.github.com> Date: Mon, 22 Sep 2025 15:53:48 +0000 Subject: [PATCH 470/521] =?UTF-8?q?Update=20pinned=20requirements=20?= =?UTF-8?q?=F0=9F=93=8D=20(#3109)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update requirements with 'nox -s requirements' * nox -s requirements * Change annotation --------- Co-authored-by: namurphy <8931994+namurphy@users.noreply.github.com> Co-authored-by: Nick Murphy --- README.md | 9 +- src/plasmapy/plasma/grids.py | 2 +- uv.lock | 391 ++++++++++++++++++----------------- 3 files changed, 207 insertions(+), 195 deletions(-) diff --git a/README.md b/README.md index 4e74f27636..7548ce918d 100644 --- a/README.md +++ b/README.md @@ -102,11 +102,12 @@ about these meetings is on the [meetings] page of PlasmaPy's website. ### Community meetings -PlasmaPy's weekly [community meetings] are a place to talk about code -development, event planning, and other community happenings. If you have -an idea for a new feature or would like to become involved in the +PlasmaPy's [community meetings] are a place to talk about code +development, event planning, and other community happenings. If you +have an idea for a new feature or would like to become involved in the PlasmaPy project, community meetings are a great place to start. As of -May 2025, our community meetings are on most Thursdays at 2 pm ET. +September 2025, our community meetings are usually held every other +Monday at 1 pm ET. ## Community diff --git a/src/plasmapy/plasma/grids.py b/src/plasmapy/plasma/grids.py index 39d9078cb3..29ba301ac3 100644 --- a/src/plasmapy/plasma/grids.py +++ b/src/plasmapy/plasma/grids.py @@ -897,7 +897,7 @@ def vector_intersects(self, p1, p2): # This property holds the list of quantity keys currently being interpolated # It's used in the following cached properties - _interp_args: ClassVar = [] + _interp_args: ClassVar[list[str]] = [] @cached_property def _interp_quantities(self): diff --git a/uv.lock b/uv.lock index 3156c2715b..3521896d6c 100644 --- a/uv.lock +++ b/uv.lock @@ -80,11 +80,11 @@ wheels = [ [[package]] name = "astropy-iers-data" -version = "0.2025.9.8.0.36.17" +version = "0.2025.9.15.0.37.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/c2/29/7716f0c3ab22f5fbc3b80d90a7687e40aab3ba32b66dd2b8ecdb09663fe1/astropy_iers_data-0.2025.9.8.0.36.17.tar.gz", hash = "sha256:63c1d647b5a2b82b67b5b923e6d4c60fd2ee6f6d88903438b701bfe302750df0", size = 1907563, upload-time = "2025-09-08T00:37:09.833Z" } +sdist = { url = "https://files.pythonhosted.org/packages/37/97/247deecc933ca6a30ed137c19740d3f738df27fdc1de9c0a88cfaba00779/astropy_iers_data-0.2025.9.15.0.37.0.tar.gz", hash = "sha256:33e513dcfdc1b5a7c34e1cc674f4a050b29f93af5ac829e05d868a681d3091d8", size = 1908647, upload-time = "2025-09-15T00:37:46.311Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/85/25/40a8354d8c062955593d1323051c1c8dfd02609e2d1041ef4ae36d745f95/astropy_iers_data-0.2025.9.8.0.36.17-py3-none-any.whl", hash = "sha256:926719b70dafd0e27eeabebb6bb38df3a2d784e1e934c094bf75d954a21423fe", size = 1963139, upload-time = "2025-09-08T00:37:07.762Z" }, + { url = "https://files.pythonhosted.org/packages/03/8c/a556b71e4603d6156814da968b7cefa9bd882e59dc691168584418f4de77/astropy_iers_data-0.2025.9.15.0.37.0-py3-none-any.whl", hash = "sha256:4ea19813150f2d6dfb0257c5e96d14ae9eac6e5a80af27ec79e3aaef8aadfa93", size = 1964242, upload-time = "2025-09-15T00:37:44.298Z" }, ] [[package]] @@ -278,14 +278,14 @@ wheels = [ [[package]] name = "click" -version = "8.2.1" +version = "8.3.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "colorama", marker = "sys_platform == 'win32'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/60/6c/8ca2efa64cf75a977a0d7fac081354553ebe483345c734fb6b6515d96bbc/click-8.2.1.tar.gz", hash = "sha256:27c491cc05d968d271d5a1db13e3b5a184636d9d930f148c50b038f0d0646202", size = 286342, upload-time = "2025-05-20T23:19:49.832Z" } +sdist = { url = "https://files.pythonhosted.org/packages/46/61/de6cd827efad202d7057d93e0fed9294b96952e188f7384832791c7b2254/click-8.3.0.tar.gz", hash = "sha256:e7b8232224eba16f4ebe410c25ced9f7875cb5f3263ffc93cc3e8da705e229c4", size = 276943, upload-time = "2025-09-18T17:32:23.696Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/85/32/10bb5764d90a8eee674e9dc6f4db6a0ab47c8c4d0d83c27f7c39ac415a4d/click-8.2.1-py3-none-any.whl", hash = "sha256:61a3265b914e850b85317d0b3109c7f8cd35a670f963866005d6ef1d5175a12b", size = 102215, upload-time = "2025-05-20T23:19:47.796Z" }, + { url = "https://files.pythonhosted.org/packages/db/d3/9dcc0f5797f070ec8edf30fbadfb200e71d9db6b84d211e3b2085a7589a0/click-8.3.0-py3-none-any.whl", hash = "sha256:9b9f285302c6e3064f4330c05f05b81945b2a39544279343e6e7c5f27a9baddc", size = 107295, upload-time = "2025-09-18T17:32:22.42Z" }, ] [[package]] @@ -491,23 +491,27 @@ wheels = [ [[package]] name = "debugpy" -version = "1.8.16" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/ca/d4/722d0bcc7986172ac2ef3c979ad56a1030e3afd44ced136d45f8142b1f4a/debugpy-1.8.16.tar.gz", hash = "sha256:31e69a1feb1cf6b51efbed3f6c9b0ef03bc46ff050679c4be7ea6d2e23540870", size = 1643809, upload-time = "2025-08-06T18:00:02.647Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/63/d6/ad70ba8b49b23fa286fb21081cf732232cc19374af362051da9c7537ae52/debugpy-1.8.16-cp311-cp311-macosx_14_0_universal2.whl", hash = "sha256:67371b28b79a6a12bcc027d94a06158f2fde223e35b5c4e0783b6f9d3b39274a", size = 2184063, upload-time = "2025-08-06T18:00:11.885Z" }, - { url = "https://files.pythonhosted.org/packages/aa/49/7b03e88dea9759a4c7910143f87f92beb494daaae25560184ff4ae883f9e/debugpy-1.8.16-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b2abae6dd02523bec2dee16bd6b0781cccb53fd4995e5c71cc659b5f45581898", size = 3134837, upload-time = "2025-08-06T18:00:13.782Z" }, - { url = "https://files.pythonhosted.org/packages/5d/52/b348930316921de7565fbe37a487d15409041713004f3d74d03eb077dbd4/debugpy-1.8.16-cp311-cp311-win32.whl", hash = "sha256:f8340a3ac2ed4f5da59e064aa92e39edd52729a88fbde7bbaa54e08249a04493", size = 5159142, upload-time = "2025-08-06T18:00:15.391Z" }, - { url = "https://files.pythonhosted.org/packages/d8/ef/9aa9549ce1e10cea696d980292e71672a91ee4a6a691ce5f8629e8f48c49/debugpy-1.8.16-cp311-cp311-win_amd64.whl", hash = "sha256:70f5fcd6d4d0c150a878d2aa37391c52de788c3dc680b97bdb5e529cb80df87a", size = 5183117, upload-time = "2025-08-06T18:00:17.251Z" }, - { url = "https://files.pythonhosted.org/packages/61/fb/0387c0e108d842c902801bc65ccc53e5b91d8c169702a9bbf4f7efcedf0c/debugpy-1.8.16-cp312-cp312-macosx_14_0_universal2.whl", hash = "sha256:b202e2843e32e80b3b584bcebfe0e65e0392920dc70df11b2bfe1afcb7a085e4", size = 2511822, upload-time = "2025-08-06T18:00:18.526Z" }, - { url = "https://files.pythonhosted.org/packages/37/44/19e02745cae22bf96440141f94e15a69a1afaa3a64ddfc38004668fcdebf/debugpy-1.8.16-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:64473c4a306ba11a99fe0bb14622ba4fbd943eb004847d9b69b107bde45aa9ea", size = 4230135, upload-time = "2025-08-06T18:00:19.997Z" }, - { url = "https://files.pythonhosted.org/packages/f3/0b/19b1ba5ee4412f303475a2c7ad5858efb99c90eae5ec627aa6275c439957/debugpy-1.8.16-cp312-cp312-win32.whl", hash = "sha256:833a61ed446426e38b0dd8be3e9d45ae285d424f5bf6cd5b2b559c8f12305508", size = 5281271, upload-time = "2025-08-06T18:00:21.281Z" }, - { url = "https://files.pythonhosted.org/packages/b1/e0/bc62e2dc141de53bd03e2c7cb9d7011de2e65e8bdcdaa26703e4d28656ba/debugpy-1.8.16-cp312-cp312-win_amd64.whl", hash = "sha256:75f204684581e9ef3dc2f67687c3c8c183fde2d6675ab131d94084baf8084121", size = 5323149, upload-time = "2025-08-06T18:00:23.033Z" }, - { url = "https://files.pythonhosted.org/packages/62/66/607ab45cc79e60624df386e233ab64a6d8d39ea02e7f80e19c1d451345bb/debugpy-1.8.16-cp313-cp313-macosx_14_0_universal2.whl", hash = "sha256:85df3adb1de5258dca910ae0bb185e48c98801ec15018a263a92bb06be1c8787", size = 2496157, upload-time = "2025-08-06T18:00:24.361Z" }, - { url = "https://files.pythonhosted.org/packages/4d/a0/c95baae08a75bceabb79868d663a0736655e427ab9c81fb848da29edaeac/debugpy-1.8.16-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bee89e948bc236a5c43c4214ac62d28b29388453f5fd328d739035e205365f0b", size = 4222491, upload-time = "2025-08-06T18:00:25.806Z" }, - { url = "https://files.pythonhosted.org/packages/5b/2f/1c8db6ddd8a257c3cd2c46413b267f1d5fa3df910401c899513ce30392d6/debugpy-1.8.16-cp313-cp313-win32.whl", hash = "sha256:cf358066650439847ec5ff3dae1da98b5461ea5da0173d93d5e10f477c94609a", size = 5281126, upload-time = "2025-08-06T18:00:27.207Z" }, - { url = "https://files.pythonhosted.org/packages/d3/ba/c3e154ab307366d6c5a9c1b68de04914e2ce7fa2f50d578311d8cc5074b2/debugpy-1.8.16-cp313-cp313-win_amd64.whl", hash = "sha256:b5aea1083f6f50023e8509399d7dc6535a351cc9f2e8827d1e093175e4d9fa4c", size = 5323094, upload-time = "2025-08-06T18:00:29.03Z" }, - { url = "https://files.pythonhosted.org/packages/52/57/ecc9ae29fa5b2d90107cd1d9bf8ed19aacb74b2264d986ae9d44fe9bdf87/debugpy-1.8.16-py2.py3-none-any.whl", hash = "sha256:19c9521962475b87da6f673514f7fd610328757ec993bf7ec0d8c96f9a325f9e", size = 5287700, upload-time = "2025-08-06T18:00:42.333Z" }, +version = "1.8.17" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/15/ad/71e708ff4ca377c4230530d6a7aa7992592648c122a2cd2b321cf8b35a76/debugpy-1.8.17.tar.gz", hash = "sha256:fd723b47a8c08892b1a16b2c6239a8b96637c62a59b94bb5dab4bac592a58a8e", size = 1644129, upload-time = "2025-09-17T16:33:20.633Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d8/53/3af72b5c159278c4a0cf4cffa518675a0e73bdb7d1cac0239b815502d2ce/debugpy-1.8.17-cp311-cp311-macosx_15_0_universal2.whl", hash = "sha256:d3fce3f0e3de262a3b67e69916d001f3e767661c6e1ee42553009d445d1cd840", size = 2207154, upload-time = "2025-09-17T16:33:29.457Z" }, + { url = "https://files.pythonhosted.org/packages/8f/6d/204f407df45600e2245b4a39860ed4ba32552330a0b3f5f160ae4cc30072/debugpy-1.8.17-cp311-cp311-manylinux_2_34_x86_64.whl", hash = "sha256:c6bdf134457ae0cac6fb68205776be635d31174eeac9541e1d0c062165c6461f", size = 3170322, upload-time = "2025-09-17T16:33:30.837Z" }, + { url = "https://files.pythonhosted.org/packages/f2/13/1b8f87d39cf83c6b713de2620c31205299e6065622e7dd37aff4808dd410/debugpy-1.8.17-cp311-cp311-win32.whl", hash = "sha256:e79a195f9e059edfe5d8bf6f3749b2599452d3e9380484cd261f6b7cd2c7c4da", size = 5155078, upload-time = "2025-09-17T16:33:33.331Z" }, + { url = "https://files.pythonhosted.org/packages/c2/c5/c012c60a2922cc91caa9675d0ddfbb14ba59e1e36228355f41cab6483469/debugpy-1.8.17-cp311-cp311-win_amd64.whl", hash = "sha256:b532282ad4eca958b1b2d7dbcb2b7218e02cb934165859b918e3b6ba7772d3f4", size = 5179011, upload-time = "2025-09-17T16:33:35.711Z" }, + { url = "https://files.pythonhosted.org/packages/08/2b/9d8e65beb2751876c82e1aceb32f328c43ec872711fa80257c7674f45650/debugpy-1.8.17-cp312-cp312-macosx_15_0_universal2.whl", hash = "sha256:f14467edef672195c6f6b8e27ce5005313cb5d03c9239059bc7182b60c176e2d", size = 2549522, upload-time = "2025-09-17T16:33:38.466Z" }, + { url = "https://files.pythonhosted.org/packages/b4/78/eb0d77f02971c05fca0eb7465b18058ba84bd957062f5eec82f941ac792a/debugpy-1.8.17-cp312-cp312-manylinux_2_34_x86_64.whl", hash = "sha256:24693179ef9dfa20dca8605905a42b392be56d410c333af82f1c5dff807a64cc", size = 4309417, upload-time = "2025-09-17T16:33:41.299Z" }, + { url = "https://files.pythonhosted.org/packages/37/42/c40f1d8cc1fed1e75ea54298a382395b8b937d923fcf41ab0797a554f555/debugpy-1.8.17-cp312-cp312-win32.whl", hash = "sha256:6a4e9dacf2cbb60d2514ff7b04b4534b0139facbf2abdffe0639ddb6088e59cf", size = 5277130, upload-time = "2025-09-17T16:33:43.554Z" }, + { url = "https://files.pythonhosted.org/packages/72/22/84263b205baad32b81b36eac076de0cdbe09fe2d0637f5b32243dc7c925b/debugpy-1.8.17-cp312-cp312-win_amd64.whl", hash = "sha256:e8f8f61c518952fb15f74a302e068b48d9c4691768ade433e4adeea961993464", size = 5319053, upload-time = "2025-09-17T16:33:53.033Z" }, + { url = "https://files.pythonhosted.org/packages/50/76/597e5cb97d026274ba297af8d89138dfd9e695767ba0e0895edb20963f40/debugpy-1.8.17-cp313-cp313-macosx_15_0_universal2.whl", hash = "sha256:857c1dd5d70042502aef1c6d1c2801211f3ea7e56f75e9c335f434afb403e464", size = 2538386, upload-time = "2025-09-17T16:33:54.594Z" }, + { url = "https://files.pythonhosted.org/packages/5f/60/ce5c34fcdfec493701f9d1532dba95b21b2f6394147234dce21160bd923f/debugpy-1.8.17-cp313-cp313-manylinux_2_34_x86_64.whl", hash = "sha256:3bea3b0b12f3946e098cce9b43c3c46e317b567f79570c3f43f0b96d00788088", size = 4292100, upload-time = "2025-09-17T16:33:56.353Z" }, + { url = "https://files.pythonhosted.org/packages/e8/95/7873cf2146577ef71d2a20bf553f12df865922a6f87b9e8ee1df04f01785/debugpy-1.8.17-cp313-cp313-win32.whl", hash = "sha256:e34ee844c2f17b18556b5bbe59e1e2ff4e86a00282d2a46edab73fd7f18f4a83", size = 5277002, upload-time = "2025-09-17T16:33:58.231Z" }, + { url = "https://files.pythonhosted.org/packages/46/11/18c79a1cee5ff539a94ec4aa290c1c069a5580fd5cfd2fb2e282f8e905da/debugpy-1.8.17-cp313-cp313-win_amd64.whl", hash = "sha256:6c5cd6f009ad4fca8e33e5238210dc1e5f42db07d4b6ab21ac7ffa904a196420", size = 5319047, upload-time = "2025-09-17T16:34:00.586Z" }, + { url = "https://files.pythonhosted.org/packages/de/45/115d55b2a9da6de812696064ceb505c31e952c5d89c4ed1d9bb983deec34/debugpy-1.8.17-cp314-cp314-macosx_15_0_universal2.whl", hash = "sha256:045290c010bcd2d82bc97aa2daf6837443cd52f6328592698809b4549babcee1", size = 2536899, upload-time = "2025-09-17T16:34:02.657Z" }, + { url = "https://files.pythonhosted.org/packages/5a/73/2aa00c7f1f06e997ef57dc9b23d61a92120bec1437a012afb6d176585197/debugpy-1.8.17-cp314-cp314-manylinux_2_34_x86_64.whl", hash = "sha256:b69b6bd9dba6a03632534cdf67c760625760a215ae289f7489a452af1031fe1f", size = 4268254, upload-time = "2025-09-17T16:34:04.486Z" }, + { url = "https://files.pythonhosted.org/packages/86/b5/ed3e65c63c68a6634e3ba04bd10255c8e46ec16ebed7d1c79e4816d8a760/debugpy-1.8.17-cp314-cp314-win32.whl", hash = "sha256:5c59b74aa5630f3a5194467100c3b3d1c77898f9ab27e3f7dc5d40fc2f122670", size = 5277203, upload-time = "2025-09-17T16:34:06.65Z" }, + { url = "https://files.pythonhosted.org/packages/b0/26/394276b71c7538445f29e792f589ab7379ae70fd26ff5577dfde71158e96/debugpy-1.8.17-cp314-cp314-win_amd64.whl", hash = "sha256:893cba7bb0f55161de4365584b025f7064e1f88913551bcd23be3260b231429c", size = 5318493, upload-time = "2025-09-17T16:34:08.483Z" }, + { url = "https://files.pythonhosted.org/packages/b0/d0/89247ec250369fc76db477720a26b2fce7ba079ff1380e4ab4529d2fe233/debugpy-1.8.17-py2.py3-none-any.whl", hash = "sha256:60c7dca6571efe660ccb7a9508d73ca14b8796c4ed484c2002abba714226cfef", size = 5283210, upload-time = "2025-09-17T16:34:25.835Z" }, ] [[package]] @@ -605,51 +609,51 @@ wheels = [ [[package]] name = "fonttools" -version = "4.59.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/0d/a5/fba25f9fbdab96e26dedcaeeba125e5f05a09043bf888e0305326e55685b/fonttools-4.59.2.tar.gz", hash = "sha256:e72c0749b06113f50bcb80332364c6be83a9582d6e3db3fe0b280f996dc2ef22", size = 3540889, upload-time = "2025-08-27T16:40:30.97Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/f8/53/742fcd750ae0bdc74de4c0ff923111199cc2f90a4ee87aaddad505b6f477/fonttools-4.59.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:511946e8d7ea5c0d6c7a53c4cb3ee48eda9ab9797cd9bf5d95829a398400354f", size = 2774961, upload-time = "2025-08-27T16:38:47.536Z" }, - { url = "https://files.pythonhosted.org/packages/57/2a/976f5f9fa3b4dd911dc58d07358467bec20e813d933bc5d3db1a955dd456/fonttools-4.59.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:8e5e2682cf7be766d84f462ba8828d01e00c8751a8e8e7ce12d7784ccb69a30d", size = 2344690, upload-time = "2025-08-27T16:38:49.723Z" }, - { url = "https://files.pythonhosted.org/packages/c1/8f/b7eefc274fcf370911e292e95565c8253b0b87c82a53919ab3c795a4f50e/fonttools-4.59.2-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5729e12a982dba3eeae650de48b06f3b9ddb51e9aee2fcaf195b7d09a96250e2", size = 5026910, upload-time = "2025-08-27T16:38:51.904Z" }, - { url = "https://files.pythonhosted.org/packages/69/95/864726eaa8f9d4e053d0c462e64d5830ec7c599cbdf1db9e40f25ca3972e/fonttools-4.59.2-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c52694eae5d652361d59ecdb5a2246bff7cff13b6367a12da8499e9df56d148d", size = 4971031, upload-time = "2025-08-27T16:38:53.676Z" }, - { url = "https://files.pythonhosted.org/packages/24/4c/b8c4735ebdea20696277c70c79e0de615dbe477834e5a7c2569aa1db4033/fonttools-4.59.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:f1f1bbc23ba1312bd8959896f46f667753b90216852d2a8cfa2d07e0cb234144", size = 5006112, upload-time = "2025-08-27T16:38:55.69Z" }, - { url = "https://files.pythonhosted.org/packages/3b/23/f9ea29c292aa2fc1ea381b2e5621ac436d5e3e0a5dee24ffe5404e58eae8/fonttools-4.59.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1a1bfe5378962825dabe741720885e8b9ae9745ec7ecc4a5ec1f1ce59a6062bf", size = 5117671, upload-time = "2025-08-27T16:38:58.984Z" }, - { url = "https://files.pythonhosted.org/packages/ba/07/cfea304c555bf06e86071ff2a3916bc90f7c07ec85b23bab758d4908c33d/fonttools-4.59.2-cp311-cp311-win32.whl", hash = "sha256:e937790f3c2c18a1cbc7da101550a84319eb48023a715914477d2e7faeaba570", size = 2218157, upload-time = "2025-08-27T16:39:00.75Z" }, - { url = "https://files.pythonhosted.org/packages/d7/de/35d839aa69db737a3f9f3a45000ca24721834d40118652a5775d5eca8ebb/fonttools-4.59.2-cp311-cp311-win_amd64.whl", hash = "sha256:9836394e2f4ce5f9c0a7690ee93bd90aa1adc6b054f1a57b562c5d242c903104", size = 2265846, upload-time = "2025-08-27T16:39:02.453Z" }, - { url = "https://files.pythonhosted.org/packages/ba/3d/1f45db2df51e7bfa55492e8f23f383d372200be3a0ded4bf56a92753dd1f/fonttools-4.59.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:82906d002c349cad647a7634b004825a7335f8159d0d035ae89253b4abf6f3ea", size = 2769711, upload-time = "2025-08-27T16:39:04.423Z" }, - { url = "https://files.pythonhosted.org/packages/29/df/cd236ab32a8abfd11558f296e064424258db5edefd1279ffdbcfd4fd8b76/fonttools-4.59.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:a10c1bd7644dc58f8862d8ba0cf9fb7fef0af01ea184ba6ce3f50ab7dfe74d5a", size = 2340225, upload-time = "2025-08-27T16:39:06.143Z" }, - { url = "https://files.pythonhosted.org/packages/98/12/b6f9f964fe6d4b4dd4406bcbd3328821c3de1f909ffc3ffa558fe72af48c/fonttools-4.59.2-cp312-cp312-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:738f31f23e0339785fd67652a94bc69ea49e413dfdb14dcb8c8ff383d249464e", size = 4912766, upload-time = "2025-08-27T16:39:08.138Z" }, - { url = "https://files.pythonhosted.org/packages/73/78/82bde2f2d2c306ef3909b927363170b83df96171f74e0ccb47ad344563cd/fonttools-4.59.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0ec99f9bdfee9cdb4a9172f9e8fd578cce5feb231f598909e0aecf5418da4f25", size = 4955178, upload-time = "2025-08-27T16:39:10.094Z" }, - { url = "https://files.pythonhosted.org/packages/92/77/7de766afe2d31dda8ee46d7e479f35c7d48747e558961489a2d6e3a02bd4/fonttools-4.59.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:0476ea74161322e08c7a982f83558a2b81b491509984523a1a540baf8611cc31", size = 4897898, upload-time = "2025-08-27T16:39:12.087Z" }, - { url = "https://files.pythonhosted.org/packages/c5/77/ce0e0b905d62a06415fda9f2b2e109a24a5db54a59502b769e9e297d2242/fonttools-4.59.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:95922a922daa1f77cc72611747c156cfb38030ead72436a2c551d30ecef519b9", size = 5049144, upload-time = "2025-08-27T16:39:13.84Z" }, - { url = "https://files.pythonhosted.org/packages/d9/ea/870d93aefd23fff2e07cbeebdc332527868422a433c64062c09d4d5e7fe6/fonttools-4.59.2-cp312-cp312-win32.whl", hash = "sha256:39ad9612c6a622726a6a130e8ab15794558591f999673f1ee7d2f3d30f6a3e1c", size = 2206473, upload-time = "2025-08-27T16:39:15.854Z" }, - { url = "https://files.pythonhosted.org/packages/61/c4/e44bad000c4a4bb2e9ca11491d266e857df98ab6d7428441b173f0fe2517/fonttools-4.59.2-cp312-cp312-win_amd64.whl", hash = "sha256:980fd7388e461b19a881d35013fec32c713ffea1fc37aef2f77d11f332dfd7da", size = 2254706, upload-time = "2025-08-27T16:39:17.893Z" }, - { url = "https://files.pythonhosted.org/packages/13/7b/d0d3b9431642947b5805201fbbbe938a47b70c76685ef1f0cb5f5d7140d6/fonttools-4.59.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:381bde13216ba09489864467f6bc0c57997bd729abfbb1ce6f807ba42c06cceb", size = 2761563, upload-time = "2025-08-27T16:39:20.286Z" }, - { url = "https://files.pythonhosted.org/packages/76/be/fc5fe58dd76af7127b769b68071dbc32d4b95adc8b58d1d28d42d93c90f2/fonttools-4.59.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f33839aa091f7eef4e9078f5b7ab1b8ea4b1d8a50aeaef9fdb3611bba80869ec", size = 2335671, upload-time = "2025-08-27T16:39:22.027Z" }, - { url = "https://files.pythonhosted.org/packages/f2/9f/bf231c2a3fac99d1d7f1d89c76594f158693f981a4aa02be406e9f036832/fonttools-4.59.2-cp313-cp313-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:6235fc06bcbdb40186f483ba9d5d68f888ea68aa3c8dac347e05a7c54346fbc8", size = 4893967, upload-time = "2025-08-27T16:39:23.664Z" }, - { url = "https://files.pythonhosted.org/packages/26/a9/d46d2ad4fcb915198504d6727f83aa07f46764c64f425a861aa38756c9fd/fonttools-4.59.2-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:83ad6e5d06ef3a2884c4fa6384a20d6367b5cfe560e3b53b07c9dc65a7020e73", size = 4951986, upload-time = "2025-08-27T16:39:25.379Z" }, - { url = "https://files.pythonhosted.org/packages/07/90/1cc8d7dd8f707dfeeca472b82b898d3add0ebe85b1f645690dcd128ee63f/fonttools-4.59.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d029804c70fddf90be46ed5305c136cae15800a2300cb0f6bba96d48e770dde0", size = 4891630, upload-time = "2025-08-27T16:39:27.494Z" }, - { url = "https://files.pythonhosted.org/packages/d8/04/f0345b0d9fe67d65aa8d3f2d4cbf91d06f111bc7b8d802e65914eb06194d/fonttools-4.59.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:95807a3b5e78f2714acaa26a33bc2143005cc05c0217b322361a772e59f32b89", size = 5035116, upload-time = "2025-08-27T16:39:29.406Z" }, - { url = "https://files.pythonhosted.org/packages/d7/7d/5ba5eefffd243182fbd067cdbfeb12addd4e5aec45011b724c98a344ea33/fonttools-4.59.2-cp313-cp313-win32.whl", hash = "sha256:b3ebda00c3bb8f32a740b72ec38537d54c7c09f383a4cfefb0b315860f825b08", size = 2204907, upload-time = "2025-08-27T16:39:31.42Z" }, - { url = "https://files.pythonhosted.org/packages/ea/a9/be7219fc64a6026cc0aded17fa3720f9277001c185434230bd351bf678e6/fonttools-4.59.2-cp313-cp313-win_amd64.whl", hash = "sha256:a72155928d7053bbde499d32a9c77d3f0f3d29ae72b5a121752481bcbd71e50f", size = 2253742, upload-time = "2025-08-27T16:39:33.079Z" }, - { url = "https://files.pythonhosted.org/packages/fc/c7/486580d00be6fa5d45e41682e5ffa5c809f3d25773c6f39628d60f333521/fonttools-4.59.2-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:d09e487d6bfbe21195801323ba95c91cb3523f0fcc34016454d4d9ae9eaa57fe", size = 2762444, upload-time = "2025-08-27T16:39:34.759Z" }, - { url = "https://files.pythonhosted.org/packages/d3/9b/950ea9b7b764ceb8d18645c62191e14ce62124d8e05cb32a4dc5e65fde0b/fonttools-4.59.2-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:dec2f22486d7781087b173799567cffdcc75e9fb2f1c045f05f8317ccce76a3e", size = 2333256, upload-time = "2025-08-27T16:39:40.777Z" }, - { url = "https://files.pythonhosted.org/packages/9b/4d/8ee9d563126de9002eede950cde0051be86cc4e8c07c63eca0c9fc95734a/fonttools-4.59.2-cp314-cp314-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:1647201af10993090120da2e66e9526c4e20e88859f3e34aa05b8c24ded2a564", size = 4834846, upload-time = "2025-08-27T16:39:42.885Z" }, - { url = "https://files.pythonhosted.org/packages/03/26/f26d947b0712dce3d118e92ce30ca88f98938b066498f60d0ee000a892ae/fonttools-4.59.2-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:47742c33fe65f41eabed36eec2d7313a8082704b7b808752406452f766c573fc", size = 4930871, upload-time = "2025-08-27T16:39:44.818Z" }, - { url = "https://files.pythonhosted.org/packages/fc/7f/ebe878061a5a5e6b6502f0548489e01100f7e6c0049846e6546ba19a3ab4/fonttools-4.59.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:92ac2d45794f95d1ad4cb43fa07e7e3776d86c83dc4b9918cf82831518165b4b", size = 4876971, upload-time = "2025-08-27T16:39:47.027Z" }, - { url = "https://files.pythonhosted.org/packages/eb/0d/0d22e3a20ac566836098d30718092351935487e3271fd57385db1adb2fde/fonttools-4.59.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:fa9ecaf2dcef8941fb5719e16322345d730f4c40599bbf47c9753de40eb03882", size = 4987478, upload-time = "2025-08-27T16:39:48.774Z" }, - { url = "https://files.pythonhosted.org/packages/3b/a3/960cc83182a408ffacc795e61b5f698c6f7b0cfccf23da4451c39973f3c8/fonttools-4.59.2-cp314-cp314-win32.whl", hash = "sha256:a8d40594982ed858780e18a7e4c80415af65af0f22efa7de26bdd30bf24e1e14", size = 2208640, upload-time = "2025-08-27T16:39:50.592Z" }, - { url = "https://files.pythonhosted.org/packages/d8/74/55e5c57c414fa3965fee5fc036ed23f26a5c4e9e10f7f078a54ff9c7dfb7/fonttools-4.59.2-cp314-cp314-win_amd64.whl", hash = "sha256:9cde8b6a6b05f68516573523f2013a3574cb2c75299d7d500f44de82ba947b80", size = 2258457, upload-time = "2025-08-27T16:39:52.611Z" }, - { url = "https://files.pythonhosted.org/packages/e1/dc/8e4261dc591c5cfee68fecff3ffee2a9b29e1edc4c4d9cbafdc5aefe74ee/fonttools-4.59.2-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:036cd87a2dbd7ef72f7b68df8314ced00b8d9973aee296f2464d06a836aeb9a9", size = 2829901, upload-time = "2025-08-27T16:39:55.014Z" }, - { url = "https://files.pythonhosted.org/packages/fb/05/331538dcf21fd6331579cd628268150e85210d0d2bdae20f7598c2b36c05/fonttools-4.59.2-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:14870930181493b1d740b6f25483e20185e5aea58aec7d266d16da7be822b4bb", size = 2362717, upload-time = "2025-08-27T16:39:56.843Z" }, - { url = "https://files.pythonhosted.org/packages/60/ae/d26428ca9ede809c0a93f0af91f44c87433dc0251e2aec333da5ed00d38f/fonttools-4.59.2-cp314-cp314t-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:7ff58ea1eb8fc7e05e9a949419f031890023f8785c925b44d6da17a6a7d6e85d", size = 4835120, upload-time = "2025-08-27T16:39:59.06Z" }, - { url = "https://files.pythonhosted.org/packages/07/c4/0f6ac15895de509e07688cb1d45f1ae583adbaa0fa5a5699d73f3bd58ca0/fonttools-4.59.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6dee142b8b3096514c96ad9e2106bf039e2fe34a704c587585b569a36df08c3c", size = 5071115, upload-time = "2025-08-27T16:40:01.009Z" }, - { url = "https://files.pythonhosted.org/packages/b2/b6/147a711b7ecf7ea39f9da9422a55866f6dd5747c2f36b3b0a7a7e0c6820b/fonttools-4.59.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:8991bdbae39cf78bcc9cd3d81f6528df1f83f2e7c23ccf6f990fa1f0b6e19708", size = 4943905, upload-time = "2025-08-27T16:40:03.179Z" }, - { url = "https://files.pythonhosted.org/packages/5b/4e/2ab19006646b753855e2b02200fa1cabb75faa4eeca4ef289f269a936974/fonttools-4.59.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:53c1a411b7690042535a4f0edf2120096a39a506adeb6c51484a232e59f2aa0c", size = 4960313, upload-time = "2025-08-27T16:40:05.45Z" }, - { url = "https://files.pythonhosted.org/packages/98/3d/df77907e5be88adcca93cc2cee00646d039da220164be12bee028401e1cf/fonttools-4.59.2-cp314-cp314t-win32.whl", hash = "sha256:59d85088e29fa7a8f87d19e97a1beae2a35821ee48d8ef6d2c4f965f26cb9f8a", size = 2269719, upload-time = "2025-08-27T16:40:07.553Z" }, - { url = "https://files.pythonhosted.org/packages/2d/a0/d4c4bc5b50275449a9a908283b567caa032a94505fe1976e17f994faa6be/fonttools-4.59.2-cp314-cp314t-win_amd64.whl", hash = "sha256:7ad5d8d8cc9e43cb438b3eb4a0094dd6d4088daa767b0a24d52529361fd4c199", size = 2333169, upload-time = "2025-08-27T16:40:09.656Z" }, - { url = "https://files.pythonhosted.org/packages/65/a4/d2f7be3c86708912c02571db0b550121caab8cd88a3c0aacb9cfa15ea66e/fonttools-4.59.2-py3-none-any.whl", hash = "sha256:8bd0f759020e87bb5d323e6283914d9bf4ae35a7307dafb2cbd1e379e720ad37", size = 1132315, upload-time = "2025-08-27T16:40:28.984Z" }, +version = "4.60.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/27/d9/4eabd956fe123651a1f0efe29d9758b3837b5ae9a98934bdb571117033bb/fonttools-4.60.0.tar.gz", hash = "sha256:8f5927f049091a0ca74d35cce7f78e8f7775c83a6901a8fbe899babcc297146a", size = 3553671, upload-time = "2025-09-17T11:34:01.504Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/da/3d/c57731fbbf204ef1045caca28d5176430161ead73cd9feac3e9d9ef77ee6/fonttools-4.60.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:a9106c202d68ff5f9b4a0094c4d7ad2eaa7e9280f06427b09643215e706eb016", size = 2830883, upload-time = "2025-09-17T11:32:10.552Z" }, + { url = "https://files.pythonhosted.org/packages/cc/2d/b7a6ebaed464ce441c755252cc222af11edc651d17c8f26482f429cc2c0e/fonttools-4.60.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:9da3a4a3f2485b156bb429b4f8faa972480fc01f553f7c8c80d05d48f17eec89", size = 2356005, upload-time = "2025-09-17T11:32:13.248Z" }, + { url = "https://files.pythonhosted.org/packages/ee/c2/ea834e921324e2051403e125c1fe0bfbdde4951a7c1784e4ae6bdbd286cc/fonttools-4.60.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1f84de764c6057b2ffd4feb50ddef481d92e348f0c70f2c849b723118d352bf3", size = 5041201, upload-time = "2025-09-17T11:32:15.373Z" }, + { url = "https://files.pythonhosted.org/packages/93/3c/1c64a338e9aa410d2d0728827d5bb1301463078cb225b94589f27558b427/fonttools-4.60.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:800b3fa0d5c12ddff02179d45b035a23989a6c597a71c8035c010fff3b2ef1bb", size = 4977696, upload-time = "2025-09-17T11:32:17.674Z" }, + { url = "https://files.pythonhosted.org/packages/07/cc/c8c411a0d9732bb886b870e052f20658fec9cf91118314f253950d2c1d65/fonttools-4.60.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8dd68f60b030277f292a582d31c374edfadc60bb33d51ec7b6cd4304531819ba", size = 5020386, upload-time = "2025-09-17T11:32:20.089Z" }, + { url = "https://files.pythonhosted.org/packages/13/01/1d3bc07cf92e7f4fc27f06d4494bf6078dc595b2e01b959157a4fd23df12/fonttools-4.60.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:53328e3ca9e5c8660ef6de07c35f8f312c189b757535e12141be7a8ec942de6e", size = 5131575, upload-time = "2025-09-17T11:32:22.582Z" }, + { url = "https://files.pythonhosted.org/packages/5a/16/08db3917ee19e89d2eb0ee637d37cd4136c849dc421ff63f406b9165c1a1/fonttools-4.60.0-cp311-cp311-win32.whl", hash = "sha256:d493c175ddd0b88a5376e61163e3e6fde3be8b8987db9b092e0a84650709c9e7", size = 2229297, upload-time = "2025-09-17T11:32:24.834Z" }, + { url = "https://files.pythonhosted.org/packages/d2/0b/76764da82c0dfcea144861f568d9e83f4b921e84f2be617b451257bb25a7/fonttools-4.60.0-cp311-cp311-win_amd64.whl", hash = "sha256:cc2770c9dc49c2d0366e9683f4d03beb46c98042d7ccc8ddbadf3459ecb051a7", size = 2277193, upload-time = "2025-09-17T11:32:27.094Z" }, + { url = "https://files.pythonhosted.org/packages/2a/9b/706ebf84b55ab03439c1f3a94d6915123c0d96099f4238b254fdacffe03a/fonttools-4.60.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:8c68928a438d60dfde90e2f09aa7f848ed201176ca6652341744ceec4215859f", size = 2831953, upload-time = "2025-09-17T11:32:29.39Z" }, + { url = "https://files.pythonhosted.org/packages/76/40/782f485be450846e4f3aecff1f10e42af414fc6e19d235c70020f64278e1/fonttools-4.60.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b7133821249097cffabf0624eafd37f5a3358d5ce814febe9db688e3673e724e", size = 2351716, upload-time = "2025-09-17T11:32:31.46Z" }, + { url = "https://files.pythonhosted.org/packages/39/77/ad8d2a6ecc19716eb488c8cf118de10f7802e14bdf61d136d7b52358d6b1/fonttools-4.60.0-cp312-cp312-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:d3638905d3d77ac8791127ce181f7cb434f37e4204d8b2e31b8f1e154320b41f", size = 4922729, upload-time = "2025-09-17T11:32:33.659Z" }, + { url = "https://files.pythonhosted.org/packages/6b/48/aa543037c6e7788e1bc36b3f858ac70a59d32d0f45915263d0b330a35140/fonttools-4.60.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7968a26ef010ae89aabbb2f8e9dec1e2709a2541bb8620790451ee8aeb4f6fbf", size = 4967188, upload-time = "2025-09-17T11:32:35.74Z" }, + { url = "https://files.pythonhosted.org/packages/ac/58/e407d2028adc6387947eff8f2940b31f4ed40b9a83c2c7bbc8b9255126e2/fonttools-4.60.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1ef01ca7847c356b0fe026b7b92304bc31dc60a4218689ee0acc66652c1a36b2", size = 4910043, upload-time = "2025-09-17T11:32:38.054Z" }, + { url = "https://files.pythonhosted.org/packages/16/ef/e78519b3c296ef757a21b792fc6a785aa2ef9a2efb098083d8ed5f6ee2ba/fonttools-4.60.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:f3482d7ed7867edfcf785f77c1dffc876c4b2ddac19539c075712ff2a0703cf5", size = 5061980, upload-time = "2025-09-17T11:32:40.457Z" }, + { url = "https://files.pythonhosted.org/packages/00/4c/ad72444d1e3ef704ee90af8d5abf198016a39908d322bf41235562fb01a0/fonttools-4.60.0-cp312-cp312-win32.whl", hash = "sha256:8c937c4fe8addff575a984c9519433391180bf52cf35895524a07b520f376067", size = 2217750, upload-time = "2025-09-17T11:32:42.586Z" }, + { url = "https://files.pythonhosted.org/packages/46/55/3e8ac21963e130242f5a9ea2ebc57f5726d704bf4dcca89088b5b637b2d3/fonttools-4.60.0-cp312-cp312-win_amd64.whl", hash = "sha256:99b06d5d6f29f32e312adaed0367112f5ff2d300ea24363d377ec917daf9e8c5", size = 2266025, upload-time = "2025-09-17T11:32:44.8Z" }, + { url = "https://files.pythonhosted.org/packages/b4/6b/d090cd54abe88192fe3010f573508b2592cf1d1f98b14bcb799a8ad20525/fonttools-4.60.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:97100ba820936cdb5148b634e0884f0088699c7e2f1302ae7bba3747c7a19fb3", size = 2824791, upload-time = "2025-09-17T11:32:47.002Z" }, + { url = "https://files.pythonhosted.org/packages/97/8c/7ccb5a27aac9a535623fe04935fb9f469a4f8a1253991af9fbac2fe88c17/fonttools-4.60.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:03fccf84f377f83e99a5328a9ebe6b41e16fcf64a1450c352b6aa7e0deedbc01", size = 2347081, upload-time = "2025-09-17T11:32:49.204Z" }, + { url = "https://files.pythonhosted.org/packages/f8/1a/c14f0bb20b4cb7849dc0519f0ab0da74318d52236dc23168530569958599/fonttools-4.60.0-cp313-cp313-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:a3ef06671f862cd7da78ab105fbf8dce9da3634a8f91b3a64ed5c29c0ac6a9a8", size = 4902095, upload-time = "2025-09-17T11:32:51.848Z" }, + { url = "https://files.pythonhosted.org/packages/c9/a0/c7c91f07c40de5399cbaec7d25e04c9afac6c8f80036a98c125efdb5fe1a/fonttools-4.60.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3f2195faf96594c238462c420c7eff97d1aa51de595434f806ec3952df428616", size = 4959137, upload-time = "2025-09-17T11:32:54.185Z" }, + { url = "https://files.pythonhosted.org/packages/38/d2/169e49498df9f2c721763aa39b0bf3d08cb762864ebc8a8ddb99f5ba7ec8/fonttools-4.60.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:3887008865fa4f56cff58a1878f1300ba81a4e34f76daf9b47234698493072ee", size = 4900467, upload-time = "2025-09-17T11:32:56.664Z" }, + { url = "https://files.pythonhosted.org/packages/cc/9c/bfb56b89c3eab8bcb739c7fd1e8a43285c8dd833e1e1d18d4f54f2f641af/fonttools-4.60.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5567bd130378f21231d3856d8f0571dcdfcd77e47832978c26dabe572d456daa", size = 5043508, upload-time = "2025-09-17T11:32:58.944Z" }, + { url = "https://files.pythonhosted.org/packages/77/30/2b511c7eb99faee1fd9a0b42e984fb91275da3d681da650af4edf409d0fd/fonttools-4.60.0-cp313-cp313-win32.whl", hash = "sha256:699d0b521ec0b188ac11f2c14ccf6a926367795818ddf2bd00a273e9a052dd20", size = 2216037, upload-time = "2025-09-17T11:33:01.192Z" }, + { url = "https://files.pythonhosted.org/packages/3d/73/a2cc5ee4faeb0302cc81942c27f3b516801bf489fdc422a1b20090fff695/fonttools-4.60.0-cp313-cp313-win_amd64.whl", hash = "sha256:24296163268e7c800009711ce5c0e9997be8882c0bd546696c82ef45966163a6", size = 2265190, upload-time = "2025-09-17T11:33:03.935Z" }, + { url = "https://files.pythonhosted.org/packages/86/dd/a126706e45e0ce097cef6de4108b5597795acaa945fdbdd922dbc090d335/fonttools-4.60.0-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:b6fe3efdc956bdad95145cea906ad9ff345c17b706356dfc1098ce3230591343", size = 2821835, upload-time = "2025-09-17T11:33:06.094Z" }, + { url = "https://files.pythonhosted.org/packages/ac/90/5c17f311bbd983fd614b82a7a06da967b5d3c87e3e61cf34de6029a92ff4/fonttools-4.60.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:764b2aaab839762a3aa3207e5b3f0e0dfa41799e0b091edec5fcbccc584fdab5", size = 2344536, upload-time = "2025-09-17T11:33:08.574Z" }, + { url = "https://files.pythonhosted.org/packages/60/67/48c1a6229b2a5668c4111fbd1694ca417adedc1254c5cd2f9a11834c429d/fonttools-4.60.0-cp314-cp314-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:b81c7c47d9e78106a4d70f1dbeb49150513171715e45e0d2661809f2b0e3f710", size = 4842494, upload-time = "2025-09-17T11:33:11.338Z" }, + { url = "https://files.pythonhosted.org/packages/13/3e/83b0b37d02b7e321cbe2b8fcec0aa18571f0a47d3dc222196404371d83b6/fonttools-4.60.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:799ff60ee66b300ebe1fe6632b1cc55a66400fe815cef7b034d076bce6b1d8fc", size = 4943203, upload-time = "2025-09-17T11:33:13.285Z" }, + { url = "https://files.pythonhosted.org/packages/c9/07/11163e49497c53392eaca210a474104e4987c17ca7731f8754ba0d416a67/fonttools-4.60.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:f9878abe155ddd1b433bab95d027a686898a6afba961f3c5ca14b27488f2d772", size = 4889233, upload-time = "2025-09-17T11:33:15.175Z" }, + { url = "https://files.pythonhosted.org/packages/60/90/e85005d955cb26e7de015d5678778b8cc3293c0f3d717865675bd641fbfc/fonttools-4.60.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:ded432b7133ea4602fdb4731a4a7443a8e9548edad28987b99590cf6da626254", size = 4998335, upload-time = "2025-09-17T11:33:17.217Z" }, + { url = "https://files.pythonhosted.org/packages/2a/82/0374ad53729de6e3788ecdb8a3731ce6592c5ffa9bff823cef2ffe0164af/fonttools-4.60.0-cp314-cp314-win32.whl", hash = "sha256:5d97cf3a9245316d5978628c05642b939809c4f55ca632ca40744cb9de6e8d4a", size = 2219840, upload-time = "2025-09-17T11:33:19.494Z" }, + { url = "https://files.pythonhosted.org/packages/11/c3/804cd47453dcafb7976f9825b43cc0e61a2fe30eddb971b681cd72c4ca65/fonttools-4.60.0-cp314-cp314-win_amd64.whl", hash = "sha256:61b9ef46dd5e9dcb6f437eb0cc5ed83d5049e1bf9348e31974ffee1235db0f8f", size = 2269891, upload-time = "2025-09-17T11:33:21.743Z" }, + { url = "https://files.pythonhosted.org/packages/75/bf/1bd760aca04098e7028b4e0e5f73b41ff74b322275698071454652476a44/fonttools-4.60.0-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:bba7e3470cf353e1484a36dfb4108f431c2859e3f6097fe10118eeae92166773", size = 2893361, upload-time = "2025-09-17T11:33:23.68Z" }, + { url = "https://files.pythonhosted.org/packages/25/35/7a2c09aa990ed77f34924def383f44fc576a5596cc3df8438071e1baa1ac/fonttools-4.60.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:c5ac6439a38c27b3287063176b3303b34982024b01e2e95bba8ac1e45f6d41c1", size = 2374086, upload-time = "2025-09-17T11:33:25.988Z" }, + { url = "https://files.pythonhosted.org/packages/77/a9/f85ed2493e82837ff73421f3f7a1c3ae8f0b14051307418c916d9563da1f/fonttools-4.60.0-cp314-cp314t-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:4acd21e9f125a1257da59edf7a6e9bd4abd76282770715c613f1fe482409e9f9", size = 4848766, upload-time = "2025-09-17T11:33:28.018Z" }, + { url = "https://files.pythonhosted.org/packages/d1/91/29830eda31ae9231a06d5246e5d0c686422d03456ed666e13576c24c3f97/fonttools-4.60.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b4a6fc53039ea047e35dc62b958af9cd397eedbc3fa42406d2910ae091b9ae37", size = 5084613, upload-time = "2025-09-17T11:33:30.562Z" }, + { url = "https://files.pythonhosted.org/packages/48/01/615905e7db2568fe1843145077e680443494b7caab2089527b7e112c7606/fonttools-4.60.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:ef34f44eadf133e94e82c775a33ee3091dd37ee0161c5f5ea224b46e3ce0fb8e", size = 4956620, upload-time = "2025-09-17T11:33:32.497Z" }, + { url = "https://files.pythonhosted.org/packages/97/8e/64e65255871ec2f13b6c00b5b12d08b928b504867cfb7e7ed73e5e941832/fonttools-4.60.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:d112cae3e7ad1bb5d7f7a60365fcf6c181374648e064a8c07617b240e7c828ee", size = 4973202, upload-time = "2025-09-17T11:33:34.561Z" }, + { url = "https://files.pythonhosted.org/packages/e0/6d/04d16243eb441e8de61074c7809e92d2e35df4cd11af5632e486bc630dab/fonttools-4.60.0-cp314-cp314t-win32.whl", hash = "sha256:0f7b2c251dc338973e892a1e153016114e7a75f6aac7a49b84d5d1a4c0608d08", size = 2281217, upload-time = "2025-09-17T11:33:36.965Z" }, + { url = "https://files.pythonhosted.org/packages/ab/5f/09bd2f9f28ef0d6f3620fa19699d11c4bc83ff8a2786d8ccdd97c209b19a/fonttools-4.60.0-cp314-cp314t-win_amd64.whl", hash = "sha256:c8a72771106bc7434098db35abecd84d608857f6e116d3ef00366b213c502ce9", size = 2344738, upload-time = "2025-09-17T11:33:39.372Z" }, + { url = "https://files.pythonhosted.org/packages/f9/a4/247d3e54eb5ed59e94e09866cfc4f9567e274fbf310ba390711851f63b3b/fonttools-4.60.0-py3-none-any.whl", hash = "sha256:496d26e4d14dcccdd6ada2e937e4d174d3138e3d73f5c9b6ec6eb2fd1dab4f66", size = 1142186, upload-time = "2025-09-17T11:33:59.287Z" }, ] [[package]] @@ -680,15 +684,15 @@ wheels = [ [[package]] name = "hypothesis" -version = "6.138.15" +version = "6.139.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "attrs" }, { name = "sortedcontainers" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/3b/68/adc338edec178cf6c08b4843ea2b2d639d47bed4b06ea9331433b71acc0a/hypothesis-6.138.15.tar.gz", hash = "sha256:6b0e1aa182eacde87110995a3543530d69ef411f642162a656efcd46c2823ad1", size = 466116, upload-time = "2025-09-08T05:34:15.956Z" } +sdist = { url = "https://files.pythonhosted.org/packages/56/8e/f408b1a6d9745bf02c3d56e0788c930add554eee6b88a39bba141e897ac4/hypothesis-6.139.2.tar.gz", hash = "sha256:2dc2ff36ea977a9cb7fb68f24a5dbf5d673b88a2e502212676eafe09b699f511", size = 466099, upload-time = "2025-09-18T03:29:15.855Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/39/49/911eb0cd17884a7a6f510e78acf0a70592e414d194695a0c7c1db91645b2/hypothesis-6.138.15-py3-none-any.whl", hash = "sha256:b7cf743d461c319eb251a13c8e1dcf00f4ef7085e4ab5bf5abf102b2a5ffd694", size = 533621, upload-time = "2025-09-08T05:34:12.272Z" }, + { url = "https://files.pythonhosted.org/packages/7c/81/4a85771072ae39064f114f23716e312771a42bfe3a089cba3da6697dd231/hypothesis-6.139.2-py3-none-any.whl", hash = "sha256:6f466780b7d1db074fb473af14e3111a5dd4fe36c47fcd776cd7c480ae0a02f2", size = 533752, upload-time = "2025-09-18T03:29:12.088Z" }, ] [[package]] @@ -1150,40 +1154,40 @@ wheels = [ [[package]] name = "mypy" -version = "1.17.1" +version = "1.18.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "mypy-extensions" }, { name = "pathspec" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/8e/22/ea637422dedf0bf36f3ef238eab4e455e2a0dcc3082b5cc067615347ab8e/mypy-1.17.1.tar.gz", hash = "sha256:25e01ec741ab5bb3eec8ba9cdb0f769230368a22c959c4937360efb89b7e9f01", size = 3352570, upload-time = "2025-07-31T07:54:19.204Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/46/cf/eadc80c4e0a70db1c08921dcc220357ba8ab2faecb4392e3cebeb10edbfa/mypy-1.17.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ad37544be07c5d7fba814eb370e006df58fed8ad1ef33ed1649cb1889ba6ff58", size = 10921009, upload-time = "2025-07-31T07:53:23.037Z" }, - { url = "https://files.pythonhosted.org/packages/5d/c1/c869d8c067829ad30d9bdae051046561552516cfb3a14f7f0347b7d973ee/mypy-1.17.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:064e2ff508e5464b4bd807a7c1625bc5047c5022b85c70f030680e18f37273a5", size = 10047482, upload-time = "2025-07-31T07:53:26.151Z" }, - { url = "https://files.pythonhosted.org/packages/98/b9/803672bab3fe03cee2e14786ca056efda4bb511ea02dadcedde6176d06d0/mypy-1.17.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:70401bbabd2fa1aa7c43bb358f54037baf0586f41e83b0ae67dd0534fc64edfd", size = 11832883, upload-time = "2025-07-31T07:53:47.948Z" }, - { url = "https://files.pythonhosted.org/packages/88/fb/fcdac695beca66800918c18697b48833a9a6701de288452b6715a98cfee1/mypy-1.17.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e92bdc656b7757c438660f775f872a669b8ff374edc4d18277d86b63edba6b8b", size = 12566215, upload-time = "2025-07-31T07:54:04.031Z" }, - { url = "https://files.pythonhosted.org/packages/7f/37/a932da3d3dace99ee8eb2043b6ab03b6768c36eb29a02f98f46c18c0da0e/mypy-1.17.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:c1fdf4abb29ed1cb091cf432979e162c208a5ac676ce35010373ff29247bcad5", size = 12751956, upload-time = "2025-07-31T07:53:36.263Z" }, - { url = "https://files.pythonhosted.org/packages/8c/cf/6438a429e0f2f5cab8bc83e53dbebfa666476f40ee322e13cac5e64b79e7/mypy-1.17.1-cp311-cp311-win_amd64.whl", hash = "sha256:ff2933428516ab63f961644bc49bc4cbe42bbffb2cd3b71cc7277c07d16b1a8b", size = 9507307, upload-time = "2025-07-31T07:53:59.734Z" }, - { url = "https://files.pythonhosted.org/packages/17/a2/7034d0d61af8098ec47902108553122baa0f438df8a713be860f7407c9e6/mypy-1.17.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:69e83ea6553a3ba79c08c6e15dbd9bfa912ec1e493bf75489ef93beb65209aeb", size = 11086295, upload-time = "2025-07-31T07:53:28.124Z" }, - { url = "https://files.pythonhosted.org/packages/14/1f/19e7e44b594d4b12f6ba8064dbe136505cec813549ca3e5191e40b1d3cc2/mypy-1.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1b16708a66d38abb1e6b5702f5c2c87e133289da36f6a1d15f6a5221085c6403", size = 10112355, upload-time = "2025-07-31T07:53:21.121Z" }, - { url = "https://files.pythonhosted.org/packages/5b/69/baa33927e29e6b4c55d798a9d44db5d394072eef2bdc18c3e2048c9ed1e9/mypy-1.17.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:89e972c0035e9e05823907ad5398c5a73b9f47a002b22359b177d40bdaee7056", size = 11875285, upload-time = "2025-07-31T07:53:55.293Z" }, - { url = "https://files.pythonhosted.org/packages/90/13/f3a89c76b0a41e19490b01e7069713a30949d9a6c147289ee1521bcea245/mypy-1.17.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:03b6d0ed2b188e35ee6d5c36b5580cffd6da23319991c49ab5556c023ccf1341", size = 12737895, upload-time = "2025-07-31T07:53:43.623Z" }, - { url = "https://files.pythonhosted.org/packages/23/a1/c4ee79ac484241301564072e6476c5a5be2590bc2e7bfd28220033d2ef8f/mypy-1.17.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c837b896b37cd103570d776bda106eabb8737aa6dd4f248451aecf53030cdbeb", size = 12931025, upload-time = "2025-07-31T07:54:17.125Z" }, - { url = "https://files.pythonhosted.org/packages/89/b8/7409477be7919a0608900e6320b155c72caab4fef46427c5cc75f85edadd/mypy-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:665afab0963a4b39dff7c1fa563cc8b11ecff7910206db4b2e64dd1ba25aed19", size = 9584664, upload-time = "2025-07-31T07:54:12.842Z" }, - { url = "https://files.pythonhosted.org/packages/5b/82/aec2fc9b9b149f372850291827537a508d6c4d3664b1750a324b91f71355/mypy-1.17.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:93378d3203a5c0800c6b6d850ad2f19f7a3cdf1a3701d3416dbf128805c6a6a7", size = 11075338, upload-time = "2025-07-31T07:53:38.873Z" }, - { url = "https://files.pythonhosted.org/packages/07/ac/ee93fbde9d2242657128af8c86f5d917cd2887584cf948a8e3663d0cd737/mypy-1.17.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:15d54056f7fe7a826d897789f53dd6377ec2ea8ba6f776dc83c2902b899fee81", size = 10113066, upload-time = "2025-07-31T07:54:14.707Z" }, - { url = "https://files.pythonhosted.org/packages/5a/68/946a1e0be93f17f7caa56c45844ec691ca153ee8b62f21eddda336a2d203/mypy-1.17.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:209a58fed9987eccc20f2ca94afe7257a8f46eb5df1fb69958650973230f91e6", size = 11875473, upload-time = "2025-07-31T07:53:14.504Z" }, - { url = "https://files.pythonhosted.org/packages/9f/0f/478b4dce1cb4f43cf0f0d00fba3030b21ca04a01b74d1cd272a528cf446f/mypy-1.17.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:099b9a5da47de9e2cb5165e581f158e854d9e19d2e96b6698c0d64de911dd849", size = 12744296, upload-time = "2025-07-31T07:53:03.896Z" }, - { url = "https://files.pythonhosted.org/packages/ca/70/afa5850176379d1b303f992a828de95fc14487429a7139a4e0bdd17a8279/mypy-1.17.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:fa6ffadfbe6994d724c5a1bb6123a7d27dd68fc9c059561cd33b664a79578e14", size = 12914657, upload-time = "2025-07-31T07:54:08.576Z" }, - { url = "https://files.pythonhosted.org/packages/53/f9/4a83e1c856a3d9c8f6edaa4749a4864ee98486e9b9dbfbc93842891029c2/mypy-1.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:9a2b7d9180aed171f033c9f2fc6c204c1245cf60b0cb61cf2e7acc24eea78e0a", size = 9593320, upload-time = "2025-07-31T07:53:01.341Z" }, - { url = "https://files.pythonhosted.org/packages/38/56/79c2fac86da57c7d8c48622a05873eaab40b905096c33597462713f5af90/mypy-1.17.1-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:15a83369400454c41ed3a118e0cc58bd8123921a602f385cb6d6ea5df050c733", size = 11040037, upload-time = "2025-07-31T07:54:10.942Z" }, - { url = "https://files.pythonhosted.org/packages/4d/c3/adabe6ff53638e3cad19e3547268482408323b1e68bf082c9119000cd049/mypy-1.17.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:55b918670f692fc9fba55c3298d8a3beae295c5cded0a55dccdc5bbead814acd", size = 10131550, upload-time = "2025-07-31T07:53:41.307Z" }, - { url = "https://files.pythonhosted.org/packages/b8/c5/2e234c22c3bdeb23a7817af57a58865a39753bde52c74e2c661ee0cfc640/mypy-1.17.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:62761474061feef6f720149d7ba876122007ddc64adff5ba6f374fda35a018a0", size = 11872963, upload-time = "2025-07-31T07:53:16.878Z" }, - { url = "https://files.pythonhosted.org/packages/ab/26/c13c130f35ca8caa5f2ceab68a247775648fdcd6c9a18f158825f2bc2410/mypy-1.17.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c49562d3d908fd49ed0938e5423daed8d407774a479b595b143a3d7f87cdae6a", size = 12710189, upload-time = "2025-07-31T07:54:01.962Z" }, - { url = "https://files.pythonhosted.org/packages/82/df/c7d79d09f6de8383fe800521d066d877e54d30b4fb94281c262be2df84ef/mypy-1.17.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:397fba5d7616a5bc60b45c7ed204717eaddc38f826e3645402c426057ead9a91", size = 12900322, upload-time = "2025-07-31T07:53:10.551Z" }, - { url = "https://files.pythonhosted.org/packages/b8/98/3d5a48978b4f708c55ae832619addc66d677f6dc59f3ebad71bae8285ca6/mypy-1.17.1-cp314-cp314-win_amd64.whl", hash = "sha256:9d6b20b97d373f41617bd0708fd46aa656059af57f2ef72aa8c7d6a2b73b74ed", size = 9751879, upload-time = "2025-07-31T07:52:56.683Z" }, - { url = "https://files.pythonhosted.org/packages/1d/f3/8fcd2af0f5b806f6cf463efaffd3c9548a28f84220493ecd38d127b6b66d/mypy-1.17.1-py3-none-any.whl", hash = "sha256:a9f52c0351c21fe24c21d8c0eb1f62967b262d6729393397b6f443c3b773c3b9", size = 2283411, upload-time = "2025-07-31T07:53:24.664Z" }, +sdist = { url = "https://files.pythonhosted.org/packages/14/a3/931e09fc02d7ba96da65266884da4e4a8806adcdb8a57faaacc6edf1d538/mypy-1.18.1.tar.gz", hash = "sha256:9e988c64ad3ac5987f43f5154f884747faf62141b7f842e87465b45299eea5a9", size = 3448447, upload-time = "2025-09-11T23:00:47.067Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/32/28/47709d5d9e7068b26c0d5189c8137c8783e81065ad1102b505214a08b548/mypy-1.18.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6c903857b3e28fc5489e54042684a9509039ea0aedb2a619469438b544ae1961", size = 12734635, upload-time = "2025-09-11T23:00:24.983Z" }, + { url = "https://files.pythonhosted.org/packages/7c/12/ee5c243e52497d0e59316854041cf3b3130131b92266d0764aca4dec3c00/mypy-1.18.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2a0c8392c19934c2b6c65566d3a6abdc6b51d5da7f5d04e43f0eb627d6eeee65", size = 11817287, upload-time = "2025-09-11T22:59:07.38Z" }, + { url = "https://files.pythonhosted.org/packages/48/bd/2aeb950151005fe708ab59725afed7c4aeeb96daf844f86a05d4b8ac34f8/mypy-1.18.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f85eb7efa2ec73ef63fc23b8af89c2fe5bf2a4ad985ed2d3ff28c1bb3c317c92", size = 12430464, upload-time = "2025-09-11T22:58:48.084Z" }, + { url = "https://files.pythonhosted.org/packages/71/e8/7a20407aafb488acb5734ad7fb5e8c2ef78d292ca2674335350fa8ebef67/mypy-1.18.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:82ace21edf7ba8af31c3308a61dc72df30500f4dbb26f99ac36b4b80809d7e94", size = 13164555, upload-time = "2025-09-11T23:00:13.803Z" }, + { url = "https://files.pythonhosted.org/packages/e8/c9/5f39065252e033b60f397096f538fb57c1d9fd70a7a490f314df20dd9d64/mypy-1.18.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a2dfd53dfe632f1ef5d161150a4b1f2d0786746ae02950eb3ac108964ee2975a", size = 13359222, upload-time = "2025-09-11T23:00:33.469Z" }, + { url = "https://files.pythonhosted.org/packages/85/b6/d54111ef3c1e55992cd2ec9b8b6ce9c72a407423e93132cae209f7e7ba60/mypy-1.18.1-cp311-cp311-win_amd64.whl", hash = "sha256:320f0ad4205eefcb0e1a72428dde0ad10be73da9f92e793c36228e8ebf7298c0", size = 9760441, upload-time = "2025-09-11T23:00:44.826Z" }, + { url = "https://files.pythonhosted.org/packages/e7/14/1c3f54d606cb88a55d1567153ef3a8bc7b74702f2ff5eb64d0994f9e49cb/mypy-1.18.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:502cde8896be8e638588b90fdcb4c5d5b8c1b004dfc63fd5604a973547367bb9", size = 12911082, upload-time = "2025-09-11T23:00:41.465Z" }, + { url = "https://files.pythonhosted.org/packages/90/83/235606c8b6d50a8eba99773add907ce1d41c068edb523f81eb0d01603a83/mypy-1.18.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7509549b5e41be279afc1228242d0e397f1af2919a8f2877ad542b199dc4083e", size = 11919107, upload-time = "2025-09-11T22:58:40.903Z" }, + { url = "https://files.pythonhosted.org/packages/ca/25/4e2ce00f8d15b99d0c68a2536ad63e9eac033f723439ef80290ec32c1ff5/mypy-1.18.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5956ecaabb3a245e3f34100172abca1507be687377fe20e24d6a7557e07080e2", size = 12472551, upload-time = "2025-09-11T22:58:37.272Z" }, + { url = "https://files.pythonhosted.org/packages/32/bb/92642a9350fc339dd9dcefcf6862d171b52294af107d521dce075f32f298/mypy-1.18.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8750ceb014a96c9890421c83f0db53b0f3b8633e2864c6f9bc0a8e93951ed18d", size = 13340554, upload-time = "2025-09-11T22:59:38.756Z" }, + { url = "https://files.pythonhosted.org/packages/cd/ee/38d01db91c198fb6350025d28f9719ecf3c8f2c55a0094bfbf3ef478cc9a/mypy-1.18.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fb89ea08ff41adf59476b235293679a6eb53a7b9400f6256272fb6029bec3ce5", size = 13530933, upload-time = "2025-09-11T22:59:20.228Z" }, + { url = "https://files.pythonhosted.org/packages/da/8d/6d991ae631f80d58edbf9d7066e3f2a96e479dca955d9a968cd6e90850a3/mypy-1.18.1-cp312-cp312-win_amd64.whl", hash = "sha256:2657654d82fcd2a87e02a33e0d23001789a554059bbf34702d623dafe353eabf", size = 9828426, upload-time = "2025-09-11T23:00:21.007Z" }, + { url = "https://files.pythonhosted.org/packages/e4/ec/ef4a7260e1460a3071628a9277a7579e7da1b071bc134ebe909323f2fbc7/mypy-1.18.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:d70d2b5baf9b9a20bc9c730015615ae3243ef47fb4a58ad7b31c3e0a59b5ef1f", size = 12918671, upload-time = "2025-09-11T22:58:29.814Z" }, + { url = "https://files.pythonhosted.org/packages/a1/82/0ea6c3953f16223f0b8eda40c1aeac6bd266d15f4902556ae6e91f6fca4c/mypy-1.18.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:b8367e33506300f07a43012fc546402f283c3f8bcff1dc338636affb710154ce", size = 11913023, upload-time = "2025-09-11T23:00:29.049Z" }, + { url = "https://files.pythonhosted.org/packages/ae/ef/5e2057e692c2690fc27b3ed0a4dbde4388330c32e2576a23f0302bc8358d/mypy-1.18.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:913f668ec50c3337b89df22f973c1c8f0b29ee9e290a8b7fe01cc1ef7446d42e", size = 12473355, upload-time = "2025-09-11T23:00:04.544Z" }, + { url = "https://files.pythonhosted.org/packages/98/43/b7e429fc4be10e390a167b0cd1810d41cb4e4add4ae50bab96faff695a3b/mypy-1.18.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1a0e70b87eb27b33209fa4792b051c6947976f6ab829daa83819df5f58330c71", size = 13346944, upload-time = "2025-09-11T22:58:23.024Z" }, + { url = "https://files.pythonhosted.org/packages/89/4e/899dba0bfe36bbd5b7c52e597de4cf47b5053d337b6d201a30e3798e77a6/mypy-1.18.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:c378d946e8a60be6b6ede48c878d145546fb42aad61df998c056ec151bf6c746", size = 13512574, upload-time = "2025-09-11T22:59:52.152Z" }, + { url = "https://files.pythonhosted.org/packages/f5/f8/7661021a5b0e501b76440454d786b0f01bb05d5c4b125fcbda02023d0250/mypy-1.18.1-cp313-cp313-win_amd64.whl", hash = "sha256:2cd2c1e0f3a7465f22731987fff6fc427e3dcbb4ca5f7db5bbeaff2ff9a31f6d", size = 9837684, upload-time = "2025-09-11T22:58:44.454Z" }, + { url = "https://files.pythonhosted.org/packages/bf/87/7b173981466219eccc64c107cf8e5ab9eb39cc304b4c07df8e7881533e4f/mypy-1.18.1-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:ba24603c58e34dd5b096dfad792d87b304fc6470cbb1c22fd64e7ebd17edcc61", size = 12900265, upload-time = "2025-09-11T22:59:03.4Z" }, + { url = "https://files.pythonhosted.org/packages/ae/cc/b10e65bae75b18a5ac8f81b1e8e5867677e418f0dd2c83b8e2de9ba96ebd/mypy-1.18.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:ed36662fb92ae4cb3cacc682ec6656208f323bbc23d4b08d091eecfc0863d4b5", size = 11942890, upload-time = "2025-09-11T23:00:00.607Z" }, + { url = "https://files.pythonhosted.org/packages/39/d4/aeefa07c44d09f4c2102e525e2031bc066d12e5351f66b8a83719671004d/mypy-1.18.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:040ecc95e026f71a9ad7956fea2724466602b561e6a25c2e5584160d3833aaa8", size = 12472291, upload-time = "2025-09-11T22:59:43.425Z" }, + { url = "https://files.pythonhosted.org/packages/c6/07/711e78668ff8e365f8c19735594ea95938bff3639a4c46a905e3ed8ff2d6/mypy-1.18.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:937e3ed86cb731276706e46e03512547e43c391a13f363e08d0fee49a7c38a0d", size = 13318610, upload-time = "2025-09-11T23:00:17.604Z" }, + { url = "https://files.pythonhosted.org/packages/ca/85/df3b2d39339c31d360ce299b418c55e8194ef3205284739b64962f6074e7/mypy-1.18.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:1f95cc4f01c0f1701ca3b0355792bccec13ecb2ec1c469e5b85a6ef398398b1d", size = 13513697, upload-time = "2025-09-11T22:58:59.534Z" }, + { url = "https://files.pythonhosted.org/packages/b1/df/462866163c99ea73bb28f0eb4d415c087e30de5d36ee0f5429d42e28689b/mypy-1.18.1-cp314-cp314-win_amd64.whl", hash = "sha256:e4f16c0019d48941220ac60b893615be2f63afedaba6a0801bdcd041b96991ce", size = 9985739, upload-time = "2025-09-11T22:58:51.644Z" }, + { url = "https://files.pythonhosted.org/packages/e0/1d/4b97d3089b48ef3d904c9ca69fab044475bd03245d878f5f0b3ea1daf7ce/mypy-1.18.1-py3-none-any.whl", hash = "sha256:b76a4de66a0ac01da1be14ecc8ae88ddea33b8380284a9e3eae39d57ebcbe26e", size = 2352212, upload-time = "2025-09-11T22:59:26.576Z" }, ] [[package]] @@ -1728,17 +1732,18 @@ wheels = [ [[package]] name = "psutil" -version = "7.0.0" +version = "7.1.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/2a/80/336820c1ad9286a4ded7e845b2eccfcb27851ab8ac6abece774a6ff4d3de/psutil-7.0.0.tar.gz", hash = "sha256:7be9c3eba38beccb6495ea33afd982a44074b78f28c434a1f51cc07fd315c456", size = 497003, upload-time = "2025-02-13T21:54:07.946Z" } +sdist = { url = "https://files.pythonhosted.org/packages/b3/31/4723d756b59344b643542936e37a31d1d3204bcdc42a7daa8ee9eb06fb50/psutil-7.1.0.tar.gz", hash = "sha256:655708b3c069387c8b77b072fc429a57d0e214221d01c0a772df7dfedcb3bcd2", size = 497660, upload-time = "2025-09-17T20:14:52.902Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ed/e6/2d26234410f8b8abdbf891c9da62bee396583f713fb9f3325a4760875d22/psutil-7.0.0-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:101d71dc322e3cffd7cea0650b09b3d08b8e7c4109dd6809fe452dfd00e58b25", size = 238051, upload-time = "2025-02-13T21:54:12.36Z" }, - { url = "https://files.pythonhosted.org/packages/04/8b/30f930733afe425e3cbfc0e1468a30a18942350c1a8816acfade80c005c4/psutil-7.0.0-cp36-abi3-macosx_11_0_arm64.whl", hash = "sha256:39db632f6bb862eeccf56660871433e111b6ea58f2caea825571951d4b6aa3da", size = 239535, upload-time = "2025-02-13T21:54:16.07Z" }, - { url = "https://files.pythonhosted.org/packages/2a/ed/d362e84620dd22876b55389248e522338ed1bf134a5edd3b8231d7207f6d/psutil-7.0.0-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1fcee592b4c6f146991ca55919ea3d1f8926497a713ed7faaf8225e174581e91", size = 275004, upload-time = "2025-02-13T21:54:18.662Z" }, - { url = "https://files.pythonhosted.org/packages/bf/b9/b0eb3f3cbcb734d930fdf839431606844a825b23eaf9a6ab371edac8162c/psutil-7.0.0-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4b1388a4f6875d7e2aff5c4ca1cc16c545ed41dd8bb596cefea80111db353a34", size = 277986, upload-time = "2025-02-13T21:54:21.811Z" }, - { url = "https://files.pythonhosted.org/packages/eb/a2/709e0fe2f093556c17fbafda93ac032257242cabcc7ff3369e2cb76a97aa/psutil-7.0.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5f098451abc2828f7dc6b58d44b532b22f2088f4999a937557b603ce72b1993", size = 279544, upload-time = "2025-02-13T21:54:24.68Z" }, - { url = "https://files.pythonhosted.org/packages/50/e6/eecf58810b9d12e6427369784efe814a1eec0f492084ce8eb8f4d89d6d61/psutil-7.0.0-cp37-abi3-win32.whl", hash = "sha256:ba3fcef7523064a6c9da440fc4d6bd07da93ac726b5733c29027d7dc95b39d99", size = 241053, upload-time = "2025-02-13T21:54:34.31Z" }, - { url = "https://files.pythonhosted.org/packages/50/1b/6921afe68c74868b4c9fa424dad3be35b095e16687989ebbb50ce4fceb7c/psutil-7.0.0-cp37-abi3-win_amd64.whl", hash = "sha256:4cf3d4eb1aa9b348dec30105c55cd9b7d4629285735a102beb4441e38db90553", size = 244885, upload-time = "2025-02-13T21:54:37.486Z" }, + { url = "https://files.pythonhosted.org/packages/46/62/ce4051019ee20ce0ed74432dd73a5bb087a6704284a470bb8adff69a0932/psutil-7.1.0-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:76168cef4397494250e9f4e73eb3752b146de1dd950040b29186d0cce1d5ca13", size = 245242, upload-time = "2025-09-17T20:14:56.126Z" }, + { url = "https://files.pythonhosted.org/packages/38/61/f76959fba841bf5b61123fbf4b650886dc4094c6858008b5bf73d9057216/psutil-7.1.0-cp36-abi3-macosx_11_0_arm64.whl", hash = "sha256:5d007560c8c372efdff9e4579c2846d71de737e4605f611437255e81efcca2c5", size = 246682, upload-time = "2025-09-17T20:14:58.25Z" }, + { url = "https://files.pythonhosted.org/packages/88/7a/37c99d2e77ec30d63398ffa6a660450b8a62517cabe44b3e9bae97696e8d/psutil-7.1.0-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:22e4454970b32472ce7deaa45d045b34d3648ce478e26a04c7e858a0a6e75ff3", size = 287994, upload-time = "2025-09-17T20:14:59.901Z" }, + { url = "https://files.pythonhosted.org/packages/9d/de/04c8c61232f7244aa0a4b9a9fbd63a89d5aeaf94b2fc9d1d16e2faa5cbb0/psutil-7.1.0-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8c70e113920d51e89f212dd7be06219a9b88014e63a4cec69b684c327bc474e3", size = 291163, upload-time = "2025-09-17T20:15:01.481Z" }, + { url = "https://files.pythonhosted.org/packages/f4/58/c4f976234bf6d4737bc8c02a81192f045c307b72cf39c9e5c5a2d78927f6/psutil-7.1.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7d4a113425c037300de3ac8b331637293da9be9713855c4fc9d2d97436d7259d", size = 293625, upload-time = "2025-09-17T20:15:04.492Z" }, + { url = "https://files.pythonhosted.org/packages/79/87/157c8e7959ec39ced1b11cc93c730c4fb7f9d408569a6c59dbd92ceb35db/psutil-7.1.0-cp37-abi3-win32.whl", hash = "sha256:09ad740870c8d219ed8daae0ad3b726d3bf9a028a198e7f3080f6a1888b99bca", size = 244812, upload-time = "2025-09-17T20:15:07.462Z" }, + { url = "https://files.pythonhosted.org/packages/bf/e9/b44c4f697276a7a95b8e94d0e320a7bf7f3318521b23de69035540b39838/psutil-7.1.0-cp37-abi3-win_amd64.whl", hash = "sha256:57f5e987c36d3146c0dd2528cd42151cf96cd359b9d67cfff836995cc5df9a3d", size = 247965, upload-time = "2025-09-17T20:15:09.673Z" }, + { url = "https://files.pythonhosted.org/packages/26/65/1070a6e3c036f39142c2820c4b52e9243246fcfc3f96239ac84472ba361e/psutil-7.1.0-cp37-abi3-win_arm64.whl", hash = "sha256:6937cb68133e7c97b6cc9649a570c9a18ba0efebed46d8c5dae4c07fa1b67a07", size = 244971, upload-time = "2025-09-17T20:15:12.262Z" }, ] [[package]] @@ -1823,11 +1828,11 @@ wheels = [ [[package]] name = "pyparsing" -version = "3.2.3" +version = "3.2.4" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/bb/22/f1129e69d94ffff626bdb5c835506b3a5b4f3d070f17ea295e12c2c6f60f/pyparsing-3.2.3.tar.gz", hash = "sha256:b9c13f1ab8b3b542f72e28f634bad4de758ab3ce4546e4301970ad6fa77c38be", size = 1088608, upload-time = "2025-03-25T05:01:28.114Z" } +sdist = { url = "https://files.pythonhosted.org/packages/98/c9/b4594e6a81371dfa9eb7a2c110ad682acf985d96115ae8b25a1d63b4bf3b/pyparsing-3.2.4.tar.gz", hash = "sha256:fff89494f45559d0f2ce46613b419f632bbb6afbdaed49696d322bcf98a58e99", size = 1098809, upload-time = "2025-09-13T05:47:19.732Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/05/e7/df2285f3d08fee213f2d041540fa4fc9ca6c2d44cf36d3a035bf2a8d2bcc/pyparsing-3.2.3-py3-none-any.whl", hash = "sha256:a749938e02d6fd0b59b356ca504a24982314bb090c383e3cf201c95ef7e2bfcf", size = 111120, upload-time = "2025-03-25T05:01:24.908Z" }, + { url = "https://files.pythonhosted.org/packages/53/b8/fbab973592e23ae313042d450fc26fa24282ebffba21ba373786e1ce63b4/pyparsing-3.2.4-py3-none-any.whl", hash = "sha256:91d0fcde680d42cd031daf3a6ba20da3107e08a75de50da58360e7d94ab24d36", size = 113869, upload-time = "2025-09-13T05:47:17.863Z" }, ] [[package]] @@ -2206,67 +2211,73 @@ wheels = [ [[package]] name = "scipy" -version = "1.16.1" +version = "1.16.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "numpy" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/f5/4a/b927028464795439faec8eaf0b03b011005c487bb2d07409f28bf30879c4/scipy-1.16.1.tar.gz", hash = "sha256:44c76f9e8b6e8e488a586190ab38016e4ed2f8a038af7cd3defa903c0a2238b3", size = 30580861, upload-time = "2025-07-27T16:33:30.834Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/da/91/812adc6f74409b461e3a5fa97f4f74c769016919203138a3bf6fc24ba4c5/scipy-1.16.1-cp311-cp311-macosx_10_14_x86_64.whl", hash = "sha256:c033fa32bab91dc98ca59d0cf23bb876454e2bb02cbe592d5023138778f70030", size = 36552519, upload-time = "2025-07-27T16:26:29.658Z" }, - { url = "https://files.pythonhosted.org/packages/47/18/8e355edcf3b71418d9e9f9acd2708cc3a6c27e8f98fde0ac34b8a0b45407/scipy-1.16.1-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:6e5c2f74e5df33479b5cd4e97a9104c511518fbd979aa9b8f6aec18b2e9ecae7", size = 28638010, upload-time = "2025-07-27T16:26:38.196Z" }, - { url = "https://files.pythonhosted.org/packages/d9/eb/e931853058607bdfbc11b86df19ae7a08686121c203483f62f1ecae5989c/scipy-1.16.1-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:0a55ffe0ba0f59666e90951971a884d1ff6f4ec3275a48f472cfb64175570f77", size = 20909790, upload-time = "2025-07-27T16:26:43.93Z" }, - { url = "https://files.pythonhosted.org/packages/45/0c/be83a271d6e96750cd0be2e000f35ff18880a46f05ce8b5d3465dc0f7a2a/scipy-1.16.1-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:f8a5d6cd147acecc2603fbd382fed6c46f474cccfcf69ea32582e033fb54dcfe", size = 23513352, upload-time = "2025-07-27T16:26:50.017Z" }, - { url = "https://files.pythonhosted.org/packages/7c/bf/fe6eb47e74f762f933cca962db7f2c7183acfdc4483bd1c3813cfe83e538/scipy-1.16.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:cb18899127278058bcc09e7b9966d41a5a43740b5bb8dcba401bd983f82e885b", size = 33534643, upload-time = "2025-07-27T16:26:57.503Z" }, - { url = "https://files.pythonhosted.org/packages/bb/ba/63f402e74875486b87ec6506a4f93f6d8a0d94d10467280f3d9d7837ce3a/scipy-1.16.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:adccd93a2fa937a27aae826d33e3bfa5edf9aa672376a4852d23a7cd67a2e5b7", size = 35376776, upload-time = "2025-07-27T16:27:06.639Z" }, - { url = "https://files.pythonhosted.org/packages/c3/b4/04eb9d39ec26a1b939689102da23d505ea16cdae3dbb18ffc53d1f831044/scipy-1.16.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:18aca1646a29ee9a0625a1be5637fa798d4d81fdf426481f06d69af828f16958", size = 35698906, upload-time = "2025-07-27T16:27:14.943Z" }, - { url = "https://files.pythonhosted.org/packages/04/d6/bb5468da53321baeb001f6e4e0d9049eadd175a4a497709939128556e3ec/scipy-1.16.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:d85495cef541729a70cdddbbf3e6b903421bc1af3e8e3a9a72a06751f33b7c39", size = 38129275, upload-time = "2025-07-27T16:27:23.873Z" }, - { url = "https://files.pythonhosted.org/packages/c4/94/994369978509f227cba7dfb9e623254d0d5559506fe994aef4bea3ed469c/scipy-1.16.1-cp311-cp311-win_amd64.whl", hash = "sha256:226652fca853008119c03a8ce71ffe1b3f6d2844cc1686e8f9806edafae68596", size = 38644572, upload-time = "2025-07-27T16:27:32.637Z" }, - { url = "https://files.pythonhosted.org/packages/f8/d9/ec4864f5896232133f51382b54a08de91a9d1af7a76dfa372894026dfee2/scipy-1.16.1-cp312-cp312-macosx_10_14_x86_64.whl", hash = "sha256:81b433bbeaf35728dad619afc002db9b189e45eebe2cd676effe1fb93fef2b9c", size = 36575194, upload-time = "2025-07-27T16:27:41.321Z" }, - { url = "https://files.pythonhosted.org/packages/5c/6d/40e81ecfb688e9d25d34a847dca361982a6addf8e31f0957b1a54fbfa994/scipy-1.16.1-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:886cc81fdb4c6903a3bb0464047c25a6d1016fef77bb97949817d0c0d79f9e04", size = 28594590, upload-time = "2025-07-27T16:27:49.204Z" }, - { url = "https://files.pythonhosted.org/packages/0e/37/9f65178edfcc629377ce9a64fc09baebea18c80a9e57ae09a52edf84880b/scipy-1.16.1-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:15240c3aac087a522b4eaedb09f0ad061753c5eebf1ea430859e5bf8640d5919", size = 20866458, upload-time = "2025-07-27T16:27:54.98Z" }, - { url = "https://files.pythonhosted.org/packages/2c/7b/749a66766871ea4cb1d1ea10f27004db63023074c22abed51f22f09770e0/scipy-1.16.1-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:65f81a25805f3659b48126b5053d9e823d3215e4a63730b5e1671852a1705921", size = 23539318, upload-time = "2025-07-27T16:28:01.604Z" }, - { url = "https://files.pythonhosted.org/packages/c4/db/8d4afec60eb833a666434d4541a3151eedbf2494ea6d4d468cbe877f00cd/scipy-1.16.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:6c62eea7f607f122069b9bad3f99489ddca1a5173bef8a0c75555d7488b6f725", size = 33292899, upload-time = "2025-07-27T16:28:09.147Z" }, - { url = "https://files.pythonhosted.org/packages/51/1e/79023ca3bbb13a015d7d2757ecca3b81293c663694c35d6541b4dca53e98/scipy-1.16.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:f965bbf3235b01c776115ab18f092a95aa74c271a52577bcb0563e85738fd618", size = 35162637, upload-time = "2025-07-27T16:28:17.535Z" }, - { url = "https://files.pythonhosted.org/packages/b6/49/0648665f9c29fdaca4c679182eb972935b3b4f5ace41d323c32352f29816/scipy-1.16.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:f006e323874ffd0b0b816d8c6a8e7f9a73d55ab3b8c3f72b752b226d0e3ac83d", size = 35490507, upload-time = "2025-07-27T16:28:25.705Z" }, - { url = "https://files.pythonhosted.org/packages/62/8f/66cbb9d6bbb18d8c658f774904f42a92078707a7c71e5347e8bf2f52bb89/scipy-1.16.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e8fd15fc5085ab4cca74cb91fe0a4263b1f32e4420761ddae531ad60934c2119", size = 37923998, upload-time = "2025-07-27T16:28:34.339Z" }, - { url = "https://files.pythonhosted.org/packages/14/c3/61f273ae550fbf1667675701112e380881905e28448c080b23b5a181df7c/scipy-1.16.1-cp312-cp312-win_amd64.whl", hash = "sha256:f7b8013c6c066609577d910d1a2a077021727af07b6fab0ee22c2f901f22352a", size = 38508060, upload-time = "2025-07-27T16:28:43.242Z" }, - { url = "https://files.pythonhosted.org/packages/93/0b/b5c99382b839854a71ca9482c684e3472badc62620287cbbdab499b75ce6/scipy-1.16.1-cp313-cp313-macosx_10_14_x86_64.whl", hash = "sha256:5451606823a5e73dfa621a89948096c6528e2896e40b39248295d3a0138d594f", size = 36533717, upload-time = "2025-07-27T16:28:51.706Z" }, - { url = "https://files.pythonhosted.org/packages/eb/e5/69ab2771062c91e23e07c12e7d5033a6b9b80b0903ee709c3c36b3eb520c/scipy-1.16.1-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:89728678c5ca5abd610aee148c199ac1afb16e19844401ca97d43dc548a354eb", size = 28570009, upload-time = "2025-07-27T16:28:57.017Z" }, - { url = "https://files.pythonhosted.org/packages/f4/69/bd75dbfdd3cf524f4d753484d723594aed62cfaac510123e91a6686d520b/scipy-1.16.1-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:e756d688cb03fd07de0fffad475649b03cb89bee696c98ce508b17c11a03f95c", size = 20841942, upload-time = "2025-07-27T16:29:01.152Z" }, - { url = "https://files.pythonhosted.org/packages/ea/74/add181c87663f178ba7d6144b370243a87af8476664d5435e57d599e6874/scipy-1.16.1-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:5aa2687b9935da3ed89c5dbed5234576589dd28d0bf7cd237501ccfbdf1ad608", size = 23498507, upload-time = "2025-07-27T16:29:05.202Z" }, - { url = "https://files.pythonhosted.org/packages/1d/74/ece2e582a0d9550cee33e2e416cc96737dce423a994d12bbe59716f47ff1/scipy-1.16.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:0851f6a1e537fe9399f35986897e395a1aa61c574b178c0d456be5b1a0f5ca1f", size = 33286040, upload-time = "2025-07-27T16:29:10.201Z" }, - { url = "https://files.pythonhosted.org/packages/e4/82/08e4076df538fb56caa1d489588d880ec7c52d8273a606bb54d660528f7c/scipy-1.16.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:fedc2cbd1baed37474b1924c331b97bdff611d762c196fac1a9b71e67b813b1b", size = 35176096, upload-time = "2025-07-27T16:29:17.091Z" }, - { url = "https://files.pythonhosted.org/packages/fa/79/cd710aab8c921375711a8321c6be696e705a120e3011a643efbbcdeeabcc/scipy-1.16.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:2ef500e72f9623a6735769e4b93e9dcb158d40752cdbb077f305487e3e2d1f45", size = 35490328, upload-time = "2025-07-27T16:29:22.928Z" }, - { url = "https://files.pythonhosted.org/packages/71/73/e9cc3d35ee4526d784520d4494a3e1ca969b071fb5ae5910c036a375ceec/scipy-1.16.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:978d8311674b05a8f7ff2ea6c6bce5d8b45a0cb09d4c5793e0318f448613ea65", size = 37939921, upload-time = "2025-07-27T16:29:29.108Z" }, - { url = "https://files.pythonhosted.org/packages/21/12/c0efd2941f01940119b5305c375ae5c0fcb7ec193f806bd8f158b73a1782/scipy-1.16.1-cp313-cp313-win_amd64.whl", hash = "sha256:81929ed0fa7a5713fcdd8b2e6f73697d3b4c4816d090dd34ff937c20fa90e8ab", size = 38479462, upload-time = "2025-07-27T16:30:24.078Z" }, - { url = "https://files.pythonhosted.org/packages/7a/19/c3d08b675260046a991040e1ea5d65f91f40c7df1045fffff412dcfc6765/scipy-1.16.1-cp313-cp313t-macosx_10_14_x86_64.whl", hash = "sha256:bcc12db731858abda693cecdb3bdc9e6d4bd200213f49d224fe22df82687bdd6", size = 36938832, upload-time = "2025-07-27T16:29:35.057Z" }, - { url = "https://files.pythonhosted.org/packages/81/f2/ce53db652c033a414a5b34598dba6b95f3d38153a2417c5a3883da429029/scipy-1.16.1-cp313-cp313t-macosx_12_0_arm64.whl", hash = "sha256:744d977daa4becb9fc59135e75c069f8d301a87d64f88f1e602a9ecf51e77b27", size = 29093084, upload-time = "2025-07-27T16:29:40.201Z" }, - { url = "https://files.pythonhosted.org/packages/a9/ae/7a10ff04a7dc15f9057d05b33737ade244e4bd195caa3f7cc04d77b9e214/scipy-1.16.1-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:dc54f76ac18073bcecffb98d93f03ed6b81a92ef91b5d3b135dcc81d55a724c7", size = 21365098, upload-time = "2025-07-27T16:29:44.295Z" }, - { url = "https://files.pythonhosted.org/packages/36/ac/029ff710959932ad3c2a98721b20b405f05f752f07344622fd61a47c5197/scipy-1.16.1-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:367d567ee9fc1e9e2047d31f39d9d6a7a04e0710c86e701e053f237d14a9b4f6", size = 23896858, upload-time = "2025-07-27T16:29:48.784Z" }, - { url = "https://files.pythonhosted.org/packages/71/13/d1ef77b6bd7898720e1f0b6b3743cb945f6c3cafa7718eaac8841035ab60/scipy-1.16.1-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:4cf5785e44e19dcd32a0e4807555e1e9a9b8d475c6afff3d21c3c543a6aa84f4", size = 33438311, upload-time = "2025-07-27T16:29:54.164Z" }, - { url = "https://files.pythonhosted.org/packages/2d/e0/e64a6821ffbb00b4c5b05169f1c1fddb4800e9307efe3db3788995a82a2c/scipy-1.16.1-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:3d0b80fb26d3e13a794c71d4b837e2a589d839fd574a6bbb4ee1288c213ad4a3", size = 35279542, upload-time = "2025-07-27T16:30:00.249Z" }, - { url = "https://files.pythonhosted.org/packages/57/59/0dc3c8b43e118f1e4ee2b798dcc96ac21bb20014e5f1f7a8e85cc0653bdb/scipy-1.16.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:8503517c44c18d1030d666cb70aaac1cc8913608816e06742498833b128488b7", size = 35667665, upload-time = "2025-07-27T16:30:05.916Z" }, - { url = "https://files.pythonhosted.org/packages/45/5f/844ee26e34e2f3f9f8febb9343748e72daeaec64fe0c70e9bf1ff84ec955/scipy-1.16.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:30cc4bb81c41831ecfd6dc450baf48ffd80ef5aed0f5cf3ea775740e80f16ecc", size = 38045210, upload-time = "2025-07-27T16:30:11.655Z" }, - { url = "https://files.pythonhosted.org/packages/8d/d7/210f2b45290f444f1de64bc7353aa598ece9f0e90c384b4a156f9b1a5063/scipy-1.16.1-cp313-cp313t-win_amd64.whl", hash = "sha256:c24fa02f7ed23ae514460a22c57eca8f530dbfa50b1cfdbf4f37c05b5309cc39", size = 38593661, upload-time = "2025-07-27T16:30:17.825Z" }, - { url = "https://files.pythonhosted.org/packages/81/ea/84d481a5237ed223bd3d32d6e82d7a6a96e34756492666c260cef16011d1/scipy-1.16.1-cp314-cp314-macosx_10_14_x86_64.whl", hash = "sha256:796a5a9ad36fa3a782375db8f4241ab02a091308eb079746bc0f874c9b998318", size = 36525921, upload-time = "2025-07-27T16:30:30.081Z" }, - { url = "https://files.pythonhosted.org/packages/4e/9f/d9edbdeff9f3a664807ae3aea383e10afaa247e8e6255e6d2aa4515e8863/scipy-1.16.1-cp314-cp314-macosx_12_0_arm64.whl", hash = "sha256:3ea0733a2ff73fd6fdc5fecca54ee9b459f4d74f00b99aced7d9a3adb43fb1cc", size = 28564152, upload-time = "2025-07-27T16:30:35.336Z" }, - { url = "https://files.pythonhosted.org/packages/3b/95/8125bcb1fe04bc267d103e76516243e8d5e11229e6b306bda1024a5423d1/scipy-1.16.1-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:85764fb15a2ad994e708258bb4ed8290d1305c62a4e1ef07c414356a24fcfbf8", size = 20836028, upload-time = "2025-07-27T16:30:39.421Z" }, - { url = "https://files.pythonhosted.org/packages/77/9c/bf92e215701fc70bbcd3d14d86337cf56a9b912a804b9c776a269524a9e9/scipy-1.16.1-cp314-cp314-macosx_14_0_x86_64.whl", hash = "sha256:ca66d980469cb623b1759bdd6e9fd97d4e33a9fad5b33771ced24d0cb24df67e", size = 23489666, upload-time = "2025-07-27T16:30:43.663Z" }, - { url = "https://files.pythonhosted.org/packages/5e/00/5e941d397d9adac41b02839011594620d54d99488d1be5be755c00cde9ee/scipy-1.16.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:e7cc1ffcc230f568549fc56670bcf3df1884c30bd652c5da8138199c8c76dae0", size = 33358318, upload-time = "2025-07-27T16:30:48.982Z" }, - { url = "https://files.pythonhosted.org/packages/0e/87/8db3aa10dde6e3e8e7eb0133f24baa011377d543f5b19c71469cf2648026/scipy-1.16.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:3ddfb1e8d0b540cb4ee9c53fc3dea3186f97711248fb94b4142a1b27178d8b4b", size = 35185724, upload-time = "2025-07-27T16:30:54.26Z" }, - { url = "https://files.pythonhosted.org/packages/89/b4/6ab9ae443216807622bcff02690262d8184078ea467efee2f8c93288a3b1/scipy-1.16.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:4dc0e7be79e95d8ba3435d193e0d8ce372f47f774cffd882f88ea4e1e1ddc731", size = 35554335, upload-time = "2025-07-27T16:30:59.765Z" }, - { url = "https://files.pythonhosted.org/packages/9c/9a/d0e9dc03c5269a1afb60661118296a32ed5d2c24298af61b676c11e05e56/scipy-1.16.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:f23634f9e5adb51b2a77766dac217063e764337fbc816aa8ad9aaebcd4397fd3", size = 37960310, upload-time = "2025-07-27T16:31:06.151Z" }, - { url = "https://files.pythonhosted.org/packages/5e/00/c8f3130a50521a7977874817ca89e0599b1b4ee8e938bad8ae798a0e1f0d/scipy-1.16.1-cp314-cp314-win_amd64.whl", hash = "sha256:57d75524cb1c5a374958a2eae3d84e1929bb971204cc9d52213fb8589183fc19", size = 39319239, upload-time = "2025-07-27T16:31:59.942Z" }, - { url = "https://files.pythonhosted.org/packages/f2/f2/1ca3eda54c3a7e4c92f6acef7db7b3a057deb135540d23aa6343ef8ad333/scipy-1.16.1-cp314-cp314t-macosx_10_14_x86_64.whl", hash = "sha256:d8da7c3dd67bcd93f15618938f43ed0995982eb38973023d46d4646c4283ad65", size = 36939460, upload-time = "2025-07-27T16:31:11.865Z" }, - { url = "https://files.pythonhosted.org/packages/80/30/98c2840b293a132400c0940bb9e140171dcb8189588619048f42b2ce7b4f/scipy-1.16.1-cp314-cp314t-macosx_12_0_arm64.whl", hash = "sha256:cc1d2f2fd48ba1e0620554fe5bc44d3e8f5d4185c8c109c7fbdf5af2792cfad2", size = 29093322, upload-time = "2025-07-27T16:31:17.045Z" }, - { url = "https://files.pythonhosted.org/packages/c1/e6/1e6e006e850622cf2a039b62d1a6ddc4497d4851e58b68008526f04a9a00/scipy-1.16.1-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:21a611ced9275cb861bacadbada0b8c0623bc00b05b09eb97f23b370fc2ae56d", size = 21365329, upload-time = "2025-07-27T16:31:21.188Z" }, - { url = "https://files.pythonhosted.org/packages/8e/02/72a5aa5b820589dda9a25e329ca752842bfbbaf635e36bc7065a9b42216e/scipy-1.16.1-cp314-cp314t-macosx_14_0_x86_64.whl", hash = "sha256:8dfbb25dffc4c3dd9371d8ab456ca81beeaf6f9e1c2119f179392f0dc1ab7695", size = 23897544, upload-time = "2025-07-27T16:31:25.408Z" }, - { url = "https://files.pythonhosted.org/packages/2b/dc/7122d806a6f9eb8a33532982234bed91f90272e990f414f2830cfe656e0b/scipy-1.16.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f0ebb7204f063fad87fc0a0e4ff4a2ff40b2a226e4ba1b7e34bf4b79bf97cd86", size = 33442112, upload-time = "2025-07-27T16:31:30.62Z" }, - { url = "https://files.pythonhosted.org/packages/24/39/e383af23564daa1021a5b3afbe0d8d6a68ec639b943661841f44ac92de85/scipy-1.16.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:f1b9e5962656f2734c2b285a8745358ecb4e4efbadd00208c80a389227ec61ff", size = 35286594, upload-time = "2025-07-27T16:31:36.112Z" }, - { url = "https://files.pythonhosted.org/packages/95/47/1a0b0aff40c3056d955f38b0df5d178350c3d74734ec54f9c68d23910be5/scipy-1.16.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:5e1a106f8c023d57a2a903e771228bf5c5b27b5d692088f457acacd3b54511e4", size = 35665080, upload-time = "2025-07-27T16:31:42.025Z" }, - { url = "https://files.pythonhosted.org/packages/64/df/ce88803e9ed6e27fe9b9abefa157cf2c80e4fa527cf17ee14be41f790ad4/scipy-1.16.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:709559a1db68a9abc3b2c8672c4badf1614f3b440b3ab326d86a5c0491eafae3", size = 38050306, upload-time = "2025-07-27T16:31:48.109Z" }, - { url = "https://files.pythonhosted.org/packages/6e/6c/a76329897a7cae4937d403e623aa6aaea616a0bb5b36588f0b9d1c9a3739/scipy-1.16.1-cp314-cp314t-win_amd64.whl", hash = "sha256:c0c804d60492a0aad7f5b2bb1862f4548b990049e27e828391ff2bf6f7199998", size = 39427705, upload-time = "2025-07-27T16:31:53.96Z" }, +sdist = { url = "https://files.pythonhosted.org/packages/4c/3b/546a6f0bfe791bbb7f8d591613454d15097e53f906308ec6f7c1ce588e8e/scipy-1.16.2.tar.gz", hash = "sha256:af029b153d243a80afb6eabe40b0a07f8e35c9adc269c019f364ad747f826a6b", size = 30580599, upload-time = "2025-09-11T17:48:08.271Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0b/ef/37ed4b213d64b48422df92560af7300e10fe30b5d665dd79932baebee0c6/scipy-1.16.2-cp311-cp311-macosx_10_14_x86_64.whl", hash = "sha256:6ab88ea43a57da1af33292ebd04b417e8e2eaf9d5aa05700be8d6e1b6501cd92", size = 36619956, upload-time = "2025-09-11T17:39:20.5Z" }, + { url = "https://files.pythonhosted.org/packages/85/ab/5c2eba89b9416961a982346a4d6a647d78c91ec96ab94ed522b3b6baf444/scipy-1.16.2-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:c95e96c7305c96ede73a7389f46ccd6c659c4da5ef1b2789466baeaed3622b6e", size = 28931117, upload-time = "2025-09-11T17:39:29.06Z" }, + { url = "https://files.pythonhosted.org/packages/80/d1/eed51ab64d227fe60229a2d57fb60ca5898cfa50ba27d4f573e9e5f0b430/scipy-1.16.2-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:87eb178db04ece7c698220d523c170125dbffebb7af0345e66c3554f6f60c173", size = 20921997, upload-time = "2025-09-11T17:39:34.892Z" }, + { url = "https://files.pythonhosted.org/packages/be/7c/33ea3e23bbadde96726edba6bf9111fb1969d14d9d477ffa202c67bec9da/scipy-1.16.2-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:4e409eac067dcee96a57fbcf424c13f428037827ec7ee3cb671ff525ca4fc34d", size = 23523374, upload-time = "2025-09-11T17:39:40.846Z" }, + { url = "https://files.pythonhosted.org/packages/96/0b/7399dc96e1e3f9a05e258c98d716196a34f528eef2ec55aad651ed136d03/scipy-1.16.2-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:e574be127bb760f0dad24ff6e217c80213d153058372362ccb9555a10fc5e8d2", size = 33583702, upload-time = "2025-09-11T17:39:49.011Z" }, + { url = "https://files.pythonhosted.org/packages/1a/bc/a5c75095089b96ea72c1bd37a4497c24b581ec73db4ef58ebee142ad2d14/scipy-1.16.2-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:f5db5ba6188d698ba7abab982ad6973265b74bb40a1efe1821b58c87f73892b9", size = 35883427, upload-time = "2025-09-11T17:39:57.406Z" }, + { url = "https://files.pythonhosted.org/packages/ab/66/e25705ca3d2b87b97fe0a278a24b7f477b4023a926847935a1a71488a6a6/scipy-1.16.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:ec6e74c4e884104ae006d34110677bfe0098203a3fec2f3faf349f4cb05165e3", size = 36212940, upload-time = "2025-09-11T17:40:06.013Z" }, + { url = "https://files.pythonhosted.org/packages/d6/fd/0bb911585e12f3abdd603d721d83fc1c7492835e1401a0e6d498d7822b4b/scipy-1.16.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:912f46667d2d3834bc3d57361f854226475f695eb08c08a904aadb1c936b6a88", size = 38865092, upload-time = "2025-09-11T17:40:15.143Z" }, + { url = "https://files.pythonhosted.org/packages/d6/73/c449a7d56ba6e6f874183759f8483cde21f900a8be117d67ffbb670c2958/scipy-1.16.2-cp311-cp311-win_amd64.whl", hash = "sha256:91e9e8a37befa5a69e9cacbe0bcb79ae5afb4a0b130fd6db6ee6cc0d491695fa", size = 38687626, upload-time = "2025-09-11T17:40:24.041Z" }, + { url = "https://files.pythonhosted.org/packages/68/72/02f37316adf95307f5d9e579023c6899f89ff3a051fa079dbd6faafc48e5/scipy-1.16.2-cp311-cp311-win_arm64.whl", hash = "sha256:f3bf75a6dcecab62afde4d1f973f1692be013110cad5338007927db8da73249c", size = 25503506, upload-time = "2025-09-11T17:40:30.703Z" }, + { url = "https://files.pythonhosted.org/packages/b7/8d/6396e00db1282279a4ddd507c5f5e11f606812b608ee58517ce8abbf883f/scipy-1.16.2-cp312-cp312-macosx_10_14_x86_64.whl", hash = "sha256:89d6c100fa5c48472047632e06f0876b3c4931aac1f4291afc81a3644316bb0d", size = 36646259, upload-time = "2025-09-11T17:40:39.329Z" }, + { url = "https://files.pythonhosted.org/packages/3b/93/ea9edd7e193fceb8eef149804491890bde73fb169c896b61aa3e2d1e4e77/scipy-1.16.2-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:ca748936cd579d3f01928b30a17dc474550b01272d8046e3e1ee593f23620371", size = 28888976, upload-time = "2025-09-11T17:40:46.82Z" }, + { url = "https://files.pythonhosted.org/packages/91/4d/281fddc3d80fd738ba86fd3aed9202331180b01e2c78eaae0642f22f7e83/scipy-1.16.2-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:fac4f8ce2ddb40e2e3d0f7ec36d2a1e7f92559a2471e59aec37bd8d9de01fec0", size = 20879905, upload-time = "2025-09-11T17:40:52.545Z" }, + { url = "https://files.pythonhosted.org/packages/69/40/b33b74c84606fd301b2915f0062e45733c6ff5708d121dd0deaa8871e2d0/scipy-1.16.2-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:033570f1dcefd79547a88e18bccacff025c8c647a330381064f561d43b821232", size = 23553066, upload-time = "2025-09-11T17:40:59.014Z" }, + { url = "https://files.pythonhosted.org/packages/55/a7/22c739e2f21a42cc8f16bc76b47cff4ed54fbe0962832c589591c2abec34/scipy-1.16.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ea3421209bf00c8a5ef2227de496601087d8f638a2363ee09af059bd70976dc1", size = 33336407, upload-time = "2025-09-11T17:41:06.796Z" }, + { url = "https://files.pythonhosted.org/packages/53/11/a0160990b82999b45874dc60c0c183d3a3a969a563fffc476d5a9995c407/scipy-1.16.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:f66bd07ba6f84cd4a380b41d1bf3c59ea488b590a2ff96744845163309ee8e2f", size = 35673281, upload-time = "2025-09-11T17:41:15.055Z" }, + { url = "https://files.pythonhosted.org/packages/96/53/7ef48a4cfcf243c3d0f1643f5887c81f29fdf76911c4e49331828e19fc0a/scipy-1.16.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5e9feab931bd2aea4a23388c962df6468af3d808ddf2d40f94a81c5dc38f32ef", size = 36004222, upload-time = "2025-09-11T17:41:23.868Z" }, + { url = "https://files.pythonhosted.org/packages/49/7f/71a69e0afd460049d41c65c630c919c537815277dfea214031005f474d78/scipy-1.16.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:03dfc75e52f72cf23ec2ced468645321407faad8f0fe7b1f5b49264adbc29cb1", size = 38664586, upload-time = "2025-09-11T17:41:31.021Z" }, + { url = "https://files.pythonhosted.org/packages/34/95/20e02ca66fb495a95fba0642fd48e0c390d0ece9b9b14c6e931a60a12dea/scipy-1.16.2-cp312-cp312-win_amd64.whl", hash = "sha256:0ce54e07bbb394b417457409a64fd015be623f36e330ac49306433ffe04bc97e", size = 38550641, upload-time = "2025-09-11T17:41:36.61Z" }, + { url = "https://files.pythonhosted.org/packages/92/ad/13646b9beb0a95528ca46d52b7babafbe115017814a611f2065ee4e61d20/scipy-1.16.2-cp312-cp312-win_arm64.whl", hash = "sha256:2a8ffaa4ac0df81a0b94577b18ee079f13fecdb924df3328fc44a7dc5ac46851", size = 25456070, upload-time = "2025-09-11T17:41:41.3Z" }, + { url = "https://files.pythonhosted.org/packages/c1/27/c5b52f1ee81727a9fc457f5ac1e9bf3d6eab311805ea615c83c27ba06400/scipy-1.16.2-cp313-cp313-macosx_10_14_x86_64.whl", hash = "sha256:84f7bf944b43e20b8a894f5fe593976926744f6c185bacfcbdfbb62736b5cc70", size = 36604856, upload-time = "2025-09-11T17:41:47.695Z" }, + { url = "https://files.pythonhosted.org/packages/32/a9/15c20d08e950b540184caa8ced675ba1128accb0e09c653780ba023a4110/scipy-1.16.2-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:5c39026d12edc826a1ef2ad35ad1e6d7f087f934bb868fc43fa3049c8b8508f9", size = 28864626, upload-time = "2025-09-11T17:41:52.642Z" }, + { url = "https://files.pythonhosted.org/packages/4c/fc/ea36098df653cca26062a627c1a94b0de659e97127c8491e18713ca0e3b9/scipy-1.16.2-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:e52729ffd45b68777c5319560014d6fd251294200625d9d70fd8626516fc49f5", size = 20855689, upload-time = "2025-09-11T17:41:57.886Z" }, + { url = "https://files.pythonhosted.org/packages/dc/6f/d0b53be55727f3e6d7c72687ec18ea6d0047cf95f1f77488b99a2bafaee1/scipy-1.16.2-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:024dd4a118cccec09ca3209b7e8e614931a6ffb804b2a601839499cb88bdf925", size = 23512151, upload-time = "2025-09-11T17:42:02.303Z" }, + { url = "https://files.pythonhosted.org/packages/11/85/bf7dab56e5c4b1d3d8eef92ca8ede788418ad38a7dc3ff50262f00808760/scipy-1.16.2-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:7a5dc7ee9c33019973a470556081b0fd3c9f4c44019191039f9769183141a4d9", size = 33329824, upload-time = "2025-09-11T17:42:07.549Z" }, + { url = "https://files.pythonhosted.org/packages/da/6a/1a927b14ddc7714111ea51f4e568203b2bb6ed59bdd036d62127c1a360c8/scipy-1.16.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c2275ff105e508942f99d4e3bc56b6ef5e4b3c0af970386ca56b777608ce95b7", size = 35681881, upload-time = "2025-09-11T17:42:13.255Z" }, + { url = "https://files.pythonhosted.org/packages/c1/5f/331148ea5780b4fcc7007a4a6a6ee0a0c1507a796365cc642d4d226e1c3a/scipy-1.16.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:af80196eaa84f033e48444d2e0786ec47d328ba00c71e4299b602235ffef9acb", size = 36006219, upload-time = "2025-09-11T17:42:18.765Z" }, + { url = "https://files.pythonhosted.org/packages/46/3a/e991aa9d2aec723b4a8dcfbfc8365edec5d5e5f9f133888067f1cbb7dfc1/scipy-1.16.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9fb1eb735fe3d6ed1f89918224e3385fbf6f9e23757cacc35f9c78d3b712dd6e", size = 38682147, upload-time = "2025-09-11T17:42:25.177Z" }, + { url = "https://files.pythonhosted.org/packages/a1/57/0f38e396ad19e41b4c5db66130167eef8ee620a49bc7d0512e3bb67e0cab/scipy-1.16.2-cp313-cp313-win_amd64.whl", hash = "sha256:fda714cf45ba43c9d3bae8f2585c777f64e3f89a2e073b668b32ede412d8f52c", size = 38520766, upload-time = "2025-09-11T17:43:25.342Z" }, + { url = "https://files.pythonhosted.org/packages/1b/a5/85d3e867b6822d331e26c862a91375bb7746a0b458db5effa093d34cdb89/scipy-1.16.2-cp313-cp313-win_arm64.whl", hash = "sha256:2f5350da923ccfd0b00e07c3e5cfb316c1c0d6c1d864c07a72d092e9f20db104", size = 25451169, upload-time = "2025-09-11T17:43:30.198Z" }, + { url = "https://files.pythonhosted.org/packages/09/d9/60679189bcebda55992d1a45498de6d080dcaf21ce0c8f24f888117e0c2d/scipy-1.16.2-cp313-cp313t-macosx_10_14_x86_64.whl", hash = "sha256:53d8d2ee29b925344c13bda64ab51785f016b1b9617849dac10897f0701b20c1", size = 37012682, upload-time = "2025-09-11T17:42:30.677Z" }, + { url = "https://files.pythonhosted.org/packages/83/be/a99d13ee4d3b7887a96f8c71361b9659ba4ef34da0338f14891e102a127f/scipy-1.16.2-cp313-cp313t-macosx_12_0_arm64.whl", hash = "sha256:9e05e33657efb4c6a9d23bd8300101536abd99c85cca82da0bffff8d8764d08a", size = 29389926, upload-time = "2025-09-11T17:42:35.845Z" }, + { url = "https://files.pythonhosted.org/packages/bf/0a/130164a4881cec6ca8c00faf3b57926f28ed429cd6001a673f83c7c2a579/scipy-1.16.2-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:7fe65b36036357003b3ef9d37547abeefaa353b237e989c21027b8ed62b12d4f", size = 21381152, upload-time = "2025-09-11T17:42:40.07Z" }, + { url = "https://files.pythonhosted.org/packages/47/a6/503ffb0310ae77fba874e10cddfc4a1280bdcca1d13c3751b8c3c2996cf8/scipy-1.16.2-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:6406d2ac6d40b861cccf57f49592f9779071655e9f75cd4f977fa0bdd09cb2e4", size = 23914410, upload-time = "2025-09-11T17:42:44.313Z" }, + { url = "https://files.pythonhosted.org/packages/fa/c7/1147774bcea50d00c02600aadaa919facbd8537997a62496270133536ed6/scipy-1.16.2-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ff4dc42bd321991fbf611c23fc35912d690f731c9914bf3af8f417e64aca0f21", size = 33481880, upload-time = "2025-09-11T17:42:49.325Z" }, + { url = "https://files.pythonhosted.org/packages/6a/74/99d5415e4c3e46b2586f30cdbecb95e101c7192628a484a40dd0d163811a/scipy-1.16.2-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:654324826654d4d9133e10675325708fb954bc84dae6e9ad0a52e75c6b1a01d7", size = 35791425, upload-time = "2025-09-11T17:42:54.711Z" }, + { url = "https://files.pythonhosted.org/packages/1b/ee/a6559de7c1cc710e938c0355d9d4fbcd732dac4d0d131959d1f3b63eb29c/scipy-1.16.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:63870a84cd15c44e65220eaed2dac0e8f8b26bbb991456a033c1d9abfe8a94f8", size = 36178622, upload-time = "2025-09-11T17:43:00.375Z" }, + { url = "https://files.pythonhosted.org/packages/4e/7b/f127a5795d5ba8ece4e0dce7d4a9fb7cb9e4f4757137757d7a69ab7d4f1a/scipy-1.16.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:fa01f0f6a3050fa6a9771a95d5faccc8e2f5a92b4a2e5440a0fa7264a2398472", size = 38783985, upload-time = "2025-09-11T17:43:06.661Z" }, + { url = "https://files.pythonhosted.org/packages/3e/9f/bc81c1d1e033951eb5912cd3750cc005943afa3e65a725d2443a3b3c4347/scipy-1.16.2-cp313-cp313t-win_amd64.whl", hash = "sha256:116296e89fba96f76353a8579820c2512f6e55835d3fad7780fece04367de351", size = 38631367, upload-time = "2025-09-11T17:43:14.44Z" }, + { url = "https://files.pythonhosted.org/packages/d6/5e/2cc7555fd81d01814271412a1d59a289d25f8b63208a0a16c21069d55d3e/scipy-1.16.2-cp313-cp313t-win_arm64.whl", hash = "sha256:98e22834650be81d42982360382b43b17f7ba95e0e6993e2a4f5b9ad9283a94d", size = 25787992, upload-time = "2025-09-11T17:43:19.745Z" }, + { url = "https://files.pythonhosted.org/packages/8b/ac/ad8951250516db71619f0bd3b2eb2448db04b720a003dd98619b78b692c0/scipy-1.16.2-cp314-cp314-macosx_10_14_x86_64.whl", hash = "sha256:567e77755019bb7461513c87f02bb73fb65b11f049aaaa8ca17cfaa5a5c45d77", size = 36595109, upload-time = "2025-09-11T17:43:35.713Z" }, + { url = "https://files.pythonhosted.org/packages/ff/f6/5779049ed119c5b503b0f3dc6d6f3f68eefc3a9190d4ad4c276f854f051b/scipy-1.16.2-cp314-cp314-macosx_12_0_arm64.whl", hash = "sha256:17d9bb346194e8967296621208fcdfd39b55498ef7d2f376884d5ac47cec1a70", size = 28859110, upload-time = "2025-09-11T17:43:40.814Z" }, + { url = "https://files.pythonhosted.org/packages/82/09/9986e410ae38bf0a0c737ff8189ac81a93b8e42349aac009891c054403d7/scipy-1.16.2-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:0a17541827a9b78b777d33b623a6dcfe2ef4a25806204d08ead0768f4e529a88", size = 20850110, upload-time = "2025-09-11T17:43:44.981Z" }, + { url = "https://files.pythonhosted.org/packages/0d/ad/485cdef2d9215e2a7df6d61b81d2ac073dfacf6ae24b9ae87274c4e936ae/scipy-1.16.2-cp314-cp314-macosx_14_0_x86_64.whl", hash = "sha256:d7d4c6ba016ffc0f9568d012f5f1eb77ddd99412aea121e6fa8b4c3b7cbad91f", size = 23497014, upload-time = "2025-09-11T17:43:49.074Z" }, + { url = "https://files.pythonhosted.org/packages/a7/74/f6a852e5d581122b8f0f831f1d1e32fb8987776ed3658e95c377d308ed86/scipy-1.16.2-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:9702c4c023227785c779cba2e1d6f7635dbb5b2e0936cdd3a4ecb98d78fd41eb", size = 33401155, upload-time = "2025-09-11T17:43:54.661Z" }, + { url = "https://files.pythonhosted.org/packages/d9/f5/61d243bbc7c6e5e4e13dde9887e84a5cbe9e0f75fd09843044af1590844e/scipy-1.16.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d1cdf0ac28948d225decdefcc45ad7dd91716c29ab56ef32f8e0d50657dffcc7", size = 35691174, upload-time = "2025-09-11T17:44:00.101Z" }, + { url = "https://files.pythonhosted.org/packages/03/99/59933956331f8cc57e406cdb7a483906c74706b156998f322913e789c7e1/scipy-1.16.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:70327d6aa572a17c2941cdfb20673f82e536e91850a2e4cb0c5b858b690e1548", size = 36070752, upload-time = "2025-09-11T17:44:05.619Z" }, + { url = "https://files.pythonhosted.org/packages/c6/7d/00f825cfb47ee19ef74ecf01244b43e95eae74e7e0ff796026ea7cd98456/scipy-1.16.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5221c0b2a4b58aa7c4ed0387d360fd90ee9086d383bb34d9f2789fafddc8a936", size = 38701010, upload-time = "2025-09-11T17:44:11.322Z" }, + { url = "https://files.pythonhosted.org/packages/e4/9f/b62587029980378304ba5a8563d376c96f40b1e133daacee76efdcae32de/scipy-1.16.2-cp314-cp314-win_amd64.whl", hash = "sha256:f5a85d7b2b708025af08f060a496dd261055b617d776fc05a1a1cc69e09fe9ff", size = 39360061, upload-time = "2025-09-11T17:45:09.814Z" }, + { url = "https://files.pythonhosted.org/packages/82/04/7a2f1609921352c7fbee0815811b5050582f67f19983096c4769867ca45f/scipy-1.16.2-cp314-cp314-win_arm64.whl", hash = "sha256:2cc73a33305b4b24556957d5857d6253ce1e2dcd67fa0ff46d87d1670b3e1e1d", size = 26126914, upload-time = "2025-09-11T17:45:14.73Z" }, + { url = "https://files.pythonhosted.org/packages/51/b9/60929ce350c16b221928725d2d1d7f86cf96b8bc07415547057d1196dc92/scipy-1.16.2-cp314-cp314t-macosx_10_14_x86_64.whl", hash = "sha256:9ea2a3fed83065d77367775d689401a703d0f697420719ee10c0780bcab594d8", size = 37013193, upload-time = "2025-09-11T17:44:16.757Z" }, + { url = "https://files.pythonhosted.org/packages/2a/41/ed80e67782d4bc5fc85a966bc356c601afddd175856ba7c7bb6d9490607e/scipy-1.16.2-cp314-cp314t-macosx_12_0_arm64.whl", hash = "sha256:7280d926f11ca945c3ef92ba960fa924e1465f8d07ce3a9923080363390624c4", size = 29390172, upload-time = "2025-09-11T17:44:21.783Z" }, + { url = "https://files.pythonhosted.org/packages/c4/a3/2f673ace4090452696ccded5f5f8efffb353b8f3628f823a110e0170b605/scipy-1.16.2-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:8afae1756f6a1fe04636407ef7dbece33d826a5d462b74f3d0eb82deabefd831", size = 21381326, upload-time = "2025-09-11T17:44:25.982Z" }, + { url = "https://files.pythonhosted.org/packages/42/bf/59df61c5d51395066c35836b78136accf506197617c8662e60ea209881e1/scipy-1.16.2-cp314-cp314t-macosx_14_0_x86_64.whl", hash = "sha256:5c66511f29aa8d233388e7416a3f20d5cae7a2744d5cee2ecd38c081f4e861b3", size = 23915036, upload-time = "2025-09-11T17:44:30.527Z" }, + { url = "https://files.pythonhosted.org/packages/91/c3/edc7b300dc16847ad3672f1a6f3f7c5d13522b21b84b81c265f4f2760d4a/scipy-1.16.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:efe6305aeaa0e96b0ccca5ff647a43737d9a092064a3894e46c414db84bc54ac", size = 33484341, upload-time = "2025-09-11T17:44:35.981Z" }, + { url = "https://files.pythonhosted.org/packages/26/c7/24d1524e72f06ff141e8d04b833c20db3021020563272ccb1b83860082a9/scipy-1.16.2-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:7f3a337d9ae06a1e8d655ee9d8ecb835ea5ddcdcbd8d23012afa055ab014f374", size = 35790840, upload-time = "2025-09-11T17:44:41.76Z" }, + { url = "https://files.pythonhosted.org/packages/aa/b7/5aaad984eeedd56858dc33d75efa59e8ce798d918e1033ef62d2708f2c3d/scipy-1.16.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:bab3605795d269067d8ce78a910220262711b753de8913d3deeaedb5dded3bb6", size = 36174716, upload-time = "2025-09-11T17:44:47.316Z" }, + { url = "https://files.pythonhosted.org/packages/fd/c2/e276a237acb09824822b0ada11b028ed4067fdc367a946730979feacb870/scipy-1.16.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:b0348d8ddb55be2a844c518cd8cc8deeeb8aeba707cf834db5758fc89b476a2c", size = 38790088, upload-time = "2025-09-11T17:44:53.011Z" }, + { url = "https://files.pythonhosted.org/packages/c6/b4/5c18a766e8353015439f3780f5fc473f36f9762edc1a2e45da3ff5a31b21/scipy-1.16.2-cp314-cp314t-win_amd64.whl", hash = "sha256:26284797e38b8a75e14ea6631d29bda11e76ceaa6ddb6fdebbfe4c4d90faf2f9", size = 39457455, upload-time = "2025-09-11T17:44:58.899Z" }, + { url = "https://files.pythonhosted.org/packages/97/30/2f9a5243008f76dfc5dee9a53dfb939d9b31e16ce4bd4f2e628bfc5d89d2/scipy-1.16.2-cp314-cp314t-win_arm64.whl", hash = "sha256:d2a4472c231328d4de38d5f1f68fdd6d28a615138f842580a8a321b5845cf779", size = 26448374, upload-time = "2025-09-11T17:45:03.45Z" }, ] [[package]] @@ -2730,28 +2741,28 @@ wheels = [ [[package]] name = "uv" -version = "0.8.17" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/6f/4c/c270c6b8ed3e8c7fe38ea0b99df9eff09c332421b93d55a158371f75220e/uv-0.8.17.tar.gz", hash = "sha256:2afd4525a53c8ab3a11a5a15093c503d27da67e76257a649b05e4f0bc2ebb5ae", size = 3615060, upload-time = "2025-09-10T21:51:25.067Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/b9/7d/bbaa45c88b2c91e02714a8a5c9e787c47e4898bddfdd268569163492ba45/uv-0.8.17-py3-none-linux_armv6l.whl", hash = "sha256:c51c9633ca93ef63c07df2443941e6264efd2819cc9faabfd9fe11899c6a0d6a", size = 20242144, upload-time = "2025-09-10T21:50:18.081Z" }, - { url = "https://files.pythonhosted.org/packages/65/34/609b72034df0c62bcfb0c0ad4b11e2b55e537c0f0817588b5337d3dcca71/uv-0.8.17-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:c28fba6d7bb5c34ade2c8da5000faebe8425a287f42a043ca01ceb24ebc81590", size = 19363081, upload-time = "2025-09-10T21:50:22.731Z" }, - { url = "https://files.pythonhosted.org/packages/b6/bc/9417df48f0c18a9d54c2444096e03f2f56a3534c5b869f50ac620729cbc8/uv-0.8.17-py3-none-macosx_11_0_arm64.whl", hash = "sha256:b009f1ec9e28de00f76814ad66e35aaae82c98a0f24015de51943dcd1c2a1895", size = 17943513, upload-time = "2025-09-10T21:50:25.824Z" }, - { url = "https://files.pythonhosted.org/packages/63/1c/14fd54c852fd592a2b5da4b7960f3bf4a15c7e51eb20eaddabe8c8cca32d/uv-0.8.17-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:84d56ae50ca71aec032577adf9737974554a82a94e52cee57722745656c1d383", size = 19507222, upload-time = "2025-09-10T21:50:29.237Z" }, - { url = "https://files.pythonhosted.org/packages/be/47/f6a68cc310feca37c965bcbd57eb999e023d35eaeda9c9759867bf3ed232/uv-0.8.17-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:85c2140f8553b9a4387a7395dc30cd151ef94046785fe8b198f13f2c380fb39b", size = 19865652, upload-time = "2025-09-10T21:50:32.87Z" }, - { url = "https://files.pythonhosted.org/packages/ab/6a/fdeb2d4a2635a6927c6d549b07177bcaf6ce15bdef58e8253e75c1b70f54/uv-0.8.17-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2076119783e4a6d3c9e25638956cb123f0eabf4d7d407d9661cdf7f84818dcb9", size = 20831760, upload-time = "2025-09-10T21:50:37.803Z" }, - { url = "https://files.pythonhosted.org/packages/d0/4c/bd58b8a76015aa9ac49d6b4e1211ae1ca98a0aade0c49e1a5f645fb5cd38/uv-0.8.17-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:707a55660d302924fdbcb509e63dfec8842e19d35b69bcc17af76c25db15ad6f", size = 22209056, upload-time = "2025-09-10T21:50:41.749Z" }, - { url = "https://files.pythonhosted.org/packages/7e/2e/28f59c00a2ed6532502fb1e27da9394e505fb7b41cc0274475104b43561b/uv-0.8.17-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1824b76911a14aaa9eee65ad9e180e6a4d2d7c86826232c2f28ae86aee56ed0e", size = 21871684, upload-time = "2025-09-10T21:50:45.331Z" }, - { url = "https://files.pythonhosted.org/packages/5a/1d/a8a4fc08de1f767316467e7a1989bb125734b7ed9cd98ce8969386a70653/uv-0.8.17-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bb9b515cc813fb1b08f1e7592f76e437e2fb44945e53cde4fee11dee3b16d0c3", size = 21145154, upload-time = "2025-09-10T21:50:50.388Z" }, - { url = "https://files.pythonhosted.org/packages/8f/35/cb47d2d07a383c07b0e5043c6fe5555f0fd79683c6d7f9760222987c8be9/uv-0.8.17-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b6d30d02fb65193309fc12a20f9e1a9fab67f469d3e487a254ca1145fd06788f", size = 21106619, upload-time = "2025-09-10T21:50:54.5Z" }, - { url = "https://files.pythonhosted.org/packages/6e/93/c310f0153b9dfe79bdd7f7eaef6380a8545c8939dbfc4e6bdee8f3ee7050/uv-0.8.17-py3-none-manylinux_2_28_aarch64.whl", hash = "sha256:3941cecd9a6a46d3d4505753912c9cf3e8ae5eea30b9d0813f3656210f8c5d01", size = 19777591, upload-time = "2025-09-10T21:50:57.765Z" }, - { url = "https://files.pythonhosted.org/packages/6c/4f/971d3c84c2f09cf8df4536c33644e6b97e10a259d8630a0c1696c1fa6e94/uv-0.8.17-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:cd0ad366cfe4cbe9212bd660b5b9f3a827ff35a7601cefdac2d153bfc8079eb7", size = 20845039, upload-time = "2025-09-10T21:51:01.167Z" }, - { url = "https://files.pythonhosted.org/packages/4a/29/8ad9038e75cb91f54b81cc933dd14fcfa92fa6f8706117d43d4251a8a662/uv-0.8.17-py3-none-musllinux_1_1_armv7l.whl", hash = "sha256:505854bc75c497b95d2c65590291dc820999a4a7d9dfab4f44a9434a6cff7b5f", size = 19820370, upload-time = "2025-09-10T21:51:04.616Z" }, - { url = "https://files.pythonhosted.org/packages/f2/c9/fc8482d1e7dfe187c6e03dcefbac0db41a5dd72aa7b017c0f80f91a04444/uv-0.8.17-py3-none-musllinux_1_1_i686.whl", hash = "sha256:dc479f661da449df37d68b36fdffa641e89fb53ad38c16a5c9f98f3211785b63", size = 20289951, upload-time = "2025-09-10T21:51:08.605Z" }, - { url = "https://files.pythonhosted.org/packages/2d/84/ad878ed045f02aa973be46636c802d494f8270caf5ea8bd04b7bbc68aa23/uv-0.8.17-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:a1d11cd805be6d137ffef4a8227905f87f459031c645ac5031c30a3bcd08abd6", size = 21234644, upload-time = "2025-09-10T21:51:12.429Z" }, - { url = "https://files.pythonhosted.org/packages/f8/03/3fa2641513922988e641050b3adbc87de527f44c2cc8328510703616be6a/uv-0.8.17-py3-none-win32.whl", hash = "sha256:d13a616eb0b2b33c7aa09746cc85860101d595655b58653f0b499af19f33467c", size = 19216757, upload-time = "2025-09-10T21:51:16.021Z" }, - { url = "https://files.pythonhosted.org/packages/1a/c4/0082f437bac162ab95e5a3a389a184c122d45eb5593960aab92fdf80374b/uv-0.8.17-py3-none-win_amd64.whl", hash = "sha256:cf85b84b81b41d57a9b6eeded8473ec06ace8ee959ad0bb57e102b5ad023bd34", size = 21125811, upload-time = "2025-09-10T21:51:19.397Z" }, - { url = "https://files.pythonhosted.org/packages/50/a2/29f57b118b3492c9d5ab1a99ba4906e7d7f8b658881d31bc2c4408d64d07/uv-0.8.17-py3-none-win_arm64.whl", hash = "sha256:64d649a8c4c3732b05dc712544963b004cf733d95fdc5d26f43c5493553ff0a7", size = 19564631, upload-time = "2025-09-10T21:51:22.599Z" }, +version = "0.8.18" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/6d/0b/6e968a7a3210da8b43535cc70422eab114332ecd1bdfdb4df15746979f2b/uv-0.8.18.tar.gz", hash = "sha256:b495e9cfb857060a2a3c25540d0ef9d40991dbfc8a8254679543608816c1921b", size = 3653354, upload-time = "2025-09-17T21:36:43.666Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3b/21/c88abfe4fc47d6a859aae234409cbe355138ccf7ad088d3697539cff8a90/uv-0.8.18-py3-none-linux_armv6l.whl", hash = "sha256:42b2b0a3c9d0d32cb7bd23cf9d05d52b3dfc83c706f927569c32ee9483bd2479", size = 20237508, upload-time = "2025-09-17T21:35:44.844Z" }, + { url = "https://files.pythonhosted.org/packages/b6/97/3a4ba6d5fa4853f96574cb085fcda4407199b62abbc0b8b170d4e3b6aa5c/uv-0.8.18-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:46668347e9b29b254a6fc45fbd9788e7c630f0b4f3f7d894a1d3d4eecb20c3e4", size = 19252461, upload-time = "2025-09-17T21:35:48.889Z" }, + { url = "https://files.pythonhosted.org/packages/4e/79/7af5b261b061b1dd92eed0be1a14264c34717006e651a83018c15adb2043/uv-0.8.18-py3-none-macosx_11_0_arm64.whl", hash = "sha256:e321544054688df7115041cc172865e5e0f9377b7b9e351e67d7db27c99c4080", size = 17870543, upload-time = "2025-09-17T21:35:51.611Z" }, + { url = "https://files.pythonhosted.org/packages/4b/89/3c9ffa0c971eab50974a976eed6d2e00d8e3e0b6146b8b45b699f64a1224/uv-0.8.18-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:087b9c8afe50585b1b4aa880ef5fe3c8067268abf8461d01cd59f65517a0696b", size = 19503893, upload-time = "2025-09-17T21:35:56.117Z" }, + { url = "https://files.pythonhosted.org/packages/5b/56/a2309381dd2138e67b22f004fb4e26b04e8e06b04dac50f0c392e3f2ae54/uv-0.8.18-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:30b89b85840500a110a0bfaf7ca97a52803617873c63e4c3cad866ad93d13ed3", size = 19850198, upload-time = "2025-09-17T21:35:58.782Z" }, + { url = "https://files.pythonhosted.org/packages/fc/0f/e46774ee081c56632acc4f8c3c35ddb3ce4bc0e8535da8907ce4623aedb2/uv-0.8.18-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3a8d4bc46fb699d1e172de3948870f5a10408e59e5c0c184ecee1d5be02cb740", size = 20798436, upload-time = "2025-09-17T21:36:02.122Z" }, + { url = "https://files.pythonhosted.org/packages/ef/7a/07fbdd3e966e86fc6dd18fe46fce51f27d799cccb06b8f95134dec800f0a/uv-0.8.18-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:3073e1fc28ba5cb9d04a09bc0bd761569d3f3f1cc4252810c3992465c9579334", size = 22198386, upload-time = "2025-09-17T21:36:05.38Z" }, + { url = "https://files.pythonhosted.org/packages/83/f6/751e1544396796a5cf5c9616ab50f14969e15708eb2746ef854a038ba9b5/uv-0.8.18-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a8dc04c632881263a880084292bbfb0140270787b12435278e4b6fc342761efe", size = 21878627, upload-time = "2025-09-17T21:36:08.204Z" }, + { url = "https://files.pythonhosted.org/packages/6c/09/ca38d471ecf5e48b61e649b407315790581871dbea49ea34577b8a22276b/uv-0.8.18-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:428d2effa05d2c0b33d30c45eac0a15eddb2ac369b987b8eb651a033f90fd73b", size = 21086454, upload-time = "2025-09-17T21:36:11.805Z" }, + { url = "https://files.pythonhosted.org/packages/57/f6/b55bf6af76e3188d63db016a65c337fe23828d6b705e58412d526b748da1/uv-0.8.18-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e9933c17dd618ca1c7e6aee877e928cd8583c20ceef9360917803a49c664a917", size = 21030766, upload-time = "2025-09-17T21:36:14.739Z" }, + { url = "https://files.pythonhosted.org/packages/49/8c/6d866287558c5aae930c4f71565000994e4b6b14e56b5c86ed1b32241820/uv-0.8.18-py3-none-manylinux_2_28_aarch64.whl", hash = "sha256:b8067f1cf8208dd6f9efc9e2e67c165c97b413ea48f90ba4ffb5caf85c1e5ce0", size = 19778490, upload-time = "2025-09-17T21:36:18.593Z" }, + { url = "https://files.pythonhosted.org/packages/d3/f2/669810996e5d164504eea5639fecff28ccf2c9cc98a9b80b4f36516420b9/uv-0.8.18-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:45d0e8ab23d7bc8a32596bb3ef7569e95c134e5fff26ab68c091f3c44b7e7caf", size = 20804081, upload-time = "2025-09-17T21:36:21.312Z" }, + { url = "https://files.pythonhosted.org/packages/8b/03/32e00cbc4fce767a26c2341bfd10317d9ec9b27b811f5d03075734e4bdb6/uv-0.8.18-py3-none-musllinux_1_1_armv7l.whl", hash = "sha256:a8f98de826a92a71956d6f255b0d93865a4d4821fa7c76c81b0fc20e15f05189", size = 19819627, upload-time = "2025-09-17T21:36:24.272Z" }, + { url = "https://files.pythonhosted.org/packages/9d/1b/e6f67c485cf3acf4af7ceed97fe162a5c201a6514610622ca7d21015a907/uv-0.8.18-py3-none-musllinux_1_1_i686.whl", hash = "sha256:336fad21ad357ae5e8cd2b75142d31d109dcc8ac3dea9fa1f4417993087f48bb", size = 20231410, upload-time = "2025-09-17T21:36:27.086Z" }, + { url = "https://files.pythonhosted.org/packages/60/dc/8a1d11b7de323f579b7e829fe77d42e81223eab6cb6714686f1e3b76227e/uv-0.8.18-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:0c492090312e3252091ef5bc570ac46a616b06d9c0ef448898eeb381f6742c0d", size = 21191101, upload-time = "2025-09-17T21:36:30.311Z" }, + { url = "https://files.pythonhosted.org/packages/e3/c0/6d188d3dc9230244eb933aedd820c6428237646f8583077e7ebfd57f4491/uv-0.8.18-py3-none-win32.whl", hash = "sha256:ee28459f377a1afcd0450ee635106dee8d77bea69d8dcd42bc4eecd3361ccab4", size = 19163833, upload-time = "2025-09-17T21:36:35.575Z" }, + { url = "https://files.pythonhosted.org/packages/4f/f5/c2dc1d07bae2687625ef29ffdd51cc4971d38077fb27022bc5fd13437e47/uv-0.8.18-py3-none-win_amd64.whl", hash = "sha256:313d09b7c076ad904853fb2788eab34b1541db67cc2feaf67a6f0f81bc3b346c", size = 20981095, upload-time = "2025-09-17T21:36:38.661Z" }, + { url = "https://files.pythonhosted.org/packages/b7/7d/c3c09a3c5640db2b2a00b343e64ad70defd02b4b5e0ab221ff210c85de79/uv-0.8.18-py3-none-win_arm64.whl", hash = "sha256:a1493b8184175af5474c75fa432940969cf6452976c37ddb8c9e28afa1d25742", size = 19591881, upload-time = "2025-09-17T21:36:41.482Z" }, ] [[package]] From 87e8660e69fb6c427333cbecf2cabb30cf836d79 Mon Sep 17 00:00:00 2001 From: Erik Date: Wed, 24 Sep 2025 14:46:53 -0700 Subject: [PATCH 471/521] rename test test_plasma_potential_didv.py -> test_plasma_potential__find_didv_peak_location.py --- ..._didv.py => test_plasma_potential__find_didv_peak_location.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename tests/analysis/swept_langmuir/{test_plasma_potential_didv.py => test_plasma_potential__find_didv_peak_location.py} (100%) diff --git a/tests/analysis/swept_langmuir/test_plasma_potential_didv.py b/tests/analysis/swept_langmuir/test_plasma_potential__find_didv_peak_location.py similarity index 100% rename from tests/analysis/swept_langmuir/test_plasma_potential_didv.py rename to tests/analysis/swept_langmuir/test_plasma_potential__find_didv_peak_location.py From 65255afea27d3265811cad4c0a3f9f19b6f0265b Mon Sep 17 00:00:00 2001 From: Erik Date: Wed, 24 Sep 2025 15:57:07 -0700 Subject: [PATCH 472/521] create test_plasma_potential__condition_smooth_fractions.py and initialize with raises tests --- ...a_potential__condition_smooth_fractions.py | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 tests/analysis/swept_langmuir/test_plasma_potential__condition_smooth_fractions.py diff --git a/tests/analysis/swept_langmuir/test_plasma_potential__condition_smooth_fractions.py b/tests/analysis/swept_langmuir/test_plasma_potential__condition_smooth_fractions.py new file mode 100644 index 0000000000..fcbb26a011 --- /dev/null +++ b/tests/analysis/swept_langmuir/test_plasma_potential__condition_smooth_fractions.py @@ -0,0 +1,41 @@ +""" +Tests for +`plasmapy.analysis.swept_langmuir.plasma_potential._condition_smooth_fractions`. +""" + +import numpy as np +import pytest + +from plasmapy.analysis.swept_langmuir.plasma_potential import _condition_smooth_fractions + + +class TestConditionSmoothFractions: + @pytest.mark.parametrize( + ("_raises", "smooth_fractions", "data_size"), + [ + # smooth_fractions is not a list-like or None + (pytest.raises(TypeError), {"one": 1, "two": 2}, 10), + (pytest.raises(TypeError), "invalid fraction", 10), + (pytest.raises(TypeError), 5.0, 10), + # smooth_fractions is not 1D + (pytest.raises(ValueError), [[1, 2], [1, 2]], 10), + (pytest.raises(ValueError), np.zeros((2, 5)), 10), + # smooth_fractions elements are NOT floats + (pytest.raises(ValueError), [1, 2, 3], 10), + (pytest.raises(ValueError), ["one", 2., "three"], 10), + # smooth_fractions is out of range.. (0, 1] + (pytest.raises(ValueError), [-5.0], 10), + (pytest.raises(ValueError), [0.0], 10), + (pytest.raises(ValueError), [5.0], 10), + (pytest.raises(ValueError), [0, 0.1, .9, 1.0], 10), + (pytest.raises(ValueError), [-0.5, 0.1, .9, 1.0], 10), + (pytest.raises(ValueError), [-0.5, 0, .9, 1.0], 10), + (pytest.raises(ValueError), [0.1, .9, 1.1], 10), + (pytest.raises(ValueError), [0.1, .9, 20.0], 10), + (pytest.raises(ValueError), [0, 0.1, .9, 1.1], 10), + (pytest.raises(ValueError), [-20.0, 0, 0.1, .9, 1.1], 10), + ], + ) + def test_raises(self, _raises, smooth_fractions, data_size): + with _raises: + _condition_smooth_fractions(smooth_fractions, data_size) From 66f893697a4cb5bd7c69bee09791e5e569cfea86 Mon Sep 17 00:00:00 2001 From: Erik Date: Wed, 24 Sep 2025 15:57:39 -0700 Subject: [PATCH 473/521] fix mask inequalities for finding smooth_fractions out of range --- src/plasmapy/analysis/swept_langmuir/plasma_potential.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py index ebb00f0a15..651a6ecba3 100644 --- a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py +++ b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py @@ -84,8 +84,8 @@ def _condition_smooth_fractions(smooth_fractions, data_size): ) smooth_fractions = np.unique(np.sort(smooth_fractions)) - mask1 = smooth_fractions > 0 - mask2 = smooth_fractions <= 1 + mask1 = smooth_fractions <= 0 + mask2 = smooth_fractions > 1 mask = np.logical_and(mask1, mask2) if np.count_nonzero(mask) == 0: raise ValueError( From 88b1dcd293ca5b977aeaff9fecc2a8a393b244f2 Mon Sep 17 00:00:00 2001 From: Erik Date: Wed, 24 Sep 2025 15:59:47 -0700 Subject: [PATCH 474/521] pass if-clause if smooth_fractions already numpy array and handle if sequence is a string --- .../analysis/swept_langmuir/plasma_potential.py | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py index 651a6ecba3..091dd0d122 100644 --- a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py +++ b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py @@ -62,16 +62,12 @@ def _condition_smooth_fractions(smooth_fractions, data_size): # for smooth_fractions in the find_didv_peak() docstring # needs to be updated accordingly. smooth_fractions = np.linspace(0.01, 0.25, num=30) - elif ( - isinstance(smooth_fractions, Sequence) - and not isinstance(smooth_fractions, np.ndarray) - ): - smooth_fractions = np.array(smooth_fractions) - - if not isinstance(smooth_fractions, np.ndarray): + elif isinstance(smooth_fractions, np.ndarray): + pass + elif not isinstance(smooth_fractions, Sequence) or isinstance(smooth_fractions, str): raise TypeError( - "Expected a 1-D list of floats in the interval (0, 1] for argument " - f"'smooth_fractions', but got type {type(smooth_fractions)}." + f"Expected a list-like object for 'smooth_fractions', " + f"but got type {type(smooth_fractions)}." ) elif smooth_fractions.ndim != 1: raise ValueError( From f8a1b39b3e69f10cb877bc1bcc48486be186dfe3 Mon Sep 17 00:00:00 2001 From: Erik Date: Wed, 24 Sep 2025 16:00:27 -0700 Subject: [PATCH 475/521] convert sequence to numpy array in else --- src/plasmapy/analysis/swept_langmuir/plasma_potential.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py index 091dd0d122..d3bc1874dc 100644 --- a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py +++ b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py @@ -69,7 +69,10 @@ def _condition_smooth_fractions(smooth_fractions, data_size): f"Expected a list-like object for 'smooth_fractions', " f"but got type {type(smooth_fractions)}." ) - elif smooth_fractions.ndim != 1: + else: + smooth_fractions = np.array(smooth_fractions) + + if smooth_fractions.ndim != 1: raise ValueError( "Expected a 1-D list of floats in the interval (0, 1] for argument " f"'smooth_fractions', but got a {smooth_fractions.ndim}-D list.") From f4a709aaab84c9a0672723c6192a9288f1afcaf4 Mon Sep 17 00:00:00 2001 From: Erik Date: Wed, 24 Sep 2025 16:40:31 -0700 Subject: [PATCH 476/521] add conditioning for data_size --- src/plasmapy/analysis/swept_langmuir/plasma_potential.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py index d3bc1874dc..b1d1a1292d 100644 --- a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py +++ b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py @@ -52,11 +52,12 @@ class dIdVExtras(NamedTuple): # noqa: N801 """ -def _condition_smooth_fractions(smooth_fractions, data_size): +def _condition_smooth_fractions(smooth_fractions, data_size: int): """ Condition ``smooth_fractions`` and return the resulting Savitzky-Golay filter windows sizes, based on the ``data_size``. """ + # condition smooth_fractions if smooth_fractions is None: # Note: If this default value is changed, then the docstring entry # for smooth_fractions in the find_didv_peak() docstring From 75e12df6f387d7bf3a8be090944fbde139e07a33 Mon Sep 17 00:00:00 2001 From: Erik Date: Wed, 24 Sep 2025 16:40:50 -0700 Subject: [PATCH 477/521] add conditioning for data_size --- .../analysis/swept_langmuir/plasma_potential.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py index b1d1a1292d..d5df52bb9c 100644 --- a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py +++ b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py @@ -94,6 +94,18 @@ def _condition_smooth_fractions(smooth_fractions, data_size: int): f"{smooth_fractions.tolist()}." ) + # condition data_size + if not isinstance(data_size, int): + raise TypeError( + "Expected a positive, non-zero integer for argument 'data_size', " + f"but got type {type(data_size)}." + ) + elif data_size < 1: + raise ValueError( + "Expected a positive, non-zero integer for argument 'data_size', " + f"but got {data_size}." + ) + # create bin sizes (savgol_windows) for the savgol_filter savgol_windows = np.unique(np.rint(smooth_fractions * data_size).astype(int)) From bc0bb3c88f8ba4a0c44e9d6abe91cb678886d08a Mon Sep 17 00:00:00 2001 From: Erik Date: Wed, 24 Sep 2025 16:41:25 -0700 Subject: [PATCH 478/521] fix logic for identifying out of range smooth_fractions elements --- src/plasmapy/analysis/swept_langmuir/plasma_potential.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py index d5df52bb9c..0687a623b1 100644 --- a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py +++ b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py @@ -86,8 +86,8 @@ def _condition_smooth_fractions(smooth_fractions, data_size: int): smooth_fractions = np.unique(np.sort(smooth_fractions)) mask1 = smooth_fractions <= 0 mask2 = smooth_fractions > 1 - mask = np.logical_and(mask1, mask2) - if np.count_nonzero(mask) == 0: + mask = np.logical_or(mask1, mask2) + if np.count_nonzero(mask) > 0: raise ValueError( "Expected a 1-D list of floats in the interval (0, 1] for argument " f"'smooth_fractions', no elements are within this interval " From dbc5db9610d4e7dd102e92c192447ced0aa2c3c1 Mon Sep 17 00:00:00 2001 From: Erik Date: Wed, 24 Sep 2025 18:19:57 -0700 Subject: [PATCH 479/521] add cases to TestConditionsSmoothFractions.test_raises() --- .../test_plasma_potential__condition_smooth_fractions.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/analysis/swept_langmuir/test_plasma_potential__condition_smooth_fractions.py b/tests/analysis/swept_langmuir/test_plasma_potential__condition_smooth_fractions.py index fcbb26a011..48986a225d 100644 --- a/tests/analysis/swept_langmuir/test_plasma_potential__condition_smooth_fractions.py +++ b/tests/analysis/swept_langmuir/test_plasma_potential__condition_smooth_fractions.py @@ -34,6 +34,15 @@ class TestConditionSmoothFractions: (pytest.raises(ValueError), [0.1, .9, 20.0], 10), (pytest.raises(ValueError), [0, 0.1, .9, 1.1], 10), (pytest.raises(ValueError), [-20.0, 0, 0.1, .9, 1.1], 10), + # data_size not integer + (pytest.raises(TypeError), [0.2, 0.5, 0.8], "hello"), + (pytest.raises(TypeError), [0.2, 0.5, 0.8], 90.5), + # data_size not positive, non-zero integer + (pytest.raises(ValueError), [0.2, 0.5, 0.8], 0), + (pytest.raises(ValueError), [0.2, 0.5, 0.8], -20), + # # computed savgol_windows is null + (pytest.raises(ValueError), [0.2, 0.5, 0.8], 1), + (pytest.raises(ValueError), [0.02], 20), ], ) def test_raises(self, _raises, smooth_fractions, data_size): From c770f9d500c99fb9e0149e0cf5da5f865f561e8a Mon Sep 17 00:00:00 2001 From: Erik Date: Wed, 24 Sep 2025 18:20:17 -0700 Subject: [PATCH 480/521] write TestConditionsSmoothFractions.test_expected() --- ...t_plasma_potential__condition_smooth_fractions.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tests/analysis/swept_langmuir/test_plasma_potential__condition_smooth_fractions.py b/tests/analysis/swept_langmuir/test_plasma_potential__condition_smooth_fractions.py index 48986a225d..ead20f4d3f 100644 --- a/tests/analysis/swept_langmuir/test_plasma_potential__condition_smooth_fractions.py +++ b/tests/analysis/swept_langmuir/test_plasma_potential__condition_smooth_fractions.py @@ -48,3 +48,15 @@ class TestConditionSmoothFractions: def test_raises(self, _raises, smooth_fractions, data_size): with _raises: _condition_smooth_fractions(smooth_fractions, data_size) + + @pytest.mark.parametrize( + ("smooth_fractions", "data_size", "expected"), + [ + ([0.2, 0.5, 0.8], 20, np.array([5, 11, 17], dtype=int)), + ([0.02, 0.2, 0.5, 0.8], 20, np.array([5, 11, 17], dtype=int)), + (None, 50, np.array([3, 5, 7, 9, 11, 13], dtype=int)), + ], + ) + def test_expected(self, smooth_fractions, data_size, expected): + result = _condition_smooth_fractions(smooth_fractions, data_size) + assert np.array_equal(result, expected) From 0d8612eeeae639becc69d9dd0c5b0d932722b7f0 Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 25 Sep 2025 10:04:22 -0700 Subject: [PATCH 481/521] initialized TestFinddIdVPeakLocation --- ...asma_potential__find_didv_peak_location.py | 78 +++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/tests/analysis/swept_langmuir/test_plasma_potential__find_didv_peak_location.py b/tests/analysis/swept_langmuir/test_plasma_potential__find_didv_peak_location.py index 9150ee54b6..8de0429140 100644 --- a/tests/analysis/swept_langmuir/test_plasma_potential__find_didv_peak_location.py +++ b/tests/analysis/swept_langmuir/test_plasma_potential__find_didv_peak_location.py @@ -51,3 +51,81 @@ def test_didv_namedtuple_index_field_mapping(index, field_name): assert extras[index] == getattr(extras, field_name) + +class TestFinddIdVPeakLocation: + + @pytest.mark.parametrize( + ("helper", "used_callable"), + [ + (sla.helpers.check_sweep, sla.plasma_potential.check_sweep), + ( + sla.helpers._condition_voltage_window, + sla.plasma_potential._condition_voltage_window, + ), + ], + ) + def test_helper_callable_consistency(self, helper, used_callable): + assert helper is used_callable + + def test_call_of_check_sweep(self) -> None: + varr = np.linspace(-20.0, 20.0, 100) + carr = np.linspace(-20.0, 20.0, 100) + + with mock.patch(f"{sla.plasma_potential.__name__}.check_sweep") as mock_cs: + mock_cs.return_value = varr, carr + find_didv_peak_location(voltage=varr, current=carr) + + assert mock_cs.call_count == 1 + + # passed args + assert len(mock_cs.call_args[0]) == 2 + assert np.array_equal(mock_cs.call_args[0][0], varr) + assert np.array_equal(mock_cs.call_args[0][1], carr) + + # passed kwargs + assert mock_cs.call_args[1] == {"strip_units": True} + + def test_call_of_merge_voltage_clusters(self) -> None: + varr = np.linspace(-20.0, 20.0, 100) + carr = np.linspace(-20.0, 20.0, 100) + + with ( + mock.patch(f"{sla.plasma_potential.__name__}.merge_voltage_clusters") + as mock_mvc + ): + mock_mvc.return_value = varr, carr + find_didv_peak_location(voltage=varr, current=carr) + + assert mock_mvc.call_count == 1 + + # passed args + assert len(mock_mvc.call_args[0]) == 2 + assert np.array_equal(mock_mvc.call_args[0][0], varr) + assert np.array_equal(mock_mvc.call_args[0][1], carr) + + # passed kwargs + assert mock_mvc.call_args[1] == {"voltage_step_size": 0} + + def test_call_of_condition_voltage_window(self) -> None: + varr = np.linspace(-20.0, 20.0, 100) + carr = np.linspace(-20.0, 20.0, 100) + + with ( + mock.patch( + f"{sla.plasma_potential.__name__}._condition_voltage_window", + side_effect=sla.plasma_potential._condition_voltage_window, + ) + as mock_cvw + ): + # mock_cvw.return_value = varr, carr + find_didv_peak_location(voltage=varr, current=carr) + + assert mock_cvw.call_count == 1 + + # passed args + assert len(mock_cvw.call_args[0]) == 2 + assert np.array_equal(mock_cvw.call_args[0][0], varr) + assert mock_cvw.call_args[0][1] is None # voltage_window arg + + # passed kwargs + assert mock_cvw.call_args[1] == {} From 019233ca8c7266e9e3c2c61478e8321332eddc0e Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 25 Sep 2025 10:07:24 -0700 Subject: [PATCH 482/521] add merge_voltage_clusters to TestFinddIdVPeakLocation.test_helper_callable_consistency() --- .../test_plasma_potential__find_didv_peak_location.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/analysis/swept_langmuir/test_plasma_potential__find_didv_peak_location.py b/tests/analysis/swept_langmuir/test_plasma_potential__find_didv_peak_location.py index 8de0429140..39ac6cc6ed 100644 --- a/tests/analysis/swept_langmuir/test_plasma_potential__find_didv_peak_location.py +++ b/tests/analysis/swept_langmuir/test_plasma_potential__find_didv_peak_location.py @@ -57,11 +57,15 @@ class TestFinddIdVPeakLocation: @pytest.mark.parametrize( ("helper", "used_callable"), [ - (sla.helpers.check_sweep, sla.plasma_potential.check_sweep), ( sla.helpers._condition_voltage_window, sla.plasma_potential._condition_voltage_window, ), + (sla.helpers.check_sweep, sla.plasma_potential.check_sweep), + ( + sla.helpers.merge_voltage_clusters, + sla.plasma_potential.merge_voltage_clusters, + ), ], ) def test_helper_callable_consistency(self, helper, used_callable): From 5b7413a7426e09102b72dfb1e167d05aba73272e Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 25 Sep 2025 10:26:13 -0700 Subject: [PATCH 483/521] add TestFinddIdVPeakLocation.test_call_of_condition_smooth_fractions() --- ...asma_potential__find_didv_peak_location.py | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/tests/analysis/swept_langmuir/test_plasma_potential__find_didv_peak_location.py b/tests/analysis/swept_langmuir/test_plasma_potential__find_didv_peak_location.py index 39ac6cc6ed..ff0d33b71c 100644 --- a/tests/analysis/swept_langmuir/test_plasma_potential__find_didv_peak_location.py +++ b/tests/analysis/swept_langmuir/test_plasma_potential__find_didv_peak_location.py @@ -133,3 +133,27 @@ def test_call_of_condition_voltage_window(self) -> None: # passed kwargs assert mock_cvw.call_args[1] == {} + + def test_call_of_condition_smooth_fractions(self) -> None: + varr = np.linspace(-20.0, 20.0, 100) + carr = np.linspace(-20.0, 20.0, 100) + + with ( + mock.patch( + f"{sla.plasma_potential.__name__}._condition_smooth_fractions", + side_effect=sla.plasma_potential._condition_smooth_fractions, + ) + as mock_csf + ): + # mock_cvw.return_value = varr, carr + find_didv_peak_location(voltage=varr, current=carr) + + assert mock_csf.call_count == 1 + + # passed args + assert len(mock_csf.call_args[0]) == 2 + assert mock_csf.call_args[0][0] is None # smooth_fractions arg + assert mock_csf.call_args[0][1] == 100 # data_size arg + + # passed kwargs + assert mock_csf.call_args[1] == {} From b432c730503ba6deffd31ef8961969400e84641b Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 25 Sep 2025 10:51:25 -0700 Subject: [PATCH 484/521] create and implement pytest fixtures simple_voltage and simple_current --- ...asma_potential__find_didv_peak_location.py | 49 +++++++++---------- 1 file changed, 24 insertions(+), 25 deletions(-) diff --git a/tests/analysis/swept_langmuir/test_plasma_potential__find_didv_peak_location.py b/tests/analysis/swept_langmuir/test_plasma_potential__find_didv_peak_location.py index ff0d33b71c..b3fee76b96 100644 --- a/tests/analysis/swept_langmuir/test_plasma_potential__find_didv_peak_location.py +++ b/tests/analysis/swept_langmuir/test_plasma_potential__find_didv_peak_location.py @@ -54,6 +54,14 @@ def test_didv_namedtuple_index_field_mapping(index, field_name): class TestFinddIdVPeakLocation: + @pytest.fixture(scope="class") + def simple_voltage(self): + return np.linspace(-20.0, 20.0, 100) + + @pytest.fixture(scope="class") + def simple_current(self): + return np.linspace(-20.0, 20.0, 100) + @pytest.mark.parametrize( ("helper", "used_callable"), [ @@ -71,48 +79,42 @@ class TestFinddIdVPeakLocation: def test_helper_callable_consistency(self, helper, used_callable): assert helper is used_callable - def test_call_of_check_sweep(self) -> None: - varr = np.linspace(-20.0, 20.0, 100) - carr = np.linspace(-20.0, 20.0, 100) + def test_call_of_check_sweep(self, simple_voltage, simple_current) -> None: with mock.patch(f"{sla.plasma_potential.__name__}.check_sweep") as mock_cs: - mock_cs.return_value = varr, carr - find_didv_peak_location(voltage=varr, current=carr) + mock_cs.return_value = simple_voltage, simple_current + find_didv_peak_location(voltage=simple_voltage, current=simple_current) assert mock_cs.call_count == 1 # passed args assert len(mock_cs.call_args[0]) == 2 - assert np.array_equal(mock_cs.call_args[0][0], varr) - assert np.array_equal(mock_cs.call_args[0][1], carr) + assert np.array_equal(mock_cs.call_args[0][0], simple_voltage) + assert np.array_equal(mock_cs.call_args[0][1], simple_current) # passed kwargs assert mock_cs.call_args[1] == {"strip_units": True} - def test_call_of_merge_voltage_clusters(self) -> None: - varr = np.linspace(-20.0, 20.0, 100) - carr = np.linspace(-20.0, 20.0, 100) + def test_call_of_merge_voltage_clusters(self, simple_voltage, simple_current) -> None: with ( mock.patch(f"{sla.plasma_potential.__name__}.merge_voltage_clusters") as mock_mvc ): - mock_mvc.return_value = varr, carr - find_didv_peak_location(voltage=varr, current=carr) + mock_mvc.return_value = simple_voltage, simple_current + find_didv_peak_location(voltage=simple_voltage, current=simple_current) assert mock_mvc.call_count == 1 # passed args assert len(mock_mvc.call_args[0]) == 2 - assert np.array_equal(mock_mvc.call_args[0][0], varr) - assert np.array_equal(mock_mvc.call_args[0][1], carr) + assert np.array_equal(mock_mvc.call_args[0][0], simple_voltage) + assert np.array_equal(mock_mvc.call_args[0][1], simple_current) # passed kwargs assert mock_mvc.call_args[1] == {"voltage_step_size": 0} - def test_call_of_condition_voltage_window(self) -> None: - varr = np.linspace(-20.0, 20.0, 100) - carr = np.linspace(-20.0, 20.0, 100) + def test_call_of_condition_voltage_window(self, simple_voltage, simple_current) -> None: with ( mock.patch( @@ -122,21 +124,19 @@ def test_call_of_condition_voltage_window(self) -> None: as mock_cvw ): # mock_cvw.return_value = varr, carr - find_didv_peak_location(voltage=varr, current=carr) + find_didv_peak_location(voltage=simple_voltage, current=simple_current) assert mock_cvw.call_count == 1 # passed args assert len(mock_cvw.call_args[0]) == 2 - assert np.array_equal(mock_cvw.call_args[0][0], varr) + assert np.array_equal(mock_cvw.call_args[0][0], simple_voltage) assert mock_cvw.call_args[0][1] is None # voltage_window arg # passed kwargs assert mock_cvw.call_args[1] == {} - def test_call_of_condition_smooth_fractions(self) -> None: - varr = np.linspace(-20.0, 20.0, 100) - carr = np.linspace(-20.0, 20.0, 100) + def test_call_of_condition_smooth_fractions(self, simple_voltage, simple_current) -> None: with ( mock.patch( @@ -145,15 +145,14 @@ def test_call_of_condition_smooth_fractions(self) -> None: ) as mock_csf ): - # mock_cvw.return_value = varr, carr - find_didv_peak_location(voltage=varr, current=carr) + find_didv_peak_location(voltage=simple_voltage, current=simple_current) assert mock_csf.call_count == 1 # passed args assert len(mock_csf.call_args[0]) == 2 assert mock_csf.call_args[0][0] is None # smooth_fractions arg - assert mock_csf.call_args[0][1] == 100 # data_size arg + assert mock_csf.call_args[0][1] == simple_voltage.size # data_size arg # passed kwargs assert mock_csf.call_args[1] == {} From b445c75d54873fd747adceb0132ec8063c59520d Mon Sep 17 00:00:00 2001 From: "plasmapy-requirements-bot[bot]" <134649236+plasmapy-requirements-bot[bot]@users.noreply.github.com> Date: Thu, 25 Sep 2025 14:27:47 -0400 Subject: [PATCH 485/521] Update requirements with 'nox -s requirements' (#3111) Co-authored-by: namurphy <8931994+namurphy@users.noreply.github.com> --- uv.lock | 278 +++++++++++++++++++++++++++++--------------------------- 1 file changed, 145 insertions(+), 133 deletions(-) diff --git a/uv.lock b/uv.lock index 3521896d6c..ec209a3f6a 100644 --- a/uv.lock +++ b/uv.lock @@ -80,11 +80,11 @@ wheels = [ [[package]] name = "astropy-iers-data" -version = "0.2025.9.15.0.37.0" +version = "0.2025.9.22.0.37.25" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/37/97/247deecc933ca6a30ed137c19740d3f738df27fdc1de9c0a88cfaba00779/astropy_iers_data-0.2025.9.15.0.37.0.tar.gz", hash = "sha256:33e513dcfdc1b5a7c34e1cc674f4a050b29f93af5ac829e05d868a681d3091d8", size = 1908647, upload-time = "2025-09-15T00:37:46.311Z" } +sdist = { url = "https://files.pythonhosted.org/packages/a4/01/853d80fdff5c6820e3d58fc88134c0cf1cd3fa3bbb982d3ae4cb84766026/astropy_iers_data-0.2025.9.22.0.37.25.tar.gz", hash = "sha256:6808ba4531b339324deb106bce4ecde6df178bcd62e763dba22289dc6e23cb83", size = 1909241, upload-time = "2025-09-22T00:38:11.36Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/03/8c/a556b71e4603d6156814da968b7cefa9bd882e59dc691168584418f4de77/astropy_iers_data-0.2025.9.15.0.37.0-py3-none-any.whl", hash = "sha256:4ea19813150f2d6dfb0257c5e96d14ae9eac6e5a80af27ec79e3aaef8aadfa93", size = 1964242, upload-time = "2025-09-15T00:37:44.298Z" }, + { url = "https://files.pythonhosted.org/packages/57/05/96b98bf096dcda278a8fe74ae2812f4e6ba3402009901e084c173d32b857/astropy_iers_data-0.2025.9.22.0.37.25-py3-none-any.whl", hash = "sha256:0ae01b0b666d545fed6e810e55b152c62ea35bde742ea3c187f974162f143a3c", size = 1964831, upload-time = "2025-09-22T00:38:09.427Z" }, ] [[package]] @@ -402,77 +402,89 @@ wheels = [ [[package]] name = "coverage" -version = "7.10.6" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/14/70/025b179c993f019105b79575ac6edb5e084fb0f0e63f15cdebef4e454fb5/coverage-7.10.6.tar.gz", hash = "sha256:f644a3ae5933a552a29dbb9aa2f90c677a875f80ebea028e5a52a4f429044b90", size = 823736, upload-time = "2025-08-29T15:35:16.668Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/d4/16/2bea27e212c4980753d6d563a0803c150edeaaddb0771a50d2afc410a261/coverage-7.10.6-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c706db3cabb7ceef779de68270150665e710b46d56372455cd741184f3868d8f", size = 217129, upload-time = "2025-08-29T15:33:13.575Z" }, - { url = "https://files.pythonhosted.org/packages/2a/51/e7159e068831ab37e31aac0969d47b8c5ee25b7d307b51e310ec34869315/coverage-7.10.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8e0c38dc289e0508ef68ec95834cb5d2e96fdbe792eaccaa1bccac3966bbadcc", size = 217532, upload-time = "2025-08-29T15:33:14.872Z" }, - { url = "https://files.pythonhosted.org/packages/e7/c0/246ccbea53d6099325d25cd208df94ea435cd55f0db38099dd721efc7a1f/coverage-7.10.6-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:752a3005a1ded28f2f3a6e8787e24f28d6abe176ca64677bcd8d53d6fe2ec08a", size = 247931, upload-time = "2025-08-29T15:33:16.142Z" }, - { url = "https://files.pythonhosted.org/packages/7d/fb/7435ef8ab9b2594a6e3f58505cc30e98ae8b33265d844007737946c59389/coverage-7.10.6-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:689920ecfd60f992cafca4f5477d55720466ad2c7fa29bb56ac8d44a1ac2b47a", size = 249864, upload-time = "2025-08-29T15:33:17.434Z" }, - { url = "https://files.pythonhosted.org/packages/51/f8/d9d64e8da7bcddb094d511154824038833c81e3a039020a9d6539bf303e9/coverage-7.10.6-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ec98435796d2624d6905820a42f82149ee9fc4f2d45c2c5bc5a44481cc50db62", size = 251969, upload-time = "2025-08-29T15:33:18.822Z" }, - { url = "https://files.pythonhosted.org/packages/43/28/c43ba0ef19f446d6463c751315140d8f2a521e04c3e79e5c5fe211bfa430/coverage-7.10.6-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:b37201ce4a458c7a758ecc4efa92fa8ed783c66e0fa3c42ae19fc454a0792153", size = 249659, upload-time = "2025-08-29T15:33:20.407Z" }, - { url = "https://files.pythonhosted.org/packages/79/3e/53635bd0b72beaacf265784508a0b386defc9ab7fad99ff95f79ce9db555/coverage-7.10.6-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:2904271c80898663c810a6b067920a61dd8d38341244a3605bd31ab55250dad5", size = 247714, upload-time = "2025-08-29T15:33:21.751Z" }, - { url = "https://files.pythonhosted.org/packages/4c/55/0964aa87126624e8c159e32b0bc4e84edef78c89a1a4b924d28dd8265625/coverage-7.10.6-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:5aea98383463d6e1fa4e95416d8de66f2d0cb588774ee20ae1b28df826bcb619", size = 248351, upload-time = "2025-08-29T15:33:23.105Z" }, - { url = "https://files.pythonhosted.org/packages/eb/ab/6cfa9dc518c6c8e14a691c54e53a9433ba67336c760607e299bfcf520cb1/coverage-7.10.6-cp311-cp311-win32.whl", hash = "sha256:e3fb1fa01d3598002777dd259c0c2e6d9d5e10e7222976fc8e03992f972a2cba", size = 219562, upload-time = "2025-08-29T15:33:24.717Z" }, - { url = "https://files.pythonhosted.org/packages/5b/18/99b25346690cbc55922e7cfef06d755d4abee803ef335baff0014268eff4/coverage-7.10.6-cp311-cp311-win_amd64.whl", hash = "sha256:f35ed9d945bece26553d5b4c8630453169672bea0050a564456eb88bdffd927e", size = 220453, upload-time = "2025-08-29T15:33:26.482Z" }, - { url = "https://files.pythonhosted.org/packages/d8/ed/81d86648a07ccb124a5cf1f1a7788712b8d7216b593562683cd5c9b0d2c1/coverage-7.10.6-cp311-cp311-win_arm64.whl", hash = "sha256:99e1a305c7765631d74b98bf7dbf54eeea931f975e80f115437d23848ee8c27c", size = 219127, upload-time = "2025-08-29T15:33:27.777Z" }, - { url = "https://files.pythonhosted.org/packages/26/06/263f3305c97ad78aab066d116b52250dd316e74fcc20c197b61e07eb391a/coverage-7.10.6-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:5b2dd6059938063a2c9fee1af729d4f2af28fd1a545e9b7652861f0d752ebcea", size = 217324, upload-time = "2025-08-29T15:33:29.06Z" }, - { url = "https://files.pythonhosted.org/packages/e9/60/1e1ded9a4fe80d843d7d53b3e395c1db3ff32d6c301e501f393b2e6c1c1f/coverage-7.10.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:388d80e56191bf846c485c14ae2bc8898aa3124d9d35903fef7d907780477634", size = 217560, upload-time = "2025-08-29T15:33:30.748Z" }, - { url = "https://files.pythonhosted.org/packages/b8/25/52136173c14e26dfed8b106ed725811bb53c30b896d04d28d74cb64318b3/coverage-7.10.6-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:90cb5b1a4670662719591aa92d0095bb41714970c0b065b02a2610172dbf0af6", size = 249053, upload-time = "2025-08-29T15:33:32.041Z" }, - { url = "https://files.pythonhosted.org/packages/cb/1d/ae25a7dc58fcce8b172d42ffe5313fc267afe61c97fa872b80ee72d9515a/coverage-7.10.6-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:961834e2f2b863a0e14260a9a273aff07ff7818ab6e66d2addf5628590c628f9", size = 251802, upload-time = "2025-08-29T15:33:33.625Z" }, - { url = "https://files.pythonhosted.org/packages/f5/7a/1f561d47743710fe996957ed7c124b421320f150f1d38523d8d9102d3e2a/coverage-7.10.6-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bf9a19f5012dab774628491659646335b1928cfc931bf8d97b0d5918dd58033c", size = 252935, upload-time = "2025-08-29T15:33:34.909Z" }, - { url = "https://files.pythonhosted.org/packages/6c/ad/8b97cd5d28aecdfde792dcbf646bac141167a5cacae2cd775998b45fabb5/coverage-7.10.6-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:99c4283e2a0e147b9c9cc6bc9c96124de9419d6044837e9799763a0e29a7321a", size = 250855, upload-time = "2025-08-29T15:33:36.922Z" }, - { url = "https://files.pythonhosted.org/packages/33/6a/95c32b558d9a61858ff9d79580d3877df3eb5bc9eed0941b1f187c89e143/coverage-7.10.6-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:282b1b20f45df57cc508c1e033403f02283adfb67d4c9c35a90281d81e5c52c5", size = 248974, upload-time = "2025-08-29T15:33:38.175Z" }, - { url = "https://files.pythonhosted.org/packages/0d/9c/8ce95dee640a38e760d5b747c10913e7a06554704d60b41e73fdea6a1ffd/coverage-7.10.6-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:8cdbe264f11afd69841bd8c0d83ca10b5b32853263ee62e6ac6a0ab63895f972", size = 250409, upload-time = "2025-08-29T15:33:39.447Z" }, - { url = "https://files.pythonhosted.org/packages/04/12/7a55b0bdde78a98e2eb2356771fd2dcddb96579e8342bb52aa5bc52e96f0/coverage-7.10.6-cp312-cp312-win32.whl", hash = "sha256:a517feaf3a0a3eca1ee985d8373135cfdedfbba3882a5eab4362bda7c7cf518d", size = 219724, upload-time = "2025-08-29T15:33:41.172Z" }, - { url = "https://files.pythonhosted.org/packages/36/4a/32b185b8b8e327802c9efce3d3108d2fe2d9d31f153a0f7ecfd59c773705/coverage-7.10.6-cp312-cp312-win_amd64.whl", hash = "sha256:856986eadf41f52b214176d894a7de05331117f6035a28ac0016c0f63d887629", size = 220536, upload-time = "2025-08-29T15:33:42.524Z" }, - { url = "https://files.pythonhosted.org/packages/08/3a/d5d8dc703e4998038c3099eaf77adddb00536a3cec08c8dcd556a36a3eb4/coverage-7.10.6-cp312-cp312-win_arm64.whl", hash = "sha256:acf36b8268785aad739443fa2780c16260ee3fa09d12b3a70f772ef100939d80", size = 219171, upload-time = "2025-08-29T15:33:43.974Z" }, - { url = "https://files.pythonhosted.org/packages/bd/e7/917e5953ea29a28c1057729c1d5af9084ab6d9c66217523fd0e10f14d8f6/coverage-7.10.6-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ffea0575345e9ee0144dfe5701aa17f3ba546f8c3bb48db62ae101afb740e7d6", size = 217351, upload-time = "2025-08-29T15:33:45.438Z" }, - { url = "https://files.pythonhosted.org/packages/eb/86/2e161b93a4f11d0ea93f9bebb6a53f113d5d6e416d7561ca41bb0a29996b/coverage-7.10.6-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:95d91d7317cde40a1c249d6b7382750b7e6d86fad9d8eaf4fa3f8f44cf171e80", size = 217600, upload-time = "2025-08-29T15:33:47.269Z" }, - { url = "https://files.pythonhosted.org/packages/0e/66/d03348fdd8df262b3a7fb4ee5727e6e4936e39e2f3a842e803196946f200/coverage-7.10.6-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:3e23dd5408fe71a356b41baa82892772a4cefcf758f2ca3383d2aa39e1b7a003", size = 248600, upload-time = "2025-08-29T15:33:48.953Z" }, - { url = "https://files.pythonhosted.org/packages/73/dd/508420fb47d09d904d962f123221bc249f64b5e56aa93d5f5f7603be475f/coverage-7.10.6-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:0f3f56e4cb573755e96a16501a98bf211f100463d70275759e73f3cbc00d4f27", size = 251206, upload-time = "2025-08-29T15:33:50.697Z" }, - { url = "https://files.pythonhosted.org/packages/e9/1f/9020135734184f439da85c70ea78194c2730e56c2d18aee6e8ff1719d50d/coverage-7.10.6-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:db4a1d897bbbe7339946ffa2fe60c10cc81c43fab8b062d3fcb84188688174a4", size = 252478, upload-time = "2025-08-29T15:33:52.303Z" }, - { url = "https://files.pythonhosted.org/packages/a4/a4/3d228f3942bb5a2051fde28c136eea23a761177dc4ff4ef54533164ce255/coverage-7.10.6-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d8fd7879082953c156d5b13c74aa6cca37f6a6f4747b39538504c3f9c63d043d", size = 250637, upload-time = "2025-08-29T15:33:53.67Z" }, - { url = "https://files.pythonhosted.org/packages/36/e3/293dce8cdb9a83de971637afc59b7190faad60603b40e32635cbd15fbf61/coverage-7.10.6-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:28395ca3f71cd103b8c116333fa9db867f3a3e1ad6a084aa3725ae002b6583bc", size = 248529, upload-time = "2025-08-29T15:33:55.022Z" }, - { url = "https://files.pythonhosted.org/packages/90/26/64eecfa214e80dd1d101e420cab2901827de0e49631d666543d0e53cf597/coverage-7.10.6-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:61c950fc33d29c91b9e18540e1aed7d9f6787cc870a3e4032493bbbe641d12fc", size = 250143, upload-time = "2025-08-29T15:33:56.386Z" }, - { url = "https://files.pythonhosted.org/packages/3e/70/bd80588338f65ea5b0d97e424b820fb4068b9cfb9597fbd91963086e004b/coverage-7.10.6-cp313-cp313-win32.whl", hash = "sha256:160c00a5e6b6bdf4e5984b0ef21fc860bc94416c41b7df4d63f536d17c38902e", size = 219770, upload-time = "2025-08-29T15:33:58.063Z" }, - { url = "https://files.pythonhosted.org/packages/a7/14/0b831122305abcc1060c008f6c97bbdc0a913ab47d65070a01dc50293c2b/coverage-7.10.6-cp313-cp313-win_amd64.whl", hash = "sha256:628055297f3e2aa181464c3808402887643405573eb3d9de060d81531fa79d32", size = 220566, upload-time = "2025-08-29T15:33:59.766Z" }, - { url = "https://files.pythonhosted.org/packages/83/c6/81a83778c1f83f1a4a168ed6673eeedc205afb562d8500175292ca64b94e/coverage-7.10.6-cp313-cp313-win_arm64.whl", hash = "sha256:df4ec1f8540b0bcbe26ca7dd0f541847cc8a108b35596f9f91f59f0c060bfdd2", size = 219195, upload-time = "2025-08-29T15:34:01.191Z" }, - { url = "https://files.pythonhosted.org/packages/d7/1c/ccccf4bf116f9517275fa85047495515add43e41dfe8e0bef6e333c6b344/coverage-7.10.6-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:c9a8b7a34a4de3ed987f636f71881cd3b8339f61118b1aa311fbda12741bff0b", size = 218059, upload-time = "2025-08-29T15:34:02.91Z" }, - { url = "https://files.pythonhosted.org/packages/92/97/8a3ceff833d27c7492af4f39d5da6761e9ff624831db9e9f25b3886ddbca/coverage-7.10.6-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:8dd5af36092430c2b075cee966719898f2ae87b636cefb85a653f1d0ba5d5393", size = 218287, upload-time = "2025-08-29T15:34:05.106Z" }, - { url = "https://files.pythonhosted.org/packages/92/d8/50b4a32580cf41ff0423777a2791aaf3269ab60c840b62009aec12d3970d/coverage-7.10.6-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:b0353b0f0850d49ada66fdd7d0c7cdb0f86b900bb9e367024fd14a60cecc1e27", size = 259625, upload-time = "2025-08-29T15:34:06.575Z" }, - { url = "https://files.pythonhosted.org/packages/7e/7e/6a7df5a6fb440a0179d94a348eb6616ed4745e7df26bf2a02bc4db72c421/coverage-7.10.6-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:d6b9ae13d5d3e8aeca9ca94198aa7b3ebbc5acfada557d724f2a1f03d2c0b0df", size = 261801, upload-time = "2025-08-29T15:34:08.006Z" }, - { url = "https://files.pythonhosted.org/packages/3a/4c/a270a414f4ed5d196b9d3d67922968e768cd971d1b251e1b4f75e9362f75/coverage-7.10.6-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:675824a363cc05781b1527b39dc2587b8984965834a748177ee3c37b64ffeafb", size = 264027, upload-time = "2025-08-29T15:34:09.806Z" }, - { url = "https://files.pythonhosted.org/packages/9c/8b/3210d663d594926c12f373c5370bf1e7c5c3a427519a8afa65b561b9a55c/coverage-7.10.6-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:692d70ea725f471a547c305f0d0fc6a73480c62fb0da726370c088ab21aed282", size = 261576, upload-time = "2025-08-29T15:34:11.585Z" }, - { url = "https://files.pythonhosted.org/packages/72/d0/e1961eff67e9e1dba3fc5eb7a4caf726b35a5b03776892da8d79ec895775/coverage-7.10.6-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:851430a9a361c7a8484a36126d1d0ff8d529d97385eacc8dfdc9bfc8c2d2cbe4", size = 259341, upload-time = "2025-08-29T15:34:13.159Z" }, - { url = "https://files.pythonhosted.org/packages/3a/06/d6478d152cd189b33eac691cba27a40704990ba95de49771285f34a5861e/coverage-7.10.6-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:d9369a23186d189b2fc95cc08b8160ba242057e887d766864f7adf3c46b2df21", size = 260468, upload-time = "2025-08-29T15:34:14.571Z" }, - { url = "https://files.pythonhosted.org/packages/ed/73/737440247c914a332f0b47f7598535b29965bf305e19bbc22d4c39615d2b/coverage-7.10.6-cp313-cp313t-win32.whl", hash = "sha256:92be86fcb125e9bda0da7806afd29a3fd33fdf58fba5d60318399adf40bf37d0", size = 220429, upload-time = "2025-08-29T15:34:16.394Z" }, - { url = "https://files.pythonhosted.org/packages/bd/76/b92d3214740f2357ef4a27c75a526eb6c28f79c402e9f20a922c295c05e2/coverage-7.10.6-cp313-cp313t-win_amd64.whl", hash = "sha256:6b3039e2ca459a70c79523d39347d83b73f2f06af5624905eba7ec34d64d80b5", size = 221493, upload-time = "2025-08-29T15:34:17.835Z" }, - { url = "https://files.pythonhosted.org/packages/fc/8e/6dcb29c599c8a1f654ec6cb68d76644fe635513af16e932d2d4ad1e5ac6e/coverage-7.10.6-cp313-cp313t-win_arm64.whl", hash = "sha256:3fb99d0786fe17b228eab663d16bee2288e8724d26a199c29325aac4b0319b9b", size = 219757, upload-time = "2025-08-29T15:34:19.248Z" }, - { url = "https://files.pythonhosted.org/packages/d3/aa/76cf0b5ec00619ef208da4689281d48b57f2c7fde883d14bf9441b74d59f/coverage-7.10.6-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:6008a021907be8c4c02f37cdc3ffb258493bdebfeaf9a839f9e71dfdc47b018e", size = 217331, upload-time = "2025-08-29T15:34:20.846Z" }, - { url = "https://files.pythonhosted.org/packages/65/91/8e41b8c7c505d398d7730206f3cbb4a875a35ca1041efc518051bfce0f6b/coverage-7.10.6-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:5e75e37f23eb144e78940b40395b42f2321951206a4f50e23cfd6e8a198d3ceb", size = 217607, upload-time = "2025-08-29T15:34:22.433Z" }, - { url = "https://files.pythonhosted.org/packages/87/7f/f718e732a423d442e6616580a951b8d1ec3575ea48bcd0e2228386805e79/coverage-7.10.6-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:0f7cb359a448e043c576f0da00aa8bfd796a01b06aa610ca453d4dde09cc1034", size = 248663, upload-time = "2025-08-29T15:34:24.425Z" }, - { url = "https://files.pythonhosted.org/packages/e6/52/c1106120e6d801ac03e12b5285e971e758e925b6f82ee9b86db3aa10045d/coverage-7.10.6-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:c68018e4fc4e14b5668f1353b41ccf4bc83ba355f0e1b3836861c6f042d89ac1", size = 251197, upload-time = "2025-08-29T15:34:25.906Z" }, - { url = "https://files.pythonhosted.org/packages/3d/ec/3a8645b1bb40e36acde9c0609f08942852a4af91a937fe2c129a38f2d3f5/coverage-7.10.6-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cd4b2b0707fc55afa160cd5fc33b27ccbf75ca11d81f4ec9863d5793fc6df56a", size = 252551, upload-time = "2025-08-29T15:34:27.337Z" }, - { url = "https://files.pythonhosted.org/packages/a1/70/09ecb68eeb1155b28a1d16525fd3a9b65fbe75337311a99830df935d62b6/coverage-7.10.6-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:4cec13817a651f8804a86e4f79d815b3b28472c910e099e4d5a0e8a3b6a1d4cb", size = 250553, upload-time = "2025-08-29T15:34:29.065Z" }, - { url = "https://files.pythonhosted.org/packages/c6/80/47df374b893fa812e953b5bc93dcb1427a7b3d7a1a7d2db33043d17f74b9/coverage-7.10.6-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:f2a6a8e06bbda06f78739f40bfb56c45d14eb8249d0f0ea6d4b3d48e1f7c695d", size = 248486, upload-time = "2025-08-29T15:34:30.897Z" }, - { url = "https://files.pythonhosted.org/packages/4a/65/9f98640979ecee1b0d1a7164b589de720ddf8100d1747d9bbdb84be0c0fb/coverage-7.10.6-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:081b98395ced0d9bcf60ada7661a0b75f36b78b9d7e39ea0790bb4ed8da14747", size = 249981, upload-time = "2025-08-29T15:34:32.365Z" }, - { url = "https://files.pythonhosted.org/packages/1f/55/eeb6603371e6629037f47bd25bef300387257ed53a3c5fdb159b7ac8c651/coverage-7.10.6-cp314-cp314-win32.whl", hash = "sha256:6937347c5d7d069ee776b2bf4e1212f912a9f1f141a429c475e6089462fcecc5", size = 220054, upload-time = "2025-08-29T15:34:34.124Z" }, - { url = "https://files.pythonhosted.org/packages/15/d1/a0912b7611bc35412e919a2cd59ae98e7ea3b475e562668040a43fb27897/coverage-7.10.6-cp314-cp314-win_amd64.whl", hash = "sha256:adec1d980fa07e60b6ef865f9e5410ba760e4e1d26f60f7e5772c73b9a5b0713", size = 220851, upload-time = "2025-08-29T15:34:35.651Z" }, - { url = "https://files.pythonhosted.org/packages/ef/2d/11880bb8ef80a45338e0b3e0725e4c2d73ffbb4822c29d987078224fd6a5/coverage-7.10.6-cp314-cp314-win_arm64.whl", hash = "sha256:a80f7aef9535442bdcf562e5a0d5a5538ce8abe6bb209cfbf170c462ac2c2a32", size = 219429, upload-time = "2025-08-29T15:34:37.16Z" }, - { url = "https://files.pythonhosted.org/packages/83/c0/1f00caad775c03a700146f55536ecd097a881ff08d310a58b353a1421be0/coverage-7.10.6-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:0de434f4fbbe5af4fa7989521c655c8c779afb61c53ab561b64dcee6149e4c65", size = 218080, upload-time = "2025-08-29T15:34:38.919Z" }, - { url = "https://files.pythonhosted.org/packages/a9/c4/b1c5d2bd7cc412cbeb035e257fd06ed4e3e139ac871d16a07434e145d18d/coverage-7.10.6-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:6e31b8155150c57e5ac43ccd289d079eb3f825187d7c66e755a055d2c85794c6", size = 218293, upload-time = "2025-08-29T15:34:40.425Z" }, - { url = "https://files.pythonhosted.org/packages/3f/07/4468d37c94724bf6ec354e4ec2f205fda194343e3e85fd2e59cec57e6a54/coverage-7.10.6-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:98cede73eb83c31e2118ae8d379c12e3e42736903a8afcca92a7218e1f2903b0", size = 259800, upload-time = "2025-08-29T15:34:41.996Z" }, - { url = "https://files.pythonhosted.org/packages/82/d8/f8fb351be5fee31690cd8da768fd62f1cfab33c31d9f7baba6cd8960f6b8/coverage-7.10.6-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:f863c08f4ff6b64fa8045b1e3da480f5374779ef187f07b82e0538c68cb4ff8e", size = 261965, upload-time = "2025-08-29T15:34:43.61Z" }, - { url = "https://files.pythonhosted.org/packages/e8/70/65d4d7cfc75c5c6eb2fed3ee5cdf420fd8ae09c4808723a89a81d5b1b9c3/coverage-7.10.6-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2b38261034fda87be356f2c3f42221fdb4171c3ce7658066ae449241485390d5", size = 264220, upload-time = "2025-08-29T15:34:45.387Z" }, - { url = "https://files.pythonhosted.org/packages/98/3c/069df106d19024324cde10e4ec379fe2fb978017d25e97ebee23002fbadf/coverage-7.10.6-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:0e93b1476b79eae849dc3872faeb0bf7948fd9ea34869590bc16a2a00b9c82a7", size = 261660, upload-time = "2025-08-29T15:34:47.288Z" }, - { url = "https://files.pythonhosted.org/packages/fc/8a/2974d53904080c5dc91af798b3a54a4ccb99a45595cc0dcec6eb9616a57d/coverage-7.10.6-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:ff8a991f70f4c0cf53088abf1e3886edcc87d53004c7bb94e78650b4d3dac3b5", size = 259417, upload-time = "2025-08-29T15:34:48.779Z" }, - { url = "https://files.pythonhosted.org/packages/30/38/9616a6b49c686394b318974d7f6e08f38b8af2270ce7488e879888d1e5db/coverage-7.10.6-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:ac765b026c9f33044419cbba1da913cfb82cca1b60598ac1c7a5ed6aac4621a0", size = 260567, upload-time = "2025-08-29T15:34:50.718Z" }, - { url = "https://files.pythonhosted.org/packages/76/16/3ed2d6312b371a8cf804abf4e14895b70e4c3491c6e53536d63fd0958a8d/coverage-7.10.6-cp314-cp314t-win32.whl", hash = "sha256:441c357d55f4936875636ef2cfb3bee36e466dcf50df9afbd398ce79dba1ebb7", size = 220831, upload-time = "2025-08-29T15:34:52.653Z" }, - { url = "https://files.pythonhosted.org/packages/d5/e5/d38d0cb830abede2adb8b147770d2a3d0e7fecc7228245b9b1ae6c24930a/coverage-7.10.6-cp314-cp314t-win_amd64.whl", hash = "sha256:073711de3181b2e204e4870ac83a7c4853115b42e9cd4d145f2231e12d670930", size = 221950, upload-time = "2025-08-29T15:34:54.212Z" }, - { url = "https://files.pythonhosted.org/packages/f4/51/e48e550f6279349895b0ffcd6d2a690e3131ba3a7f4eafccc141966d4dea/coverage-7.10.6-cp314-cp314t-win_arm64.whl", hash = "sha256:137921f2bac5559334ba66122b753db6dc5d1cf01eb7b64eb412bb0d064ef35b", size = 219969, upload-time = "2025-08-29T15:34:55.83Z" }, - { url = "https://files.pythonhosted.org/packages/44/0c/50db5379b615854b5cf89146f8f5bd1d5a9693d7f3a987e269693521c404/coverage-7.10.6-py3-none-any.whl", hash = "sha256:92c4ecf6bf11b2e85fd4d8204814dc26e6a19f0c9d938c207c5cb0eadfcabbe3", size = 208986, upload-time = "2025-08-29T15:35:14.506Z" }, +version = "7.10.7" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/51/26/d22c300112504f5f9a9fd2297ce33c35f3d353e4aeb987c8419453b2a7c2/coverage-7.10.7.tar.gz", hash = "sha256:f4ab143ab113be368a3e9b795f9cd7906c5ef407d6173fe9675a902e1fffc239", size = 827704, upload-time = "2025-09-21T20:03:56.815Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d2/5d/c1a17867b0456f2e9ce2d8d4708a4c3a089947d0bec9c66cdf60c9e7739f/coverage-7.10.7-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a609f9c93113be646f44c2a0256d6ea375ad047005d7f57a5c15f614dc1b2f59", size = 218102, upload-time = "2025-09-21T20:01:16.089Z" }, + { url = "https://files.pythonhosted.org/packages/54/f0/514dcf4b4e3698b9a9077f084429681bf3aad2b4a72578f89d7f643eb506/coverage-7.10.7-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:65646bb0359386e07639c367a22cf9b5bf6304e8630b565d0626e2bdf329227a", size = 218505, upload-time = "2025-09-21T20:01:17.788Z" }, + { url = "https://files.pythonhosted.org/packages/20/f6/9626b81d17e2a4b25c63ac1b425ff307ecdeef03d67c9a147673ae40dc36/coverage-7.10.7-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:5f33166f0dfcce728191f520bd2692914ec70fac2713f6bf3ce59c3deacb4699", size = 248898, upload-time = "2025-09-21T20:01:19.488Z" }, + { url = "https://files.pythonhosted.org/packages/b0/ef/bd8e719c2f7417ba03239052e099b76ea1130ac0cbb183ee1fcaa58aaff3/coverage-7.10.7-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:35f5e3f9e455bb17831876048355dca0f758b6df22f49258cb5a91da23ef437d", size = 250831, upload-time = "2025-09-21T20:01:20.817Z" }, + { url = "https://files.pythonhosted.org/packages/a5/b6/bf054de41ec948b151ae2b79a55c107f5760979538f5fb80c195f2517718/coverage-7.10.7-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4da86b6d62a496e908ac2898243920c7992499c1712ff7c2b6d837cc69d9467e", size = 252937, upload-time = "2025-09-21T20:01:22.171Z" }, + { url = "https://files.pythonhosted.org/packages/0f/e5/3860756aa6f9318227443c6ce4ed7bf9e70bb7f1447a0353f45ac5c7974b/coverage-7.10.7-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:6b8b09c1fad947c84bbbc95eca841350fad9cbfa5a2d7ca88ac9f8d836c92e23", size = 249021, upload-time = "2025-09-21T20:01:23.907Z" }, + { url = "https://files.pythonhosted.org/packages/26/0f/bd08bd042854f7fd07b45808927ebcce99a7ed0f2f412d11629883517ac2/coverage-7.10.7-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:4376538f36b533b46f8971d3a3e63464f2c7905c9800db97361c43a2b14792ab", size = 250626, upload-time = "2025-09-21T20:01:25.721Z" }, + { url = "https://files.pythonhosted.org/packages/8e/a7/4777b14de4abcc2e80c6b1d430f5d51eb18ed1d75fca56cbce5f2db9b36e/coverage-7.10.7-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:121da30abb574f6ce6ae09840dae322bef734480ceafe410117627aa54f76d82", size = 248682, upload-time = "2025-09-21T20:01:27.105Z" }, + { url = "https://files.pythonhosted.org/packages/34/72/17d082b00b53cd45679bad682fac058b87f011fd8b9fe31d77f5f8d3a4e4/coverage-7.10.7-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:88127d40df529336a9836870436fc2751c339fbaed3a836d42c93f3e4bd1d0a2", size = 248402, upload-time = "2025-09-21T20:01:28.629Z" }, + { url = "https://files.pythonhosted.org/packages/81/7a/92367572eb5bdd6a84bfa278cc7e97db192f9f45b28c94a9ca1a921c3577/coverage-7.10.7-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ba58bbcd1b72f136080c0bccc2400d66cc6115f3f906c499013d065ac33a4b61", size = 249320, upload-time = "2025-09-21T20:01:30.004Z" }, + { url = "https://files.pythonhosted.org/packages/2f/88/a23cc185f6a805dfc4fdf14a94016835eeb85e22ac3a0e66d5e89acd6462/coverage-7.10.7-cp311-cp311-win32.whl", hash = "sha256:972b9e3a4094b053a4e46832b4bc829fc8a8d347160eb39d03f1690316a99c14", size = 220536, upload-time = "2025-09-21T20:01:32.184Z" }, + { url = "https://files.pythonhosted.org/packages/fe/ef/0b510a399dfca17cec7bc2f05ad8bd78cf55f15c8bc9a73ab20c5c913c2e/coverage-7.10.7-cp311-cp311-win_amd64.whl", hash = "sha256:a7b55a944a7f43892e28ad4bc0561dfd5f0d73e605d1aa5c3c976b52aea121d2", size = 221425, upload-time = "2025-09-21T20:01:33.557Z" }, + { url = "https://files.pythonhosted.org/packages/51/7f/023657f301a276e4ba1850f82749bc136f5a7e8768060c2e5d9744a22951/coverage-7.10.7-cp311-cp311-win_arm64.whl", hash = "sha256:736f227fb490f03c6488f9b6d45855f8e0fd749c007f9303ad30efab0e73c05a", size = 220103, upload-time = "2025-09-21T20:01:34.929Z" }, + { url = "https://files.pythonhosted.org/packages/13/e4/eb12450f71b542a53972d19117ea5a5cea1cab3ac9e31b0b5d498df1bd5a/coverage-7.10.7-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7bb3b9ddb87ef7725056572368040c32775036472d5a033679d1fa6c8dc08417", size = 218290, upload-time = "2025-09-21T20:01:36.455Z" }, + { url = "https://files.pythonhosted.org/packages/37/66/593f9be12fc19fb36711f19a5371af79a718537204d16ea1d36f16bd78d2/coverage-7.10.7-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:18afb24843cbc175687225cab1138c95d262337f5473512010e46831aa0c2973", size = 218515, upload-time = "2025-09-21T20:01:37.982Z" }, + { url = "https://files.pythonhosted.org/packages/66/80/4c49f7ae09cafdacc73fbc30949ffe77359635c168f4e9ff33c9ebb07838/coverage-7.10.7-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:399a0b6347bcd3822be369392932884b8216d0944049ae22925631a9b3d4ba4c", size = 250020, upload-time = "2025-09-21T20:01:39.617Z" }, + { url = "https://files.pythonhosted.org/packages/a6/90/a64aaacab3b37a17aaedd83e8000142561a29eb262cede42d94a67f7556b/coverage-7.10.7-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:314f2c326ded3f4b09be11bc282eb2fc861184bc95748ae67b360ac962770be7", size = 252769, upload-time = "2025-09-21T20:01:41.341Z" }, + { url = "https://files.pythonhosted.org/packages/98/2e/2dda59afd6103b342e096f246ebc5f87a3363b5412609946c120f4e7750d/coverage-7.10.7-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c41e71c9cfb854789dee6fc51e46743a6d138b1803fab6cb860af43265b42ea6", size = 253901, upload-time = "2025-09-21T20:01:43.042Z" }, + { url = "https://files.pythonhosted.org/packages/53/dc/8d8119c9051d50f3119bb4a75f29f1e4a6ab9415cd1fa8bf22fcc3fb3b5f/coverage-7.10.7-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:bc01f57ca26269c2c706e838f6422e2a8788e41b3e3c65e2f41148212e57cd59", size = 250413, upload-time = "2025-09-21T20:01:44.469Z" }, + { url = "https://files.pythonhosted.org/packages/98/b3/edaff9c5d79ee4d4b6d3fe046f2b1d799850425695b789d491a64225d493/coverage-7.10.7-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a6442c59a8ac8b85812ce33bc4d05bde3fb22321fa8294e2a5b487c3505f611b", size = 251820, upload-time = "2025-09-21T20:01:45.915Z" }, + { url = "https://files.pythonhosted.org/packages/11/25/9a0728564bb05863f7e513e5a594fe5ffef091b325437f5430e8cfb0d530/coverage-7.10.7-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:78a384e49f46b80fb4c901d52d92abe098e78768ed829c673fbb53c498bef73a", size = 249941, upload-time = "2025-09-21T20:01:47.296Z" }, + { url = "https://files.pythonhosted.org/packages/e0/fd/ca2650443bfbef5b0e74373aac4df67b08180d2f184b482c41499668e258/coverage-7.10.7-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:5e1e9802121405ede4b0133aa4340ad8186a1d2526de5b7c3eca519db7bb89fb", size = 249519, upload-time = "2025-09-21T20:01:48.73Z" }, + { url = "https://files.pythonhosted.org/packages/24/79/f692f125fb4299b6f963b0745124998ebb8e73ecdfce4ceceb06a8c6bec5/coverage-7.10.7-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:d41213ea25a86f69efd1575073d34ea11aabe075604ddf3d148ecfec9e1e96a1", size = 251375, upload-time = "2025-09-21T20:01:50.529Z" }, + { url = "https://files.pythonhosted.org/packages/5e/75/61b9bbd6c7d24d896bfeec57acba78e0f8deac68e6baf2d4804f7aae1f88/coverage-7.10.7-cp312-cp312-win32.whl", hash = "sha256:77eb4c747061a6af8d0f7bdb31f1e108d172762ef579166ec84542f711d90256", size = 220699, upload-time = "2025-09-21T20:01:51.941Z" }, + { url = "https://files.pythonhosted.org/packages/ca/f3/3bf7905288b45b075918d372498f1cf845b5b579b723c8fd17168018d5f5/coverage-7.10.7-cp312-cp312-win_amd64.whl", hash = "sha256:f51328ffe987aecf6d09f3cd9d979face89a617eacdaea43e7b3080777f647ba", size = 221512, upload-time = "2025-09-21T20:01:53.481Z" }, + { url = "https://files.pythonhosted.org/packages/5c/44/3e32dbe933979d05cf2dac5e697c8599cfe038aaf51223ab901e208d5a62/coverage-7.10.7-cp312-cp312-win_arm64.whl", hash = "sha256:bda5e34f8a75721c96085903c6f2197dc398c20ffd98df33f866a9c8fd95f4bf", size = 220147, upload-time = "2025-09-21T20:01:55.2Z" }, + { url = "https://files.pythonhosted.org/packages/9a/94/b765c1abcb613d103b64fcf10395f54d69b0ef8be6a0dd9c524384892cc7/coverage-7.10.7-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:981a651f543f2854abd3b5fcb3263aac581b18209be49863ba575de6edf4c14d", size = 218320, upload-time = "2025-09-21T20:01:56.629Z" }, + { url = "https://files.pythonhosted.org/packages/72/4f/732fff31c119bb73b35236dd333030f32c4bfe909f445b423e6c7594f9a2/coverage-7.10.7-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:73ab1601f84dc804f7812dc297e93cd99381162da39c47040a827d4e8dafe63b", size = 218575, upload-time = "2025-09-21T20:01:58.203Z" }, + { url = "https://files.pythonhosted.org/packages/87/02/ae7e0af4b674be47566707777db1aa375474f02a1d64b9323e5813a6cdd5/coverage-7.10.7-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:a8b6f03672aa6734e700bbcd65ff050fd19cddfec4b031cc8cf1c6967de5a68e", size = 249568, upload-time = "2025-09-21T20:01:59.748Z" }, + { url = "https://files.pythonhosted.org/packages/a2/77/8c6d22bf61921a59bce5471c2f1f7ac30cd4ac50aadde72b8c48d5727902/coverage-7.10.7-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:10b6ba00ab1132a0ce4428ff68cf50a25efd6840a42cdf4239c9b99aad83be8b", size = 252174, upload-time = "2025-09-21T20:02:01.192Z" }, + { url = "https://files.pythonhosted.org/packages/b1/20/b6ea4f69bbb52dac0aebd62157ba6a9dddbfe664f5af8122dac296c3ee15/coverage-7.10.7-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c79124f70465a150e89340de5963f936ee97097d2ef76c869708c4248c63ca49", size = 253447, upload-time = "2025-09-21T20:02:02.701Z" }, + { url = "https://files.pythonhosted.org/packages/f9/28/4831523ba483a7f90f7b259d2018fef02cb4d5b90bc7c1505d6e5a84883c/coverage-7.10.7-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:69212fbccdbd5b0e39eac4067e20a4a5256609e209547d86f740d68ad4f04911", size = 249779, upload-time = "2025-09-21T20:02:04.185Z" }, + { url = "https://files.pythonhosted.org/packages/a7/9f/4331142bc98c10ca6436d2d620c3e165f31e6c58d43479985afce6f3191c/coverage-7.10.7-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:7ea7c6c9d0d286d04ed3541747e6597cbe4971f22648b68248f7ddcd329207f0", size = 251604, upload-time = "2025-09-21T20:02:06.034Z" }, + { url = "https://files.pythonhosted.org/packages/ce/60/bda83b96602036b77ecf34e6393a3836365481b69f7ed7079ab85048202b/coverage-7.10.7-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:b9be91986841a75042b3e3243d0b3cb0b2434252b977baaf0cd56e960fe1e46f", size = 249497, upload-time = "2025-09-21T20:02:07.619Z" }, + { url = "https://files.pythonhosted.org/packages/5f/af/152633ff35b2af63977edd835d8e6430f0caef27d171edf2fc76c270ef31/coverage-7.10.7-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:b281d5eca50189325cfe1f365fafade89b14b4a78d9b40b05ddd1fc7d2a10a9c", size = 249350, upload-time = "2025-09-21T20:02:10.34Z" }, + { url = "https://files.pythonhosted.org/packages/9d/71/d92105d122bd21cebba877228990e1646d862e34a98bb3374d3fece5a794/coverage-7.10.7-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:99e4aa63097ab1118e75a848a28e40d68b08a5e19ce587891ab7fd04475e780f", size = 251111, upload-time = "2025-09-21T20:02:12.122Z" }, + { url = "https://files.pythonhosted.org/packages/a2/9e/9fdb08f4bf476c912f0c3ca292e019aab6712c93c9344a1653986c3fd305/coverage-7.10.7-cp313-cp313-win32.whl", hash = "sha256:dc7c389dce432500273eaf48f410b37886be9208b2dd5710aaf7c57fd442c698", size = 220746, upload-time = "2025-09-21T20:02:13.919Z" }, + { url = "https://files.pythonhosted.org/packages/b1/b1/a75fd25df44eab52d1931e89980d1ada46824c7a3210be0d3c88a44aaa99/coverage-7.10.7-cp313-cp313-win_amd64.whl", hash = "sha256:cac0fdca17b036af3881a9d2729a850b76553f3f716ccb0360ad4dbc06b3b843", size = 221541, upload-time = "2025-09-21T20:02:15.57Z" }, + { url = "https://files.pythonhosted.org/packages/14/3a/d720d7c989562a6e9a14b2c9f5f2876bdb38e9367126d118495b89c99c37/coverage-7.10.7-cp313-cp313-win_arm64.whl", hash = "sha256:4b6f236edf6e2f9ae8fcd1332da4e791c1b6ba0dc16a2dc94590ceccb482e546", size = 220170, upload-time = "2025-09-21T20:02:17.395Z" }, + { url = "https://files.pythonhosted.org/packages/bb/22/e04514bf2a735d8b0add31d2b4ab636fc02370730787c576bb995390d2d5/coverage-7.10.7-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:a0ec07fd264d0745ee396b666d47cef20875f4ff2375d7c4f58235886cc1ef0c", size = 219029, upload-time = "2025-09-21T20:02:18.936Z" }, + { url = "https://files.pythonhosted.org/packages/11/0b/91128e099035ece15da3445d9015e4b4153a6059403452d324cbb0a575fa/coverage-7.10.7-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:dd5e856ebb7bfb7672b0086846db5afb4567a7b9714b8a0ebafd211ec7ce6a15", size = 219259, upload-time = "2025-09-21T20:02:20.44Z" }, + { url = "https://files.pythonhosted.org/packages/8b/51/66420081e72801536a091a0c8f8c1f88a5c4bf7b9b1bdc6222c7afe6dc9b/coverage-7.10.7-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:f57b2a3c8353d3e04acf75b3fed57ba41f5c0646bbf1d10c7c282291c97936b4", size = 260592, upload-time = "2025-09-21T20:02:22.313Z" }, + { url = "https://files.pythonhosted.org/packages/5d/22/9b8d458c2881b22df3db5bb3e7369e63d527d986decb6c11a591ba2364f7/coverage-7.10.7-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:1ef2319dd15a0b009667301a3f84452a4dc6fddfd06b0c5c53ea472d3989fbf0", size = 262768, upload-time = "2025-09-21T20:02:24.287Z" }, + { url = "https://files.pythonhosted.org/packages/f7/08/16bee2c433e60913c610ea200b276e8eeef084b0d200bdcff69920bd5828/coverage-7.10.7-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:83082a57783239717ceb0ad584de3c69cf581b2a95ed6bf81ea66034f00401c0", size = 264995, upload-time = "2025-09-21T20:02:26.133Z" }, + { url = "https://files.pythonhosted.org/packages/20/9d/e53eb9771d154859b084b90201e5221bca7674ba449a17c101a5031d4054/coverage-7.10.7-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:50aa94fb1fb9a397eaa19c0d5ec15a5edd03a47bf1a3a6111a16b36e190cff65", size = 259546, upload-time = "2025-09-21T20:02:27.716Z" }, + { url = "https://files.pythonhosted.org/packages/ad/b0/69bc7050f8d4e56a89fb550a1577d5d0d1db2278106f6f626464067b3817/coverage-7.10.7-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:2120043f147bebb41c85b97ac45dd173595ff14f2a584f2963891cbcc3091541", size = 262544, upload-time = "2025-09-21T20:02:29.216Z" }, + { url = "https://files.pythonhosted.org/packages/ef/4b/2514b060dbd1bc0aaf23b852c14bb5818f244c664cb16517feff6bb3a5ab/coverage-7.10.7-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:2fafd773231dd0378fdba66d339f84904a8e57a262f583530f4f156ab83863e6", size = 260308, upload-time = "2025-09-21T20:02:31.226Z" }, + { url = "https://files.pythonhosted.org/packages/54/78/7ba2175007c246d75e496f64c06e94122bdb914790a1285d627a918bd271/coverage-7.10.7-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:0b944ee8459f515f28b851728ad224fa2d068f1513ef6b7ff1efafeb2185f999", size = 258920, upload-time = "2025-09-21T20:02:32.823Z" }, + { url = "https://files.pythonhosted.org/packages/c0/b3/fac9f7abbc841409b9a410309d73bfa6cfb2e51c3fada738cb607ce174f8/coverage-7.10.7-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:4b583b97ab2e3efe1b3e75248a9b333bd3f8b0b1b8e5b45578e05e5850dfb2c2", size = 261434, upload-time = "2025-09-21T20:02:34.86Z" }, + { url = "https://files.pythonhosted.org/packages/ee/51/a03bec00d37faaa891b3ff7387192cef20f01604e5283a5fabc95346befa/coverage-7.10.7-cp313-cp313t-win32.whl", hash = "sha256:2a78cd46550081a7909b3329e2266204d584866e8d97b898cd7fb5ac8d888b1a", size = 221403, upload-time = "2025-09-21T20:02:37.034Z" }, + { url = "https://files.pythonhosted.org/packages/53/22/3cf25d614e64bf6d8e59c7c669b20d6d940bb337bdee5900b9ca41c820bb/coverage-7.10.7-cp313-cp313t-win_amd64.whl", hash = "sha256:33a5e6396ab684cb43dc7befa386258acb2d7fae7f67330ebb85ba4ea27938eb", size = 222469, upload-time = "2025-09-21T20:02:39.011Z" }, + { url = "https://files.pythonhosted.org/packages/49/a1/00164f6d30d8a01c3c9c48418a7a5be394de5349b421b9ee019f380df2a0/coverage-7.10.7-cp313-cp313t-win_arm64.whl", hash = "sha256:86b0e7308289ddde73d863b7683f596d8d21c7d8664ce1dee061d0bcf3fbb4bb", size = 220731, upload-time = "2025-09-21T20:02:40.939Z" }, + { url = "https://files.pythonhosted.org/packages/23/9c/5844ab4ca6a4dd97a1850e030a15ec7d292b5c5cb93082979225126e35dd/coverage-7.10.7-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:b06f260b16ead11643a5a9f955bd4b5fd76c1a4c6796aeade8520095b75de520", size = 218302, upload-time = "2025-09-21T20:02:42.527Z" }, + { url = "https://files.pythonhosted.org/packages/f0/89/673f6514b0961d1f0e20ddc242e9342f6da21eaba3489901b565c0689f34/coverage-7.10.7-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:212f8f2e0612778f09c55dd4872cb1f64a1f2b074393d139278ce902064d5b32", size = 218578, upload-time = "2025-09-21T20:02:44.468Z" }, + { url = "https://files.pythonhosted.org/packages/05/e8/261cae479e85232828fb17ad536765c88dd818c8470aca690b0ac6feeaa3/coverage-7.10.7-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:3445258bcded7d4aa630ab8296dea4d3f15a255588dd535f980c193ab6b95f3f", size = 249629, upload-time = "2025-09-21T20:02:46.503Z" }, + { url = "https://files.pythonhosted.org/packages/82/62/14ed6546d0207e6eda876434e3e8475a3e9adbe32110ce896c9e0c06bb9a/coverage-7.10.7-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:bb45474711ba385c46a0bfe696c695a929ae69ac636cda8f532be9e8c93d720a", size = 252162, upload-time = "2025-09-21T20:02:48.689Z" }, + { url = "https://files.pythonhosted.org/packages/ff/49/07f00db9ac6478e4358165a08fb41b469a1b053212e8a00cb02f0d27a05f/coverage-7.10.7-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:813922f35bd800dca9994c5971883cbc0d291128a5de6b167c7aa697fcf59360", size = 253517, upload-time = "2025-09-21T20:02:50.31Z" }, + { url = "https://files.pythonhosted.org/packages/a2/59/c5201c62dbf165dfbc91460f6dbbaa85a8b82cfa6131ac45d6c1bfb52deb/coverage-7.10.7-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:93c1b03552081b2a4423091d6fb3787265b8f86af404cff98d1b5342713bdd69", size = 249632, upload-time = "2025-09-21T20:02:51.971Z" }, + { url = "https://files.pythonhosted.org/packages/07/ae/5920097195291a51fb00b3a70b9bbd2edbfe3c84876a1762bd1ef1565ebc/coverage-7.10.7-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:cc87dd1b6eaf0b848eebb1c86469b9f72a1891cb42ac7adcfbce75eadb13dd14", size = 251520, upload-time = "2025-09-21T20:02:53.858Z" }, + { url = "https://files.pythonhosted.org/packages/b9/3c/a815dde77a2981f5743a60b63df31cb322c944843e57dbd579326625a413/coverage-7.10.7-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:39508ffda4f343c35f3236fe8d1a6634a51f4581226a1262769d7f970e73bffe", size = 249455, upload-time = "2025-09-21T20:02:55.807Z" }, + { url = "https://files.pythonhosted.org/packages/aa/99/f5cdd8421ea656abefb6c0ce92556709db2265c41e8f9fc6c8ae0f7824c9/coverage-7.10.7-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:925a1edf3d810537c5a3abe78ec5530160c5f9a26b1f4270b40e62cc79304a1e", size = 249287, upload-time = "2025-09-21T20:02:57.784Z" }, + { url = "https://files.pythonhosted.org/packages/c3/7a/e9a2da6a1fc5d007dd51fca083a663ab930a8c4d149c087732a5dbaa0029/coverage-7.10.7-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:2c8b9a0636f94c43cd3576811e05b89aa9bc2d0a85137affc544ae5cb0e4bfbd", size = 250946, upload-time = "2025-09-21T20:02:59.431Z" }, + { url = "https://files.pythonhosted.org/packages/ef/5b/0b5799aa30380a949005a353715095d6d1da81927d6dbed5def2200a4e25/coverage-7.10.7-cp314-cp314-win32.whl", hash = "sha256:b7b8288eb7cdd268b0304632da8cb0bb93fadcfec2fe5712f7b9cc8f4d487be2", size = 221009, upload-time = "2025-09-21T20:03:01.324Z" }, + { url = "https://files.pythonhosted.org/packages/da/b0/e802fbb6eb746de006490abc9bb554b708918b6774b722bb3a0e6aa1b7de/coverage-7.10.7-cp314-cp314-win_amd64.whl", hash = "sha256:1ca6db7c8807fb9e755d0379ccc39017ce0a84dcd26d14b5a03b78563776f681", size = 221804, upload-time = "2025-09-21T20:03:03.4Z" }, + { url = "https://files.pythonhosted.org/packages/9e/e8/71d0c8e374e31f39e3389bb0bd19e527d46f00ea8571ec7ec8fd261d8b44/coverage-7.10.7-cp314-cp314-win_arm64.whl", hash = "sha256:097c1591f5af4496226d5783d036bf6fd6cd0cbc132e071b33861de756efb880", size = 220384, upload-time = "2025-09-21T20:03:05.111Z" }, + { url = "https://files.pythonhosted.org/packages/62/09/9a5608d319fa3eba7a2019addeacb8c746fb50872b57a724c9f79f146969/coverage-7.10.7-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:a62c6ef0d50e6de320c270ff91d9dd0a05e7250cac2a800b7784bae474506e63", size = 219047, upload-time = "2025-09-21T20:03:06.795Z" }, + { url = "https://files.pythonhosted.org/packages/f5/6f/f58d46f33db9f2e3647b2d0764704548c184e6f5e014bef528b7f979ef84/coverage-7.10.7-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:9fa6e4dd51fe15d8738708a973470f67a855ca50002294852e9571cdbd9433f2", size = 219266, upload-time = "2025-09-21T20:03:08.495Z" }, + { url = "https://files.pythonhosted.org/packages/74/5c/183ffc817ba68e0b443b8c934c8795553eb0c14573813415bd59941ee165/coverage-7.10.7-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:8fb190658865565c549b6b4706856d6a7b09302c797eb2cf8e7fe9dabb043f0d", size = 260767, upload-time = "2025-09-21T20:03:10.172Z" }, + { url = "https://files.pythonhosted.org/packages/0f/48/71a8abe9c1ad7e97548835e3cc1adbf361e743e9d60310c5f75c9e7bf847/coverage-7.10.7-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:affef7c76a9ef259187ef31599a9260330e0335a3011732c4b9effa01e1cd6e0", size = 262931, upload-time = "2025-09-21T20:03:11.861Z" }, + { url = "https://files.pythonhosted.org/packages/84/fd/193a8fb132acfc0a901f72020e54be5e48021e1575bb327d8ee1097a28fd/coverage-7.10.7-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6e16e07d85ca0cf8bafe5f5d23a0b850064e8e945d5677492b06bbe6f09cc699", size = 265186, upload-time = "2025-09-21T20:03:13.539Z" }, + { url = "https://files.pythonhosted.org/packages/b1/8f/74ecc30607dd95ad50e3034221113ccb1c6d4e8085cc761134782995daae/coverage-7.10.7-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:03ffc58aacdf65d2a82bbeb1ffe4d01ead4017a21bfd0454983b88ca73af94b9", size = 259470, upload-time = "2025-09-21T20:03:15.584Z" }, + { url = "https://files.pythonhosted.org/packages/0f/55/79ff53a769f20d71b07023ea115c9167c0bb56f281320520cf64c5298a96/coverage-7.10.7-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:1b4fd784344d4e52647fd7857b2af5b3fbe6c239b0b5fa63e94eb67320770e0f", size = 262626, upload-time = "2025-09-21T20:03:17.673Z" }, + { url = "https://files.pythonhosted.org/packages/88/e2/dac66c140009b61ac3fc13af673a574b00c16efdf04f9b5c740703e953c0/coverage-7.10.7-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:0ebbaddb2c19b71912c6f2518e791aa8b9f054985a0769bdb3a53ebbc765c6a1", size = 260386, upload-time = "2025-09-21T20:03:19.36Z" }, + { url = "https://files.pythonhosted.org/packages/a2/f1/f48f645e3f33bb9ca8a496bc4a9671b52f2f353146233ebd7c1df6160440/coverage-7.10.7-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:a2d9a3b260cc1d1dbdb1c582e63ddcf5363426a1a68faa0f5da28d8ee3c722a0", size = 258852, upload-time = "2025-09-21T20:03:21.007Z" }, + { url = "https://files.pythonhosted.org/packages/bb/3b/8442618972c51a7affeead957995cfa8323c0c9bcf8fa5a027421f720ff4/coverage-7.10.7-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:a3cc8638b2480865eaa3926d192e64ce6c51e3d29c849e09d5b4ad95efae5399", size = 261534, upload-time = "2025-09-21T20:03:23.12Z" }, + { url = "https://files.pythonhosted.org/packages/b2/dc/101f3fa3a45146db0cb03f5b4376e24c0aac818309da23e2de0c75295a91/coverage-7.10.7-cp314-cp314t-win32.whl", hash = "sha256:67f8c5cbcd3deb7a60b3345dffc89a961a484ed0af1f6f73de91705cc6e31235", size = 221784, upload-time = "2025-09-21T20:03:24.769Z" }, + { url = "https://files.pythonhosted.org/packages/4c/a1/74c51803fc70a8a40d7346660379e144be772bab4ac7bb6e6b905152345c/coverage-7.10.7-cp314-cp314t-win_amd64.whl", hash = "sha256:e1ed71194ef6dea7ed2d5cb5f7243d4bcd334bfb63e59878519be558078f848d", size = 222905, upload-time = "2025-09-21T20:03:26.93Z" }, + { url = "https://files.pythonhosted.org/packages/12/65/f116a6d2127df30bcafbceef0302d8a64ba87488bf6f73a6d8eebf060873/coverage-7.10.7-cp314-cp314t-win_arm64.whl", hash = "sha256:7fe650342addd8524ca63d77b2362b02345e5f1a093266787d210c70a50b471a", size = 220922, upload-time = "2025-09-21T20:03:28.672Z" }, + { url = "https://files.pythonhosted.org/packages/ec/16/114df1c291c22cac3b0c127a73e0af5c12ed7bbb6558d310429a0ae24023/coverage-7.10.7-py3-none-any.whl", hash = "sha256:f7941f6f2fe6dd6807a1208737b8a0cbcf1cc6d7b07d24998ad2d63590868260", size = 209952, upload-time = "2025-09-21T20:03:53.918Z" }, ] [package.optional-dependencies] @@ -684,15 +696,15 @@ wheels = [ [[package]] name = "hypothesis" -version = "6.139.2" +version = "6.140.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "attrs" }, { name = "sortedcontainers" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/56/8e/f408b1a6d9745bf02c3d56e0788c930add554eee6b88a39bba141e897ac4/hypothesis-6.139.2.tar.gz", hash = "sha256:2dc2ff36ea977a9cb7fb68f24a5dbf5d673b88a2e502212676eafe09b699f511", size = 466099, upload-time = "2025-09-18T03:29:15.855Z" } +sdist = { url = "https://files.pythonhosted.org/packages/ad/4a/3c340178b986b44b4f71ddb04625c8fb8bf815e7c7e23a6aabb2ce17e849/hypothesis-6.140.2.tar.gz", hash = "sha256:b3b4a162134eeef8a992621de6c43d80e03d44704a3c3bfb5b9d0661b375b0d2", size = 466699, upload-time = "2025-09-23T00:07:21.087Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/7c/81/4a85771072ae39064f114f23716e312771a42bfe3a089cba3da6697dd231/hypothesis-6.139.2-py3-none-any.whl", hash = "sha256:6f466780b7d1db074fb473af14e3111a5dd4fe36c47fcd776cd7c480ae0a02f2", size = 533752, upload-time = "2025-09-18T03:29:12.088Z" }, + { url = "https://files.pythonhosted.org/packages/e9/7d/7dd3684f9cb707b6b1e808c7f23dd0fa4a96fe106b6accd9b757c9985c50/hypothesis-6.140.2-py3-none-any.whl", hash = "sha256:4524cb84be90961563ef15634e2efe96150bbcce47621a13cff3c1b03a326663", size = 534388, upload-time = "2025-09-23T00:07:16.555Z" }, ] [[package]] @@ -1154,40 +1166,40 @@ wheels = [ [[package]] name = "mypy" -version = "1.18.1" +version = "1.18.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "mypy-extensions" }, { name = "pathspec" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/14/a3/931e09fc02d7ba96da65266884da4e4a8806adcdb8a57faaacc6edf1d538/mypy-1.18.1.tar.gz", hash = "sha256:9e988c64ad3ac5987f43f5154f884747faf62141b7f842e87465b45299eea5a9", size = 3448447, upload-time = "2025-09-11T23:00:47.067Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/32/28/47709d5d9e7068b26c0d5189c8137c8783e81065ad1102b505214a08b548/mypy-1.18.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6c903857b3e28fc5489e54042684a9509039ea0aedb2a619469438b544ae1961", size = 12734635, upload-time = "2025-09-11T23:00:24.983Z" }, - { url = "https://files.pythonhosted.org/packages/7c/12/ee5c243e52497d0e59316854041cf3b3130131b92266d0764aca4dec3c00/mypy-1.18.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2a0c8392c19934c2b6c65566d3a6abdc6b51d5da7f5d04e43f0eb627d6eeee65", size = 11817287, upload-time = "2025-09-11T22:59:07.38Z" }, - { url = "https://files.pythonhosted.org/packages/48/bd/2aeb950151005fe708ab59725afed7c4aeeb96daf844f86a05d4b8ac34f8/mypy-1.18.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f85eb7efa2ec73ef63fc23b8af89c2fe5bf2a4ad985ed2d3ff28c1bb3c317c92", size = 12430464, upload-time = "2025-09-11T22:58:48.084Z" }, - { url = "https://files.pythonhosted.org/packages/71/e8/7a20407aafb488acb5734ad7fb5e8c2ef78d292ca2674335350fa8ebef67/mypy-1.18.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:82ace21edf7ba8af31c3308a61dc72df30500f4dbb26f99ac36b4b80809d7e94", size = 13164555, upload-time = "2025-09-11T23:00:13.803Z" }, - { url = "https://files.pythonhosted.org/packages/e8/c9/5f39065252e033b60f397096f538fb57c1d9fd70a7a490f314df20dd9d64/mypy-1.18.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a2dfd53dfe632f1ef5d161150a4b1f2d0786746ae02950eb3ac108964ee2975a", size = 13359222, upload-time = "2025-09-11T23:00:33.469Z" }, - { url = "https://files.pythonhosted.org/packages/85/b6/d54111ef3c1e55992cd2ec9b8b6ce9c72a407423e93132cae209f7e7ba60/mypy-1.18.1-cp311-cp311-win_amd64.whl", hash = "sha256:320f0ad4205eefcb0e1a72428dde0ad10be73da9f92e793c36228e8ebf7298c0", size = 9760441, upload-time = "2025-09-11T23:00:44.826Z" }, - { url = "https://files.pythonhosted.org/packages/e7/14/1c3f54d606cb88a55d1567153ef3a8bc7b74702f2ff5eb64d0994f9e49cb/mypy-1.18.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:502cde8896be8e638588b90fdcb4c5d5b8c1b004dfc63fd5604a973547367bb9", size = 12911082, upload-time = "2025-09-11T23:00:41.465Z" }, - { url = "https://files.pythonhosted.org/packages/90/83/235606c8b6d50a8eba99773add907ce1d41c068edb523f81eb0d01603a83/mypy-1.18.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7509549b5e41be279afc1228242d0e397f1af2919a8f2877ad542b199dc4083e", size = 11919107, upload-time = "2025-09-11T22:58:40.903Z" }, - { url = "https://files.pythonhosted.org/packages/ca/25/4e2ce00f8d15b99d0c68a2536ad63e9eac033f723439ef80290ec32c1ff5/mypy-1.18.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5956ecaabb3a245e3f34100172abca1507be687377fe20e24d6a7557e07080e2", size = 12472551, upload-time = "2025-09-11T22:58:37.272Z" }, - { url = "https://files.pythonhosted.org/packages/32/bb/92642a9350fc339dd9dcefcf6862d171b52294af107d521dce075f32f298/mypy-1.18.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8750ceb014a96c9890421c83f0db53b0f3b8633e2864c6f9bc0a8e93951ed18d", size = 13340554, upload-time = "2025-09-11T22:59:38.756Z" }, - { url = "https://files.pythonhosted.org/packages/cd/ee/38d01db91c198fb6350025d28f9719ecf3c8f2c55a0094bfbf3ef478cc9a/mypy-1.18.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fb89ea08ff41adf59476b235293679a6eb53a7b9400f6256272fb6029bec3ce5", size = 13530933, upload-time = "2025-09-11T22:59:20.228Z" }, - { url = "https://files.pythonhosted.org/packages/da/8d/6d991ae631f80d58edbf9d7066e3f2a96e479dca955d9a968cd6e90850a3/mypy-1.18.1-cp312-cp312-win_amd64.whl", hash = "sha256:2657654d82fcd2a87e02a33e0d23001789a554059bbf34702d623dafe353eabf", size = 9828426, upload-time = "2025-09-11T23:00:21.007Z" }, - { url = "https://files.pythonhosted.org/packages/e4/ec/ef4a7260e1460a3071628a9277a7579e7da1b071bc134ebe909323f2fbc7/mypy-1.18.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:d70d2b5baf9b9a20bc9c730015615ae3243ef47fb4a58ad7b31c3e0a59b5ef1f", size = 12918671, upload-time = "2025-09-11T22:58:29.814Z" }, - { url = "https://files.pythonhosted.org/packages/a1/82/0ea6c3953f16223f0b8eda40c1aeac6bd266d15f4902556ae6e91f6fca4c/mypy-1.18.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:b8367e33506300f07a43012fc546402f283c3f8bcff1dc338636affb710154ce", size = 11913023, upload-time = "2025-09-11T23:00:29.049Z" }, - { url = "https://files.pythonhosted.org/packages/ae/ef/5e2057e692c2690fc27b3ed0a4dbde4388330c32e2576a23f0302bc8358d/mypy-1.18.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:913f668ec50c3337b89df22f973c1c8f0b29ee9e290a8b7fe01cc1ef7446d42e", size = 12473355, upload-time = "2025-09-11T23:00:04.544Z" }, - { url = "https://files.pythonhosted.org/packages/98/43/b7e429fc4be10e390a167b0cd1810d41cb4e4add4ae50bab96faff695a3b/mypy-1.18.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1a0e70b87eb27b33209fa4792b051c6947976f6ab829daa83819df5f58330c71", size = 13346944, upload-time = "2025-09-11T22:58:23.024Z" }, - { url = "https://files.pythonhosted.org/packages/89/4e/899dba0bfe36bbd5b7c52e597de4cf47b5053d337b6d201a30e3798e77a6/mypy-1.18.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:c378d946e8a60be6b6ede48c878d145546fb42aad61df998c056ec151bf6c746", size = 13512574, upload-time = "2025-09-11T22:59:52.152Z" }, - { url = "https://files.pythonhosted.org/packages/f5/f8/7661021a5b0e501b76440454d786b0f01bb05d5c4b125fcbda02023d0250/mypy-1.18.1-cp313-cp313-win_amd64.whl", hash = "sha256:2cd2c1e0f3a7465f22731987fff6fc427e3dcbb4ca5f7db5bbeaff2ff9a31f6d", size = 9837684, upload-time = "2025-09-11T22:58:44.454Z" }, - { url = "https://files.pythonhosted.org/packages/bf/87/7b173981466219eccc64c107cf8e5ab9eb39cc304b4c07df8e7881533e4f/mypy-1.18.1-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:ba24603c58e34dd5b096dfad792d87b304fc6470cbb1c22fd64e7ebd17edcc61", size = 12900265, upload-time = "2025-09-11T22:59:03.4Z" }, - { url = "https://files.pythonhosted.org/packages/ae/cc/b10e65bae75b18a5ac8f81b1e8e5867677e418f0dd2c83b8e2de9ba96ebd/mypy-1.18.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:ed36662fb92ae4cb3cacc682ec6656208f323bbc23d4b08d091eecfc0863d4b5", size = 11942890, upload-time = "2025-09-11T23:00:00.607Z" }, - { url = "https://files.pythonhosted.org/packages/39/d4/aeefa07c44d09f4c2102e525e2031bc066d12e5351f66b8a83719671004d/mypy-1.18.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:040ecc95e026f71a9ad7956fea2724466602b561e6a25c2e5584160d3833aaa8", size = 12472291, upload-time = "2025-09-11T22:59:43.425Z" }, - { url = "https://files.pythonhosted.org/packages/c6/07/711e78668ff8e365f8c19735594ea95938bff3639a4c46a905e3ed8ff2d6/mypy-1.18.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:937e3ed86cb731276706e46e03512547e43c391a13f363e08d0fee49a7c38a0d", size = 13318610, upload-time = "2025-09-11T23:00:17.604Z" }, - { url = "https://files.pythonhosted.org/packages/ca/85/df3b2d39339c31d360ce299b418c55e8194ef3205284739b64962f6074e7/mypy-1.18.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:1f95cc4f01c0f1701ca3b0355792bccec13ecb2ec1c469e5b85a6ef398398b1d", size = 13513697, upload-time = "2025-09-11T22:58:59.534Z" }, - { url = "https://files.pythonhosted.org/packages/b1/df/462866163c99ea73bb28f0eb4d415c087e30de5d36ee0f5429d42e28689b/mypy-1.18.1-cp314-cp314-win_amd64.whl", hash = "sha256:e4f16c0019d48941220ac60b893615be2f63afedaba6a0801bdcd041b96991ce", size = 9985739, upload-time = "2025-09-11T22:58:51.644Z" }, - { url = "https://files.pythonhosted.org/packages/e0/1d/4b97d3089b48ef3d904c9ca69fab044475bd03245d878f5f0b3ea1daf7ce/mypy-1.18.1-py3-none-any.whl", hash = "sha256:b76a4de66a0ac01da1be14ecc8ae88ddea33b8380284a9e3eae39d57ebcbe26e", size = 2352212, upload-time = "2025-09-11T22:59:26.576Z" }, +sdist = { url = "https://files.pythonhosted.org/packages/c0/77/8f0d0001ffad290cef2f7f216f96c814866248a0b92a722365ed54648e7e/mypy-1.18.2.tar.gz", hash = "sha256:06a398102a5f203d7477b2923dda3634c36727fa5c237d8f859ef90c42a9924b", size = 3448846, upload-time = "2025-09-19T00:11:10.519Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/88/87/cafd3ae563f88f94eec33f35ff722d043e09832ea8530ef149ec1efbaf08/mypy-1.18.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:807d9315ab9d464125aa9fcf6d84fde6e1dc67da0b6f80e7405506b8ac72bc7f", size = 12731198, upload-time = "2025-09-19T00:09:44.857Z" }, + { url = "https://files.pythonhosted.org/packages/0f/e0/1e96c3d4266a06d4b0197ace5356d67d937d8358e2ee3ffac71faa843724/mypy-1.18.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:776bb00de1778caf4db739c6e83919c1d85a448f71979b6a0edd774ea8399341", size = 11817879, upload-time = "2025-09-19T00:09:47.131Z" }, + { url = "https://files.pythonhosted.org/packages/72/ef/0c9ba89eb03453e76bdac5a78b08260a848c7bfc5d6603634774d9cd9525/mypy-1.18.2-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1379451880512ffce14505493bd9fe469e0697543717298242574882cf8cdb8d", size = 12427292, upload-time = "2025-09-19T00:10:22.472Z" }, + { url = "https://files.pythonhosted.org/packages/1a/52/ec4a061dd599eb8179d5411d99775bec2a20542505988f40fc2fee781068/mypy-1.18.2-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1331eb7fd110d60c24999893320967594ff84c38ac6d19e0a76c5fd809a84c86", size = 13163750, upload-time = "2025-09-19T00:09:51.472Z" }, + { url = "https://files.pythonhosted.org/packages/c4/5f/2cf2ceb3b36372d51568f2208c021870fe7834cf3186b653ac6446511839/mypy-1.18.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:3ca30b50a51e7ba93b00422e486cbb124f1c56a535e20eff7b2d6ab72b3b2e37", size = 13351827, upload-time = "2025-09-19T00:09:58.311Z" }, + { url = "https://files.pythonhosted.org/packages/c8/7d/2697b930179e7277529eaaec1513f8de622818696857f689e4a5432e5e27/mypy-1.18.2-cp311-cp311-win_amd64.whl", hash = "sha256:664dc726e67fa54e14536f6e1224bcfce1d9e5ac02426d2326e2bb4e081d1ce8", size = 9757983, upload-time = "2025-09-19T00:10:09.071Z" }, + { url = "https://files.pythonhosted.org/packages/07/06/dfdd2bc60c66611dd8335f463818514733bc763e4760dee289dcc33df709/mypy-1.18.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:33eca32dd124b29400c31d7cf784e795b050ace0e1f91b8dc035672725617e34", size = 12908273, upload-time = "2025-09-19T00:10:58.321Z" }, + { url = "https://files.pythonhosted.org/packages/81/14/6a9de6d13a122d5608e1a04130724caf9170333ac5a924e10f670687d3eb/mypy-1.18.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a3c47adf30d65e89b2dcd2fa32f3aeb5e94ca970d2c15fcb25e297871c8e4764", size = 11920910, upload-time = "2025-09-19T00:10:20.043Z" }, + { url = "https://files.pythonhosted.org/packages/5f/a9/b29de53e42f18e8cc547e38daa9dfa132ffdc64f7250e353f5c8cdd44bee/mypy-1.18.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5d6c838e831a062f5f29d11c9057c6009f60cb294fea33a98422688181fe2893", size = 12465585, upload-time = "2025-09-19T00:10:33.005Z" }, + { url = "https://files.pythonhosted.org/packages/77/ae/6c3d2c7c61ff21f2bee938c917616c92ebf852f015fb55917fd6e2811db2/mypy-1.18.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:01199871b6110a2ce984bde85acd481232d17413868c9807e95c1b0739a58914", size = 13348562, upload-time = "2025-09-19T00:10:11.51Z" }, + { url = "https://files.pythonhosted.org/packages/4d/31/aec68ab3b4aebdf8f36d191b0685d99faa899ab990753ca0fee60fb99511/mypy-1.18.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a2afc0fa0b0e91b4599ddfe0f91e2c26c2b5a5ab263737e998d6817874c5f7c8", size = 13533296, upload-time = "2025-09-19T00:10:06.568Z" }, + { url = "https://files.pythonhosted.org/packages/9f/83/abcb3ad9478fca3ebeb6a5358bb0b22c95ea42b43b7789c7fb1297ca44f4/mypy-1.18.2-cp312-cp312-win_amd64.whl", hash = "sha256:d8068d0afe682c7c4897c0f7ce84ea77f6de953262b12d07038f4d296d547074", size = 9828828, upload-time = "2025-09-19T00:10:28.203Z" }, + { url = "https://files.pythonhosted.org/packages/5f/04/7f462e6fbba87a72bc8097b93f6842499c428a6ff0c81dd46948d175afe8/mypy-1.18.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:07b8b0f580ca6d289e69209ec9d3911b4a26e5abfde32228a288eb79df129fcc", size = 12898728, upload-time = "2025-09-19T00:10:01.33Z" }, + { url = "https://files.pythonhosted.org/packages/99/5b/61ed4efb64f1871b41fd0b82d29a64640f3516078f6c7905b68ab1ad8b13/mypy-1.18.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:ed4482847168439651d3feee5833ccedbf6657e964572706a2adb1f7fa4dfe2e", size = 11910758, upload-time = "2025-09-19T00:10:42.607Z" }, + { url = "https://files.pythonhosted.org/packages/3c/46/d297d4b683cc89a6e4108c4250a6a6b717f5fa96e1a30a7944a6da44da35/mypy-1.18.2-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c3ad2afadd1e9fea5cf99a45a822346971ede8685cc581ed9cd4d42eaf940986", size = 12475342, upload-time = "2025-09-19T00:11:00.371Z" }, + { url = "https://files.pythonhosted.org/packages/83/45/4798f4d00df13eae3bfdf726c9244bcb495ab5bd588c0eed93a2f2dd67f3/mypy-1.18.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a431a6f1ef14cf8c144c6b14793a23ec4eae3db28277c358136e79d7d062f62d", size = 13338709, upload-time = "2025-09-19T00:11:03.358Z" }, + { url = "https://files.pythonhosted.org/packages/d7/09/479f7358d9625172521a87a9271ddd2441e1dab16a09708f056e97007207/mypy-1.18.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:7ab28cc197f1dd77a67e1c6f35cd1f8e8b73ed2217e4fc005f9e6a504e46e7ba", size = 13529806, upload-time = "2025-09-19T00:10:26.073Z" }, + { url = "https://files.pythonhosted.org/packages/71/cf/ac0f2c7e9d0ea3c75cd99dff7aec1c9df4a1376537cb90e4c882267ee7e9/mypy-1.18.2-cp313-cp313-win_amd64.whl", hash = "sha256:0e2785a84b34a72ba55fb5daf079a1003a34c05b22238da94fcae2bbe46f3544", size = 9833262, upload-time = "2025-09-19T00:10:40.035Z" }, + { url = "https://files.pythonhosted.org/packages/5a/0c/7d5300883da16f0063ae53996358758b2a2df2a09c72a5061fa79a1f5006/mypy-1.18.2-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:62f0e1e988ad41c2a110edde6c398383a889d95b36b3e60bcf155f5164c4fdce", size = 12893775, upload-time = "2025-09-19T00:10:03.814Z" }, + { url = "https://files.pythonhosted.org/packages/50/df/2cffbf25737bdb236f60c973edf62e3e7b4ee1c25b6878629e88e2cde967/mypy-1.18.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:8795a039bab805ff0c1dfdb8cd3344642c2b99b8e439d057aba30850b8d3423d", size = 11936852, upload-time = "2025-09-19T00:10:51.631Z" }, + { url = "https://files.pythonhosted.org/packages/be/50/34059de13dd269227fb4a03be1faee6e2a4b04a2051c82ac0a0b5a773c9a/mypy-1.18.2-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6ca1e64b24a700ab5ce10133f7ccd956a04715463d30498e64ea8715236f9c9c", size = 12480242, upload-time = "2025-09-19T00:11:07.955Z" }, + { url = "https://files.pythonhosted.org/packages/5b/11/040983fad5132d85914c874a2836252bbc57832065548885b5bb5b0d4359/mypy-1.18.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d924eef3795cc89fecf6bedc6ed32b33ac13e8321344f6ddbf8ee89f706c05cb", size = 13326683, upload-time = "2025-09-19T00:09:55.572Z" }, + { url = "https://files.pythonhosted.org/packages/e9/ba/89b2901dd77414dd7a8c8729985832a5735053be15b744c18e4586e506ef/mypy-1.18.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:20c02215a080e3a2be3aa50506c67242df1c151eaba0dcbc1e4e557922a26075", size = 13514749, upload-time = "2025-09-19T00:10:44.827Z" }, + { url = "https://files.pythonhosted.org/packages/25/bc/cc98767cffd6b2928ba680f3e5bc969c4152bf7c2d83f92f5a504b92b0eb/mypy-1.18.2-cp314-cp314-win_amd64.whl", hash = "sha256:749b5f83198f1ca64345603118a6f01a4e99ad4bf9d103ddc5a3200cc4614adf", size = 9982959, upload-time = "2025-09-19T00:10:37.344Z" }, + { url = "https://files.pythonhosted.org/packages/87/e3/be76d87158ebafa0309946c4a73831974d4d6ab4f4ef40c3b53a385a66fd/mypy-1.18.2-py3-none-any.whl", hash = "sha256:22a1748707dd62b58d2ae53562ffc4d7f8bcc727e8ac7cbc69c053ddc874d47e", size = 2352367, upload-time = "2025-09-19T00:10:15.489Z" }, ] [[package]] @@ -1828,11 +1840,11 @@ wheels = [ [[package]] name = "pyparsing" -version = "3.2.4" +version = "3.2.5" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/98/c9/b4594e6a81371dfa9eb7a2c110ad682acf985d96115ae8b25a1d63b4bf3b/pyparsing-3.2.4.tar.gz", hash = "sha256:fff89494f45559d0f2ce46613b419f632bbb6afbdaed49696d322bcf98a58e99", size = 1098809, upload-time = "2025-09-13T05:47:19.732Z" } +sdist = { url = "https://files.pythonhosted.org/packages/f2/a5/181488fc2b9d093e3972d2a472855aae8a03f000592dbfce716a512b3359/pyparsing-3.2.5.tar.gz", hash = "sha256:2df8d5b7b2802ef88e8d016a2eb9c7aeaa923529cd251ed0fe4608275d4105b6", size = 1099274, upload-time = "2025-09-21T04:11:06.277Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/53/b8/fbab973592e23ae313042d450fc26fa24282ebffba21ba373786e1ce63b4/pyparsing-3.2.4-py3-none-any.whl", hash = "sha256:91d0fcde680d42cd031daf3a6ba20da3107e08a75de50da58360e7d94ab24d36", size = 113869, upload-time = "2025-09-13T05:47:17.863Z" }, + { url = "https://files.pythonhosted.org/packages/10/5e/1aa9a93198c6b64513c9d7752de7422c06402de6600a8767da1524f9570b/pyparsing-3.2.5-py3-none-any.whl", hash = "sha256:e38a4f02064cf41fe6593d328d0512495ad1f3d8a91c4f73fc401b3079a59a5e", size = 113890, upload-time = "2025-09-21T04:11:04.117Z" }, ] [[package]] @@ -2741,28 +2753,28 @@ wheels = [ [[package]] name = "uv" -version = "0.8.18" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/6d/0b/6e968a7a3210da8b43535cc70422eab114332ecd1bdfdb4df15746979f2b/uv-0.8.18.tar.gz", hash = "sha256:b495e9cfb857060a2a3c25540d0ef9d40991dbfc8a8254679543608816c1921b", size = 3653354, upload-time = "2025-09-17T21:36:43.666Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/3b/21/c88abfe4fc47d6a859aae234409cbe355138ccf7ad088d3697539cff8a90/uv-0.8.18-py3-none-linux_armv6l.whl", hash = "sha256:42b2b0a3c9d0d32cb7bd23cf9d05d52b3dfc83c706f927569c32ee9483bd2479", size = 20237508, upload-time = "2025-09-17T21:35:44.844Z" }, - { url = "https://files.pythonhosted.org/packages/b6/97/3a4ba6d5fa4853f96574cb085fcda4407199b62abbc0b8b170d4e3b6aa5c/uv-0.8.18-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:46668347e9b29b254a6fc45fbd9788e7c630f0b4f3f7d894a1d3d4eecb20c3e4", size = 19252461, upload-time = "2025-09-17T21:35:48.889Z" }, - { url = "https://files.pythonhosted.org/packages/4e/79/7af5b261b061b1dd92eed0be1a14264c34717006e651a83018c15adb2043/uv-0.8.18-py3-none-macosx_11_0_arm64.whl", hash = "sha256:e321544054688df7115041cc172865e5e0f9377b7b9e351e67d7db27c99c4080", size = 17870543, upload-time = "2025-09-17T21:35:51.611Z" }, - { url = "https://files.pythonhosted.org/packages/4b/89/3c9ffa0c971eab50974a976eed6d2e00d8e3e0b6146b8b45b699f64a1224/uv-0.8.18-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:087b9c8afe50585b1b4aa880ef5fe3c8067268abf8461d01cd59f65517a0696b", size = 19503893, upload-time = "2025-09-17T21:35:56.117Z" }, - { url = "https://files.pythonhosted.org/packages/5b/56/a2309381dd2138e67b22f004fb4e26b04e8e06b04dac50f0c392e3f2ae54/uv-0.8.18-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:30b89b85840500a110a0bfaf7ca97a52803617873c63e4c3cad866ad93d13ed3", size = 19850198, upload-time = "2025-09-17T21:35:58.782Z" }, - { url = "https://files.pythonhosted.org/packages/fc/0f/e46774ee081c56632acc4f8c3c35ddb3ce4bc0e8535da8907ce4623aedb2/uv-0.8.18-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3a8d4bc46fb699d1e172de3948870f5a10408e59e5c0c184ecee1d5be02cb740", size = 20798436, upload-time = "2025-09-17T21:36:02.122Z" }, - { url = "https://files.pythonhosted.org/packages/ef/7a/07fbdd3e966e86fc6dd18fe46fce51f27d799cccb06b8f95134dec800f0a/uv-0.8.18-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:3073e1fc28ba5cb9d04a09bc0bd761569d3f3f1cc4252810c3992465c9579334", size = 22198386, upload-time = "2025-09-17T21:36:05.38Z" }, - { url = "https://files.pythonhosted.org/packages/83/f6/751e1544396796a5cf5c9616ab50f14969e15708eb2746ef854a038ba9b5/uv-0.8.18-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a8dc04c632881263a880084292bbfb0140270787b12435278e4b6fc342761efe", size = 21878627, upload-time = "2025-09-17T21:36:08.204Z" }, - { url = "https://files.pythonhosted.org/packages/6c/09/ca38d471ecf5e48b61e649b407315790581871dbea49ea34577b8a22276b/uv-0.8.18-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:428d2effa05d2c0b33d30c45eac0a15eddb2ac369b987b8eb651a033f90fd73b", size = 21086454, upload-time = "2025-09-17T21:36:11.805Z" }, - { url = "https://files.pythonhosted.org/packages/57/f6/b55bf6af76e3188d63db016a65c337fe23828d6b705e58412d526b748da1/uv-0.8.18-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e9933c17dd618ca1c7e6aee877e928cd8583c20ceef9360917803a49c664a917", size = 21030766, upload-time = "2025-09-17T21:36:14.739Z" }, - { url = "https://files.pythonhosted.org/packages/49/8c/6d866287558c5aae930c4f71565000994e4b6b14e56b5c86ed1b32241820/uv-0.8.18-py3-none-manylinux_2_28_aarch64.whl", hash = "sha256:b8067f1cf8208dd6f9efc9e2e67c165c97b413ea48f90ba4ffb5caf85c1e5ce0", size = 19778490, upload-time = "2025-09-17T21:36:18.593Z" }, - { url = "https://files.pythonhosted.org/packages/d3/f2/669810996e5d164504eea5639fecff28ccf2c9cc98a9b80b4f36516420b9/uv-0.8.18-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:45d0e8ab23d7bc8a32596bb3ef7569e95c134e5fff26ab68c091f3c44b7e7caf", size = 20804081, upload-time = "2025-09-17T21:36:21.312Z" }, - { url = "https://files.pythonhosted.org/packages/8b/03/32e00cbc4fce767a26c2341bfd10317d9ec9b27b811f5d03075734e4bdb6/uv-0.8.18-py3-none-musllinux_1_1_armv7l.whl", hash = "sha256:a8f98de826a92a71956d6f255b0d93865a4d4821fa7c76c81b0fc20e15f05189", size = 19819627, upload-time = "2025-09-17T21:36:24.272Z" }, - { url = "https://files.pythonhosted.org/packages/9d/1b/e6f67c485cf3acf4af7ceed97fe162a5c201a6514610622ca7d21015a907/uv-0.8.18-py3-none-musllinux_1_1_i686.whl", hash = "sha256:336fad21ad357ae5e8cd2b75142d31d109dcc8ac3dea9fa1f4417993087f48bb", size = 20231410, upload-time = "2025-09-17T21:36:27.086Z" }, - { url = "https://files.pythonhosted.org/packages/60/dc/8a1d11b7de323f579b7e829fe77d42e81223eab6cb6714686f1e3b76227e/uv-0.8.18-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:0c492090312e3252091ef5bc570ac46a616b06d9c0ef448898eeb381f6742c0d", size = 21191101, upload-time = "2025-09-17T21:36:30.311Z" }, - { url = "https://files.pythonhosted.org/packages/e3/c0/6d188d3dc9230244eb933aedd820c6428237646f8583077e7ebfd57f4491/uv-0.8.18-py3-none-win32.whl", hash = "sha256:ee28459f377a1afcd0450ee635106dee8d77bea69d8dcd42bc4eecd3361ccab4", size = 19163833, upload-time = "2025-09-17T21:36:35.575Z" }, - { url = "https://files.pythonhosted.org/packages/4f/f5/c2dc1d07bae2687625ef29ffdd51cc4971d38077fb27022bc5fd13437e47/uv-0.8.18-py3-none-win_amd64.whl", hash = "sha256:313d09b7c076ad904853fb2788eab34b1541db67cc2feaf67a6f0f81bc3b346c", size = 20981095, upload-time = "2025-09-17T21:36:38.661Z" }, - { url = "https://files.pythonhosted.org/packages/b7/7d/c3c09a3c5640db2b2a00b343e64ad70defd02b4b5e0ab221ff210c85de79/uv-0.8.18-py3-none-win_arm64.whl", hash = "sha256:a1493b8184175af5474c75fa432940969cf6452976c37ddb8c9e28afa1d25742", size = 19591881, upload-time = "2025-09-17T21:36:41.482Z" }, +version = "0.8.22" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a6/39/231e123458d50dd497cf6d27b592f5d3bc3e2e50f496b56859865a7b22e3/uv-0.8.22.tar.gz", hash = "sha256:e6e1289c411d43e0ca245f46e76457f3807de646d90b656591b6cf46348bed5c", size = 3667007, upload-time = "2025-09-23T20:35:14.736Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7c/e6/bb440171dd8a36d0f9874b4c71778f7bbc83e62ccf42c62bd1583c802793/uv-0.8.22-py3-none-linux_armv6l.whl", hash = "sha256:7350c5f82d9c38944e6466933edcf96a90e0cb85eae5c0e53a5bc716d6f62332", size = 20554993, upload-time = "2025-09-23T20:34:26.549Z" }, + { url = "https://files.pythonhosted.org/packages/28/e9/813f7eb9fb9694c4024362782c8933e37887b5195e189f80dc40f2da5958/uv-0.8.22-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:89944e99b04cc8542cb5931306f1c593f00c9d6f2b652fffc4d84d12b915f911", size = 19565276, upload-time = "2025-09-23T20:34:30.436Z" }, + { url = "https://files.pythonhosted.org/packages/d7/ca/bf37d86af6e16e45fa2b1a03300784ff3297aa9252a23dfbeaf6e391e72e/uv-0.8.22-py3-none-macosx_11_0_arm64.whl", hash = "sha256:6706b782ad75662df794e186d16b9ffa4946d57c88f21d0eadfd43425794d1b0", size = 18162303, upload-time = "2025-09-23T20:34:32.761Z" }, + { url = "https://files.pythonhosted.org/packages/e4/eb/289b6a59fff1613958499a886283f52403c5ce4f0a8a550b86fbd70e8e4f/uv-0.8.22-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:d6a33bd5309f8fb77d9fc249bb17f77a23426e6153e43b03ca1cd6640f0a423d", size = 19982769, upload-time = "2025-09-23T20:34:34.962Z" }, + { url = "https://files.pythonhosted.org/packages/df/ba/2fcc3ce75be62eecf280f3cbe74d186f371a468fad3167b5a34dee2f904e/uv-0.8.22-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4a982bdd5d239dd6dd2b4219165e209c75af1e1819730454ee46d65b3ccf77a3", size = 20163849, upload-time = "2025-09-23T20:34:37.744Z" }, + { url = "https://files.pythonhosted.org/packages/f4/4d/4fc9a508c2c497a80c41710c96f1782a29edecffcac742f3843af061ba8f/uv-0.8.22-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:58b6fb191a04b922dc3c8fea6660f58545a651843d7d0efa9ae69164fca9e05d", size = 21130147, upload-time = "2025-09-23T20:34:40.414Z" }, + { url = "https://files.pythonhosted.org/packages/71/79/6bcb3c3c3b7c9cb1a162a76dca2b166752e4ba39ec90e802b252f0a54039/uv-0.8.22-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:8ea724ae9f15c0cb4964e9e2e1b21df65c56ae02a54dc1d8a6ea44a52d819268", size = 22561974, upload-time = "2025-09-23T20:34:42.843Z" }, + { url = "https://files.pythonhosted.org/packages/3f/98/89bb29d82ff7e5ab1b5e862d9bdc12b1d3a4d5201cf558432487e29cc448/uv-0.8.22-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7378127cbd6ebce8ba6d9bdb88aa8ea995b579824abb5ec381c63b3a123a43be", size = 22183189, upload-time = "2025-09-23T20:34:45.57Z" }, + { url = "https://files.pythonhosted.org/packages/95/b0/354c7d7d11fff2ee97bb208f0fec6b09ae885c0d591b6eff2d7b84cc6695/uv-0.8.22-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7e761ca7df8a0059b3fae6bc2c1db24583fa00b016e35bd22a5599d7084471a7", size = 21492888, upload-time = "2025-09-23T20:34:48.45Z" }, + { url = "https://files.pythonhosted.org/packages/3a/a9/a83cee9b8cf63e57ce64ba27c77777cc66410e144fd178368f55af1fa18d/uv-0.8.22-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8efec4ef5acddc35f0867998c44e0b15fc4dace1e4c26d01443871a2fbb04bf6", size = 21252972, upload-time = "2025-09-23T20:34:50.862Z" }, + { url = "https://files.pythonhosted.org/packages/0f/0c/71d5d5d3fca7aa788d63297a06ca26d3585270342277b52312bb693b100c/uv-0.8.22-py3-none-manylinux_2_28_aarch64.whl", hash = "sha256:9eb3b4abfa25e07d7e1bb4c9bb8dbbdd51878356a37c3c4a2ece3d68d4286f28", size = 20115520, upload-time = "2025-09-23T20:34:53.165Z" }, + { url = "https://files.pythonhosted.org/packages/da/90/57fae2798be1e71692872b8304e2e2c345eacbe2070bdcbba6d5a7675fa1/uv-0.8.22-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:b1fdffc2e71892ce648b66317e478fe8884d0007e20cfa582fff3dcea588a450", size = 21168787, upload-time = "2025-09-23T20:34:55.638Z" }, + { url = "https://files.pythonhosted.org/packages/fe/f6/23c8d8fdd1084603795f6344eee8e763ba06f891e863397fe5b7b532cb58/uv-0.8.22-py3-none-musllinux_1_1_armv7l.whl", hash = "sha256:f6ded9bacb31441d788afca397b8b884ebc2e70f903bea0a38806194be4b249c", size = 20170112, upload-time = "2025-09-23T20:34:58.008Z" }, + { url = "https://files.pythonhosted.org/packages/96/23/801d517964a7200014897522ae067bf7111fc2e138b38d13d9df9544bf06/uv-0.8.22-py3-none-musllinux_1_1_i686.whl", hash = "sha256:aefa0cb27a86d2145ca9290a1e99c16a17ea26a4f14a89fb7336bc19388427cc", size = 20537608, upload-time = "2025-09-23T20:35:00.44Z" }, + { url = "https://files.pythonhosted.org/packages/20/8a/1bd4159089f8df0128e4ceb7f4c31c23a451984a5b49c13489c70e721335/uv-0.8.22-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:9757f0b0c7d296f1e354db442ed0ce39721c06d11635ce4ee6638c5e809a9cb4", size = 21471224, upload-time = "2025-09-23T20:35:03.718Z" }, + { url = "https://files.pythonhosted.org/packages/86/ba/262d16059e3b0837728e8aa3590fc2c7bc23e0cefec81d6903b4b6af080a/uv-0.8.22-py3-none-win32.whl", hash = "sha256:36c7aecdb0044caf15ace00da00af172759c49c832f0017b7433d80f46552cd3", size = 19350586, upload-time = "2025-09-23T20:35:06.837Z" }, + { url = "https://files.pythonhosted.org/packages/38/82/94f08992eeb193dc3d5baac437d1867cd37f040f34c7b1a4b1bde2bc4b4b/uv-0.8.22-py3-none-win_amd64.whl", hash = "sha256:cda349c9ea53644d8d9ceae30db71616b733eb5330375ab4259765aef494b74e", size = 21355960, upload-time = "2025-09-23T20:35:09.472Z" }, + { url = "https://files.pythonhosted.org/packages/f9/00/2c7a93bbe93b74dc0496a8e875bac11027cb30c29636c106c6e49038b95f/uv-0.8.22-py3-none-win_arm64.whl", hash = "sha256:2a436b941b6e79fe1e1065b705a5689d72210f4367cbe885e19910cbcde2e4a1", size = 19778983, upload-time = "2025-09-23T20:35:12.188Z" }, ] [[package]] @@ -2781,11 +2793,11 @@ wheels = [ [[package]] name = "wcwidth" -version = "0.2.13" +version = "0.2.14" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/6c/63/53559446a878410fc5a5974feb13d31d78d752eb18aeba59c7fef1af7598/wcwidth-0.2.13.tar.gz", hash = "sha256:72ea0c06399eb286d978fdedb6923a9eb47e1c486ce63e9b4e64fc18303972b5", size = 101301, upload-time = "2024-01-06T02:10:57.829Z" } +sdist = { url = "https://files.pythonhosted.org/packages/24/30/6b0809f4510673dc723187aeaf24c7f5459922d01e2f794277a3dfb90345/wcwidth-0.2.14.tar.gz", hash = "sha256:4d478375d31bc5395a3c55c40ccdf3354688364cd61c4f6adacaa9215d0b3605", size = 102293, upload-time = "2025-09-22T16:29:53.023Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/fd/84/fd2ba7aafacbad3c4201d395674fc6348826569da3c0937e75505ead3528/wcwidth-0.2.13-py2.py3-none-any.whl", hash = "sha256:3da69048e4540d84af32131829ff948f1e022c1c6bdb8d6102117aac784f6859", size = 34166, upload-time = "2024-01-06T02:10:55.763Z" }, + { url = "https://files.pythonhosted.org/packages/af/b5/123f13c975e9f27ab9c0770f514345bd406d0e8d3b7a0723af9d43f710af/wcwidth-0.2.14-py2.py3-none-any.whl", hash = "sha256:a7bb560c8aee30f9957e5f9895805edd20602f2d7f720186dfd906e82b4982e1", size = 37286, upload-time = "2025-09-22T16:29:51.641Z" }, ] [[package]] From 7f8f4a42dda6f6a299bd1f3d16d71aaf3f26666f Mon Sep 17 00:00:00 2001 From: Nick Murphy Date: Thu, 25 Sep 2025 15:50:25 -0400 Subject: [PATCH 486/521] Update Nox session and configuration for running mypy (#3094) * Update mypy configuration * Bump mypy minimum version * Remove mypy ignores for old deps * nox -s requirements * Install pip in Nox session for mypy mypy uses pip to install type hint packages when using --install-types * pre-commit autoupdate mostly * Skip printing uv sync output in mypy session This information is rarely needed when fixing type hint stuff. * Edit changelog: 3094.internal.rst * Edit changelog: 3094.internal.rst --- .pre-commit-config.yaml | 6 +++--- changelog/3094.internal.rst | 1 + mypy.ini | 14 +++++--------- noxfile.py | 3 +++ pyproject.toml | 2 +- uv.lock | 2 +- 6 files changed, 14 insertions(+), 14 deletions(-) create mode 100644 changelog/3094.internal.rst diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 4cb408e622..dd0f1ebd9e 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -28,7 +28,7 @@ repos: - id: check-yaml - repo: https://github.com/python-jsonschema/check-jsonschema - rev: 0.33.3 + rev: 0.34.0 hooks: - id: check-github-workflows @@ -87,7 +87,7 @@ repos: exclude: .pre-commit-search-and-replace.yaml - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.12.11 + rev: v0.13.2 hooks: - id: ruff name: ruff (see https://docs.astral.sh/ruff/rules) @@ -96,7 +96,7 @@ repos: name: autoformat source code with ruff-format - repo: https://github.com/asottile/blacken-docs - rev: 1.19.1 + rev: 1.20.0 hooks: - id: blacken-docs name: autoformat code blocks in docs diff --git a/changelog/3094.internal.rst b/changelog/3094.internal.rst new file mode 100644 index 0000000000..9f23a3dbe5 --- /dev/null +++ b/changelog/3094.internal.rst @@ -0,0 +1 @@ +Removed obsolete configuration settings from :file:`mypy.ini`. diff --git a/mypy.ini b/mypy.ini index c093717935..48a4a17e96 100644 --- a/mypy.ini +++ b/mypy.ini @@ -5,6 +5,11 @@ exclude = (?x)( docs| \.run| \.tox| + \.nox| + env| + .env| + venv| + \.venv| ^conftest.py| build| _version.py| @@ -41,18 +46,12 @@ ignore_missing_imports = true [mypy-hypothesis.*] ignore_missing_imports = true -[mypy-ipywidgets.*] -ignore_missing_imports = true - [mypy-lmfit.*] ignore_missing_imports = true [mypy-mpmath.*] ignore_missing_imports = true -[mypy-numba.*] -ignore_missing_imports = true - [mypy-pkg_resources.*] ignore_missing_imports = true @@ -62,9 +61,6 @@ ignore_missing_imports = true [mypy-scipy.*] ignore_missing_imports = true -[mypy-setuptools.*] -ignore_missing_imports = true - [mypy-plasmapy._dev.scm_version] ignore_errors = true diff --git a/noxfile.py b/noxfile.py index 5a7fa29578..617bf010d6 100644 --- a/noxfile.py +++ b/noxfile.py @@ -519,8 +519,11 @@ def mypy(session: nox.Session) -> None: Configuration file: mypy.ini """ + session.install("pip") # mypy uses pip if --install-types is used + session.run_install( *uv_sync, + "--quiet", "--extra=tests", "--no-default-groups", f"--python={session.virtualenv.location}", diff --git a/pyproject.toml b/pyproject.toml index d72cddfc6f..f537b8d24f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -105,7 +105,7 @@ optional-dependencies.docs = [ # requirements to ensure that tests are run in consistent environments. optional-dependencies.tests = [ "hypothesis>=6.108.2", - "mypy>=1.11", + "mypy>=1.18.2", "nox[uv]>=2025.5.1", "pytest>=8.3.1", "pytest-cov>=5", diff --git a/uv.lock b/uv.lock index ec209a3f6a..3c0a435b12 100644 --- a/uv.lock +++ b/uv.lock @@ -1653,7 +1653,7 @@ requires-dist = [ { name = "lmfit", specifier = ">=1.1" }, { name = "matplotlib", specifier = ">=3.7" }, { name = "mpmath", specifier = ">=1.3" }, - { name = "mypy", marker = "extra == 'tests'", specifier = ">=1.11" }, + { name = "mypy", marker = "extra == 'tests'", specifier = ">=1.18.2" }, { name = "nbsphinx", marker = "extra == 'docs'", specifier = ">=0.9.4" }, { name = "nox", extras = ["uv"], marker = "extra == 'docs'", specifier = ">=2025.5.1" }, { name = "nox", extras = ["uv"], marker = "extra == 'tests'", specifier = ">=2025.5.1" }, From 0f2422dc5805e9cb4d52e626946ae79c729e1c3c Mon Sep 17 00:00:00 2001 From: Nick Murphy Date: Tue, 30 Sep 2025 14:06:29 -0400 Subject: [PATCH 487/521] Remove `pre-commit-search-and-replace` hook for `pre-commit` (#3113) * Remove pre-commit-search-and-replace hook for pre-commit * Edit changelog: 3113.internal.rst --- .pre-commit-config.yaml | 11 ---- .pre-commit-search-and-replace.yaml | 79 ----------------------------- changelog/3113.internal.rst | 1 + 3 files changed, 1 insertion(+), 90 deletions(-) delete mode 100644 .pre-commit-search-and-replace.yaml create mode 100644 changelog/3113.internal.rst diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index dd0f1ebd9e..1f448a4d0e 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -2,10 +2,6 @@ ci: autofix_prs: false autoupdate_schedule: quarterly -# Specify the default version of Ruby in case it is not installed -default_language_version: - ruby: 2.7.2 - repos: - repo: https://github.com/pre-commit/pre-commit-hooks @@ -53,13 +49,6 @@ repos: # run this hook on `labeler.yml` (or certain other files). exclude: .github/labeler.yml|.pre-commit-search-and-replace.yaml -- repo: https://github.com/mattlqx/pre-commit-search-and-replace - # keep at v1.0.5 - rev: v1.0.5 - hooks: - - id: search-and-replace - exclude: changelog/README.rst|docs/changelog/.*|.sourcery.yaml|docs/_global_substitutions.py|CHANGELOG.rst|docs/contributing/doc_guide.rst - - repo: https://github.com/pre-commit/pygrep-hooks rev: v1.10.0 hooks: diff --git a/.pre-commit-search-and-replace.yaml b/.pre-commit-search-and-replace.yaml deleted file mode 100644 index 646931e490..0000000000 --- a/.pre-commit-search-and-replace.yaml +++ /dev/null @@ -1,79 +0,0 @@ -# Include regular expressions between slashes. The "|" means "or". -# If there are special characters in one of the fields, put it in single -# quotes. - -- search: /Plasmapy|PlasmaPY/PlasmPy|Plasmpy|Palsmapy|PlasmaPY/ - replacement: PlasmaPy - description: Fix common misspellings and use consistent capitalization for PlasmaPy - -- search: /plasmpy|plaspmy|plasapy|palsmapy/ - replacement: plasmapy - description: Fix common misspellings of plasmapy - -- search: AstroPy - replacement: Astropy - -- search: from astropy import units as u - replacement: import astropy.units as u - -- search: from astropy import constants as const - replacement: import astropy.constants as const - -- search: '|array-like|' - replacement: '|array_like|' - description: NumPy uses an underscore in 'array_like' - -- search: ':term:`particle-like`' - replacement: '|particle-like|' - description: Apply reStructuredText substitution - -- search: ':term:`array_like`' - replacement: '|array_like|' - description: Apply reStructuredText substitution - -- search: 'optional, |keyword-only|' - replacement: '|keyword-only|, optional' - description: Keep a consistent order in type specifications - -- search: ', optional, default:' - replacement: ', default:' - description: No need to specify that a parameter is optional if there is a default value - -- search: 'the the ' - replacement: 'the ' - description: Fix common grammar error - -- search: 'MacOS' - replacement: 'macOS' - -- search: 'particle="e"' - replacement: 'particle="e-"' - description: Use canonical symbol for electron - -- search: 'particle="p"' - replacement: 'particle="p+"' - description: Use canonical symbol for proton - -- search: 'ion="p"' - replacement: 'ion="p+"' - description: Use canonical symbol for proton - -- search: '|nox|' - replacement: '|Nox|' - description: Nox is capitalized except when used as a command - -- search: 'nox -e' - replacement: 'nox -s' - description: The -s refers to Nox sessions, while the -e is from tox environments - -- search: '``~plasmapy' - description: Either enclose the namespace with single backticks to make it a link, or remove the tilde and keep it a literal - -- search: /astropy\.unit\./ - replacement: 'astropy.units.' - -- search: quantitity - replacement: quantity - -- search: quantitities - replacement: quantities diff --git a/changelog/3113.internal.rst b/changelog/3113.internal.rst new file mode 100644 index 0000000000..a4a4b7d0a9 --- /dev/null +++ b/changelog/3113.internal.rst @@ -0,0 +1 @@ +Removed ``pre-commit-search-and-replace`` as a |pre-commit| hook. From a24b0a286eb3bfa9938be9771f97e7e29565f3dc Mon Sep 17 00:00:00 2001 From: "plasmapy-requirements-bot[bot]" <134649236+plasmapy-requirements-bot[bot]@users.noreply.github.com> Date: Thu, 2 Oct 2025 12:55:55 -0400 Subject: [PATCH 488/521] Update requirements with 'nox -s requirements' (#3115) Co-authored-by: namurphy <8931994+namurphy@users.noreply.github.com> --- uv.lock | 383 ++++++++++++++++++++++++++++++++------------------------ 1 file changed, 221 insertions(+), 162 deletions(-) diff --git a/uv.lock b/uv.lock index 3c0a435b12..373727a94a 100644 --- a/uv.lock +++ b/uv.lock @@ -80,11 +80,11 @@ wheels = [ [[package]] name = "astropy-iers-data" -version = "0.2025.9.22.0.37.25" +version = "0.2025.9.29.0.35.48" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/a4/01/853d80fdff5c6820e3d58fc88134c0cf1cd3fa3bbb982d3ae4cb84766026/astropy_iers_data-0.2025.9.22.0.37.25.tar.gz", hash = "sha256:6808ba4531b339324deb106bce4ecde6df178bcd62e763dba22289dc6e23cb83", size = 1909241, upload-time = "2025-09-22T00:38:11.36Z" } +sdist = { url = "https://files.pythonhosted.org/packages/3b/9f/73b96768c677bbf31da639ba12a5f54a0b28ed9fd292ce1af2b6b6b591c9/astropy_iers_data-0.2025.9.29.0.35.48.tar.gz", hash = "sha256:0a7841c9a0ff41e2abafcde984cb6b271cdfd9cb5b13e01d5ddd0ed2e8fc4065", size = 1909905, upload-time = "2025-09-29T00:36:26.92Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/57/05/96b98bf096dcda278a8fe74ae2812f4e6ba3402009901e084c173d32b857/astropy_iers_data-0.2025.9.22.0.37.25-py3-none-any.whl", hash = "sha256:0ae01b0b666d545fed6e810e55b152c62ea35bde742ea3c187f974162f143a3c", size = 1964831, upload-time = "2025-09-22T00:38:09.427Z" }, + { url = "https://files.pythonhosted.org/packages/19/3a/1fd856a497a4add1b9b782061b5a804ed35a66e395a43a08f877eb32b193/astropy_iers_data-0.2025.9.29.0.35.48-py3-none-any.whl", hash = "sha256:c6988670a03a66fefe9266164194c8e5d74513efd13af47efe2829b7be4b5159", size = 1965541, upload-time = "2025-09-29T00:36:24.918Z" }, ] [[package]] @@ -116,15 +116,15 @@ wheels = [ [[package]] name = "beautifulsoup4" -version = "4.13.5" +version = "4.14.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "soupsieve" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/85/2e/3e5079847e653b1f6dc647aa24549d68c6addb4c595cc0d902d1b19308ad/beautifulsoup4-4.13.5.tar.gz", hash = "sha256:5e70131382930e7c3de33450a2f54a63d5e4b19386eab43a5b34d594268f3695", size = 622954, upload-time = "2025-08-24T14:06:13.168Z" } +sdist = { url = "https://files.pythonhosted.org/packages/77/e9/df2358efd7659577435e2177bfa69cba6c33216681af51a707193dec162a/beautifulsoup4-4.14.2.tar.gz", hash = "sha256:2a98ab9f944a11acee9cc848508ec28d9228abfd522ef0fad6a02a72e0ded69e", size = 625822, upload-time = "2025-09-29T10:05:42.613Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/04/eb/f4151e0c7377a6e08a38108609ba5cede57986802757848688aeedd1b9e8/beautifulsoup4-4.13.5-py3-none-any.whl", hash = "sha256:642085eaa22233aceadff9c69651bc51e8bf3f874fb6d7104ece2beb24b47c4a", size = 105113, upload-time = "2025-08-24T14:06:14.884Z" }, + { url = "https://files.pythonhosted.org/packages/94/fe/3aed5d0be4d404d12d36ab97e2f1791424d9ca39c2f754a6285d59a3b01d/beautifulsoup4-4.14.2-py3-none-any.whl", hash = "sha256:5ef6fa3a8cbece8488d66985560f97ed091e22bbc4e9c2338508a9d5de6d4515", size = 106392, upload-time = "2025-09-29T10:05:43.771Z" }, ] [[package]] @@ -621,51 +621,51 @@ wheels = [ [[package]] name = "fonttools" -version = "4.60.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/27/d9/4eabd956fe123651a1f0efe29d9758b3837b5ae9a98934bdb571117033bb/fonttools-4.60.0.tar.gz", hash = "sha256:8f5927f049091a0ca74d35cce7f78e8f7775c83a6901a8fbe899babcc297146a", size = 3553671, upload-time = "2025-09-17T11:34:01.504Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/da/3d/c57731fbbf204ef1045caca28d5176430161ead73cd9feac3e9d9ef77ee6/fonttools-4.60.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:a9106c202d68ff5f9b4a0094c4d7ad2eaa7e9280f06427b09643215e706eb016", size = 2830883, upload-time = "2025-09-17T11:32:10.552Z" }, - { url = "https://files.pythonhosted.org/packages/cc/2d/b7a6ebaed464ce441c755252cc222af11edc651d17c8f26482f429cc2c0e/fonttools-4.60.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:9da3a4a3f2485b156bb429b4f8faa972480fc01f553f7c8c80d05d48f17eec89", size = 2356005, upload-time = "2025-09-17T11:32:13.248Z" }, - { url = "https://files.pythonhosted.org/packages/ee/c2/ea834e921324e2051403e125c1fe0bfbdde4951a7c1784e4ae6bdbd286cc/fonttools-4.60.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1f84de764c6057b2ffd4feb50ddef481d92e348f0c70f2c849b723118d352bf3", size = 5041201, upload-time = "2025-09-17T11:32:15.373Z" }, - { url = "https://files.pythonhosted.org/packages/93/3c/1c64a338e9aa410d2d0728827d5bb1301463078cb225b94589f27558b427/fonttools-4.60.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:800b3fa0d5c12ddff02179d45b035a23989a6c597a71c8035c010fff3b2ef1bb", size = 4977696, upload-time = "2025-09-17T11:32:17.674Z" }, - { url = "https://files.pythonhosted.org/packages/07/cc/c8c411a0d9732bb886b870e052f20658fec9cf91118314f253950d2c1d65/fonttools-4.60.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8dd68f60b030277f292a582d31c374edfadc60bb33d51ec7b6cd4304531819ba", size = 5020386, upload-time = "2025-09-17T11:32:20.089Z" }, - { url = "https://files.pythonhosted.org/packages/13/01/1d3bc07cf92e7f4fc27f06d4494bf6078dc595b2e01b959157a4fd23df12/fonttools-4.60.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:53328e3ca9e5c8660ef6de07c35f8f312c189b757535e12141be7a8ec942de6e", size = 5131575, upload-time = "2025-09-17T11:32:22.582Z" }, - { url = "https://files.pythonhosted.org/packages/5a/16/08db3917ee19e89d2eb0ee637d37cd4136c849dc421ff63f406b9165c1a1/fonttools-4.60.0-cp311-cp311-win32.whl", hash = "sha256:d493c175ddd0b88a5376e61163e3e6fde3be8b8987db9b092e0a84650709c9e7", size = 2229297, upload-time = "2025-09-17T11:32:24.834Z" }, - { url = "https://files.pythonhosted.org/packages/d2/0b/76764da82c0dfcea144861f568d9e83f4b921e84f2be617b451257bb25a7/fonttools-4.60.0-cp311-cp311-win_amd64.whl", hash = "sha256:cc2770c9dc49c2d0366e9683f4d03beb46c98042d7ccc8ddbadf3459ecb051a7", size = 2277193, upload-time = "2025-09-17T11:32:27.094Z" }, - { url = "https://files.pythonhosted.org/packages/2a/9b/706ebf84b55ab03439c1f3a94d6915123c0d96099f4238b254fdacffe03a/fonttools-4.60.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:8c68928a438d60dfde90e2f09aa7f848ed201176ca6652341744ceec4215859f", size = 2831953, upload-time = "2025-09-17T11:32:29.39Z" }, - { url = "https://files.pythonhosted.org/packages/76/40/782f485be450846e4f3aecff1f10e42af414fc6e19d235c70020f64278e1/fonttools-4.60.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b7133821249097cffabf0624eafd37f5a3358d5ce814febe9db688e3673e724e", size = 2351716, upload-time = "2025-09-17T11:32:31.46Z" }, - { url = "https://files.pythonhosted.org/packages/39/77/ad8d2a6ecc19716eb488c8cf118de10f7802e14bdf61d136d7b52358d6b1/fonttools-4.60.0-cp312-cp312-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:d3638905d3d77ac8791127ce181f7cb434f37e4204d8b2e31b8f1e154320b41f", size = 4922729, upload-time = "2025-09-17T11:32:33.659Z" }, - { url = "https://files.pythonhosted.org/packages/6b/48/aa543037c6e7788e1bc36b3f858ac70a59d32d0f45915263d0b330a35140/fonttools-4.60.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7968a26ef010ae89aabbb2f8e9dec1e2709a2541bb8620790451ee8aeb4f6fbf", size = 4967188, upload-time = "2025-09-17T11:32:35.74Z" }, - { url = "https://files.pythonhosted.org/packages/ac/58/e407d2028adc6387947eff8f2940b31f4ed40b9a83c2c7bbc8b9255126e2/fonttools-4.60.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1ef01ca7847c356b0fe026b7b92304bc31dc60a4218689ee0acc66652c1a36b2", size = 4910043, upload-time = "2025-09-17T11:32:38.054Z" }, - { url = "https://files.pythonhosted.org/packages/16/ef/e78519b3c296ef757a21b792fc6a785aa2ef9a2efb098083d8ed5f6ee2ba/fonttools-4.60.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:f3482d7ed7867edfcf785f77c1dffc876c4b2ddac19539c075712ff2a0703cf5", size = 5061980, upload-time = "2025-09-17T11:32:40.457Z" }, - { url = "https://files.pythonhosted.org/packages/00/4c/ad72444d1e3ef704ee90af8d5abf198016a39908d322bf41235562fb01a0/fonttools-4.60.0-cp312-cp312-win32.whl", hash = "sha256:8c937c4fe8addff575a984c9519433391180bf52cf35895524a07b520f376067", size = 2217750, upload-time = "2025-09-17T11:32:42.586Z" }, - { url = "https://files.pythonhosted.org/packages/46/55/3e8ac21963e130242f5a9ea2ebc57f5726d704bf4dcca89088b5b637b2d3/fonttools-4.60.0-cp312-cp312-win_amd64.whl", hash = "sha256:99b06d5d6f29f32e312adaed0367112f5ff2d300ea24363d377ec917daf9e8c5", size = 2266025, upload-time = "2025-09-17T11:32:44.8Z" }, - { url = "https://files.pythonhosted.org/packages/b4/6b/d090cd54abe88192fe3010f573508b2592cf1d1f98b14bcb799a8ad20525/fonttools-4.60.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:97100ba820936cdb5148b634e0884f0088699c7e2f1302ae7bba3747c7a19fb3", size = 2824791, upload-time = "2025-09-17T11:32:47.002Z" }, - { url = "https://files.pythonhosted.org/packages/97/8c/7ccb5a27aac9a535623fe04935fb9f469a4f8a1253991af9fbac2fe88c17/fonttools-4.60.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:03fccf84f377f83e99a5328a9ebe6b41e16fcf64a1450c352b6aa7e0deedbc01", size = 2347081, upload-time = "2025-09-17T11:32:49.204Z" }, - { url = "https://files.pythonhosted.org/packages/f8/1a/c14f0bb20b4cb7849dc0519f0ab0da74318d52236dc23168530569958599/fonttools-4.60.0-cp313-cp313-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:a3ef06671f862cd7da78ab105fbf8dce9da3634a8f91b3a64ed5c29c0ac6a9a8", size = 4902095, upload-time = "2025-09-17T11:32:51.848Z" }, - { url = "https://files.pythonhosted.org/packages/c9/a0/c7c91f07c40de5399cbaec7d25e04c9afac6c8f80036a98c125efdb5fe1a/fonttools-4.60.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3f2195faf96594c238462c420c7eff97d1aa51de595434f806ec3952df428616", size = 4959137, upload-time = "2025-09-17T11:32:54.185Z" }, - { url = "https://files.pythonhosted.org/packages/38/d2/169e49498df9f2c721763aa39b0bf3d08cb762864ebc8a8ddb99f5ba7ec8/fonttools-4.60.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:3887008865fa4f56cff58a1878f1300ba81a4e34f76daf9b47234698493072ee", size = 4900467, upload-time = "2025-09-17T11:32:56.664Z" }, - { url = "https://files.pythonhosted.org/packages/cc/9c/bfb56b89c3eab8bcb739c7fd1e8a43285c8dd833e1e1d18d4f54f2f641af/fonttools-4.60.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5567bd130378f21231d3856d8f0571dcdfcd77e47832978c26dabe572d456daa", size = 5043508, upload-time = "2025-09-17T11:32:58.944Z" }, - { url = "https://files.pythonhosted.org/packages/77/30/2b511c7eb99faee1fd9a0b42e984fb91275da3d681da650af4edf409d0fd/fonttools-4.60.0-cp313-cp313-win32.whl", hash = "sha256:699d0b521ec0b188ac11f2c14ccf6a926367795818ddf2bd00a273e9a052dd20", size = 2216037, upload-time = "2025-09-17T11:33:01.192Z" }, - { url = "https://files.pythonhosted.org/packages/3d/73/a2cc5ee4faeb0302cc81942c27f3b516801bf489fdc422a1b20090fff695/fonttools-4.60.0-cp313-cp313-win_amd64.whl", hash = "sha256:24296163268e7c800009711ce5c0e9997be8882c0bd546696c82ef45966163a6", size = 2265190, upload-time = "2025-09-17T11:33:03.935Z" }, - { url = "https://files.pythonhosted.org/packages/86/dd/a126706e45e0ce097cef6de4108b5597795acaa945fdbdd922dbc090d335/fonttools-4.60.0-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:b6fe3efdc956bdad95145cea906ad9ff345c17b706356dfc1098ce3230591343", size = 2821835, upload-time = "2025-09-17T11:33:06.094Z" }, - { url = "https://files.pythonhosted.org/packages/ac/90/5c17f311bbd983fd614b82a7a06da967b5d3c87e3e61cf34de6029a92ff4/fonttools-4.60.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:764b2aaab839762a3aa3207e5b3f0e0dfa41799e0b091edec5fcbccc584fdab5", size = 2344536, upload-time = "2025-09-17T11:33:08.574Z" }, - { url = "https://files.pythonhosted.org/packages/60/67/48c1a6229b2a5668c4111fbd1694ca417adedc1254c5cd2f9a11834c429d/fonttools-4.60.0-cp314-cp314-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:b81c7c47d9e78106a4d70f1dbeb49150513171715e45e0d2661809f2b0e3f710", size = 4842494, upload-time = "2025-09-17T11:33:11.338Z" }, - { url = "https://files.pythonhosted.org/packages/13/3e/83b0b37d02b7e321cbe2b8fcec0aa18571f0a47d3dc222196404371d83b6/fonttools-4.60.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:799ff60ee66b300ebe1fe6632b1cc55a66400fe815cef7b034d076bce6b1d8fc", size = 4943203, upload-time = "2025-09-17T11:33:13.285Z" }, - { url = "https://files.pythonhosted.org/packages/c9/07/11163e49497c53392eaca210a474104e4987c17ca7731f8754ba0d416a67/fonttools-4.60.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:f9878abe155ddd1b433bab95d027a686898a6afba961f3c5ca14b27488f2d772", size = 4889233, upload-time = "2025-09-17T11:33:15.175Z" }, - { url = "https://files.pythonhosted.org/packages/60/90/e85005d955cb26e7de015d5678778b8cc3293c0f3d717865675bd641fbfc/fonttools-4.60.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:ded432b7133ea4602fdb4731a4a7443a8e9548edad28987b99590cf6da626254", size = 4998335, upload-time = "2025-09-17T11:33:17.217Z" }, - { url = "https://files.pythonhosted.org/packages/2a/82/0374ad53729de6e3788ecdb8a3731ce6592c5ffa9bff823cef2ffe0164af/fonttools-4.60.0-cp314-cp314-win32.whl", hash = "sha256:5d97cf3a9245316d5978628c05642b939809c4f55ca632ca40744cb9de6e8d4a", size = 2219840, upload-time = "2025-09-17T11:33:19.494Z" }, - { url = "https://files.pythonhosted.org/packages/11/c3/804cd47453dcafb7976f9825b43cc0e61a2fe30eddb971b681cd72c4ca65/fonttools-4.60.0-cp314-cp314-win_amd64.whl", hash = "sha256:61b9ef46dd5e9dcb6f437eb0cc5ed83d5049e1bf9348e31974ffee1235db0f8f", size = 2269891, upload-time = "2025-09-17T11:33:21.743Z" }, - { url = "https://files.pythonhosted.org/packages/75/bf/1bd760aca04098e7028b4e0e5f73b41ff74b322275698071454652476a44/fonttools-4.60.0-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:bba7e3470cf353e1484a36dfb4108f431c2859e3f6097fe10118eeae92166773", size = 2893361, upload-time = "2025-09-17T11:33:23.68Z" }, - { url = "https://files.pythonhosted.org/packages/25/35/7a2c09aa990ed77f34924def383f44fc576a5596cc3df8438071e1baa1ac/fonttools-4.60.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:c5ac6439a38c27b3287063176b3303b34982024b01e2e95bba8ac1e45f6d41c1", size = 2374086, upload-time = "2025-09-17T11:33:25.988Z" }, - { url = "https://files.pythonhosted.org/packages/77/a9/f85ed2493e82837ff73421f3f7a1c3ae8f0b14051307418c916d9563da1f/fonttools-4.60.0-cp314-cp314t-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:4acd21e9f125a1257da59edf7a6e9bd4abd76282770715c613f1fe482409e9f9", size = 4848766, upload-time = "2025-09-17T11:33:28.018Z" }, - { url = "https://files.pythonhosted.org/packages/d1/91/29830eda31ae9231a06d5246e5d0c686422d03456ed666e13576c24c3f97/fonttools-4.60.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b4a6fc53039ea047e35dc62b958af9cd397eedbc3fa42406d2910ae091b9ae37", size = 5084613, upload-time = "2025-09-17T11:33:30.562Z" }, - { url = "https://files.pythonhosted.org/packages/48/01/615905e7db2568fe1843145077e680443494b7caab2089527b7e112c7606/fonttools-4.60.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:ef34f44eadf133e94e82c775a33ee3091dd37ee0161c5f5ea224b46e3ce0fb8e", size = 4956620, upload-time = "2025-09-17T11:33:32.497Z" }, - { url = "https://files.pythonhosted.org/packages/97/8e/64e65255871ec2f13b6c00b5b12d08b928b504867cfb7e7ed73e5e941832/fonttools-4.60.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:d112cae3e7ad1bb5d7f7a60365fcf6c181374648e064a8c07617b240e7c828ee", size = 4973202, upload-time = "2025-09-17T11:33:34.561Z" }, - { url = "https://files.pythonhosted.org/packages/e0/6d/04d16243eb441e8de61074c7809e92d2e35df4cd11af5632e486bc630dab/fonttools-4.60.0-cp314-cp314t-win32.whl", hash = "sha256:0f7b2c251dc338973e892a1e153016114e7a75f6aac7a49b84d5d1a4c0608d08", size = 2281217, upload-time = "2025-09-17T11:33:36.965Z" }, - { url = "https://files.pythonhosted.org/packages/ab/5f/09bd2f9f28ef0d6f3620fa19699d11c4bc83ff8a2786d8ccdd97c209b19a/fonttools-4.60.0-cp314-cp314t-win_amd64.whl", hash = "sha256:c8a72771106bc7434098db35abecd84d608857f6e116d3ef00366b213c502ce9", size = 2344738, upload-time = "2025-09-17T11:33:39.372Z" }, - { url = "https://files.pythonhosted.org/packages/f9/a4/247d3e54eb5ed59e94e09866cfc4f9567e274fbf310ba390711851f63b3b/fonttools-4.60.0-py3-none-any.whl", hash = "sha256:496d26e4d14dcccdd6ada2e937e4d174d3138e3d73f5c9b6ec6eb2fd1dab4f66", size = 1142186, upload-time = "2025-09-17T11:33:59.287Z" }, +version = "4.60.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/4b/42/97a13e47a1e51a5a7142475bbcf5107fe3a68fc34aef331c897d5fb98ad0/fonttools-4.60.1.tar.gz", hash = "sha256:ef00af0439ebfee806b25f24c8f92109157ff3fac5731dc7867957812e87b8d9", size = 3559823, upload-time = "2025-09-29T21:13:27.129Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ea/85/639aa9bface1537e0fb0f643690672dde0695a5bbbc90736bc571b0b1941/fonttools-4.60.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:7b4c32e232a71f63a5d00259ca3d88345ce2a43295bb049d21061f338124246f", size = 2831872, upload-time = "2025-09-29T21:11:20.329Z" }, + { url = "https://files.pythonhosted.org/packages/6b/47/3c63158459c95093be9618794acb1067b3f4d30dcc5c3e8114b70e67a092/fonttools-4.60.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3630e86c484263eaac71d117085d509cbcf7b18f677906824e4bace598fb70d2", size = 2356990, upload-time = "2025-09-29T21:11:22.754Z" }, + { url = "https://files.pythonhosted.org/packages/94/dd/1934b537c86fcf99f9761823f1fc37a98fbd54568e8e613f29a90fed95a9/fonttools-4.60.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5c1015318e4fec75dd4943ad5f6a206d9727adf97410d58b7e32ab644a807914", size = 5042189, upload-time = "2025-09-29T21:11:25.061Z" }, + { url = "https://files.pythonhosted.org/packages/d2/d2/9f4e4c4374dd1daa8367784e1bd910f18ba886db1d6b825b12edf6db3edc/fonttools-4.60.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:e6c58beb17380f7c2ea181ea11e7db8c0ceb474c9dd45f48e71e2cb577d146a1", size = 4978683, upload-time = "2025-09-29T21:11:27.693Z" }, + { url = "https://files.pythonhosted.org/packages/cc/c4/0fb2dfd1ecbe9a07954cc13414713ed1eab17b1c0214ef07fc93df234a47/fonttools-4.60.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:ec3681a0cb34c255d76dd9d865a55f260164adb9fa02628415cdc2d43ee2c05d", size = 5021372, upload-time = "2025-09-29T21:11:30.257Z" }, + { url = "https://files.pythonhosted.org/packages/0c/d5/495fc7ae2fab20223cc87179a8f50f40f9a6f821f271ba8301ae12bb580f/fonttools-4.60.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f4b5c37a5f40e4d733d3bbaaef082149bee5a5ea3156a785ff64d949bd1353fa", size = 5132562, upload-time = "2025-09-29T21:11:32.737Z" }, + { url = "https://files.pythonhosted.org/packages/bc/fa/021dab618526323c744e0206b3f5c8596a2e7ae9aa38db5948a131123e83/fonttools-4.60.1-cp311-cp311-win32.whl", hash = "sha256:398447f3d8c0c786cbf1209711e79080a40761eb44b27cdafffb48f52bcec258", size = 2230288, upload-time = "2025-09-29T21:11:35.015Z" }, + { url = "https://files.pythonhosted.org/packages/bb/78/0e1a6d22b427579ea5c8273e1c07def2f325b977faaf60bb7ddc01456cb1/fonttools-4.60.1-cp311-cp311-win_amd64.whl", hash = "sha256:d066ea419f719ed87bc2c99a4a4bfd77c2e5949cb724588b9dd58f3fd90b92bf", size = 2278184, upload-time = "2025-09-29T21:11:37.434Z" }, + { url = "https://files.pythonhosted.org/packages/e3/f7/a10b101b7a6f8836a5adb47f2791f2075d044a6ca123f35985c42edc82d8/fonttools-4.60.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:7b0c6d57ab00dae9529f3faf187f2254ea0aa1e04215cf2f1a8ec277c96661bc", size = 2832953, upload-time = "2025-09-29T21:11:39.616Z" }, + { url = "https://files.pythonhosted.org/packages/ed/fe/7bd094b59c926acf2304d2151354ddbeb74b94812f3dc943c231db09cb41/fonttools-4.60.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:839565cbf14645952d933853e8ade66a463684ed6ed6c9345d0faf1f0e868877", size = 2352706, upload-time = "2025-09-29T21:11:41.826Z" }, + { url = "https://files.pythonhosted.org/packages/c0/ca/4bb48a26ed95a1e7eba175535fe5805887682140ee0a0d10a88e1de84208/fonttools-4.60.1-cp312-cp312-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:8177ec9676ea6e1793c8a084a90b65a9f778771998eb919d05db6d4b1c0b114c", size = 4923716, upload-time = "2025-09-29T21:11:43.893Z" }, + { url = "https://files.pythonhosted.org/packages/b8/9f/2cb82999f686c1d1ddf06f6ae1a9117a880adbec113611cc9d22b2fdd465/fonttools-4.60.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:996a4d1834524adbb423385d5a629b868ef9d774670856c63c9a0408a3063401", size = 4968175, upload-time = "2025-09-29T21:11:46.439Z" }, + { url = "https://files.pythonhosted.org/packages/18/79/be569699e37d166b78e6218f2cde8c550204f2505038cdd83b42edc469b9/fonttools-4.60.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a46b2f450bc79e06ef3b6394f0c68660529ed51692606ad7f953fc2e448bc903", size = 4911031, upload-time = "2025-09-29T21:11:48.977Z" }, + { url = "https://files.pythonhosted.org/packages/cc/9f/89411cc116effaec5260ad519162f64f9c150e5522a27cbb05eb62d0c05b/fonttools-4.60.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:6ec722ee589e89a89f5b7574f5c45604030aa6ae24cb2c751e2707193b466fed", size = 5062966, upload-time = "2025-09-29T21:11:54.344Z" }, + { url = "https://files.pythonhosted.org/packages/62/a1/f888221934b5731d46cb9991c7a71f30cb1f97c0ef5fcf37f8da8fce6c8e/fonttools-4.60.1-cp312-cp312-win32.whl", hash = "sha256:b2cf105cee600d2de04ca3cfa1f74f1127f8455b71dbad02b9da6ec266e116d6", size = 2218750, upload-time = "2025-09-29T21:11:56.601Z" }, + { url = "https://files.pythonhosted.org/packages/88/8f/a55b5550cd33cd1028601df41acd057d4be20efa5c958f417b0c0613924d/fonttools-4.60.1-cp312-cp312-win_amd64.whl", hash = "sha256:992775c9fbe2cf794786fa0ffca7f09f564ba3499b8fe9f2f80bd7197db60383", size = 2267026, upload-time = "2025-09-29T21:11:58.852Z" }, + { url = "https://files.pythonhosted.org/packages/7c/5b/cdd2c612277b7ac7ec8c0c9bc41812c43dc7b2d5f2b0897e15fdf5a1f915/fonttools-4.60.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:6f68576bb4bbf6060c7ab047b1574a1ebe5c50a17de62830079967b211059ebb", size = 2825777, upload-time = "2025-09-29T21:12:01.22Z" }, + { url = "https://files.pythonhosted.org/packages/d6/8a/de9cc0540f542963ba5e8f3a1f6ad48fa211badc3177783b9d5cadf79b5d/fonttools-4.60.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:eedacb5c5d22b7097482fa834bda0dafa3d914a4e829ec83cdea2a01f8c813c4", size = 2348080, upload-time = "2025-09-29T21:12:03.785Z" }, + { url = "https://files.pythonhosted.org/packages/2d/8b/371ab3cec97ee3fe1126b3406b7abd60c8fec8975fd79a3c75cdea0c3d83/fonttools-4.60.1-cp313-cp313-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:b33a7884fabd72bdf5f910d0cf46be50dce86a0362a65cfc746a4168c67eb96c", size = 4903082, upload-time = "2025-09-29T21:12:06.382Z" }, + { url = "https://files.pythonhosted.org/packages/04/05/06b1455e4bc653fcb2117ac3ef5fa3a8a14919b93c60742d04440605d058/fonttools-4.60.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2409d5fb7b55fd70f715e6d34e7a6e4f7511b8ad29a49d6df225ee76da76dd77", size = 4960125, upload-time = "2025-09-29T21:12:09.314Z" }, + { url = "https://files.pythonhosted.org/packages/8e/37/f3b840fcb2666f6cb97038793606bdd83488dca2d0b0fc542ccc20afa668/fonttools-4.60.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:c8651e0d4b3bdeda6602b85fdc2abbefc1b41e573ecb37b6779c4ca50753a199", size = 4901454, upload-time = "2025-09-29T21:12:11.931Z" }, + { url = "https://files.pythonhosted.org/packages/fd/9e/eb76f77e82f8d4a46420aadff12cec6237751b0fb9ef1de373186dcffb5f/fonttools-4.60.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:145daa14bf24824b677b9357c5e44fd8895c2a8f53596e1b9ea3496081dc692c", size = 5044495, upload-time = "2025-09-29T21:12:15.241Z" }, + { url = "https://files.pythonhosted.org/packages/f8/b3/cede8f8235d42ff7ae891bae8d619d02c8ac9fd0cfc450c5927a6200c70d/fonttools-4.60.1-cp313-cp313-win32.whl", hash = "sha256:2299df884c11162617a66b7c316957d74a18e3758c0274762d2cc87df7bc0272", size = 2217028, upload-time = "2025-09-29T21:12:17.96Z" }, + { url = "https://files.pythonhosted.org/packages/75/4d/b022c1577807ce8b31ffe055306ec13a866f2337ecee96e75b24b9b753ea/fonttools-4.60.1-cp313-cp313-win_amd64.whl", hash = "sha256:a3db56f153bd4c5c2b619ab02c5db5192e222150ce5a1bc10f16164714bc39ac", size = 2266200, upload-time = "2025-09-29T21:12:20.14Z" }, + { url = "https://files.pythonhosted.org/packages/9a/83/752ca11c1aa9a899b793a130f2e466b79ea0cf7279c8d79c178fc954a07b/fonttools-4.60.1-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:a884aef09d45ba1206712c7dbda5829562d3fea7726935d3289d343232ecb0d3", size = 2822830, upload-time = "2025-09-29T21:12:24.406Z" }, + { url = "https://files.pythonhosted.org/packages/57/17/bbeab391100331950a96ce55cfbbff27d781c1b85ebafb4167eae50d9fe3/fonttools-4.60.1-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:8a44788d9d91df72d1a5eac49b31aeb887a5f4aab761b4cffc4196c74907ea85", size = 2345524, upload-time = "2025-09-29T21:12:26.819Z" }, + { url = "https://files.pythonhosted.org/packages/3d/2e/d4831caa96d85a84dd0da1d9f90d81cec081f551e0ea216df684092c6c97/fonttools-4.60.1-cp314-cp314-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:e852d9dda9f93ad3651ae1e3bb770eac544ec93c3807888798eccddf84596537", size = 4843490, upload-time = "2025-09-29T21:12:29.123Z" }, + { url = "https://files.pythonhosted.org/packages/49/13/5e2ea7c7a101b6fc3941be65307ef8df92cbbfa6ec4804032baf1893b434/fonttools-4.60.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:154cb6ee417e417bf5f7c42fe25858c9140c26f647c7347c06f0cc2d47eff003", size = 4944184, upload-time = "2025-09-29T21:12:31.414Z" }, + { url = "https://files.pythonhosted.org/packages/0c/2b/cf9603551c525b73fc47c52ee0b82a891579a93d9651ed694e4e2cd08bb8/fonttools-4.60.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:5664fd1a9ea7f244487ac8f10340c4e37664675e8667d6fee420766e0fb3cf08", size = 4890218, upload-time = "2025-09-29T21:12:33.936Z" }, + { url = "https://files.pythonhosted.org/packages/fd/2f/933d2352422e25f2376aae74f79eaa882a50fb3bfef3c0d4f50501267101/fonttools-4.60.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:583b7f8e3c49486e4d489ad1deacfb8d5be54a8ef34d6df824f6a171f8511d99", size = 4999324, upload-time = "2025-09-29T21:12:36.637Z" }, + { url = "https://files.pythonhosted.org/packages/38/99/234594c0391221f66216bc2c886923513b3399a148defaccf81dc3be6560/fonttools-4.60.1-cp314-cp314-win32.whl", hash = "sha256:66929e2ea2810c6533a5184f938502cfdaea4bc3efb7130d8cc02e1c1b4108d6", size = 2220861, upload-time = "2025-09-29T21:12:39.108Z" }, + { url = "https://files.pythonhosted.org/packages/3e/1d/edb5b23726dde50fc4068e1493e4fc7658eeefcaf75d4c5ffce067d07ae5/fonttools-4.60.1-cp314-cp314-win_amd64.whl", hash = "sha256:f3d5be054c461d6a2268831f04091dc82753176f6ea06dc6047a5e168265a987", size = 2270934, upload-time = "2025-09-29T21:12:41.339Z" }, + { url = "https://files.pythonhosted.org/packages/fb/da/1392aaa2170adc7071fe7f9cfd181a5684a7afcde605aebddf1fb4d76df5/fonttools-4.60.1-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:b6379e7546ba4ae4b18f8ae2b9bc5960936007a1c0e30b342f662577e8bc3299", size = 2894340, upload-time = "2025-09-29T21:12:43.774Z" }, + { url = "https://files.pythonhosted.org/packages/bf/a7/3b9f16e010d536ce567058b931a20b590d8f3177b2eda09edd92e392375d/fonttools-4.60.1-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:9d0ced62b59e0430b3690dbc5373df1c2aa7585e9a8ce38eff87f0fd993c5b01", size = 2375073, upload-time = "2025-09-29T21:12:46.437Z" }, + { url = "https://files.pythonhosted.org/packages/9b/b5/e9bcf51980f98e59bb5bb7c382a63c6f6cac0eec5f67de6d8f2322382065/fonttools-4.60.1-cp314-cp314t-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:875cb7764708b3132637f6c5fb385b16eeba0f7ac9fa45a69d35e09b47045801", size = 4849758, upload-time = "2025-09-29T21:12:48.694Z" }, + { url = "https://files.pythonhosted.org/packages/e3/dc/1d2cf7d1cba82264b2f8385db3f5960e3d8ce756b4dc65b700d2c496f7e9/fonttools-4.60.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a184b2ea57b13680ab6d5fbde99ccef152c95c06746cb7718c583abd8f945ccc", size = 5085598, upload-time = "2025-09-29T21:12:51.081Z" }, + { url = "https://files.pythonhosted.org/packages/5d/4d/279e28ba87fb20e0c69baf72b60bbf1c4d873af1476806a7b5f2b7fac1ff/fonttools-4.60.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:026290e4ec76583881763fac284aca67365e0be9f13a7fb137257096114cb3bc", size = 4957603, upload-time = "2025-09-29T21:12:53.423Z" }, + { url = "https://files.pythonhosted.org/packages/78/d4/ff19976305e0c05aa3340c805475abb00224c954d3c65e82c0a69633d55d/fonttools-4.60.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:f0e8817c7d1a0c2eedebf57ef9a9896f3ea23324769a9a2061a80fe8852705ed", size = 4974184, upload-time = "2025-09-29T21:12:55.962Z" }, + { url = "https://files.pythonhosted.org/packages/63/22/8553ff6166f5cd21cfaa115aaacaa0dc73b91c079a8cfd54a482cbc0f4f5/fonttools-4.60.1-cp314-cp314t-win32.whl", hash = "sha256:1410155d0e764a4615774e5c2c6fc516259fe3eca5882f034eb9bfdbee056259", size = 2282241, upload-time = "2025-09-29T21:12:58.179Z" }, + { url = "https://files.pythonhosted.org/packages/8a/cb/fa7b4d148e11d5a72761a22e595344133e83a9507a4c231df972e657579b/fonttools-4.60.1-cp314-cp314t-win_amd64.whl", hash = "sha256:022beaea4b73a70295b688f817ddc24ed3e3418b5036ffcd5658141184ef0d0c", size = 2345760, upload-time = "2025-09-29T21:13:00.375Z" }, + { url = "https://files.pythonhosted.org/packages/c7/93/0dd45cd283c32dea1545151d8c3637b4b8c53cdb3a625aeb2885b184d74d/fonttools-4.60.1-py3-none-any.whl", hash = "sha256:906306ac7afe2156fcf0042173d6ebbb05416af70f6b370967b47f8f00103bbb", size = 1143175, upload-time = "2025-09-29T21:13:24.134Z" }, ] [[package]] @@ -760,7 +760,7 @@ wheels = [ [[package]] name = "ipython" -version = "9.5.0" +version = "9.6.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "colorama", marker = "sys_platform == 'win32'" }, @@ -775,9 +775,9 @@ dependencies = [ { name = "traitlets" }, { name = "typing-extensions", marker = "python_full_version < '3.12'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/6e/71/a86262bf5a68bf211bcc71fe302af7e05f18a2852fdc610a854d20d085e6/ipython-9.5.0.tar.gz", hash = "sha256:129c44b941fe6d9b82d36fc7a7c18127ddb1d6f02f78f867f402e2e3adde3113", size = 4389137, upload-time = "2025-08-29T12:15:21.519Z" } +sdist = { url = "https://files.pythonhosted.org/packages/2a/34/29b18c62e39ee2f7a6a3bba7efd952729d8aadd45ca17efc34453b717665/ipython-9.6.0.tar.gz", hash = "sha256:5603d6d5d356378be5043e69441a072b50a5b33b4503428c77b04cb8ce7bc731", size = 4396932, upload-time = "2025-09-29T10:55:53.948Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/08/2a/5628a99d04acb2d2f2e749cdf4ea571d2575e898df0528a090948018b726/ipython-9.5.0-py3-none-any.whl", hash = "sha256:88369ffa1d5817d609120daa523a6da06d02518e582347c29f8451732a9c5e72", size = 612426, upload-time = "2025-08-29T12:15:18.866Z" }, + { url = "https://files.pythonhosted.org/packages/48/c5/d5e07995077e48220269c28a221e168c91123ad5ceee44d548f54a057fc0/ipython-9.6.0-py3-none-any.whl", hash = "sha256:5f77efafc886d2f023442479b8149e7d86547ad0a979e9da9f045d252f648196", size = 616170, upload-time = "2025-09-29T10:55:47.676Z" }, ] [[package]] @@ -1024,50 +1024,76 @@ wheels = [ [[package]] name = "markupsafe" -version = "3.0.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/b2/97/5d42485e71dfc078108a86d6de8fa46db44a1a9295e89c5d6d4a06e23a62/markupsafe-3.0.2.tar.gz", hash = "sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0", size = 20537, upload-time = "2024-10-18T15:21:54.129Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/6b/28/bbf83e3f76936960b850435576dd5e67034e200469571be53f69174a2dfd/MarkupSafe-3.0.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9025b4018f3a1314059769c7bf15441064b2207cb3f065e6ea1e7359cb46db9d", size = 14353, upload-time = "2024-10-18T15:21:02.187Z" }, - { url = "https://files.pythonhosted.org/packages/6c/30/316d194b093cde57d448a4c3209f22e3046c5bb2fb0820b118292b334be7/MarkupSafe-3.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:93335ca3812df2f366e80509ae119189886b0f3c2b81325d39efdb84a1e2ae93", size = 12392, upload-time = "2024-10-18T15:21:02.941Z" }, - { url = "https://files.pythonhosted.org/packages/f2/96/9cdafba8445d3a53cae530aaf83c38ec64c4d5427d975c974084af5bc5d2/MarkupSafe-3.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2cb8438c3cbb25e220c2ab33bb226559e7afb3baec11c4f218ffa7308603c832", size = 23984, upload-time = "2024-10-18T15:21:03.953Z" }, - { url = "https://files.pythonhosted.org/packages/f1/a4/aefb044a2cd8d7334c8a47d3fb2c9f328ac48cb349468cc31c20b539305f/MarkupSafe-3.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a123e330ef0853c6e822384873bef7507557d8e4a082961e1defa947aa59ba84", size = 23120, upload-time = "2024-10-18T15:21:06.495Z" }, - { url = "https://files.pythonhosted.org/packages/8d/21/5e4851379f88f3fad1de30361db501300d4f07bcad047d3cb0449fc51f8c/MarkupSafe-3.0.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e084f686b92e5b83186b07e8a17fc09e38fff551f3602b249881fec658d3eca", size = 23032, upload-time = "2024-10-18T15:21:07.295Z" }, - { url = "https://files.pythonhosted.org/packages/00/7b/e92c64e079b2d0d7ddf69899c98842f3f9a60a1ae72657c89ce2655c999d/MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d8213e09c917a951de9d09ecee036d5c7d36cb6cb7dbaece4c71a60d79fb9798", size = 24057, upload-time = "2024-10-18T15:21:08.073Z" }, - { url = "https://files.pythonhosted.org/packages/f9/ac/46f960ca323037caa0a10662ef97d0a4728e890334fc156b9f9e52bcc4ca/MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:5b02fb34468b6aaa40dfc198d813a641e3a63b98c2b05a16b9f80b7ec314185e", size = 23359, upload-time = "2024-10-18T15:21:09.318Z" }, - { url = "https://files.pythonhosted.org/packages/69/84/83439e16197337b8b14b6a5b9c2105fff81d42c2a7c5b58ac7b62ee2c3b1/MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:0bff5e0ae4ef2e1ae4fdf2dfd5b76c75e5c2fa4132d05fc1b0dabcd20c7e28c4", size = 23306, upload-time = "2024-10-18T15:21:10.185Z" }, - { url = "https://files.pythonhosted.org/packages/9a/34/a15aa69f01e2181ed8d2b685c0d2f6655d5cca2c4db0ddea775e631918cd/MarkupSafe-3.0.2-cp311-cp311-win32.whl", hash = "sha256:6c89876f41da747c8d3677a2b540fb32ef5715f97b66eeb0c6b66f5e3ef6f59d", size = 15094, upload-time = "2024-10-18T15:21:11.005Z" }, - { url = "https://files.pythonhosted.org/packages/da/b8/3a3bd761922d416f3dc5d00bfbed11f66b1ab89a0c2b6e887240a30b0f6b/MarkupSafe-3.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:70a87b411535ccad5ef2f1df5136506a10775d267e197e4cf531ced10537bd6b", size = 15521, upload-time = "2024-10-18T15:21:12.911Z" }, - { url = "https://files.pythonhosted.org/packages/22/09/d1f21434c97fc42f09d290cbb6350d44eb12f09cc62c9476effdb33a18aa/MarkupSafe-3.0.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:9778bd8ab0a994ebf6f84c2b949e65736d5575320a17ae8984a77fab08db94cf", size = 14274, upload-time = "2024-10-18T15:21:13.777Z" }, - { url = "https://files.pythonhosted.org/packages/6b/b0/18f76bba336fa5aecf79d45dcd6c806c280ec44538b3c13671d49099fdd0/MarkupSafe-3.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:846ade7b71e3536c4e56b386c2a47adf5741d2d8b94ec9dc3e92e5e1ee1e2225", size = 12348, upload-time = "2024-10-18T15:21:14.822Z" }, - { url = "https://files.pythonhosted.org/packages/e0/25/dd5c0f6ac1311e9b40f4af06c78efde0f3b5cbf02502f8ef9501294c425b/MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1c99d261bd2d5f6b59325c92c73df481e05e57f19837bdca8413b9eac4bd8028", size = 24149, upload-time = "2024-10-18T15:21:15.642Z" }, - { url = "https://files.pythonhosted.org/packages/f3/f0/89e7aadfb3749d0f52234a0c8c7867877876e0a20b60e2188e9850794c17/MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e17c96c14e19278594aa4841ec148115f9c7615a47382ecb6b82bd8fea3ab0c8", size = 23118, upload-time = "2024-10-18T15:21:17.133Z" }, - { url = "https://files.pythonhosted.org/packages/d5/da/f2eeb64c723f5e3777bc081da884b414671982008c47dcc1873d81f625b6/MarkupSafe-3.0.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:88416bd1e65dcea10bc7569faacb2c20ce071dd1f87539ca2ab364bf6231393c", size = 22993, upload-time = "2024-10-18T15:21:18.064Z" }, - { url = "https://files.pythonhosted.org/packages/da/0e/1f32af846df486dce7c227fe0f2398dc7e2e51d4a370508281f3c1c5cddc/MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2181e67807fc2fa785d0592dc2d6206c019b9502410671cc905d132a92866557", size = 24178, upload-time = "2024-10-18T15:21:18.859Z" }, - { url = "https://files.pythonhosted.org/packages/c4/f6/bb3ca0532de8086cbff5f06d137064c8410d10779c4c127e0e47d17c0b71/MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:52305740fe773d09cffb16f8ed0427942901f00adedac82ec8b67752f58a1b22", size = 23319, upload-time = "2024-10-18T15:21:19.671Z" }, - { url = "https://files.pythonhosted.org/packages/a2/82/8be4c96ffee03c5b4a034e60a31294daf481e12c7c43ab8e34a1453ee48b/MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ad10d3ded218f1039f11a75f8091880239651b52e9bb592ca27de44eed242a48", size = 23352, upload-time = "2024-10-18T15:21:20.971Z" }, - { url = "https://files.pythonhosted.org/packages/51/ae/97827349d3fcffee7e184bdf7f41cd6b88d9919c80f0263ba7acd1bbcb18/MarkupSafe-3.0.2-cp312-cp312-win32.whl", hash = "sha256:0f4ca02bea9a23221c0182836703cbf8930c5e9454bacce27e767509fa286a30", size = 15097, upload-time = "2024-10-18T15:21:22.646Z" }, - { url = "https://files.pythonhosted.org/packages/c1/80/a61f99dc3a936413c3ee4e1eecac96c0da5ed07ad56fd975f1a9da5bc630/MarkupSafe-3.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:8e06879fc22a25ca47312fbe7c8264eb0b662f6db27cb2d3bbbc74b1df4b9b87", size = 15601, upload-time = "2024-10-18T15:21:23.499Z" }, - { url = "https://files.pythonhosted.org/packages/83/0e/67eb10a7ecc77a0c2bbe2b0235765b98d164d81600746914bebada795e97/MarkupSafe-3.0.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ba9527cdd4c926ed0760bc301f6728ef34d841f405abf9d4f959c478421e4efd", size = 14274, upload-time = "2024-10-18T15:21:24.577Z" }, - { url = "https://files.pythonhosted.org/packages/2b/6d/9409f3684d3335375d04e5f05744dfe7e9f120062c9857df4ab490a1031a/MarkupSafe-3.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f8b3d067f2e40fe93e1ccdd6b2e1d16c43140e76f02fb1319a05cf2b79d99430", size = 12352, upload-time = "2024-10-18T15:21:25.382Z" }, - { url = "https://files.pythonhosted.org/packages/d2/f5/6eadfcd3885ea85fe2a7c128315cc1bb7241e1987443d78c8fe712d03091/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:569511d3b58c8791ab4c2e1285575265991e6d8f8700c7be0e88f86cb0672094", size = 24122, upload-time = "2024-10-18T15:21:26.199Z" }, - { url = "https://files.pythonhosted.org/packages/0c/91/96cf928db8236f1bfab6ce15ad070dfdd02ed88261c2afafd4b43575e9e9/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15ab75ef81add55874e7ab7055e9c397312385bd9ced94920f2802310c930396", size = 23085, upload-time = "2024-10-18T15:21:27.029Z" }, - { url = "https://files.pythonhosted.org/packages/c2/cf/c9d56af24d56ea04daae7ac0940232d31d5a8354f2b457c6d856b2057d69/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f3818cb119498c0678015754eba762e0d61e5b52d34c8b13d770f0719f7b1d79", size = 22978, upload-time = "2024-10-18T15:21:27.846Z" }, - { url = "https://files.pythonhosted.org/packages/2a/9f/8619835cd6a711d6272d62abb78c033bda638fdc54c4e7f4272cf1c0962b/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:cdb82a876c47801bb54a690c5ae105a46b392ac6099881cdfb9f6e95e4014c6a", size = 24208, upload-time = "2024-10-18T15:21:28.744Z" }, - { url = "https://files.pythonhosted.org/packages/f9/bf/176950a1792b2cd2102b8ffeb5133e1ed984547b75db47c25a67d3359f77/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:cabc348d87e913db6ab4aa100f01b08f481097838bdddf7c7a84b7575b7309ca", size = 23357, upload-time = "2024-10-18T15:21:29.545Z" }, - { url = "https://files.pythonhosted.org/packages/ce/4f/9a02c1d335caabe5c4efb90e1b6e8ee944aa245c1aaaab8e8a618987d816/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:444dcda765c8a838eaae23112db52f1efaf750daddb2d9ca300bcae1039adc5c", size = 23344, upload-time = "2024-10-18T15:21:30.366Z" }, - { url = "https://files.pythonhosted.org/packages/ee/55/c271b57db36f748f0e04a759ace9f8f759ccf22b4960c270c78a394f58be/MarkupSafe-3.0.2-cp313-cp313-win32.whl", hash = "sha256:bcf3e58998965654fdaff38e58584d8937aa3096ab5354d493c77d1fdd66d7a1", size = 15101, upload-time = "2024-10-18T15:21:31.207Z" }, - { url = "https://files.pythonhosted.org/packages/29/88/07df22d2dd4df40aba9f3e402e6dc1b8ee86297dddbad4872bd5e7b0094f/MarkupSafe-3.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:e6a2a455bd412959b57a172ce6328d2dd1f01cb2135efda2e4576e8a23fa3b0f", size = 15603, upload-time = "2024-10-18T15:21:32.032Z" }, - { url = "https://files.pythonhosted.org/packages/62/6a/8b89d24db2d32d433dffcd6a8779159da109842434f1dd2f6e71f32f738c/MarkupSafe-3.0.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:b5a6b3ada725cea8a5e634536b1b01c30bcdcd7f9c6fff4151548d5bf6b3a36c", size = 14510, upload-time = "2024-10-18T15:21:33.625Z" }, - { url = "https://files.pythonhosted.org/packages/7a/06/a10f955f70a2e5a9bf78d11a161029d278eeacbd35ef806c3fd17b13060d/MarkupSafe-3.0.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:a904af0a6162c73e3edcb969eeeb53a63ceeb5d8cf642fade7d39e7963a22ddb", size = 12486, upload-time = "2024-10-18T15:21:34.611Z" }, - { url = "https://files.pythonhosted.org/packages/34/cf/65d4a571869a1a9078198ca28f39fba5fbb910f952f9dbc5220afff9f5e6/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4aa4e5faecf353ed117801a068ebab7b7e09ffb6e1d5e412dc852e0da018126c", size = 25480, upload-time = "2024-10-18T15:21:35.398Z" }, - { url = "https://files.pythonhosted.org/packages/0c/e3/90e9651924c430b885468b56b3d597cabf6d72be4b24a0acd1fa0e12af67/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0ef13eaeee5b615fb07c9a7dadb38eac06a0608b41570d8ade51c56539e509d", size = 23914, upload-time = "2024-10-18T15:21:36.231Z" }, - { url = "https://files.pythonhosted.org/packages/66/8c/6c7cf61f95d63bb866db39085150df1f2a5bd3335298f14a66b48e92659c/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d16a81a06776313e817c951135cf7340a3e91e8c1ff2fac444cfd75fffa04afe", size = 23796, upload-time = "2024-10-18T15:21:37.073Z" }, - { url = "https://files.pythonhosted.org/packages/bb/35/cbe9238ec3f47ac9a7c8b3df7a808e7cb50fe149dc7039f5f454b3fba218/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:6381026f158fdb7c72a168278597a5e3a5222e83ea18f543112b2662a9b699c5", size = 25473, upload-time = "2024-10-18T15:21:37.932Z" }, - { url = "https://files.pythonhosted.org/packages/e6/32/7621a4382488aa283cc05e8984a9c219abad3bca087be9ec77e89939ded9/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:3d79d162e7be8f996986c064d1c7c817f6df3a77fe3d6859f6f9e7be4b8c213a", size = 24114, upload-time = "2024-10-18T15:21:39.799Z" }, - { url = "https://files.pythonhosted.org/packages/0d/80/0985960e4b89922cb5a0bac0ed39c5b96cbc1a536a99f30e8c220a996ed9/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:131a3c7689c85f5ad20f9f6fb1b866f402c445b220c19fe4308c0b147ccd2ad9", size = 24098, upload-time = "2024-10-18T15:21:40.813Z" }, - { url = "https://files.pythonhosted.org/packages/82/78/fedb03c7d5380df2427038ec8d973587e90561b2d90cd472ce9254cf348b/MarkupSafe-3.0.2-cp313-cp313t-win32.whl", hash = "sha256:ba8062ed2cf21c07a9e295d5b8a2a5ce678b913b45fdf68c32d95d6c1291e0b6", size = 15208, upload-time = "2024-10-18T15:21:41.814Z" }, - { url = "https://files.pythonhosted.org/packages/4f/65/6079a46068dfceaeabb5dcad6d674f5f5c61a6fa5673746f42a9f4c233b3/MarkupSafe-3.0.2-cp313-cp313t-win_amd64.whl", hash = "sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f", size = 15739, upload-time = "2024-10-18T15:21:42.784Z" }, +version = "3.0.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/7e/99/7690b6d4034fffd95959cbe0c02de8deb3098cc577c67bb6a24fe5d7caa7/markupsafe-3.0.3.tar.gz", hash = "sha256:722695808f4b6457b320fdc131280796bdceb04ab50fe1795cd540799ebe1698", size = 80313, upload-time = "2025-09-27T18:37:40.426Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/08/db/fefacb2136439fc8dd20e797950e749aa1f4997ed584c62cfb8ef7c2be0e/markupsafe-3.0.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1cc7ea17a6824959616c525620e387f6dd30fec8cb44f649e31712db02123dad", size = 11631, upload-time = "2025-09-27T18:36:18.185Z" }, + { url = "https://files.pythonhosted.org/packages/e1/2e/5898933336b61975ce9dc04decbc0a7f2fee78c30353c5efba7f2d6ff27a/markupsafe-3.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4bd4cd07944443f5a265608cc6aab442e4f74dff8088b0dfc8238647b8f6ae9a", size = 12058, upload-time = "2025-09-27T18:36:19.444Z" }, + { url = "https://files.pythonhosted.org/packages/1d/09/adf2df3699d87d1d8184038df46a9c80d78c0148492323f4693df54e17bb/markupsafe-3.0.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6b5420a1d9450023228968e7e6a9ce57f65d148ab56d2313fcd589eee96a7a50", size = 24287, upload-time = "2025-09-27T18:36:20.768Z" }, + { url = "https://files.pythonhosted.org/packages/30/ac/0273f6fcb5f42e314c6d8cd99effae6a5354604d461b8d392b5ec9530a54/markupsafe-3.0.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0bf2a864d67e76e5c9a34dc26ec616a66b9888e25e7b9460e1c76d3293bd9dbf", size = 22940, upload-time = "2025-09-27T18:36:22.249Z" }, + { url = "https://files.pythonhosted.org/packages/19/ae/31c1be199ef767124c042c6c3e904da327a2f7f0cd63a0337e1eca2967a8/markupsafe-3.0.3-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:bc51efed119bc9cfdf792cdeaa4d67e8f6fcccab66ed4bfdd6bde3e59bfcbb2f", size = 21887, upload-time = "2025-09-27T18:36:23.535Z" }, + { url = "https://files.pythonhosted.org/packages/b2/76/7edcab99d5349a4532a459e1fe64f0b0467a3365056ae550d3bcf3f79e1e/markupsafe-3.0.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:068f375c472b3e7acbe2d5318dea141359e6900156b5b2ba06a30b169086b91a", size = 23692, upload-time = "2025-09-27T18:36:24.823Z" }, + { url = "https://files.pythonhosted.org/packages/a4/28/6e74cdd26d7514849143d69f0bf2399f929c37dc2b31e6829fd2045b2765/markupsafe-3.0.3-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:7be7b61bb172e1ed687f1754f8e7484f1c8019780f6f6b0786e76bb01c2ae115", size = 21471, upload-time = "2025-09-27T18:36:25.95Z" }, + { url = "https://files.pythonhosted.org/packages/62/7e/a145f36a5c2945673e590850a6f8014318d5577ed7e5920a4b3448e0865d/markupsafe-3.0.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f9e130248f4462aaa8e2552d547f36ddadbeaa573879158d721bbd33dfe4743a", size = 22923, upload-time = "2025-09-27T18:36:27.109Z" }, + { url = "https://files.pythonhosted.org/packages/0f/62/d9c46a7f5c9adbeeeda52f5b8d802e1094e9717705a645efc71b0913a0a8/markupsafe-3.0.3-cp311-cp311-win32.whl", hash = "sha256:0db14f5dafddbb6d9208827849fad01f1a2609380add406671a26386cdf15a19", size = 14572, upload-time = "2025-09-27T18:36:28.045Z" }, + { url = "https://files.pythonhosted.org/packages/83/8a/4414c03d3f891739326e1783338e48fb49781cc915b2e0ee052aa490d586/markupsafe-3.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:de8a88e63464af587c950061a5e6a67d3632e36df62b986892331d4620a35c01", size = 15077, upload-time = "2025-09-27T18:36:29.025Z" }, + { url = "https://files.pythonhosted.org/packages/35/73/893072b42e6862f319b5207adc9ae06070f095b358655f077f69a35601f0/markupsafe-3.0.3-cp311-cp311-win_arm64.whl", hash = "sha256:3b562dd9e9ea93f13d53989d23a7e775fdfd1066c33494ff43f5418bc8c58a5c", size = 13876, upload-time = "2025-09-27T18:36:29.954Z" }, + { url = "https://files.pythonhosted.org/packages/5a/72/147da192e38635ada20e0a2e1a51cf8823d2119ce8883f7053879c2199b5/markupsafe-3.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d53197da72cc091b024dd97249dfc7794d6a56530370992a5e1a08983ad9230e", size = 11615, upload-time = "2025-09-27T18:36:30.854Z" }, + { url = "https://files.pythonhosted.org/packages/9a/81/7e4e08678a1f98521201c3079f77db69fb552acd56067661f8c2f534a718/markupsafe-3.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1872df69a4de6aead3491198eaf13810b565bdbeec3ae2dc8780f14458ec73ce", size = 12020, upload-time = "2025-09-27T18:36:31.971Z" }, + { url = "https://files.pythonhosted.org/packages/1e/2c/799f4742efc39633a1b54a92eec4082e4f815314869865d876824c257c1e/markupsafe-3.0.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3a7e8ae81ae39e62a41ec302f972ba6ae23a5c5396c8e60113e9066ef893da0d", size = 24332, upload-time = "2025-09-27T18:36:32.813Z" }, + { url = "https://files.pythonhosted.org/packages/3c/2e/8d0c2ab90a8c1d9a24f0399058ab8519a3279d1bd4289511d74e909f060e/markupsafe-3.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d6dd0be5b5b189d31db7cda48b91d7e0a9795f31430b7f271219ab30f1d3ac9d", size = 22947, upload-time = "2025-09-27T18:36:33.86Z" }, + { url = "https://files.pythonhosted.org/packages/2c/54/887f3092a85238093a0b2154bd629c89444f395618842e8b0c41783898ea/markupsafe-3.0.3-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:94c6f0bb423f739146aec64595853541634bde58b2135f27f61c1ffd1cd4d16a", size = 21962, upload-time = "2025-09-27T18:36:35.099Z" }, + { url = "https://files.pythonhosted.org/packages/c9/2f/336b8c7b6f4a4d95e91119dc8521402461b74a485558d8f238a68312f11c/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:be8813b57049a7dc738189df53d69395eba14fb99345e0a5994914a3864c8a4b", size = 23760, upload-time = "2025-09-27T18:36:36.001Z" }, + { url = "https://files.pythonhosted.org/packages/32/43/67935f2b7e4982ffb50a4d169b724d74b62a3964bc1a9a527f5ac4f1ee2b/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:83891d0e9fb81a825d9a6d61e3f07550ca70a076484292a70fde82c4b807286f", size = 21529, upload-time = "2025-09-27T18:36:36.906Z" }, + { url = "https://files.pythonhosted.org/packages/89/e0/4486f11e51bbba8b0c041098859e869e304d1c261e59244baa3d295d47b7/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:77f0643abe7495da77fb436f50f8dab76dbc6e5fd25d39589a0f1fe6548bfa2b", size = 23015, upload-time = "2025-09-27T18:36:37.868Z" }, + { url = "https://files.pythonhosted.org/packages/2f/e1/78ee7a023dac597a5825441ebd17170785a9dab23de95d2c7508ade94e0e/markupsafe-3.0.3-cp312-cp312-win32.whl", hash = "sha256:d88b440e37a16e651bda4c7c2b930eb586fd15ca7406cb39e211fcff3bf3017d", size = 14540, upload-time = "2025-09-27T18:36:38.761Z" }, + { url = "https://files.pythonhosted.org/packages/aa/5b/bec5aa9bbbb2c946ca2733ef9c4ca91c91b6a24580193e891b5f7dbe8e1e/markupsafe-3.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:26a5784ded40c9e318cfc2bdb30fe164bdb8665ded9cd64d500a34fb42067b1c", size = 15105, upload-time = "2025-09-27T18:36:39.701Z" }, + { url = "https://files.pythonhosted.org/packages/e5/f1/216fc1bbfd74011693a4fd837e7026152e89c4bcf3e77b6692fba9923123/markupsafe-3.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:35add3b638a5d900e807944a078b51922212fb3dedb01633a8defc4b01a3c85f", size = 13906, upload-time = "2025-09-27T18:36:40.689Z" }, + { url = "https://files.pythonhosted.org/packages/38/2f/907b9c7bbba283e68f20259574b13d005c121a0fa4c175f9bed27c4597ff/markupsafe-3.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e1cf1972137e83c5d4c136c43ced9ac51d0e124706ee1c8aa8532c1287fa8795", size = 11622, upload-time = "2025-09-27T18:36:41.777Z" }, + { url = "https://files.pythonhosted.org/packages/9c/d9/5f7756922cdd676869eca1c4e3c0cd0df60ed30199ffd775e319089cb3ed/markupsafe-3.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:116bb52f642a37c115f517494ea5feb03889e04df47eeff5b130b1808ce7c219", size = 12029, upload-time = "2025-09-27T18:36:43.257Z" }, + { url = "https://files.pythonhosted.org/packages/00/07/575a68c754943058c78f30db02ee03a64b3c638586fba6a6dd56830b30a3/markupsafe-3.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:133a43e73a802c5562be9bbcd03d090aa5a1fe899db609c29e8c8d815c5f6de6", size = 24374, upload-time = "2025-09-27T18:36:44.508Z" }, + { url = "https://files.pythonhosted.org/packages/a9/21/9b05698b46f218fc0e118e1f8168395c65c8a2c750ae2bab54fc4bd4e0e8/markupsafe-3.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ccfcd093f13f0f0b7fdd0f198b90053bf7b2f02a3927a30e63f3ccc9df56b676", size = 22980, upload-time = "2025-09-27T18:36:45.385Z" }, + { url = "https://files.pythonhosted.org/packages/7f/71/544260864f893f18b6827315b988c146b559391e6e7e8f7252839b1b846a/markupsafe-3.0.3-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:509fa21c6deb7a7a273d629cf5ec029bc209d1a51178615ddf718f5918992ab9", size = 21990, upload-time = "2025-09-27T18:36:46.916Z" }, + { url = "https://files.pythonhosted.org/packages/c2/28/b50fc2f74d1ad761af2f5dcce7492648b983d00a65b8c0e0cb457c82ebbe/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a4afe79fb3de0b7097d81da19090f4df4f8d3a2b3adaa8764138aac2e44f3af1", size = 23784, upload-time = "2025-09-27T18:36:47.884Z" }, + { url = "https://files.pythonhosted.org/packages/ed/76/104b2aa106a208da8b17a2fb72e033a5a9d7073c68f7e508b94916ed47a9/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:795e7751525cae078558e679d646ae45574b47ed6e7771863fcc079a6171a0fc", size = 21588, upload-time = "2025-09-27T18:36:48.82Z" }, + { url = "https://files.pythonhosted.org/packages/b5/99/16a5eb2d140087ebd97180d95249b00a03aa87e29cc224056274f2e45fd6/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8485f406a96febb5140bfeca44a73e3ce5116b2501ac54fe953e488fb1d03b12", size = 23041, upload-time = "2025-09-27T18:36:49.797Z" }, + { url = "https://files.pythonhosted.org/packages/19/bc/e7140ed90c5d61d77cea142eed9f9c303f4c4806f60a1044c13e3f1471d0/markupsafe-3.0.3-cp313-cp313-win32.whl", hash = "sha256:bdd37121970bfd8be76c5fb069c7751683bdf373db1ed6c010162b2a130248ed", size = 14543, upload-time = "2025-09-27T18:36:51.584Z" }, + { url = "https://files.pythonhosted.org/packages/05/73/c4abe620b841b6b791f2edc248f556900667a5a1cf023a6646967ae98335/markupsafe-3.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:9a1abfdc021a164803f4d485104931fb8f8c1efd55bc6b748d2f5774e78b62c5", size = 15113, upload-time = "2025-09-27T18:36:52.537Z" }, + { url = "https://files.pythonhosted.org/packages/f0/3a/fa34a0f7cfef23cf9500d68cb7c32dd64ffd58a12b09225fb03dd37d5b80/markupsafe-3.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:7e68f88e5b8799aa49c85cd116c932a1ac15caaa3f5db09087854d218359e485", size = 13911, upload-time = "2025-09-27T18:36:53.513Z" }, + { url = "https://files.pythonhosted.org/packages/e4/d7/e05cd7efe43a88a17a37b3ae96e79a19e846f3f456fe79c57ca61356ef01/markupsafe-3.0.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:218551f6df4868a8d527e3062d0fb968682fe92054e89978594c28e642c43a73", size = 11658, upload-time = "2025-09-27T18:36:54.819Z" }, + { url = "https://files.pythonhosted.org/packages/99/9e/e412117548182ce2148bdeacdda3bb494260c0b0184360fe0d56389b523b/markupsafe-3.0.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:3524b778fe5cfb3452a09d31e7b5adefeea8c5be1d43c4f810ba09f2ceb29d37", size = 12066, upload-time = "2025-09-27T18:36:55.714Z" }, + { url = "https://files.pythonhosted.org/packages/bc/e6/fa0ffcda717ef64a5108eaa7b4f5ed28d56122c9a6d70ab8b72f9f715c80/markupsafe-3.0.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4e885a3d1efa2eadc93c894a21770e4bc67899e3543680313b09f139e149ab19", size = 25639, upload-time = "2025-09-27T18:36:56.908Z" }, + { url = "https://files.pythonhosted.org/packages/96/ec/2102e881fe9d25fc16cb4b25d5f5cde50970967ffa5dddafdb771237062d/markupsafe-3.0.3-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8709b08f4a89aa7586de0aadc8da56180242ee0ada3999749b183aa23df95025", size = 23569, upload-time = "2025-09-27T18:36:57.913Z" }, + { url = "https://files.pythonhosted.org/packages/4b/30/6f2fce1f1f205fc9323255b216ca8a235b15860c34b6798f810f05828e32/markupsafe-3.0.3-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b8512a91625c9b3da6f127803b166b629725e68af71f8184ae7e7d54686a56d6", size = 23284, upload-time = "2025-09-27T18:36:58.833Z" }, + { url = "https://files.pythonhosted.org/packages/58/47/4a0ccea4ab9f5dcb6f79c0236d954acb382202721e704223a8aafa38b5c8/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9b79b7a16f7fedff2495d684f2b59b0457c3b493778c9eed31111be64d58279f", size = 24801, upload-time = "2025-09-27T18:36:59.739Z" }, + { url = "https://files.pythonhosted.org/packages/6a/70/3780e9b72180b6fecb83a4814d84c3bf4b4ae4bf0b19c27196104149734c/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:12c63dfb4a98206f045aa9563db46507995f7ef6d83b2f68eda65c307c6829eb", size = 22769, upload-time = "2025-09-27T18:37:00.719Z" }, + { url = "https://files.pythonhosted.org/packages/98/c5/c03c7f4125180fc215220c035beac6b9cb684bc7a067c84fc69414d315f5/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:8f71bc33915be5186016f675cd83a1e08523649b0e33efdb898db577ef5bb009", size = 23642, upload-time = "2025-09-27T18:37:01.673Z" }, + { url = "https://files.pythonhosted.org/packages/80/d6/2d1b89f6ca4bff1036499b1e29a1d02d282259f3681540e16563f27ebc23/markupsafe-3.0.3-cp313-cp313t-win32.whl", hash = "sha256:69c0b73548bc525c8cb9a251cddf1931d1db4d2258e9599c28c07ef3580ef354", size = 14612, upload-time = "2025-09-27T18:37:02.639Z" }, + { url = "https://files.pythonhosted.org/packages/2b/98/e48a4bfba0a0ffcf9925fe2d69240bfaa19c6f7507b8cd09c70684a53c1e/markupsafe-3.0.3-cp313-cp313t-win_amd64.whl", hash = "sha256:1b4b79e8ebf6b55351f0d91fe80f893b4743f104bff22e90697db1590e47a218", size = 15200, upload-time = "2025-09-27T18:37:03.582Z" }, + { url = "https://files.pythonhosted.org/packages/0e/72/e3cc540f351f316e9ed0f092757459afbc595824ca724cbc5a5d4263713f/markupsafe-3.0.3-cp313-cp313t-win_arm64.whl", hash = "sha256:ad2cf8aa28b8c020ab2fc8287b0f823d0a7d8630784c31e9ee5edea20f406287", size = 13973, upload-time = "2025-09-27T18:37:04.929Z" }, + { url = "https://files.pythonhosted.org/packages/33/8a/8e42d4838cd89b7dde187011e97fe6c3af66d8c044997d2183fbd6d31352/markupsafe-3.0.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:eaa9599de571d72e2daf60164784109f19978b327a3910d3e9de8c97b5b70cfe", size = 11619, upload-time = "2025-09-27T18:37:06.342Z" }, + { url = "https://files.pythonhosted.org/packages/b5/64/7660f8a4a8e53c924d0fa05dc3a55c9cee10bbd82b11c5afb27d44b096ce/markupsafe-3.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c47a551199eb8eb2121d4f0f15ae0f923d31350ab9280078d1e5f12b249e0026", size = 12029, upload-time = "2025-09-27T18:37:07.213Z" }, + { url = "https://files.pythonhosted.org/packages/da/ef/e648bfd021127bef5fa12e1720ffed0c6cbb8310c8d9bea7266337ff06de/markupsafe-3.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f34c41761022dd093b4b6896d4810782ffbabe30f2d443ff5f083e0cbbb8c737", size = 24408, upload-time = "2025-09-27T18:37:09.572Z" }, + { url = "https://files.pythonhosted.org/packages/41/3c/a36c2450754618e62008bf7435ccb0f88053e07592e6028a34776213d877/markupsafe-3.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:457a69a9577064c05a97c41f4e65148652db078a3a509039e64d3467b9e7ef97", size = 23005, upload-time = "2025-09-27T18:37:10.58Z" }, + { url = "https://files.pythonhosted.org/packages/bc/20/b7fdf89a8456b099837cd1dc21974632a02a999ec9bf7ca3e490aacd98e7/markupsafe-3.0.3-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e8afc3f2ccfa24215f8cb28dcf43f0113ac3c37c2f0f0806d8c70e4228c5cf4d", size = 22048, upload-time = "2025-09-27T18:37:11.547Z" }, + { url = "https://files.pythonhosted.org/packages/9a/a7/591f592afdc734f47db08a75793a55d7fbcc6902a723ae4cfbab61010cc5/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:ec15a59cf5af7be74194f7ab02d0f59a62bdcf1a537677ce67a2537c9b87fcda", size = 23821, upload-time = "2025-09-27T18:37:12.48Z" }, + { url = "https://files.pythonhosted.org/packages/7d/33/45b24e4f44195b26521bc6f1a82197118f74df348556594bd2262bda1038/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:0eb9ff8191e8498cca014656ae6b8d61f39da5f95b488805da4bb029cccbfbaf", size = 21606, upload-time = "2025-09-27T18:37:13.485Z" }, + { url = "https://files.pythonhosted.org/packages/ff/0e/53dfaca23a69fbfbbf17a4b64072090e70717344c52eaaaa9c5ddff1e5f0/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:2713baf880df847f2bece4230d4d094280f4e67b1e813eec43b4c0e144a34ffe", size = 23043, upload-time = "2025-09-27T18:37:14.408Z" }, + { url = "https://files.pythonhosted.org/packages/46/11/f333a06fc16236d5238bfe74daccbca41459dcd8d1fa952e8fbd5dccfb70/markupsafe-3.0.3-cp314-cp314-win32.whl", hash = "sha256:729586769a26dbceff69f7a7dbbf59ab6572b99d94576a5592625d5b411576b9", size = 14747, upload-time = "2025-09-27T18:37:15.36Z" }, + { url = "https://files.pythonhosted.org/packages/28/52/182836104b33b444e400b14f797212f720cbc9ed6ba34c800639d154e821/markupsafe-3.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:bdc919ead48f234740ad807933cdf545180bfbe9342c2bb451556db2ed958581", size = 15341, upload-time = "2025-09-27T18:37:16.496Z" }, + { url = "https://files.pythonhosted.org/packages/6f/18/acf23e91bd94fd7b3031558b1f013adfa21a8e407a3fdb32745538730382/markupsafe-3.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:5a7d5dc5140555cf21a6fefbdbf8723f06fcd2f63ef108f2854de715e4422cb4", size = 14073, upload-time = "2025-09-27T18:37:17.476Z" }, + { url = "https://files.pythonhosted.org/packages/3c/f0/57689aa4076e1b43b15fdfa646b04653969d50cf30c32a102762be2485da/markupsafe-3.0.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:1353ef0c1b138e1907ae78e2f6c63ff67501122006b0f9abad68fda5f4ffc6ab", size = 11661, upload-time = "2025-09-27T18:37:18.453Z" }, + { url = "https://files.pythonhosted.org/packages/89/c3/2e67a7ca217c6912985ec766c6393b636fb0c2344443ff9d91404dc4c79f/markupsafe-3.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1085e7fbddd3be5f89cc898938f42c0b3c711fdcb37d75221de2666af647c175", size = 12069, upload-time = "2025-09-27T18:37:19.332Z" }, + { url = "https://files.pythonhosted.org/packages/f0/00/be561dce4e6ca66b15276e184ce4b8aec61fe83662cce2f7d72bd3249d28/markupsafe-3.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1b52b4fb9df4eb9ae465f8d0c228a00624de2334f216f178a995ccdcf82c4634", size = 25670, upload-time = "2025-09-27T18:37:20.245Z" }, + { url = "https://files.pythonhosted.org/packages/50/09/c419f6f5a92e5fadde27efd190eca90f05e1261b10dbd8cbcb39cd8ea1dc/markupsafe-3.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fed51ac40f757d41b7c48425901843666a6677e3e8eb0abcff09e4ba6e664f50", size = 23598, upload-time = "2025-09-27T18:37:21.177Z" }, + { url = "https://files.pythonhosted.org/packages/22/44/a0681611106e0b2921b3033fc19bc53323e0b50bc70cffdd19f7d679bb66/markupsafe-3.0.3-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f190daf01f13c72eac4efd5c430a8de82489d9cff23c364c3ea822545032993e", size = 23261, upload-time = "2025-09-27T18:37:22.167Z" }, + { url = "https://files.pythonhosted.org/packages/5f/57/1b0b3f100259dc9fffe780cfb60d4be71375510e435efec3d116b6436d43/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e56b7d45a839a697b5eb268c82a71bd8c7f6c94d6fd50c3d577fa39a9f1409f5", size = 24835, upload-time = "2025-09-27T18:37:23.296Z" }, + { url = "https://files.pythonhosted.org/packages/26/6a/4bf6d0c97c4920f1597cc14dd720705eca0bf7c787aebc6bb4d1bead5388/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:f3e98bb3798ead92273dc0e5fd0f31ade220f59a266ffd8a4f6065e0a3ce0523", size = 22733, upload-time = "2025-09-27T18:37:24.237Z" }, + { url = "https://files.pythonhosted.org/packages/14/c7/ca723101509b518797fedc2fdf79ba57f886b4aca8a7d31857ba3ee8281f/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:5678211cb9333a6468fb8d8be0305520aa073f50d17f089b5b4b477ea6e67fdc", size = 23672, upload-time = "2025-09-27T18:37:25.271Z" }, + { url = "https://files.pythonhosted.org/packages/fb/df/5bd7a48c256faecd1d36edc13133e51397e41b73bb77e1a69deab746ebac/markupsafe-3.0.3-cp314-cp314t-win32.whl", hash = "sha256:915c04ba3851909ce68ccc2b8e2cd691618c4dc4c4232fb7982bca3f41fd8c3d", size = 14819, upload-time = "2025-09-27T18:37:26.285Z" }, + { url = "https://files.pythonhosted.org/packages/1a/8a/0402ba61a2f16038b48b39bccca271134be00c5c9f0f623208399333c448/markupsafe-3.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4faffd047e07c38848ce017e8725090413cd80cbc23d86e55c587bf979e579c9", size = 15426, upload-time = "2025-09-27T18:37:27.316Z" }, + { url = "https://files.pythonhosted.org/packages/70/bc/6f1c2f612465f5fa89b95bead1f44dcb607670fd42891d8fdcd5d039f4f4/markupsafe-3.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:32001d6a8fc98c8cb5c947787c5d08b0a50663d139f1305bac5885d98d9b40fa", size = 14146, upload-time = "2025-09-27T18:37:28.327Z" }, ] [[package]] @@ -1418,7 +1444,7 @@ wheels = [ [[package]] name = "pandas" -version = "2.3.2" +version = "2.3.3" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "numpy" }, @@ -1426,35 +1452,48 @@ dependencies = [ { name = "pytz" }, { name = "tzdata" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/79/8e/0e90233ac205ad182bd6b422532695d2b9414944a280488105d598c70023/pandas-2.3.2.tar.gz", hash = "sha256:ab7b58f8f82706890924ccdfb5f48002b83d2b5a3845976a9fb705d36c34dcdb", size = 4488684, upload-time = "2025-08-21T10:28:29.257Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/7a/59/f3e010879f118c2d400902d2d871c2226cef29b08c09fb8dc41111730400/pandas-2.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1333e9c299adcbb68ee89a9bb568fc3f20f9cbb419f1dd5225071e6cddb2a743", size = 11563308, upload-time = "2025-08-21T10:26:56.656Z" }, - { url = "https://files.pythonhosted.org/packages/38/18/48f10f1cc5c397af59571d638d211f494dba481f449c19adbd282aa8f4ca/pandas-2.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:76972bcbd7de8e91ad5f0ca884a9f2c477a2125354af624e022c49e5bd0dfff4", size = 10820319, upload-time = "2025-08-21T10:26:59.162Z" }, - { url = "https://files.pythonhosted.org/packages/95/3b/1e9b69632898b048e223834cd9702052bcf06b15e1ae716eda3196fb972e/pandas-2.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b98bdd7c456a05eef7cd21fd6b29e3ca243591fe531c62be94a2cc987efb5ac2", size = 11790097, upload-time = "2025-08-21T10:27:02.204Z" }, - { url = "https://files.pythonhosted.org/packages/8b/ef/0e2ffb30b1f7fbc9a588bd01e3c14a0d96854d09a887e15e30cc19961227/pandas-2.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1d81573b3f7db40d020983f78721e9bfc425f411e616ef019a10ebf597aedb2e", size = 12397958, upload-time = "2025-08-21T10:27:05.409Z" }, - { url = "https://files.pythonhosted.org/packages/23/82/e6b85f0d92e9afb0e7f705a51d1399b79c7380c19687bfbf3d2837743249/pandas-2.3.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:e190b738675a73b581736cc8ec71ae113d6c3768d0bd18bffa5b9a0927b0b6ea", size = 13225600, upload-time = "2025-08-21T10:27:07.791Z" }, - { url = "https://files.pythonhosted.org/packages/e8/f1/f682015893d9ed51611948bd83683670842286a8edd4f68c2c1c3b231eef/pandas-2.3.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:c253828cb08f47488d60f43c5fc95114c771bbfff085da54bfc79cb4f9e3a372", size = 13879433, upload-time = "2025-08-21T10:27:10.347Z" }, - { url = "https://files.pythonhosted.org/packages/a7/e7/ae86261695b6c8a36d6a4c8d5f9b9ede8248510d689a2f379a18354b37d7/pandas-2.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:9467697b8083f9667b212633ad6aa4ab32436dcbaf4cd57325debb0ddef2012f", size = 11336557, upload-time = "2025-08-21T10:27:12.983Z" }, - { url = "https://files.pythonhosted.org/packages/ec/db/614c20fb7a85a14828edd23f1c02db58a30abf3ce76f38806155d160313c/pandas-2.3.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:3fbb977f802156e7a3f829e9d1d5398f6192375a3e2d1a9ee0803e35fe70a2b9", size = 11587652, upload-time = "2025-08-21T10:27:15.888Z" }, - { url = "https://files.pythonhosted.org/packages/99/b0/756e52f6582cade5e746f19bad0517ff27ba9c73404607c0306585c201b3/pandas-2.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1b9b52693123dd234b7c985c68b709b0b009f4521000d0525f2b95c22f15944b", size = 10717686, upload-time = "2025-08-21T10:27:18.486Z" }, - { url = "https://files.pythonhosted.org/packages/37/4c/dd5ccc1e357abfeee8353123282de17997f90ff67855f86154e5a13b81e5/pandas-2.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0bd281310d4f412733f319a5bc552f86d62cddc5f51d2e392c8787335c994175", size = 11278722, upload-time = "2025-08-21T10:27:21.149Z" }, - { url = "https://files.pythonhosted.org/packages/d3/a4/f7edcfa47e0a88cda0be8b068a5bae710bf264f867edfdf7b71584ace362/pandas-2.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:96d31a6b4354e3b9b8a2c848af75d31da390657e3ac6f30c05c82068b9ed79b9", size = 11987803, upload-time = "2025-08-21T10:27:23.767Z" }, - { url = "https://files.pythonhosted.org/packages/f6/61/1bce4129f93ab66f1c68b7ed1c12bac6a70b1b56c5dab359c6bbcd480b52/pandas-2.3.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:df4df0b9d02bb873a106971bb85d448378ef14b86ba96f035f50bbd3688456b4", size = 12766345, upload-time = "2025-08-21T10:27:26.6Z" }, - { url = "https://files.pythonhosted.org/packages/8e/46/80d53de70fee835531da3a1dae827a1e76e77a43ad22a8cd0f8142b61587/pandas-2.3.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:213a5adf93d020b74327cb2c1b842884dbdd37f895f42dcc2f09d451d949f811", size = 13439314, upload-time = "2025-08-21T10:27:29.213Z" }, - { url = "https://files.pythonhosted.org/packages/28/30/8114832daff7489f179971dbc1d854109b7f4365a546e3ea75b6516cea95/pandas-2.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:8c13b81a9347eb8c7548f53fd9a4f08d4dfe996836543f805c987bafa03317ae", size = 10983326, upload-time = "2025-08-21T10:27:31.901Z" }, - { url = "https://files.pythonhosted.org/packages/27/64/a2f7bf678af502e16b472527735d168b22b7824e45a4d7e96a4fbb634b59/pandas-2.3.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0c6ecbac99a354a051ef21c5307601093cb9e0f4b1855984a084bfec9302699e", size = 11531061, upload-time = "2025-08-21T10:27:34.647Z" }, - { url = "https://files.pythonhosted.org/packages/54/4c/c3d21b2b7769ef2f4c2b9299fcadd601efa6729f1357a8dbce8dd949ed70/pandas-2.3.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:c6f048aa0fd080d6a06cc7e7537c09b53be6642d330ac6f54a600c3ace857ee9", size = 10668666, upload-time = "2025-08-21T10:27:37.203Z" }, - { url = "https://files.pythonhosted.org/packages/50/e2/f775ba76ecfb3424d7f5862620841cf0edb592e9abd2d2a5387d305fe7a8/pandas-2.3.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0064187b80a5be6f2f9c9d6bdde29372468751dfa89f4211a3c5871854cfbf7a", size = 11332835, upload-time = "2025-08-21T10:27:40.188Z" }, - { url = "https://files.pythonhosted.org/packages/8f/52/0634adaace9be2d8cac9ef78f05c47f3a675882e068438b9d7ec7ef0c13f/pandas-2.3.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4ac8c320bded4718b298281339c1a50fb00a6ba78cb2a63521c39bec95b0209b", size = 12057211, upload-time = "2025-08-21T10:27:43.117Z" }, - { url = "https://files.pythonhosted.org/packages/0b/9d/2df913f14b2deb9c748975fdb2491da1a78773debb25abbc7cbc67c6b549/pandas-2.3.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:114c2fe4f4328cf98ce5716d1532f3ab79c5919f95a9cfee81d9140064a2e4d6", size = 12749277, upload-time = "2025-08-21T10:27:45.474Z" }, - { url = "https://files.pythonhosted.org/packages/87/af/da1a2417026bd14d98c236dba88e39837182459d29dcfcea510b2ac9e8a1/pandas-2.3.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:48fa91c4dfb3b2b9bfdb5c24cd3567575f4e13f9636810462ffed8925352be5a", size = 13415256, upload-time = "2025-08-21T10:27:49.885Z" }, - { url = "https://files.pythonhosted.org/packages/22/3c/f2af1ce8840ef648584a6156489636b5692c162771918aa95707c165ad2b/pandas-2.3.2-cp313-cp313-win_amd64.whl", hash = "sha256:12d039facec710f7ba305786837d0225a3444af7bbd9c15c32ca2d40d157ed8b", size = 10982579, upload-time = "2025-08-21T10:28:08.435Z" }, - { url = "https://files.pythonhosted.org/packages/f3/98/8df69c4097a6719e357dc249bf437b8efbde808038268e584421696cbddf/pandas-2.3.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:c624b615ce97864eb588779ed4046186f967374185c047070545253a52ab2d57", size = 12028163, upload-time = "2025-08-21T10:27:52.232Z" }, - { url = "https://files.pythonhosted.org/packages/0e/23/f95cbcbea319f349e10ff90db488b905c6883f03cbabd34f6b03cbc3c044/pandas-2.3.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:0cee69d583b9b128823d9514171cabb6861e09409af805b54459bd0c821a35c2", size = 11391860, upload-time = "2025-08-21T10:27:54.673Z" }, - { url = "https://files.pythonhosted.org/packages/ad/1b/6a984e98c4abee22058aa75bfb8eb90dce58cf8d7296f8bc56c14bc330b0/pandas-2.3.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2319656ed81124982900b4c37f0e0c58c015af9a7bbc62342ba5ad07ace82ba9", size = 11309830, upload-time = "2025-08-21T10:27:56.957Z" }, - { url = "https://files.pythonhosted.org/packages/15/d5/f0486090eb18dd8710bf60afeaf638ba6817047c0c8ae5c6a25598665609/pandas-2.3.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b37205ad6f00d52f16b6d09f406434ba928c1a1966e2771006a9033c736d30d2", size = 11883216, upload-time = "2025-08-21T10:27:59.302Z" }, - { url = "https://files.pythonhosted.org/packages/10/86/692050c119696da19e20245bbd650d8dfca6ceb577da027c3a73c62a047e/pandas-2.3.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:837248b4fc3a9b83b9c6214699a13f069dc13510a6a6d7f9ba33145d2841a012", size = 12699743, upload-time = "2025-08-21T10:28:02.447Z" }, - { url = "https://files.pythonhosted.org/packages/cd/d7/612123674d7b17cf345aad0a10289b2a384bff404e0463a83c4a3a59d205/pandas-2.3.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:d2c3554bd31b731cd6490d94a28f3abb8dd770634a9e06eb6d2911b9827db370", size = 13186141, upload-time = "2025-08-21T10:28:05.377Z" }, +sdist = { url = "https://files.pythonhosted.org/packages/33/01/d40b85317f86cf08d853a4f495195c73815fdf205eef3993821720274518/pandas-2.3.3.tar.gz", hash = "sha256:e05e1af93b977f7eafa636d043f9f94c7ee3ac81af99c13508215942e64c993b", size = 4495223, upload-time = "2025-09-29T23:34:51.853Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c1/fa/7ac648108144a095b4fb6aa3de1954689f7af60a14cf25583f4960ecb878/pandas-2.3.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:602b8615ebcc4a0c1751e71840428ddebeb142ec02c786e8ad6b1ce3c8dec523", size = 11578790, upload-time = "2025-09-29T23:18:30.065Z" }, + { url = "https://files.pythonhosted.org/packages/9b/35/74442388c6cf008882d4d4bdfc4109be87e9b8b7ccd097ad1e7f006e2e95/pandas-2.3.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8fe25fc7b623b0ef6b5009149627e34d2a4657e880948ec3c840e9402e5c1b45", size = 10833831, upload-time = "2025-09-29T23:38:56.071Z" }, + { url = "https://files.pythonhosted.org/packages/fe/e4/de154cbfeee13383ad58d23017da99390b91d73f8c11856f2095e813201b/pandas-2.3.3-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b468d3dad6ff947df92dcb32ede5b7bd41a9b3cceef0a30ed925f6d01fb8fa66", size = 12199267, upload-time = "2025-09-29T23:18:41.627Z" }, + { url = "https://files.pythonhosted.org/packages/bf/c9/63f8d545568d9ab91476b1818b4741f521646cbdd151c6efebf40d6de6f7/pandas-2.3.3-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b98560e98cb334799c0b07ca7967ac361a47326e9b4e5a7dfb5ab2b1c9d35a1b", size = 12789281, upload-time = "2025-09-29T23:18:56.834Z" }, + { url = "https://files.pythonhosted.org/packages/f2/00/a5ac8c7a0e67fd1a6059e40aa08fa1c52cc00709077d2300e210c3ce0322/pandas-2.3.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1d37b5848ba49824e5c30bedb9c830ab9b7751fd049bc7914533e01c65f79791", size = 13240453, upload-time = "2025-09-29T23:19:09.247Z" }, + { url = "https://files.pythonhosted.org/packages/27/4d/5c23a5bc7bd209231618dd9e606ce076272c9bc4f12023a70e03a86b4067/pandas-2.3.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:db4301b2d1f926ae677a751eb2bd0e8c5f5319c9cb3f88b0becbbb0b07b34151", size = 13890361, upload-time = "2025-09-29T23:19:25.342Z" }, + { url = "https://files.pythonhosted.org/packages/8e/59/712db1d7040520de7a4965df15b774348980e6df45c129b8c64d0dbe74ef/pandas-2.3.3-cp311-cp311-win_amd64.whl", hash = "sha256:f086f6fe114e19d92014a1966f43a3e62285109afe874f067f5abbdcbb10e59c", size = 11348702, upload-time = "2025-09-29T23:19:38.296Z" }, + { url = "https://files.pythonhosted.org/packages/9c/fb/231d89e8637c808b997d172b18e9d4a4bc7bf31296196c260526055d1ea0/pandas-2.3.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:6d21f6d74eb1725c2efaa71a2bfc661a0689579b58e9c0ca58a739ff0b002b53", size = 11597846, upload-time = "2025-09-29T23:19:48.856Z" }, + { url = "https://files.pythonhosted.org/packages/5c/bd/bf8064d9cfa214294356c2d6702b716d3cf3bb24be59287a6a21e24cae6b/pandas-2.3.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3fd2f887589c7aa868e02632612ba39acb0b8948faf5cc58f0850e165bd46f35", size = 10729618, upload-time = "2025-09-29T23:39:08.659Z" }, + { url = "https://files.pythonhosted.org/packages/57/56/cf2dbe1a3f5271370669475ead12ce77c61726ffd19a35546e31aa8edf4e/pandas-2.3.3-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ecaf1e12bdc03c86ad4a7ea848d66c685cb6851d807a26aa245ca3d2017a1908", size = 11737212, upload-time = "2025-09-29T23:19:59.765Z" }, + { url = "https://files.pythonhosted.org/packages/e5/63/cd7d615331b328e287d8233ba9fdf191a9c2d11b6af0c7a59cfcec23de68/pandas-2.3.3-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b3d11d2fda7eb164ef27ffc14b4fcab16a80e1ce67e9f57e19ec0afaf715ba89", size = 12362693, upload-time = "2025-09-29T23:20:14.098Z" }, + { url = "https://files.pythonhosted.org/packages/a6/de/8b1895b107277d52f2b42d3a6806e69cfef0d5cf1d0ba343470b9d8e0a04/pandas-2.3.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a68e15f780eddf2b07d242e17a04aa187a7ee12b40b930bfdd78070556550e98", size = 12771002, upload-time = "2025-09-29T23:20:26.76Z" }, + { url = "https://files.pythonhosted.org/packages/87/21/84072af3187a677c5893b170ba2c8fbe450a6ff911234916da889b698220/pandas-2.3.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:371a4ab48e950033bcf52b6527eccb564f52dc826c02afd9a1bc0ab731bba084", size = 13450971, upload-time = "2025-09-29T23:20:41.344Z" }, + { url = "https://files.pythonhosted.org/packages/86/41/585a168330ff063014880a80d744219dbf1dd7a1c706e75ab3425a987384/pandas-2.3.3-cp312-cp312-win_amd64.whl", hash = "sha256:a16dcec078a01eeef8ee61bf64074b4e524a2a3f4b3be9326420cabe59c4778b", size = 10992722, upload-time = "2025-09-29T23:20:54.139Z" }, + { url = "https://files.pythonhosted.org/packages/cd/4b/18b035ee18f97c1040d94debd8f2e737000ad70ccc8f5513f4eefad75f4b/pandas-2.3.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:56851a737e3470de7fa88e6131f41281ed440d29a9268dcbf0002da5ac366713", size = 11544671, upload-time = "2025-09-29T23:21:05.024Z" }, + { url = "https://files.pythonhosted.org/packages/31/94/72fac03573102779920099bcac1c3b05975c2cb5f01eac609faf34bed1ca/pandas-2.3.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:bdcd9d1167f4885211e401b3036c0c8d9e274eee67ea8d0758a256d60704cfe8", size = 10680807, upload-time = "2025-09-29T23:21:15.979Z" }, + { url = "https://files.pythonhosted.org/packages/16/87/9472cf4a487d848476865321de18cc8c920b8cab98453ab79dbbc98db63a/pandas-2.3.3-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e32e7cc9af0f1cc15548288a51a3b681cc2a219faa838e995f7dc53dbab1062d", size = 11709872, upload-time = "2025-09-29T23:21:27.165Z" }, + { url = "https://files.pythonhosted.org/packages/15/07/284f757f63f8a8d69ed4472bfd85122bd086e637bf4ed09de572d575a693/pandas-2.3.3-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:318d77e0e42a628c04dc56bcef4b40de67918f7041c2b061af1da41dcff670ac", size = 12306371, upload-time = "2025-09-29T23:21:40.532Z" }, + { url = "https://files.pythonhosted.org/packages/33/81/a3afc88fca4aa925804a27d2676d22dcd2031c2ebe08aabd0ae55b9ff282/pandas-2.3.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4e0a175408804d566144e170d0476b15d78458795bb18f1304fb94160cabf40c", size = 12765333, upload-time = "2025-09-29T23:21:55.77Z" }, + { url = "https://files.pythonhosted.org/packages/8d/0f/b4d4ae743a83742f1153464cf1a8ecfafc3ac59722a0b5c8602310cb7158/pandas-2.3.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:93c2d9ab0fc11822b5eece72ec9587e172f63cff87c00b062f6e37448ced4493", size = 13418120, upload-time = "2025-09-29T23:22:10.109Z" }, + { url = "https://files.pythonhosted.org/packages/4f/c7/e54682c96a895d0c808453269e0b5928a07a127a15704fedb643e9b0a4c8/pandas-2.3.3-cp313-cp313-win_amd64.whl", hash = "sha256:f8bfc0e12dc78f777f323f55c58649591b2cd0c43534e8355c51d3fede5f4dee", size = 10993991, upload-time = "2025-09-29T23:25:04.889Z" }, + { url = "https://files.pythonhosted.org/packages/f9/ca/3f8d4f49740799189e1395812f3bf23b5e8fc7c190827d55a610da72ce55/pandas-2.3.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:75ea25f9529fdec2d2e93a42c523962261e567d250b0013b16210e1d40d7c2e5", size = 12048227, upload-time = "2025-09-29T23:22:24.343Z" }, + { url = "https://files.pythonhosted.org/packages/0e/5a/f43efec3e8c0cc92c4663ccad372dbdff72b60bdb56b2749f04aa1d07d7e/pandas-2.3.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:74ecdf1d301e812db96a465a525952f4dde225fdb6d8e5a521d47e1f42041e21", size = 11411056, upload-time = "2025-09-29T23:22:37.762Z" }, + { url = "https://files.pythonhosted.org/packages/46/b1/85331edfc591208c9d1a63a06baa67b21d332e63b7a591a5ba42a10bb507/pandas-2.3.3-cp313-cp313t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6435cb949cb34ec11cc9860246ccb2fdc9ecd742c12d3304989017d53f039a78", size = 11645189, upload-time = "2025-09-29T23:22:51.688Z" }, + { url = "https://files.pythonhosted.org/packages/44/23/78d645adc35d94d1ac4f2a3c4112ab6f5b8999f4898b8cdf01252f8df4a9/pandas-2.3.3-cp313-cp313t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:900f47d8f20860de523a1ac881c4c36d65efcb2eb850e6948140fa781736e110", size = 12121912, upload-time = "2025-09-29T23:23:05.042Z" }, + { url = "https://files.pythonhosted.org/packages/53/da/d10013df5e6aaef6b425aa0c32e1fc1f3e431e4bcabd420517dceadce354/pandas-2.3.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:a45c765238e2ed7d7c608fc5bc4a6f88b642f2f01e70c0c23d2224dd21829d86", size = 12712160, upload-time = "2025-09-29T23:23:28.57Z" }, + { url = "https://files.pythonhosted.org/packages/bd/17/e756653095a083d8a37cbd816cb87148debcfcd920129b25f99dd8d04271/pandas-2.3.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:c4fc4c21971a1a9f4bdb4c73978c7f7256caa3e62b323f70d6cb80db583350bc", size = 13199233, upload-time = "2025-09-29T23:24:24.876Z" }, + { url = "https://files.pythonhosted.org/packages/04/fd/74903979833db8390b73b3a8a7d30d146d710bd32703724dd9083950386f/pandas-2.3.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:ee15f284898e7b246df8087fc82b87b01686f98ee67d85a17b7ab44143a3a9a0", size = 11540635, upload-time = "2025-09-29T23:25:52.486Z" }, + { url = "https://files.pythonhosted.org/packages/21/00/266d6b357ad5e6d3ad55093a7e8efc7dd245f5a842b584db9f30b0f0a287/pandas-2.3.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:1611aedd912e1ff81ff41c745822980c49ce4a7907537be8692c8dbc31924593", size = 10759079, upload-time = "2025-09-29T23:26:33.204Z" }, + { url = "https://files.pythonhosted.org/packages/ca/05/d01ef80a7a3a12b2f8bbf16daba1e17c98a2f039cbc8e2f77a2c5a63d382/pandas-2.3.3-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6d2cefc361461662ac48810cb14365a365ce864afe85ef1f447ff5a1e99ea81c", size = 11814049, upload-time = "2025-09-29T23:27:15.384Z" }, + { url = "https://files.pythonhosted.org/packages/15/b2/0e62f78c0c5ba7e3d2c5945a82456f4fac76c480940f805e0b97fcbc2f65/pandas-2.3.3-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ee67acbbf05014ea6c763beb097e03cd629961c8a632075eeb34247120abcb4b", size = 12332638, upload-time = "2025-09-29T23:27:51.625Z" }, + { url = "https://files.pythonhosted.org/packages/c5/33/dd70400631b62b9b29c3c93d2feee1d0964dc2bae2e5ad7a6c73a7f25325/pandas-2.3.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c46467899aaa4da076d5abc11084634e2d197e9460643dd455ac3db5856b24d6", size = 12886834, upload-time = "2025-09-29T23:28:21.289Z" }, + { url = "https://files.pythonhosted.org/packages/d3/18/b5d48f55821228d0d2692b34fd5034bb185e854bdb592e9c640f6290e012/pandas-2.3.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:6253c72c6a1d990a410bc7de641d34053364ef8bcd3126f7e7450125887dffe3", size = 13409925, upload-time = "2025-09-29T23:28:58.261Z" }, + { url = "https://files.pythonhosted.org/packages/a6/3d/124ac75fcd0ecc09b8fdccb0246ef65e35b012030defb0e0eba2cbbbe948/pandas-2.3.3-cp314-cp314-win_amd64.whl", hash = "sha256:1b07204a219b3b7350abaae088f451860223a52cfb8a6c53358e7948735158e5", size = 11109071, upload-time = "2025-09-29T23:32:27.484Z" }, + { url = "https://files.pythonhosted.org/packages/89/9c/0e21c895c38a157e0faa1fb64587a9226d6dd46452cac4532d80c3c4a244/pandas-2.3.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:2462b1a365b6109d275250baaae7b760fd25c726aaca0054649286bcfbb3e8ec", size = 12048504, upload-time = "2025-09-29T23:29:31.47Z" }, + { url = "https://files.pythonhosted.org/packages/d7/82/b69a1c95df796858777b68fbe6a81d37443a33319761d7c652ce77797475/pandas-2.3.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:0242fe9a49aa8b4d78a4fa03acb397a58833ef6199e9aa40a95f027bb3a1b6e7", size = 11410702, upload-time = "2025-09-29T23:29:54.591Z" }, + { url = "https://files.pythonhosted.org/packages/f9/88/702bde3ba0a94b8c73a0181e05144b10f13f29ebfc2150c3a79062a8195d/pandas-2.3.3-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a21d830e78df0a515db2b3d2f5570610f5e6bd2e27749770e8bb7b524b89b450", size = 11634535, upload-time = "2025-09-29T23:30:21.003Z" }, + { url = "https://files.pythonhosted.org/packages/a4/1e/1bac1a839d12e6a82ec6cb40cda2edde64a2013a66963293696bbf31fbbb/pandas-2.3.3-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2e3ebdb170b5ef78f19bfb71b0dc5dc58775032361fa188e814959b74d726dd5", size = 12121582, upload-time = "2025-09-29T23:30:43.391Z" }, + { url = "https://files.pythonhosted.org/packages/44/91/483de934193e12a3b1d6ae7c8645d083ff88dec75f46e827562f1e4b4da6/pandas-2.3.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:d051c0e065b94b7a3cea50eb1ec32e912cd96dba41647eb24104b6c6c14c5788", size = 12699963, upload-time = "2025-09-29T23:31:10.009Z" }, + { url = "https://files.pythonhosted.org/packages/70/44/5191d2e4026f86a2a109053e194d3ba7a31a2d10a9c2348368c63ed4e85a/pandas-2.3.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:3869faf4bd07b3b66a9f462417d0ca3a9df29a9f6abd5d0d0dbab15dac7abe87", size = 13202175, upload-time = "2025-09-29T23:31:59.173Z" }, ] [[package]] @@ -1984,37 +2023,57 @@ wheels = [ [[package]] name = "pyyaml" -version = "6.0.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/54/ed/79a089b6be93607fa5cdaedf301d7dfb23af5f25c398d5ead2525b063e17/pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e", size = 130631, upload-time = "2024-08-06T20:33:50.674Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/f8/aa/7af4e81f7acba21a4c6be026da38fd2b872ca46226673c89a758ebdc4fd2/PyYAML-6.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774", size = 184612, upload-time = "2024-08-06T20:32:03.408Z" }, - { url = "https://files.pythonhosted.org/packages/8b/62/b9faa998fd185f65c1371643678e4d58254add437edb764a08c5a98fb986/PyYAML-6.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee", size = 172040, upload-time = "2024-08-06T20:32:04.926Z" }, - { url = "https://files.pythonhosted.org/packages/ad/0c/c804f5f922a9a6563bab712d8dcc70251e8af811fce4524d57c2c0fd49a4/PyYAML-6.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c", size = 736829, upload-time = "2024-08-06T20:32:06.459Z" }, - { url = "https://files.pythonhosted.org/packages/51/16/6af8d6a6b210c8e54f1406a6b9481febf9c64a3109c541567e35a49aa2e7/PyYAML-6.0.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317", size = 764167, upload-time = "2024-08-06T20:32:08.338Z" }, - { url = "https://files.pythonhosted.org/packages/75/e4/2c27590dfc9992f73aabbeb9241ae20220bd9452df27483b6e56d3975cc5/PyYAML-6.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85", size = 762952, upload-time = "2024-08-06T20:32:14.124Z" }, - { url = "https://files.pythonhosted.org/packages/9b/97/ecc1abf4a823f5ac61941a9c00fe501b02ac3ab0e373c3857f7d4b83e2b6/PyYAML-6.0.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4", size = 735301, upload-time = "2024-08-06T20:32:16.17Z" }, - { url = "https://files.pythonhosted.org/packages/45/73/0f49dacd6e82c9430e46f4a027baa4ca205e8b0a9dce1397f44edc23559d/PyYAML-6.0.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e", size = 756638, upload-time = "2024-08-06T20:32:18.555Z" }, - { url = "https://files.pythonhosted.org/packages/22/5f/956f0f9fc65223a58fbc14459bf34b4cc48dec52e00535c79b8db361aabd/PyYAML-6.0.2-cp311-cp311-win32.whl", hash = "sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5", size = 143850, upload-time = "2024-08-06T20:32:19.889Z" }, - { url = "https://files.pythonhosted.org/packages/ed/23/8da0bbe2ab9dcdd11f4f4557ccaf95c10b9811b13ecced089d43ce59c3c8/PyYAML-6.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44", size = 161980, upload-time = "2024-08-06T20:32:21.273Z" }, - { url = "https://files.pythonhosted.org/packages/86/0c/c581167fc46d6d6d7ddcfb8c843a4de25bdd27e4466938109ca68492292c/PyYAML-6.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab", size = 183873, upload-time = "2024-08-06T20:32:25.131Z" }, - { url = "https://files.pythonhosted.org/packages/a8/0c/38374f5bb272c051e2a69281d71cba6fdb983413e6758b84482905e29a5d/PyYAML-6.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725", size = 173302, upload-time = "2024-08-06T20:32:26.511Z" }, - { url = "https://files.pythonhosted.org/packages/c3/93/9916574aa8c00aa06bbac729972eb1071d002b8e158bd0e83a3b9a20a1f7/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5", size = 739154, upload-time = "2024-08-06T20:32:28.363Z" }, - { url = "https://files.pythonhosted.org/packages/95/0f/b8938f1cbd09739c6da569d172531567dbcc9789e0029aa070856f123984/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425", size = 766223, upload-time = "2024-08-06T20:32:30.058Z" }, - { url = "https://files.pythonhosted.org/packages/b9/2b/614b4752f2e127db5cc206abc23a8c19678e92b23c3db30fc86ab731d3bd/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476", size = 767542, upload-time = "2024-08-06T20:32:31.881Z" }, - { url = "https://files.pythonhosted.org/packages/d4/00/dd137d5bcc7efea1836d6264f049359861cf548469d18da90cd8216cf05f/PyYAML-6.0.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48", size = 731164, upload-time = "2024-08-06T20:32:37.083Z" }, - { url = "https://files.pythonhosted.org/packages/c9/1f/4f998c900485e5c0ef43838363ba4a9723ac0ad73a9dc42068b12aaba4e4/PyYAML-6.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b", size = 756611, upload-time = "2024-08-06T20:32:38.898Z" }, - { url = "https://files.pythonhosted.org/packages/df/d1/f5a275fdb252768b7a11ec63585bc38d0e87c9e05668a139fea92b80634c/PyYAML-6.0.2-cp312-cp312-win32.whl", hash = "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4", size = 140591, upload-time = "2024-08-06T20:32:40.241Z" }, - { url = "https://files.pythonhosted.org/packages/0c/e8/4f648c598b17c3d06e8753d7d13d57542b30d56e6c2dedf9c331ae56312e/PyYAML-6.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8", size = 156338, upload-time = "2024-08-06T20:32:41.93Z" }, - { url = "https://files.pythonhosted.org/packages/ef/e3/3af305b830494fa85d95f6d95ef7fa73f2ee1cc8ef5b495c7c3269fb835f/PyYAML-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba", size = 181309, upload-time = "2024-08-06T20:32:43.4Z" }, - { url = "https://files.pythonhosted.org/packages/45/9f/3b1c20a0b7a3200524eb0076cc027a970d320bd3a6592873c85c92a08731/PyYAML-6.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1", size = 171679, upload-time = "2024-08-06T20:32:44.801Z" }, - { url = "https://files.pythonhosted.org/packages/7c/9a/337322f27005c33bcb656c655fa78325b730324c78620e8328ae28b64d0c/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133", size = 733428, upload-time = "2024-08-06T20:32:46.432Z" }, - { url = "https://files.pythonhosted.org/packages/a3/69/864fbe19e6c18ea3cc196cbe5d392175b4cf3d5d0ac1403ec3f2d237ebb5/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484", size = 763361, upload-time = "2024-08-06T20:32:51.188Z" }, - { url = "https://files.pythonhosted.org/packages/04/24/b7721e4845c2f162d26f50521b825fb061bc0a5afcf9a386840f23ea19fa/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5", size = 759523, upload-time = "2024-08-06T20:32:53.019Z" }, - { url = "https://files.pythonhosted.org/packages/2b/b2/e3234f59ba06559c6ff63c4e10baea10e5e7df868092bf9ab40e5b9c56b6/PyYAML-6.0.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc", size = 726660, upload-time = "2024-08-06T20:32:54.708Z" }, - { url = "https://files.pythonhosted.org/packages/fe/0f/25911a9f080464c59fab9027482f822b86bf0608957a5fcc6eaac85aa515/PyYAML-6.0.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652", size = 751597, upload-time = "2024-08-06T20:32:56.985Z" }, - { url = "https://files.pythonhosted.org/packages/14/0d/e2c3b43bbce3cf6bd97c840b46088a3031085179e596d4929729d8d68270/PyYAML-6.0.2-cp313-cp313-win32.whl", hash = "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183", size = 140527, upload-time = "2024-08-06T20:33:03.001Z" }, - { url = "https://files.pythonhosted.org/packages/fa/de/02b54f42487e3d3c6efb3f89428677074ca7bf43aae402517bc7cca949f3/PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563", size = 156446, upload-time = "2024-08-06T20:33:04.33Z" }, +version = "6.0.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/05/8e/961c0007c59b8dd7729d542c61a4d537767a59645b82a0b521206e1e25c2/pyyaml-6.0.3.tar.gz", hash = "sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f", size = 130960, upload-time = "2025-09-25T21:33:16.546Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6d/16/a95b6757765b7b031c9374925bb718d55e0a9ba8a1b6a12d25962ea44347/pyyaml-6.0.3-cp311-cp311-macosx_10_13_x86_64.whl", hash = "sha256:44edc647873928551a01e7a563d7452ccdebee747728c1080d881d68af7b997e", size = 185826, upload-time = "2025-09-25T21:31:58.655Z" }, + { url = "https://files.pythonhosted.org/packages/16/19/13de8e4377ed53079ee996e1ab0a9c33ec2faf808a4647b7b4c0d46dd239/pyyaml-6.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:652cb6edd41e718550aad172851962662ff2681490a8a711af6a4d288dd96824", size = 175577, upload-time = "2025-09-25T21:32:00.088Z" }, + { url = "https://files.pythonhosted.org/packages/0c/62/d2eb46264d4b157dae1275b573017abec435397aa59cbcdab6fc978a8af4/pyyaml-6.0.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:10892704fc220243f5305762e276552a0395f7beb4dbf9b14ec8fd43b57f126c", size = 775556, upload-time = "2025-09-25T21:32:01.31Z" }, + { url = "https://files.pythonhosted.org/packages/10/cb/16c3f2cf3266edd25aaa00d6c4350381c8b012ed6f5276675b9eba8d9ff4/pyyaml-6.0.3-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:850774a7879607d3a6f50d36d04f00ee69e7fc816450e5f7e58d7f17f1ae5c00", size = 882114, upload-time = "2025-09-25T21:32:03.376Z" }, + { url = "https://files.pythonhosted.org/packages/71/60/917329f640924b18ff085ab889a11c763e0b573da888e8404ff486657602/pyyaml-6.0.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b8bb0864c5a28024fac8a632c443c87c5aa6f215c0b126c449ae1a150412f31d", size = 806638, upload-time = "2025-09-25T21:32:04.553Z" }, + { url = "https://files.pythonhosted.org/packages/dd/6f/529b0f316a9fd167281a6c3826b5583e6192dba792dd55e3203d3f8e655a/pyyaml-6.0.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1d37d57ad971609cf3c53ba6a7e365e40660e3be0e5175fa9f2365a379d6095a", size = 767463, upload-time = "2025-09-25T21:32:06.152Z" }, + { url = "https://files.pythonhosted.org/packages/f2/6a/b627b4e0c1dd03718543519ffb2f1deea4a1e6d42fbab8021936a4d22589/pyyaml-6.0.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:37503bfbfc9d2c40b344d06b2199cf0e96e97957ab1c1b546fd4f87e53e5d3e4", size = 794986, upload-time = "2025-09-25T21:32:07.367Z" }, + { url = "https://files.pythonhosted.org/packages/45/91/47a6e1c42d9ee337c4839208f30d9f09caa9f720ec7582917b264defc875/pyyaml-6.0.3-cp311-cp311-win32.whl", hash = "sha256:8098f252adfa6c80ab48096053f512f2321f0b998f98150cea9bd23d83e1467b", size = 142543, upload-time = "2025-09-25T21:32:08.95Z" }, + { url = "https://files.pythonhosted.org/packages/da/e3/ea007450a105ae919a72393cb06f122f288ef60bba2dc64b26e2646fa315/pyyaml-6.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:9f3bfb4965eb874431221a3ff3fdcddc7e74e3b07799e0e84ca4a0f867d449bf", size = 158763, upload-time = "2025-09-25T21:32:09.96Z" }, + { url = "https://files.pythonhosted.org/packages/d1/33/422b98d2195232ca1826284a76852ad5a86fe23e31b009c9886b2d0fb8b2/pyyaml-6.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7f047e29dcae44602496db43be01ad42fc6f1cc0d8cd6c83d342306c32270196", size = 182063, upload-time = "2025-09-25T21:32:11.445Z" }, + { url = "https://files.pythonhosted.org/packages/89/a0/6cf41a19a1f2f3feab0e9c0b74134aa2ce6849093d5517a0c550fe37a648/pyyaml-6.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:fc09d0aa354569bc501d4e787133afc08552722d3ab34836a80547331bb5d4a0", size = 173973, upload-time = "2025-09-25T21:32:12.492Z" }, + { url = "https://files.pythonhosted.org/packages/ed/23/7a778b6bd0b9a8039df8b1b1d80e2e2ad78aa04171592c8a5c43a56a6af4/pyyaml-6.0.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9149cad251584d5fb4981be1ecde53a1ca46c891a79788c0df828d2f166bda28", size = 775116, upload-time = "2025-09-25T21:32:13.652Z" }, + { url = "https://files.pythonhosted.org/packages/65/30/d7353c338e12baef4ecc1b09e877c1970bd3382789c159b4f89d6a70dc09/pyyaml-6.0.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5fdec68f91a0c6739b380c83b951e2c72ac0197ace422360e6d5a959d8d97b2c", size = 844011, upload-time = "2025-09-25T21:32:15.21Z" }, + { url = "https://files.pythonhosted.org/packages/8b/9d/b3589d3877982d4f2329302ef98a8026e7f4443c765c46cfecc8858c6b4b/pyyaml-6.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ba1cc08a7ccde2d2ec775841541641e4548226580ab850948cbfda66a1befcdc", size = 807870, upload-time = "2025-09-25T21:32:16.431Z" }, + { url = "https://files.pythonhosted.org/packages/05/c0/b3be26a015601b822b97d9149ff8cb5ead58c66f981e04fedf4e762f4bd4/pyyaml-6.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8dc52c23056b9ddd46818a57b78404882310fb473d63f17b07d5c40421e47f8e", size = 761089, upload-time = "2025-09-25T21:32:17.56Z" }, + { url = "https://files.pythonhosted.org/packages/be/8e/98435a21d1d4b46590d5459a22d88128103f8da4c2d4cb8f14f2a96504e1/pyyaml-6.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:41715c910c881bc081f1e8872880d3c650acf13dfa8214bad49ed4cede7c34ea", size = 790181, upload-time = "2025-09-25T21:32:18.834Z" }, + { url = "https://files.pythonhosted.org/packages/74/93/7baea19427dcfbe1e5a372d81473250b379f04b1bd3c4c5ff825e2327202/pyyaml-6.0.3-cp312-cp312-win32.whl", hash = "sha256:96b533f0e99f6579b3d4d4995707cf36df9100d67e0c8303a0c55b27b5f99bc5", size = 137658, upload-time = "2025-09-25T21:32:20.209Z" }, + { url = "https://files.pythonhosted.org/packages/86/bf/899e81e4cce32febab4fb42bb97dcdf66bc135272882d1987881a4b519e9/pyyaml-6.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:5fcd34e47f6e0b794d17de1b4ff496c00986e1c83f7ab2fb8fcfe9616ff7477b", size = 154003, upload-time = "2025-09-25T21:32:21.167Z" }, + { url = "https://files.pythonhosted.org/packages/1a/08/67bd04656199bbb51dbed1439b7f27601dfb576fb864099c7ef0c3e55531/pyyaml-6.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:64386e5e707d03a7e172c0701abfb7e10f0fb753ee1d773128192742712a98fd", size = 140344, upload-time = "2025-09-25T21:32:22.617Z" }, + { url = "https://files.pythonhosted.org/packages/d1/11/0fd08f8192109f7169db964b5707a2f1e8b745d4e239b784a5a1dd80d1db/pyyaml-6.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8da9669d359f02c0b91ccc01cac4a67f16afec0dac22c2ad09f46bee0697eba8", size = 181669, upload-time = "2025-09-25T21:32:23.673Z" }, + { url = "https://files.pythonhosted.org/packages/b1/16/95309993f1d3748cd644e02e38b75d50cbc0d9561d21f390a76242ce073f/pyyaml-6.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:2283a07e2c21a2aa78d9c4442724ec1eb15f5e42a723b99cb3d822d48f5f7ad1", size = 173252, upload-time = "2025-09-25T21:32:25.149Z" }, + { url = "https://files.pythonhosted.org/packages/50/31/b20f376d3f810b9b2371e72ef5adb33879b25edb7a6d072cb7ca0c486398/pyyaml-6.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ee2922902c45ae8ccada2c5b501ab86c36525b883eff4255313a253a3160861c", size = 767081, upload-time = "2025-09-25T21:32:26.575Z" }, + { url = "https://files.pythonhosted.org/packages/49/1e/a55ca81e949270d5d4432fbbd19dfea5321eda7c41a849d443dc92fd1ff7/pyyaml-6.0.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a33284e20b78bd4a18c8c2282d549d10bc8408a2a7ff57653c0cf0b9be0afce5", size = 841159, upload-time = "2025-09-25T21:32:27.727Z" }, + { url = "https://files.pythonhosted.org/packages/74/27/e5b8f34d02d9995b80abcef563ea1f8b56d20134d8f4e5e81733b1feceb2/pyyaml-6.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0f29edc409a6392443abf94b9cf89ce99889a1dd5376d94316ae5145dfedd5d6", size = 801626, upload-time = "2025-09-25T21:32:28.878Z" }, + { url = "https://files.pythonhosted.org/packages/f9/11/ba845c23988798f40e52ba45f34849aa8a1f2d4af4b798588010792ebad6/pyyaml-6.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f7057c9a337546edc7973c0d3ba84ddcdf0daa14533c2065749c9075001090e6", size = 753613, upload-time = "2025-09-25T21:32:30.178Z" }, + { url = "https://files.pythonhosted.org/packages/3d/e0/7966e1a7bfc0a45bf0a7fb6b98ea03fc9b8d84fa7f2229e9659680b69ee3/pyyaml-6.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:eda16858a3cab07b80edaf74336ece1f986ba330fdb8ee0d6c0d68fe82bc96be", size = 794115, upload-time = "2025-09-25T21:32:31.353Z" }, + { url = "https://files.pythonhosted.org/packages/de/94/980b50a6531b3019e45ddeada0626d45fa85cbe22300844a7983285bed3b/pyyaml-6.0.3-cp313-cp313-win32.whl", hash = "sha256:d0eae10f8159e8fdad514efdc92d74fd8d682c933a6dd088030f3834bc8e6b26", size = 137427, upload-time = "2025-09-25T21:32:32.58Z" }, + { url = "https://files.pythonhosted.org/packages/97/c9/39d5b874e8b28845e4ec2202b5da735d0199dbe5b8fb85f91398814a9a46/pyyaml-6.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:79005a0d97d5ddabfeeea4cf676af11e647e41d81c9a7722a193022accdb6b7c", size = 154090, upload-time = "2025-09-25T21:32:33.659Z" }, + { url = "https://files.pythonhosted.org/packages/73/e8/2bdf3ca2090f68bb3d75b44da7bbc71843b19c9f2b9cb9b0f4ab7a5a4329/pyyaml-6.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:5498cd1645aa724a7c71c8f378eb29ebe23da2fc0d7a08071d89469bf1d2defb", size = 140246, upload-time = "2025-09-25T21:32:34.663Z" }, + { url = "https://files.pythonhosted.org/packages/9d/8c/f4bd7f6465179953d3ac9bc44ac1a8a3e6122cf8ada906b4f96c60172d43/pyyaml-6.0.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:8d1fab6bb153a416f9aeb4b8763bc0f22a5586065f86f7664fc23339fc1c1fac", size = 181814, upload-time = "2025-09-25T21:32:35.712Z" }, + { url = "https://files.pythonhosted.org/packages/bd/9c/4d95bb87eb2063d20db7b60faa3840c1b18025517ae857371c4dd55a6b3a/pyyaml-6.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:34d5fcd24b8445fadc33f9cf348c1047101756fd760b4dacb5c3e99755703310", size = 173809, upload-time = "2025-09-25T21:32:36.789Z" }, + { url = "https://files.pythonhosted.org/packages/92/b5/47e807c2623074914e29dabd16cbbdd4bf5e9b2db9f8090fa64411fc5382/pyyaml-6.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:501a031947e3a9025ed4405a168e6ef5ae3126c59f90ce0cd6f2bfc477be31b7", size = 766454, upload-time = "2025-09-25T21:32:37.966Z" }, + { url = "https://files.pythonhosted.org/packages/02/9e/e5e9b168be58564121efb3de6859c452fccde0ab093d8438905899a3a483/pyyaml-6.0.3-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b3bc83488de33889877a0f2543ade9f70c67d66d9ebb4ac959502e12de895788", size = 836355, upload-time = "2025-09-25T21:32:39.178Z" }, + { url = "https://files.pythonhosted.org/packages/88/f9/16491d7ed2a919954993e48aa941b200f38040928474c9e85ea9e64222c3/pyyaml-6.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c458b6d084f9b935061bc36216e8a69a7e293a2f1e68bf956dcd9e6cbcd143f5", size = 794175, upload-time = "2025-09-25T21:32:40.865Z" }, + { url = "https://files.pythonhosted.org/packages/dd/3f/5989debef34dc6397317802b527dbbafb2b4760878a53d4166579111411e/pyyaml-6.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7c6610def4f163542a622a73fb39f534f8c101d690126992300bf3207eab9764", size = 755228, upload-time = "2025-09-25T21:32:42.084Z" }, + { url = "https://files.pythonhosted.org/packages/d7/ce/af88a49043cd2e265be63d083fc75b27b6ed062f5f9fd6cdc223ad62f03e/pyyaml-6.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5190d403f121660ce8d1d2c1bb2ef1bd05b5f68533fc5c2ea899bd15f4399b35", size = 789194, upload-time = "2025-09-25T21:32:43.362Z" }, + { url = "https://files.pythonhosted.org/packages/23/20/bb6982b26a40bb43951265ba29d4c246ef0ff59c9fdcdf0ed04e0687de4d/pyyaml-6.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:4a2e8cebe2ff6ab7d1050ecd59c25d4c8bd7e6f400f5f82b96557ac0abafd0ac", size = 156429, upload-time = "2025-09-25T21:32:57.844Z" }, + { url = "https://files.pythonhosted.org/packages/f4/f4/a4541072bb9422c8a883ab55255f918fa378ecf083f5b85e87fc2b4eda1b/pyyaml-6.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:93dda82c9c22deb0a405ea4dc5f2d0cda384168e466364dec6255b293923b2f3", size = 143912, upload-time = "2025-09-25T21:32:59.247Z" }, + { url = "https://files.pythonhosted.org/packages/7c/f9/07dd09ae774e4616edf6cda684ee78f97777bdd15847253637a6f052a62f/pyyaml-6.0.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:02893d100e99e03eda1c8fd5c441d8c60103fd175728e23e431db1b589cf5ab3", size = 189108, upload-time = "2025-09-25T21:32:44.377Z" }, + { url = "https://files.pythonhosted.org/packages/4e/78/8d08c9fb7ce09ad8c38ad533c1191cf27f7ae1effe5bb9400a46d9437fcf/pyyaml-6.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c1ff362665ae507275af2853520967820d9124984e0f7466736aea23d8611fba", size = 183641, upload-time = "2025-09-25T21:32:45.407Z" }, + { url = "https://files.pythonhosted.org/packages/7b/5b/3babb19104a46945cf816d047db2788bcaf8c94527a805610b0289a01c6b/pyyaml-6.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6adc77889b628398debc7b65c073bcb99c4a0237b248cacaf3fe8a557563ef6c", size = 831901, upload-time = "2025-09-25T21:32:48.83Z" }, + { url = "https://files.pythonhosted.org/packages/8b/cc/dff0684d8dc44da4d22a13f35f073d558c268780ce3c6ba1b87055bb0b87/pyyaml-6.0.3-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a80cb027f6b349846a3bf6d73b5e95e782175e52f22108cfa17876aaeff93702", size = 861132, upload-time = "2025-09-25T21:32:50.149Z" }, + { url = "https://files.pythonhosted.org/packages/b1/5e/f77dc6b9036943e285ba76b49e118d9ea929885becb0a29ba8a7c75e29fe/pyyaml-6.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:00c4bdeba853cc34e7dd471f16b4114f4162dc03e6b7afcc2128711f0eca823c", size = 839261, upload-time = "2025-09-25T21:32:51.808Z" }, + { url = "https://files.pythonhosted.org/packages/ce/88/a9db1376aa2a228197c58b37302f284b5617f56a5d959fd1763fb1675ce6/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:66e1674c3ef6f541c35191caae2d429b967b99e02040f5ba928632d9a7f0f065", size = 805272, upload-time = "2025-09-25T21:32:52.941Z" }, + { url = "https://files.pythonhosted.org/packages/da/92/1446574745d74df0c92e6aa4a7b0b3130706a4142b2d1a5869f2eaa423c6/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:16249ee61e95f858e83976573de0f5b2893b3677ba71c9dd36b9cf8be9ac6d65", size = 829923, upload-time = "2025-09-25T21:32:54.537Z" }, + { url = "https://files.pythonhosted.org/packages/f0/7a/1c7270340330e575b92f397352af856a8c06f230aa3e76f86b39d01b416a/pyyaml-6.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4ad1906908f2f5ae4e5a8ddfce73c320c2a1429ec52eafd27138b7f1cbe341c9", size = 174062, upload-time = "2025-09-25T21:32:55.767Z" }, + { url = "https://files.pythonhosted.org/packages/f1/12/de94a39c2ef588c7e6455cfbe7343d3b2dc9d6b6b2f40c4c6565744c873d/pyyaml-6.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:ebc55a14a21cb14062aa4162f906cd962b28e2e9ea38f9b4391244cd8de4ae0b", size = 149341, upload-time = "2025-09-25T21:32:56.828Z" }, ] [[package]] @@ -2879,14 +2938,14 @@ wheels = [ [[package]] name = "xarray" -version = "2025.9.0" +version = "2025.9.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "numpy" }, { name = "packaging" }, { name = "pandas" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/4e/0b/bbb76e05c8e2099baf90e259c29cafe6a525524b1d1da8bfbc39577c043e/xarray-2025.9.0.tar.gz", hash = "sha256:7dd6816fe0062c49c5e9370dd483843bc13e5ed80a47a9ff10baff2b51e070fb", size = 3040318, upload-time = "2025-09-04T04:20:26.296Z" } +sdist = { url = "https://files.pythonhosted.org/packages/d0/5d/e139112a463336c636d4455494f3227b7f47a2e06ca7571e6b88158ffc06/xarray-2025.9.1.tar.gz", hash = "sha256:f34a27a52c13d1f3cceb7b27276aeec47021558363617dd7ef4f4c8b379011c0", size = 3057322, upload-time = "2025-09-30T05:28:53.084Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/8d/f0/73c24457c941b8b08f7d090853e40f4b2cdde88b5da721f3f28e98df77c9/xarray-2025.9.0-py3-none-any.whl", hash = "sha256:79f0e25fb39571f612526ee998ee5404d8725a1db3951aabffdb287388885df0", size = 1349595, upload-time = "2025-09-04T04:20:24.36Z" }, + { url = "https://files.pythonhosted.org/packages/0e/a7/6eeb32e705d510a672f74135f538ad27f87f3d600845bfd3834ea3a77c7e/xarray-2025.9.1-py3-none-any.whl", hash = "sha256:3e9708db0d7915c784ed6c227d81b398dca4957afe68d119481f8a448fc88c44", size = 1364411, upload-time = "2025-09-30T05:28:51.294Z" }, ] From 1d071d3abefea13b8aa410ea401302e6c30e0fc3 Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 2 Oct 2025 12:04:38 -0700 Subject: [PATCH 489/521] create and implement pytest fixtures class SLAFixtures --- tests/analysis/swept_langmuir/__init__.py | 13 +++++++++++++ ...t_plasma_potential__find_didv_peak_location.py | 15 ++++++++++----- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/tests/analysis/swept_langmuir/__init__.py b/tests/analysis/swept_langmuir/__init__.py index e69de29bb2..7263da710c 100644 --- a/tests/analysis/swept_langmuir/__init__.py +++ b/tests/analysis/swept_langmuir/__init__.py @@ -0,0 +1,13 @@ +import numpy as np +import pytest + + +class SLAFixtures: + + @pytest.fixture(scope="class") + def simple_voltage(self): + return np.linspace(-20.0, 20.0, 100) + + @pytest.fixture(scope="class") + def simple_current(self): + return np.linspace(-20.0, 20.0, 100) diff --git a/tests/analysis/swept_langmuir/test_plasma_potential__find_didv_peak_location.py b/tests/analysis/swept_langmuir/test_plasma_potential__find_didv_peak_location.py index b3fee76b96..301872500e 100644 --- a/tests/analysis/swept_langmuir/test_plasma_potential__find_didv_peak_location.py +++ b/tests/analysis/swept_langmuir/test_plasma_potential__find_didv_peak_location.py @@ -17,6 +17,7 @@ find_didv_peak_location, ) from plasmapy.utils.exceptions import PlasmaPyWarning +from tests.analysis.swept_langmuir import SLAFixtures @pytest.mark.parametrize( @@ -52,15 +53,19 @@ def test_didv_namedtuple_index_field_mapping(index, field_name): assert extras[index] == getattr(extras, field_name) -class TestFinddIdVPeakLocation: +class TestFinddIdVPeakLocation(SLAFixtures): + + # @pytest.fixture(scope="class") + # def simple_voltage(self): + # return np.linspace(-20.0, 20.0, 100) + # + # @pytest.fixture(scope="class") + # def simple_current(self): + # return np.linspace(-20.0, 20.0, 100) @pytest.fixture(scope="class") - def simple_voltage(self): - return np.linspace(-20.0, 20.0, 100) @pytest.fixture(scope="class") - def simple_current(self): - return np.linspace(-20.0, 20.0, 100) @pytest.mark.parametrize( ("helper", "used_callable"), From 553493a48c23145e4e089b597c6eda39ba82e6e9 Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 2 Oct 2025 12:58:10 -0700 Subject: [PATCH 490/521] move fixtures to a conftest.py --- tests/analysis/swept_langmuir/__init__.py | 13 ------------- tests/analysis/swept_langmuir/conftest.py | 12 ++++++++++++ ...est_plasma_potential__find_didv_peak_location.py | 11 +---------- 3 files changed, 13 insertions(+), 23 deletions(-) create mode 100644 tests/analysis/swept_langmuir/conftest.py diff --git a/tests/analysis/swept_langmuir/__init__.py b/tests/analysis/swept_langmuir/__init__.py index 7263da710c..e69de29bb2 100644 --- a/tests/analysis/swept_langmuir/__init__.py +++ b/tests/analysis/swept_langmuir/__init__.py @@ -1,13 +0,0 @@ -import numpy as np -import pytest - - -class SLAFixtures: - - @pytest.fixture(scope="class") - def simple_voltage(self): - return np.linspace(-20.0, 20.0, 100) - - @pytest.fixture(scope="class") - def simple_current(self): - return np.linspace(-20.0, 20.0, 100) diff --git a/tests/analysis/swept_langmuir/conftest.py b/tests/analysis/swept_langmuir/conftest.py new file mode 100644 index 0000000000..9253dbb0b0 --- /dev/null +++ b/tests/analysis/swept_langmuir/conftest.py @@ -0,0 +1,12 @@ +import numpy as np +import pytest + + +@pytest.fixture(scope="module") +def simple_voltage(): + return np.linspace(-20.0, 20.0, 100) + + +@pytest.fixture(scope="module") +def simple_current(): + return np.linspace(-20.0, 20.0, 100) diff --git a/tests/analysis/swept_langmuir/test_plasma_potential__find_didv_peak_location.py b/tests/analysis/swept_langmuir/test_plasma_potential__find_didv_peak_location.py index 301872500e..0de396009b 100644 --- a/tests/analysis/swept_langmuir/test_plasma_potential__find_didv_peak_location.py +++ b/tests/analysis/swept_langmuir/test_plasma_potential__find_didv_peak_location.py @@ -17,7 +17,6 @@ find_didv_peak_location, ) from plasmapy.utils.exceptions import PlasmaPyWarning -from tests.analysis.swept_langmuir import SLAFixtures @pytest.mark.parametrize( @@ -53,15 +52,7 @@ def test_didv_namedtuple_index_field_mapping(index, field_name): assert extras[index] == getattr(extras, field_name) -class TestFinddIdVPeakLocation(SLAFixtures): - - # @pytest.fixture(scope="class") - # def simple_voltage(self): - # return np.linspace(-20.0, 20.0, 100) - # - # @pytest.fixture(scope="class") - # def simple_current(self): - # return np.linspace(-20.0, 20.0, 100) +class TestFinddIdVPeakLocation: @pytest.fixture(scope="class") From 7f59cadd3a9efc0672f05026fcbb0dc3cbddbe43 Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 2 Oct 2025 18:08:46 -0700 Subject: [PATCH 491/521] increase size of simple_voltage, make simple_current just be a compy of simple_voltage --- tests/analysis/swept_langmuir/conftest.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/analysis/swept_langmuir/conftest.py b/tests/analysis/swept_langmuir/conftest.py index 9253dbb0b0..e0f73dabb9 100644 --- a/tests/analysis/swept_langmuir/conftest.py +++ b/tests/analysis/swept_langmuir/conftest.py @@ -4,9 +4,9 @@ @pytest.fixture(scope="module") def simple_voltage(): - return np.linspace(-20.0, 20.0, 100) + return np.linspace(-20.0, 20.0, 200) @pytest.fixture(scope="module") -def simple_current(): - return np.linspace(-20.0, 20.0, 100) +def simple_current(simple_voltage): + return simple_voltage.copy() From 0f259e25bd073c5dc68ec542bd0ce072de5d9297 Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 2 Oct 2025 18:09:49 -0700 Subject: [PATCH 492/521] create func arch_current --- tests/analysis/swept_langmuir/conftest.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/tests/analysis/swept_langmuir/conftest.py b/tests/analysis/swept_langmuir/conftest.py index e0f73dabb9..77f7533210 100644 --- a/tests/analysis/swept_langmuir/conftest.py +++ b/tests/analysis/swept_langmuir/conftest.py @@ -10,3 +10,21 @@ def simple_voltage(): @pytest.fixture(scope="module") def simple_current(simple_voltage): return simple_voltage.copy() + + +def arch_current(voltage, *, radius, centroid, positive_arch=True): + # radius: float + # radius of the arch/circle to be generated + # + # centroid: 2 element array + # center (x, y) location of the circle + # + # positive_arch: bool + # if True draw the positive (upper) arch + # if False draw the negative (lower) arch + # + + sign = 1.0 if positive_arch else -1.0 + return sign * np.sqrt( + radius ** 2 - (voltage - centroid[0]) ** 2 + ) + centroid[1] From a81adfc8fc59708a6e3b3606c3ed1b64cdfd6266 Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 2 Oct 2025 18:10:24 -0700 Subject: [PATCH 493/521] create pytext fixture simple_current_two_arches --- tests/analysis/swept_langmuir/conftest.py | 46 +++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/tests/analysis/swept_langmuir/conftest.py b/tests/analysis/swept_langmuir/conftest.py index 77f7533210..8d90f5de22 100644 --- a/tests/analysis/swept_langmuir/conftest.py +++ b/tests/analysis/swept_langmuir/conftest.py @@ -28,3 +28,49 @@ def arch_current(voltage, *, radius, centroid, positive_arch=True): return sign * np.sqrt( radius ** 2 - (voltage - centroid[0]) ** 2 ) + centroid[1] + + +@pytest.fixture(scope="module") +def simple_current_two_arches(simple_voltage): + voltage = simple_voltage + current = np.full_like(voltage, np.nan) + + # inflection_point = location where the two arches transition from + # one to the other + # slope_angle = angle of the slope line at the two arch inflection + # point + # bisect_line_angle = the angle of the line that bisects the + # centroids of the two arch circles + # + inflection_point = np.array([0.0, 0.0]) + slope_angle = np.deg2rad(65.0) + bisect_line_angle = slope_angle - np.deg2rad(90) + + centroid_1 = np.array([1.1 * np.min(voltage), np.nan]) + centroid_2 = np.array([1.1 * np.max(voltage), np.nan]) + + radius_1 = np.abs(centroid_1[0]) / np.cos(bisect_line_angle) + radius_2 = np.abs(centroid_2[0]) / np.cos(bisect_line_angle) + + centroid_1[1] = -radius_1 * np.sin(bisect_line_angle) + inflection_point[1] + centroid_2[1] = radius_2 * np.sin(bisect_line_angle) + inflection_point[1] + + # generate first (left) arch + mask = voltage <= 0 + current[mask] = arch_current( + voltage[mask], + centroid=centroid_1, + radius=radius_1, + positive_arch=False, + ) + + # generate second (right) arch + mask = voltage > 0 + current[mask] = arch_current( + voltage[mask], + centroid=centroid_2, + radius=radius_2, + positive_arch=True, + ) + + return current From b8d1552288d73f495a7f5e8aa870b5de64211061 Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 2 Oct 2025 18:27:24 -0700 Subject: [PATCH 494/521] cleanup imports --- .../test_plasma_potential__find_didv_peak_location.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/analysis/swept_langmuir/test_plasma_potential__find_didv_peak_location.py b/tests/analysis/swept_langmuir/test_plasma_potential__find_didv_peak_location.py index 0de396009b..a9e5456199 100644 --- a/tests/analysis/swept_langmuir/test_plasma_potential__find_didv_peak_location.py +++ b/tests/analysis/swept_langmuir/test_plasma_potential__find_didv_peak_location.py @@ -6,8 +6,8 @@ from unittest import mock -import operator import numpy as np +import operator import pytest from plasmapy.analysis import fit_functions as ffuncs From 82d39318d71c0371ad3667c0e277d26428ac81c0 Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 2 Oct 2025 18:28:32 -0700 Subject: [PATCH 495/521] add test case TestFinddIdVPeakLocation.test_raises() --- ...asma_potential__find_didv_peak_location.py | 29 ++++++++++++++++--- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/tests/analysis/swept_langmuir/test_plasma_potential__find_didv_peak_location.py b/tests/analysis/swept_langmuir/test_plasma_potential__find_didv_peak_location.py index a9e5456199..49ab3e57bd 100644 --- a/tests/analysis/swept_langmuir/test_plasma_potential__find_didv_peak_location.py +++ b/tests/analysis/swept_langmuir/test_plasma_potential__find_didv_peak_location.py @@ -54,10 +54,6 @@ def test_didv_namedtuple_index_field_mapping(index, field_name): class TestFinddIdVPeakLocation: - @pytest.fixture(scope="class") - - @pytest.fixture(scope="class") - @pytest.mark.parametrize( ("helper", "used_callable"), [ @@ -152,3 +148,28 @@ def test_call_of_condition_smooth_fractions(self, simple_voltage, simple_current # passed kwargs assert mock_csf.call_args[1] == {} + + @pytest.mark.usefixtures("request") + @pytest.mark.parametrize( + ("_raises", "voltage", "current", "voltage_window"), + [ + # voltage_window is too small (<3 points) + (pytest.raises(ValueError), "simple_voltage", "simple_current", [4, 5]), + ], + ) + def test_raises(self, _raises, voltage, current, voltage_window, request): + if isinstance(voltage, str): + # assume fixture name + voltage = request.getfixturevalue(voltage) + + if isinstance(current, str): + # assume fixture name + current = request.getfixturevalue(current) + + with _raises: + find_didv_peak_location( + voltage=voltage, + current=current, + voltage_window=voltage_window, + ) + From 0a2e202343bca05b0e79bca885ca996fc653fbf2 Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 2 Oct 2025 18:29:15 -0700 Subject: [PATCH 496/521] add test case TestFinddIdVPeakLocation.test_designed_didv() --- ...asma_potential__find_didv_peak_location.py | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/tests/analysis/swept_langmuir/test_plasma_potential__find_didv_peak_location.py b/tests/analysis/swept_langmuir/test_plasma_potential__find_didv_peak_location.py index 49ab3e57bd..9804681943 100644 --- a/tests/analysis/swept_langmuir/test_plasma_potential__find_didv_peak_location.py +++ b/tests/analysis/swept_langmuir/test_plasma_potential__find_didv_peak_location.py @@ -173,3 +173,33 @@ def test_raises(self, _raises, voltage, current, voltage_window, request): voltage_window=voltage_window, ) + @pytest.mark.usefixtures("request") + @pytest.mark.parametrize( + ("voltage", "current", "kwargs", "expected"), + [ + ( + "simple_voltage", + "simple_current_two_arches", + {"smooth_fractions": [0.0]}, # no smoothing + {"vp": 0.0}, + ), + ], + ) + def test_designed_didv(self, voltage, current, kwargs, expected, request): + if isinstance(voltage, str): + # assume fixture name + voltage = request.getfixturevalue(voltage) + + if isinstance(current, str): + # assume fixture name + current = request.getfixturevalue(current) + + vp, extras = find_didv_peak_location(voltage, current, **kwargs) + + assert isinstance(vp, float) + assert isinstance(extras, dIdVExtras) + + dv = float(np.average(np.diff(voltage))) + vp_expected = expected["vp"] + + assert -0.5 * dv < (vp - vp_expected) < 0.5 * dv From 6d61d31a6e01fe3c14ad39e64ee6f2b1c8b400c5 Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 2 Oct 2025 18:30:01 -0700 Subject: [PATCH 497/521] allow for a smooth_fractions of 0.0 (or no smoothing) --- .../swept_langmuir/plasma_potential.py | 24 ++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py index 0687a623b1..35b280d448 100644 --- a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py +++ b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py @@ -84,7 +84,7 @@ def _condition_smooth_fractions(smooth_fractions, data_size: int): ) smooth_fractions = np.unique(np.sort(smooth_fractions)) - mask1 = smooth_fractions <= 0 + mask1 = smooth_fractions < 0 mask2 = smooth_fractions > 1 mask = np.logical_or(mask1, mask2) if np.count_nonzero(mask) > 0: @@ -113,11 +113,8 @@ def _condition_smooth_fractions(smooth_fractions, data_size: int): mask = savgol_windows > 2 savgol_windows = savgol_windows[mask] - # force windows sizes to be odd - mask = savgol_windows % 2 == 0 - if np.count_nonzero(mask) > 0: - savgol_windows[mask] = savgol_windows[mask] + 1 - savgol_windows = np.unique(savgol_windows) + if 0.0 in smooth_fractions: + savgol_windows = np.sort(np.append(savgol_windows, 0)) # do not let windows sizes exceed data_size mask = savgol_windows <= data_size @@ -169,12 +166,13 @@ def find_didv_peak_location( ``voltage`` window will be used. smooth_fractions : `list[float]` | `None`, default: `None` - An order list of fractions in the interval :math:`(0, 1]` used + An order list of fractions in the interval :math:`[0, 1]` used to compute the Savitzky-Golay filter window sizes. For example, if the ``voltage_windows`` had a size of 50, then a ``smooth_fraction`` value of 0.5 would result in a - Savitzky-Golay window size of 25. If `None` (default), then - ``smooth_fractions`` will default to + Savitzky-Golay window size of 25. For ``smooth_fraction`` + value of ``0.0`` no smoother will be performed. If `None` + (default), then ``smooth_fractions`` will default to ``numpy.linspace(0.01, 0.25, num=30)``. Notes @@ -210,8 +208,12 @@ def find_didv_peak_location( plasma_potentials = [] rtn_extras["savgol_windows"] = [] for _window in savgol_windows: - v_smooth = signal.savgol_filter(voltage_slice, _window, 1) - c_smooth = signal.savgol_filter(current_slice, _window, 1) + if _window == 0: + v_smooth = voltage_slice + c_smooth = current_slice + else: + v_smooth = signal.savgol_filter(voltage_slice, _window, 1) + c_smooth = signal.savgol_filter(current_slice, _window, 1) didv = np.gradient(c_smooth, v_smooth) imax = np.argmax(didv) From 95042f74f0b0a3806fee6f9235a339ff13ee3e27 Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 2 Oct 2025 18:31:15 -0700 Subject: [PATCH 498/521] update error message to indicate smooth_fraction allowed of [0,1] --- src/plasmapy/analysis/swept_langmuir/plasma_potential.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py index 35b280d448..188937813a 100644 --- a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py +++ b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py @@ -75,11 +75,11 @@ def _condition_smooth_fractions(smooth_fractions, data_size: int): if smooth_fractions.ndim != 1: raise ValueError( - "Expected a 1-D list of floats in the interval (0, 1] for argument " + "Expected a 1-D list of floats in the interval [0, 1] for argument " f"'smooth_fractions', but got a {smooth_fractions.ndim}-D list.") elif not np.issubdtype(smooth_fractions.dtype, np.floating): raise ValueError( - "Expected a 1-D list of floats in the interval (0, 1] for argument " + "Expected a 1-D list of floats in the interval [0, 1] for argument " "'smooth_fractions', not all elements are floats." ) @@ -89,7 +89,7 @@ def _condition_smooth_fractions(smooth_fractions, data_size: int): mask = np.logical_or(mask1, mask2) if np.count_nonzero(mask) > 0: raise ValueError( - "Expected a 1-D list of floats in the interval (0, 1] for argument " + "Expected a 1-D list of floats in the interval [0, 1] for argument " f"'smooth_fractions', no elements are within this interval " f"{smooth_fractions.tolist()}." ) From 9497a7056cd48b9818105c9a8107c977713a6c56 Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 2 Oct 2025 18:48:52 -0700 Subject: [PATCH 499/521] update TestConditionSmoothFractions for change in allowing smooth_fraction of zero and even windows --- ...st_plasma_potential__condition_smooth_fractions.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/tests/analysis/swept_langmuir/test_plasma_potential__condition_smooth_fractions.py b/tests/analysis/swept_langmuir/test_plasma_potential__condition_smooth_fractions.py index ead20f4d3f..3986e76b59 100644 --- a/tests/analysis/swept_langmuir/test_plasma_potential__condition_smooth_fractions.py +++ b/tests/analysis/swept_langmuir/test_plasma_potential__condition_smooth_fractions.py @@ -23,11 +23,9 @@ class TestConditionSmoothFractions: # smooth_fractions elements are NOT floats (pytest.raises(ValueError), [1, 2, 3], 10), (pytest.raises(ValueError), ["one", 2., "three"], 10), - # smooth_fractions is out of range.. (0, 1] + # smooth_fractions is out of range.. [0, 1] (pytest.raises(ValueError), [-5.0], 10), - (pytest.raises(ValueError), [0.0], 10), (pytest.raises(ValueError), [5.0], 10), - (pytest.raises(ValueError), [0, 0.1, .9, 1.0], 10), (pytest.raises(ValueError), [-0.5, 0.1, .9, 1.0], 10), (pytest.raises(ValueError), [-0.5, 0, .9, 1.0], 10), (pytest.raises(ValueError), [0.1, .9, 1.1], 10), @@ -52,9 +50,10 @@ def test_raises(self, _raises, smooth_fractions, data_size): @pytest.mark.parametrize( ("smooth_fractions", "data_size", "expected"), [ - ([0.2, 0.5, 0.8], 20, np.array([5, 11, 17], dtype=int)), - ([0.02, 0.2, 0.5, 0.8], 20, np.array([5, 11, 17], dtype=int)), - (None, 50, np.array([3, 5, 7, 9, 11, 13], dtype=int)), + ([0.2, 0.5, 0.8], 20, np.array([4, 10, 16], dtype=int)), + ([0.02, 0.2, 0.5, 0.8], 20, np.array([4, 10, 16], dtype=int)), + ([0.0, 0.02, 0.2, 0.5, 0.8], 20, np.array([0, 4, 10, 16], dtype=int)), + (None, 50, np.array([3, 4, 5, 6, 7, 8, 9, 10, 11, 12], dtype=int)), ], ) def test_expected(self, smooth_fractions, data_size, expected): From 23485b2c6f923a36a2430e0c1864a6dd25183324 Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 2 Oct 2025 18:57:50 -0700 Subject: [PATCH 500/521] add fixtures pace_voltage and pace_current --- tests/analysis/swept_langmuir/conftest.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/tests/analysis/swept_langmuir/conftest.py b/tests/analysis/swept_langmuir/conftest.py index 8d90f5de22..466ac1a2b3 100644 --- a/tests/analysis/swept_langmuir/conftest.py +++ b/tests/analysis/swept_langmuir/conftest.py @@ -1,6 +1,13 @@ +from pathlib import Path + import numpy as np import pytest +from plasmapy.analysis.swept_langmuir import sort_sweep_arrays + +PACE_DATA_FILE = (Path(__file__).parent / "Pace2015.npy").resolve() +PACE_DATA = sort_sweep_arrays(*np.load(PACE_DATA_FILE)) + @pytest.fixture(scope="module") def simple_voltage(): @@ -74,3 +81,13 @@ def simple_current_two_arches(simple_voltage): ) return current + + +@pytest.fixture(scope="module") +def pace_voltage(): + return PACE_DATA[0] + + +@pytest.fixture(scope="module") +def pace_current(): + return PACE_DATA[1] From 746a2abf6dbdc59c50e20257b010d52848f934b0 Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 2 Oct 2025 18:58:16 -0700 Subject: [PATCH 501/521] rough out test TestFinddIdVPeakLocation.test_on_pace_data() --- ...t_plasma_potential__find_didv_peak_location.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tests/analysis/swept_langmuir/test_plasma_potential__find_didv_peak_location.py b/tests/analysis/swept_langmuir/test_plasma_potential__find_didv_peak_location.py index 9804681943..fe43acaf97 100644 --- a/tests/analysis/swept_langmuir/test_plasma_potential__find_didv_peak_location.py +++ b/tests/analysis/swept_langmuir/test_plasma_potential__find_didv_peak_location.py @@ -203,3 +203,18 @@ def test_designed_didv(self, voltage, current, kwargs, expected, request): vp_expected = expected["vp"] assert -0.5 * dv < (vp - vp_expected) < 0.5 * dv + + def test_on_pace_data(self, pace_voltage, pace_current): + vp, extras = find_didv_peak_location( + pace_voltage, + pace_current, + voltage_window=[-33.814, None], + ) + + assert isinstance(vp, float) + assert isinstance(extras, dIdVExtras) + + assert np.isclose(vp, -16.6526) + + # TODO: add tests of extras + assert False From b7225fba3e9c988abf3c277e3681b32eef13699c Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 3 Oct 2025 10:48:31 -0700 Subject: [PATCH 502/521] fill out assertions on extras for TestFinddIdVPeakLocation.test_on_pace_data() --- ...asma_potential__find_didv_peak_location.py | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/tests/analysis/swept_langmuir/test_plasma_potential__find_didv_peak_location.py b/tests/analysis/swept_langmuir/test_plasma_potential__find_didv_peak_location.py index fe43acaf97..51f3a2cffb 100644 --- a/tests/analysis/swept_langmuir/test_plasma_potential__find_didv_peak_location.py +++ b/tests/analysis/swept_langmuir/test_plasma_potential__find_didv_peak_location.py @@ -211,10 +211,21 @@ def test_on_pace_data(self, pace_voltage, pace_current): voltage_window=[-33.814, None], ) + # assertions on computed plasma potential assert isinstance(vp, float) - assert isinstance(extras, dIdVExtras) - assert np.isclose(vp, -16.6526) - # TODO: add tests of extras - assert False + # assertions on extras from computation + assert isinstance(extras, dIdVExtras) + assert np.isclose(extras.std, 0.348483) + assert extras.data_slice == slice(78, None, 1) + assert ( + extras.savgol_windows == [ + 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + ], + ) + assert (extras.savgol_peaks == [ + -16.4, -17.2, -16.8, -17.2, -17.2, -16.4, -16.4, -16.4, -16.0, -16.8, -16.8, + -16.8, -16.8, -16.8, -16.8, -16.8, -16.4, -16.4, -16.0 + ], + ) From 9dda5492e9fd7bf95e5e15c64f633d9f53921585 Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 3 Oct 2025 10:52:58 -0700 Subject: [PATCH 503/521] remove extra, un-needed comma --- .../test_plasma_potential__find_didv_peak_location.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/analysis/swept_langmuir/test_plasma_potential__find_didv_peak_location.py b/tests/analysis/swept_langmuir/test_plasma_potential__find_didv_peak_location.py index 51f3a2cffb..caf981c752 100644 --- a/tests/analysis/swept_langmuir/test_plasma_potential__find_didv_peak_location.py +++ b/tests/analysis/swept_langmuir/test_plasma_potential__find_didv_peak_location.py @@ -222,10 +222,10 @@ def test_on_pace_data(self, pace_voltage, pace_current): assert ( extras.savgol_windows == [ 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, - ], + ] ) assert (extras.savgol_peaks == [ -16.4, -17.2, -16.8, -17.2, -17.2, -16.4, -16.4, -16.4, -16.0, -16.8, -16.8, -16.8, -16.8, -16.8, -16.8, -16.8, -16.4, -16.4, -16.0 - ], + ] ) From 90da4c093203b4fe58e3d7397c6292864e83e44c Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 3 Oct 2025 10:53:19 -0700 Subject: [PATCH 504/521] add noqa C901 to _condition_smooth_fractions() --- src/plasmapy/analysis/swept_langmuir/plasma_potential.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py index 188937813a..5af6199e94 100644 --- a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py +++ b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py @@ -52,7 +52,9 @@ class dIdVExtras(NamedTuple): # noqa: N801 """ -def _condition_smooth_fractions(smooth_fractions, data_size: int): +def _condition_smooth_fractions( # noqa: C901 + smooth_fractions, data_size: int +): """ Condition ``smooth_fractions`` and return the resulting Savitzky-Golay filter windows sizes, based on the ``data_size``. From 5e64badc85d2e4839fb9b11da244d74f90300caf Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 3 Oct 2025 11:05:54 -0700 Subject: [PATCH 505/521] cleanup imports --- .../test_plasma_potential__condition_smooth_fractions.py | 4 +++- .../test_plasma_potential__find_didv_peak_location.py | 4 +--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/analysis/swept_langmuir/test_plasma_potential__condition_smooth_fractions.py b/tests/analysis/swept_langmuir/test_plasma_potential__condition_smooth_fractions.py index 3986e76b59..f484ce807a 100644 --- a/tests/analysis/swept_langmuir/test_plasma_potential__condition_smooth_fractions.py +++ b/tests/analysis/swept_langmuir/test_plasma_potential__condition_smooth_fractions.py @@ -6,7 +6,9 @@ import numpy as np import pytest -from plasmapy.analysis.swept_langmuir.plasma_potential import _condition_smooth_fractions +from plasmapy.analysis.swept_langmuir.plasma_potential import ( + _condition_smooth_fractions, +) class TestConditionSmoothFractions: diff --git a/tests/analysis/swept_langmuir/test_plasma_potential__find_didv_peak_location.py b/tests/analysis/swept_langmuir/test_plasma_potential__find_didv_peak_location.py index caf981c752..b5d7cdc885 100644 --- a/tests/analysis/swept_langmuir/test_plasma_potential__find_didv_peak_location.py +++ b/tests/analysis/swept_langmuir/test_plasma_potential__find_didv_peak_location.py @@ -4,19 +4,17 @@ peak slope of the langmuir drives (i.e. peak dI/dV). """ +import operator from unittest import mock import numpy as np -import operator import pytest -from plasmapy.analysis import fit_functions as ffuncs from plasmapy.analysis import swept_langmuir as sla from plasmapy.analysis.swept_langmuir.plasma_potential import ( dIdVExtras, find_didv_peak_location, ) -from plasmapy.utils.exceptions import PlasmaPyWarning @pytest.mark.parametrize( From f3d96c2ca946c6dda1ae1f7bc4d70f81ce901bce Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 3 Oct 2025 11:08:15 -0700 Subject: [PATCH 506/521] add lint.per-file-ignores."tests/**/conftest.py" = ["D103"] --- pyproject.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/pyproject.toml b/pyproject.toml index 2cfb86cbdd..6f855ecdc4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -331,6 +331,7 @@ lint.per-file-ignores."src/plasmapy/formulary/braginskii.py" = [ "C901", "RET503 lint.per-file-ignores."src/plasmapy/plasma/sources/*.py" = [ "D102" ] lint.per-file-ignores."src/plasmapy/utils/_pytest_helpers/pytest_helpers.py" = [ "BLE001", "PLR", "SLF001" ] lint.per-file-ignores."tests/**/__init__.py" = [ "D104" ] +lint.per-file-ignores."tests/**/conftest.py" = ["D103"] lint.per-file-ignores."tests/**/test_*.py" = [ "D100", "D101", From 9a2fa11c1b85a3c5d11032b02168d7e41fecf3c5 Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 3 Oct 2025 11:09:03 -0700 Subject: [PATCH 507/521] add module docstring --- tests/analysis/swept_langmuir/conftest.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/analysis/swept_langmuir/conftest.py b/tests/analysis/swept_langmuir/conftest.py index 466ac1a2b3..7160e022cd 100644 --- a/tests/analysis/swept_langmuir/conftest.py +++ b/tests/analysis/swept_langmuir/conftest.py @@ -1,3 +1,6 @@ +""" +pytest fixtures for all swept_langmuir tests +""" from pathlib import Path import numpy as np From a60505960e5db30761fb269b91d422c0cb144f3f Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 3 Oct 2025 11:21:31 -0700 Subject: [PATCH 508/521] appease grumpy ruff --- pyproject.toml | 2 +- tests/analysis/swept_langmuir/conftest.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 6f855ecdc4..793ef31b2f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -331,7 +331,7 @@ lint.per-file-ignores."src/plasmapy/formulary/braginskii.py" = [ "C901", "RET503 lint.per-file-ignores."src/plasmapy/plasma/sources/*.py" = [ "D102" ] lint.per-file-ignores."src/plasmapy/utils/_pytest_helpers/pytest_helpers.py" = [ "BLE001", "PLR", "SLF001" ] lint.per-file-ignores."tests/**/__init__.py" = [ "D104" ] -lint.per-file-ignores."tests/**/conftest.py" = ["D103"] +lint.per-file-ignores."tests/**/conftest.py" = [ "D103" ] lint.per-file-ignores."tests/**/test_*.py" = [ "D100", "D101", diff --git a/tests/analysis/swept_langmuir/conftest.py b/tests/analysis/swept_langmuir/conftest.py index 7160e022cd..23e742ea7e 100644 --- a/tests/analysis/swept_langmuir/conftest.py +++ b/tests/analysis/swept_langmuir/conftest.py @@ -1,5 +1,5 @@ """ -pytest fixtures for all swept_langmuir tests +pytest fixtures for all swept_langmuir tests. """ from pathlib import Path From fbfb3e562313dfeb22f3f9ad01dfac50c4487ee7 Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 3 Oct 2025 11:24:38 -0700 Subject: [PATCH 509/521] appease grumpy ruff format --- tests/analysis/swept_langmuir/conftest.py | 5 +- ...a_potential__condition_smooth_fractions.py | 14 +-- ...asma_potential__find_didv_peak_location.py | 98 ++++++++++++------- 3 files changed, 71 insertions(+), 46 deletions(-) diff --git a/tests/analysis/swept_langmuir/conftest.py b/tests/analysis/swept_langmuir/conftest.py index 23e742ea7e..4857bd0ff0 100644 --- a/tests/analysis/swept_langmuir/conftest.py +++ b/tests/analysis/swept_langmuir/conftest.py @@ -1,6 +1,7 @@ """ pytest fixtures for all swept_langmuir tests. """ + from pathlib import Path import numpy as np @@ -35,9 +36,7 @@ def arch_current(voltage, *, radius, centroid, positive_arch=True): # sign = 1.0 if positive_arch else -1.0 - return sign * np.sqrt( - radius ** 2 - (voltage - centroid[0]) ** 2 - ) + centroid[1] + return sign * np.sqrt(radius**2 - (voltage - centroid[0]) ** 2) + centroid[1] @pytest.fixture(scope="module") diff --git a/tests/analysis/swept_langmuir/test_plasma_potential__condition_smooth_fractions.py b/tests/analysis/swept_langmuir/test_plasma_potential__condition_smooth_fractions.py index f484ce807a..e1ddd3ecd4 100644 --- a/tests/analysis/swept_langmuir/test_plasma_potential__condition_smooth_fractions.py +++ b/tests/analysis/swept_langmuir/test_plasma_potential__condition_smooth_fractions.py @@ -24,16 +24,16 @@ class TestConditionSmoothFractions: (pytest.raises(ValueError), np.zeros((2, 5)), 10), # smooth_fractions elements are NOT floats (pytest.raises(ValueError), [1, 2, 3], 10), - (pytest.raises(ValueError), ["one", 2., "three"], 10), + (pytest.raises(ValueError), ["one", 2.0, "three"], 10), # smooth_fractions is out of range.. [0, 1] (pytest.raises(ValueError), [-5.0], 10), (pytest.raises(ValueError), [5.0], 10), - (pytest.raises(ValueError), [-0.5, 0.1, .9, 1.0], 10), - (pytest.raises(ValueError), [-0.5, 0, .9, 1.0], 10), - (pytest.raises(ValueError), [0.1, .9, 1.1], 10), - (pytest.raises(ValueError), [0.1, .9, 20.0], 10), - (pytest.raises(ValueError), [0, 0.1, .9, 1.1], 10), - (pytest.raises(ValueError), [-20.0, 0, 0.1, .9, 1.1], 10), + (pytest.raises(ValueError), [-0.5, 0.1, 0.9, 1.0], 10), + (pytest.raises(ValueError), [-0.5, 0, 0.9, 1.0], 10), + (pytest.raises(ValueError), [0.1, 0.9, 1.1], 10), + (pytest.raises(ValueError), [0.1, 0.9, 20.0], 10), + (pytest.raises(ValueError), [0, 0.1, 0.9, 1.1], 10), + (pytest.raises(ValueError), [-20.0, 0, 0.1, 0.9, 1.1], 10), # data_size not integer (pytest.raises(TypeError), [0.2, 0.5, 0.8], "hello"), (pytest.raises(TypeError), [0.2, 0.5, 0.8], 90.5), diff --git a/tests/analysis/swept_langmuir/test_plasma_potential__find_didv_peak_location.py b/tests/analysis/swept_langmuir/test_plasma_potential__find_didv_peak_location.py index b5d7cdc885..1f0b5f1999 100644 --- a/tests/analysis/swept_langmuir/test_plasma_potential__find_didv_peak_location.py +++ b/tests/analysis/swept_langmuir/test_plasma_potential__find_didv_peak_location.py @@ -51,7 +51,6 @@ def test_didv_namedtuple_index_field_mapping(index, field_name): class TestFinddIdVPeakLocation: - @pytest.mark.parametrize( ("helper", "used_callable"), [ @@ -70,7 +69,6 @@ def test_helper_callable_consistency(self, helper, used_callable): assert helper is used_callable def test_call_of_check_sweep(self, simple_voltage, simple_current) -> None: - with mock.patch(f"{sla.plasma_potential.__name__}.check_sweep") as mock_cs: mock_cs.return_value = simple_voltage, simple_current find_didv_peak_location(voltage=simple_voltage, current=simple_current) @@ -85,12 +83,12 @@ def test_call_of_check_sweep(self, simple_voltage, simple_current) -> None: # passed kwargs assert mock_cs.call_args[1] == {"strip_units": True} - def test_call_of_merge_voltage_clusters(self, simple_voltage, simple_current) -> None: - - with ( - mock.patch(f"{sla.plasma_potential.__name__}.merge_voltage_clusters") - as mock_mvc - ): + def test_call_of_merge_voltage_clusters( + self, simple_voltage, simple_current + ) -> None: + with mock.patch( + f"{sla.plasma_potential.__name__}.merge_voltage_clusters" + ) as mock_mvc: mock_mvc.return_value = simple_voltage, simple_current find_didv_peak_location(voltage=simple_voltage, current=simple_current) @@ -104,15 +102,13 @@ def test_call_of_merge_voltage_clusters(self, simple_voltage, simple_current) -> # passed kwargs assert mock_mvc.call_args[1] == {"voltage_step_size": 0} - def test_call_of_condition_voltage_window(self, simple_voltage, simple_current) -> None: - - with ( - mock.patch( - f"{sla.plasma_potential.__name__}._condition_voltage_window", - side_effect=sla.plasma_potential._condition_voltage_window, - ) - as mock_cvw - ): + def test_call_of_condition_voltage_window( + self, simple_voltage, simple_current + ) -> None: + with mock.patch( + f"{sla.plasma_potential.__name__}._condition_voltage_window", + side_effect=sla.plasma_potential._condition_voltage_window, + ) as mock_cvw: # mock_cvw.return_value = varr, carr find_didv_peak_location(voltage=simple_voltage, current=simple_current) @@ -126,15 +122,13 @@ def test_call_of_condition_voltage_window(self, simple_voltage, simple_current) # passed kwargs assert mock_cvw.call_args[1] == {} - def test_call_of_condition_smooth_fractions(self, simple_voltage, simple_current) -> None: - - with ( - mock.patch( - f"{sla.plasma_potential.__name__}._condition_smooth_fractions", - side_effect=sla.plasma_potential._condition_smooth_fractions, - ) - as mock_csf - ): + def test_call_of_condition_smooth_fractions( + self, simple_voltage, simple_current + ) -> None: + with mock.patch( + f"{sla.plasma_potential.__name__}._condition_smooth_fractions", + side_effect=sla.plasma_potential._condition_smooth_fractions, + ) as mock_csf: find_didv_peak_location(voltage=simple_voltage, current=simple_current) assert mock_csf.call_count == 1 @@ -217,13 +211,45 @@ def test_on_pace_data(self, pace_voltage, pace_current): assert isinstance(extras, dIdVExtras) assert np.isclose(extras.std, 0.348483) assert extras.data_slice == slice(78, None, 1) - assert ( - extras.savgol_windows == [ - 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, - ] - ) - assert (extras.savgol_peaks == [ - -16.4, -17.2, -16.8, -17.2, -17.2, -16.4, -16.4, -16.4, -16.0, -16.8, -16.8, - -16.8, -16.8, -16.8, -16.8, -16.8, -16.4, -16.4, -16.0 - ] - ) + assert extras.savgol_windows == [ + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + ] + assert extras.savgol_peaks == [ + -16.4, + -17.2, + -16.8, + -17.2, + -17.2, + -16.4, + -16.4, + -16.4, + -16.0, + -16.8, + -16.8, + -16.8, + -16.8, + -16.8, + -16.8, + -16.8, + -16.4, + -16.4, + -16.0, + ] From 01a156c0b68daaf6ea4d005b4267a949dd3fe8b6 Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 3 Oct 2025 12:19:32 -0700 Subject: [PATCH 510/521] appease grumpy ruff format --- src/plasmapy/analysis/swept_langmuir/helpers.py | 4 ++-- src/plasmapy/analysis/swept_langmuir/plasma_potential.py | 7 +++++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/plasmapy/analysis/swept_langmuir/helpers.py b/src/plasmapy/analysis/swept_langmuir/helpers.py index 94f8e49ac8..073358af36 100644 --- a/src/plasmapy/analysis/swept_langmuir/helpers.py +++ b/src/plasmapy/analysis/swept_langmuir/helpers.py @@ -569,7 +569,7 @@ def merge_voltage_clusters( # noqa: C901, PLR0912 def _condition_voltage_window( # noqa: C901, PLR0912 - voltage, voltage_window + voltage, voltage_window ) -> slice: """ Condition ``voltage_window`` and return resulting `slice` object to @@ -652,7 +652,7 @@ def _condition_voltage_window( # noqa: C901, PLR0912 ) if last_index is None: pass - elif last_index == voltage.size-1: + elif last_index == voltage.size - 1: last_index = None else: last_index += 1 diff --git a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py index 5af6199e94..483d8ff352 100644 --- a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py +++ b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py @@ -67,7 +67,9 @@ def _condition_smooth_fractions( # noqa: C901 smooth_fractions = np.linspace(0.01, 0.25, num=30) elif isinstance(smooth_fractions, np.ndarray): pass - elif not isinstance(smooth_fractions, Sequence) or isinstance(smooth_fractions, str): + elif not isinstance(smooth_fractions, Sequence) or isinstance( + smooth_fractions, str + ): raise TypeError( f"Expected a list-like object for 'smooth_fractions', " f"but got type {type(smooth_fractions)}." @@ -78,7 +80,8 @@ def _condition_smooth_fractions( # noqa: C901 if smooth_fractions.ndim != 1: raise ValueError( "Expected a 1-D list of floats in the interval [0, 1] for argument " - f"'smooth_fractions', but got a {smooth_fractions.ndim}-D list.") + f"'smooth_fractions', but got a {smooth_fractions.ndim}-D list." + ) elif not np.issubdtype(smooth_fractions.dtype, np.floating): raise ValueError( "Expected a 1-D list of floats in the interval [0, 1] for argument " From aa7ae66a75fde405ce2742839cf4db9b29fc7bac Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 3 Oct 2025 12:20:57 -0700 Subject: [PATCH 511/521] remove noqa D103 since it is now defined in pyproject.toml --- tests/particles/conftest.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/particles/conftest.py b/tests/particles/conftest.py index e68c848228..2ddd50620f 100644 --- a/tests/particles/conftest.py +++ b/tests/particles/conftest.py @@ -8,12 +8,12 @@ @pytest.fixture(params=sorted(particle_zoo.everything)) -def particle(request): # noqa: D103 +def particle(request): return Particle(request.param) @pytest.fixture -def opposite(particle): # noqa: D103 +def opposite(particle): try: opposite_particle = ~particle except Exception as exc: @@ -38,5 +38,5 @@ def opposite(particle): # noqa: D103 ] ) ) -def particle_antiparticle_pair(request): # noqa: D103 +def particle_antiparticle_pair(request): return [Particle(p) for p in request.param] From 3e1b6b6528d1931b21f02f64e96e7ebdafaa2e74 Mon Sep 17 00:00:00 2001 From: Erik Date: Fri, 3 Oct 2025 12:28:55 -0700 Subject: [PATCH 512/521] appease grumpy ruff format --- .../find_didv_peak_location.ipynb | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/docs/notebooks/analysis/swept_langmuir/find_didv_peak_location.ipynb b/docs/notebooks/analysis/swept_langmuir/find_didv_peak_location.ipynb index 306d676873..7ba188e1bf 100644 --- a/docs/notebooks/analysis/swept_langmuir/find_didv_peak_location.ipynb +++ b/docs/notebooks/analysis/swept_langmuir/find_didv_peak_location.ipynb @@ -173,7 +173,7 @@ "axs[0].set_xlabel(\"Bias Voltage (V)\", fontsize=_font_size)\n", "axs[0].set_ylabel(\"Current (A)\", fontsize=_font_size)\n", "\n", - "axs[0].plot(voltage, current, label=\"Sweep Data\")\n", + "axs[0].plot(voltage, current, label=\"Sweep Data\")\n", "\n", "ylim = axs[0].get_ylim()\n", "xlim = axs[0].get_xlim()\n", @@ -181,8 +181,8 @@ "axs[0].axvline(bias, color=\"grey\")\n", "axs[0].fill_between(\n", " [bias - extras.std, bias + extras.std],\n", - " 2*[ylim[0]],\n", - " 2*[ylim[1]],\n", + " 2 * [ylim[0]],\n", + " 2 * [ylim[1]],\n", " color=\"grey\",\n", " alpha=0.2,\n", ")\n", @@ -208,7 +208,9 @@ "\n", "axs[1].set_xlim(xlim)\n", "\n", - "voltage_merge, current_merge = sla.merge_voltage_clusters(voltage, current, voltage_step_size=0)\n", + "voltage_merge, current_merge = sla.merge_voltage_clusters(\n", + " voltage, current, voltage_step_size=0\n", + ")\n", "voltage_slice = voltage_merge[extras.data_slice]\n", "current_slice = current_merge[extras.data_slice]\n", "\n", @@ -232,11 +234,11 @@ "axs[1].axvline(bias, color=\"grey\", zorder=100)\n", "axs[1].fill_between(\n", " [bias - extras.std, bias + extras.std],\n", - " 2*[ylim[0]],\n", - " 2*[ylim[1]],\n", + " 2 * [ylim[0]],\n", + " 2 * [ylim[1]],\n", " color=\"grey\",\n", " alpha=0.2,\n", - " zorder=0\n", + " zorder=0,\n", ")\n", "\n", "axs[1].legend();" @@ -267,7 +269,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.13.3" + "version": "3.13.7" } }, "nbformat": 4, From b7e843874e076f3a8b959bbc1c99500cf383d81e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 8 Oct 2025 11:57:10 -0400 Subject: [PATCH 513/521] Bump astral-sh/setup-uv from 6 to 7 in /.github/workflows (#3117) Bumps [astral-sh/setup-uv](https://github.com/astral-sh/setup-uv) from 6 to 7. - [Release notes](https://github.com/astral-sh/setup-uv/releases) - [Commits](https://github.com/astral-sh/setup-uv/compare/v6...v7) --- updated-dependencies: - dependency-name: astral-sh/setup-uv dependency-version: '7' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/check-author-included.yml | 2 +- .github/workflows/ci.yml | 2 +- .github/workflows/linkcheck.yml | 2 +- .github/workflows/prepare-release-pr.yml | 2 +- .github/workflows/update-pinned-reqs.yml | 2 +- .github/workflows/weekly.yml | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/check-author-included.yml b/.github/workflows/check-author-included.yml index de5ffde5fe..c5908e8cf9 100644 --- a/.github/workflows/check-author-included.yml +++ b/.github/workflows/check-author-included.yml @@ -18,7 +18,7 @@ jobs: persist-credentials: false - name: Install uv - uses: astral-sh/setup-uv@v6 + uses: astral-sh/setup-uv@v7 with: enable-cache: true cache-suffix: author-cff diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f74706e30e..5257d3a0d5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -98,7 +98,7 @@ jobs: sudo apt-get install -y pandoc - name: Install uv - uses: astral-sh/setup-uv@v6 + uses: astral-sh/setup-uv@v7 with: python-version: ${{ matrix.python }} enable-cache: true # zizmor: ignore[cache-poisoning] diff --git a/.github/workflows/linkcheck.yml b/.github/workflows/linkcheck.yml index d933b69600..c7deed76ad 100644 --- a/.github/workflows/linkcheck.yml +++ b/.github/workflows/linkcheck.yml @@ -41,7 +41,7 @@ jobs: sudo apt-get install -y pandoc - name: Install uv - uses: astral-sh/setup-uv@v6 + uses: astral-sh/setup-uv@v7 with: python-version: 3.12 diff --git a/.github/workflows/prepare-release-pr.yml b/.github/workflows/prepare-release-pr.yml index e6ee0a90fd..b79ee527b7 100644 --- a/.github/workflows/prepare-release-pr.yml +++ b/.github/workflows/prepare-release-pr.yml @@ -43,7 +43,7 @@ jobs: persist-credentials: false - name: Install uv - uses: astral-sh/setup-uv@v6 + uses: astral-sh/setup-uv@v7 - name: Update version and DOI in CITATION.cff and docs/about/citation.rst run: | diff --git a/.github/workflows/update-pinned-reqs.yml b/.github/workflows/update-pinned-reqs.yml index bc96095ae2..29d1290108 100644 --- a/.github/workflows/update-pinned-reqs.yml +++ b/.github/workflows/update-pinned-reqs.yml @@ -19,7 +19,7 @@ jobs: persist-credentials: false - name: Install uv - uses: astral-sh/setup-uv@v6 + uses: astral-sh/setup-uv@v7 with: python: 3.13 diff --git a/.github/workflows/weekly.yml b/.github/workflows/weekly.yml index 4519023981..9fbf3c3681 100644 --- a/.github/workflows/weekly.yml +++ b/.github/workflows/weekly.yml @@ -164,7 +164,7 @@ jobs: sudo apt-get install -y pandoc - name: Install uv - uses: astral-sh/setup-uv@v6 + uses: astral-sh/setup-uv@v7 with: python-version: ${{ matrix.python }} enable-cache: true From 036d670c00006b89512dacfef11f9f5a65038072 Mon Sep 17 00:00:00 2001 From: "plasmapy-requirements-bot[bot]" <134649236+plasmapy-requirements-bot[bot]@users.noreply.github.com> Date: Sat, 11 Oct 2025 19:28:45 -0400 Subject: [PATCH 514/521] Update requirements with 'nox -s requirements' (#3118) Co-authored-by: namurphy <8931994+namurphy@users.noreply.github.com> --- uv.lock | 262 +++++++++++++++++++++++++++++--------------------------- 1 file changed, 136 insertions(+), 126 deletions(-) diff --git a/uv.lock b/uv.lock index 373727a94a..c13a1fb5b7 100644 --- a/uv.lock +++ b/uv.lock @@ -80,11 +80,11 @@ wheels = [ [[package]] name = "astropy-iers-data" -version = "0.2025.9.29.0.35.48" +version = "0.2025.10.6.0.35.25" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/3b/9f/73b96768c677bbf31da639ba12a5f54a0b28ed9fd292ce1af2b6b6b591c9/astropy_iers_data-0.2025.9.29.0.35.48.tar.gz", hash = "sha256:0a7841c9a0ff41e2abafcde984cb6b271cdfd9cb5b13e01d5ddd0ed2e8fc4065", size = 1909905, upload-time = "2025-09-29T00:36:26.92Z" } +sdist = { url = "https://files.pythonhosted.org/packages/c8/d2/7a41e765d318449d00a42a9bc29a1c8c681709615adb6555ae62c326074b/astropy_iers_data-0.2025.10.6.0.35.25.tar.gz", hash = "sha256:60a0a8ff69dcb2d3470071f444c58685b06299c48214349a1a0ce2d44e178f76", size = 1910387, upload-time = "2025-10-06T00:36:05.541Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/19/3a/1fd856a497a4add1b9b782061b5a804ed35a66e395a43a08f877eb32b193/astropy_iers_data-0.2025.9.29.0.35.48-py3-none-any.whl", hash = "sha256:c6988670a03a66fefe9266164194c8e5d74513efd13af47efe2829b7be4b5159", size = 1965541, upload-time = "2025-09-29T00:36:24.918Z" }, + { url = "https://files.pythonhosted.org/packages/c5/38/be921eaf8fc67333fd2c2657ea965103ccc4050c29a66d5fd5f3db881c0f/astropy_iers_data-0.2025.10.6.0.35.25-py3-none-any.whl", hash = "sha256:b6f572ee3ae4e02e4ae377229b533ed89d6f8eb027ae31e380cbc8096735ba49", size = 1966052, upload-time = "2025-10-06T00:36:03.945Z" }, ] [[package]] @@ -98,11 +98,11 @@ wheels = [ [[package]] name = "attrs" -version = "25.3.0" +version = "25.4.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/5a/b0/1367933a8532ee6ff8d63537de4f1177af4bff9f3e829baf7331f595bb24/attrs-25.3.0.tar.gz", hash = "sha256:75d7cefc7fb576747b2c81b4442d4d4a1ce0900973527c011d1030fd3bf4af1b", size = 812032, upload-time = "2025-03-13T11:10:22.779Z" } +sdist = { url = "https://files.pythonhosted.org/packages/6b/5c/685e6633917e101e5dcb62b9dd76946cbb57c26e133bae9e0cd36033c0a9/attrs-25.4.0.tar.gz", hash = "sha256:16d5969b87f0859ef33a48b35d55ac1be6e42ae49d5e853b597db70c35c57e11", size = 934251, upload-time = "2025-10-06T13:54:44.725Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/77/06/bb80f5f86020c4551da315d78b3ab75e8228f89f0162f2c3a819e407941a/attrs-25.3.0-py3-none-any.whl", hash = "sha256:427318ce031701fea540783410126f03899a97ffc6f61596ad581ac2e40e3bc3", size = 63815, upload-time = "2025-03-13T11:10:21.14Z" }, + { url = "https://files.pythonhosted.org/packages/3a/2a/7cc015f5b9f5db42b7d48157e23356022889fc354a2813c15934b7cb5c0e/attrs-25.4.0-py3-none-any.whl", hash = "sha256:adcf7e2a1fb3b36ac48d97835bb6d8ade15b8dcce26aba8bf1d14847b57a3373", size = 67615, upload-time = "2025-10-06T13:54:43.17Z" }, ] [[package]] @@ -146,11 +146,11 @@ css = [ [[package]] name = "certifi" -version = "2025.8.3" +version = "2025.10.5" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/dc/67/960ebe6bf230a96cda2e0abcf73af550ec4f090005363542f0765df162e0/certifi-2025.8.3.tar.gz", hash = "sha256:e564105f78ded564e3ae7c923924435e1daa7463faeab5bb932bc53ffae63407", size = 162386, upload-time = "2025-08-03T03:07:47.08Z" } +sdist = { url = "https://files.pythonhosted.org/packages/4c/5b/b6ce21586237c77ce67d01dc5507039d444b630dd76611bbca2d8e5dcd91/certifi-2025.10.5.tar.gz", hash = "sha256:47c09d31ccf2acf0be3f701ea53595ee7e0b8fa08801c6624be771df09ae7b43", size = 164519, upload-time = "2025-10-05T04:12:15.808Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/e5/48/1549795ba7742c948d2ad169c1c8cdbae65bc450d6cd753d124b17c8cd32/certifi-2025.8.3-py3-none-any.whl", hash = "sha256:f6c12493cfb1b06ba2ff328595af9350c65d6644968e5d3a2ffd78699af217a5", size = 161216, upload-time = "2025-08-03T03:07:45.777Z" }, + { url = "https://files.pythonhosted.org/packages/e4/37/af0d2ef3967ac0d6113837b44a4f0bfe1328c2b9763bd5b1744520e5cfed/certifi-2025.10.5-py3-none-any.whl", hash = "sha256:0f212c2744a9bb6de0c56639a6f68afe01ecd92d91f14ae897c4fe7bbeeef0de", size = 163286, upload-time = "2025-10-05T04:12:14.03Z" }, ] [[package]] @@ -612,11 +612,11 @@ wheels = [ [[package]] name = "filelock" -version = "3.19.1" +version = "3.20.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/40/bb/0ab3e58d22305b6f5440629d20683af28959bf793d98d11950e305c1c326/filelock-3.19.1.tar.gz", hash = "sha256:66eda1888b0171c998b35be2bcc0f6d75c388a7ce20c3f3f37aa8e96c2dddf58", size = 17687, upload-time = "2025-08-14T16:56:03.016Z" } +sdist = { url = "https://files.pythonhosted.org/packages/58/46/0028a82567109b5ef6e4d2a1f04a583fb513e6cf9527fcdd09afd817deeb/filelock-3.20.0.tar.gz", hash = "sha256:711e943b4ec6be42e1d4e6690b48dc175c822967466bb31c0c293f34334c13f4", size = 18922, upload-time = "2025-10-08T18:03:50.056Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/42/14/42b2651a2f46b022ccd948bca9f2d5af0fd8929c4eec235b8d6d844fbe67/filelock-3.19.1-py3-none-any.whl", hash = "sha256:d38e30481def20772f5baf097c122c3babc4fcdb7e14e57049eb9d88c6dc017d", size = 15988, upload-time = "2025-08-14T16:56:01.633Z" }, + { url = "https://files.pythonhosted.org/packages/76/91/7216b27286936c16f5b4d0c530087e4a54eead683e6b0b73dd0c64844af6/filelock-3.20.0-py3-none-any.whl", hash = "sha256:339b4732ffda5cd79b13f4e2711a31b0365ce445d95d243bb996273d072546a2", size = 16054, upload-time = "2025-10-08T18:03:48.35Z" }, ] [[package]] @@ -696,15 +696,15 @@ wheels = [ [[package]] name = "hypothesis" -version = "6.140.2" +version = "6.140.3" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "attrs" }, { name = "sortedcontainers" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/ad/4a/3c340178b986b44b4f71ddb04625c8fb8bf815e7c7e23a6aabb2ce17e849/hypothesis-6.140.2.tar.gz", hash = "sha256:b3b4a162134eeef8a992621de6c43d80e03d44704a3c3bfb5b9d0661b375b0d2", size = 466699, upload-time = "2025-09-23T00:07:21.087Z" } +sdist = { url = "https://files.pythonhosted.org/packages/18/7f/946343e32881b56adc0eba64e428ad2f85251f9ef16e3e4ec1b6ab80199b/hypothesis-6.140.3.tar.gz", hash = "sha256:4f4a09bf77af21e0cc3dffed1ea639812dc75d38f81308ec9fb0e33f8557b0cb", size = 466925, upload-time = "2025-10-04T22:29:44.499Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/e9/7d/7dd3684f9cb707b6b1e808c7f23dd0fa4a96fe106b6accd9b757c9985c50/hypothesis-6.140.2-py3-none-any.whl", hash = "sha256:4524cb84be90961563ef15634e2efe96150bbcce47621a13cff3c1b03a326663", size = 534388, upload-time = "2025-09-23T00:07:16.555Z" }, + { url = "https://files.pythonhosted.org/packages/65/2a/0553ac2a8af432df92f2ffc05ca97e7ed64e00c97a371b019ae2690de325/hypothesis-6.140.3-py3-none-any.whl", hash = "sha256:a2cfff51641a58a56081f5c90ae1da6ccf3d043404f411805f7f0e0d75742d0e", size = 534534, upload-time = "2025-10-04T22:29:40.635Z" }, ] [[package]] @@ -1098,7 +1098,7 @@ wheels = [ [[package]] name = "matplotlib" -version = "3.10.6" +version = "3.10.7" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "contourpy" }, @@ -1111,53 +1111,53 @@ dependencies = [ { name = "pyparsing" }, { name = "python-dateutil" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/a0/59/c3e6453a9676ffba145309a73c462bb407f4400de7de3f2b41af70720a3c/matplotlib-3.10.6.tar.gz", hash = "sha256:ec01b645840dd1996df21ee37f208cd8ba57644779fa20464010638013d3203c", size = 34804264, upload-time = "2025-08-30T00:14:25.137Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/80/d6/5d3665aa44c49005aaacaa68ddea6fcb27345961cd538a98bb0177934ede/matplotlib-3.10.6-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:905b60d1cb0ee604ce65b297b61cf8be9f4e6cfecf95a3fe1c388b5266bc8f4f", size = 8257527, upload-time = "2025-08-30T00:12:45.31Z" }, - { url = "https://files.pythonhosted.org/packages/8c/af/30ddefe19ca67eebd70047dabf50f899eaff6f3c5e6a1a7edaecaf63f794/matplotlib-3.10.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7bac38d816637343e53d7185d0c66677ff30ffb131044a81898b5792c956ba76", size = 8119583, upload-time = "2025-08-30T00:12:47.236Z" }, - { url = "https://files.pythonhosted.org/packages/d3/29/4a8650a3dcae97fa4f375d46efcb25920d67b512186f8a6788b896062a81/matplotlib-3.10.6-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:942a8de2b5bfff1de31d95722f702e2966b8a7e31f4e68f7cd963c7cd8861cf6", size = 8692682, upload-time = "2025-08-30T00:12:48.781Z" }, - { url = "https://files.pythonhosted.org/packages/aa/d3/b793b9cb061cfd5d42ff0f69d1822f8d5dbc94e004618e48a97a8373179a/matplotlib-3.10.6-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a3276c85370bc0dfca051ec65c5817d1e0f8f5ce1b7787528ec8ed2d524bbc2f", size = 9521065, upload-time = "2025-08-30T00:12:50.602Z" }, - { url = "https://files.pythonhosted.org/packages/f7/c5/53de5629f223c1c66668d46ac2621961970d21916a4bc3862b174eb2a88f/matplotlib-3.10.6-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9df5851b219225731f564e4b9e7f2ac1e13c9e6481f941b5631a0f8e2d9387ce", size = 9576888, upload-time = "2025-08-30T00:12:52.92Z" }, - { url = "https://files.pythonhosted.org/packages/fc/8e/0a18d6d7d2d0a2e66585032a760d13662e5250c784d53ad50434e9560991/matplotlib-3.10.6-cp311-cp311-win_amd64.whl", hash = "sha256:abb5d9478625dd9c9eb51a06d39aae71eda749ae9b3138afb23eb38824026c7e", size = 8115158, upload-time = "2025-08-30T00:12:54.863Z" }, - { url = "https://files.pythonhosted.org/packages/07/b3/1a5107bb66c261e23b9338070702597a2d374e5aa7004b7adfc754fbed02/matplotlib-3.10.6-cp311-cp311-win_arm64.whl", hash = "sha256:886f989ccfae63659183173bb3fced7fd65e9eb793c3cc21c273add368536951", size = 7992444, upload-time = "2025-08-30T00:12:57.067Z" }, - { url = "https://files.pythonhosted.org/packages/ea/1a/7042f7430055d567cc3257ac409fcf608599ab27459457f13772c2d9778b/matplotlib-3.10.6-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:31ca662df6a80bd426f871105fdd69db7543e28e73a9f2afe80de7e531eb2347", size = 8272404, upload-time = "2025-08-30T00:12:59.112Z" }, - { url = "https://files.pythonhosted.org/packages/a9/5d/1d5f33f5b43f4f9e69e6a5fe1fb9090936ae7bc8e2ff6158e7a76542633b/matplotlib-3.10.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1678bb61d897bb4ac4757b5ecfb02bfb3fddf7f808000fb81e09c510712fda75", size = 8128262, upload-time = "2025-08-30T00:13:01.141Z" }, - { url = "https://files.pythonhosted.org/packages/67/c3/135fdbbbf84e0979712df58e5e22b4f257b3f5e52a3c4aacf1b8abec0d09/matplotlib-3.10.6-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:56cd2d20842f58c03d2d6e6c1f1cf5548ad6f66b91e1e48f814e4fb5abd1cb95", size = 8697008, upload-time = "2025-08-30T00:13:03.24Z" }, - { url = "https://files.pythonhosted.org/packages/9c/be/c443ea428fb2488a3ea7608714b1bd85a82738c45da21b447dc49e2f8e5d/matplotlib-3.10.6-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:662df55604a2f9a45435566d6e2660e41efe83cd94f4288dfbf1e6d1eae4b0bb", size = 9530166, upload-time = "2025-08-30T00:13:05.951Z" }, - { url = "https://files.pythonhosted.org/packages/a9/35/48441422b044d74034aea2a3e0d1a49023f12150ebc58f16600132b9bbaf/matplotlib-3.10.6-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:08f141d55148cd1fc870c3387d70ca4df16dee10e909b3b038782bd4bda6ea07", size = 9593105, upload-time = "2025-08-30T00:13:08.356Z" }, - { url = "https://files.pythonhosted.org/packages/45/c3/994ef20eb4154ab84cc08d033834555319e4af970165e6c8894050af0b3c/matplotlib-3.10.6-cp312-cp312-win_amd64.whl", hash = "sha256:590f5925c2d650b5c9d813c5b3b5fc53f2929c3f8ef463e4ecfa7e052044fb2b", size = 8122784, upload-time = "2025-08-30T00:13:10.367Z" }, - { url = "https://files.pythonhosted.org/packages/57/b8/5c85d9ae0e40f04e71bedb053aada5d6bab1f9b5399a0937afb5d6b02d98/matplotlib-3.10.6-cp312-cp312-win_arm64.whl", hash = "sha256:f44c8d264a71609c79a78d50349e724f5d5fc3684ead7c2a473665ee63d868aa", size = 7992823, upload-time = "2025-08-30T00:13:12.24Z" }, - { url = "https://files.pythonhosted.org/packages/a0/db/18380e788bb837e724358287b08e223b32bc8dccb3b0c12fa8ca20bc7f3b/matplotlib-3.10.6-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:819e409653c1106c8deaf62e6de6b8611449c2cd9939acb0d7d4e57a3d95cc7a", size = 8273231, upload-time = "2025-08-30T00:13:13.881Z" }, - { url = "https://files.pythonhosted.org/packages/d3/0f/38dd49445b297e0d4f12a322c30779df0d43cb5873c7847df8a82e82ec67/matplotlib-3.10.6-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:59c8ac8382fefb9cb71308dde16a7c487432f5255d8f1fd32473523abecfecdf", size = 8128730, upload-time = "2025-08-30T00:13:15.556Z" }, - { url = "https://files.pythonhosted.org/packages/e5/b8/9eea6630198cb303d131d95d285a024b3b8645b1763a2916fddb44ca8760/matplotlib-3.10.6-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:84e82d9e0fd70c70bc55739defbd8055c54300750cbacf4740c9673a24d6933a", size = 8698539, upload-time = "2025-08-30T00:13:17.297Z" }, - { url = "https://files.pythonhosted.org/packages/71/34/44c7b1f075e1ea398f88aeabcc2907c01b9cc99e2afd560c1d49845a1227/matplotlib-3.10.6-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:25f7a3eb42d6c1c56e89eacd495661fc815ffc08d9da750bca766771c0fd9110", size = 9529702, upload-time = "2025-08-30T00:13:19.248Z" }, - { url = "https://files.pythonhosted.org/packages/b5/7f/e5c2dc9950c7facaf8b461858d1b92c09dd0cf174fe14e21953b3dda06f7/matplotlib-3.10.6-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:f9c862d91ec0b7842920a4cfdaaec29662195301914ea54c33e01f1a28d014b2", size = 9593742, upload-time = "2025-08-30T00:13:21.181Z" }, - { url = "https://files.pythonhosted.org/packages/ff/1d/70c28528794f6410ee2856cd729fa1f1756498b8d3126443b0a94e1a8695/matplotlib-3.10.6-cp313-cp313-win_amd64.whl", hash = "sha256:1b53bd6337eba483e2e7d29c5ab10eee644bc3a2491ec67cc55f7b44583ffb18", size = 8122753, upload-time = "2025-08-30T00:13:23.44Z" }, - { url = "https://files.pythonhosted.org/packages/e8/74/0e1670501fc7d02d981564caf7c4df42974464625935424ca9654040077c/matplotlib-3.10.6-cp313-cp313-win_arm64.whl", hash = "sha256:cbd5eb50b7058b2892ce45c2f4e92557f395c9991f5c886d1bb74a1582e70fd6", size = 7992973, upload-time = "2025-08-30T00:13:26.632Z" }, - { url = "https://files.pythonhosted.org/packages/b1/4e/60780e631d73b6b02bd7239f89c451a72970e5e7ec34f621eda55cd9a445/matplotlib-3.10.6-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:acc86dd6e0e695c095001a7fccff158c49e45e0758fdf5dcdbb0103318b59c9f", size = 8316869, upload-time = "2025-08-30T00:13:28.262Z" }, - { url = "https://files.pythonhosted.org/packages/f8/15/baa662374a579413210fc2115d40c503b7360a08e9cc254aa0d97d34b0c1/matplotlib-3.10.6-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:e228cd2ffb8f88b7d0b29e37f68ca9aaf83e33821f24a5ccc4f082dd8396bc27", size = 8178240, upload-time = "2025-08-30T00:13:30.007Z" }, - { url = "https://files.pythonhosted.org/packages/c6/3f/3c38e78d2aafdb8829fcd0857d25aaf9e7dd2dfcf7ec742765b585774931/matplotlib-3.10.6-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:658bc91894adeab669cf4bb4a186d049948262987e80f0857216387d7435d833", size = 8711719, upload-time = "2025-08-30T00:13:31.72Z" }, - { url = "https://files.pythonhosted.org/packages/96/4b/2ec2bbf8cefaa53207cc56118d1fa8a0f9b80642713ea9390235d331ede4/matplotlib-3.10.6-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8913b7474f6dd83ac444c9459c91f7f0f2859e839f41d642691b104e0af056aa", size = 9541422, upload-time = "2025-08-30T00:13:33.611Z" }, - { url = "https://files.pythonhosted.org/packages/83/7d/40255e89b3ef11c7871020563b2dd85f6cb1b4eff17c0f62b6eb14c8fa80/matplotlib-3.10.6-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:091cea22e059b89f6d7d1a18e2c33a7376c26eee60e401d92a4d6726c4e12706", size = 9594068, upload-time = "2025-08-30T00:13:35.833Z" }, - { url = "https://files.pythonhosted.org/packages/f0/a9/0213748d69dc842537a113493e1c27daf9f96bd7cc316f933dc8ec4de985/matplotlib-3.10.6-cp313-cp313t-win_amd64.whl", hash = "sha256:491e25e02a23d7207629d942c666924a6b61e007a48177fdd231a0097b7f507e", size = 8200100, upload-time = "2025-08-30T00:13:37.668Z" }, - { url = "https://files.pythonhosted.org/packages/be/15/79f9988066ce40b8a6f1759a934ea0cde8dc4adc2262255ee1bc98de6ad0/matplotlib-3.10.6-cp313-cp313t-win_arm64.whl", hash = "sha256:3d80d60d4e54cda462e2cd9a086d85cd9f20943ead92f575ce86885a43a565d5", size = 8042142, upload-time = "2025-08-30T00:13:39.426Z" }, - { url = "https://files.pythonhosted.org/packages/7c/58/e7b6d292beae6fb4283ca6fb7fa47d7c944a68062d6238c07b497dd35493/matplotlib-3.10.6-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:70aaf890ce1d0efd482df969b28a5b30ea0b891224bb315810a3940f67182899", size = 8273802, upload-time = "2025-08-30T00:13:41.006Z" }, - { url = "https://files.pythonhosted.org/packages/9f/f6/7882d05aba16a8cdd594fb9a03a9d3cca751dbb6816adf7b102945522ee9/matplotlib-3.10.6-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:1565aae810ab79cb72e402b22facfa6501365e73ebab70a0fdfb98488d2c3c0c", size = 8131365, upload-time = "2025-08-30T00:13:42.664Z" }, - { url = "https://files.pythonhosted.org/packages/94/bf/ff32f6ed76e78514e98775a53715eca4804b12bdcf35902cdd1cf759d324/matplotlib-3.10.6-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f3b23315a01981689aa4e1a179dbf6ef9fbd17143c3eea77548c2ecfb0499438", size = 9533961, upload-time = "2025-08-30T00:13:44.372Z" }, - { url = "https://files.pythonhosted.org/packages/fe/c3/6bf88c2fc2da7708a2ff8d2eeb5d68943130f50e636d5d3dcf9d4252e971/matplotlib-3.10.6-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:30fdd37edf41a4e6785f9b37969de57aea770696cb637d9946eb37470c94a453", size = 9804262, upload-time = "2025-08-30T00:13:46.614Z" }, - { url = "https://files.pythonhosted.org/packages/0f/7a/e05e6d9446d2d577b459427ad060cd2de5742d0e435db3191fea4fcc7e8b/matplotlib-3.10.6-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:bc31e693da1c08012c764b053e702c1855378e04102238e6a5ee6a7117c53a47", size = 9595508, upload-time = "2025-08-30T00:13:48.731Z" }, - { url = "https://files.pythonhosted.org/packages/39/fb/af09c463ced80b801629fd73b96f726c9f6124c3603aa2e480a061d6705b/matplotlib-3.10.6-cp314-cp314-win_amd64.whl", hash = "sha256:05be9bdaa8b242bc6ff96330d18c52f1fc59c6fb3a4dd411d953d67e7e1baf98", size = 8252742, upload-time = "2025-08-30T00:13:50.539Z" }, - { url = "https://files.pythonhosted.org/packages/b1/f9/b682f6db9396d9ab8f050c0a3bfbb5f14fb0f6518f08507c04cc02f8f229/matplotlib-3.10.6-cp314-cp314-win_arm64.whl", hash = "sha256:f56a0d1ab05d34c628592435781d185cd99630bdfd76822cd686fb5a0aecd43a", size = 8124237, upload-time = "2025-08-30T00:13:54.3Z" }, - { url = "https://files.pythonhosted.org/packages/b5/d2/b69b4a0923a3c05ab90527c60fdec899ee21ca23ede7f0fb818e6620d6f2/matplotlib-3.10.6-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:94f0b4cacb23763b64b5dace50d5b7bfe98710fed5f0cef5c08135a03399d98b", size = 8316956, upload-time = "2025-08-30T00:13:55.932Z" }, - { url = "https://files.pythonhosted.org/packages/28/e9/dc427b6f16457ffaeecb2fc4abf91e5adb8827861b869c7a7a6d1836fa73/matplotlib-3.10.6-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:cc332891306b9fb39462673d8225d1b824c89783fee82840a709f96714f17a5c", size = 8178260, upload-time = "2025-08-30T00:14:00.942Z" }, - { url = "https://files.pythonhosted.org/packages/c4/89/1fbd5ad611802c34d1c7ad04607e64a1350b7fb9c567c4ec2c19e066ed35/matplotlib-3.10.6-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ee1d607b3fb1590deb04b69f02ea1d53ed0b0bf75b2b1a5745f269afcbd3cdd3", size = 9541422, upload-time = "2025-08-30T00:14:02.664Z" }, - { url = "https://files.pythonhosted.org/packages/b0/3b/65fec8716025b22c1d72d5a82ea079934c76a547696eaa55be6866bc89b1/matplotlib-3.10.6-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:376a624a218116461696b27b2bbf7a8945053e6d799f6502fc03226d077807bf", size = 9803678, upload-time = "2025-08-30T00:14:04.741Z" }, - { url = "https://files.pythonhosted.org/packages/c7/b0/40fb2b3a1ab9381bb39a952e8390357c8be3bdadcf6d5055d9c31e1b35ae/matplotlib-3.10.6-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:83847b47f6524c34b4f2d3ce726bb0541c48c8e7692729865c3df75bfa0f495a", size = 9594077, upload-time = "2025-08-30T00:14:07.012Z" }, - { url = "https://files.pythonhosted.org/packages/76/34/c4b71b69edf5b06e635eee1ed10bfc73cf8df058b66e63e30e6a55e231d5/matplotlib-3.10.6-cp314-cp314t-win_amd64.whl", hash = "sha256:c7e0518e0d223683532a07f4b512e2e0729b62674f1b3a1a69869f98e6b1c7e3", size = 8342822, upload-time = "2025-08-30T00:14:09.041Z" }, - { url = "https://files.pythonhosted.org/packages/e8/62/aeabeef1a842b6226a30d49dd13e8a7a1e81e9ec98212c0b5169f0a12d83/matplotlib-3.10.6-cp314-cp314t-win_arm64.whl", hash = "sha256:4dd83e029f5b4801eeb87c64efd80e732452781c16a9cf7415b7b63ec8f374d7", size = 8172588, upload-time = "2025-08-30T00:14:11.166Z" }, - { url = "https://files.pythonhosted.org/packages/12/bb/02c35a51484aae5f49bd29f091286e7af5f3f677a9736c58a92b3c78baeb/matplotlib-3.10.6-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:f2d684c3204fa62421bbf770ddfebc6b50130f9cad65531eeba19236d73bb488", size = 8252296, upload-time = "2025-08-30T00:14:19.49Z" }, - { url = "https://files.pythonhosted.org/packages/7d/85/41701e3092005aee9a2445f5ee3904d9dbd4a7df7a45905ffef29b7ef098/matplotlib-3.10.6-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:6f4a69196e663a41d12a728fab8751177215357906436804217d6d9cf0d4d6cf", size = 8116749, upload-time = "2025-08-30T00:14:21.344Z" }, - { url = "https://files.pythonhosted.org/packages/16/53/8d8fa0ea32a8c8239e04d022f6c059ee5e1b77517769feccd50f1df43d6d/matplotlib-3.10.6-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:4d6ca6ef03dfd269f4ead566ec6f3fb9becf8dab146fb999022ed85ee9f6b3eb", size = 8693933, upload-time = "2025-08-30T00:14:22.942Z" }, +sdist = { url = "https://files.pythonhosted.org/packages/ae/e2/d2d5295be2f44c678ebaf3544ba32d20c1f9ef08c49fe47f496180e1db15/matplotlib-3.10.7.tar.gz", hash = "sha256:a06ba7e2a2ef9131c79c49e63dad355d2d878413a0376c1727c8b9335ff731c7", size = 34804865, upload-time = "2025-10-09T00:28:00.669Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fc/bc/0fb489005669127ec13f51be0c6adc074d7cf191075dab1da9fe3b7a3cfc/matplotlib-3.10.7-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:53b492410a6cd66c7a471de6c924f6ede976e963c0f3097a3b7abfadddc67d0a", size = 8257507, upload-time = "2025-10-09T00:26:19.073Z" }, + { url = "https://files.pythonhosted.org/packages/e2/6a/d42588ad895279ff6708924645b5d2ed54a7fb2dc045c8a804e955aeace1/matplotlib-3.10.7-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d9749313deb729f08207718d29c86246beb2ea3fdba753595b55901dee5d2fd6", size = 8119565, upload-time = "2025-10-09T00:26:21.023Z" }, + { url = "https://files.pythonhosted.org/packages/10/b7/4aa196155b4d846bd749cf82aa5a4c300cf55a8b5e0dfa5b722a63c0f8a0/matplotlib-3.10.7-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:2222c7ba2cbde7fe63032769f6eb7e83ab3227f47d997a8453377709b7fe3a5a", size = 8692668, upload-time = "2025-10-09T00:26:22.967Z" }, + { url = "https://files.pythonhosted.org/packages/e6/e7/664d2b97016f46683a02d854d730cfcf54ff92c1dafa424beebef50f831d/matplotlib-3.10.7-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e91f61a064c92c307c5a9dc8c05dc9f8a68f0a3be199d9a002a0622e13f874a1", size = 9521051, upload-time = "2025-10-09T00:26:25.041Z" }, + { url = "https://files.pythonhosted.org/packages/a8/a3/37aef1404efa615f49b5758a5e0261c16dd88f389bc1861e722620e4a754/matplotlib-3.10.7-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:6f1851eab59ca082c95df5a500106bad73672645625e04538b3ad0f69471ffcc", size = 9576878, upload-time = "2025-10-09T00:26:27.478Z" }, + { url = "https://files.pythonhosted.org/packages/33/cd/b145f9797126f3f809d177ca378de57c45413c5099c5990de2658760594a/matplotlib-3.10.7-cp311-cp311-win_amd64.whl", hash = "sha256:6516ce375109c60ceec579e699524e9d504cd7578506f01150f7a6bc174a775e", size = 8115142, upload-time = "2025-10-09T00:26:29.774Z" }, + { url = "https://files.pythonhosted.org/packages/2e/39/63bca9d2b78455ed497fcf51a9c71df200a11048f48249038f06447fa947/matplotlib-3.10.7-cp311-cp311-win_arm64.whl", hash = "sha256:b172db79759f5f9bc13ef1c3ef8b9ee7b37b0247f987fbbbdaa15e4f87fd46a9", size = 7992439, upload-time = "2025-10-09T00:26:40.32Z" }, + { url = "https://files.pythonhosted.org/packages/be/b3/09eb0f7796932826ec20c25b517d568627754f6c6462fca19e12c02f2e12/matplotlib-3.10.7-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7a0edb7209e21840e8361e91ea84ea676658aa93edd5f8762793dec77a4a6748", size = 8272389, upload-time = "2025-10-09T00:26:42.474Z" }, + { url = "https://files.pythonhosted.org/packages/11/0b/1ae80ddafb8652fd8046cb5c8460ecc8d4afccb89e2c6d6bec61e04e1eaf/matplotlib-3.10.7-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c380371d3c23e0eadf8ebff114445b9f970aff2010198d498d4ab4c3b41eea4f", size = 8128247, upload-time = "2025-10-09T00:26:44.77Z" }, + { url = "https://files.pythonhosted.org/packages/7d/18/95ae2e242d4a5c98bd6e90e36e128d71cf1c7e39b0874feaed3ef782e789/matplotlib-3.10.7-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d5f256d49fea31f40f166a5e3131235a5d2f4b7f44520b1cf0baf1ce568ccff0", size = 8696996, upload-time = "2025-10-09T00:26:46.792Z" }, + { url = "https://files.pythonhosted.org/packages/7e/3d/5b559efc800bd05cb2033aa85f7e13af51958136a48327f7c261801ff90a/matplotlib-3.10.7-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:11ae579ac83cdf3fb72573bb89f70e0534de05266728740d478f0f818983c695", size = 9530153, upload-time = "2025-10-09T00:26:49.07Z" }, + { url = "https://files.pythonhosted.org/packages/88/57/eab4a719fd110312d3c220595d63a3c85ec2a39723f0f4e7fa7e6e3f74ba/matplotlib-3.10.7-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:4c14b6acd16cddc3569a2d515cfdd81c7a68ac5639b76548cfc1a9e48b20eb65", size = 9593093, upload-time = "2025-10-09T00:26:51.067Z" }, + { url = "https://files.pythonhosted.org/packages/31/3c/80816f027b3a4a28cd2a0a6ef7f89a2db22310e945cd886ec25bfb399221/matplotlib-3.10.7-cp312-cp312-win_amd64.whl", hash = "sha256:0d8c32b7ea6fb80b1aeff5a2ceb3fb9778e2759e899d9beff75584714afcc5ee", size = 8122771, upload-time = "2025-10-09T00:26:53.296Z" }, + { url = "https://files.pythonhosted.org/packages/de/77/ef1fc78bfe99999b2675435cc52120887191c566b25017d78beaabef7f2d/matplotlib-3.10.7-cp312-cp312-win_arm64.whl", hash = "sha256:5f3f6d315dcc176ba7ca6e74c7768fb7e4cf566c49cb143f6bc257b62e634ed8", size = 7992812, upload-time = "2025-10-09T00:26:54.882Z" }, + { url = "https://files.pythonhosted.org/packages/02/9c/207547916a02c78f6bdd83448d9b21afbc42f6379ed887ecf610984f3b4e/matplotlib-3.10.7-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:1d9d3713a237970569156cfb4de7533b7c4eacdd61789726f444f96a0d28f57f", size = 8273212, upload-time = "2025-10-09T00:26:56.752Z" }, + { url = "https://files.pythonhosted.org/packages/bc/d0/b3d3338d467d3fc937f0bb7f256711395cae6f78e22cef0656159950adf0/matplotlib-3.10.7-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:37a1fea41153dd6ee061d21ab69c9cf2cf543160b1b85d89cd3d2e2a7902ca4c", size = 8128713, upload-time = "2025-10-09T00:26:59.001Z" }, + { url = "https://files.pythonhosted.org/packages/22/ff/6425bf5c20d79aa5b959d1ce9e65f599632345391381c9a104133fe0b171/matplotlib-3.10.7-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:b3c4ea4948d93c9c29dc01c0c23eef66f2101bf75158c291b88de6525c55c3d1", size = 8698527, upload-time = "2025-10-09T00:27:00.69Z" }, + { url = "https://files.pythonhosted.org/packages/d0/7f/ccdca06f4c2e6c7989270ed7829b8679466682f4cfc0f8c9986241c023b6/matplotlib-3.10.7-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:22df30ffaa89f6643206cf13877191c63a50e8f800b038bc39bee9d2d4957632", size = 9529690, upload-time = "2025-10-09T00:27:02.664Z" }, + { url = "https://files.pythonhosted.org/packages/b8/95/b80fc2c1f269f21ff3d193ca697358e24408c33ce2b106a7438a45407b63/matplotlib-3.10.7-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b69676845a0a66f9da30e87f48be36734d6748024b525ec4710be40194282c84", size = 9593732, upload-time = "2025-10-09T00:27:04.653Z" }, + { url = "https://files.pythonhosted.org/packages/e1/b6/23064a96308b9aeceeffa65e96bcde459a2ea4934d311dee20afde7407a0/matplotlib-3.10.7-cp313-cp313-win_amd64.whl", hash = "sha256:744991e0cc863dd669c8dc9136ca4e6e0082be2070b9d793cbd64bec872a6815", size = 8122727, upload-time = "2025-10-09T00:27:06.814Z" }, + { url = "https://files.pythonhosted.org/packages/b3/a6/2faaf48133b82cf3607759027f82b5c702aa99cdfcefb7f93d6ccf26a424/matplotlib-3.10.7-cp313-cp313-win_arm64.whl", hash = "sha256:fba2974df0bf8ce3c995fa84b79cde38326e0f7b5409e7a3a481c1141340bcf7", size = 7992958, upload-time = "2025-10-09T00:27:08.567Z" }, + { url = "https://files.pythonhosted.org/packages/4a/f0/b018fed0b599bd48d84c08794cb242227fe3341952da102ee9d9682db574/matplotlib-3.10.7-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:932c55d1fa7af4423422cb6a492a31cbcbdbe68fd1a9a3f545aa5e7a143b5355", size = 8316849, upload-time = "2025-10-09T00:27:10.254Z" }, + { url = "https://files.pythonhosted.org/packages/b0/b7/bb4f23856197659f275e11a2a164e36e65e9b48ea3e93c4ec25b4f163198/matplotlib-3.10.7-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:5e38c2d581d62ee729a6e144c47a71b3f42fb4187508dbbf4fe71d5612c3433b", size = 8178225, upload-time = "2025-10-09T00:27:12.241Z" }, + { url = "https://files.pythonhosted.org/packages/62/56/0600609893ff277e6f3ab3c0cef4eafa6e61006c058e84286c467223d4d5/matplotlib-3.10.7-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:786656bb13c237bbcebcd402f65f44dd61ead60ee3deb045af429d889c8dbc67", size = 8711708, upload-time = "2025-10-09T00:27:13.879Z" }, + { url = "https://files.pythonhosted.org/packages/d8/1a/6bfecb0cafe94d6658f2f1af22c43b76cf7a1c2f0dc34ef84cbb6809617e/matplotlib-3.10.7-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:09d7945a70ea43bf9248f4b6582734c2fe726723204a76eca233f24cffc7ef67", size = 9541409, upload-time = "2025-10-09T00:27:15.684Z" }, + { url = "https://files.pythonhosted.org/packages/08/50/95122a407d7f2e446fd865e2388a232a23f2b81934960ea802f3171518e4/matplotlib-3.10.7-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:d0b181e9fa8daf1d9f2d4c547527b167cb8838fc587deabca7b5c01f97199e84", size = 9594054, upload-time = "2025-10-09T00:27:17.547Z" }, + { url = "https://files.pythonhosted.org/packages/13/76/75b194a43b81583478a81e78a07da8d9ca6ddf50dd0a2ccabf258059481d/matplotlib-3.10.7-cp313-cp313t-win_amd64.whl", hash = "sha256:31963603041634ce1a96053047b40961f7a29eb8f9a62e80cc2c0427aa1d22a2", size = 8200100, upload-time = "2025-10-09T00:27:20.039Z" }, + { url = "https://files.pythonhosted.org/packages/f5/9e/6aefebdc9f8235c12bdeeda44cc0383d89c1e41da2c400caf3ee2073a3ce/matplotlib-3.10.7-cp313-cp313t-win_arm64.whl", hash = "sha256:aebed7b50aa6ac698c90f60f854b47e48cd2252b30510e7a1feddaf5a3f72cbf", size = 8042131, upload-time = "2025-10-09T00:27:21.608Z" }, + { url = "https://files.pythonhosted.org/packages/0d/4b/e5bc2c321b6a7e3a75638d937d19ea267c34bd5a90e12bee76c4d7c7a0d9/matplotlib-3.10.7-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:d883460c43e8c6b173fef244a2341f7f7c0e9725c7fe68306e8e44ed9c8fb100", size = 8273787, upload-time = "2025-10-09T00:27:23.27Z" }, + { url = "https://files.pythonhosted.org/packages/86/ad/6efae459c56c2fbc404da154e13e3a6039129f3c942b0152624f1c621f05/matplotlib-3.10.7-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:07124afcf7a6504eafcb8ce94091c5898bbdd351519a1beb5c45f7a38c67e77f", size = 8131348, upload-time = "2025-10-09T00:27:24.926Z" }, + { url = "https://files.pythonhosted.org/packages/a6/5a/a4284d2958dee4116359cc05d7e19c057e64ece1b4ac986ab0f2f4d52d5a/matplotlib-3.10.7-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c17398b709a6cce3d9fdb1595c33e356d91c098cd9486cb2cc21ea2ea418e715", size = 9533949, upload-time = "2025-10-09T00:27:26.704Z" }, + { url = "https://files.pythonhosted.org/packages/de/ff/f3781b5057fa3786623ad8976fc9f7b0d02b2f28534751fd5a44240de4cf/matplotlib-3.10.7-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7146d64f561498764561e9cd0ed64fcf582e570fc519e6f521e2d0cfd43365e1", size = 9804247, upload-time = "2025-10-09T00:27:28.514Z" }, + { url = "https://files.pythonhosted.org/packages/47/5a/993a59facb8444efb0e197bf55f545ee449902dcee86a4dfc580c3b61314/matplotlib-3.10.7-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:90ad854c0a435da3104c01e2c6f0028d7e719b690998a2333d7218db80950722", size = 9595497, upload-time = "2025-10-09T00:27:30.418Z" }, + { url = "https://files.pythonhosted.org/packages/0d/a5/77c95aaa9bb32c345cbb49626ad8eb15550cba2e6d4c88081a6c2ac7b08d/matplotlib-3.10.7-cp314-cp314-win_amd64.whl", hash = "sha256:4645fc5d9d20ffa3a39361fcdbcec731382763b623b72627806bf251b6388866", size = 8252732, upload-time = "2025-10-09T00:27:32.332Z" }, + { url = "https://files.pythonhosted.org/packages/74/04/45d269b4268d222390d7817dae77b159651909669a34ee9fdee336db5883/matplotlib-3.10.7-cp314-cp314-win_arm64.whl", hash = "sha256:9257be2f2a03415f9105c486d304a321168e61ad450f6153d77c69504ad764bb", size = 8124240, upload-time = "2025-10-09T00:27:33.94Z" }, + { url = "https://files.pythonhosted.org/packages/4b/c7/ca01c607bb827158b439208c153d6f14ddb9fb640768f06f7ca3488ae67b/matplotlib-3.10.7-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:1e4bbad66c177a8fdfa53972e5ef8be72a5f27e6a607cec0d8579abd0f3102b1", size = 8316938, upload-time = "2025-10-09T00:27:35.534Z" }, + { url = "https://files.pythonhosted.org/packages/84/d2/5539e66e9f56d2fdec94bb8436f5e449683b4e199bcc897c44fbe3c99e28/matplotlib-3.10.7-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:d8eb7194b084b12feb19142262165832fc6ee879b945491d1c3d4660748020c4", size = 8178245, upload-time = "2025-10-09T00:27:37.334Z" }, + { url = "https://files.pythonhosted.org/packages/77/b5/e6ca22901fd3e4fe433a82e583436dd872f6c966fca7e63cf806b40356f8/matplotlib-3.10.7-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b4d41379b05528091f00e1728004f9a8d7191260f3862178b88e8fd770206318", size = 9541411, upload-time = "2025-10-09T00:27:39.387Z" }, + { url = "https://files.pythonhosted.org/packages/9e/99/a4524db57cad8fee54b7237239a8f8360bfcfa3170d37c9e71c090c0f409/matplotlib-3.10.7-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4a74f79fafb2e177f240579bc83f0b60f82cc47d2f1d260f422a0627207008ca", size = 9803664, upload-time = "2025-10-09T00:27:41.492Z" }, + { url = "https://files.pythonhosted.org/packages/e6/a5/85e2edf76ea0ad4288d174926d9454ea85f3ce5390cc4e6fab196cbf250b/matplotlib-3.10.7-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:702590829c30aada1e8cef0568ddbffa77ca747b4d6e36c6d173f66e301f89cc", size = 9594066, upload-time = "2025-10-09T00:27:43.694Z" }, + { url = "https://files.pythonhosted.org/packages/39/69/9684368a314f6d83fe5c5ad2a4121a3a8e03723d2e5c8ea17b66c1bad0e7/matplotlib-3.10.7-cp314-cp314t-win_amd64.whl", hash = "sha256:f79d5de970fc90cd5591f60053aecfce1fcd736e0303d9f0bf86be649fa68fb8", size = 8342832, upload-time = "2025-10-09T00:27:45.543Z" }, + { url = "https://files.pythonhosted.org/packages/04/5f/e22e08da14bc1a0894184640d47819d2338b792732e20d292bf86e5ab785/matplotlib-3.10.7-cp314-cp314t-win_arm64.whl", hash = "sha256:cb783436e47fcf82064baca52ce748af71725d0352e1d31564cbe9c95df92b9c", size = 8172585, upload-time = "2025-10-09T00:27:47.185Z" }, + { url = "https://files.pythonhosted.org/packages/58/8f/76d5dc21ac64a49e5498d7f0472c0781dae442dd266a67458baec38288ec/matplotlib-3.10.7-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:15112bcbaef211bd663fa935ec33313b948e214454d949b723998a43357b17b0", size = 8252283, upload-time = "2025-10-09T00:27:54.739Z" }, + { url = "https://files.pythonhosted.org/packages/27/0d/9c5d4c2317feb31d819e38c9f947c942f42ebd4eb935fc6fd3518a11eaa7/matplotlib-3.10.7-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:d2a959c640cdeecdd2ec3136e8ea0441da59bcaf58d67e9c590740addba2cb68", size = 8116733, upload-time = "2025-10-09T00:27:56.406Z" }, + { url = "https://files.pythonhosted.org/packages/9a/cc/3fe688ff1355010937713164caacf9ed443675ac48a997bab6ed23b3f7c0/matplotlib-3.10.7-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:3886e47f64611046bc1db523a09dd0a0a6bed6081e6f90e13806dd1d1d1b5e91", size = 8693919, upload-time = "2025-10-09T00:27:58.41Z" }, ] [[package]] @@ -1753,11 +1753,11 @@ wheels = [ [[package]] name = "platformdirs" -version = "4.4.0" +version = "4.5.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/23/e8/21db9c9987b0e728855bd57bff6984f67952bea55d6f75e055c46b5383e8/platformdirs-4.4.0.tar.gz", hash = "sha256:ca753cf4d81dc309bc67b0ea38fd15dc97bc30ce419a7f58d13eb3bf14c4febf", size = 21634, upload-time = "2025-08-26T14:32:04.268Z" } +sdist = { url = "https://files.pythonhosted.org/packages/61/33/9611380c2bdb1225fdef633e2a9610622310fed35ab11dac9620972ee088/platformdirs-4.5.0.tar.gz", hash = "sha256:70ddccdd7c99fc5942e9fc25636a8b34d04c24b335100223152c2803e4063312", size = 21632, upload-time = "2025-10-08T17:44:48.791Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/40/4b/2028861e724d3bd36227adfa20d3fd24c3fc6d52032f4a93c133be5d17ce/platformdirs-4.4.0-py3-none-any.whl", hash = "sha256:abd01743f24e5287cd7a5db3752faf1a2d65353f38ec26d98e25a6db65958c85", size = 18654, upload-time = "2025-08-26T14:32:02.735Z" }, + { url = "https://files.pythonhosted.org/packages/73/cb/ac7874b3e5d58441674fb70742e6c374b28b0c7cb988d37d991cde47166c/platformdirs-4.5.0-py3-none-any.whl", hash = "sha256:e578a81bb873cbb89a41fcc904c7ef523cc18284b7e3b3ccf06aca1403b7ebd3", size = 18651, upload-time = "2025-10-08T17:44:47.223Z" }, ] [[package]] @@ -2675,41 +2675,51 @@ wheels = [ [[package]] name = "tomli" -version = "2.2.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/18/87/302344fed471e44a87289cf4967697d07e532f2421fdaf868a303cbae4ff/tomli-2.2.1.tar.gz", hash = "sha256:cd45e1dc79c835ce60f7404ec8119f2eb06d38b1deba146f07ced3bbc44505ff", size = 17175, upload-time = "2024-11-27T22:38:36.873Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/43/ca/75707e6efa2b37c77dadb324ae7d9571cb424e61ea73fad7c56c2d14527f/tomli-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249", size = 131077, upload-time = "2024-11-27T22:37:54.956Z" }, - { url = "https://files.pythonhosted.org/packages/c7/16/51ae563a8615d472fdbffc43a3f3d46588c264ac4f024f63f01283becfbb/tomli-2.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6", size = 123429, upload-time = "2024-11-27T22:37:56.698Z" }, - { url = "https://files.pythonhosted.org/packages/f1/dd/4f6cd1e7b160041db83c694abc78e100473c15d54620083dbd5aae7b990e/tomli-2.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ece47d672db52ac607a3d9599a9d48dcb2f2f735c6c2d1f34130085bb12b112a", size = 226067, upload-time = "2024-11-27T22:37:57.63Z" }, - { url = "https://files.pythonhosted.org/packages/a9/6b/c54ede5dc70d648cc6361eaf429304b02f2871a345bbdd51e993d6cdf550/tomli-2.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6972ca9c9cc9f0acaa56a8ca1ff51e7af152a9f87fb64623e31d5c83700080ee", size = 236030, upload-time = "2024-11-27T22:37:59.344Z" }, - { url = "https://files.pythonhosted.org/packages/1f/47/999514fa49cfaf7a92c805a86c3c43f4215621855d151b61c602abb38091/tomli-2.2.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c954d2250168d28797dd4e3ac5cf812a406cd5a92674ee4c8f123c889786aa8e", size = 240898, upload-time = "2024-11-27T22:38:00.429Z" }, - { url = "https://files.pythonhosted.org/packages/73/41/0a01279a7ae09ee1573b423318e7934674ce06eb33f50936655071d81a24/tomli-2.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8dd28b3e155b80f4d54beb40a441d366adcfe740969820caf156c019fb5c7ec4", size = 229894, upload-time = "2024-11-27T22:38:02.094Z" }, - { url = "https://files.pythonhosted.org/packages/55/18/5d8bc5b0a0362311ce4d18830a5d28943667599a60d20118074ea1b01bb7/tomli-2.2.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e59e304978767a54663af13c07b3d1af22ddee3bb2fb0618ca1593e4f593a106", size = 245319, upload-time = "2024-11-27T22:38:03.206Z" }, - { url = "https://files.pythonhosted.org/packages/92/a3/7ade0576d17f3cdf5ff44d61390d4b3febb8a9fc2b480c75c47ea048c646/tomli-2.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:33580bccab0338d00994d7f16f4c4ec25b776af3ffaac1ed74e0b3fc95e885a8", size = 238273, upload-time = "2024-11-27T22:38:04.217Z" }, - { url = "https://files.pythonhosted.org/packages/72/6f/fa64ef058ac1446a1e51110c375339b3ec6be245af9d14c87c4a6412dd32/tomli-2.2.1-cp311-cp311-win32.whl", hash = "sha256:465af0e0875402f1d226519c9904f37254b3045fc5084697cefb9bdde1ff99ff", size = 98310, upload-time = "2024-11-27T22:38:05.908Z" }, - { url = "https://files.pythonhosted.org/packages/6a/1c/4a2dcde4a51b81be3530565e92eda625d94dafb46dbeb15069df4caffc34/tomli-2.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:2d0f2fdd22b02c6d81637a3c95f8cd77f995846af7414c5c4b8d0545afa1bc4b", size = 108309, upload-time = "2024-11-27T22:38:06.812Z" }, - { url = "https://files.pythonhosted.org/packages/52/e1/f8af4c2fcde17500422858155aeb0d7e93477a0d59a98e56cbfe75070fd0/tomli-2.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4a8f6e44de52d5e6c657c9fe83b562f5f4256d8ebbfe4ff922c495620a7f6cea", size = 132762, upload-time = "2024-11-27T22:38:07.731Z" }, - { url = "https://files.pythonhosted.org/packages/03/b8/152c68bb84fc00396b83e7bbddd5ec0bd3dd409db4195e2a9b3e398ad2e3/tomli-2.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8d57ca8095a641b8237d5b079147646153d22552f1c637fd3ba7f4b0b29167a8", size = 123453, upload-time = "2024-11-27T22:38:09.384Z" }, - { url = "https://files.pythonhosted.org/packages/c8/d6/fc9267af9166f79ac528ff7e8c55c8181ded34eb4b0e93daa767b8841573/tomli-2.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e340144ad7ae1533cb897d406382b4b6fede8890a03738ff1683af800d54192", size = 233486, upload-time = "2024-11-27T22:38:10.329Z" }, - { url = "https://files.pythonhosted.org/packages/5c/51/51c3f2884d7bab89af25f678447ea7d297b53b5a3b5730a7cb2ef6069f07/tomli-2.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db2b95f9de79181805df90bedc5a5ab4c165e6ec3fe99f970d0e302f384ad222", size = 242349, upload-time = "2024-11-27T22:38:11.443Z" }, - { url = "https://files.pythonhosted.org/packages/ab/df/bfa89627d13a5cc22402e441e8a931ef2108403db390ff3345c05253935e/tomli-2.2.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40741994320b232529c802f8bc86da4e1aa9f413db394617b9a256ae0f9a7f77", size = 252159, upload-time = "2024-11-27T22:38:13.099Z" }, - { url = "https://files.pythonhosted.org/packages/9e/6e/fa2b916dced65763a5168c6ccb91066f7639bdc88b48adda990db10c8c0b/tomli-2.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:400e720fe168c0f8521520190686ef8ef033fb19fc493da09779e592861b78c6", size = 237243, upload-time = "2024-11-27T22:38:14.766Z" }, - { url = "https://files.pythonhosted.org/packages/b4/04/885d3b1f650e1153cbb93a6a9782c58a972b94ea4483ae4ac5cedd5e4a09/tomli-2.2.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:02abe224de6ae62c19f090f68da4e27b10af2b93213d36cf44e6e1c5abd19fdd", size = 259645, upload-time = "2024-11-27T22:38:15.843Z" }, - { url = "https://files.pythonhosted.org/packages/9c/de/6b432d66e986e501586da298e28ebeefd3edc2c780f3ad73d22566034239/tomli-2.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b82ebccc8c8a36f2094e969560a1b836758481f3dc360ce9a3277c65f374285e", size = 244584, upload-time = "2024-11-27T22:38:17.645Z" }, - { url = "https://files.pythonhosted.org/packages/1c/9a/47c0449b98e6e7d1be6cbac02f93dd79003234ddc4aaab6ba07a9a7482e2/tomli-2.2.1-cp312-cp312-win32.whl", hash = "sha256:889f80ef92701b9dbb224e49ec87c645ce5df3fa2cc548664eb8a25e03127a98", size = 98875, upload-time = "2024-11-27T22:38:19.159Z" }, - { url = "https://files.pythonhosted.org/packages/ef/60/9b9638f081c6f1261e2688bd487625cd1e660d0a85bd469e91d8db969734/tomli-2.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:7fc04e92e1d624a4a63c76474610238576942d6b8950a2d7f908a340494e67e4", size = 109418, upload-time = "2024-11-27T22:38:20.064Z" }, - { url = "https://files.pythonhosted.org/packages/04/90/2ee5f2e0362cb8a0b6499dc44f4d7d48f8fff06d28ba46e6f1eaa61a1388/tomli-2.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f4039b9cbc3048b2416cc57ab3bda989a6fcf9b36cf8937f01a6e731b64f80d7", size = 132708, upload-time = "2024-11-27T22:38:21.659Z" }, - { url = "https://files.pythonhosted.org/packages/c0/ec/46b4108816de6b385141f082ba99e315501ccd0a2ea23db4a100dd3990ea/tomli-2.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:286f0ca2ffeeb5b9bd4fcc8d6c330534323ec51b2f52da063b11c502da16f30c", size = 123582, upload-time = "2024-11-27T22:38:22.693Z" }, - { url = "https://files.pythonhosted.org/packages/a0/bd/b470466d0137b37b68d24556c38a0cc819e8febe392d5b199dcd7f578365/tomli-2.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a92ef1a44547e894e2a17d24e7557a5e85a9e1d0048b0b5e7541f76c5032cb13", size = 232543, upload-time = "2024-11-27T22:38:24.367Z" }, - { url = "https://files.pythonhosted.org/packages/d9/e5/82e80ff3b751373f7cead2815bcbe2d51c895b3c990686741a8e56ec42ab/tomli-2.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9316dc65bed1684c9a98ee68759ceaed29d229e985297003e494aa825ebb0281", size = 241691, upload-time = "2024-11-27T22:38:26.081Z" }, - { url = "https://files.pythonhosted.org/packages/05/7e/2a110bc2713557d6a1bfb06af23dd01e7dde52b6ee7dadc589868f9abfac/tomli-2.2.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e85e99945e688e32d5a35c1ff38ed0b3f41f43fad8df0bdf79f72b2ba7bc5272", size = 251170, upload-time = "2024-11-27T22:38:27.921Z" }, - { url = "https://files.pythonhosted.org/packages/64/7b/22d713946efe00e0adbcdfd6d1aa119ae03fd0b60ebed51ebb3fa9f5a2e5/tomli-2.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ac065718db92ca818f8d6141b5f66369833d4a80a9d74435a268c52bdfa73140", size = 236530, upload-time = "2024-11-27T22:38:29.591Z" }, - { url = "https://files.pythonhosted.org/packages/38/31/3a76f67da4b0cf37b742ca76beaf819dca0ebef26d78fc794a576e08accf/tomli-2.2.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:d920f33822747519673ee656a4b6ac33e382eca9d331c87770faa3eef562aeb2", size = 258666, upload-time = "2024-11-27T22:38:30.639Z" }, - { url = "https://files.pythonhosted.org/packages/07/10/5af1293da642aded87e8a988753945d0cf7e00a9452d3911dd3bb354c9e2/tomli-2.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a198f10c4d1b1375d7687bc25294306e551bf1abfa4eace6650070a5c1ae2744", size = 243954, upload-time = "2024-11-27T22:38:31.702Z" }, - { url = "https://files.pythonhosted.org/packages/5b/b9/1ed31d167be802da0fc95020d04cd27b7d7065cc6fbefdd2f9186f60d7bd/tomli-2.2.1-cp313-cp313-win32.whl", hash = "sha256:d3f5614314d758649ab2ab3a62d4f2004c825922f9e370b29416484086b264ec", size = 98724, upload-time = "2024-11-27T22:38:32.837Z" }, - { url = "https://files.pythonhosted.org/packages/c7/32/b0963458706accd9afcfeb867c0f9175a741bf7b19cd424230714d722198/tomli-2.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:a38aa0308e754b0e3c67e344754dff64999ff9b513e691d0e786265c93583c69", size = 109383, upload-time = "2024-11-27T22:38:34.455Z" }, - { url = "https://files.pythonhosted.org/packages/6e/c2/61d3e0f47e2b74ef40a68b9e6ad5984f6241a942f7cd3bbfbdbd03861ea9/tomli-2.2.1-py3-none-any.whl", hash = "sha256:cb55c73c5f4408779d0cf3eef9f762b9c9f147a77de7b258bef0a5628adc85cc", size = 14257, upload-time = "2024-11-27T22:38:35.385Z" }, +version = "2.3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/52/ed/3f73f72945444548f33eba9a87fc7a6e969915e7b1acc8260b30e1f76a2f/tomli-2.3.0.tar.gz", hash = "sha256:64be704a875d2a59753d80ee8a533c3fe183e3f06807ff7dc2232938ccb01549", size = 17392, upload-time = "2025-10-08T22:01:47.119Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b3/2e/299f62b401438d5fe1624119c723f5d877acc86a4c2492da405626665f12/tomli-2.3.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:88bd15eb972f3664f5ed4b57c1634a97153b4bac4479dcb6a495f41921eb7f45", size = 153236, upload-time = "2025-10-08T22:01:00.137Z" }, + { url = "https://files.pythonhosted.org/packages/86/7f/d8fffe6a7aefdb61bced88fcb5e280cfd71e08939da5894161bd71bea022/tomli-2.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:883b1c0d6398a6a9d29b508c331fa56adbcdff647f6ace4dfca0f50e90dfd0ba", size = 148084, upload-time = "2025-10-08T22:01:01.63Z" }, + { url = "https://files.pythonhosted.org/packages/47/5c/24935fb6a2ee63e86d80e4d3b58b222dafaf438c416752c8b58537c8b89a/tomli-2.3.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d1381caf13ab9f300e30dd8feadb3de072aeb86f1d34a8569453ff32a7dea4bf", size = 234832, upload-time = "2025-10-08T22:01:02.543Z" }, + { url = "https://files.pythonhosted.org/packages/89/da/75dfd804fc11e6612846758a23f13271b76d577e299592b4371a4ca4cd09/tomli-2.3.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a0e285d2649b78c0d9027570d4da3425bdb49830a6156121360b3f8511ea3441", size = 242052, upload-time = "2025-10-08T22:01:03.836Z" }, + { url = "https://files.pythonhosted.org/packages/70/8c/f48ac899f7b3ca7eb13af73bacbc93aec37f9c954df3c08ad96991c8c373/tomli-2.3.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0a154a9ae14bfcf5d8917a59b51ffd5a3ac1fd149b71b47a3a104ca4edcfa845", size = 239555, upload-time = "2025-10-08T22:01:04.834Z" }, + { url = "https://files.pythonhosted.org/packages/ba/28/72f8afd73f1d0e7829bfc093f4cb98ce0a40ffc0cc997009ee1ed94ba705/tomli-2.3.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:74bf8464ff93e413514fefd2be591c3b0b23231a77f901db1eb30d6f712fc42c", size = 245128, upload-time = "2025-10-08T22:01:05.84Z" }, + { url = "https://files.pythonhosted.org/packages/b6/eb/a7679c8ac85208706d27436e8d421dfa39d4c914dcf5fa8083a9305f58d9/tomli-2.3.0-cp311-cp311-win32.whl", hash = "sha256:00b5f5d95bbfc7d12f91ad8c593a1659b6387b43f054104cda404be6bda62456", size = 96445, upload-time = "2025-10-08T22:01:06.896Z" }, + { url = "https://files.pythonhosted.org/packages/0a/fe/3d3420c4cb1ad9cb462fb52967080575f15898da97e21cb6f1361d505383/tomli-2.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:4dc4ce8483a5d429ab602f111a93a6ab1ed425eae3122032db7e9acf449451be", size = 107165, upload-time = "2025-10-08T22:01:08.107Z" }, + { url = "https://files.pythonhosted.org/packages/ff/b7/40f36368fcabc518bb11c8f06379a0fd631985046c038aca08c6d6a43c6e/tomli-2.3.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d7d86942e56ded512a594786a5ba0a5e521d02529b3826e7761a05138341a2ac", size = 154891, upload-time = "2025-10-08T22:01:09.082Z" }, + { url = "https://files.pythonhosted.org/packages/f9/3f/d9dd692199e3b3aab2e4e4dd948abd0f790d9ded8cd10cbaae276a898434/tomli-2.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:73ee0b47d4dad1c5e996e3cd33b8a76a50167ae5f96a2607cbe8cc773506ab22", size = 148796, upload-time = "2025-10-08T22:01:10.266Z" }, + { url = "https://files.pythonhosted.org/packages/60/83/59bff4996c2cf9f9387a0f5a3394629c7efa5ef16142076a23a90f1955fa/tomli-2.3.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:792262b94d5d0a466afb5bc63c7daa9d75520110971ee269152083270998316f", size = 242121, upload-time = "2025-10-08T22:01:11.332Z" }, + { url = "https://files.pythonhosted.org/packages/45/e5/7c5119ff39de8693d6baab6c0b6dcb556d192c165596e9fc231ea1052041/tomli-2.3.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4f195fe57ecceac95a66a75ac24d9d5fbc98ef0962e09b2eddec5d39375aae52", size = 250070, upload-time = "2025-10-08T22:01:12.498Z" }, + { url = "https://files.pythonhosted.org/packages/45/12/ad5126d3a278f27e6701abde51d342aa78d06e27ce2bb596a01f7709a5a2/tomli-2.3.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e31d432427dcbf4d86958c184b9bfd1e96b5b71f8eb17e6d02531f434fd335b8", size = 245859, upload-time = "2025-10-08T22:01:13.551Z" }, + { url = "https://files.pythonhosted.org/packages/fb/a1/4d6865da6a71c603cfe6ad0e6556c73c76548557a8d658f9e3b142df245f/tomli-2.3.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:7b0882799624980785240ab732537fcfc372601015c00f7fc367c55308c186f6", size = 250296, upload-time = "2025-10-08T22:01:14.614Z" }, + { url = "https://files.pythonhosted.org/packages/a0/b7/a7a7042715d55c9ba6e8b196d65d2cb662578b4d8cd17d882d45322b0d78/tomli-2.3.0-cp312-cp312-win32.whl", hash = "sha256:ff72b71b5d10d22ecb084d345fc26f42b5143c5533db5e2eaba7d2d335358876", size = 97124, upload-time = "2025-10-08T22:01:15.629Z" }, + { url = "https://files.pythonhosted.org/packages/06/1e/f22f100db15a68b520664eb3328fb0ae4e90530887928558112c8d1f4515/tomli-2.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:1cb4ed918939151a03f33d4242ccd0aa5f11b3547d0cf30f7c74a408a5b99878", size = 107698, upload-time = "2025-10-08T22:01:16.51Z" }, + { url = "https://files.pythonhosted.org/packages/89/48/06ee6eabe4fdd9ecd48bf488f4ac783844fd777f547b8d1b61c11939974e/tomli-2.3.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5192f562738228945d7b13d4930baffda67b69425a7f0da96d360b0a3888136b", size = 154819, upload-time = "2025-10-08T22:01:17.964Z" }, + { url = "https://files.pythonhosted.org/packages/f1/01/88793757d54d8937015c75dcdfb673c65471945f6be98e6a0410fba167ed/tomli-2.3.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:be71c93a63d738597996be9528f4abe628d1adf5e6eb11607bc8fe1a510b5dae", size = 148766, upload-time = "2025-10-08T22:01:18.959Z" }, + { url = "https://files.pythonhosted.org/packages/42/17/5e2c956f0144b812e7e107f94f1cc54af734eb17b5191c0bbfb72de5e93e/tomli-2.3.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c4665508bcbac83a31ff8ab08f424b665200c0e1e645d2bd9ab3d3e557b6185b", size = 240771, upload-time = "2025-10-08T22:01:20.106Z" }, + { url = "https://files.pythonhosted.org/packages/d5/f4/0fbd014909748706c01d16824eadb0307115f9562a15cbb012cd9b3512c5/tomli-2.3.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4021923f97266babc6ccab9f5068642a0095faa0a51a246a6a02fccbb3514eaf", size = 248586, upload-time = "2025-10-08T22:01:21.164Z" }, + { url = "https://files.pythonhosted.org/packages/30/77/fed85e114bde5e81ecf9bc5da0cc69f2914b38f4708c80ae67d0c10180c5/tomli-2.3.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a4ea38c40145a357d513bffad0ed869f13c1773716cf71ccaa83b0fa0cc4e42f", size = 244792, upload-time = "2025-10-08T22:01:22.417Z" }, + { url = "https://files.pythonhosted.org/packages/55/92/afed3d497f7c186dc71e6ee6d4fcb0acfa5f7d0a1a2878f8beae379ae0cc/tomli-2.3.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ad805ea85eda330dbad64c7ea7a4556259665bdf9d2672f5dccc740eb9d3ca05", size = 248909, upload-time = "2025-10-08T22:01:23.859Z" }, + { url = "https://files.pythonhosted.org/packages/f8/84/ef50c51b5a9472e7265ce1ffc7f24cd4023d289e109f669bdb1553f6a7c2/tomli-2.3.0-cp313-cp313-win32.whl", hash = "sha256:97d5eec30149fd3294270e889b4234023f2c69747e555a27bd708828353ab606", size = 96946, upload-time = "2025-10-08T22:01:24.893Z" }, + { url = "https://files.pythonhosted.org/packages/b2/b7/718cd1da0884f281f95ccfa3a6cc572d30053cba64603f79d431d3c9b61b/tomli-2.3.0-cp313-cp313-win_amd64.whl", hash = "sha256:0c95ca56fbe89e065c6ead5b593ee64b84a26fca063b5d71a1122bf26e533999", size = 107705, upload-time = "2025-10-08T22:01:26.153Z" }, + { url = "https://files.pythonhosted.org/packages/19/94/aeafa14a52e16163008060506fcb6aa1949d13548d13752171a755c65611/tomli-2.3.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:cebc6fe843e0733ee827a282aca4999b596241195f43b4cc371d64fc6639da9e", size = 154244, upload-time = "2025-10-08T22:01:27.06Z" }, + { url = "https://files.pythonhosted.org/packages/db/e4/1e58409aa78eefa47ccd19779fc6f36787edbe7d4cd330eeeedb33a4515b/tomli-2.3.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:4c2ef0244c75aba9355561272009d934953817c49f47d768070c3c94355c2aa3", size = 148637, upload-time = "2025-10-08T22:01:28.059Z" }, + { url = "https://files.pythonhosted.org/packages/26/b6/d1eccb62f665e44359226811064596dd6a366ea1f985839c566cd61525ae/tomli-2.3.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c22a8bf253bacc0cf11f35ad9808b6cb75ada2631c2d97c971122583b129afbc", size = 241925, upload-time = "2025-10-08T22:01:29.066Z" }, + { url = "https://files.pythonhosted.org/packages/70/91/7cdab9a03e6d3d2bb11beae108da5bdc1c34bdeb06e21163482544ddcc90/tomli-2.3.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0eea8cc5c5e9f89c9b90c4896a8deefc74f518db5927d0e0e8d4a80953d774d0", size = 249045, upload-time = "2025-10-08T22:01:31.98Z" }, + { url = "https://files.pythonhosted.org/packages/15/1b/8c26874ed1f6e4f1fcfeb868db8a794cbe9f227299402db58cfcc858766c/tomli-2.3.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:b74a0e59ec5d15127acdabd75ea17726ac4c5178ae51b85bfe39c4f8a278e879", size = 245835, upload-time = "2025-10-08T22:01:32.989Z" }, + { url = "https://files.pythonhosted.org/packages/fd/42/8e3c6a9a4b1a1360c1a2a39f0b972cef2cc9ebd56025168c4137192a9321/tomli-2.3.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:b5870b50c9db823c595983571d1296a6ff3e1b88f734a4c8f6fc6188397de005", size = 253109, upload-time = "2025-10-08T22:01:34.052Z" }, + { url = "https://files.pythonhosted.org/packages/22/0c/b4da635000a71b5f80130937eeac12e686eefb376b8dee113b4a582bba42/tomli-2.3.0-cp314-cp314-win32.whl", hash = "sha256:feb0dacc61170ed7ab602d3d972a58f14ee3ee60494292d384649a3dc38ef463", size = 97930, upload-time = "2025-10-08T22:01:35.082Z" }, + { url = "https://files.pythonhosted.org/packages/b9/74/cb1abc870a418ae99cd5c9547d6bce30701a954e0e721821df483ef7223c/tomli-2.3.0-cp314-cp314-win_amd64.whl", hash = "sha256:b273fcbd7fc64dc3600c098e39136522650c49bca95df2d11cf3b626422392c8", size = 107964, upload-time = "2025-10-08T22:01:36.057Z" }, + { url = "https://files.pythonhosted.org/packages/54/78/5c46fff6432a712af9f792944f4fcd7067d8823157949f4e40c56b8b3c83/tomli-2.3.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:940d56ee0410fa17ee1f12b817b37a4d4e4dc4d27340863cc67236c74f582e77", size = 163065, upload-time = "2025-10-08T22:01:37.27Z" }, + { url = "https://files.pythonhosted.org/packages/39/67/f85d9bd23182f45eca8939cd2bc7050e1f90c41f4a2ecbbd5963a1d1c486/tomli-2.3.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:f85209946d1fe94416debbb88d00eb92ce9cd5266775424ff81bc959e001acaf", size = 159088, upload-time = "2025-10-08T22:01:38.235Z" }, + { url = "https://files.pythonhosted.org/packages/26/5a/4b546a0405b9cc0659b399f12b6adb750757baf04250b148d3c5059fc4eb/tomli-2.3.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a56212bdcce682e56b0aaf79e869ba5d15a6163f88d5451cbde388d48b13f530", size = 268193, upload-time = "2025-10-08T22:01:39.712Z" }, + { url = "https://files.pythonhosted.org/packages/42/4f/2c12a72ae22cf7b59a7fe75b3465b7aba40ea9145d026ba41cb382075b0e/tomli-2.3.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c5f3ffd1e098dfc032d4d3af5c0ac64f6d286d98bc148698356847b80fa4de1b", size = 275488, upload-time = "2025-10-08T22:01:40.773Z" }, + { url = "https://files.pythonhosted.org/packages/92/04/a038d65dbe160c3aa5a624e93ad98111090f6804027d474ba9c37c8ae186/tomli-2.3.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:5e01decd096b1530d97d5d85cb4dff4af2d8347bd35686654a004f8dea20fc67", size = 272669, upload-time = "2025-10-08T22:01:41.824Z" }, + { url = "https://files.pythonhosted.org/packages/be/2f/8b7c60a9d1612a7cbc39ffcca4f21a73bf368a80fc25bccf8253e2563267/tomli-2.3.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:8a35dd0e643bb2610f156cca8db95d213a90015c11fee76c946aa62b7ae7e02f", size = 279709, upload-time = "2025-10-08T22:01:43.177Z" }, + { url = "https://files.pythonhosted.org/packages/7e/46/cc36c679f09f27ded940281c38607716c86cf8ba4a518d524e349c8b4874/tomli-2.3.0-cp314-cp314t-win32.whl", hash = "sha256:a1f7f282fe248311650081faafa5f4732bdbfef5d45fe3f2e702fbc6f2d496e0", size = 107563, upload-time = "2025-10-08T22:01:44.233Z" }, + { url = "https://files.pythonhosted.org/packages/84/ff/426ca8683cf7b753614480484f6437f568fd2fda2edbdf57a2d3d8b27a0b/tomli-2.3.0-cp314-cp314t-win_amd64.whl", hash = "sha256:70a251f8d4ba2d9ac2542eecf008b3c8a9fc5c3f9f02c56a9d7952612be2fdba", size = 119756, upload-time = "2025-10-08T22:01:45.234Z" }, + { url = "https://files.pythonhosted.org/packages/77/b8/0135fadc89e73be292b473cb820b4f5a08197779206b33191e801feeae40/tomli-2.3.0-py3-none-any.whl", hash = "sha256:e95b1af3c5b07d9e643909b5abbec77cd9f1217e6d0bca72b0234736b9fb1f1b", size = 14408, upload-time = "2025-10-08T22:01:46.04Z" }, ] [[package]] @@ -2812,28 +2822,28 @@ wheels = [ [[package]] name = "uv" -version = "0.8.22" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/a6/39/231e123458d50dd497cf6d27b592f5d3bc3e2e50f496b56859865a7b22e3/uv-0.8.22.tar.gz", hash = "sha256:e6e1289c411d43e0ca245f46e76457f3807de646d90b656591b6cf46348bed5c", size = 3667007, upload-time = "2025-09-23T20:35:14.736Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/7c/e6/bb440171dd8a36d0f9874b4c71778f7bbc83e62ccf42c62bd1583c802793/uv-0.8.22-py3-none-linux_armv6l.whl", hash = "sha256:7350c5f82d9c38944e6466933edcf96a90e0cb85eae5c0e53a5bc716d6f62332", size = 20554993, upload-time = "2025-09-23T20:34:26.549Z" }, - { url = "https://files.pythonhosted.org/packages/28/e9/813f7eb9fb9694c4024362782c8933e37887b5195e189f80dc40f2da5958/uv-0.8.22-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:89944e99b04cc8542cb5931306f1c593f00c9d6f2b652fffc4d84d12b915f911", size = 19565276, upload-time = "2025-09-23T20:34:30.436Z" }, - { url = "https://files.pythonhosted.org/packages/d7/ca/bf37d86af6e16e45fa2b1a03300784ff3297aa9252a23dfbeaf6e391e72e/uv-0.8.22-py3-none-macosx_11_0_arm64.whl", hash = "sha256:6706b782ad75662df794e186d16b9ffa4946d57c88f21d0eadfd43425794d1b0", size = 18162303, upload-time = "2025-09-23T20:34:32.761Z" }, - { url = "https://files.pythonhosted.org/packages/e4/eb/289b6a59fff1613958499a886283f52403c5ce4f0a8a550b86fbd70e8e4f/uv-0.8.22-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:d6a33bd5309f8fb77d9fc249bb17f77a23426e6153e43b03ca1cd6640f0a423d", size = 19982769, upload-time = "2025-09-23T20:34:34.962Z" }, - { url = "https://files.pythonhosted.org/packages/df/ba/2fcc3ce75be62eecf280f3cbe74d186f371a468fad3167b5a34dee2f904e/uv-0.8.22-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4a982bdd5d239dd6dd2b4219165e209c75af1e1819730454ee46d65b3ccf77a3", size = 20163849, upload-time = "2025-09-23T20:34:37.744Z" }, - { url = "https://files.pythonhosted.org/packages/f4/4d/4fc9a508c2c497a80c41710c96f1782a29edecffcac742f3843af061ba8f/uv-0.8.22-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:58b6fb191a04b922dc3c8fea6660f58545a651843d7d0efa9ae69164fca9e05d", size = 21130147, upload-time = "2025-09-23T20:34:40.414Z" }, - { url = "https://files.pythonhosted.org/packages/71/79/6bcb3c3c3b7c9cb1a162a76dca2b166752e4ba39ec90e802b252f0a54039/uv-0.8.22-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:8ea724ae9f15c0cb4964e9e2e1b21df65c56ae02a54dc1d8a6ea44a52d819268", size = 22561974, upload-time = "2025-09-23T20:34:42.843Z" }, - { url = "https://files.pythonhosted.org/packages/3f/98/89bb29d82ff7e5ab1b5e862d9bdc12b1d3a4d5201cf558432487e29cc448/uv-0.8.22-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7378127cbd6ebce8ba6d9bdb88aa8ea995b579824abb5ec381c63b3a123a43be", size = 22183189, upload-time = "2025-09-23T20:34:45.57Z" }, - { url = "https://files.pythonhosted.org/packages/95/b0/354c7d7d11fff2ee97bb208f0fec6b09ae885c0d591b6eff2d7b84cc6695/uv-0.8.22-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7e761ca7df8a0059b3fae6bc2c1db24583fa00b016e35bd22a5599d7084471a7", size = 21492888, upload-time = "2025-09-23T20:34:48.45Z" }, - { url = "https://files.pythonhosted.org/packages/3a/a9/a83cee9b8cf63e57ce64ba27c77777cc66410e144fd178368f55af1fa18d/uv-0.8.22-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8efec4ef5acddc35f0867998c44e0b15fc4dace1e4c26d01443871a2fbb04bf6", size = 21252972, upload-time = "2025-09-23T20:34:50.862Z" }, - { url = "https://files.pythonhosted.org/packages/0f/0c/71d5d5d3fca7aa788d63297a06ca26d3585270342277b52312bb693b100c/uv-0.8.22-py3-none-manylinux_2_28_aarch64.whl", hash = "sha256:9eb3b4abfa25e07d7e1bb4c9bb8dbbdd51878356a37c3c4a2ece3d68d4286f28", size = 20115520, upload-time = "2025-09-23T20:34:53.165Z" }, - { url = "https://files.pythonhosted.org/packages/da/90/57fae2798be1e71692872b8304e2e2c345eacbe2070bdcbba6d5a7675fa1/uv-0.8.22-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:b1fdffc2e71892ce648b66317e478fe8884d0007e20cfa582fff3dcea588a450", size = 21168787, upload-time = "2025-09-23T20:34:55.638Z" }, - { url = "https://files.pythonhosted.org/packages/fe/f6/23c8d8fdd1084603795f6344eee8e763ba06f891e863397fe5b7b532cb58/uv-0.8.22-py3-none-musllinux_1_1_armv7l.whl", hash = "sha256:f6ded9bacb31441d788afca397b8b884ebc2e70f903bea0a38806194be4b249c", size = 20170112, upload-time = "2025-09-23T20:34:58.008Z" }, - { url = "https://files.pythonhosted.org/packages/96/23/801d517964a7200014897522ae067bf7111fc2e138b38d13d9df9544bf06/uv-0.8.22-py3-none-musllinux_1_1_i686.whl", hash = "sha256:aefa0cb27a86d2145ca9290a1e99c16a17ea26a4f14a89fb7336bc19388427cc", size = 20537608, upload-time = "2025-09-23T20:35:00.44Z" }, - { url = "https://files.pythonhosted.org/packages/20/8a/1bd4159089f8df0128e4ceb7f4c31c23a451984a5b49c13489c70e721335/uv-0.8.22-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:9757f0b0c7d296f1e354db442ed0ce39721c06d11635ce4ee6638c5e809a9cb4", size = 21471224, upload-time = "2025-09-23T20:35:03.718Z" }, - { url = "https://files.pythonhosted.org/packages/86/ba/262d16059e3b0837728e8aa3590fc2c7bc23e0cefec81d6903b4b6af080a/uv-0.8.22-py3-none-win32.whl", hash = "sha256:36c7aecdb0044caf15ace00da00af172759c49c832f0017b7433d80f46552cd3", size = 19350586, upload-time = "2025-09-23T20:35:06.837Z" }, - { url = "https://files.pythonhosted.org/packages/38/82/94f08992eeb193dc3d5baac437d1867cd37f040f34c7b1a4b1bde2bc4b4b/uv-0.8.22-py3-none-win_amd64.whl", hash = "sha256:cda349c9ea53644d8d9ceae30db71616b733eb5330375ab4259765aef494b74e", size = 21355960, upload-time = "2025-09-23T20:35:09.472Z" }, - { url = "https://files.pythonhosted.org/packages/f9/00/2c7a93bbe93b74dc0496a8e875bac11027cb30c29636c106c6e49038b95f/uv-0.8.22-py3-none-win_arm64.whl", hash = "sha256:2a436b941b6e79fe1e1065b705a5689d72210f4367cbe885e19910cbcde2e4a1", size = 19778983, upload-time = "2025-09-23T20:35:12.188Z" }, +version = "0.9.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/fc/05/98147931b168b32273b20da39192856650b4b04198ffadd046340c3b2af1/uv-0.9.0.tar.gz", hash = "sha256:9f6bbcec6d45f921a81a3ab7cd384738b842d2a5e49686fdf5a0affcd4875d47", size = 3681408, upload-time = "2025-10-07T23:45:13.71Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/38/3f/812eb731f5abfe0a9a3ecb15614e011b5b5d9a684cc9ddfed5095af43b4b/uv-0.9.0-py3-none-linux_armv6l.whl", hash = "sha256:c447a5f49f3d75d65c91d3ab286d52f3bcc054256c31725c6a60ab7b2b180797", size = 20530647, upload-time = "2025-10-07T23:44:23.276Z" }, + { url = "https://files.pythonhosted.org/packages/c2/1e/efb46c17b7220fab41b470e6f269f4e7997d274fb5fb46512e1579ff3b07/uv-0.9.0-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:ecc841797888d5983dcbac0918d0392f8078265083c2bc676a76e36a1a84b3ad", size = 19617751, upload-time = "2025-10-07T23:44:27.644Z" }, + { url = "https://files.pythonhosted.org/packages/8e/06/f5e38314e318bfaa20ccce966f6d0a69b093854648d31085b2d8b2097aab/uv-0.9.0-py3-none-macosx_11_0_arm64.whl", hash = "sha256:b900e84d992a657e16371426dbb030ab031c0322a604b632dada34401ebe7145", size = 18207114, upload-time = "2025-10-07T23:44:30.076Z" }, + { url = "https://files.pythonhosted.org/packages/83/2e/2a0787ee496bef5e1312a733aab6d06b28b093b87a196ec6d45497a1cc4c/uv-0.9.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:ac6ec2b69dbf61ddd725d10626db2d9401c2687b1c71077217d097214bb9665d", size = 19962531, upload-time = "2025-10-07T23:44:32.958Z" }, + { url = "https://files.pythonhosted.org/packages/42/a7/d0bf7573ea4956c6ea6ea8375a0ec06a11e4a7240f1c21592ae160cb9c36/uv-0.9.0-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:431856f10a8fea6e10f6194a0cc1410d9e0d007e484c2259fea50524e904e1ae", size = 20147793, upload-time = "2025-10-07T23:44:35.594Z" }, + { url = "https://files.pythonhosted.org/packages/c1/09/8e09ae31a421464cf9e42d578e632342a2c7542575bfcef2b78d2b89bb7b/uv-0.9.0-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:57ea8d38cbc44bb0a19facb2a953015c1e7f8445c7c007913c6de615ff976270", size = 21091691, upload-time = "2025-10-07T23:44:38.369Z" }, + { url = "https://files.pythonhosted.org/packages/ce/a4/2669f39ed5fb9f66de9971f301841a6596b5d16b63c4d033d65ef38d8aa0/uv-0.9.0-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:dc7ae35d33174aa5861182ca44ddc3a68146eeae11fbda10f306c1924b4057a1", size = 22531644, upload-time = "2025-10-07T23:44:40.99Z" }, + { url = "https://files.pythonhosted.org/packages/02/f3/553278547813ad866cdf29500913d9811b8ce896c9c798495de9b20e112d/uv-0.9.0-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8d9654d8953303402ec88e95474da1533ea309c3086f3f8375b7a56492273530", size = 22213399, upload-time = "2025-10-07T23:44:43.984Z" }, + { url = "https://files.pythonhosted.org/packages/69/e3/d9c2d52a3487d66c3a99a521f2ca5a1f3f7a975a3fb61f446c093646e970/uv-0.9.0-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c68fa7c8cd172d11bcb2fa0adac2ddb53bd51264be3f52e02840c00feb0f0572", size = 21386341, upload-time = "2025-10-07T23:44:46.624Z" }, + { url = "https://files.pythonhosted.org/packages/6f/92/7d491ede63c70e237168d7c6a53aa6353420414fa29e5ee06e0c130cfa35/uv-0.9.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8fcd2f0d52ab16faa055ca2969d1d94ae1b1397ba5a0962332c500dd81b0f893", size = 21216943, upload-time = "2025-10-07T23:44:49.201Z" }, + { url = "https://files.pythonhosted.org/packages/4a/52/25a5dcfccb7a905f9fde93acd0a6c6bb6d1a14333d2f696e64d33ec108df/uv-0.9.0-py3-none-manylinux_2_28_aarch64.whl", hash = "sha256:5ff5954dc403b408d30470d499a40286bc549e2f9623dc05c93d5bb05af80340", size = 20105222, upload-time = "2025-10-07T23:44:52.184Z" }, + { url = "https://files.pythonhosted.org/packages/8c/fb/f96df677030a29e7af381e9fdc014e4a15bd28bb239719f540dd780eefed/uv-0.9.0-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:d9234efcd64d09be3cdd5482a5fc5ca824715533f8ad064d9c14d4ae844584f7", size = 21227746, upload-time = "2025-10-07T23:44:54.715Z" }, + { url = "https://files.pythonhosted.org/packages/cf/b1/87451ceae6ac012e21e893899fcb5d4748c718c6a0e574b00d2777ec3785/uv-0.9.0-py3-none-musllinux_1_1_armv7l.whl", hash = "sha256:54e14d2b5dce68930e76dc1b61a7d9920cc5f08dee68074e02e828b515cbe565", size = 20096479, upload-time = "2025-10-07T23:44:57.145Z" }, + { url = "https://files.pythonhosted.org/packages/66/33/afd79936553b3d901ccdaa0e4a3f482b5a16c5d263c032cc927800c3de2a/uv-0.9.0-py3-none-musllinux_1_1_i686.whl", hash = "sha256:ab1c25094cd298ad82d331abb80ab56ad0e49a3c18c6c1c25413389be7432158", size = 20528329, upload-time = "2025-10-07T23:44:59.868Z" }, + { url = "https://files.pythonhosted.org/packages/9b/cd/9f47b7aeb907c7c9c8e87a02796c386bc102f142d4dbe29f57eb68802d62/uv-0.9.0-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:4e0b226ed5d061ff9001547f59ca4a76af427d5f28d1d50ae245c6916ea026d7", size = 21415050, upload-time = "2025-10-07T23:45:03.936Z" }, + { url = "https://files.pythonhosted.org/packages/fa/b1/d1973ac4c34c5e8608760a81147e51e5f6d4670a1bf6e6c56fc1067ff5f5/uv-0.9.0-py3-none-win32.whl", hash = "sha256:943ff96a34c5cf364eaf43cfc8cf181261ed94ab0c7e199686deb1dfa0cd9723", size = 19380428, upload-time = "2025-10-07T23:45:06.475Z" }, + { url = "https://files.pythonhosted.org/packages/60/cd/98242bb85c92a06156ebfead3c3c9126e8dbb7872808b11a76428b9aaf4a/uv-0.9.0-py3-none-win_amd64.whl", hash = "sha256:ee5969cef61e8eef251ee14e573fa22b42bbe90a2d194b6de6d794baee176a9b", size = 21387424, upload-time = "2025-10-07T23:45:09.05Z" }, + { url = "https://files.pythonhosted.org/packages/1a/7e/d9b4df434081e883eefb0e975e4dd40de210596c28cf8a88ec5783ae593b/uv-0.9.0-py3-none-win_arm64.whl", hash = "sha256:4a77a33c86d478fd1fb27db29035044261f086e7287325bcbe695c9b31808f4c", size = 19853856, upload-time = "2025-10-07T23:45:11.69Z" }, ] [[package]] @@ -2938,14 +2948,14 @@ wheels = [ [[package]] name = "xarray" -version = "2025.9.1" +version = "2025.10.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "numpy" }, { name = "packaging" }, { name = "pandas" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/d0/5d/e139112a463336c636d4455494f3227b7f47a2e06ca7571e6b88158ffc06/xarray-2025.9.1.tar.gz", hash = "sha256:f34a27a52c13d1f3cceb7b27276aeec47021558363617dd7ef4f4c8b379011c0", size = 3057322, upload-time = "2025-09-30T05:28:53.084Z" } +sdist = { url = "https://files.pythonhosted.org/packages/7b/ce/f5dd613ddd0b3f839c59e6c2fa20c62469bf671bf4c92a12b09dc0972326/xarray-2025.10.1.tar.gz", hash = "sha256:3c2b5ad7389825bd624ada5ff26b01ac54b1aae72e2fe0d724d81d40a2bf5785", size = 3058736, upload-time = "2025-10-07T20:25:56.708Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/0e/a7/6eeb32e705d510a672f74135f538ad27f87f3d600845bfd3834ea3a77c7e/xarray-2025.9.1-py3-none-any.whl", hash = "sha256:3e9708db0d7915c784ed6c227d81b398dca4957afe68d119481f8a448fc88c44", size = 1364411, upload-time = "2025-09-30T05:28:51.294Z" }, + { url = "https://files.pythonhosted.org/packages/c3/78/4d6d68555a92cb97b4c192759c4ab585c5cb23490f64d4ddf12c66a3b051/xarray-2025.10.1-py3-none-any.whl", hash = "sha256:a4e699433b87a7fac340951bc36648645eeef72bdd915ff055ac2fd99865a73d", size = 1365202, upload-time = "2025-10-07T20:25:54.964Z" }, ] From aa03ea20e45ecd269044320e97cdf3bfd9136836 Mon Sep 17 00:00:00 2001 From: Erik Date: Tue, 14 Oct 2025 11:15:43 -0700 Subject: [PATCH 515/521] repair TestFinddIdVPeakLocation.test_raises --- .../test_plasma_potential__find_didv_peak_location.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/analysis/swept_langmuir/test_plasma_potential__find_didv_peak_location.py b/tests/analysis/swept_langmuir/test_plasma_potential__find_didv_peak_location.py index 1f0b5f1999..b060003918 100644 --- a/tests/analysis/swept_langmuir/test_plasma_potential__find_didv_peak_location.py +++ b/tests/analysis/swept_langmuir/test_plasma_potential__find_didv_peak_location.py @@ -146,7 +146,7 @@ def test_call_of_condition_smooth_fractions( ("_raises", "voltage", "current", "voltage_window"), [ # voltage_window is too small (<3 points) - (pytest.raises(ValueError), "simple_voltage", "simple_current", [4, 5]), + (pytest.raises(ValueError), "simple_voltage", "simple_current", [4, 4.5]), ], ) def test_raises(self, _raises, voltage, current, voltage_window, request): From 7247054edfb0c0740976700bb4aa838530846410 Mon Sep 17 00:00:00 2001 From: Erik Date: Tue, 14 Oct 2025 12:52:54 -0700 Subject: [PATCH 516/521] add clarifying comments --- src/plasmapy/analysis/swept_langmuir/plasma_potential.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py index 483d8ff352..e26dd53004 100644 --- a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py +++ b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py @@ -224,8 +224,13 @@ def find_didv_peak_location( imax = np.argmax(didv) if imax.size > 1: if np.all(np.diff(imax) == 1): + # neighboring indices have the same peak value, take + # voltage average vp = np.average(voltage_slice[imax]) else: + # peaks occur at separated indices (i.e. NOT neighboring + # indices) ... unable to determine vp just go to the next + # savgol window continue elif np.isscalar(imax): vp = voltage_slice[imax] From 7ab00e41666bb1e597c902f9bc8fa8cbadea5b1a Mon Sep 17 00:00:00 2001 From: Erik Date: Tue, 14 Oct 2025 15:23:40 -0700 Subject: [PATCH 517/521] use np.max and np.isclose to find max indices instead of np.argmax --- src/plasmapy/analysis/swept_langmuir/plasma_potential.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py index e26dd53004..2f3f8c9f5b 100644 --- a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py +++ b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py @@ -221,7 +221,8 @@ def find_didv_peak_location( c_smooth = signal.savgol_filter(current_slice, _window, 1) didv = np.gradient(c_smooth, v_smooth) - imax = np.argmax(didv) + didv_max = np.max(didv) + imax = np.where(np.isclose(didv, didv_max, atol=0.0))[0] if imax.size > 1: if np.all(np.diff(imax) == 1): # neighboring indices have the same peak value, take From 0cb3547c0a3fadeb55ff98505c66c445ffd5bde1 Mon Sep 17 00:00:00 2001 From: Erik Date: Tue, 14 Oct 2025 15:24:02 -0700 Subject: [PATCH 518/521] raise RuntimeError if no plasma potential values calculated --- src/plasmapy/analysis/swept_langmuir/plasma_potential.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py index 2f3f8c9f5b..ef3fcd29a7 100644 --- a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py +++ b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py @@ -241,6 +241,11 @@ def find_didv_peak_location( plasma_potentials.append(float(vp)) rtn_extras["savgol_windows"].append(int(_window)) + if len(plasma_potentials) == 0: + raise RuntimeError( + "Unable to identify any dI/dV peaks in the Langmuir trace." + ) + rtn_extras["savgol_peaks"] = plasma_potentials rtn_extras["std"] = float(np.std(plasma_potentials)) From e305f2af3b3739d2efb89d70b3d0a67e52de8017 Mon Sep 17 00:00:00 2001 From: Erik Date: Tue, 14 Oct 2025 15:24:59 -0700 Subject: [PATCH 519/521] update TestFinddIdVPeakLocation.test_raise to cover the RuntimeError if no valid plasma potential values computed --- ...asma_potential__find_didv_peak_location.py | 38 +++++++++++++++++-- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/tests/analysis/swept_langmuir/test_plasma_potential__find_didv_peak_location.py b/tests/analysis/swept_langmuir/test_plasma_potential__find_didv_peak_location.py index b060003918..3f93e3daa9 100644 --- a/tests/analysis/swept_langmuir/test_plasma_potential__find_didv_peak_location.py +++ b/tests/analysis/swept_langmuir/test_plasma_potential__find_didv_peak_location.py @@ -143,13 +143,32 @@ def test_call_of_condition_smooth_fractions( @pytest.mark.usefixtures("request") @pytest.mark.parametrize( - ("_raises", "voltage", "current", "voltage_window"), + ("_raises", "voltage", "current", "voltage_window", "smooth_fractions"), [ # voltage_window is too small (<3 points) - (pytest.raises(ValueError), "simple_voltage", "simple_current", [4, 4.5]), + ( + pytest.raises(ValueError), + "simple_voltage", + "simple_current", + [4, 4.5], + None, + ), + # no valid computer plasma potentials + ( + pytest.raises(RuntimeError), + "simple_voltage", + np.append( + np.append(np.linspace(0, 10., 50), np.linspace(0, 10., 100)), + np.linspace(0, 10, 50) + ), + None, + [0.0], + ), ], ) - def test_raises(self, _raises, voltage, current, voltage_window, request): + def test_raises( + self, _raises, voltage, current, voltage_window, smooth_fractions, request + ): if isinstance(voltage, str): # assume fixture name voltage = request.getfixturevalue(voltage) @@ -158,11 +177,22 @@ def test_raises(self, _raises, voltage, current, voltage_window, request): # assume fixture name current = request.getfixturevalue(current) - with _raises: + with ( + mock.patch( + f"{sla.plasma_potential.__name__}.check_sweep", + return_value=(voltage, current), + ), + mock.patch( + f"{sla.plasma_potential.__name__}.merge_voltage_clusters", + return_value=(voltage, current), + ), + _raises, + ): find_didv_peak_location( voltage=voltage, current=current, voltage_window=voltage_window, + smooth_fractions=smooth_fractions, ) @pytest.mark.usefixtures("request") From 6389da34b94f4dc220c6ed51b52bb38417fdf7eb Mon Sep 17 00:00:00 2001 From: Erik Date: Tue, 14 Oct 2025 16:10:51 -0700 Subject: [PATCH 520/521] add test TestFinddIdVPeakLocation.test_peak_index_identification --- ...asma_potential__find_didv_peak_location.py | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/tests/analysis/swept_langmuir/test_plasma_potential__find_didv_peak_location.py b/tests/analysis/swept_langmuir/test_plasma_potential__find_didv_peak_location.py index 3f93e3daa9..c93e4235af 100644 --- a/tests/analysis/swept_langmuir/test_plasma_potential__find_didv_peak_location.py +++ b/tests/analysis/swept_langmuir/test_plasma_potential__find_didv_peak_location.py @@ -283,3 +283,29 @@ def test_on_pace_data(self, pace_voltage, pace_current): -16.4, -16.0, ] + + @pytest.mark.parametrize( + ("argmax_return", "expected"), + [ + (np.array([10, 11, 12], dtype=np.int64), -17.78894472), + (np.array([45], dtype=np.int64), -10.95477386), + (np.int64(45), -10.95477386), + ], + ) + def test_peak_index_identification( + self, argmax_return, expected, simple_voltage, simple_current + ): + with mock.patch("numpy.where") as mock_argmax: + mock_argmax.return_value = (argmax_return, ) + + vp, extras = find_didv_peak_location( + simple_voltage, + simple_current, + voltage_window=None, + smooth_fractions=[0.1], + ) + + assert np.isclose(vp, expected) + + mock_argmax.reset_mock() + From 8603cb2b754b719ca3c40636a9aabd5fc0cb477e Mon Sep 17 00:00:00 2001 From: Erik Date: Tue, 14 Oct 2025 16:13:33 -0700 Subject: [PATCH 521/521] appease grumpy ruff format --- src/plasmapy/analysis/swept_langmuir/plasma_potential.py | 4 +--- .../test_plasma_potential__find_didv_peak_location.py | 7 +++---- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py index ef3fcd29a7..9a9e3f80c5 100644 --- a/src/plasmapy/analysis/swept_langmuir/plasma_potential.py +++ b/src/plasmapy/analysis/swept_langmuir/plasma_potential.py @@ -242,9 +242,7 @@ def find_didv_peak_location( rtn_extras["savgol_windows"].append(int(_window)) if len(plasma_potentials) == 0: - raise RuntimeError( - "Unable to identify any dI/dV peaks in the Langmuir trace." - ) + raise RuntimeError("Unable to identify any dI/dV peaks in the Langmuir trace.") rtn_extras["savgol_peaks"] = plasma_potentials rtn_extras["std"] = float(np.std(plasma_potentials)) diff --git a/tests/analysis/swept_langmuir/test_plasma_potential__find_didv_peak_location.py b/tests/analysis/swept_langmuir/test_plasma_potential__find_didv_peak_location.py index c93e4235af..4792788043 100644 --- a/tests/analysis/swept_langmuir/test_plasma_potential__find_didv_peak_location.py +++ b/tests/analysis/swept_langmuir/test_plasma_potential__find_didv_peak_location.py @@ -158,8 +158,8 @@ def test_call_of_condition_smooth_fractions( pytest.raises(RuntimeError), "simple_voltage", np.append( - np.append(np.linspace(0, 10., 50), np.linspace(0, 10., 100)), - np.linspace(0, 10, 50) + np.append(np.linspace(0, 10.0, 50), np.linspace(0, 10.0, 100)), + np.linspace(0, 10, 50), ), None, [0.0], @@ -296,7 +296,7 @@ def test_peak_index_identification( self, argmax_return, expected, simple_voltage, simple_current ): with mock.patch("numpy.where") as mock_argmax: - mock_argmax.return_value = (argmax_return, ) + mock_argmax.return_value = (argmax_return,) vp, extras = find_didv_peak_location( simple_voltage, @@ -308,4 +308,3 @@ def test_peak_index_identification( assert np.isclose(vp, expected) mock_argmax.reset_mock() -