prefig 0.3.8.dev20250725054648__py3-none-any.whl → 0.3.9.dev20250727054417__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.
@@ -15,6 +15,9 @@ def set_diagram(d):
15
15
  # introduce some useful mathematical operations
16
16
  # that are meant to be available to authors
17
17
 
18
+ def ln(x):
19
+ return math.log(x)
20
+
18
21
  def dot(u, v):
19
22
  return np.dot(np.array(u), np.array(v))
20
23
 
@@ -80,6 +83,17 @@ def rotate(v, theta):
80
83
  def deriv(f, a):
81
84
  return calculus.derivative(f, a)
82
85
 
86
+ def grad(f, a):
87
+ a = list(a)
88
+ grad = []
89
+ for j in range(len(a)):
90
+ def f_trace(x):
91
+ b = a[:]
92
+ b[j] = x
93
+ return f(*b)
94
+ grad.append(calculus.derivative(f_trace, a[j]))
95
+ return np.array(grad)
96
+
83
97
  def zip_lists(a, b):
84
98
  return list(zip(a, b))
85
99
 
prefig/core/polygon.py CHANGED
@@ -188,6 +188,9 @@ def spline(element, diagram, parent, outline_status):
188
188
 
189
189
  cs = CubicSpline(t_vals, points, bc_type=bc)
190
190
 
191
+ if element.get('name', None) is not None:
192
+ un.enter_function(element.get('name'), cs)
193
+
191
194
  N = un.valid_eval(element.get('N', '100'))
192
195
  domain = element.get('domain', None)
193
196
  if domain is not None:
@@ -11,6 +11,7 @@ from . import math_utilities as math_util
11
11
  from . import calculus
12
12
 
13
13
  log = logging.getLogger('prefigure')
14
+ np.seterr(divide="ignore", invalid="ignore")
14
15
 
15
16
  # Add a graphical element for slope fields
16
17
  def slope_field(element, diagram, parent, outline_status):
@@ -140,52 +141,95 @@ def vector_field(element, diagram, parent, outline_status):
140
141
  else:
141
142
  line_template.set('stroke', element.get('stroke', 'blue'))
142
143
  line_template.set('thickness', element.get('thickness', '2'))
143
- if element.get('arrows', 'yes') == 'yes':
144
- line_template.set('arrows', '1')
144
+ line_template.set('arrows', '1')
145
145
 
146
146
  if element.get('arrow-width', None) is not None:
147
147
  line_template.set('arrow-width', element.get('arrow-width'))
148
148
  if element.get('arrow-angles', None) is not None:
149
149
  line_template.set('arrow-angles', element.get('arrow-angles'))
150
150
 
151
- spacings = element.get('spacings', None)
152
- if spacings is not None:
151
+ field_data = []
152
+ if element.get('curve', None) is not None:
153
+ curve = un.valid_eval(element.get('curve'))
153
154
  try:
154
- spacings = un.valid_eval(spacings)
155
- rx, ry = spacings
155
+ domain = un.valid_eval(element.get('domain'))
156
156
  except:
157
- log.error(f"Error parsing slope-field attribute @spacings={element.get('spacings')}")
157
+ log.error('A @domain is needed if adding a vector field to a curve')
158
+ return
159
+ try:
160
+ N = un.valid_eval(element.get('N'))
161
+ except:
162
+ log.error('A @N is needed if adding a vector field to a curve')
158
163
  return
159
- else:
160
- rx = grid_axes.find_gridspacing((bbox[0], bbox[2]))
161
- ry = grid_axes.find_gridspacing((bbox[1], bbox[3]))
162
164
 
163
- # we will go through and generate the vectors first
164
- # since we'll need to scale them
165
- field_data = []
166
- max_scale = 0
167
- x = rx[0]
168
- while x <= rx[2]:
169
- y = ry[0]
170
- while y <= ry[2]:
171
- f_value = f(x, y)
165
+ t = domain[0]
166
+ # if "f" a function of t or (x,y)?
167
+ one_variable = True
168
+ try:
169
+ f(t)
170
+ except TypeError:
171
+ one_variable = False
172
+
173
+ dt = (domain[1]-domain[0])/(N-1)
174
+ for _ in range(N):
175
+ position = curve(t)
176
+ if one_variable:
177
+ field_data.append([position, f(t)])
178
+ else:
179
+ field_data.append([position, f(*position)])
180
+ t += dt
181
+ scale_factor = un.valid_eval(element.get('scale', '1'))
182
+
183
+ else:
184
+ spacings = element.get('spacings', None)
185
+ if spacings is not None:
172
186
  try:
173
- if len(f_value) != 2:
174
- log.error("Only two-dimensional vector fields are supported")
175
- return;
187
+ spacings = un.valid_eval(spacings)
188
+ rx, ry = spacings
176
189
  except:
177
- pass
178
- max_scale = max(max_scale,
179
- abs((f_value[0])/rx[1]),
180
- abs((f_value[1])/ry[1]))
181
- field_data.append([np.array([x,y]), f_value])
182
- y += ry[1]
183
- x += rx[1]
190
+ log.error(f"Error parsing slope-field attribute @spacings={element.get('spacings')}")
191
+ return
192
+ else:
193
+ rx = grid_axes.find_gridspacing((bbox[0], bbox[2]))
194
+ ry = grid_axes.find_gridspacing((bbox[1], bbox[3]))
195
+
196
+ # we will go through and generate the vectors first
197
+ # since we'll need to scale them
198
+ max_scale = 0
199
+ exponent = un.valid_eval(element.get('exponent', '1'))
200
+ x = rx[0]
201
+ while x <= rx[2]:
202
+ y = ry[0]
203
+ while y <= ry[2]:
204
+ f_value = f(x, y)
205
+ if any(np.isnan(f_value)):
206
+ y += ry[1]
207
+ continue
184
208
 
185
- scale_factor = min(1, 0.75 / max_scale)
186
- if element.get('scale') is not None:
187
- scale = un.valid_eval(element.get('scale'))
188
- scale_factor = scale
209
+ try:
210
+ if len(f_value) != 2:
211
+ log.error("Only two-dimensional vector fields are supported")
212
+ return;
213
+ except:
214
+ pass
215
+ norm = math_util.length(f_value)
216
+ if norm < 1e-10:
217
+ f_value = np.array((0,0))
218
+ else:
219
+ # we will scale the length by length**exponent
220
+ # to promote the length of shorter vectors
221
+ f_value = norm**exponent * (1/norm * f_value)
222
+ max_scale = max(max_scale,
223
+ abs((f_value[0])/rx[1]),
224
+ abs((f_value[1])/ry[1]))
225
+ field_data.append([np.array([x,y]), f_value])
226
+ y += ry[1]
227
+ x += rx[1]
228
+
229
+ scale_factor = min(1, 0.75 / max_scale)
230
+ if element.get('scale') is not None:
231
+ scale = un.valid_eval(element.get('scale'))
232
+ scale_factor = scale
189
233
 
190
234
  for datum in field_data:
191
235
  p, v = datum
@@ -205,18 +249,3 @@ def vector_field(element, diagram, parent, outline_status):
205
249
 
206
250
  group.group(element, diagram, parent, outline_status)
207
251
 
208
- def gradient(element, diagram, parent, outline_status):
209
- try:
210
- f = un.valid_eval(element.get("function"))
211
- except:
212
- log.error("Error retrieving function in gradient element")
213
- return
214
-
215
- def grad(a, b):
216
- f_x_trace = lambda x: f(x, b)
217
- f_y_trace = lambda y: f(a, y)
218
- return np.array([calculus.derivative(f_x_trace, a),
219
- calculus.derivative(f_y_trace, b)])
220
- un.enter_namespace("__grad", grad)
221
- element.set("function", "__grad")
222
- vector_field(element, diagram, parent, outline_status)
prefig/core/tags.py CHANGED
@@ -41,11 +41,11 @@ tag_dict = {
41
41
  'caption': label.caption,
42
42
  'circle': circle.circle,
43
43
  'clip': clip.clip,
44
+ 'contour': implicit.implicit_curve,
44
45
  'coordinates': coordinates.coordinates,
45
46
  'definition': definition.definition,
46
47
  'derivative': definition.derivative,
47
48
  'ellipse': circle.ellipse,
48
- 'gradient': slope_field.gradient,
49
49
  'graph': graph.graph,
50
50
  'grid': grid_axes.grid,
51
51
  'grid-axes': grid_axes.grid_axes,
@@ -66,6 +66,8 @@ def validate_node(node, args=None):
66
66
  return True
67
67
  if isinstance(node, ast.Expression):
68
68
  return validate_node(node.body, args)
69
+ if isinstance(node, ast.Starred):
70
+ return validate_node(node.value)
69
71
  if isinstance(node, ast.Name):
70
72
  if node.id in variables:
71
73
  return True
@@ -170,6 +172,11 @@ def derivative(f, name):
170
172
  functions.add(name)
171
173
  variables.add(name)
172
174
 
175
+ def enter_function(name, f):
176
+ globals()[name] = f
177
+ functions.add(name)
178
+ variables.add(name)
179
+
173
180
  def enter_namespace(name, value):
174
181
  globals()[name] = value
175
182
  variables.add(name)
@@ -313,6 +313,7 @@ GraphicalElements =
313
313
  Area-Under-Curve* &
314
314
  Axes* &
315
315
  Circle* &
316
+ Contour* &
316
317
  Ellipse* &
317
318
  Graph* &
318
319
  Grid* &
@@ -337,7 +338,8 @@ GraphicalElements =
337
338
  Tick-Mark* &
338
339
  Tangent-line* &
339
340
  Triangle* &
340
- Vector*
341
+ Vector* &
342
+ Vector-Field*
341
343
  )
342
344
 
343
345
  Angle-Marker = element angle-marker {
@@ -433,6 +435,7 @@ Grid = element grid {
433
435
  attribute coordinates {text}?,
434
436
  attribute spacing-degrees {"yes"|"no"}?,
435
437
  attribute scales {"linear"|"semilogx"|"semilogy"|"loglog"}?,
438
+ Stroke-Attributes,
436
439
  CommonAttributes
437
440
  }
438
441
 
@@ -457,6 +460,7 @@ Grid-Axes = element grid-axes {
457
460
  attribute h-zero-label {"yes"|"no"}?,
458
461
  attribute v-zero-label {"yes"|"no"}?,
459
462
  attribute label-commas {"yes"|"no"}?,
463
+ StrokeAttributes,
460
464
  CommonAttributes,
461
465
  XLabel?,
462
466
  YLabel?
@@ -469,10 +473,21 @@ Tick-Mark = element tick-mark {
469
473
  attribute stroke {text}?,
470
474
  attribute size {text}?,
471
475
  attribute thickness {text}?,
476
+ StrokeAttributes,
472
477
  LabelAttributes,
473
478
  LabelText?
474
479
  }
475
480
 
481
+ Contour = element contour {
482
+ attribute at {text}?,
483
+ attribute function {text},
484
+ attribute k {text}?,
485
+ attribute depth {text}?,
486
+ attribute initial-depth {text}?,
487
+ StrokeAttributes,
488
+ CommonAttributes
489
+ }
490
+
476
491
  Circle = element circle {
477
492
  attribute at {text}?,
478
493
  attribute center {text},
@@ -744,6 +759,7 @@ Spline = element spline {
744
759
  attribute closed {"yes"|"no"}?,
745
760
  attribute arrow-width {text}?,
746
761
  attribute arrow-angles {text}?,
762
+ attribute name {text}?,
747
763
  FillAttributes,
748
764
  CommonAttributes
749
765
  }
@@ -781,4 +797,18 @@ Vector = element vector {
781
797
  CommonAttributes
782
798
  }
783
799
 
800
+ Vector-Field = element vector-field {
801
+ attribute at {text}?,
802
+ attribute function {text}?,
803
+ attribute spacings {text}?,
804
+ attribute scale {text}?,
805
+ attribute curve {text}?,
806
+ attribute domain {text}?,
807
+ attribute N {text}?,
808
+ attribute arrow-width {text}?,
809
+ attribute arrow-angles {text?}?,
810
+ StrokeAttributes,
811
+ CommonAttributes
812
+ }
813
+
784
814
  }
@@ -762,6 +762,9 @@
762
762
  <zeroOrMore>
763
763
  <ref name="Circle"/>
764
764
  </zeroOrMore>
765
+ <zeroOrMore>
766
+ <ref name="Contour"/>
767
+ </zeroOrMore>
765
768
  <zeroOrMore>
766
769
  <ref name="Ellipse"/>
767
770
  </zeroOrMore>
@@ -837,6 +840,9 @@
837
840
  <zeroOrMore>
838
841
  <ref name="Vector"/>
839
842
  </zeroOrMore>
843
+ <zeroOrMore>
844
+ <ref name="Vector-Field"/>
845
+ </zeroOrMore>
840
846
  </interleave>
841
847
  </define>
842
848
  <define name="Angle-Marker">
@@ -1176,6 +1182,7 @@
1176
1182
  </choice>
1177
1183
  </attribute>
1178
1184
  </optional>
1185
+ <ref name="Stroke-Attributes"/>
1179
1186
  <ref name="CommonAttributes"/>
1180
1187
  </element>
1181
1188
  </define>
@@ -1291,6 +1298,7 @@
1291
1298
  </choice>
1292
1299
  </attribute>
1293
1300
  </optional>
1301
+ <ref name="StrokeAttributes"/>
1294
1302
  <ref name="CommonAttributes"/>
1295
1303
  <optional>
1296
1304
  <ref name="XLabel"/>
@@ -1318,12 +1326,32 @@
1318
1326
  <optional>
1319
1327
  <attribute name="thickness"/>
1320
1328
  </optional>
1329
+ <ref name="StrokeAttributes"/>
1321
1330
  <ref name="LabelAttributes"/>
1322
1331
  <optional>
1323
1332
  <ref name="LabelText"/>
1324
1333
  </optional>
1325
1334
  </element>
1326
1335
  </define>
1336
+ <define name="Contour">
1337
+ <element name="contour">
1338
+ <optional>
1339
+ <attribute name="at"/>
1340
+ </optional>
1341
+ <attribute name="function"/>
1342
+ <optional>
1343
+ <attribute name="k"/>
1344
+ </optional>
1345
+ <optional>
1346
+ <attribute name="depth"/>
1347
+ </optional>
1348
+ <optional>
1349
+ <attribute name="initial-depth"/>
1350
+ </optional>
1351
+ <ref name="StrokeAttributes"/>
1352
+ <ref name="CommonAttributes"/>
1353
+ </element>
1354
+ </define>
1327
1355
  <define name="Circle">
1328
1356
  <element name="circle">
1329
1357
  <optional>
@@ -2029,6 +2057,9 @@
2029
2057
  <optional>
2030
2058
  <attribute name="arrow-angles"/>
2031
2059
  </optional>
2060
+ <optional>
2061
+ <attribute name="name"/>
2062
+ </optional>
2032
2063
  <ref name="FillAttributes"/>
2033
2064
  <ref name="CommonAttributes"/>
2034
2065
  </element>
@@ -2112,4 +2143,41 @@
2112
2143
  <ref name="CommonAttributes"/>
2113
2144
  </element>
2114
2145
  </define>
2146
+ <define name="Vector-Field">
2147
+ <element name="vector-field">
2148
+ <optional>
2149
+ <attribute name="at"/>
2150
+ </optional>
2151
+ <optional>
2152
+ <attribute name="function"/>
2153
+ </optional>
2154
+ <optional>
2155
+ <attribute name="spacings"/>
2156
+ </optional>
2157
+ <optional>
2158
+ <attribute name="scale"/>
2159
+ </optional>
2160
+ <optional>
2161
+ <attribute name="curve"/>
2162
+ </optional>
2163
+ <optional>
2164
+ <attribute name="domain"/>
2165
+ </optional>
2166
+ <optional>
2167
+ <attribute name="N"/>
2168
+ </optional>
2169
+ <optional>
2170
+ <attribute name="arrow-width"/>
2171
+ </optional>
2172
+ <optional>
2173
+ <attribute name="arrow-angles">
2174
+ <optional>
2175
+ <text/>
2176
+ </optional>
2177
+ </attribute>
2178
+ </optional>
2179
+ <ref name="StrokeAttributes"/>
2180
+ <ref name="CommonAttributes"/>
2181
+ </element>
2182
+ </define>
2115
2183
  </grammar>
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: prefig
3
- Version: 0.3.8.dev20250725054648
3
+ Version: 0.3.9.dev20250727054417
4
4
  Summary: An authoring system for mathematical diagrams
5
5
  Home-page: https://prefigure.org
6
6
  License: GPL-3.0-or-later
@@ -22,23 +22,23 @@ prefig/core/label.py,sha256=e_gOd2kcdOtcJay1VyRstP66SiDNxK2UK2-obkxQnOc,24746
22
22
  prefig/core/label_tools.py,sha256=jOawiyrKC5iQs0vq7133xNXqrkJbMqDZVHflT-hOruo,9167
23
23
  prefig/core/legend.py,sha256=0mVfyU3LvqgDCYUOlCeBD04maV-rj2h0fs1aOEBBt6c,13340
24
24
  prefig/core/line.py,sha256=HBB9cvJawKAtdubISn5maRrzFFzV0NQuBgwoQoxeXcw,6055
25
- prefig/core/math_utilities.py,sha256=HyPUmCGhPYPaL52t4uOwLkY8bfTjwDIcDU8J6z7aW38,5644
25
+ prefig/core/math_utilities.py,sha256=sMm3U9rcYKY8oZZWeJjcBokCDO4CxUkvmaX55auR4Eo,5927
26
26
  prefig/core/network.py,sha256=1izAX2AKvnj2knElrdLeojE_0Q0zO0aQM-EsEwor0Os,27217
27
27
  prefig/core/parametric_curve.py,sha256=ftxdg3gs0M0ME5iPJo3iEX7jT8PHQEMYpx8psr8Cm-w,3046
28
28
  prefig/core/parse.py,sha256=plLmR0KKrUjYx0PmHHo5HZonaaT3tW4qjiDOtzuhSkQ,4542
29
29
  prefig/core/path.py,sha256=ZWKUNgVU4qeU98Vp4WKpQoy7DehH1UmnyXA4DKRhpGo,19365
30
30
  prefig/core/point.py,sha256=a97N1soBcmYn3StZ60HBmaBi3pB1abA7sL0LNJ2nxR0,8341
31
- prefig/core/polygon.py,sha256=fh9l3XN4qxXGq9ZRskZv8yIXzGdHltIT8cI5ne_uf4o,11203
31
+ prefig/core/polygon.py,sha256=8NVdWSUVXuNE4GiPQ4MySSmLy8aCNwKUqCcfHukizME,11301
32
32
  prefig/core/read.py,sha256=Q1Nsluwysg3M5wtUmwIirfNo-Rw9-dFJPEeM4pDCpyo,1988
33
33
  prefig/core/rectangle.py,sha256=T0EMtRdLtmG1uY7Bu8kXmxQ81IGG_102g5fLCg9RuzE,3387
34
34
  prefig/core/repeat.py,sha256=DAO5w4BxUMGU-8ymsv8EwsifI0zPa_cgIRUcWWS8BWU,2755
35
35
  prefig/core/riemann_sum.py,sha256=T2dQgJIY17QuuPDOB8XWIP8HYmg5jOQ-LroFH7tiGAU,3012
36
36
  prefig/core/shape.py,sha256=Qb_-upbSHwEoYrrAnbCoFFFuVIb3JgJLdyP9ckD5evc,8675
37
- prefig/core/slope_field.py,sha256=ctkMFQ34ZFk-Hr9a8HkmKN-CUjWuZ0yutM4pN515wXk,7560
37
+ prefig/core/slope_field.py,sha256=e396uznWNaCUmOIIf70lsxvy9g_SGRFZlpxsIpy4ajE,8640
38
38
  prefig/core/statistics.py,sha256=5qN_-ABN0EFVG12ZP95uSPk82INbWRqI3w2fUdR3wsw,3458
39
- prefig/core/tags.py,sha256=vsaoRMBuxWcTF6o2xlHFCu55EhGTcuJX3jEi6-N64T8,4086
39
+ prefig/core/tags.py,sha256=fj86TjSkSpo0cAYmp0OQ83ULX9B8Nz4PRsNyZsR2JMk,4088
40
40
  prefig/core/tangent_line.py,sha256=I9wf9VAqhnmmsh8Lzynwi7_Z1DonHXqHf8ym7eO40tk,3400
41
- prefig/core/user_namespace.py,sha256=t5D_diLDPQpfek8w7al_DWI6OlAMedgHoMg45DhPJAI,6878
41
+ prefig/core/user_namespace.py,sha256=6xlkYd2g9dSiDPH0vmYj93oPzm1BFZdgyMGQ9ipKOgU,7059
42
42
  prefig/core/utilities.py,sha256=R1fBrzj-abXHG4Bh-sS0pZNC8vc9fIt6yJBcuztCVho,2905
43
43
  prefig/core/vector.py,sha256=lTw-y9mt6jqmbFxdPwQB4PYBQ9y4pGrQRcpRp9lBIbY,2917
44
44
  prefig/engine.py,sha256=Zz7j2sFxeMwPN1f3GFTpaBihqguzMNJD5iBONOVL7eQ,11972
@@ -55,13 +55,13 @@ prefig/resources/examples/tangent.xml,sha256=FLZaNz0iFoTLX6gB4pfLZFtu_TWeCug4Dda
55
55
  prefig/resources/fonts/Braille29.ttf,sha256=T4hosDvaUGMVK0Wh0BmBgWeT7sQQmLXyA3gRUR-a0oE,55880
56
56
  prefig/resources/js/mj-sre-page.js,sha256=LHVeI4dCH13bTv56nz3SKNo3JGRXa6joPM3D3wpKV40,9251
57
57
  prefig/resources/js/package.json,sha256=hwKDg76_GzkhX72T7DRiF3FoMLokCv9PSLQvnW5Ovok,116
58
- prefig/resources/schema/pf_schema.rnc,sha256=K9CY2wKcsKEQo9S480Mnt7f-qckhUWt9AFRA7-PYNi8,19104
59
- prefig/resources/schema/pf_schema.rng,sha256=24kDLnXSWgBE1_I4TM5RR1I30XJo6Cq59rVC5ygSG_8,51821
58
+ prefig/resources/schema/pf_schema.rnc,sha256=KAmcFfhLpVRVG9nFzdHcPOMdEj62aUOMs6BXqiXy7jc,19824
59
+ prefig/resources/schema/pf_schema.rng,sha256=OfOY7Pgd_G6V07v6kqRVJlvyAbyclWBSX9Q8Br97CKo,53495
60
60
  prefig/resources/template/pf_publication.xml,sha256=eEv8HACv610Apw5DSVNy0reLfELYqHlNy9Oq0GH7C_c,200
61
61
  prefig/scripts/__init__.py,sha256=qJcPi1WRh9UAwu4zIFJbmxWalAMilMYqgi6LxRkF7bI,25
62
62
  prefig/scripts/install_mj.py,sha256=5A6-oc1xbIXka5mkFE70vlp9-Rh_QoxOxGMrQi9Hkio,1219
63
- prefig-0.3.8.dev20250725054648.dist-info/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
64
- prefig-0.3.8.dev20250725054648.dist-info/METADATA,sha256=T3jXMcdrLim_prFihqU2ZP468zTdn_OLa1xOMG5PdTc,8728
65
- prefig-0.3.8.dev20250725054648.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
66
- prefig-0.3.8.dev20250725054648.dist-info/entry_points.txt,sha256=OP4ZQT71q2b0Zfbie-oM2Z1HlxpkuX7qaxJnzwsBOVQ,42
67
- prefig-0.3.8.dev20250725054648.dist-info/RECORD,,
63
+ prefig-0.3.9.dev20250727054417.dist-info/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
64
+ prefig-0.3.9.dev20250727054417.dist-info/METADATA,sha256=6USAGTlT0nCcH_I6UUkca9UtA9kQrSHhCzyf64mpVPM,8728
65
+ prefig-0.3.9.dev20250727054417.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
66
+ prefig-0.3.9.dev20250727054417.dist-info/entry_points.txt,sha256=OP4ZQT71q2b0Zfbie-oM2Z1HlxpkuX7qaxJnzwsBOVQ,42
67
+ prefig-0.3.9.dev20250727054417.dist-info/RECORD,,