weac 3.1.1__py3-none-any.whl → 3.1.3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
weac/__init__.py CHANGED
@@ -2,4 +2,4 @@
2
2
  WEAC - Weak Layer Anticrack Nucleation Model
3
3
  """
4
4
 
5
- __version__ = "3.1.1"
5
+ __version__ = "3.1.3"
@@ -24,6 +24,7 @@ from weac.components import (
24
24
  WeakLayer,
25
25
  )
26
26
  from weac.constants import RHO_ICE
27
+ from weac.components.scenario_config import TouchdownMode
27
28
  from weac.core.system_model import SystemModel
28
29
 
29
30
  logger = logging.getLogger(__name__)
@@ -683,6 +684,7 @@ class CriteriaEvaluator:
683
684
  def evaluate_SteadyState(
684
685
  self,
685
686
  system: SystemModel,
687
+ mode: TouchdownMode = "C_in_contact",
686
688
  vertical: bool = False,
687
689
  print_call_stats: bool = False,
688
690
  ) -> SteadyStateResult:
@@ -710,20 +712,38 @@ class CriteriaEvaluator:
710
712
  UserWarning,
711
713
  )
712
714
  system_copy = copy.deepcopy(system)
715
+ # Evaluate touchdown distance for flat slab
713
716
  system_copy.toggle_touchdown(True)
714
- system_copy.update_scenario(scenario_config=ScenarioConfig(phi=0.0))
715
- l_BC = system_copy.slab_touchdown.l_BC
717
+ segments = [
718
+ Segment(length=5e3, has_foundation=True, m=0.0),
719
+ Segment(length=5e3, has_foundation=False, m=0.0),
720
+ ]
721
+ system_copy.update_scenario(
722
+ segments=segments, scenario_config=ScenarioConfig(phi=0.0)
723
+ )
724
+
725
+ cut_distance = 0
726
+ match mode:
727
+ case "C_in_contact":
728
+ cut_distance = 2 * system_copy.slab_touchdown.l_BC
729
+ case "B_point_contact":
730
+ cut_distance = system_copy.slab_touchdown.l_BC - 1e-3
731
+ case "A_free_hanging":
732
+ cut_distance = system_copy.slab_touchdown.l_AB - 1e-3
716
733
 
717
734
  segments = [
718
735
  Segment(length=5e3, has_foundation=True, m=0.0),
719
- Segment(length=2 * l_BC, has_foundation=False, m=0.0),
736
+ Segment(length=cut_distance, has_foundation=False, m=0.0),
720
737
  ]
721
738
  scenario_config = ScenarioConfig(
722
739
  system_type="vpst-" if vertical else "pst-",
723
740
  phi=0.0, # Slab Touchdown works only for flat slab
724
- cut_length=2 * l_BC,
741
+ cut_length=cut_distance,
725
742
  )
726
743
  system_copy.update_scenario(segments=segments, scenario_config=scenario_config)
744
+ # Force the requested mode to avoid floating-point precision issues
745
+ # when l_AB/l_BC are recalculated with different scenario parameters
746
+ system_copy.set_forced_touchdown_mode(mode)
727
747
  touchdown_distance = system_copy.slab_touchdown.touchdown_distance
728
748
  analyzer = Analyzer(system_copy, printing_enabled=print_call_stats)
729
749
  energy_release_rate, _, _ = analyzer.differential_ERR(unit="J/m^2")
@@ -7,7 +7,7 @@ from .criteria_config import CriteriaConfig
7
7
  from .layer import Layer, WeakLayer
8
8
  from .model_input import ModelInput
9
9
  from .segment import Segment
10
- from .scenario_config import ScenarioConfig, SystemType
10
+ from .scenario_config import ScenarioConfig, SystemType, TouchdownMode
11
11
 
12
12
  __all__ = [
13
13
  "Config",
@@ -18,4 +18,5 @@ __all__ = [
18
18
  "ScenarioConfig",
19
19
  "ModelInput",
20
20
  "SystemType",
21
+ "TouchdownMode",
21
22
  ]
weac/components/config.py CHANGED
@@ -12,6 +12,8 @@ field_name: type = Field(..., gt=0, description="Description")
12
12
 
13
13
  from pydantic import BaseModel, Field
14
14
 
15
+ from weac.components.scenario_config import TouchdownMode
16
+
15
17
 
16
18
  class Config(BaseModel):
17
19
  """
@@ -21,11 +23,19 @@ class Config(BaseModel):
21
23
  ----------
22
24
  touchdown : bool
23
25
  Whether slab touchdown on the collapsed weak layer is considered.
26
+ forced_touchdown_mode : TouchdownMode | None
27
+ If set, forces the touchdown mode instead of calculating it from l_AB/l_BC.
28
+ This avoids floating-point precision issues when the mode boundary values
29
+ are recalculated with different scenario parameters.
24
30
  """
25
31
 
26
32
  touchdown: bool = Field(
27
33
  default=False, description="Whether to include slab touchdown in the analysis"
28
34
  )
35
+ forced_touchdown_mode: TouchdownMode | None = Field(
36
+ default=None,
37
+ description="Force a specific touchdown mode instead of auto-calculating",
38
+ )
29
39
 
30
40
 
31
41
  if __name__ == "__main__":
weac/components/layer.py CHANGED
@@ -94,8 +94,43 @@ def _sigrist_tensile_strength(rho, unit: Literal["kPa", "MPa"] = "kPa"):
94
94
  return convert[unit] * 240 * (rho / RHO_ICE) ** 2.44
95
95
 
96
96
 
97
- # TODO: Compressive Strength from Schöttner
98
- # (11 +/- 7) * (rho/rho_0) ^ (5.4 +/- 0.5)
97
+ def _adam_tensile_strength(rho, unit: Literal["kPa", "MPa"] = "kPa"):
98
+ """
99
+ Estimate the tensile strength of a slab layer from its density.
100
+
101
+ Uses the density parametrization of Adam (2025).
102
+
103
+ Arguments
104
+ ---------
105
+ rho : ndarray, float
106
+ Layer density (kg/m^3).
107
+ unit : str, optional
108
+ Desired output unit of the layer strength. Default is 'kPa'.
109
+
110
+ Returns
111
+ -------
112
+ ndarray
113
+ Tensile strength in specified unit.
114
+ """
115
+ convert = {"kPa": 1e3, "MPa": 1}
116
+ TS_0 = 1.0 # [MPa]
117
+ kappa = 3.45 # [-]
118
+ # Adam's equation is given in MPa
119
+ return TS_0 * (rho / RHO_ICE) ** kappa * convert[unit]
120
+
121
+
122
+ # # TODO: Compressive Strength from Schöttner
123
+ # def _schotter_compressive_strength(rho, unit: Literal["kPa", "MPa"] = "kPa"):
124
+ # """
125
+ # Estimate the compressive strength of a slab layer from its density.
126
+ # On the compressive strength of weak snow layers of depth hoar - Schöttner (2025).
127
+
128
+ # Uses the density parametrization of Schöttner (2025).
129
+ # """
130
+ # convert = {"kPa": 1e3, "MPa": 1}
131
+ # CS_0 = 11.0 # [MPa]
132
+ # CS_1 = 5.4 # [-]
133
+ # return CS_0 * (rho / RHO_ICE) ** CS_1 * convert[unit]
99
134
 
100
135
 
101
136
  class Layer(BaseModel):
@@ -114,6 +149,10 @@ class Layer(BaseModel):
114
149
  Young's modulus E [MPa]. If omitted it is derived from ``rho``.
115
150
  G : float, optional
116
151
  Shear modulus G [MPa]. If omitted it is derived from ``E`` and ``nu``.
152
+ tensile_strength: float
153
+ Tensile strength [kPa].
154
+ tensile_strength_method: Literal["sigrist", "adam", "hybrid"]
155
+ Method to calculate the tensile strength.
117
156
  """
118
157
 
119
158
  # has to be provided
@@ -129,8 +168,8 @@ class Layer(BaseModel):
129
168
  tensile_strength: float = Field(
130
169
  default=0.0, ge=0, description="Tensile strength [kPa]"
131
170
  )
132
- tensile_strength_method: Literal["sigrist"] = Field(
133
- default="sigrist",
171
+ tensile_strength_method: Literal["sigrist", "adam", "hybrid"] = Field(
172
+ default="hybrid",
134
173
  description="Method to calculate the tensile strength",
135
174
  )
136
175
  E_method: Literal["bergfeld", "scapazzo", "gerling"] = Field(
@@ -153,17 +192,23 @@ class Layer(BaseModel):
153
192
  else:
154
193
  raise ValueError(f"Invalid E_method: {self.E_method}")
155
194
  object.__setattr__(self, "G", self.G or self.E / (2 * (1 + self.nu)))
156
- if self.tensile_strength_method == "sigrist":
157
- object.__setattr__(
158
- self,
159
- "tensile_strength",
160
- self.tensile_strength
161
- or _sigrist_tensile_strength(self.rho, unit="kPa"),
162
- )
163
- else:
164
- raise ValueError(
165
- f"Invalid tensile_strength_method: {self.tensile_strength_method}"
166
- )
195
+
196
+ if not self.tensile_strength:
197
+ if self.tensile_strength_method == "sigrist":
198
+ ts_value = _sigrist_tensile_strength(self.rho, unit="kPa")
199
+ elif self.tensile_strength_method == "adam":
200
+ ts_value = _adam_tensile_strength(self.rho, unit="kPa")
201
+ elif self.tensile_strength_method == "hybrid":
202
+ # Use Sigrist for rho < 250, Adam for rho >= 250
203
+ if self.rho < 250:
204
+ ts_value = _sigrist_tensile_strength(self.rho, unit="kPa")
205
+ else:
206
+ ts_value = _adam_tensile_strength(self.rho, unit="kPa")
207
+ else:
208
+ raise ValueError(
209
+ f"Invalid tensile_strength_method: {self.tensile_strength_method}"
210
+ )
211
+ object.__setattr__(self, "tensile_strength", ts_value)
167
212
 
168
213
  @model_validator(mode="after")
169
214
  def validate_positive_E_G(self):
@@ -11,6 +11,8 @@ SystemType = Literal[
11
11
  "skier", "skiers", "pst-", "-pst", "rot", "trans", "vpst-", "-vpst"
12
12
  ]
13
13
 
14
+ TouchdownMode = Literal["A_free_hanging", "B_point_contact", "C_in_contact"]
15
+
14
16
 
15
17
  class ScenarioConfig(BaseModel):
16
18
  """
@@ -9,7 +9,7 @@ from typing import Literal
9
9
  from scipy.optimize import brentq
10
10
 
11
11
  from weac.components.layer import WeakLayer
12
- from weac.components.scenario_config import ScenarioConfig
12
+ from weac.components.scenario_config import ScenarioConfig, TouchdownMode
13
13
  from weac.components.segment import Segment
14
14
  from weac.constants import STIFFNESS_COLLAPSE_FACTOR
15
15
  from weac.core.eigensystem import Eigensystem
@@ -49,6 +49,9 @@ class SlabTouchdown: # pylint: disable=too-many-instance-attributes,too-few-pub
49
49
  -----------
50
50
  scenario: `Scenario`
51
51
  eigensystem: `Eigensystem`
52
+ forced_mode: `TouchdownMode | None`
53
+ If provided, forces this touchdown mode instead of calculating from l_AB/l_BC.
54
+ This avoids floating-point precision issues when scenario parameters change.
52
55
 
53
56
  Attributes:
54
57
  -----------
@@ -56,7 +59,7 @@ class SlabTouchdown: # pylint: disable=too-many-instance-attributes,too-few-pub
56
59
  Length of the crack for transition of stage A to stage B [mm]
57
60
  l_BC : float
58
61
  Length of the crack for transition of stage B to stage C [mm]
59
- touchdown_mode : Literal["A_free_hanging", "B_point_contact", "C_in_contact"]
62
+ touchdown_mode : TouchdownMode
60
63
  Type of touchdown mode
61
64
  touchdown_distance : float
62
65
  Length of the touchdown segment [mm]
@@ -74,15 +77,19 @@ class SlabTouchdown: # pylint: disable=too-many-instance-attributes,too-few-pub
74
77
  straight_scenario: Scenario
75
78
  l_AB: float
76
79
  l_BC: float
77
- touchdown_mode: Literal[
78
- "A_free_hanging", "B_point_contact", "C_in_contact"
79
- ] # Three types of contact with collapsed weak layer
80
+ touchdown_mode: TouchdownMode # Three types of contact with collapsed weak layer
80
81
  touchdown_distance: float
81
82
  collapsed_weak_layer_kR: float | None = None
82
83
 
83
- def __init__(self, scenario: Scenario, eigensystem: Eigensystem):
84
+ def __init__(
85
+ self,
86
+ scenario: Scenario,
87
+ eigensystem: Eigensystem,
88
+ forced_mode: TouchdownMode | None = None,
89
+ ):
84
90
  self.scenario = scenario
85
91
  self.eigensystem = eigensystem
92
+ self._forced_mode = forced_mode
86
93
 
87
94
  # Create a new scenario config with phi=0 (flat slab) while preserving other settings
88
95
  self.flat_config = ScenarioConfig(
@@ -113,14 +120,25 @@ class SlabTouchdown: # pylint: disable=too-many-instance-attributes,too-few-pub
113
120
  self.l_BC = self._calc_l_BC()
114
121
  except ValueError:
115
122
  self.l_BC = self.scenario.L
116
- # Assign stage
117
- touchdown_mode = "A_free_hanging"
118
- if self.scenario.cut_length <= self.l_AB:
123
+
124
+ # Assign stage - use forced mode if provided, otherwise calculate from thresholds
125
+ if self._forced_mode is not None:
126
+ touchdown_mode = self._forced_mode
127
+ logger.debug(
128
+ "Using forced touchdown mode: %s (l_AB=%.2f, l_BC=%.2f, cut_length=%.2f)",
129
+ touchdown_mode,
130
+ self.l_AB,
131
+ self.l_BC,
132
+ self.scenario.cut_length,
133
+ )
134
+ else:
119
135
  touchdown_mode = "A_free_hanging"
120
- elif self.l_AB < self.scenario.cut_length <= self.l_BC:
121
- touchdown_mode = "B_point_contact"
122
- elif self.l_BC < self.scenario.cut_length:
123
- touchdown_mode = "C_in_contact"
136
+ if self.scenario.cut_length <= self.l_AB:
137
+ touchdown_mode = "A_free_hanging"
138
+ elif self.l_AB < self.scenario.cut_length <= self.l_BC:
139
+ touchdown_mode = "B_point_contact"
140
+ elif self.l_BC < self.scenario.cut_length:
141
+ touchdown_mode = "C_in_contact"
124
142
  self.touchdown_mode = touchdown_mode
125
143
 
126
144
  def _calc_touchdown_distance(self):
weac/core/system_model.py CHANGED
@@ -28,6 +28,7 @@ from weac.core.eigensystem import Eigensystem
28
28
  from weac.core.field_quantities import FieldQuantities
29
29
  from weac.core.scenario import Scenario
30
30
  from weac.core.slab import Slab
31
+ from weac.components.scenario_config import TouchdownMode
31
32
  from weac.core.slab_touchdown import SlabTouchdown
32
33
  from weac.core.unknown_constants_solver import UnknownConstantsSolver
33
34
 
@@ -164,7 +165,9 @@ class SystemModel:
164
165
  if self.config.touchdown:
165
166
  logger.info("Solving for Slab Touchdown")
166
167
  slab_touchdown = SlabTouchdown(
167
- scenario=self.scenario, eigensystem=self.eigensystem
168
+ scenario=self.scenario,
169
+ eigensystem=self.eigensystem,
170
+ forced_mode=self.config.forced_touchdown_mode,
168
171
  )
169
172
  logger.info(
170
173
  "Original cut_length: %s, touchdown_distance: %s",
@@ -335,8 +338,7 @@ class SystemModel:
335
338
  weak_layer=self.weak_layer,
336
339
  slab=self.slab,
337
340
  )
338
- if self.config.touchdown:
339
- self._invalidate_slab_touchdown()
341
+ self._invalidate_slab_touchdown()
340
342
  self._invalidate_constants()
341
343
 
342
344
  def toggle_touchdown(self, touchdown: bool):
@@ -346,6 +348,26 @@ class SystemModel:
346
348
  self._invalidate_slab_touchdown()
347
349
  self._invalidate_constants()
348
350
 
351
+ def set_forced_touchdown_mode(self, mode: TouchdownMode | None):
352
+ """
353
+ Set the forced touchdown mode.
354
+
355
+ When set, the touchdown mode calculation will use this mode instead of
356
+ calculating it from l_AB/l_BC thresholds. This avoids floating-point
357
+ precision issues when the mode boundaries are recalculated with different
358
+ scenario parameters.
359
+
360
+ Parameters
361
+ ----------
362
+ mode : TouchdownMode | None
363
+ The mode to force ("A_free_hanging", "B_point_contact", "C_in_contact"),
364
+ or None to use automatic calculation.
365
+ """
366
+ if self.config.forced_touchdown_mode != mode:
367
+ self.config.forced_touchdown_mode = mode
368
+ self._invalidate_slab_touchdown()
369
+ self._invalidate_constants()
370
+
349
371
  def _invalidate_eigensystem(self):
350
372
  """Invalidate the eigensystem."""
351
373
  self.__dict__.pop("eigensystem", None)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: weac
3
- Version: 3.1.1
3
+ Version: 3.1.3
4
4
  Summary: Weak layer anticrack nucleation model
5
5
  Author-email: 2phi GbR <mail@2phi.de>
6
6
  License-Expression: MIT
@@ -1,32 +1,32 @@
1
- weac/__init__.py,sha256=kgTwOD6mYTXI3qvj9z5uFDNJH84Toa29jQuKAu-5P_M,76
1
+ weac/__init__.py,sha256=LEEvHYM1lupYQMMcn2dSLg39Hwlksbx2UAscsPiUt3M,76
2
2
  weac/constants.py,sha256=BX8ifZhFciCuzzako1p-2Wh5CWWzR3cPdvyu501UtUs,1194
3
3
  weac/logging_config.py,sha256=GJn4Fs80dDRpbPkSPByCmIOLkEI01dbeuMMSv_IDgoM,1103
4
4
  weac/analysis/__init__.py,sha256=FDbmQLC5zmT8OJftqNYgihXc8WYB1b9FasFPGzkKVU8,498
5
5
  weac/analysis/analyzer.py,sha256=-yoOqsdQvpNvBc-U2nqB4UEKHGTMBu23lVPJqKxUVcs,29095
6
- weac/analysis/criteria_evaluator.py,sha256=yiKQV6ccgNnDMEky18zlHT3YfvoxdqCQtnPHKhbnrJA,47624
6
+ weac/analysis/criteria_evaluator.py,sha256=T4_BdWFHkw8ZpOOWdR0A4Y3GGSZHuMJdtX8bPC1mRdo,48498
7
7
  weac/analysis/plotter.py,sha256=ibkH4rzQ2pqQVXPRfek722e8eU3vP63uysb-Q-EzfC0,80556
8
- weac/components/__init__.py,sha256=94WIUVjPI3U-grN_7v0oi9bZB3Z8rCBcx9wJPOwJBAQ,439
9
- weac/components/config.py,sha256=tnOnJ0M-_knZBhdr052nDyyFFAZN0f2hQ68XRuXG6d8,869
8
+ weac/components/__init__.py,sha256=zEQCrc9q-yd0B-n1-vLhpZLQD3ZPYhAyivHySnI1zhs,475
9
+ weac/components/config.py,sha256=PTzLLmtWqazcRvkxQt4mCV1gAGAng3oNuQpBbEYc22g,1372
10
10
  weac/components/criteria_config.py,sha256=f2agU7nXWURFAw8_68igiSk5aICUxwaB9u3Qasit-Q0,2909
11
- weac/components/layer.py,sha256=kfghjavzCqzzGrkKzllMMT4qD3F0pcYfk1ZHgM6rvE0,10755
11
+ weac/components/layer.py,sha256=Ut0B9jKW4a6GVPxV43A4VCtAQJYk6ZA3MX8gt2aJBcQ,12491
12
12
  weac/components/model_input.py,sha256=oyX4p7PgaAtUXXtpvV8XO_KxwOXtG1TB0x7rXxNfCFA,3330
13
- weac/components/scenario_config.py,sha256=Tam-m9DQtdjmTm-lKQ8Dcjqje04ttJS2X3v_Nn7AUHQ,2563
13
+ weac/components/scenario_config.py,sha256=kR_YkI1fEKCs8VDQyvc118QCJnTsEFltYuDb-cpSJsc,2641
14
14
  weac/components/segment.py,sha256=F279KcAAkRuJKWav_BZ4BanO96WZm4KXtKHinFZki7s,941
15
15
  weac/core/__init__.py,sha256=pRyCKD8XD3qXVUWtFG7N3cS91P5x5d8Jpr1hMEgxQ2U,233
16
16
  weac/core/eigensystem.py,sha256=b7KXi2weCY9IVlH_7lCTXzKSx_pLdWY-x8BPjHL5nKo,13736
17
17
  weac/core/field_quantities.py,sha256=rr0KvM5Eu9AR43CQrrODJJkXkM2b2N3BWk2dE38f64c,9175
18
18
  weac/core/scenario.py,sha256=vHHe-JDWc-8ECVfy6lFGVtJmIIKRc0J9iUEGR8zckdw,6050
19
19
  weac/core/slab.py,sha256=YwbAf7ogYDn3p0nXfj3IjVqwA6ro3jBSg2wXb_io_gQ,5125
20
- weac/core/slab_touchdown.py,sha256=k30FyvclH_Q3mCZNTbJkNhSenv3ja6qSNhhkmi5p04A,14009
21
- weac/core/system_model.py,sha256=HAZuquY6p1wf5QuUPA6VOVDIICeCxOaeXqk1dSfEzNY,15513
20
+ weac/core/slab_touchdown.py,sha256=gO-nB1RntBdDuxckqnTIoFKnATheX6JeTrzxjo-6wsc,14707
21
+ weac/core/system_model.py,sha256=U7iAcVRZrUbRR-vNhRU1lKWZQwtucMLdrY-K0ZcFcbo,16418
22
22
  weac/core/unknown_constants_solver.py,sha256=kzB8351UC03rVcJWez0FAwdawI2tERbpcgqMRKgYbi8,17753
23
23
  weac/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
24
24
  weac/utils/geldsetzer.py,sha256=Rmn_PUyeomPLfxZlj9LDbdBBRDWovavrQenka318TIM,3681
25
25
  weac/utils/misc.py,sha256=lGz0IDDJ_3nvYjSkivPJ5Xscl1D_AmvQLSjaL7SUbKs,3674
26
26
  weac/utils/snow_types.py,sha256=OKSY8LzfKycSjg7uSUZkSXUzwhcw1D1fZs5S3hVQtUM,1573
27
27
  weac/utils/snowpilot_parser.py,sha256=drOLnUg7uzMJMO9qU9x79xZkqQfFPCCQonVpU9S0x8U,13682
28
- weac-3.1.1.dist-info/licenses/LICENSE,sha256=ojZPWKFHbFGDrlNOvuAKGH9WcKhpLHWZPcQ4SzhK91M,1082
29
- weac-3.1.1.dist-info/METADATA,sha256=0cdfjFenF40KllOBi5gLkyOSkdA3Ko_1LAdX43AlUK4,25593
30
- weac-3.1.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
31
- weac-3.1.1.dist-info/top_level.txt,sha256=8tyXUHPFU4Ba_5kPtpwvXo5l6GjJmOnODVBJFygpdeE,5
32
- weac-3.1.1.dist-info/RECORD,,
28
+ weac-3.1.3.dist-info/licenses/LICENSE,sha256=ojZPWKFHbFGDrlNOvuAKGH9WcKhpLHWZPcQ4SzhK91M,1082
29
+ weac-3.1.3.dist-info/METADATA,sha256=D1EzMmxGIS1qFrcq9QnI8P4vKy7Y77GAiTL_LenYvms,25593
30
+ weac-3.1.3.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
31
+ weac-3.1.3.dist-info/top_level.txt,sha256=8tyXUHPFU4Ba_5kPtpwvXo5l6GjJmOnODVBJFygpdeE,5
32
+ weac-3.1.3.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.9.0)
2
+ Generator: setuptools (80.10.2)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5