From c2f89a7a8d78a71070e91ac3a2b6e5a99095e8b3 Mon Sep 17 00:00:00 2001 From: Greg Wilson Date: Wed, 29 Jun 2016 23:16:39 -0400 Subject: [PATCH] Checking ends of lines --- Makefile | 27 ++++++++++++++++----------- bin/lesson_check.py | 26 +++++++++++++++++++++----- bin/util.py | 12 ++++++++---- 3 files changed, 45 insertions(+), 20 deletions(-) diff --git a/Makefile b/Makefile index 7b1b1b9..7116629 100644 --- a/Makefile +++ b/Makefile @@ -11,23 +11,23 @@ DST=_site .PHONY : commands clean files all : commands -## commands : show all commands. +## commands : show all commands. commands : @grep -h -E '^##' ${MAKEFILES} | sed -e 's/## //g' -## serve : run a local server. +## serve : run a local server. serve : lesson-rmd ${JEKYLL} serve --config _config.yml,_config_dev.yml -## site : build files but do not run a server. +## site : build files but do not run a server. site : lesson-rmd ${JEKYLL} build --config _config.yml,_config_dev.yml -## figures : re-generate inclusion displaying all figures. +## figures : re-generate inclusion displaying all figures. figures : @bin/extract_figures.py -s _episodes -p ${PARSER} > _includes/all_figures.html -## clean : clean up junk files. +## clean : clean up junk files. clean : @rm -rf ${DST} @rm -rf .sass-cache @@ -36,7 +36,7 @@ clean : @find . -name '*~' -exec rm {} \; @find . -name '*.pyc' -exec rm {} \; -## clean-rmd : clean intermediate R files (that need to be committed to the repo). +## clean-rmd : clean intermediate R files (that need to be committed to the repo). clear-rmd : @rm -rf ${RMD_DST} @rm -rf fig/rmd-* @@ -46,7 +46,7 @@ clear-rmd : .PHONY : workshop-check -## workshop-check : check workshop homepage. +## workshop-check : check workshop homepage. workshop-check : @bin/workshop_check.py . @@ -79,25 +79,30 @@ HTML_DST = \ $(patsubst _extras/%.md,${DST}/%/index.html,$(wildcard _extras/*.md)) \ ${DST}/license/index.html -## lesson-rmd: : convert Rmarkdown files to markdown +## lesson-rmd : convert Rmarkdown files to markdown lesson-rmd: $(RMD_SRC) @bin/knit_lessons.sh $(RMD_SRC) -## lesson-check : validate lesson Markdown. +## lesson-check : validate lesson Markdown. lesson-check : @bin/lesson_check.py -s . -p ${PARSER} +## lesson-check-all : validate lesson Markdown, checking line lengths and trailing whitespace. +lesson-check-all : + @bin/lesson_check.py -s . -p ${PARSER} -l -w + +## unittest : run unit tests on checking tools. unittest : python bin/test_lesson_check.py -## lesson-files : show expected names of generated files for debugging. +## lesson-files : show expected names of generated files for debugging. lesson-files : @echo 'RMD_SRC:' ${RMD_SRC} @echo 'RMD_DST:' ${RMD_DST} @echo 'MARKDOWN_SRC:' ${MARKDOWN_SRC} @echo 'HTML_DST:' ${HTML_DST} -## lesson-fixme : show FIXME markers embedded in source files. +## lesson-fixme : show FIXME markers embedded in source files. lesson-fixme : @fgrep -i -n FIXME ${MARKDOWN_SRC} || true diff --git a/bin/lesson_check.py b/bin/lesson_check.py index c123984..c85661e 100755 --- a/bin/lesson_check.py +++ b/bin/lesson_check.py @@ -11,7 +11,7 @@ import json import re from optparse import OptionParser -from util import Reporter, read_markdown +from util import Reporter, read_markdown, load_yaml __version__ = '0.2' @@ -106,7 +106,7 @@ def parse_args(): parser = OptionParser() parser.add_option('-l', '--linelen', default=False, - dest='line_len', + dest='line_lengths', help='Check line lengths') parser.add_option('-p', '--parser', default=None, @@ -116,6 +116,10 @@ def parse_args(): default=os.curdir, dest='source_dir', help='source directory') + parser.add_option('-w', '--whitespace', + default=False, + dest='trailing_whitespace', + help='Check for trailing whitespace') args, extras = parser.parse_args() require(args.parser is not None, @@ -227,7 +231,8 @@ class CheckBase(object): """Run tests on metadata.""" self.check_metadata() - self.check_text() + self.check_line_lengths() + self.check_trailing_whitespace() self.check_blockquote_classes() self.check_codeblock_classes() @@ -243,10 +248,10 @@ class CheckBase(object): self.reporter.check_field(self.filename, 'metadata', self.metadata, 'layout', self.layout) - def check_text(self): + def check_line_lengths(self): """Check the raw text of the lesson body.""" - if self.args.line_len: + if self.args.line_lengths: over = [i for (i, l, n) in self.lines if (n > MAX_LINE_LEN) and (not l.startswith('!'))] self.reporter.check(not over, self.filename, @@ -254,6 +259,17 @@ class CheckBase(object): ', '.join([str(i) for i in over])) + def check_trailing_whitespace(self): + """Check for whitespace at the ends of lines.""" + + if self.args.trailing_whitespace: + trailing = [i for (i, l, n) in self.lines if l.endswidth(' ')] + self.reporter.check(not trailing, + self.filename, + 'Line(s) end with whitespace: {0}', + ', '.join([str[i] for i in over])) + + def check_blockquote_classes(self): """Check that all blockquotes have known classes.""" diff --git a/bin/util.py b/bin/util.py index 6af0a33..f7aaf2e 100644 --- a/bin/util.py +++ b/bin/util.py @@ -114,9 +114,13 @@ def split_metadata(path, text): def load_yaml(filename): """ - Wrapper around YAML loading so that 'import yaml' and error - handling is only needed in one place. + Wrapper around YAML loading so that 'import yaml' is only needed + in one file. """ - with open(filename, 'r') as reader: - return yaml.load(reader) + try: + with open(filename, 'r') as reader: + return yaml.load(reader) + except (yaml.YAMLError, FileNotFoundError) as e: + print('Unable to load YAML file {0}:\n{1}'.format(filename, e), file=sys.stderr) + sys.exit(1) -- 2.30.2