holobench 1.8.0__py2.py3-none-any.whl → 1.9.0__py2.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.
bencher/bench_runner.py CHANGED
@@ -103,7 +103,7 @@ class BenchRunner:
103
103
  for r in range(1, repeats + 1):
104
104
  for lvl in range(min_level, max_level + 1):
105
105
  if grouped:
106
- report_level = BenchReport(f"{self.name}_{run_cfg.run_tag}")
106
+ report_level = BenchReport(f"{run_cfg.run_tag}_{self.name}")
107
107
 
108
108
  for bch_fn in self.bench_fns:
109
109
  run_lvl = deepcopy(run_cfg)
@@ -114,6 +114,7 @@ class BenchRunner:
114
114
  res = bch_fn(run_lvl, report_level)
115
115
  else:
116
116
  res = bch_fn(run_lvl, BenchReport())
117
+ res.report.bench_name = f"{run_cfg.run_tag}_{res.report.bench_name}"
117
118
  self.show_publish(res.report, show, publish, save, debug)
118
119
  self.results.append(res)
119
120
  if grouped:
bencher/bencher.py CHANGED
@@ -175,8 +175,13 @@ class Bench(BenchPlotServer):
175
175
  self.plot_callbacks = []
176
176
  self.plot = True
177
177
 
178
- def add_plot_callback(self, callback: Callable[[BenchResult], pn.panel]) -> None:
179
- self.plot_callbacks.append(callback)
178
+ def add_plot_callback(self, callback: Callable[[BenchResult], pn.panel], **kwargs) -> None:
179
+ """Add a plotting callback that will be called on any result produced when calling a sweep funciton. You can pass additional arguments to the plotting function with kwargs. e.g. add_plot_callback(bch.BenchResult.to_video_grid,)
180
+
181
+ Args:
182
+ callback (Callable[[BenchResult], pn.panel]): _description_
183
+ """
184
+ self.plot_callbacks.append(partial(callback, **kwargs))
180
185
 
181
186
  def set_worker(self, worker: Callable, worker_input_cfg: ParametrizedSweep = None) -> None:
182
187
  """Set the benchmark worker function and optionally the type the worker expects
@@ -18,6 +18,7 @@ class BenchPolygons(bch.ParametrizedSweep):
18
18
  linestyle = bch.StringSweep(["solid", "dashed", "dotted"])
19
19
  color = bch.StringSweep(["red", "green", "blue"])
20
20
  polygon = bch.ResultImage()
21
+ area = bch.ResultVar()
21
22
  # hmap = bch.ResultHmap()
22
23
 
23
24
  def __call__(self, **kwargs):
@@ -25,6 +26,7 @@ class BenchPolygons(bch.ParametrizedSweep):
25
26
  points = polygon_points(self.radius, self.sides)
26
27
  # self.hmap = hv.Curve(points)
27
28
  self.polygon = self.points_to_polygon_png(points, bch.gen_image_path("polygon"))
29
+ self.area = self.radius * self.sides
28
30
  return super().__call__()
29
31
 
30
32
  def points_to_polygon_png(self, points: list[float], filename: str):
@@ -52,17 +54,26 @@ class BenchPolygons(bch.ParametrizedSweep):
52
54
  def example_image(
53
55
  run_cfg: bch.BenchRunCfg = bch.BenchRunCfg(), report: bch.BenchReport = bch.BenchReport()
54
56
  ) -> bch.Bench:
57
+ run_cfg.use_cache = False
55
58
  bench = bch.Bench("polygons", BenchPolygons(), run_cfg=run_cfg, report=report)
56
59
 
60
+ bench.result_vars = ["polygon", "area"]
61
+
62
+ bench.add_plot_callback(bch.BenchResult.to_sweep_summary)
63
+ # bench.add_plot_callback(bch.BenchResult.to_auto, level=2)
64
+ bench.add_plot_callback(bch.BenchResult.to_panes, level=3)
65
+ # bench.add_plot_callback(bch.BenchResult.to_panes)
66
+
57
67
  sweep_vars = ["sides", "radius", "linewidth", "color"]
68
+
69
+ # sweep_vars = ["sides", "radius" ]
70
+
58
71
  for i in range(1, len(sweep_vars)):
59
72
  s = sweep_vars[:i]
60
73
  bench.plot_sweep(
61
74
  f"Polygons Sweeping {len(s)} Parameters",
62
75
  input_vars=s,
63
- result_vars=[BenchPolygons.param.polygon],
64
76
  )
65
-
66
77
  return bench
67
78
 
68
79
 
@@ -97,6 +108,6 @@ if __name__ == "__main__":
97
108
  # ex_run_cfg.debug = True
98
109
  # ex_run_cfg.repeats = 2
99
110
  ex_run_cfg.level = 4
100
- example_image_vid(ex_run_cfg).report.show()
111
+ # example_image_vid(ex_run_cfg).report.show()
101
112
  # example_image_vid_sequential(ex_run_cfg).report.show()
102
- # example_image(ex_run_cfg).report.show()
113
+ example_image(ex_run_cfg).report.show()
@@ -10,6 +10,8 @@ import panel as pn
10
10
  from bencher.utils import int_to_col, color_tuple_to_css, callable_name
11
11
 
12
12
  from bencher.variables.parametrised_sweep import ParametrizedSweep
13
+ from bencher.variables.inputs import with_level
14
+
13
15
  from bencher.variables.results import OptDir
14
16
  from copy import deepcopy
15
17
  from bencher.results.optuna_result import OptunaResult
@@ -21,6 +23,7 @@ from bencher.variables.results import (
21
23
  )
22
24
 
23
25
  from bencher.results.composable_container.composable_container_panel import ComposableContainerPanel
26
+ from bencher.utils import listify
24
27
 
25
28
  # todo add plugins
26
29
  # https://gist.github.com/dorneanu/cce1cd6711969d581873a88e0257e312
@@ -54,7 +57,7 @@ class BenchResultBase(OptunaResult):
54
57
  return self.ds.count()
55
58
 
56
59
  def to_hv_dataset(
57
- self, reduce: ReduceType = ReduceType.AUTO, result_var: ResultVar = None
60
+ self, reduce: ReduceType = ReduceType.AUTO, result_var: ResultVar = None, level: int = None
58
61
  ) -> hv.Dataset:
59
62
  """Generate a holoviews dataset from the xarray dataset.
60
63
 
@@ -67,11 +70,11 @@ class BenchResultBase(OptunaResult):
67
70
 
68
71
  if reduce == ReduceType.NONE:
69
72
  kdims = [i.name for i in self.bench_cfg.all_vars]
70
- return hv.Dataset(self.to_dataset(reduce, result_var), kdims=kdims)
71
- return hv.Dataset(self.to_dataset(reduce, result_var))
73
+ return hv.Dataset(self.to_dataset(reduce, result_var, level), kdims=kdims)
74
+ return hv.Dataset(self.to_dataset(reduce, result_var, level))
72
75
 
73
76
  def to_dataset(
74
- self, reduce: ReduceType = ReduceType.AUTO, result_var: ResultVar = None
77
+ self, reduce: ReduceType = ReduceType.AUTO, result_var: ResultVar = None, level: int = None
75
78
  ) -> xr.Dataset:
76
79
  """Generate a summarised xarray dataset.
77
80
 
@@ -84,20 +87,25 @@ class BenchResultBase(OptunaResult):
84
87
  if reduce == ReduceType.AUTO:
85
88
  reduce = ReduceType.REDUCE if self.bench_cfg.repeats > 1 else ReduceType.SQUEEZE
86
89
 
87
- ds = self.ds if result_var is None else self.ds[result_var.name]
90
+ ds_out = self.ds if result_var is None else self.ds[result_var.name]
88
91
 
89
92
  match (reduce):
90
93
  case ReduceType.REDUCE:
91
- ds_reduce_mean = ds.mean(dim="repeat", keep_attrs=True)
92
- ds_reduce_std = ds.std(dim="repeat", keep_attrs=True)
94
+ ds_reduce_mean = ds_out.mean(dim="repeat", keep_attrs=True)
95
+ ds_reduce_std = ds_out.std(dim="repeat", keep_attrs=True)
93
96
 
94
97
  for v in ds_reduce_mean.data_vars:
95
98
  ds_reduce_mean[f"{v}_std"] = ds_reduce_std[v]
96
- return ds_reduce_mean
99
+ ds_out = ds_reduce_mean
97
100
  case ReduceType.SQUEEZE:
98
- return ds.squeeze(drop=True)
99
- case _:
100
- return ds
101
+ ds_out = ds_out.squeeze(drop=True)
102
+ if level is not None:
103
+ coords_no_repeat = {}
104
+ for c, v in ds_out.coords.items():
105
+ if c != "repeat":
106
+ coords_no_repeat[c] = with_level(v.to_numpy(), level)
107
+ return ds_out.sel(coords_no_repeat)
108
+ return ds_out
101
109
 
102
110
  def get_optimal_vec(
103
111
  self,
@@ -405,6 +413,45 @@ class BenchResultBase(OptunaResult):
405
413
  return container(val, styles={"background": "white"}, **kwargs)
406
414
  return val
407
415
 
416
+ @staticmethod
417
+ def select_level(
418
+ dataset: xr.Dataset,
419
+ level: int,
420
+ include_types: List[type] = None,
421
+ exclude_names: List[str] = None,
422
+ ) -> xr.Dataset:
423
+ """Given a dataset, return a reduced dataset that only contains data from a specified level. By default all types of variables are filtered at the specified level. If you only want to get a reduced level for some types of data you can pass in a list of types to get filtered, You can also pass a list of variables names to exclude from getting filtered
424
+ Args:
425
+ dataset (xr.Dataset): dataset to filter
426
+ level (int): desired data resolution level
427
+ include_types (List[type], optional): Only filter data of these types. Defaults to None.
428
+ exclude_names (List[str], optional): Only filter data with these variable names. Defaults to None.
429
+
430
+ Returns:
431
+ xr.Dataset: A reduced dataset at the specified level
432
+
433
+ Example: a dataset with float_var: [1,2,3,4,5] cat_var: [a,b,c,d,e]
434
+
435
+ select_level(ds,2) -> [1,5] [a,e]
436
+ select_level(ds,2,(float)) -> [1,5] [a,b,c,d,e]
437
+ select_level(ds,2,exclude_names=["cat_var]) -> [1,5] [a,b,c,d,e]
438
+
439
+ see test_bench_result_base.py -> test_select_level()
440
+ """
441
+ coords_no_repeat = {}
442
+ for c, v in dataset.coords.items():
443
+ if c != "repeat":
444
+ vals = v.to_numpy()
445
+ print(vals.dtype)
446
+ include = True
447
+ if include_types is not None and vals.dtype not in listify(include_types):
448
+ include = False
449
+ if exclude_names is not None and c in listify(exclude_names):
450
+ include = False
451
+ if include:
452
+ coords_no_repeat[c] = with_level(v.to_numpy(), level)
453
+ return dataset.sel(coords_no_repeat)
454
+
408
455
  # MAPPING TO LOWER LEVEL BENCHCFG functions so they are available at a top level.
409
456
  def to_sweep_summary(self, **kwargs):
410
457
  return self.bench_cfg.to_sweep_summary(**kwargs)
@@ -36,9 +36,11 @@ class ComposableContainerBase:
36
36
  return f"{var_value}"
37
37
  return None
38
38
 
39
- def __init__(self, horizontal: bool = True) -> None:
39
+ def __init__(
40
+ self, horizontal: bool = True, compose_method: ComposeType = ComposeType.right
41
+ ) -> None:
40
42
  self.horizontal: bool = horizontal
41
- self.compose_method = ComposeType.right
43
+ self.compose_method = compose_method
42
44
  self.container = []
43
45
 
44
46
  def append(self, obj: Any) -> None:
@@ -130,6 +130,7 @@ class HoloviewResult(PanelResult):
130
130
  float_range=VarRange(1, 1),
131
131
  cat_range=VarRange(0, None),
132
132
  repeats_range=VarRange(1, 1),
133
+ panel_range=VarRange(0, None),
133
134
  reduce=ReduceType.SQUEEZE,
134
135
  target_dimension=2,
135
136
  result_var=result_var,
@@ -2,6 +2,7 @@ from typing import Optional
2
2
  from functools import partial
3
3
  import panel as pn
4
4
  from param import Parameter
5
+ import holoviews as hv
5
6
  from bencher.results.bench_result_base import BenchResultBase, ReduceType
6
7
  from bencher.results.video_result import VideoControls
7
8
  from bencher.variables.results import (
@@ -18,13 +19,23 @@ class PanelResult(BenchResultBase):
18
19
  )
19
20
 
20
21
  def to_panes(
21
- self, result_var: Parameter = None, target_dimension: int = 0, container=None, **kwargs
22
+ self,
23
+ result_var: Parameter = None,
24
+ hv_dataset=None,
25
+ target_dimension: int = 0,
26
+ container=None,
27
+ level: int = None,
28
+ **kwargs
22
29
  ) -> Optional[pn.pane.panel]:
23
30
  if container is None:
24
31
  container = pn.pane.panel
32
+ if hv_dataset is None:
33
+ hv_dataset = self.to_hv_dataset(ReduceType.SQUEEZE, level=level)
34
+ elif not isinstance(hv_dataset, hv.Dataset):
35
+ hv_dataset = hv.Dataset(hv_dataset)
25
36
  return self.map_plot_panes(
26
37
  partial(self.ds_to_container, container=container),
27
- hv_dataset=self.to_hv_dataset(ReduceType.SQUEEZE),
38
+ hv_dataset=hv_dataset,
28
39
  target_dimension=target_dimension,
29
40
  result_var=result_var,
30
41
  result_types=PANEL_TYPES,
bencher/utils.py CHANGED
@@ -150,7 +150,7 @@ def callable_name(any_callable: Callable[..., Any]) -> str:
150
150
 
151
151
 
152
152
  def listify(obj) -> list:
153
- """Take an object and turn it into a list if its not already a list"""
153
+ """Take an object and turn it into a list if its not already a list. However if the object is none, don't turn it into a list"""
154
154
  if obj is None:
155
155
  return None
156
156
  if isinstance(obj, list):
@@ -191,3 +191,8 @@ def box(name, center, width):
191
191
  var = FloatSweep(default=center, bounds=(center - width, center + width))
192
192
  var.name = name
193
193
  return var
194
+
195
+
196
+ def with_level(arr: list, level) -> list:
197
+ return IntSweep(sample_values=arr).with_level(level).values()
198
+ # return tmp.with_sample_values(arr).with_level(level).values()
@@ -138,7 +138,7 @@ class SweepBase(param.Parameter):
138
138
  output.step = None # pylint: disable = attribute-defined-outside-init
139
139
  return output
140
140
 
141
- def with_sample_values(self, sample_values: int) -> SweepBase:
141
+ def with_sample_values(self, sample_values: list) -> SweepBase:
142
142
  output = deepcopy(self)
143
143
  # TODO set up class properly. Slightly complicated due to slots
144
144
  try:
bencher/video_writer.py CHANGED
@@ -32,7 +32,7 @@ class VideoWriter:
32
32
  return self.filename
33
33
 
34
34
  @staticmethod
35
- def create_label(label, width=None, height=20):
35
+ def create_label(label, width=None, height=14):
36
36
  if width is None:
37
37
  width = len(label) * 8
38
38
  new_img = Image.new("RGB", (width, height), (255, 255, 255))
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: holobench
3
- Version: 1.8.0
3
+ Version: 1.9.0
4
4
  Summary: A package for benchmarking the performance of arbitrary functions
5
5
  Author-email: Austin Gregg-Smith <blooop@gmail.com>
6
6
  Description-Content-Type: text/markdown
@@ -2,13 +2,13 @@ bencher/__init__.py,sha256=lw9moEkY3rb3kQVS3_SM9L0LsOAXRSM1JUJ_mm16tMQ,1236
2
2
  bencher/bench_cfg.py,sha256=IUhAhjpn_RkBTHonWN7deye_gYLgvTHszSGtcHj4MJY,18867
3
3
  bencher/bench_plot_server.py,sha256=ZePbN9lKMQggONYMBW0CJm9saLjmxtdeAEs6eiei_8g,4088
4
4
  bencher/bench_report.py,sha256=jh3T_q9KByZDeMPMf0KNJojZukxRzkfaYGeuWQU8MKM,10528
5
- bencher/bench_runner.py,sha256=AE1V0zGOxhe6qByFbb-V60GUugg3vQzyUxFK8Z1yc6Y,6072
6
- bencher/bencher.py,sha256=YwXvWpHZkrkXi47sxNpyYUnRv3li_kWY3TL38xqVMto,32539
5
+ bencher/bench_runner.py,sha256=F4DN1YSFXnUAGO17tJ6DZDyEu7QBgvTyqn8G_iCd36c,6165
6
+ bencher/bencher.py,sha256=Qi_UzkX_FkJ9PS4yONbZgMCR0Q2vsOJqCnw8DWrJ0T8,32906
7
7
  bencher/caching.py,sha256=AusaNrzGGlj5m6zcwcqnTn55Mam2mQdF--oqelO806M,1627
8
8
  bencher/job.py,sha256=Q2zpia95Ibukk8EeFq5IBbpo2PMRe7o5keelJCJlGnI,5927
9
9
  bencher/optuna_conversions.py,sha256=9nLVPAydSQ8PyJlyhzs__Em6_Rx8l8Ld94UNJZxy6cY,5303
10
- bencher/utils.py,sha256=QwK8uqt5RhYJc5A3zsHiuBxx7CHOa1YxwDNA6QBzCz4,5536
11
- bencher/video_writer.py,sha256=3nYVyLU_iaPmTlNBEjjwDbrh93XjrzLaLL-yxabvi30,4409
10
+ bencher/utils.py,sha256=qcbqBXTy9vH-PQbT1Hbdb81kAofTjnq-_A3bXvpJIvo,5595
11
+ bencher/video_writer.py,sha256=2bzupazLRN7J35W8qAggQ6-tcUIzaIMSXCC2sgcjdN4,4409
12
12
  bencher/worker_job.py,sha256=FREi0yWQACFmH86R1j-LH72tALEFkKhLDmmoGQY9Jh4,1571
13
13
  bencher/example/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
14
  bencher/example/benchmark_data.py,sha256=D9yUg_KKtqqEkAiLceodDwsv6sh7xEFWZNp6P6Y3pj4,6989
@@ -23,7 +23,7 @@ bencher/example/example_floats2D.py,sha256=D0kljoUCinMKCEW-Zg-cQ8sYu_yPCZqzKJ9tR
23
23
  bencher/example/example_holosweep.py,sha256=d9g5aWCAUb7FMZahb4t3xNs344EshPhA-8-K6K1SBXg,3180
24
24
  bencher/example/example_holosweep_objects.py,sha256=vHuAtkM1VrJelHOazn_SJfzxNywKyaMzN-DE8W7Ricc,3228
25
25
  bencher/example/example_holosweep_tap.py,sha256=3ayQ0bTj_XWP_92ifQJAhe1whwPAj_xWHPkzC7fvqAY,4540
26
- bencher/example/example_image.py,sha256=dbuEzaHCcaY3OVfJOg0Qny3LtAMjdGK6-FzRZuJvSmc,3477
26
+ bencher/example/example_image.py,sha256=ri7ZPXNmK7B7hU-TA331CLevX-4GlBnyq0rIWRPt1rs,3856
27
27
  bencher/example/example_levels.py,sha256=rpSNB571yfMnT7iO66Ds-DPGHWzOTM9FLMNfSetJdHY,6896
28
28
  bencher/example/example_pareto.py,sha256=yyAg8Vb-5sgsS6LkYKT7T5Evcfg69FlCqCakUippSmU,2687
29
29
  bencher/example/example_sample_cache.py,sha256=7gf1BJ63VAgdqNuNXkbL9-jeTeC3kXA_PY9yG3ulTz0,4200
@@ -58,23 +58,23 @@ bencher/plotting/plot_filter.py,sha256=Zff02hEcRffiqDEoXUHVZQJK5kW4HbMxe2GYCrxI8
58
58
  bencher/plotting/plt_cnt_cfg.py,sha256=BkiAsgHm35Mqb5OsjULGVK0Q6pGZ0WSsJxxwSOrbaQs,3124
59
59
  bencher/results/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
60
60
  bencher/results/bench_result.py,sha256=bxYm80avpfCMJr4bS94smkFSYbxvniXMJpXDEm2noHA,3444
61
- bencher/results/bench_result_base.py,sha256=ymR99Fvnmbsw6Qn24wPP1gesofjATKwKX_FcpCT9ZWU,16257
61
+ bencher/results/bench_result_base.py,sha256=ya-0Tqo6djoKLB0pJzQCM9F8dJGtKlG3kPMxt7MQJCE,18545
62
62
  bencher/results/float_formatter.py,sha256=sX6HNCyaXdHDxC8ybVUHwCJ3qOKbPUkBOplVIHtKWjM,1746
63
- bencher/results/holoview_result.py,sha256=nfXYTaGQkXwLqJ_gEB3TYJxHfKAQCN1E60D9Tfbkxos,22254
63
+ bencher/results/holoview_result.py,sha256=SAOUFVWfrcwlDpzI6vWGK9NdKfBDpO825dMtdhYQpO8,22297
64
64
  bencher/results/optuna_result.py,sha256=jtsWJGdCS0L98EzxTxXU_AyarCL5CkXRLOVuSvs048M,13437
65
- bencher/results/panel_result.py,sha256=ZHTkobAYHHsYYvQqLafba8g3rbT255hKO7u9A_oMBhM,1115
65
+ bencher/results/panel_result.py,sha256=vzZaXhGurbKex50hrSksdTh7tBIAGvcDN9l1OBulWDQ,1403
66
66
  bencher/results/plotly_result.py,sha256=wkgfL38qJp6RviekXBYpNPeU4HCf0nbtKDAhu5QZhUg,2132
67
67
  bencher/results/video_result.py,sha256=E3fAxXctRVxiRyamadpKCMXanM5TTqw1tEYICS2LDLs,1146
68
68
  bencher/results/video_summary.py,sha256=lcRb4XWOVd5xU7XPuLa_NBbD2heBjINS5RtiUlBT0yk,6977
69
69
  bencher/results/composable_container/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
70
- bencher/results/composable_container/composable_container_base.py,sha256=u5bSXD0yuKSwvr2z3cWF1FijQqpr-pciPm86JxhLmJo,2323
70
+ bencher/results/composable_container/composable_container_base.py,sha256=RWcXTf__PvWXesCmY244NFXj7TJqVcle29o-4QgZdBQ,2383
71
71
  bencher/results/composable_container/composable_container_panel.py,sha256=A56-MaaaId_VBMFhvM7Jtfh8_3PeKNxlEnOKU49IsW8,1221
72
72
  bencher/results/composable_container/composable_container_video.py,sha256=tcFAjmFU74ZJ5HYOEd5EZrZaFdnOryEh1kvb2JoO9dk,2508
73
- bencher/variables/inputs.py,sha256=XtUko3qNYB1xk7fwM9teVGRU0MNCW673n2teGtoyFGU,6393
73
+ bencher/variables/inputs.py,sha256=o7_xyA7DE4ZsyrFi_apRVSRClGA-3o2jgKeFbyMYx5Y,6571
74
74
  bencher/variables/parametrised_sweep.py,sha256=sqi5JPzloZ7f6fiZZwOFMa3AQnFWkfjYXQy7OWSask0,7361
75
75
  bencher/variables/results.py,sha256=QCn7IZd4RwcRcDCp6DQp8w0wBMnHzluyw-Hu19Jg7Ig,6028
76
- bencher/variables/sweep_base.py,sha256=I1LEeG1y5Jsw0a-Ik03t0tSzcfENht2GmBECJ3KNs28,6559
76
+ bencher/variables/sweep_base.py,sha256=YC9Oxi5xJ7wloGgquommLT8Qvov369RQiTmc_pxEU34,6560
77
77
  bencher/variables/time.py,sha256=Le7s8_oUYJD4wCqwQw-a_FRDpYQOi8CqMbGYsBF07jg,2860
78
- holobench-1.8.0.dist-info/WHEEL,sha256=Sgu64hAMa6g5FdzHxXv9Xdse9yxpGGMeagVtPMWpJQY,99
79
- holobench-1.8.0.dist-info/METADATA,sha256=N4t3a4JUHu4nlco2qbafem_Ktexqe3LjqkYz62lZSNk,5109
80
- holobench-1.8.0.dist-info/RECORD,,
78
+ holobench-1.9.0.dist-info/WHEEL,sha256=Sgu64hAMa6g5FdzHxXv9Xdse9yxpGGMeagVtPMWpJQY,99
79
+ holobench-1.9.0.dist-info/METADATA,sha256=5JW1AFNH9lkROtXUMXP0_dwVOnDC_zkpZrqx7nbYIio,5109
80
+ holobench-1.9.0.dist-info/RECORD,,