Commit f687c5f6 authored by Greg Wilson's avatar Greg Wilson
Browse files

Merging changes to requirements

parents 7c022a19 b67d798a
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -31,7 +31,7 @@ motivation.html : motivation.md _layouts/slides.html
	-o $@ $<

## unittest : Run unit test (for Python 2 and 3)
unittest: tools/check tools/validation_helpers.py tools/test_check.py
unittest: tools/check.py tools/validation_helpers.py tools/test_check.py
	cd tools/ && python2 test_check.py
	cd tools/ && python3 test_check.py

+8 −5
Original line number Diff line number Diff line
@@ -18,11 +18,6 @@ div.chapter h2 {
    font-style: italic;
}

/* Objectives and key points */
.objectives, .keypoints {
    background-color: azure;
}

/* Things to fix. */
.fixme {
    text-decoration: underline;
@@ -124,6 +119,14 @@ h1 a, h2 a, h3 a, h4 a, h5 a, h6 a {
    padding: 0em 1em;
}

/* Challenges */
.challenge {
    background-color: #CCFFCC;
    border: 5px solid #CCFFCC;
    margin: 1em 0;
    padding: 0em 1em;
}

/* Things to fix. */
.fixme {
    text-decoration: underline;
+1 −0
Original line number Diff line number Diff line
CommonMark
pandocfilters
PyYAML
+33 −35
Original line number Diff line number Diff line
@@ -20,21 +20,8 @@ import os
import re
import sys

try:
    # Code tested with CommonMark version 0.5.4; API may change
import CommonMark
except ImportError:
    ERROR_MESSAGE = """This program requires the CommonMark python package.
Install using

    # pip install commonmark

or

    # easy_install commonmark
"""
    print(ERROR_MESSAGE)
    sys.exit(1)
import yaml

import validation_helpers as vh

@@ -101,9 +88,8 @@ class MarkdownValidator(object):
                valid = False
        return valid

    def _validate_one_doc_header_row(self, text):
    def _validate_one_doc_header_row(self, label, content):
        """Validate a single row of the document header section"""
        label, content = text.split(":", 1)
        if label not in self.DOC_HEADERS:
            logging.warning(
                "In {0}: "
@@ -116,8 +102,8 @@ class MarkdownValidator(object):
        if not validate_header:
            logging.error(
                "In {0}: "
                "Document header field for label {1} "
                "does not follow expected format".format(self.filename, label))
                "Contents of document header field for label {1} "
                "do not follow expected format".format(self.filename, label))
        return validate_header

    # Methods related to specific validation. Can override specific tests.
@@ -127,21 +113,37 @@ class MarkdownValidator(object):
        Pass only if the header of the document contains the specified
            sections with the expected contents"""

        # Header section should be wrapped in hrs
        # Test: Header section should be wrapped in hrs
        has_hrs = self._validate_hrs()

        # Labeled sections in the actual headers should match expected format
        header_node = self.ast.children[1]
        test_headers = [self._validate_one_doc_header_row(s)
                        for s in header_node.strings]
        header_text = '\n'.join(header_node.strings)

        # Parse headers as YAML. Don't check if parser returns None or str.
        header_yaml = yaml.load(header_text)
        if not isinstance(header_yaml, dict):
            logging.error("In {0}: "
                          "Expected YAML markup with labels "
                          "{1}".format(self.filename, self.DOC_HEADERS.keys()))
            return False

        # Must have all expected header lines, and no others.
        only_headers = (len(header_node.strings) == len(self.DOC_HEADERS))
        # Test: Labeled YAML should match expected format
        test_headers = [self._validate_one_doc_header_row(k, v)
                        for k, v in header_yaml.items()]

        # Headings must appear in the order expected
        valid_order = self._validate_section_heading_order()
        # Test: Must have all expected header lines, and no others.
        only_headers = (len(header_yaml) == len(self.DOC_HEADERS))

        return has_hrs and all(test_headers) and only_headers and valid_order
        # If expected headings are missing, print an informative message
        missing_headings = [h for h in self.DOC_HEADERS
                            if h not in header_yaml]

        for h in missing_headings:
            logging.error("In {0}: "
                          "Header section is missing expected "
                          "row {1}".format(self.filename, h))

        return has_hrs and all(test_headers) and only_headers

    def _validate_section_heading_order(self, ast_node=None, headings=None):
        """Verify that section headings appear, and in the order expected"""
@@ -344,8 +346,8 @@ class IndexPageValidator(MarkdownValidator):
        return super(IndexPageValidator, self)._validate_links(links_to_skip)

    def _run_tests(self):
        tests = [self._validate_intro_section()]
        parent_tests = super(IndexPageValidator, self)._run_tests()
        tests = [self._validate_intro_section()]
        return all(tests) and parent_tests


@@ -397,9 +399,9 @@ class TopicPageValidator(MarkdownValidator):
        return False

    def _run_tests(self):
        parent_tests = super(TopicPageValidator, self)._run_tests()
        tests = [self._validate_has_no_headings(),
                 self._validate_learning_objective()]
        parent_tests = super(TopicPageValidator, self)._run_tests()
        return all(tests) and parent_tests


@@ -499,7 +501,7 @@ class LicensePageValidator(MarkdownValidator):
    def _run_tests(self):
        """Skip the base tests; just check md5 hash"""
        # TODO: This hash is specific to the license for english-language repo
        expected_hash = '258aa6822fa77f7c49c37c3759017891'
        expected_hash = 'cd5742b6596a1f2f35c602ad43fa24b2'
        m = hashlib.md5()
        try:
            m.update(self.markdown)
@@ -661,7 +663,3 @@ def main(parsed_args_obj):
if __name__ == "__main__":
    parsed_args = command_line()
    main(parsed_args)

    #### Sample of how validator is used directly
    # validator = HomePageValidator('../index.md')
    # print validator.validate()
+14 −14
Original line number Diff line number Diff line
@@ -7,14 +7,11 @@ Some of these tests require looking for example files, which exist only on
the gh-pages branch.   Some tests may therefore fail on branch "core".
"""


import imp
import logging
import os
import unittest

check = imp.load_source("check",  # Import non-.py file
                        os.path.join(os.path.dirname(__file__), "check"))
import check

# Make log messages visible to help audit test failures
check.start_logging(level=logging.DEBUG)
@@ -63,7 +60,6 @@ class TestIndexPage(BaseTemplateTest):

layout: lesson
title: Lesson Title
keywords: ["some", "key terms", "in a list"]

Another section that isn't an HR
""")
@@ -74,7 +70,6 @@ Another section that isn't an HR
        """One of the required headers is missing"""
        validator = self._create_validator("""---
layout: lesson
keywords: ["some", "key terms", "in a list"]
---""")
        self.assertFalse(validator._validate_doc_headers())

@@ -83,16 +78,14 @@ keywords: ["some", "key terms", "in a list"]
        validator = self._create_validator("""---
layout: lesson
title: Lesson Title
keywords: ["some", "key terms", "in a list"]
otherline: Nothing
---""")
        self.assertFalse(validator._validate_doc_headers())

    def test_headers_fail_because_invalid_content(self):
    def test_fail_when_headers_not_yaml_dict(self):
        """Fail when the headers can't be parsed to a dict of YAML data"""
        validator = self._create_validator("""---
layout: lesson
title: Lesson Title
keywords: this is not a list
This will parse as a string, not a dictionary
---""")
        self.assertFalse(validator._validate_doc_headers())

@@ -158,7 +151,6 @@ Paragraph of introductory material.
        validator = self._create_validator("""---
layout: lesson
title: Lesson Title
keywords: ["some", "key terms", "in a list"]
---
Paragraph of introductory material.

@@ -185,7 +177,6 @@ Paragraph of introductory material.
        validator = self._create_validator("""---
layout: lesson
title: Lesson Title
keywords: ["some", "key terms", "in a list"]
---
Paragraph of introductory material.

@@ -200,7 +191,6 @@ Paragraph of introductory material.
        validator = self._create_validator("""---
layout: lesson
title: Lesson Title
keywords: ["some", "key terms", "in a list"]
---
Paragraph of introductory material.

@@ -295,6 +285,16 @@ class TestTopicPage(BaseTemplateTest):
    SAMPLE_FILE = os.path.join(MARKDOWN_DIR, "01-one.md")
    VALIDATOR = check.TopicPageValidator

    def test_headers_fail_because_invalid_content(self):
        """The value provided as YAML does not match the expected datatype"""
        validator = self._create_validator("""---
layout: lesson
title: Lesson Title
subtitle: A page
minutes: not a number
---""")
        self.assertFalse(validator._validate_doc_headers())

    def test_sample_file_passes_validation(self):
        sample_validator = self.VALIDATOR(self.SAMPLE_FILE)
        res = sample_validator.validate()