Remove software carpentries logo
[rnaseq-cwl-training.git] / bin / workshop_check.py
old mode 100755 (executable)
new mode 100644 (file)
index 3b6f6f2..15d954a
@@ -1,16 +1,13 @@
-#!/usr/bin/env python
-
 '''Check that a workshop's index.html metadata is valid.  See the
 docstrings on the checking functions for a summary of the checks.
 '''
 
+
 import sys
 import os
 import re
-import yaml
 from datetime import date
-from util import Reporter, split_metadata
-
+from util import Reporter, split_metadata, load_yaml, check_unwanted_files
 
 # Metadata field patterns.
 EMAIL_PATTERN = r'[^@]+@[^@]+\.[^@]+'
@@ -19,10 +16,10 @@ EVENTBRITE_PATTERN = r'\d{9,10}'
 URL_PATTERN = r'https?://.+'
 
 # Defaults.
-CARPENTRIES = ("dc", "swc")
+CARPENTRIES = ("dc", "swc", "lc", "cp")
 DEFAULT_CONTACT_EMAIL = 'admin@software-carpentry.org'
 
-USAGE = 'Usage: "check-workshop path/to/root/directory"'
+USAGE = 'Usage: "workshop_check.py path/to/root/directory"'
 
 # Country and language codes.  Note that codes mean different things: 'ar'
 # is 'Arabic' as a language but 'Argentina' as a country.
@@ -92,7 +89,7 @@ def check_layout(layout):
 
 @look_for_fixme
 def check_carpentry(layout):
-    '''"carpentry" in YAML header must be "dc" or "swc".'''
+    '''"carpentry" in YAML header must be "dc", "swc", "lc", or "cp".'''
 
     return layout in CARPENTRIES
 
@@ -118,7 +115,7 @@ def check_humandate(date):
     and 4-digit year.  Examples include 'Feb 18-20, 2025' and 'Feb 18
     and 20, 2025'.  It may be in languages other than English, but the
     month name should be kept short to aid formatting of the main
-    Software Carpentry web site.
+    Carpentries web site.
     """
 
     if ',' not in date:
@@ -175,8 +172,8 @@ def check_latitude_longitude(latlng):
     try:
         lat, lng = latlng.split(',')
         lat = float(lat)
-        long = float(lng)
-        return (-90.0 <= lat <= 90.0) and (-180.0 <= long <= 180.0)
+        lng = float(lng)
+        return (-90.0 <= lat <= 90.0) and (-180.0 <= lng <= 180.0)
     except ValueError:
         return False
 
@@ -204,15 +201,22 @@ def check_helpers(helpers):
 
 
 @look_for_fixme
-def check_email(email):
+def check_emails(emails):
     """
-    'contact' must be a valid email address consisting of characters,
-    an '@', and more characters.  It should not be the default contact
-    email address 'admin@software-carpentry.org'.
+    'emails' must be a comma-separated list of valid email addresses.
+    The list may be empty. A valid email address consists of characters,
+    an '@', and more characters.  It should not contain the default contact
     """
 
-    return bool(re.match(EMAIL_PATTERN, email)) and \
-           (email != DEFAULT_CONTACT_EMAIL)
+    # YAML automatically loads list-like strings as lists.
+    if (isinstance(emails, list) and len(emails) >= 0):
+        for email in emails:
+            if ((not bool(re.match(EMAIL_PATTERN, email))) or (email == DEFAULT_CONTACT_EMAIL)):
+                return False
+    else:
+        return False
+
+    return True
 
 
 def check_eventbrite(eventbrite):
@@ -228,12 +232,12 @@ def check_eventbrite(eventbrite):
 
 
 @look_for_fixme
-def check_etherpad(etherpad):
+def check_collaborative_notes(collaborative_notes):
     """
-    'etherpad' must be a valid URL.
+    'collaborative_notes' must be a valid URL.
     """
 
-    return bool(re.match(URL_PATTERN, etherpad))
+    return bool(re.match(URL_PATTERN, collaborative_notes))
 
 
 @look_for_fixme
@@ -287,13 +291,14 @@ HANDLERS = {
                    'helper list isn\'t a valid list of format ' +
                    '["First helper", "Second helper",..]'),
 
-    'contact':    (True, check_email,
-                   'contact email invalid or still set to ' +
-                   '"{0}".'.format(DEFAULT_CONTACT_EMAIL)),
+    'email':    (True, check_emails,
+                 'contact email list isn\'t a valid list of format ' +
+                 '["me@example.org", "you@example.org",..] or contains incorrectly formatted email addresses or ' +
+                 '"{0}".'.format(DEFAULT_CONTACT_EMAIL)),
 
     'eventbrite': (False, check_eventbrite, 'Eventbrite key appears invalid'),
 
-    'etherpad':   (False, check_etherpad, 'Etherpad URL appears invalid'),
+    'collaborative_notes':   (False, check_collaborative_notes, 'Collaborative Notes URL appears invalid'),
 
     'venue':      (False, check_pass, 'venue name not specified'),
 
@@ -301,10 +306,10 @@ HANDLERS = {
 }
 
 # REQUIRED is all required categories.
-REQUIRED = set([k for k in HANDLERS if HANDLERS[k][0]])
+REQUIRED = {k for k in HANDLERS if HANDLERS[k][0]}
 
 # OPTIONAL is all optional categories.
-OPTIONAL = set([k for k in HANDLERS if not HANDLERS[k][0]])
+OPTIONAL = {k for k in HANDLERS if not HANDLERS[k][0]}
 
 
 def check_blank_lines(reporter, raw):
@@ -312,7 +317,8 @@ def check_blank_lines(reporter, raw):
     Blank lines are not allowed in category headers.
     """
 
-    lines = [(i, x) for (i, x) in enumerate(raw.strip().split('\n')) if not x.strip()]
+    lines = [(i, x) for (i, x) in enumerate(
+        raw.strip().split('\n')) if not x.strip()]
     reporter.check(not lines,
                    None,
                    'Blank line(s) in header: {0}',
@@ -373,13 +379,19 @@ def check_config(reporter, filename):
     Check YAML configuration file.
     """
 
-    with open(filename, 'r') as reader:
-        config = yaml.load(reader)
+    config = load_yaml(filename)
+
+    kind = config.get('kind', None)
+    reporter.check(kind == 'workshop',
+                   filename,
+                   'Missing or unknown kind of event: {0}',
+                   kind)
 
-    reporter.check(config['kind'] == 'workshop',
+    carpentry = config.get('carpentry', None)
+    reporter.check(carpentry in ('swc', 'dc', 'lc', 'cp'),
                    filename,
-                   'Not configured as a workshop: found "{0}" instead',
-                   config['kind'])
+                   'Missing or unknown carpentry: {0}',
+                   carpentry)
 
 
 def main():
@@ -395,7 +407,8 @@ def main():
 
     reporter = Reporter()
     check_config(reporter, config_file)
-    with open(index_file) as reader:
+    check_unwanted_files(root_dir, reporter)
+    with open(index_file, encoding='utf-8') as reader:
         data = reader.read()
         check_file(reporter, index_file, data)
     reporter.report()