From 1a7da68572e976823722b358c756e781a447f47b Mon Sep 17 00:00:00 2001 From: Brenda Anderson Date: Sat, 10 Jan 2026 09:18:54 +1300 Subject: [PATCH 1/2] Add checks for Homepage Add checks for the Homepage requirements. Checks are purposefully "loose" but should address all major requirements. --- homepage/__init__.py | 131 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 128 insertions(+), 3 deletions(-) diff --git a/homepage/__init__.py b/homepage/__init__.py index 1e7aad5d..f75cf397 100644 --- a/homepage/__init__.py +++ b/homepage/__init__.py @@ -1,6 +1,131 @@ +import os +import re + import check50 + +# helper +def html_pages(): + return sorted(f for f in os.listdir(".") if f.endswith(".html")) + + @check50.check() -def submitted(): - """Homepage submitted""" - \ No newline at end of file +def required_files(): + """required files exist""" + check50.exists("index.html") + check50.exists("styles.css") + check50.exists("specification.txt") + + +@check50.check(required_files) +def four_pages(): + """contains at least 4 HTML pages including index.html""" + pages = html_pages() + if len(pages) < 4: + raise check50.Failure("expected at least 4 HTML pages") + + +@check50.check(four_pages) +def navigation(): + """pages link to each other""" + pages = html_pages() + href_re = re.compile(r"""href\s*=\s*["']([^"']+)["']""", re.I) + + for p in pages: + html = open(p).read() + for m in href_re.finditer(html): + href = m.group(1).split("#", 1)[0].split("?", 1)[0] + if href in pages and href != p: + break + else: + raise check50.Failure("one or more pages do not link to another page") + + +@check50.check(four_pages) +def ten_distinct_tags(): + """contains at least 10 distinct HTML tags besides html/head/body/title""" + tag_re = re.compile(r"<\s*([a-zA-Z][\w:-]*)\b") + used = set() + + for p in html_pages(): + page = open(p).read() + for m in tag_re.finditer(page): + used.add(m.group(1).lower()) + excluded_tags = {"html", "head", "body", "title"} + used -= excluded_tags + if len(used) < 10: + raise check50.Failure("fewer than 10 distinct HTML tags were found") + + +@check50.check(four_pages) +def bootstrap(): + """Bootstrap is used""" + for p in html_pages(): + if "bootstrap" in open(p).read().lower(): + return + + raise check50.Failure( + "Bootstrap not detected", + help="Use Bootstrap on at least one page of your site." + ) + + +@check50.check(four_pages) +def stylesheet(): + """styles.css is linked""" + for p in html_pages(): + if "styles.css" in open(p).read().lower(): + return + + raise check50.Failure( + "styles.css not linked", + help="Link your own stylesheet (styles.css) from at least one page." + ) + + +@check50.check(four_pages) +def css_rules(): + """styles.css uses at least 5 selectors and 5 distinct properties""" + css = open("styles.css").read() + + # Count number of rule blocks + selector_count = css.count("{") + + # Set of any "name:" occurrences + props_count = len(set(re.findall(r"([a-zA-Z-]+)\s*:", css))) + + if selector_count < 5: + raise check50.Failure("styles.css does not appear to use at least 5 selectors") + + if props_count < 5: + raise check50.Failure("styles.css does not appear to use at least 5 CSS properties") + + +@check50.check(four_pages) +def javascript(): + """JavaScript is used""" + for p in html_pages(): + if " Date: Fri, 9 Jan 2026 20:27:15 -0500 Subject: [PATCH 2/2] Use context managers for file handling in homepage checks --- homepage/__init__.py | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/homepage/__init__.py b/homepage/__init__.py index f75cf397..84438b5e 100644 --- a/homepage/__init__.py +++ b/homepage/__init__.py @@ -32,7 +32,8 @@ def navigation(): href_re = re.compile(r"""href\s*=\s*["']([^"']+)["']""", re.I) for p in pages: - html = open(p).read() + with open(p) as f: + html = f.read() for m in href_re.finditer(html): href = m.group(1).split("#", 1)[0].split("?", 1)[0] if href in pages and href != p: @@ -48,7 +49,8 @@ def ten_distinct_tags(): used = set() for p in html_pages(): - page = open(p).read() + with open(p) as f: + page = f.read() for m in tag_re.finditer(page): used.add(m.group(1).lower()) excluded_tags = {"html", "head", "body", "title"} @@ -61,8 +63,9 @@ def ten_distinct_tags(): def bootstrap(): """Bootstrap is used""" for p in html_pages(): - if "bootstrap" in open(p).read().lower(): - return + with open(p) as f: + if "bootstrap" in f.read().lower(): + return raise check50.Failure( "Bootstrap not detected", @@ -74,8 +77,9 @@ def bootstrap(): def stylesheet(): """styles.css is linked""" for p in html_pages(): - if "styles.css" in open(p).read().lower(): - return + with open(p) as f: + if "styles.css" in f.read().lower(): + return raise check50.Failure( "styles.css not linked", @@ -86,7 +90,8 @@ def stylesheet(): @check50.check(four_pages) def css_rules(): """styles.css uses at least 5 selectors and 5 distinct properties""" - css = open("styles.css").read() + with open("styles.css") as f: + css = f.read() # Count number of rule blocks selector_count = css.count("{") @@ -105,8 +110,9 @@ def css_rules(): def javascript(): """JavaScript is used""" for p in html_pages(): - if "