PARSER=bin/markdown_ast.rb
DST=_site
+# Check Python 3 is installed and determine if it's called via python3 or python
+# (https://stackoverflow.com/a/4933395)
+PYTHON3_EXE := $(shell which python3 2>/dev/null)
+ifneq (, $(PYTHON3_EXE))
+ ifeq (,$(findstring Microsoft/WindowsApps/python3,$(subst \,/,$(PYTHON3_EXE))))
+ PYTHON := python3
+ endif
+endif
+
+ifeq (,$(PYTHON))
+ PYTHON_EXE := $(shell which python 2>/dev/null)
+ ifneq (, $(PYTHON_EXE))
+ PYTHON_VERSION_FULL := $(wordlist 2,4,$(subst ., ,$(shell python --version 2>&1)))
+ PYTHON_VERSION_MAJOR := $(word 1,${PYTHON_VERSION_FULL})
+ ifneq (3, ${PYTHON_VERSION_MAJOR})
+ $(error "Your system does not appear to have Python 3 installed.")
+ endif
+ PYTHON := python
+ else
+ $(error "Your system does not appear to have any Python installed.")
+ endif
+endif
+
+
# Controls
.PHONY : commands clean files
.NOTPARALLEL:
## commands : show all commands.
commands :
- @grep -h -E '^##' ${MAKEFILES} | sed -e 's/## //g'
+ @grep -h -E '^##' ${MAKEFILES} | sed -e "s/## //g"
## docker-serve : use docker to build the site
docker-serve :
## workshop-check : check workshop homepage.
workshop-check :
- @bin/workshop_check.py .
+ @${PYTHON} bin/workshop_check.py .
## ----------------------------------------
## Commands specific to lesson websites.
## lesson-check : validate lesson Markdown.
lesson-check : lesson-fixme
- @bin/lesson_check.py -s . -p ${PARSER} -r _includes/links.md
+ @${PYTHON} bin/lesson_check.py -s . -p ${PARSER} -r _includes/links.md
## lesson-check-all : validate lesson Markdown, checking line lengths and trailing whitespace.
lesson-check-all :
- @bin/lesson_check.py -s . -p ${PARSER} -r _includes/links.md -l -w --permissive
+ @${PYTHON} bin/lesson_check.py -s . -p ${PARSER} -r _includes/links.md -l -w --permissive
## unittest : run unit tests on checking tools.
unittest :
- @bin/test_lesson_check.py
+ @${PYTHON} bin/test_lesson_check.py
## lesson-files : show expected names of generated files for debugging.
lesson-files :
-#!/usr/bin/env python3
-
"""
Check lesson files and their contents.
"""
# specially. This list must include all the Markdown files listed in the
# 'bin/initialize' script.
REQUIRED_FILES = {
- '%/CODE_OF_CONDUCT.md': True,
- '%/CONTRIBUTING.md': False,
- '%/LICENSE.md': True,
- '%/README.md': False,
- '%/_extras/discuss.md': True,
- '%/_extras/guide.md': True,
- '%/index.md': True,
- '%/reference.md': True,
- '%/setup.md': True,
+ 'CODE_OF_CONDUCT.md': True,
+ 'CONTRIBUTING.md': False,
+ 'LICENSE.md': True,
+ 'README.md': False,
+ os.path.join('_extras', 'discuss.md'): True,
+ os.path.join('_extras', 'guide.md'): True,
+ 'index.md': True,
+ 'reference.md': True,
+ 'setup.md': True,
}
# Episode filename pattern.
-P_EPISODE_FILENAME = re.compile(r'/_episodes/(\d\d)-[-\w]+.md$')
+P_EPISODE_FILENAME = re.compile(r'(\d\d)-[-\w]+.md$')
# Pattern to match lines ending with whitespace.
P_TRAILING_WHITESPACE = re.compile(r'\s+$')
"""Are all required files present? Are extraneous files present?"""
# Check files with predictable names.
- required = [p.replace('%', source_dir) for p in REQUIRED_FILES]
+ required = [os.path.join(source_dir, p) for p in REQUIRED_FILES]
missing = set(required) - set(filenames_present)
for m in missing:
reporter.add(None, 'Missing required file {0}', m)
for filename in filenames_present:
if '_episodes' not in filename:
continue
- m = P_EPISODE_FILENAME.search(filename)
+
+ # split path to check episode name
+ base_name = os.path.basename(filename)
+ m = P_EPISODE_FILENAME.search(base_name)
if m and m.group(1):
seen.append(m.group(1))
else:
(re.compile(r'README\.md'), CheckNonJekyll),
(re.compile(r'index\.md'), CheckIndex),
(re.compile(r'reference\.md'), CheckReference),
- (re.compile(r'_episodes/.*\.md'), CheckEpisode),
+ (re.compile(os.path.join('_episodes', '*\.md')), CheckEpisode),
(re.compile(r'.*\.md'), CheckGeneric)
]
-#!/usr/bin/env python3
-
"""Initialize a newly-created repository."""
'CONTRIBUTING.md',
'README.md',
'_config.yml',
- '_episodes/01-introduction.md',
- '_extras/about.md',
- '_extras/discuss.md',
- '_extras/figures.md',
- '_extras/guide.md',
+ os.path.join('_episodes', '01-introduction.md'),
+ os.path.join('_extras', 'about.md'),
+ os.path.join('_extras', 'discuss.md'),
+ os.path.join('_extras', 'figures.md'),
+ os.path.join('_extras', 'guide.md'),
'index.md',
'reference.md',
'setup.md',
# Create.
for path in BOILERPLATE:
shutil.copyfile(
- "bin/boilerplate/{}".format(path),
+ os.path.join('bin', 'boilerplate', path),
path
)
-#!/usr/bin/env python3
-
"""
Check repository settings.
"""
# Guess.
cmd = 'git remote -v'
p = Popen(cmd, shell=True, stdin=PIPE, stdout=PIPE,
- close_fds=True, universal_newlines=True)
+ close_fds=True, universal_newlines=True, encoding='utf-8')
stdout_data, stderr_data = p.communicate()
stdout_data = stdout_data.split('\n')
matches = [P_GIT_REMOTE.match(line) for line in stdout_data]
-#!/usr/bin/env python3
-
import unittest
import lesson_check
def test_file_list_has_expected_entries(self):
# For first pass, simply assume that all required files are present
- all_filenames = [filename.replace('%', '')
- for filename in lesson_check.REQUIRED_FILES]
- lesson_check.check_fileset('', self.reporter, all_filenames)
+ lesson_check.check_fileset('', self.reporter, lesson_check.REQUIRED_FILES)
self.assertEqual(len(self.reporter.messages), 0)
# Parse Markdown.
cmd = 'ruby {0}'.format(parser)
p = Popen(cmd, shell=True, stdin=PIPE, stdout=PIPE,
- close_fds=True, universal_newlines=True)
+ close_fds=True, universal_newlines=True, encoding='utf-8')
stdout_data, stderr_data = p.communicate(body)
doc = json.loads(stdout_data)
-#!/usr/bin/env python3
-
'''Check that a workshop's index.html metadata is valid. See the
docstrings on the checking functions for a summary of the checks.
'''