99import re
1010from fnmatch import fnmatch
1111
12- import six
12+ from six . moves import shlex_quote
1313
1414from scripting .unix import system , check_output
1515from scripting .contexts import cd
@@ -113,22 +113,41 @@ def read_notebooks_from_file(file_like):
113113 return []
114114
115115
116- def main ():
117- import argparse
118- parser = argparse .ArgumentParser (
119- description = 'Run Jupyter notebooks.' )
120- parser .add_argument ('notebook' , type = str , nargs = '*' , default = [],
121- help = 'Notebook to test.' )
122- parser .add_argument ('-e' , '--exclude' , metavar = 'PATTERN' , type = str ,
123- action = 'append' , default = [],
124- help = 'Notebooks to exclude.' )
125- parser .add_argument ('--dry-run' , action = 'store_true' ,
126- help = 'Find notebooks but do not do anything' )
127- parser .add_argument ('-f' , '--file' , type = argparse .FileType ('r' ),
128- help = 'Read notebooks from a file.' )
116+ def find_notebooks (base ):
117+ """Find Jupyter notebooks.
118+
119+ Parameters
120+ ----------
121+ base : str
122+ Path to search for notebooks under.
123+
124+ Returns
125+ -------
126+ list of str
127+ Paths to discovered notebooks.
128+ """
129+ notebooks = []
130+ for root , dirs , files in os .walk (base , topdown = True ):
131+ for dir in dirs :
132+ if dir .startswith ('.' ):
133+ dirs .remove (dir )
134+ for fname in files :
135+ file_path = os .path .join (root , fname )
136+ if file_path .endswith ('.ipynb' ):
137+ notebooks .append (file_path )
138+ return notebooks
129139
130- args = parser .parse_args ()
131140
141+ def find_command (args ):
142+ notebooks = find_notebooks (args .path )
143+
144+ if args .sort :
145+ notebooks .sort ()
146+
147+ print (os .linesep .join ([nb for nb in notebooks ]))
148+
149+
150+ def run_command (args ):
132151 notebooks = read_notebooks_from_file (args .file ) + args .notebook
133152
134153 excluded = match_by_pattern (notebooks , args .exclude )
@@ -146,5 +165,35 @@ def main():
146165 return print_success_or_failure (summary )
147166
148167
168+ def main ():
169+ import argparse
170+ parser = argparse .ArgumentParser (description = 'Run Jupyter notebooks.' )
171+
172+ subparsers = parser .add_subparsers (title = 'subcommands' ,
173+ description = 'valid subcommands' ,
174+ help = 'additional help' )
175+
176+ parser_find = subparsers .add_parser ('find' , help = 'Find notebooks.' )
177+ parser_find .set_defaults (func = find_command )
178+ parser_find .add_argument ('path' , help = 'Path to search for notebooks.' )
179+ parser_find .add_argument ('--sort' , action = 'store_true' ,
180+ help = 'Sort notebooks alphabetically.' )
181+
182+ parser_run = subparsers .add_parser ('run' , help = 'Run notebooks.' )
183+ parser_run .set_defaults (func = run_command )
184+ parser_run .add_argument ('notebook' , type = str , nargs = '*' , default = [],
185+ help = 'Notebook to test.' )
186+ parser_run .add_argument ('-e' , '--exclude' , metavar = 'PATTERN' , type = str ,
187+ action = 'append' , default = [],
188+ help = 'Notebooks to exclude.' )
189+ parser_run .add_argument ('--dry-run' , action = 'store_true' ,
190+ help = 'Find notebooks but do not do anything' )
191+ parser_run .add_argument ('-f' , '--file' , type = argparse .FileType ('r' ),
192+ help = 'Read notebooks from a file.' )
193+
194+ args = parser .parse_args ()
195+ args .func (args )
196+
197+
149198if __name__ == '__main__' :
150199 sys .exit (main ())
0 commit comments