Update plugins
diff --git a/theme/plugins/asfdata.py b/theme/plugins/asfdata.py
index 1c4087f..342c027 100644
--- a/theme/plugins/asfdata.py
+++ b/theme/plugins/asfdata.py
@@ -21,10 +21,12 @@
 #
 
 import os.path
+import sys
 import random
 import json
 import traceback
 import operator
+import pprint
 
 import requests
 import yaml
@@ -41,34 +43,40 @@
     'debug': False,
 }
 
+# read the asfdata configuration in order to get data load and transformation instructions.
 def read_config(config_yaml):
     with pelican.utils.pelican_open(config_yaml) as text:
         config_data = yaml.safe_load(text)
-        print(config_data)
+        pp = pprint.PrettyPrinter(indent=2)
+        pp.pprint(config_data)
     return config_data
 
 
+# load yaml and json data sources.
 def load_data(path, content):
     parts = path.split('/')
     extension = os.path.splitext(parts[-1])[1]  # split off ext, keep ext
-    print(f"Loading {extension} from {path}")
-    if extension == ".json":
+    print(f'Loading {extension} from {path}')
+    if extension == '.json':
         load = json.loads(content)
-    elif extension == ".yaml":
+    elif extension == '.yaml':
         load = yaml.safe_load(content)
     else:
         load = { }
     return load
 
 
+# load data source from a url.
 def url_data(url):
     return load_data( url, requests.get(url).text )
 
 
+# load data source from a file.
 def file_data(rel_path):
     return load_data( rel_path, open(rel_path,'r').read() )
 
 
+# remove parts of a data source we don't want ro access
 def remove_part(reference, part):
     for refs in reference:
         if refs == part:
@@ -78,16 +86,21 @@
             remove_part(reference[refs], part)
 
 
+# trim out parts of a data source that don't match part = True
 def where_parts(reference, part):
     # currently only works on True parts
+    # if we trim as we go we invalidate the iterator. Instead create a deletion list.
     filtered = [ ]
+    # first find the list that needs to be trimmed.
     for refs in reference:
         if not reference[refs][part]:
             filtered.append(refs)
+    # remove the parts to be trimmed.
     for refs in filtered:
         del reference[refs]
 
 
+# perform alphabetation. HTTP Server is special.
 def alpha_part(reference, part):
     for refs in reference:
         name = reference[refs][part]
@@ -99,6 +112,7 @@
         reference[refs]['letter'] = letter
 
 
+# rotate a roster list singleton into an name and availid 
 def asfid_part(reference, part):
     for refs in reference:
         fix = reference[refs][part]
@@ -109,18 +123,20 @@
         reference[refs]['availid'] = availid
 
 
+# add logo attribute with HEAD check for existence. If nonexistent use default.
 def add_logo(reference, part):
+    # split between logo pattern and default.
     parts = part.split(',')
     for item in reference:
         logo = (parts[0].format(item.key_id))
-        response = requests.head("https://www.apache.org/" + logo)
+        response = requests.head('https://www.apache.org/' + logo)
         if response.status_code != 200:
             logo = parts[1]
         setattr(item, 'logo', logo)
-        print(logo, item.logo)
     return reference
 
 
+# convert a dictionary into a sequence (list)
 def sequence_dict(seq, reference):
     sequence = [ ]
     for refs in reference:
@@ -133,6 +149,7 @@
     return sequence
 
 
+# convert a list into a sequence. convert dictionaries items into objects.
 def sequence_list(seq, reference):
     sequence = [ ]
     for refs in reference:
@@ -142,13 +159,11 @@
                     refs[item] = ezt.boolean(refs[item])
                 elif isinstance(refs[item], list):
                     refs[item] = sequence_list(item, refs[item])
-            sequence.append(type(f"{seq}", (), refs))
-    print(f"{seq} {sequence}")
-    for item in sequence:
-        print(vars(item))
+            sequence.append(type(f'{seq}', (), refs))
     return sequence
 
 
+# split a list into equal sized columns. Adds back letter breaks in the alphabetical sequence.
 def split_list(metadata, seq, reference, split):
     # copy sequence
     sequence = list(reference)
@@ -174,12 +189,13 @@
                 nseq = nseq+1
             nrow = nrow+1
         # save the column sequence in the metadata
-        metadata[f"{seq}_{column}"] = subsequence
+        metadata[f'{seq}_{column}'] = subsequence
         start = end
     if nseq < size:
-        print(f"WARNING: {seq} not all of sequence consumed: short {size-nseq} projects")
+        print(f'WARNING: {seq} not all of sequence consumed: short {size-nseq} projects')
 
 
+# process sequencing transformations to the data source
 def process_sequence(metadata, seq, sequence, load, debug):
     reference = load
     # has been converted to a sequence
@@ -191,46 +207,40 @@
 
     # description
     if 'description' in sequence:
-        print(f"{seq}: {sequence['description']}")
+        print(f'{seq}: {sequence["description"]}')
 
     # select sub dictionary
     if 'path' in sequence:
-        if debug:
-            print(f"path: {sequence['path']}")
+        print(f'path: {sequence["path"]}')
         parts = sequence['path'].split('.')
         for part in parts:
             reference = reference[part]
 
     # filter dictionary by attribute value. if filter is false discard
     if 'where' in sequence:
-        if debug:
-            print(f"where: {sequence['where']}")
+        print(f'where: {sequence["where"]}')
         where_parts(reference, sequence['where'])
 
     # remove irrelevant keys
     if 'trim' in sequence:
-        if debug:
-            print(f"trim: {sequence['trim']}")
+        print(f'trim: {sequence["trim"]}')
         parts = sequence['trim'].split(',')
         for part in parts:
             remove_part(reference, part)
 
     # transform roster and chair patterns
     if 'asfid' in sequence:
-        if debug:
-            print(f"asfid: {sequence['asfid']}")
+        print(f'asfid: {sequence["asfid"]}')
         asfid_part(reference, sequence['asfid'])
 
     # add first letter ofr alphabetic categories
     if 'alpha' in sequence:
-        if debug:
-            print(f"alpha: {sequence['alpha']}")
+        print(f'alpha: {sequence["alpha"]}')
         alpha_part(reference, sequence['alpha'])
 
     # this dictionary is derived from sequences
     if 'dictionary' in sequence:
-        if debug:
-            print(f"dictionary: {sequence['dictionary']}")
+        print(f'dictionary: {sequence["dictionary"]}')
         reference = { }
         paths = sequence['dictionary'].split(',')
         for path in paths:
@@ -240,59 +250,55 @@
 
     # this sequence is derived from another sequence
     if 'sequence' in sequence:
-        if debug:
-            print(f"sequence: {sequence['sequence']}")
+        print(f'sequence: {sequence["sequence"]}')
         reference = metadata[sequence['sequence']]
         is_sequence = True
 
     # this sequence is a random sample of another sequence
     if 'random' in sequence:
-        if debug:
-            print(f"random: {sequence['random']}")
+        print(f'random: {sequence["random"]}')
         if is_sequence:
             reference = random.sample(reference, sequence['random'])
         else:
-            print(f"{seq} - random requires an existing sequence to sample")
+            print(f'{seq} - random requires an existing sequence to sample')
 
     # for a project or podling see if the logo exists w/HEAD and set the relative path.
     if 'logo' in sequence:
-        if debug:
-            print(f"logo: {sequence['logo']}")
+        print(f'logo: {sequence["logo"]}')
         if is_sequence:
             reference = add_logo(reference, sequence['logo'])
             if seq == 'featured_pods':
                 # for podlings strip "Apache" from the beginning and "(incubating)" from the end.
                 for item in reference:
-                    setattr(item, 'name', " ".join(item.name.split(' ')[1:-1]))
+                    setattr(item, 'name', ' '.join(item.name.split(' ')[1:-1]))
         else:
-            print(f"{seq} - logo requires an existing sequence")
+            print(f'{seq} - logo requires an existing sequence')
 
     # this sequence is a sorted list divided into multiple columns
     if 'split' in sequence:
-        if debug:
-            print(f"split: {sequence['split']}")
+        print(f'split: {sequence["split"]}')
         if is_sequence:
             split_list(metadata, seq, reference, sequence['split'])
             save_metadata = False
         else:
-            print(f"{seq} - split requires an existing sequence to split")
+            print(f'{seq} - split requires an existing sequence to split')
 
     # convert the dictionary/list to a sequence of objects
     if not is_sequence and not is_dictionary:
-        if debug:
-            print(f"{seq}: create sequence")
+        print(f'{seq}: create sequence')
         if isinstance(reference, dict):
             reference = sequence_dict(seq, reference)
         elif isinstance(reference, list):
             reference = sequence_list(seq, reference)
         else:
-            print(f"{seq}: cannot proceed invalid type, must be dict or list")
+            print(f'{seq}: cannot proceed invalid type, must be dict or list')
 
     # save sequence in metadata
     if save_metadata:
         metadata[seq] = reference
 
 
+# create metadata sequences and dictionaries from a data load
 def process_load(metadata, value, load, debug):
     for seq in value:
         if seq not in ('url', 'file'):
@@ -301,61 +307,69 @@
             process_sequence(metadata, seq, sequence, load, debug)
 
 
+# get xml text node
 def get_node_text(nodelist):
     """http://www.python.org/doc/2.5.2/lib/minidom-example.txt"""
-    rc = ""
+    rc = ''
     for node in nodelist:
         if node.nodeType == node.TEXT_NODE:
             rc = rc + node.data
     return rc
 
 
+# get xml element's text nodes.
 def get_element_text(entry, child):
     elements = entry.getElementsByTagName(child)
     return get_node_text(elements[0].childNodes)
 
 
-def process_blog(feed, count):
+# retrieve blog posts from an Atom feed.
+def process_blog(feed, count, debug):
+    print(f'blog feed: {feed}')
     content = requests.get(feed).text
     dom = xml.dom.minidom.parseString(content)
     entries = dom.getElementsByTagName('entry')
     entries = entries[:count]
     v = [ ]
     for entry in entries:
-        print(entry.tagName)
+        if debug:
+            print(entry.tagName)
         v.append(
             {
                 'id': get_element_text(entry, 'id'),
                 'title': get_element_text(entry, 'title'),
             }
         )
-    for s in v:
-        print(s)
+    if debug:
+        for s in v:
+            print(s)
 
     return [ Blog(href=s['id'],
                   title=s['title'])
              for s in v ]
 
 
+# to be updated from hidden location. (Need to discuss local.)
 def twitter_auth():
-    return "AAAAAAAAAAAAAAAAAAAAACg4PgEAAAAApGfiQijpZK4EQmSvWFLqYE%2FWD%2BI%3D4F9v6SszNmT3lf8o2scY28Zlv7XilgfhMIOFdiFcUmaHfg2PwH"
+    return 'AAAAAAAAAAAAAAAAAAAAACg4PgEAAAAApGfiQijpZK4EQmSvWFLqYE%2FWD%2BI%3D4F9v6SszNmT3lf8o2scY28Zlv7XilgfhMIOFdiFcUmaHfg2PwH'
 
 
+# retrieve from twitter
 def connect_to_endpoint(url, headers):
-    response = requests.request("GET", url, headers=headers)
+    response = requests.request('GET', url, headers=headers)
     if response.status_code != 200:
         raise Exception(response.status_code, response.text)
     return response.json()
 
 
+# retrieve the last count recent tweets from the handle.
 def process_twitter(handle, count):
+    print(f'-----\ntwitter feed: {handle}')
     bearer_token = twitter_auth()
-    query = f"from:{handle}"
-    tweet_fields = "tweet.fields=author_id"
-    url = "https://api.twitter.com/2/tweets/search/recent?query={}&{}".format(
-        query, tweet_fields
-    )
-    headers = {"Authorization": "Bearer {}".format(bearer_token)}
+    query = f'from:{handle}'
+    tweet_fields = 'tweet.fields=author_id'
+    url = f'https://api.twitter.com/2/tweets/search/recent?query={query}&{tweet_fields}'
+    headers = {'Authorization': f'Bearer {bearer_token}'}
     load = connect_to_endpoint(url, headers)
     reference = sequence_list('twitter', load['data'])
     if load['meta']['result_count'] < count:
@@ -365,8 +379,9 @@
     return v
 
 
+# create sequence of sequences of ASF ECCN data.
 def process_eccn(fname):
-    print('ECCN:', fname)
+    print('-----\nECCN:', fname)
     j = yaml.safe_load(open(fname))
 
     def make_sources(sources):
@@ -399,6 +414,7 @@
                                 key=operator.itemgetter('name')) ]
 
 
+# object wrappers
 class wrapper:
     def __init__(self, **kw):
         vars(self).update(kw)
@@ -411,19 +427,21 @@
 class Blog(wrapper): pass
 
 
+# create metadata according to instructions.
 def config_read_data(pel_ob):
-    print("-----\nasfdata")
+    print('-----\nasfdata')
 
     asf_data = pel_ob.settings.get('ASF_DATA')
-    print('ASFDATA:', asf_data)
 
     if not asf_data:
-        # This Pelican installation is not using ASF_DATA
+        print('This Pelican installation is not using ASF_DATA')
         return
 
     for key in asf_data:
-        print(f"config: [{key}] = {asf_data[key]}")
+        print(f'config: [{key}] = {asf_data[key]}')
 
+    debug = asf_data['debug']
+    
     # This must be present in ASF_DATA. It contains data for use
     # by our plugins, and possibly where we load/inject data from
     # other sources.
@@ -431,7 +449,7 @@
 
     # Lift data from ASF_DATA['data'] into METADATA
     if 'data' in asf_data:
-        print(f"Processing {asf_data['data']}")
+        print(f'Processing {asf_data["data"]}')
         config_data = read_config(asf_data['data'])
         for key in config_data:
             # first check for data that is a singleton with special handling
@@ -439,7 +457,8 @@
                 # process eccn data
                 fname = config_data[key]['file']
                 metadata[key] = v = process_eccn(fname)
-                print('ECCN V:', v)
+                if debug:
+                    print('ECCN V:', v)
                 continue
 
             if key == 'twitter':
@@ -447,54 +466,68 @@
                 handle = config_data[key]['handle']
                 count = config_data[key]['count']
                 metadata[key] = v = process_twitter(handle, count)
-                print('TWITTER V:', v)
+                if debug:
+                    print('TWITTER V:', v)
                 continue
 
             value = config_data[key]
             if isinstance(value, dict):
                 # dictionaries are complex data sources
-                print(f"{key} is a dict")
-                print(value)
+                print(f'-----\n{key} creates one or more sequences')
+                if debug:
+                    print(value)
                 # special cases that are multiple are processed first
                 if 'blog' in value:
                     # process blog feed
                     feed = config_data[key]['blog']
                     count = config_data[key]['count']
-                    v = process_blog(feed, count)
-                    print('BLOG V:', v)
-                    metadata[key] = v
+                    metadata[key] = v = process_blog(feed, count, debug)
+                    if debug:
+                        print('BLOG V:', v)
                     continue
 
                 elif 'url' in value:
                     # process a url based data source
                     load = url_data(value['url'])
-                    process_load(metadata, value, load, asf_data['debug'])
+                    process_load(metadata, value, load, debug)
 
                 elif 'file' in value:
                     # process a file from within the site tree
                     load = file_data(value['file'])
-                    process_load(metadata, value, load, asf_data['debug'])
+                    process_load(metadata, value, load, debug)
 
                 else:
                     # should probably be an error.
                     metadata[key] = value
             else:
                 # simple metadata values
-                print(f"{key} = {value}")
+                print(f'{key} = {value}')
                 metadata[key] = value
 
-    print("-----")
+    # display asfdata metadata.
+    print('-----')
     for key in metadata:
-        print(f"metadata[{key}] =")
-        print(metadata[key])
-        print("-----")
+        if debug:
+            print(f'metadata[{key}] =')
+            print(metadata[key])
+            print('-----')
+        elif isinstance(metadata[key], str):
+            print(f'metadata[{key}] = "{metadata[key]}"')
+        elif isinstance(metadata[key], list):
+            print(f'metadata[{key}] is a sequence.')
+        elif isinstance(metadata[key], dict):
+            print(f'metadata[{key}] is a dictionary.')
+        else:
+            keytype = type(metadata[key])
+            print(f'metadata[{key}] is a {keytype}')
 
 
 def tb_initialized(pel_ob):
-    "Print any exception, before Pelican chews it into nothingness."
+    """ Print any exception, before Pelican chews it into nothingness."""
     try:
         config_read_data(pel_ob)
     except:
+        print('-----', file=sys.stderr)
         traceback.print_exc()
         raise
 
diff --git a/theme/plugins/asfgenid.py b/theme/plugins/asfgenid.py
index bf951e8..1c49973 100644
--- a/theme/plugins/asfgenid.py
+++ b/theme/plugins/asfgenid.py
@@ -31,7 +31,7 @@
     'headings': True,
     'headings_re': r'^h[1-6]',
     'toc': True,
-    'toc_headers': r"h[1-6]",
+    'toc_headers': r'h[1-6]',
     'permalinks': True,
     'tables': True,
     'debug': False
@@ -85,7 +85,7 @@
             new_string = new_header.find_all(
                 text=lambda t: not isinstance(t, Comment),
                 recursive=True)
-            new_string = "".join(new_string)
+            new_string = ''.join(new_string)
         new_string = new_string.translate(PARA_MAP)
 
         if self.level < new_level:
@@ -100,7 +100,7 @@
             return self.parent.add(new_header)
 
     def __str__(self):
-        ret = ""
+        ret = ''
         if self.parent:
             ret = "<a class='toc-href' href='#{0}' title='{1}'>{1}</a>".format(
                 self.id, self.header)
@@ -139,7 +139,7 @@
 def unique(id, ids):
     while id in ids or not id:
         m = IDCOUNT_RE.match(id)
-        print(f"id=\"{id}\" is a duplicate")
+        print(f'id="{id}" is a duplicate')
         if m:
             id = '%s_%d' % (m.group(1), int(m.group(2)) + 1)
         else:
@@ -150,9 +150,9 @@
 
 # append a permalink
 def permalink(soup, mod_element):
-    new_tag = soup.new_tag('a', href="#" + mod_element['id'])
-    new_tag['class'] = "headerlink"
-    new_tag['title'] = "Permalink"
+    new_tag = soup.new_tag('a', href='#' + mod_element['id'])
+    new_tag['class'] = 'headerlink'
+    new_tag['title'] = 'Permalink'
     new_tag.string = LINK_CHAR
     mod_element.append(new_tag)
 
@@ -191,10 +191,10 @@
                     new_string = ref
                 else:
                     if len(parts) == 3:
-                        this_data = f"{parts[0]}[{parts[1]}].{parts[2]}"
+                        this_data = f'{parts[0]}[{parts[1]}].{parts[2]}'
                     format_string = '{{{0}}}'.format(this_data)
                     new_string = format_string.format(**metadata)
-                print(f"{{{{{m.group(1)}}}}} -> {new_string}")
+                print(f'{{{{{m.group(1)}}}}} -> {new_string}')
             except Exception:
                 # the data expression was not found
                 print(f'{{{{{m.group(1)}}}}} is not found')
@@ -211,7 +211,7 @@
     tagnav = tag.parent
     this_string = str(tag.string)
     if debug:
-        print(f"name = {tagnav.name}, string = {this_string}")
+        print(f'name = {tagnav.name}, string = {this_string}')
     if tagnav.name not in ['[document]', 'code', 'pre']:
         m = ELEMENTID_RE.search(tag.string)
         if m:
@@ -224,12 +224,12 @@
                     permalink(soup, tagnav)
                     unique(tagnav['id'], perma_set)
                 if debug:
-                    print(f"# insertion {tagnav}")
+                    print(f'# insertion {tagnav}')
             else:
                 # class attribute annotation (regex only recognizes the two types)
                 tagnav['class'] = m.group('id')
                 if debug:
-                    print(f"Class {tag.name} : {tagnav['class']}")
+                    print(f'Class {tag.name} : {tagnav["class"]}')
 
 
 # generate id for a heading
@@ -240,7 +240,7 @@
         new_string = tag.find_all(
             text=lambda t: not isinstance(t, Comment),
             recursive=True)
-        new_string = "".join(new_string)
+        new_string = ''.join(new_string)
 
     # don't have an id create it from text
     new_id = slugify(new_string, '-')
@@ -266,9 +266,9 @@
         # add the heading.
         node, _new_header = node.add(header)
     # convert the ToC to Beautiful Soup
-    tree_soup = ""
+    tree_soup = ''
     if settoc:
-        print("  ToC")
+        print('  ToC')
         # convert the HtmlTreeNode into Beautiful Soup
         tree_string = '{}'.format(tree)
         tree_soup = BeautifulSoup(tree_string, 'html.parser')
@@ -278,11 +278,11 @@
     for tag in tags:
         tag.replaceWith(tree_soup)
         # replace additional [TOC] with nothing
-        tree_soup = ""
+        tree_soup = ''
 
 
 def add_data(content):
-    "Mix in ASF data as metadata"
+    """ Mix in ASF data as metadata """
 
     # if the reader is 'asf' then the asf metadata is already in place
     if content.metadata.get('reader') != 'asf':
@@ -290,9 +290,6 @@
         if asf_metadata:
             content.metadata.update(asf_metadata)
 
-    # if content.settings.get('ASF_DATA', { }).get('debug'):
-    #    print("metadata: %s" % content.metadata)
-
 
 # main worker transforming the html
 def generate_id(content):
@@ -315,7 +312,7 @@
     # assure relative source path is in the metadata
     content.metadata['relative_source_path'] = content.relative_source_path
     # display output path and title
-    print(f"{content.relative_source_path} - {title}")
+    print(f'{content.relative_source_path} - {title}')
     # enhance metadata if done by asfreader
     add_data(content)
     # get plugin settings
@@ -324,27 +321,27 @@
     asf_headings = content.metadata.get('asf_headings', str(asf_genid['headings']))
     # show active plugins
     if asf_genid['debug']:
-        print("asfgenid:\nshow plugins in case one is processing before this one")
+        print('asfgenid:\nshow plugins in case one is processing before this one')
         for name in content.settings['PLUGINS']:
-            print(f"plugin: {name}")
+            print(f'plugin: {name}')
 
     # step 3 - metadata expansion
     if asf_genid['metadata']:
         if asf_genid['debug']:
-            print(f"metadata expansion: {content.relative_source_path}")
+            print(f'metadata expansion: {content.relative_source_path}')
 
         for tag in soup.findAll(string=METADATA_RE):
             expand_metadata(tag, content.metadata)
 
     # step 4 - find all id attributes already present
     for tag in soup.findAll(id=True):
-        unique(tag["id"], ids)
+        unique(tag['id'], ids)
         # don't change existing ids
 
     # step 5 - find all {#id} and {.class} text and assign attributes
     if asf_genid['elements']:
         if asf_genid['debug']:
-            print(f"elementid: {content.relative_source_path}")
+            print(f'elementid: {content.relative_source_path}')
 
         for tag in soup.findAll(string=ELEMENTID_RE):
             elementid_transform(ids, soup, tag, asf_genid['permalinks'], permalinks, asf_genid['debug'])
@@ -352,7 +349,7 @@
     # step 6 - find all headings w/o ids already present or assigned with {#id} text
     if asf_headings == 'True':
         if asf_genid['debug']:
-            print(f"headings: {content.relative_source_path}")
+            print(f'headings: {content.relative_source_path}')
 
         # Find heading tags
         HEADING_RE = re.compile(asf_genid['headings_re'])
@@ -362,7 +359,7 @@
     # step 7 - find all tables without class
     if asf_genid['tables']:
         if asf_genid['debug']:
-            print(f"tables: {content.relative_source_path}")
+            print(f'tables: {content.relative_source_path}')
 
         for tag in soup.findAll(TABLE_RE, _class=False):
             tag['class'] = 'table'
@@ -378,17 +375,18 @@
 
     # step 10 - output all of the permalinks created
     for tag in permalinks:
-        print(f"    #{tag}")
+        print(f'    #{tag}')
 
 
 def tb_connect(pel_ob):
-    "Print any exception, before Pelican chews it into nothingness."
+    """Print any exception, before Pelican chews it into nothingness."""
     try:
         generate_id(pel_ob)
     except:
+        print('-----', file=sys.stderr)
         print('FATAL: %s' % (pel_ob.relative_source_path), file=sys.stderr)
         traceback.print_exc()
-        "if we have errors in this module then we want to quit to avoid erasing the site"
+        # if we have errors in this module then we want to quit to avoid erasing the site
         sys.exit(4)
 
 
diff --git a/theme/plugins/asfreader.py b/theme/plugins/asfreader.py
index ed8e273..c17ad47 100644
--- a/theme/plugins/asfreader.py
+++ b/theme/plugins/asfreader.py
@@ -59,8 +59,6 @@
         asf_metadata = self.settings.get('ASF_DATA', { }).get('metadata')
         if asf_metadata:
             metadata.update(asf_metadata)
-            # if self.settings.get('ASF_DATA', { }).get('debug'):
-            #    print("metadata: %s" % metadata)
 
     def read(self, source_path):
         "Read metadata and content, process content as ezt template, then render into HTML."
@@ -84,6 +82,7 @@
             content = super().render(fp.getvalue().encode('utf-8')).decode('utf-8')
             assert content
         except:
+            print('-----', file=sys.stderr)
             print('ERROR: %s' % (source_path), file=sys.stderr)
             traceback.print_exc()
             raise