22import json
33import os
44import sys
5+ import warnings
56from glob import glob
67
78from pathlib import Path
8- from pprint import pprint
9+ from pprint import pformat , pprint
910from typing import List , Optional
1011
1112import typer
1213
1314from bioimageio .core import __version__ , prediction , commands , resource_tests , load_raw_resource_description
15+ from bioimageio .core .common import TestSummary
1416from bioimageio .core .prediction_pipeline import get_weight_formats
1517from bioimageio .spec .__main__ import app , help_version as help_version_spec
1618from bioimageio .spec .model .raw_nodes import WeightsFormat
2123 from typing_extensions import get_args # type: ignore
2224
2325try :
24- from bioimageio .core .weight_converter import torch as torch_converter
26+ with warnings .catch_warnings ():
27+ warnings .simplefilter ("ignore" )
28+ from bioimageio .core .weight_converter import torch as torch_converter
2529except ImportError :
2630 torch_converter = None
2731
2832try :
29- from bioimageio .core .weight_converter import keras as keras_converter
33+ with warnings .catch_warnings ():
34+ warnings .simplefilter ("ignore" )
35+ from bioimageio .core .weight_converter import keras as keras_converter
3036except ImportError :
3137 keras_converter = None
3238
@@ -78,6 +84,46 @@ def package(
7884# WeightFormatEnum = enum.Enum("WeightFormatEnum", get_args(WeightsFormat))
7985
8086
87+ def _log_test_summaries (summaries : List [TestSummary ], msg : str ):
88+ # todo: improve logging of multiple test summaries
89+ ret_code = 0
90+ for summary in summaries :
91+ print (f"{ summary ['name' ]} : { summary ['status' ]} " )
92+ if summary ["status" ] != "passed" :
93+ s = {
94+ k : v
95+ for k , v in summary .items ()
96+ if k not in ("name" , "status" , "bioimageio_spec_version" , "bioimageio_core_version" )
97+ }
98+ tb = s .pop ("traceback" )
99+ if tb :
100+ print ("traceback:" )
101+ print ("" .join (tb ))
102+
103+ def show_part (part , show ):
104+ if show :
105+ line = f"{ part } : "
106+ print (line + pformat (show , width = min (80 , 120 - len (line ))).replace ("\n " , " " * len (line ) + "\n " ))
107+
108+ for part in ["error" , "warnings" , "source_name" ]:
109+ show_part (part , s .pop (part , None ))
110+
111+ for part in sorted (s .keys ()):
112+ show_part (part , s [part ])
113+
114+ ret_code = 1
115+
116+ if ret_code :
117+ result = "FAILED!"
118+ icon = "❌"
119+ else :
120+ result = "passed."
121+ icon = "✔️"
122+
123+ print (msg .format (icon = icon , result = result ))
124+ return ret_code
125+
126+
81127@app .command ()
82128def test_model (
83129 model_rdf : str = typer .Argument (
@@ -88,31 +134,16 @@ def test_model(
88134 decimal : int = typer .Option (4 , help = "The test precision." ),
89135):
90136 # this is a weird typer bug: default devices are empty tuple although they should be None
91- if len ( devices ) == 0 :
92- devices = None
93- summary = resource_tests .test_model (
137+ devices = devices or None
138+
139+ summaries = resource_tests .test_model (
94140 model_rdf ,
95141 weight_format = None if weight_format is None else weight_format .value ,
96142 devices = devices ,
97143 decimal = decimal ,
98144 )
99-
100- if weight_format is None :
101- weight_formats = get_weight_formats ()
102- model_weight_formats = list (load_raw_resource_description (model_rdf ).weights .keys ())
103- for wf in weight_formats :
104- if wf in model_weight_formats :
105- weight_format = wf
106- break
107- weight_format = "unknown" if weight_format is None else weight_format
108-
109- if summary ["error" ] is None :
110- print (f"Model test for { model_rdf } using { weight_format } weight format has passed." )
111- ret_code = 0
112- else :
113- print (f"Model test for { model_rdf } using { weight_format } weight format has FAILED!" )
114- pprint (summary )
115- ret_code = 1
145+ print (f"\n testing model { model_rdf } ..." )
146+ ret_code = _log_test_summaries (summaries , f"\n {{icon}} Model { model_rdf } {{result}}" )
116147 sys .exit (ret_code )
117148
118149
@@ -131,16 +162,11 @@ def test_resource(
131162 # this is a weird typer bug: default devices are empty tuple although they should be None
132163 if len (devices ) == 0 :
133164 devices = None
134- summary = resource_tests .test_resource (
165+ summaries = resource_tests .test_resource (
135166 rdf , weight_format = None if weight_format is None else weight_format .value , devices = devices , decimal = decimal
136167 )
137- if summary ["error" ] is None :
138- print (f"Resource test for { rdf } has passed." )
139- ret_code = 0
140- else :
141- print (f"Resource test for { rdf } has FAILED!" )
142- pprint (summary )
143- ret_code = 1
168+ print (f"\n testing { rdf } ..." )
169+ ret_code = _log_test_summaries (summaries , f"{{icon}} Resource test for { rdf } has {{result}}" )
144170 sys .exit (ret_code )
145171
146172
0 commit comments