restage 0.9.0__py3-none-any.whl → 0.10.0__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.
restage/emulate.py CHANGED
@@ -3,7 +3,7 @@ from pathlib import Path
3
3
  def mccode_sim_io(instr, parameters, args: dict, detectors: list[str], file=None, grid: bool = False):
4
4
  from datetime import datetime
5
5
  from restage import __version__
6
- from restage.range import parameters_to_scan
6
+ from mccode_antlr.run.range import parameters_to_scan
7
7
  if file is None:
8
8
  from io import StringIO
9
9
  file = StringIO()
@@ -44,7 +44,7 @@ def mccode_sim_io(instr, parameters, args: dict, detectors: list[str], file=None
44
44
 
45
45
  def mccode_dat_io(instr, parameters, args: dict, detectors: list[str], lines: list[str], file=None, grid: bool = False):
46
46
  from datetime import datetime
47
- from restage.range import parameters_to_scan
47
+ from mccode_antlr.run.range import parameters_to_scan
48
48
  if file is None:
49
49
  from io import StringIO
50
50
  file = StringIO()
@@ -73,7 +73,6 @@ def mccode_dat_io(instr, parameters, args: dict, detectors: list[str], lines: li
73
73
 
74
74
 
75
75
  def mccode_dat_line(directory, parameters):
76
- from math import sqrt
77
76
  from pathlib import Path
78
77
  from collections import namedtuple
79
78
  Detector = namedtuple('Detector', ['name', 'intensity', 'error', 'count', 'norm'])
restage/energy.py CHANGED
@@ -35,9 +35,9 @@ def bifrost_translate_energy_to_chopper_parameters(parameters: dict):
35
35
  # names = [a+b for a, b in product(('ps', 'fo', 'bw'), ('1', '2'))]
36
36
  chopper_parameter_present = False
37
37
  for name in product(choppers, ('speed', 'phase')):
38
- name = ''.join(name)
39
- if name not in parameters:
40
- parameters[name] = 0
38
+ n = ''.join(name)
39
+ if n not in parameters:
40
+ parameters[n] = 0
41
41
  else:
42
42
  chopper_parameter_present = True
43
43
  order = get_and_remove(parameters, 'order', 14)
@@ -51,9 +51,9 @@ def cspec_translate_energy_to_chopper_parameters(parameters: dict):
51
51
  choppers = ('bw1', 'bw2', 'bw3', 's', 'p', 'm1', 'm2')
52
52
  chopper_parameter_present = False
53
53
  for name in product(choppers, ('speed', 'phase')):
54
- name = ''.join(name)
55
- if name not in parameters:
56
- parameters[name] = 0
54
+ n = ''.join(name)
55
+ if n not in parameters:
56
+ parameters[n] = 0
57
57
  else:
58
58
  chopper_parameter_present = True
59
59
  time = get_and_remove(parameters, 'time', 0.004)
restage/run.py CHANGED
@@ -1,6 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
- from .range import Singular
3
+ from mccode_antlr.run.range import Singular
4
4
 
5
5
 
6
6
  def make_run_parser():
@@ -19,7 +19,7 @@ def parse_run_parameters(unparsed: list[str]) -> dict[str, Singular]:
19
19
 
20
20
  :parameter unparsed: A list of parameters.
21
21
  """
22
- from .range import parse_list
22
+ from mccode_antlr.run.range import parse_list
23
23
  return parse_list(Singular, unparsed)
24
24
 
25
25
 
restage/scan.py CHANGED
@@ -15,7 +15,7 @@ def make_scan_parser():
15
15
 
16
16
 
17
17
  def parse_scan():
18
- from .range import parse_scan_parameters
18
+ from mccode_antlr.run.range import parse_scan_parameters
19
19
  args = make_scan_parser().parse_args()
20
20
  parameters = parse_scan_parameters(args.parameters)
21
21
  return args, parameters
@@ -29,7 +29,7 @@ def run_point(args, parameters):
29
29
  def entrypoint():
30
30
  """Entrypoint for the restage_scan command."""
31
31
  from .energy import bifrost_translate_energy_to_chopper_parameters
32
- from .range import parameters_to_scan
32
+ from mccode_antlr.run.range import parameters_to_scan
33
33
  args, parameters = parse_scan()
34
34
  n_points, names, scan = parameters_to_scan(parameters)
35
35
  for i, p in enumerate(scan):
restage/splitrun.py CHANGED
@@ -41,11 +41,11 @@ def si_int_limits(s: str) -> tuple[Optional[int], int, Optional[int]]:
41
41
  low, high = None, None
42
42
  min_seps, max_seps = (']', '-', '}'), ('[', '+', '{')
43
43
  if any(x in s for x in min_seps):
44
- low, s = s.split(next(x for x in min_seps if x in s), maxsplit=1)
45
- low = si_int(low)
44
+ low_s, s = s.split(next(x for x in min_seps if x in s), maxsplit=1)
45
+ low = si_int(low_s)
46
46
  if any(x in s for x in max_seps):
47
- s, high = s.split(next(x for x in max_seps if x in s), maxsplit=1)
48
- high = si_int(high)
47
+ s, high_s = s.split(next(x for x in max_seps if x in s), maxsplit=1)
48
+ high = si_int(high_s)
49
49
  return low, si_int(s), high
50
50
 
51
51
  def make_splitrun_parser():
@@ -162,7 +162,7 @@ def args_fixup(args):
162
162
  return args
163
163
 
164
164
  def parse_splitrun(parser):
165
- from .range import parse_scan_parameters
165
+ from mccode_antlr.run.range import parse_scan_parameters
166
166
  from mccode_antlr.run.runner import sort_args
167
167
  import sys
168
168
  sys.argv[1:] = sort_args(sys.argv[1:])
@@ -228,14 +228,18 @@ def splitrun(instr, parameters, precision: dict[str, float], split_at=None, grid
228
228
  log.error(f'The specified split-at component, {split_at}, does not exist in the instrument file')
229
229
  # splitting defines an instrument parameter in both returned instrument, 'mcpl_filename'.
230
230
  if mcpl_output_parameters is not None:
231
- mcpl_output_parameters = tuple(ComponentParameter(k, Expr.parse(v)) for k, v in mcpl_output_parameters.items())
231
+ output_parameters = tuple(ComponentParameter(k, Expr.parse(v)) for k, v in mcpl_output_parameters.items())
232
+ else:
233
+ output_parameters = None
232
234
  if mcpl_input_parameters is not None:
233
- mcpl_input_parameters = tuple(ComponentParameter(k, Expr.parse(v)) for k, v in mcpl_input_parameters.items())
235
+ input_parameters = tuple(ComponentParameter(k, Expr.parse(v)) for k, v in mcpl_input_parameters.items())
236
+ else:
237
+ input_parameters = None
234
238
  pre, post = instr.mcpl_split(split_at,
235
239
  output_component=mcpl_output_component,
236
- output_parameters=mcpl_output_parameters,
240
+ output_parameters=output_parameters,
237
241
  input_component=mcpl_input_component,
238
- input_parameters=mcpl_input_parameters,
242
+ input_parameters=input_parameters,
239
243
  remove_unused_parameters=True
240
244
  )
241
245
  if output_split_instrs:
@@ -270,7 +274,7 @@ def splitrun_pre(instr, parameters, grid, precision: dict[str, float],
270
274
  from functools import partial
271
275
  from .cache import cache_instr
272
276
  from .energy import energy_to_chopper_translator
273
- from .range import parameters_to_scan
277
+ from mccode_antlr.run.range import parameters_to_scan
274
278
  # check if this instr is already represented in the module's cache database
275
279
  # if not, it is compiled and added to the cache with (hopefully sensible) defaults specified
276
280
  entry = cache_instr(instr, mpi=parallel, acc=gpu)
@@ -319,7 +323,7 @@ def splitrun_combined(pre_entry, pre, post, pre_parameters, post_parameters, gri
319
323
  from pathlib import Path
320
324
  from .cache import cache_instr, cache_get_simulation
321
325
  from .energy import energy_to_chopper_translator
322
- from .range import parameters_to_scan
326
+ from mccode_antlr.run.range import parameters_to_scan
323
327
  from .instr import collect_parameter_dict
324
328
  from .tables import best_simulation_entry_match
325
329
  from .emulate import mccode_sim_io, mccode_dat_io, mccode_dat_line
@@ -488,7 +492,9 @@ def repeat_simulation_until(count, runner, args: dict, parameters, work_dir: Pat
488
492
  if 'seed' in args and args['seed'] is not None:
489
493
  random.seed(args['seed'])
490
494
 
491
- files, outputs, counts = [], [], []
495
+ files: list[Path] = []
496
+ outputs: list[Path] = []
497
+ counts: list[int] = []
492
498
  total_count = 0
493
499
  while goal - sum(counts) > 0:
494
500
  if len(counts) and counts[-1] <= 0:
@@ -1,23 +1,23 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: restage
3
- Version: 0.9.0
3
+ Version: 0.10.0
4
4
  Author-email: Gregory Tucker <gregory.tucker@ess.eu>
5
5
  License: BSD-3-Clause
6
6
  Classifier: License :: OSI Approved :: BSD License
7
7
  Classifier: Programming Language :: Python :: 3
8
8
  Classifier: Programming Language :: Python :: 3 :: Only
9
- Classifier: Programming Language :: Python :: 3.9
10
9
  Classifier: Programming Language :: Python :: 3.10
11
10
  Classifier: Programming Language :: Python :: 3.11
12
11
  Classifier: Programming Language :: Python :: 3.12
13
12
  Classifier: Programming Language :: Python :: 3.13
13
+ Classifier: Programming Language :: Python :: 3.14
14
14
  Requires-Python: >=3.9
15
15
  Description-Content-Type: text/markdown
16
16
  Requires-Dist: zenlog>=1.1
17
17
  Requires-Dist: platformdirs>=3.11
18
18
  Requires-Dist: confuse
19
19
  Requires-Dist: psutil>=5.9.6
20
- Requires-Dist: mccode-antlr[hdf5]>=0.16.1
20
+ Requires-Dist: mccode-antlr[hdf5]>=0.16.2
21
21
  Provides-Extra: test
22
22
  Requires-Dist: pytest; extra == "test"
23
23
  Requires-Dist: chopcal>=0.4.0; extra == "test"
@@ -0,0 +1,20 @@
1
+ restage/__init__.py,sha256=HlqvPpL7DKet00NAFyqJBNg9UFO7o05Gt2tFyKBQcsY,744
2
+ restage/bifrost_choppers.py,sha256=xQu21g2NcTLPpZ0ZWOuvN20zh07EWoO4QVoTnoORwZI,6443
3
+ restage/cache.py,sha256=wh8b66aUDtOu38L-B-tqLs-bMtrnbWmuhy_HaKRYOsA,8102
4
+ restage/cspec_choppers.py,sha256=ZWxyCcwYn4z9ZNqj_r6RC9ImbhVjYc1fmv-Ijm8A2Yk,206
5
+ restage/database.py,sha256=anyOby31fUN7rGAVNsnWDUhAISV0vQ7en8aQwVS5ZwA,11051
6
+ restage/emulate.py,sha256=dcxEZsOgNBtCpTQeIol9O-zZqq3bueAR0ig_Wl5oMMY,6156
7
+ restage/energy.py,sha256=od_YiV6e6UJEJMHrxxIvUv6NxpgxitH80ycKjH7V3A8,3353
8
+ restage/instr.py,sha256=9yiV7Pve4XJrh2mIKJkLGtLa1fjUJiECtPhC76HQM2g,2628
9
+ restage/mcpl.py,sha256=u7ixerJs4lqKSW2MYndZ2Xpsk8O0S-ZVo735YIy86gc,3223
10
+ restage/run.py,sha256=A7Q1x8FHbEcR2LedzI9H8tRzTjcGBV6vlwzgefSbPTk,1507
11
+ restage/scan.py,sha256=2U6MHOoxr0X4ecBiTY5UThbJB6aqMXNALq92VeqVmwU,1464
12
+ restage/splitrun.py,sha256=hUqVYlrpUrXIC3DHOmYoPxKtuuOUmxzHEQlKp5kkoBA,27957
13
+ restage/tables.py,sha256=vQf0GkM7ojQbWee_P_Xqfx0-lXLym7x6kyam8CWpB5s,16373
14
+ restage/config/__init__.py,sha256=zFRT9QXgpUJpBncELCQ6by1-kjYp8Li1yJDfqxkHxAA,965
15
+ restage/config/default.yaml,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
16
+ restage-0.10.0.dist-info/METADATA,sha256=3rXkDG3ZBKGpoQ0q_FiCBCiXeSPZNAEPIBuvMzNV6B8,7443
17
+ restage-0.10.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
18
+ restage-0.10.0.dist-info/entry_points.txt,sha256=vYNOPxJ4PzG-1GGFSd08jFxhrtKUWAdWzjJQeFBzFJE,116
19
+ restage-0.10.0.dist-info/top_level.txt,sha256=iM_pb-taTZ0S2WMoDnt_qDMZoNMjmM19z3tTCuVm1IE,8
20
+ restage-0.10.0.dist-info/RECORD,,
restage/range.py DELETED
@@ -1,231 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from typing import Union
4
-
5
-
6
- class MRange:
7
- """A range of values for a parameter in a MATLAB style.
8
- The range is inclusive of the start and stop values, and the step is the difference between items in the range.
9
- """
10
- def __init__(self, start, stop, step):
11
- self.start = start
12
- self.stop = stop
13
- self.step = step
14
- if self.start == self.stop:
15
- raise ValueError(f'MRange start and stop values are equal: {self.start} '
16
- f'`list(MRange)` will be empty! Use a `Singular({self.start}, 1)` range instead.')
17
- if self.step == 0:
18
- raise ZeroDivisionError('MRange step cannot be zero')
19
-
20
- def __eq__(self, other):
21
- return self.start == other.start and self.stop == other.stop and self.step == other.step
22
-
23
- @property
24
- def min(self):
25
- return self.start
26
-
27
- @property
28
- def max(self):
29
- return self.stop
30
-
31
- def __iter__(self):
32
- def range_gen(start, stop, step):
33
- v = start
34
- i = 0
35
- while (step > 0 and v + step <= stop) or (step < 0 and v + step >= stop):
36
- v = i * step + start
37
- i += 1
38
- yield v
39
- return range_gen(self.start, self.stop, self.step)
40
-
41
- def __getitem__(self, index: int):
42
- if index < 0 or index >= len(self):
43
- raise IndexError(f'Index {index} out of range')
44
- return index * self.step + self.start
45
-
46
- def __str__(self):
47
- return f'{self.start}:{self.step}:{self.stop}'
48
-
49
- def __repr__(self):
50
- return f'MStyleRange({self})'
51
-
52
- def __len__(self):
53
- return int((self.stop - self.start) / self.step) + 1
54
-
55
- @classmethod
56
- def from_str(cls, string):
57
- """Parse a string in MATLAB style into a range.
58
- The string should be of the form start:step:stop
59
- """
60
- def float_or_int(s):
61
- try:
62
- return int(s)
63
- except ValueError:
64
- pass
65
- return float(s)
66
-
67
- if string.count(':') > 2:
68
- raise ValueError(f'Range string {string} contains more than two colons')
69
- step = '1'
70
- if ':' not in string:
71
- start, stop = string, string
72
- elif string.count(':') == 1:
73
- start, stop = string.split(':')
74
- else:
75
- start, step, stop = string.split(':')
76
- return cls(float_or_int(start), float_or_int(stop), float_or_int(step))
77
-
78
-
79
- class Singular:
80
- """A singular range parameter for use with other range parameters in, e.g., a zip.
81
-
82
- Note:
83
- The Singular range value will be repeated up to `maximum` times in an iterator.
84
- If `maximum` is None, the Singular range will be repeated forever.
85
- Therefore, care must be taken to ensure that the Singular range is used in a zip with a range that is
86
- not infinite.
87
- """
88
- def __init__(self, value, maximum=None):
89
- self.value = value
90
- self.maximum = maximum
91
-
92
- def __eq__(self, other):
93
- return self.value == other.value and self.maximum == other.maximum
94
-
95
- def __str__(self):
96
- return f'{self.value}(up to {self.maximum} times)'
97
-
98
- def __repr__(self):
99
- return f'Singular({self.value}, {self.maximum})'
100
-
101
- @property
102
- def min(self):
103
- return self.value
104
-
105
- @property
106
- def max(self):
107
- return self.value
108
-
109
- def __iter__(self):
110
- def forever():
111
- while True:
112
- yield self.value
113
-
114
- def until():
115
- i = 0
116
- while i < self.maximum:
117
- i += 1
118
- yield self.value
119
-
120
- return until() if self.maximum is not None else forever()
121
-
122
- def __len__(self):
123
- return self.maximum
124
-
125
- @classmethod
126
- def from_str(cls, string):
127
- def float_or_int_or_str(s):
128
- try:
129
- return int(s)
130
- except ValueError:
131
- pass
132
- try:
133
- return float(s)
134
- except ValueError:
135
- return s
136
-
137
- if string.count(':') > 0:
138
- raise ValueError(f'Singular string {string} contains a colon')
139
- return cls(float_or_int_or_str(string))
140
-
141
-
142
- def parse_list(range_type, unparsed: list[str]):
143
- ranges = {}
144
- while len(unparsed):
145
- if '=' in unparsed[0]:
146
- k, v = unparsed[0].split('=', 1)
147
- ranges[k.lower()] = range_type.from_str(v)
148
- elif len(unparsed) > 1 and '=' not in unparsed[1]:
149
- ranges[unparsed[0].lower()] = range_type.from_str(unparsed[1])
150
- del unparsed[1]
151
- else:
152
- raise ValueError(f'Invalid parameter: {unparsed[0]}')
153
- del unparsed[0]
154
- return ranges
155
-
156
-
157
- def parameters_to_scan(parameters: dict[str, Union[list, MRange, Singular]], grid: bool = False):
158
- """Convert a dictionary of ranged parameters to a list of parameter names and an iterable of parameter value tuples.
159
-
160
- The ranged parameters can be either MRange objects or lists of values. If a list of values is provided, it will be
161
- iterated over directly.
162
-
163
- :parameter parameters: A dictionary of ranged parameters.
164
- :parameter grid: Controls how the parameters are iterated; True implies a grid scan, False implies a linear scan.
165
- """
166
- if grid:
167
- for k, v in parameters.items():
168
- if isinstance(v, Singular):
169
- parameters[k] = Singular(v.value, 1)
170
-
171
- names = [x.lower() for x in parameters.keys()]
172
- values = [x if hasattr(x, '__iter__') else [x] for x in parameters.values()]
173
- if not len(values):
174
- return 0, names, []
175
- elif grid:
176
- from itertools import product
177
- from math import prod
178
- # singular MRange objects *should* stop the grid along their axis:
179
- n_pts = prod([len(v) for v in values])
180
- return n_pts, names, product(*values)
181
- else:
182
- # replace singular MRange entries with Singular iterators, to avoid stopping the zip early:
183
- n_max = max([len(v) for v in values])
184
- for i, v in enumerate(values):
185
- if len(v) > 1 and len(v) != n_max:
186
- oth = [names[i] for i, n in enumerate(values) if len(n) == n_max]
187
- par = 'parameters' if len(oth) > 1 else 'parameter'
188
- have = 'have' if len(oth) > 1 else 'has'
189
- raise ValueError(f'Parameter {names[i]} has {len(v)} values, but {par} {", ".join(oth)} {have} {n_max}')
190
- return n_max, names, zip(*[v if len(v) > 1 else Singular(v[0] if isinstance(v, MRange) else v.value, n_max) for v in values])
191
-
192
-
193
- def _MRange_or_Singular(s: str):
194
- if ':' in s:
195
- return MRange.from_str(s)
196
- return Singular.from_str(s)
197
-
198
-
199
- def parse_command_line_parameters(unparsed: list[str]) -> dict[str, Union[Singular, MRange]]:
200
- """Parse a list of input parameters into a dictionary of MRange objects.
201
-
202
- :parameter unparsed: A list of parameters.
203
- """
204
- ranges = {}
205
- index = 0
206
- while index < len(unparsed):
207
- if '=' in unparsed[index]:
208
- k, v = unparsed[index].split('=', 1)
209
- ranges[k.lower()] = _MRange_or_Singular(v)
210
- elif index + 1 < len(unparsed) and '=' not in unparsed[index + 1]:
211
- ranges[unparsed[index].lower()] = _MRange_or_Singular(unparsed[index + 1])
212
- index += 1
213
- else:
214
- raise ValueError(f'Invalid parameter: {unparsed[index]}')
215
- index += 1
216
- return ranges
217
-
218
-
219
- def parse_scan_parameters(unparsed: list[str]) -> dict[str, MRange | Singular]:
220
- """Parse a list of input parameters into a dictionary of MRange or Singular objects.
221
-
222
- :parameter unparsed: A list of parameters.
223
- :return: A dictionary of MRange or Singular objects. The Singular objects have their maximum length set to the
224
- maximum iterations of all the ranges to avoid infinite iterations.
225
- """
226
- ranges = parse_command_line_parameters(unparsed)
227
- max_length = max(len(v) if isinstance(v, MRange) else 1 for v in ranges.values())
228
- for k, v in ranges.items():
229
- if isinstance(v, Singular) and v.maximum is None:
230
- ranges[k] = Singular(v.value, max_length)
231
- return ranges
@@ -1,21 +0,0 @@
1
- restage/__init__.py,sha256=HlqvPpL7DKet00NAFyqJBNg9UFO7o05Gt2tFyKBQcsY,744
2
- restage/bifrost_choppers.py,sha256=xQu21g2NcTLPpZ0ZWOuvN20zh07EWoO4QVoTnoORwZI,6443
3
- restage/cache.py,sha256=wh8b66aUDtOu38L-B-tqLs-bMtrnbWmuhy_HaKRYOsA,8102
4
- restage/cspec_choppers.py,sha256=ZWxyCcwYn4z9ZNqj_r6RC9ImbhVjYc1fmv-Ijm8A2Yk,206
5
- restage/database.py,sha256=anyOby31fUN7rGAVNsnWDUhAISV0vQ7en8aQwVS5ZwA,11051
6
- restage/emulate.py,sha256=VrhfZJIbECdbDS-MHklqRuAIy9cRkjZkwPBTKQSQoe0,6164
7
- restage/energy.py,sha256=w78GUIWcHxANvBl2DTu73FQFawCXfzlK6L32TBQNt4g,3371
8
- restage/instr.py,sha256=9yiV7Pve4XJrh2mIKJkLGtLa1fjUJiECtPhC76HQM2g,2628
9
- restage/mcpl.py,sha256=u7ixerJs4lqKSW2MYndZ2Xpsk8O0S-ZVo735YIy86gc,3223
10
- restage/range.py,sha256=TjOf4DSKfgoAIcrWQvv6MrtksQpnGJHdsEjVI5K-UfI,8116
11
- restage/run.py,sha256=bTcQIN9edKMXU_eFdX3E_mtJjwemoARrIUmZqzEGf0E,1475
12
- restage/scan.py,sha256=Yx8OQSBG6I2_64sW0LIDb0glVKwWoxUQQznASXgDZFQ,1432
13
- restage/splitrun.py,sha256=5mTSkw-Mm0yq6GAq6oG0NNU7ajVkp_hvLvdcx_HlCj0,27793
14
- restage/tables.py,sha256=vQf0GkM7ojQbWee_P_Xqfx0-lXLym7x6kyam8CWpB5s,16373
15
- restage/config/__init__.py,sha256=zFRT9QXgpUJpBncELCQ6by1-kjYp8Li1yJDfqxkHxAA,965
16
- restage/config/default.yaml,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
- restage-0.9.0.dist-info/METADATA,sha256=TXVZ4jlhvX8gqgMFqCqMAL3m1Yyg8uTpncnbFKe7l40,7441
18
- restage-0.9.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
19
- restage-0.9.0.dist-info/entry_points.txt,sha256=vYNOPxJ4PzG-1GGFSd08jFxhrtKUWAdWzjJQeFBzFJE,116
20
- restage-0.9.0.dist-info/top_level.txt,sha256=iM_pb-taTZ0S2WMoDnt_qDMZoNMjmM19z3tTCuVm1IE,8
21
- restage-0.9.0.dist-info/RECORD,,