31
31
from argparse import ArgumentParser
32
32
33
33
from rich .console import Console
34
+ from dataclasses import dataclass
34
35
import logging
35
36
from pathlib import Path
36
37
from tempfile import NamedTemporaryFile
@@ -99,7 +100,13 @@ def actual_run(notebook_path: Path, i: int, total: int) -> None:
99
100
)
100
101
101
102
102
- class NotebookFailure (TypedDict ):
103
+ @dataclass
104
+ class NotebookSuccess :
105
+ notebook_path : Path
106
+
107
+
108
+ @dataclass
109
+ class NotebookFailure :
103
110
notebook_path : Path
104
111
error : str
105
112
@@ -109,19 +116,17 @@ def run_notebook(
109
116
i : int ,
110
117
total : int ,
111
118
mock : bool = True ,
112
- ) -> NotebookFailure | None :
119
+ ) -> NotebookFailure | NotebookSuccess :
113
120
logging .info (f"Running notebook: { notebook_path .name } " )
114
121
run = mock_run if mock else actual_run
115
122
116
123
try :
117
124
run (notebook_path , i = i , total = total )
118
125
except Exception as e :
119
- logging .error (
120
- f"{ e .__class__ .__name__ } encountered running notebook: { str (notebook_path )} "
121
- )
126
+ logging .error (f"{ e .__class__ .__name__ } encountered running notebook: { str (notebook_path )} " )
122
127
return NotebookFailure (notebook_path = notebook_path , error = str (e ))
123
128
else :
124
- return
129
+ return NotebookSuccess ( notebook_path = notebook_path )
125
130
126
131
127
132
class RunParams (TypedDict ):
@@ -133,35 +138,35 @@ class RunParams(TypedDict):
133
138
134
139
def run_parameters (notebook_paths : list [Path ], mock : bool = True ) -> list [RunParams ]:
135
140
def to_mock (notebook_path : Path , i : int ) -> RunParams :
136
- return RunParams (
137
- notebook_path = notebook_path , mock = mock , i = i , total = len (notebook_paths )
138
- )
141
+ return RunParams (notebook_path = notebook_path , mock = mock , i = i , total = len (notebook_paths ))
139
142
140
- return [
141
- to_mock (notebook_path , i = i )
142
- for i , notebook_path in enumerate (notebook_paths , start = 1 )
143
- ]
143
+ return [to_mock (notebook_path , i = i ) for i , notebook_path in enumerate (notebook_paths , start = 1 )]
144
144
145
145
146
146
def main (notebooks_to_run : list [Path ], mock : bool = True ) -> None :
147
147
console = Console ()
148
- errors : list [NotebookFailure ]
149
148
setup_logging ()
150
149
logging .info ("Starting notebook runner" )
151
150
logging .info (f"Running { len (notebooks_to_run )} notebook(s)." )
152
151
results = Parallel (n_jobs = - 1 )(
153
152
delayed (run_notebook )(** run_params )
154
153
for run_params in run_parameters (notebooks_to_run , mock = mock )
155
154
)
156
- errors = [result for result in results if result is not None ]
155
+ errors : list [NotebookFailure ] = list (filter (lambda x : isinstance (x , NotebookFailure ), results ))
156
+ successes : list [NotebookSuccess ] = list (
157
+ filter (lambda x : isinstance (x , NotebookSuccess ), results )
158
+ )
157
159
158
160
if not errors :
159
- logging .info ("Notebooks run successfully!" )
161
+ logging .info ("All notebooks ran successfully!" )
160
162
return
161
163
162
164
for error in errors :
163
- console .rule (f"[bold red]Error running { error ['notebook_path' ]} [/bold red]" )
164
- console .print (error ["error" ])
165
+ console .rule (f"[bold red]Error running { error .notebook_path } [/bold red]" )
166
+ console .print (error .error )
167
+
168
+ for success in successes :
169
+ console .print (f"[bold green]Success running { success .notebook_path } [/bold green]" )
165
170
166
171
logging .error (f"{ len (errors )} / { len (notebooks_to_run )} notebooks failed" )
167
172
0 commit comments