Skip to content

Commit 9f8d3e5

Browse files
author
Raniere Silva
committed
Add docstrings
and others small fixes.
1 parent 80b4434 commit 9f8d3e5

File tree

1 file changed

+108
-59
lines changed

1 file changed

+108
-59
lines changed

tools/check

Lines changed: 108 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -10,37 +10,39 @@
1010

1111
import os
1212
import re
13+
import sys
14+
1315
import yaml
1416

1517
#----------------------------------------
1618
# Error reporting.
1719

1820
def report_error(file_path, line_number, line, error_message):
19-
'''
20-
FIXME: docstring.
21-
'''
21+
"""
22+
Print information about general error.
23+
"""
2224
ERR_MSG = "Error at line {} of {}:\n\t{}\n{}"
2325
print(ERR_MSG.format(line_number, file_path, line, error_message))
2426

2527
def report_missing(present, file_path, missing_element):
26-
'''
27-
FIXME: docstring.
28-
'''
28+
"""
29+
Print information about missing element.
30+
"""
2931
ERR_MSG = "Error on {}: missing {}"
3032
if not present:
3133
print(ERR_MSG.format(file_path, missing_element))
3234

3335
def report_missing_metadata(missing_element):
34-
'''
35-
FIXME: docstring.
36-
'''
36+
"""
37+
Print information about missing metadata at YAML header.
38+
"""
3739
ERR_MSG = "Error on YAML header: missing {}"
3840
print(ERR_MSG.format(missing_element))
3941

4042
def report_broken_link(file_path, line_number, link):
41-
'''
42-
FIXME: docstring.
43-
'''
43+
"""
44+
Print information about broken link.
45+
"""
4446
ERR_MSG = "Broken link at line {} of {}:\n\tCan't find {}."
4547
print(ERR_MSG.format(line_number, file_path, link))
4648

@@ -55,23 +57,50 @@ def check_yaml(metadata):
5557
for key in METADATA_REQUIRED - set(metadata.keys()):
5658
report_missing_metadata(key)
5759

60+
# TODO: Implement check_lesson
5861
def check_lesson(file_path):
59-
'''
60-
FIXME: docstring telling people what you want them to write here.
61-
'''
62+
"""
63+
Checks the file ``pages/[0-9]{2}-.*.md`` for:
64+
65+
- "layout: topic" at YAML header
66+
- "title" as keyword at YAML header
67+
- line "> ## Learning Objectives {.objectives}" after YAML header
68+
- items at learning objectives begin with "*"
69+
- items at learning objective following four space rule
70+
- code samples be of type error, output, python, shell, r, matlab, sql
71+
- callout box style
72+
- line with "> ## Key Points {.keypoints}"
73+
- challenge box style
74+
"""
6275
pass
6376

77+
# TODO: Implement check_discussion
6478
def check_discussion(file_path):
65-
'''
66-
FIXME: docstring telling people what you want them to write here.
67-
'''
79+
"""
80+
Checks the file ``pages/discussion.md`` for:
81+
82+
FIXME: tell what need to check.
83+
"""
6884
pass
6985

86+
# TODO: Complete implementation of check_index
87+
# TODO: break check_index into pieces -- it's too long.
7088
def check_index(file_path):
71-
'''
72-
FIXME: docstring.
73-
And break this up into pieces -- it's too long.
74-
'''
89+
"""
90+
Checks the file ``pages/index.md`` for:
91+
92+
- "layout: lesson" in YAML header
93+
- "title" as keyword in YAML header
94+
- introductory paragraph right after YAML header
95+
- line with "> ## Prerequisites"
96+
- non empty prerequisites
97+
- line with "## Topics"
98+
- items at topic list begin with "*"
99+
- links at topic list are valid
100+
- line with "## Other Resources"
101+
- items at other resources list begin with "*"
102+
- link at other resources list are valid
103+
"""
75104
# State variables
76105
in_yaml = False
77106
yaml_metadata = []
@@ -80,85 +109,105 @@ def check_index(file_path):
80109
has_other_resources = False
81110

82111
# Load file and process it
83-
with open(file_path, 'r') as lines:
112+
with open(file_path, "r") as lines:
84113
for line_number, line in enumerate(lines):
85-
if re.match('---', line): # what if there are multiple YAML blocks??
114+
if re.match("---", line): # what if there are multiple YAML blocks??
86115
in_yaml = not in_yaml
87116
elif in_yaml:
88117
yaml_metadata.append(line)
89-
elif re.match('> ## Prerequisites', line): # check this in the Markdown or in the generated HTML?
118+
elif re.match("> ## Prerequisites", line): # check this in the Markdown or in the generated HTML?
90119
has_prerequisites = True
91-
elif re.match('## Topics', line): # as above?
120+
elif re.match("## Topics", line): # as above?
92121
has_topics = True
93-
elif re.match('## Other Resources', line): # as above
122+
elif re.match("## Other Resources", line): # as above
94123
has_other_resources = True
95124
else:
96125
## Push this check into another function - this one is getting too long.
97126
# Check if local links are valid
98-
matches = re.search('\[.*\]\((?P<link>.*)\)', line)
127+
matches = re.search("\[.*\]\((?P<link>.*)\)", line)
99128
if matches and not matches.group("link").startswith("http"):
100129
link = os.path.join(os.path.dirname(file_path), matches.group("link"))
101130
if link.endswith(".html"):
102-
link = link.replace("html", "md") # NO: what about '03-html-editing.html' ?
131+
link = link.replace("html", "md") # NO: what about "03-html-editing.html" ?
103132
if not os.path.exists(link):
104133
report_broken_link(file_path, line_number, link)
105134

106135
## Again, this function is too long - break it into sub-functions.
107136
# Check YAML
108-
yaml_metadata = yaml.load('\n'.join(yaml_metadata))
109-
check_yaml(yaml_metadata, {"minutes"})
137+
yaml_metadata = yaml.load("\n".join(yaml_metadata))
138+
check_yaml(yaml_metadata)
110139

111140
# Check sections
112141
## Note the refactoring: replaces three conditionals with one.
113142
report_missing(has_prerequisites, file_path, "Prerequisites")
114143
report_missing(has_topics, file_path, "Topics")
115144
report_missing(has_other_resources, file_path, "Other Resources")
116145

146+
# TODO Implement check_intructors
117147
def check_intructors(file_path):
118-
'''
119-
FIXME: docstring telling people what you want them to write here.
120-
'''
148+
"""
149+
Checks the file ``pages/instructors.md`` for:
150+
151+
- "title: Instructor"s Guide" in YAML header
152+
- line with "## Overall"
153+
- line with "## General Points"
154+
- lines with topics titles begin with "## "
155+
- points begin with "*" and following four space rules.
156+
"""
121157
pass
122158

159+
# TODO Implement check_motivation
123160
def check_motivation(file_path):
124-
'''
125-
FIXME: docstring telling people what you want them to write here.
126-
'''
161+
"""
162+
Checks the file ``pages/motivation.md``.
163+
164+
FIXME: tell what need to check.
165+
"""
127166
pass
128167

168+
# TODO Implement check_reference
129169
def check_reference(file_path):
130-
'''
131-
FIXME: docstring telling people what you want them to write here.
132-
'''
170+
"""
171+
Checks the file ``pages/reference.md`` for:
172+
173+
- ``layout: reference`` in YAML header
174+
- line with "## Glossary"
175+
- words definitions after at the "Glossary" as::
176+
177+
> **Key Word 1**: the definition
178+
> relevant to the lesson.
179+
"""
133180
pass
134181

135182
def check_file(file_path):
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.
183+
"""
184+
Call the correctly check function based on the name of the file.
185+
"""
186+
# Pair of regex and function to call
140187
CONTROL = (
141-
('[0-9]{2}-.*', check_lesson),
142-
('discussion', check_discussion),
143-
('index', check_index),
144-
('instructors', check_intructors),
188+
("[0-9]{2}-.*", check_lesson),
189+
("discussion", check_discussion),
190+
("index", check_index),
191+
("instructors", check_intructors),
145192
("motivation", check_motivation),
146193
("reference", check_reference)
147194
)
148195
for (pattern, checker) in CONTROL:
149196
if re.search(pattern, file_path):
150197
checker(file_path)
151198

152-
## main doesn't take sys.argv[1:] or the like? Will help with testing...
153-
def main():
154-
'''
155-
FIXME: docstring telling people what you want them to write here.
156-
'''
157-
lessons_file = os.listdir("pages")
158-
for lesson in lessons_file:
159-
if lesson.endswith('.md'):
160-
## Why not os.path.join('pages', lesson) ?
161-
check_file('pages/{}'.format(lesson))
199+
def main(list_of_files):
200+
"""
201+
Call the check function for every file in ``list_of_files``.
202+
203+
If ``list_of_files`` is empty load all the files from ``pages`` directory.
204+
"""
205+
if not list_of_files:
206+
list_of_files = [os.path.join("pages", filename) for filename in os.listdir("pages")]
207+
208+
for filename in list_of_files:
209+
if filename.endswith(".md"):
210+
check_file(filename)
162211

163212
if __name__ == "__main__":
164-
main()
213+
main(sys.argv[1:])

0 commit comments

Comments
 (0)