99# $ tools/check
1010
1111import os
12- import os .path
1312import re
14-
1513import yaml
1614
17- def report_error (file_path , line_number , line , error_message ):
18- print ("Error at line {} of {}:\n \t {}\n {}" .format (line_number ,
19- file_path , line , error_message ))
15+ #----------------------------------------
16+ # Error reporting.
2017
21- def report_missing (file_path , missing_element ):
22- print ("Error on {}: missing {}" .format (file_path , missing_element ))
18+ def report_error (file_path , line_number , line , error_message ):
19+ '''
20+ FIXME: docstring.
21+ '''
22+ ERR_MSG = "Error at line {} of {}:\n \t {}\n {}"
23+ print (ERR_MSG .format (line_number , file_path , line , error_message ))
24+
25+ def report_missing (present , file_path , missing_element ):
26+ '''
27+ FIXME: docstring.
28+ '''
29+ ERR_MSG = "Error on {}: missing {}"
30+ if not present :
31+ print (ERR_MSG .format (file_path , missing_element ))
2332
2433def report_missing_metadata (missing_element ):
25- print ("Error on YAML header: missing {}" .format (missing_element ))
34+ '''
35+ FIXME: docstring.
36+ '''
37+ ERR_MSG = "Error on YAML header: missing {}"
38+ print (ERR_MSG .format (missing_element ))
2639
2740def report_broken_link (file_path , line_number , link ):
28- print ("Broken link at line {} of {}:\n \t Can't find {}." .format (line_number ,
29- file_path , link ))
41+ '''
42+ FIXME: docstring.
43+ '''
44+ ERR_MSG = "Broken link at line {} of {}:\n \t Can't find {}."
45+ print (ERR_MSG .format (line_number , file_path , link ))
3046
31- def check_yaml (metadata , skip = []):
47+ #----------------------------------------
48+ # Checking.
49+
50+ def check_yaml (metadata ):
3251 """
3352 Check if all metadata are present at YAML header.
34-
35- :param skip: list of keys to skip check
3653 """
37- metadata_required = ["layout" , "title" , "minutes" ]
38- for key in metadata_required :
39- if key not in skip and key not in metadata :
40- report_missing_metadata (key )
54+ METADATA_REQUIRED = {"layout" , "title" , "minutes" }
55+ for key in METADATA_REQUIRED - set (metadata .keys ()):
56+ report_missing_metadata (key )
4157
4258def check_lesson (file_path ):
59+ '''
60+ FIXME: docstring telling people what you want them to write here.
61+ '''
4362 pass
4463
4564def check_discussion (file_path ):
65+ '''
66+ FIXME: docstring telling people what you want them to write here.
67+ '''
4668 pass
4769
4870def check_index (file_path ):
71+ '''
72+ FIXME: docstring.
73+ And break this up into pieces -- it's too long.
74+ '''
4975 # State variables
5076 in_yaml = False
5177 yaml_metadata = []
@@ -56,66 +82,82 @@ def check_index(file_path):
5682 # Load file and process it
5783 with open (file_path , 'r' ) as lines :
5884 for line_number , line in enumerate (lines ):
59- if re .match ('---' , line ):
85+ if re .match ('---' , line ): # what if there are multiple YAML blocks??
6086 in_yaml = not in_yaml
6187 elif in_yaml :
6288 yaml_metadata .append (line )
63- elif re .match ('> ## Prerequisites' , line ):
89+ elif re .match ('> ## Prerequisites' , line ): # check this in the Markdown or in the generated HTML?
6490 has_prerequisites = True
65- elif re .match ('## Topics' , line ):
91+ elif re .match ('## Topics' , line ): # as above?
6692 has_topics = True
67- elif re .match ('## Other Resources' , line ):
93+ elif re .match ('## Other Resources' , line ): # as above
6894 has_other_resources = True
6995 else :
96+ ## Push this check into another function - this one is getting too long.
7097 # Check if local links are valid
7198 matches = re .search ('\[.*\]\((?P<link>.*)\)' , line )
7299 if matches and not matches .group ("link" ).startswith ("http" ):
73- link = os .path .join (os .path .dirname (file_path ),
74- matches .group ("link" ))
100+ link = os .path .join (os .path .dirname (file_path ), matches .group ("link" ))
75101 if link .endswith (".html" ):
76- link = link .replace ("html" , "md" )
102+ link = link .replace ("html" , "md" ) # NO: what about '03-html-editing.html' ?
77103 if not os .path .exists (link ):
78104 report_broken_link (file_path , line_number , link )
79105
106+ ## Again, this function is too long - break it into sub-functions.
80107 # Check YAML
81108 yaml_metadata = yaml .load ('\n ' .join (yaml_metadata ))
82- check_yaml (yaml_metadata , [ "minutes" ] )
109+ check_yaml (yaml_metadata , { "minutes" } )
83110
84111 # Check sections
85- if not has_prerequisites :
86- report_missing (file_path , "Prerequisites" )
87- if not has_topics :
88- report_missing (file_path , "Topics" )
89- if not has_other_resources :
90- report_missing (file_path , "Other Resources" )
112+ ## Note the refactoring: replaces three conditionals with one.
113+ report_missing (has_prerequisites , file_path , "Prerequisites" )
114+ report_missing (has_topics , file_path , "Topics" )
115+ report_missing (has_other_resources , file_path , "Other Resources" )
91116
92117def check_intructors (file_path ):
118+ '''
119+ FIXME: docstring telling people what you want them to write here.
120+ '''
93121 pass
94122
95123def check_motivation (file_path ):
124+ '''
125+ FIXME: docstring telling people what you want them to write here.
126+ '''
96127 pass
97128
98129def check_reference (file_path ):
130+ '''
131+ FIXME: docstring telling people what you want them to write here.
132+ '''
99133 pass
100134
101135def check_file (file_path ):
102- if re .search ('[0-9]{2}-.*' , file_path ):
103- check_lesson (file_path )
104- elif re .search ('discussion' , file_path ):
105- check_discussion (file_path )
106- elif re .search ('index' , file_path ):
107- check_index (file_path )
108- elif re .search ('instructors' , file_path ):
109- check_intructors (file_path )
110- elif re .search ("motivation" , file_path ):
111- check_motivation (file_path )
112- elif re .search ("reference" , file_path ):
113- check_reference (file_path )
114-
136+ '''
137+ FIXME: docstring telling people what you want them to write here.
138+ '''
139+ ## Functions are objects, and so can be put in tables like the one below.
140+ CONTROL = (
141+ ('[0-9]{2}-.*' , check_lesson ),
142+ ('discussion' , check_discussion ),
143+ ('index' , check_index ),
144+ ('instructors' , check_intructors ),
145+ ("motivation" , check_motivation ),
146+ ("reference" , check_reference )
147+ )
148+ for (pattern , checker ) in CONTROL :
149+ if re .search (pattern , file_path ):
150+ checker (file_path )
151+
152+ ## main doesn't take sys.argv[1:] or the like? Will help with testing...
115153def main ():
154+ '''
155+ FIXME: docstring telling people what you want them to write here.
156+ '''
116157 lessons_file = os .listdir ("pages" )
117158 for lesson in lessons_file :
118159 if lesson .endswith ('.md' ):
160+ ## Why not os.path.join('pages', lesson) ?
119161 check_file ('pages/{}' .format (lesson ))
120162
121163if __name__ == "__main__" :
0 commit comments