瀏覽代碼

Apply Black to Python utils (#1365)

This applies Black formatting to Python scripts in utils and adds the directory to the checks.
Vaclav Petras 4 年之前
父節點
當前提交
6d4d14afb3

+ 1 - 0
.github/workflows/black.yml

@@ -14,6 +14,7 @@ jobs:
         directory:
         - lib/init
         - scripts
+        - utils
       fail-fast: false
 
     steps:

+ 7 - 6
utils/create_python_init_file.py

@@ -22,27 +22,28 @@ import glob
 
 def main(path):
     if not os.path.exists(path) or not os.path.isdir(path):
-        print >> sys.stderr, "'%s' is not a directory" % path
+        print >>sys.stderr, "'%s' is not a directory" % path
         return 1
 
     modules = []
-    pattern = os.path.join(path, '*.py')
+    pattern = os.path.join(path, "*.py")
     for f in glob.glob(pattern):
-        if f[-5:-3] == '__':
+        if f[-5:-3] == "__":
             continue
         modules.append(os.path.splitext(os.path.basename(f))[0])
 
-    fd = open(os.path.join(path, '__init__.py'), 'w')
+    fd = open(os.path.join(path, "__init__.py"), "w")
     try:
-        fd.write('all = [%s' % os.linesep)
+        fd.write("all = [%s" % os.linesep)
         for m in modules:
             fd.write("    '%s',%s" % (m, os.linesep))
-        fd.write('    ]%s' % os.linesep)
+        fd.write("    ]%s" % os.linesep)
     finally:
         fd.close()
 
     return 0
 
+
 if __name__ == "__main__":
     if len(sys.argv) < 2:
         sys.exit("usage: %s path/to/package/directory" % sys.argv[0])

+ 12 - 16
utils/g.html2man/g.html2man.py

@@ -11,10 +11,7 @@ except ImportError:
     # Python 3 str - unicode version
     from io import StringIO
 
-entities = {
-    'nbsp': " ",
-    'bull': "*"
-}
+entities = {"nbsp": " ", "bull": "*"}
 
 # Remove ToC
 
@@ -22,15 +19,12 @@ entities = {
 def fix(content):
     if isinstance(content, tuple):
         tag, attrs, body = content
-        if tag == 'div' and ('class', 'toc') in attrs:
+        if tag == "div" and ("class", "toc") in attrs:
             return None
         else:
             return (tag, attrs, fix(body))
     elif isinstance(content, list):
-        return [fixed
-                for item in content
-                for fixed in [fix(item)]
-                if fixed is not None]
+        return [fixed for item in content for fixed in [fix(item)] if fixed is not None]
     else:
         return content
 
@@ -45,13 +39,14 @@ def main():
             p.feed(line)
         except HTMLParseError as err:
             sys.stderr.write(
-                '%s:%d:%d: Parse error: %s\n' %
-                (infile, err.lineno, err.offset, err.msg))
+                "%s:%d:%d: Parse error: %s\n"
+                % (infile, err.lineno, err.offset, err.msg)
+            )
             sys.exit(1)
         except Exception as err:
             sys.stderr.write(
-                '%s:%d:0: Error (%s): %s\n' %
-                (infile, n + 1, repr(err), line))
+                "%s:%d:0: Error (%s): %s\n" % (infile, n + 1, repr(err), line)
+            )
             sys.exit(1)
     p.close()
     inf.close()
@@ -65,14 +60,15 @@ def main():
 
     # strip excess whitespace
     blank_re = re.compile("[ \t\n]*\n([ \t]*\n)*")
-    s = blank_re.sub('\n', s)
+    s = blank_re.sub("\n", s)
     s = s.lstrip()
 
     # write groff
-    with open(sys.argv[2], 'wb') as outf:
+    with open(sys.argv[2], "wb") as outf:
         if sys.version_info.major >= 3:
-            s = s.encode('UTF-8')
+            s = s.encode("UTF-8")
         outf.write(s)
 
+
 if __name__ == "__main__":
     main()

+ 62 - 60
utils/g.html2man/ggroff.py

@@ -1,4 +1,3 @@
-
 import sys
 import os
 import re
@@ -6,33 +5,33 @@ import re
 __all__ = ["Formatter"]
 
 try:
-    version = os.environ['VERSION_NUMBER']
+    version = os.environ["VERSION_NUMBER"]
 except:
     version = ""
 
 styles = {
-    'b': "\\fB@\\fR",
-    'i': "\\fI@\\fR",
-    'em': "\\fI@\\fR",
-    'code': "\\fC@\\fR",
-    'span': "\\fC@\\fR",
-    'sup': "\\u@\\d",
-    'hr': ""
+    "b": "\\fB@\\fR",
+    "i": "\\fI@\\fR",
+    "em": "\\fI@\\fR",
+    "code": "\\fC@\\fR",
+    "span": "\\fC@\\fR",
+    "sup": "\\u@\\d",
+    "hr": "",
 }
 
 formats = {
-    'br': "\n.br\n",
-    'h2': "\n.SH @",
-    'h3': "\n.SS @",
-    'h4': "\n.SS @",
-    'dt': ("\n.IP \"@\" 4m", 'no_nl'),
-    'dd': "\n.br\n@",
-    'ul': ("\n.RS 4n\n@\n.RE\n", 'in_ul'),
-    'menu': ("\n.RS 4n\n@\n.RE\n", 'in_ul'),
-    'dir': ("\n.RS 4n\n@\n.RE\n", 'in_ul'),
-    'ol': ("\n.IP\n@\n.PP\n", 'index'),
-    'p': "\n.PP\n@",
-    'pre': ("\n.br\n.nf\n\\fC\n@\n\\fR\n.fi\n", 'preformat')
+    "br": "\n.br\n",
+    "h2": "\n.SH @",
+    "h3": "\n.SS @",
+    "h4": "\n.SS @",
+    "dt": ('\n.IP "@" 4m', "no_nl"),
+    "dd": "\n.br\n@",
+    "ul": ("\n.RS 4n\n@\n.RE\n", "in_ul"),
+    "menu": ("\n.RS 4n\n@\n.RE\n", "in_ul"),
+    "dir": ("\n.RS 4n\n@\n.RE\n", "in_ul"),
+    "ol": ("\n.IP\n@\n.PP\n", "index"),
+    "p": "\n.PP\n@",
+    "pre": ("\n.br\n.nf\n\\fC\n@\n\\fR\n.fi\n", "preformat"),
 }
 
 formats.update(styles)
@@ -59,22 +58,23 @@ def clean(content):
 
 
 class Formatter:
-
     def __init__(self, filename, stream=sys.stdout):
         self.stream = stream
-        self.style = dict(preformat=False,
-                          in_ul=False,
-                          no_nl=False,
-                          in_table=False,
-                          in_tr=False,
-                          index=[])
+        self.style = dict(
+            preformat=False,
+            in_ul=False,
+            no_nl=False,
+            in_table=False,
+            in_tr=False,
+            index=[],
+        )
         self.stack = []
         self.strip_re = re.compile("^[ \t]+")
         self.filename = filename
         self.at_bol = True
 
     def warning(self, msg):
-        sys.stderr.write(msg + '\n')
+        sys.stderr.write(msg + "\n")
 
     def set(self, var, val):
         self.style[var] = val
@@ -91,8 +91,8 @@ class Formatter:
 
     def show(self, s):
         self.stream.write(s)
-        if s != '':
-            self.at_bol = s.endswith('\n')
+        if s != "":
+            self.at_bol = s.endswith("\n")
 
     def pp_with(self, content, var, val):
         self.push()
@@ -103,24 +103,24 @@ class Formatter:
     def fmt(self, format, content, var=None):
         # String.partition is only in 2.5+
         # (pre,sep,post) = format.partition("@")
-        if self.get('no_nl') and '\n' in format:
+        if self.get("no_nl") and "\n" in format:
             self.warning("can't handle line breaks in <dt>...</dt>")
             format = "@"
-        f = format.split('@', 1)
+        f = format.split("@", 1)
         pre = f[0]
         if len(f) > 1:
-            sep = '@'
+            sep = "@"
             post = f[1]
         else:
-            sep = ''
-            post = ''
+            sep = ""
+            post = ""
 
         if pre != "":
             self.show(pre)
         if sep != "":
             if var:
-                if var == 'index':
-                    val = self.get('index') + [0]
+                if var == "index":
+                    val = self.get("index") + [0]
                 else:
                     val = True
                 self.pp_with(content, var, val)
@@ -130,22 +130,24 @@ class Formatter:
             self.show(post)
 
     def pp_li(self, content):
-        if self.get('in_ul'):
+        if self.get("in_ul"):
             self.fmt("\n.IP \(bu 4n\n@", content)
         else:
-            idx = self.get('index')
+            idx = self.get("index")
             idx[-1] += 1
             sec = ".".join(map(str, idx))
             self.show("\n.IP \\fB%s\\fR\n" % sec)
-            self.set('index', idx)
+            self.set("index", idx)
             self.pp(content)
 
     def pp_title(self):
-        self.show("\n.TH " +
-                  os.path.basename(self.filename).replace(".html", "") +
-                  " 1 \"\" \"GRASS " +
-                  version +
-                  "\" \"GRASS GIS User's Manual\"")
+        self.show(
+            "\n.TH "
+            + os.path.basename(self.filename).replace(".html", "")
+            + ' 1 "" "GRASS '
+            + version
+            + '" "GRASS GIS User\'s Manual"'
+        )
 
     def pp_tr(self, content):
         content = clean(content)
@@ -156,7 +158,7 @@ class Formatter:
                 self.warning("invalid item in table row: %s" % str(item))
                 continue
             (tag, attrs, body) = item
-            if tag not in ['td', 'th']:
+            if tag not in ["td", "th"]:
                 self.warning("invalid tag in table row: %s" % tag)
                 continue
             if col > 0:
@@ -172,9 +174,9 @@ class Formatter:
         for item in content:
             if is_tuple(item):
                 (tag, attrs, body) = item
-                if tag in ['thead', 'tbody', 'tfoot']:
+                if tag in ["thead", "tbody", "tfoot"]:
                     self.pp_tbody(body)
-                elif tag == 'tr':
+                elif tag == "tr":
                     self.pp_tr(body)
                     self.show(".sp 1\n")
 
@@ -186,9 +188,9 @@ class Formatter:
                 pass
             elif is_tuple(item):
                 (tag, attrs, body) = item
-                if tag in ['thead', 'tbody', 'tfoot']:
+                if tag in ["thead", "tbody", "tfoot"]:
                     n = self.count_cols(body)
-                elif tag == 'tr':
+                elif tag == "tr":
                     n = len(clean(body))
                 cols = max(cols, n)
             else:
@@ -205,7 +207,7 @@ class Formatter:
         self.show("\n.TE\n")
 
     def pp_tag(self, tag, content):
-        if self.get('in_tr') and tag not in styles:
+        if self.get("in_tr") and tag not in styles:
             self.pp(content)
         elif tag in formats:
             spec = formats[tag]
@@ -214,16 +216,16 @@ class Formatter:
             else:
                 (fmt, var) = spec
                 self.fmt(fmt, content, var)
-        elif tag == 'table':
-            if self.get('in_table'):
+        elif tag == "table":
+            if self.get("in_table"):
                 self.warning("cannot handle nested tables")
                 return
             self.push(in_table=True)
             self.pp_table(content)
             self.pop()
-        elif tag == 'li':
+        elif tag == "li":
             self.pp_li(content)
-        elif tag == 'title':
+        elif tag == "title":
             self.pp_title()
         else:
             self.pp(content)
@@ -232,11 +234,11 @@ class Formatter:
         if content == "":
             return
         s = content
-        if self.get('no_nl'):
+        if self.get("no_nl"):
             s = s.replace("\n", " ")
         s = s.replace("\\", "\\(rs")
         s = s.replace("'", "\\(cq")
-        s = s.replace("\"", "\\(dq")
+        s = s.replace('"', "\\(dq")
         s = s.replace("`", "\\(ga")
         s = s.replace("-", "\\-")
         if self.at_bol and s[0] in [".", "'"]:
@@ -253,8 +255,8 @@ class Formatter:
             return
         else:
             content = lines[0]
-        if self.at_bol and not self.get('preformat'):
-            content = self.strip_re.sub('', content)
+        if self.at_bol and not self.get("preformat"):
+            content = self.strip_re.sub("", content)
         self.pp_string(content)
 
     def pp_list(self, content):

+ 90 - 17
utils/g.html2man/ghtml.py

@@ -1,14 +1,23 @@
-from __future__ import (absolute_import, division, generators, nested_scopes,
-                        print_function, unicode_literals, with_statement)
+from __future__ import (
+    absolute_import,
+    division,
+    generators,
+    nested_scopes,
+    print_function,
+    unicode_literals,
+    with_statement,
+)
 import sys
 
 try:
     # Python 2 import
     import HTMLParser as base
+
     HTMLParseError = base.HTMLParseError
 except:
     # Python 3 import
     import html.parser as base
+
     # TODO: this needs a better fix since HTMLParseError is actually
     # used including its attributes, so that actually fails
     # HTMLParseError is depreciated, parsing is not strict
@@ -26,24 +35,88 @@ __all__ = ["HTMLParser", "HTMLParseError"]
 
 omit_start = ["body", "tbody", "head", "html"]
 
-single = ["area", "base", "basefont", "br", "col", "frame",
-          "hr", "img", "input", "isindex", "link", "meta", "param"]
+single = [
+    "area",
+    "base",
+    "basefont",
+    "br",
+    "col",
+    "frame",
+    "hr",
+    "img",
+    "input",
+    "isindex",
+    "link",
+    "meta",
+    "param",
+]
 single = frozenset(single)
 
 heading = ["h1", "h2", "h3", "h4", "h5", "h6"]
 fontstyle = ["tt", "i", "b", "u", "s", "strike", "big", "small"]
-phrase = ["em", "strong", "dfn", "code", "samp", "kbd", "var", "cite", "abbr",
-          "acronym"]
-special = ["a", "img", "applet", "object", "font", "basefont", "br", "script",
-           "map", "q", "sub", "sup", "span", "bdo", "iframe"]
+phrase = [
+    "em",
+    "strong",
+    "dfn",
+    "code",
+    "samp",
+    "kbd",
+    "var",
+    "cite",
+    "abbr",
+    "acronym",
+]
+special = [
+    "a",
+    "img",
+    "applet",
+    "object",
+    "font",
+    "basefont",
+    "br",
+    "script",
+    "map",
+    "q",
+    "sub",
+    "sup",
+    "span",
+    "bdo",
+    "iframe",
+]
 formctrl = ["input", "select", "textarea", "label", "button"]
 lists = ["ul", "ol", " dir", "menu"]
 head_misc = ["script", "style", "meta", "link", "object"]
-pre_exclusion = ["img", "object", "applet", "big", "small", "sub", "sup",
-                 "font", "basefont"]
-block = ["p", "pre", "dl", "div", "center", "noscript", "noframes",
-         "blockquote", "form", "isindex", "hr", "table", "fieldset",
-         "address"] + heading + lists
+pre_exclusion = [
+    "img",
+    "object",
+    "applet",
+    "big",
+    "small",
+    "sub",
+    "sup",
+    "font",
+    "basefont",
+]
+block = (
+    [
+        "p",
+        "pre",
+        "dl",
+        "div",
+        "center",
+        "noscript",
+        "noframes",
+        "blockquote",
+        "form",
+        "isindex",
+        "hr",
+        "table",
+        "fieldset",
+        "address",
+    ]
+    + heading
+    + lists
+)
 inline = fontstyle + phrase + special + formctrl
 flow = block + inline
 html_content = ["head", "body"]
@@ -63,6 +136,7 @@ def omit(allowed, tags):
         result[k] = v
     return result
 
+
 allowed = {
     "a": inline,
     "abbr": inline,
@@ -141,7 +215,7 @@ allowed = {
     "tt": inline,
     "u": inline,
     "ul": ["li"],
-    "var": inline
+    "var": inline,
 }
 
 allowed = setify(allowed)
@@ -154,14 +228,13 @@ excluded = {
     "form": ["form"],
     "label": ["label"],
     "menu": block,
-    "pre": pre_exclusion
+    "pre": pre_exclusion,
 }
 
 excluded = setify(excluded)
 
 
 class HTMLParser(base.HTMLParser):
-
     def __init__(self, entities=None):
         base.HTMLParser.__init__(self)
         self.tag_stack = []
@@ -221,7 +294,7 @@ class HTMLParser(base.HTMLParser):
             sys.stderr.write("unrecognized entity: %s\n" % name)
 
     def handle_charref(self, name):
-        sys.stderr.write('unsupported character reference <%s>' % name)
+        sys.stderr.write("unsupported character reference <%s>" % name)
 
     def handle_data(self, data):
         self.append(data)

+ 58 - 58
utils/g.html2man/rest.py

@@ -19,11 +19,11 @@ def find(node, tag, attr=None, val=None):
     if isinstance(node, tuple):
         node = node[2]
     if not isinstance(node, list):
-        raise ValueError('child not found')
+        raise ValueError("child not found")
     for child in node:
         if match(child, tag, attr, val):
             return child
-    raise ValueError('child not found')
+    raise ValueError("child not found")
 
 
 def children(node):
@@ -35,7 +35,7 @@ def text(node):
 
 
 def _(s):
-    return s        # TODO
+    return s  # TODO
 
 
 def rest(root, f=sys.stdout):
@@ -44,89 +44,89 @@ def rest(root, f=sys.stdout):
 
     def show(item, italic=False, bold=False):
         if isinstance(item, str):
-            spc = ''  # if item[-1] == '\n' else ' '
-            fmt = '**' if bold else ('*' if italic else '')
-            write('%s%s%s%s' % (fmt, item, fmt, spc))
-        elif match(item, 'b'):
+            spc = ""  # if item[-1] == '\n' else ' '
+            fmt = "**" if bold else ("*" if italic else "")
+            write("%s%s%s%s" % (fmt, item, fmt, spc))
+        elif match(item, "b"):
             for i in children(item):
                 show(i, italic, True)
-        elif match(item, 'i') or match(item, 'em'):
+        elif match(item, "i") or match(item, "em"):
             for i in children(item):
                 show(i, True, bold)
 
-    html = find(root, 'html')
+    html = find(root, "html")
 
-    title = text(find(find(html, 'head'), 'title'))
-    rule = '=' * len(title)
-    write('%s\n' % rule)
-    write('%s\n' % title)
-    write('%s\n' % rule)
-    write('\n')
+    title = text(find(find(html, "head"), "title"))
+    rule = "=" * len(title)
+    write("%s\n" % rule)
+    write("%s\n" % title)
+    write("%s\n" % rule)
+    write("\n")
     write(".. figure:: grass_logo.png\n")
     write("   :align: center\n")
     write("   :alt: GRASS logo\n")
-    write('\n')
+    write("\n")
 
-    body = find(html, 'body')
+    body = find(html, "body")
     section = None
     for child in children(body):
-        if match(child, 'h2'):
+        if match(child, "h2"):
             section = text(child)
-            rule = '-' * len(section)
+            rule = "-" * len(section)
             write("%s\n%s\n" % (section, rule))
-        elif section == _('NAME'):
-            if match(child, 'em'):
-                name = text(find(child, 'b'))
+        elif section == _("NAME"):
+            if match(child, "em"):
+                name = text(find(child, "b"))
                 write("**%s**" % name)
-                section = 'desc'
-        elif section == 'desc' and isinstance(child, str) and child[:4] == '  - ':
-            write(' - ')
+                section = "desc"
+        elif section == "desc" and isinstance(child, str) and child[:4] == "  - ":
+            write(" - ")
             write(child[4:])
-            if child[-1] != '\n':
-                write('\n')
-            write('\n')
+            if child[-1] != "\n":
+                write("\n")
+            write("\n")
             section = None
-        elif section == _('KEYWORDS'):
+        elif section == _("KEYWORDS"):
             write(child.strip())
-            write('\n\n')
+            write("\n\n")
             section = None
-        elif section == _('SYNOPSIS'):
-            if match(child, 'div', 'id', 'name'):
-                name = text(find(child, 'b'))
+        elif section == _("SYNOPSIS"):
+            if match(child, "div", "id", "name"):
+                name = text(find(child, "b"))
                 write("**%s**\n\n" % name)
                 write("**%s** help\n\n" % name)
-            elif match(child, 'div', 'id', 'synopsis'):
+            elif match(child, "div", "id", "synopsis"):
                 for item in children(child):
                     show(item)
-                write('\n')
-            elif match(child, 'div', 'id', 'flags'):
-                header = text(find(child, 'h3'))
-                rule = '=' * len(header)
-                write('%s\n%s\n' % (header, rule))
-                flags = find(child, 'dl')
+                write("\n")
+            elif match(child, "div", "id", "flags"):
+                header = text(find(child, "h3"))
+                rule = "=" * len(header)
+                write("%s\n%s\n" % (header, rule))
+                flags = find(child, "dl")
                 for flag in children(flags):
-                    if match(flag, 'dt'):
-                        item = text(find(flag, 'b'))
-                        write('**%s**\n' % item)
-                    elif match(flag, 'dd'):
-                        write('    %s\n' % text(flag))
-                write('\n\n')
-            elif match(child, 'div', 'id', 'parameters'):
-                header = text(find(child, 'h3'))
-                rule = '=' * len(header)
-                write('%s\n%s\n' % (header, rule))
-                params = find(child, 'dl')
+                    if match(flag, "dt"):
+                        item = text(find(flag, "b"))
+                        write("**%s**\n" % item)
+                    elif match(flag, "dd"):
+                        write("    %s\n" % text(flag))
+                write("\n\n")
+            elif match(child, "div", "id", "parameters"):
+                header = text(find(child, "h3"))
+                rule = "=" * len(header)
+                write("%s\n%s\n" % (header, rule))
+                params = find(child, "dl")
                 for param in children(params):
-                    if match(param, 'dt'):
+                    if match(param, "dt"):
                         name = text(children(param)[0])
-                        write('**%s** = ' % name)
+                        write("**%s** = " % name)
                         for item in children(param)[2:]:
                             show(item)
-                        write('\n\n')
-                    elif match(param, 'dd'):
-                        write('\t')
+                        write("\n\n")
+                    elif match(param, "dd"):
+                        write("\t")
                         for item in children(param):
                             show(item)
-                        write('\n\n')
-                write('\n')
+                        write("\n\n")
+                write("\n")
                 return

+ 19 - 19
utils/gitlog2changelog.py

@@ -9,16 +9,16 @@ import os
 from textwrap import TextWrapper
 import sys
 
-rev_range = ''
+rev_range = ""
 
 if len(sys.argv) > 1:
     base = sys.argv[1]
-    rev_range = '%s..HEAD' % base
+    rev_range = "%s..HEAD" % base
 
 # Execute git log with the desired command line options.
-fin = os.popen('git log --summary --stat --no-merges --date=short %s' % rev_range, 'r')
+fin = os.popen("git log --summary --stat --no-merges --date=short %s" % rev_range, "r")
 # Create a ChangeLog file in the current directory.
-fout = open('ChangeLog', 'w')
+fout = open("ChangeLog", "w")
 
 # Set up the loop variables in order to locate the blocks we want
 authorFound = False
@@ -35,7 +35,7 @@ wrapper = TextWrapper(initial_indent="\t", subsequent_indent="\t  ")
 # The main part of the loop
 for line in fin:
     # The commit line marks the start of a new commit object.
-    if line.startswith('commit'):
+    if line.startswith("commit"):
         # Start all over again...
         authorFound = False
         dateFound = False
@@ -47,32 +47,32 @@ for line in fin:
         continue
     # Match the author line and extract the part we want
     # (Don't use startswith to allow Author override inside commit message.)
-    elif 'Author:' in line:
-        authorList = re.split(': ', line, 1)
+    elif "Author:" in line:
+        authorList = re.split(": ", line, 1)
         try:
             author = authorList[1]
-            author = author[0:len(author)-1]
+            author = author[0 : len(author) - 1]
             authorFound = True
         except:
-            print ("Could not parse authorList = '%s'" % (line))
+            print("Could not parse authorList = '%s'" % (line))
 
     # Match the date line
-    elif line.startswith('Date:'):
-        dateList = re.split(':   ', line, 1)
+    elif line.startswith("Date:"):
+        dateList = re.split(":   ", line, 1)
         try:
             date = dateList[1]
-            date = date[0:len(date)-1]
+            date = date[0 : len(date) - 1]
             dateFound = True
         except:
-            print ("Could not parse dateList = '%s'" % (line))
+            print("Could not parse dateList = '%s'" % (line))
     # The Fossil-IDs are ignored:
-    elif line.startswith('    Fossil-ID:') or line.startswith('    [[SVN:'):
+    elif line.startswith("    Fossil-ID:") or line.startswith("    [[SVN:"):
         continue
     # The svn-id lines are ignored
-    elif '    git-svn-id:' in line:
+    elif "    git-svn-id:" in line:
         continue
     # The sign off line is ignored too
-    elif 'Signed-off-by' in line:
+    elif "Signed-off-by" in line:
         continue
     # Extract the actual commit message for this commit
     elif authorFound & dateFound & messageFound == False:
@@ -90,12 +90,12 @@ for line in fin:
             else:
                 message = message + " " + line.strip()
     # If this line is hit all of the files have been stored for this commit
-    elif re.search('files? changed', line):
+    elif re.search("files? changed", line):
         filesFound = True
         continue
     # Collect the files for this commit. FIXME: Still need to add +/- to files
     elif authorFound & dateFound & messageFound:
-        fileList = re.split(' \| ', line, 2)
+        fileList = re.split(" \| ", line, 2)
         if len(fileList) > 1:
             if len(files) > 0:
                 files = files + ", " + fileList[0].strip()
@@ -120,7 +120,7 @@ for line in fin:
         # Write out the commit line
         fout.write(wrapper.fill(commitLine) + "\n")
 
-        #Now reset all the variables ready for a new commit block.
+        # Now reset all the variables ready for a new commit block.
         authorFound = False
         dateFound = False
         messageFound = False

+ 112 - 92
utils/mkhtml.py

@@ -48,7 +48,7 @@ if not PY2:
 def _get_encoding():
     encoding = locale.getdefaultlocale()[1]
     if not encoding:
-        encoding = 'UTF-8'
+        encoding = "UTF-8"
     return encoding
 
 
@@ -67,8 +67,11 @@ def decode(bytes_):
     return unicode(bytes_)
 
 
-html_page_footer_pages_path = os.getenv('HTML_PAGE_FOOTER_PAGES_PATH') if \
-    os.getenv('HTML_PAGE_FOOTER_PAGES_PATH') else ''
+html_page_footer_pages_path = (
+    os.getenv("HTML_PAGE_FOOTER_PAGES_PATH")
+    if os.getenv("HTML_PAGE_FOOTER_PAGES_PATH")
+    else ""
+)
 
 pgm = sys.argv[1]
 
@@ -130,7 +133,8 @@ GRASS GIS ${GRASS_VERSION} Reference Manual
 </div>
 </body>
 </html>
-""")
+"""
+)
 
 footer_noindex = string.Template(
     """<hr class="header">
@@ -150,11 +154,13 @@ GRASS GIS ${GRASS_VERSION} Reference Manual
 </div>
 </body>
 </html>
-""")
+"""
+)
+
 
 def read_file(name):
     try:
-        f = open(name, 'rb')
+        f = open(name, "rb")
         s = f.read()
         f.close()
         if PY2:
@@ -171,13 +177,13 @@ def create_toc(src_data):
             HTMLParser.__init__(self)
             self.reset()
             self.idx = 1
-            self.tag_curr = ''
-            self.tag_last = ''
+            self.tag_curr = ""
+            self.tag_last = ""
             self.process_text = False
             self.data = []
-            self.tags_allowed = ('h1', 'h2', 'h3')
-            self.tags_ignored = ('img')
-            self.text = ''
+            self.tags_allowed = ("h1", "h2", "h3")
+            self.tags_ignored = "img"
+            self.text = ""
 
         def handle_starttag(self, tag, attrs):
             if tag in self.tags_allowed:
@@ -187,11 +193,10 @@ def create_toc(src_data):
 
         def handle_endtag(self, tag):
             if tag in self.tags_allowed:
-                self.data.append((tag, '%s_%d' % (tag, self.idx),
-                                  self.text))
+                self.data.append((tag, "%s_%d" % (tag, self.idx), self.text))
                 self.idx += 1
                 self.process_text = False
-                self.text = ''
+                self.text = ""
 
             self.tag_curr = self.tag_last
 
@@ -201,7 +206,7 @@ def create_toc(src_data):
             if self.tag_curr in self.tags_allowed or self.tag_curr in self.tags_ignored:
                 self.text += data
             else:
-                self.text += '<%s>%s</%s>' % (self.tag_curr, data, self.tag_curr)
+                self.text += "<%s>%s</%s>" % (self.tag_curr, data, self.tag_curr)
 
     # instantiate the parser and fed it some HTML
     parser = MyHTMLParser()
@@ -209,15 +214,17 @@ def create_toc(src_data):
 
     return parser.data
 
+
 def escape_href(label):
     # remove html tags
-    label = re.sub('<[^<]+?>', '', label)
+    label = re.sub("<[^<]+?>", "", label)
     # fix &nbsp;
-    label = label.replace('&nbsp;', '')
+    label = label.replace("&nbsp;", "")
     # fix "
-    label = label.replace('"', '')
+    label = label.replace('"', "")
     # replace space with underscore + lower
-    return label.replace(' ', '-').lower()
+    return label.replace(" ", "-").lower()
+
 
 def write_toc(data):
     if not data:
@@ -232,40 +239,49 @@ def write_toc(data):
     in_h3 = False
     indent = 4
     for tag, href, text in data:
-        if tag == 'h3' and not in_h3 and has_h2:
-            fd.write('\n%s<ul class="toc">\n' % (' ' * indent))
+        if tag == "h3" and not in_h3 and has_h2:
+            fd.write('\n%s<ul class="toc">\n' % (" " * indent))
             indent += 4
             in_h3 = True
         elif not first:
-            fd.write('</li>\n')
+            fd.write("</li>\n")
 
-        if tag == 'h2':
+        if tag == "h2":
             has_h2 = True
             if in_h3:
                 indent -= 4
-                fd.write('%s</ul></li>\n' % (' ' * indent))
+                fd.write("%s</ul></li>\n" % (" " * indent))
                 in_h3 = False
 
-        text = text.replace(u'\xa0', u' ')
-        fd.write('%s<li class="toc"><a href="#%s" class="toc">%s</a>' %
-                     (' ' * indent, escape_href(text), text))
+        text = text.replace(u"\xa0", u" ")
+        fd.write(
+            '%s<li class="toc"><a href="#%s" class="toc">%s</a>'
+            % (" " * indent, escape_href(text), text)
+        )
         first = False
 
-    fd.write('</li>\n</ul>\n')
-    fd.write('</div>\n')
+    fd.write("</li>\n</ul>\n")
+    fd.write("</div>\n")
+
 
 def update_toc(data):
     ret_data = []
-    pat = re.compile(r'(<(h[2|3])>)(.+)(</h[2|3]>)')
+    pat = re.compile(r"(<(h[2|3])>)(.+)(</h[2|3]>)")
     idx = 1
     for line in data.splitlines():
         if pat.search(line):
             xline = pat.split(line)
-            line = xline[1] + '<a name="%s">' % escape_href(xline[3]) + xline[3] + '</a>' + xline[4]
+            line = (
+                xline[1]
+                + '<a name="%s">' % escape_href(xline[3])
+                + xline[3]
+                + "</a>"
+                + xline[4]
+            )
             idx += 1
         ret_data.append(line)
 
-    return '\n'.join(ret_data)
+    return "\n".join(ret_data)
 
 
 def get_addon_path(pgm):
@@ -275,34 +291,35 @@ def get_addon_path(pgm):
 
     :return tuple: (True, path) if pgm is addon else (None, None)
     """
-    addon_base = os.getenv('GRASS_ADDON_BASE')
+    addon_base = os.getenv("GRASS_ADDON_BASE")
     if addon_base:
         """'addons_paths.json' is file created during install extension
         check get_addons_paths() function in the g.extension.py file
         """
-        addons_paths = os.path.join(addon_base, 'addons_paths.json')
+        addons_paths = os.path.join(addon_base, "addons_paths.json")
         if os.path.exists(addons_paths):
-            with open(addons_paths, 'r') as f:
+            with open(addons_paths, "r") as f:
                 addons_paths = json.load(f)
-            for addon in addons_paths['tree']:
-                split_path = addon['path'].split('/')
+            for addon in addons_paths["tree"]:
+                split_path = addon["path"].split("/")
                 root_dir, module_dir = split_path[0], split_path[-1]
-                if 'grass7' == root_dir and pgm == module_dir:
-                    return True, addon['path']
+                if "grass7" == root_dir and pgm == module_dir:
+                    return True, addon["path"]
     return None, None
 
 
 # process header
 src_data = read_file(src_file)
-name = re.search('(<!-- meta page name:)(.*)(-->)', src_data, re.IGNORECASE)
+name = re.search("(<!-- meta page name:)(.*)(-->)", src_data, re.IGNORECASE)
 pgm_desc = "GRASS GIS Reference Manual"
 if name:
-    pgm = name.group(2).strip().split('-', 1)[0].strip()
-    name_desc = re.search('(<!-- meta page name description:)(.*)(-->)', src_data, re.IGNORECASE)
+    pgm = name.group(2).strip().split("-", 1)[0].strip()
+    name_desc = re.search(
+        "(<!-- meta page name description:)(.*)(-->)", src_data, re.IGNORECASE
+    )
     if name_desc:
         pgm_desc = name_desc.group(2).strip()
-desc = re.search('(<!-- meta page description:)(.*)(-->)', src_data,
-                 re.IGNORECASE)
+desc = re.search("(<!-- meta page description:)(.*)(-->)", src_data, re.IGNORECASE)
 if desc:
     pgm = desc.group(2).strip()
     header_tmpl = string.Template(header_base + header_nopgm)
@@ -312,7 +329,7 @@ else:
     else:
         header_tmpl = string.Template(header_base + header_pgm_desc)
 
-if not re.search('<html>', src_data, re.IGNORECASE):
+if not re.search("<html>", src_data, re.IGNORECASE):
     tmp_data = read_file(tmp_file)
     """
     Adjusting keywords html pages paths if add-on html man page
@@ -321,12 +338,13 @@ if not re.search('<html>', src_data, re.IGNORECASE):
     if html_page_footer_pages_path:
         new_keywords_paths = []
         orig_keywords_paths = re.search(
-            r'<h[1-9]>KEYWORDS</h[1-9]>(.*?)<h[1-9]>',
-            tmp_data, re.DOTALL,
+            r"<h[1-9]>KEYWORDS</h[1-9]>(.*?)<h[1-9]>",
+            tmp_data,
+            re.DOTALL,
         )
         if orig_keywords_paths:
             search_txt = 'href="'
-            for i in orig_keywords_paths.group(1).split(','):
+            for i in orig_keywords_paths.group(1).split(","):
                 if search_txt in i:
                     index = i.index(search_txt) + len(search_txt)
                     new_keywords_paths.append(
@@ -335,13 +353,13 @@ if not re.search('<html>', src_data, re.IGNORECASE):
         if new_keywords_paths:
             tmp_data = tmp_data.replace(
                 orig_keywords_paths.group(1),
-                ','.join(new_keywords_paths),
+                ",".join(new_keywords_paths),
             )
-    if not re.search('<html>', tmp_data, re.IGNORECASE):
+    if not re.search("<html>", tmp_data, re.IGNORECASE):
         sys.stdout.write(header_tmpl.substitute(PGM=pgm, PGM_DESC=pgm_desc))
     if tmp_data:
         for line in tmp_data.splitlines(True):
-            if not re.search('</body>|</html>', line, re.IGNORECASE):
+            if not re.search("</body>|</html>", line, re.IGNORECASE):
                 sys.stdout.write(line)
 
 # create TOC
@@ -352,31 +370,31 @@ sys.stdout.write(update_toc(src_data))
 
 # if </html> is found, suppose a complete html is provided.
 # otherwise, generate module class reference:
-if re.search('</html>', src_data, re.IGNORECASE):
+if re.search("</html>", src_data, re.IGNORECASE):
     sys.exit()
 
 index_names = {
-    'd': 'display',
-    'db': 'database',
-    'g': 'general',
-    'i': 'imagery',
-    'm': 'miscellaneous',
-    'ps': 'postscript',
-    'p': 'paint',
-    'r': 'raster',
-    'r3': 'raster3d',
-    's': 'sites',
-    't': 'temporal',
-    'v': 'vector'
+    "d": "display",
+    "db": "database",
+    "g": "general",
+    "i": "imagery",
+    "m": "miscellaneous",
+    "ps": "postscript",
+    "p": "paint",
+    "r": "raster",
+    "r3": "raster3d",
+    "s": "sites",
+    "t": "temporal",
+    "v": "vector",
 }
 
 
 def to_title(name):
     """Convert name of command class/family to form suitable for title"""
-    if name == 'raster3d':
-        return '3D raster'
-    elif name == 'postscript':
-        return 'PostScript'
+    if name == "raster3d":
+        return "3D raster"
+    elif name == "postscript":
+        return "PostScript"
     else:
         return name.capitalize()
 
@@ -386,17 +404,17 @@ for key, name in index_names.items():
     index_titles[key] = to_title(name)
 
 # process footer
-index = re.search('(<!-- meta page index:)(.*)(-->)', src_data, re.IGNORECASE)
+index = re.search("(<!-- meta page index:)(.*)(-->)", src_data, re.IGNORECASE)
 if index:
     index_name = index.group(2).strip()
-    if '|' in index_name:
-        index_name, index_name_cap = index_name.split('|', 1)
+    if "|" in index_name:
+        index_name, index_name_cap = index_name.split("|", 1)
     else:
         index_name_cap = to_title(index_name)
 else:
-    mod_class = pgm.split('.', 1)[0]
-    index_name = index_names.get(mod_class, '')
-    index_name_cap = index_titles.get(mod_class, '')
+    mod_class = pgm.split(".", 1)[0]
+    index_name = index_names.get(mod_class, "")
+    index_name_cap = index_titles.get(mod_class, "")
 
 grass_version = os.getenv("VERSION_NUMBER", "unknown")
 year = os.getenv("VERSION_DATE")
@@ -408,45 +426,47 @@ topdir = os.path.abspath(os.getenv("MODULE_TOPDIR"))
 curdir = os.path.abspath(os.path.curdir)
 if curdir.startswith(topdir):
     source_url = trunk_url
-    pgmdir = curdir.replace(topdir, '').lstrip(os.path.sep)
+    pgmdir = curdir.replace(topdir, "").lstrip(os.path.sep)
 else:
     # addons
     source_url = addons_url
     pgmdir = os.path.sep.join(curdir.split(os.path.sep)[-3:])
-url_source = ''
-if os.getenv('SOURCE_URL', ''):
+url_source = ""
+if os.getenv("SOURCE_URL", ""):
     # addons
     for prefix in index_names.keys():
         cwd = os.getcwd()
-        idx = cwd.find('{0}{1}.'.format(os.path.sep, prefix))
+        idx = cwd.find("{0}{1}.".format(os.path.sep, prefix))
         if idx > -1:
-            pgmname = cwd[idx+1:]
+            pgmname = cwd[idx + 1 :]
             classname = index_names[prefix]
-            url_source = urlparse.urljoin('{0}{1}/'.format(
-                os.environ['SOURCE_URL'], classname),
-                pgmname
+            url_source = urlparse.urljoin(
+                "{0}{1}/".format(os.environ["SOURCE_URL"], classname), pgmname
             )
             break
 else:
     url_source = urlparse.urljoin(source_url, pgmdir)
-if sys.platform == 'win32':
-    url_source = url_source.replace(os.path.sep, '/')
+if sys.platform == "win32":
+    url_source = url_source.replace(os.path.sep, "/")
 
 if index_name:
-    tree = 'grass/tree'
-    commits = 'grass/commits'
+    tree = "grass/tree"
+    commits = "grass/commits"
     is_addon, addon_path = get_addon_path(pgm=pgm)
     if is_addon:
         # Fix gui/wxpython addon url path
         url_source = urlparse.urljoin(
-            os.environ['SOURCE_URL'], addon_path.split('/', 1)[1],
+            os.environ["SOURCE_URL"],
+            addon_path.split("/", 1)[1],
         )
-        tree = 'grass-addons/tree'
-        commits = 'grass-addons/commits'
+        tree = "grass-addons/tree"
+        commits = "grass-addons/commits"
 
-    sys.stdout.write(sourcecode.substitute(
-        URL_SOURCE=url_source, PGM=pgm, URL_LOG=url_source.replace(
-            tree, commits)))
+    sys.stdout.write(
+        sourcecode.substitute(
+            URL_SOURCE=url_source, PGM=pgm, URL_LOG=url_source.replace(tree, commits)
+        )
+    )
     sys.stdout.write(
         footer_index.substitute(
             INDEXNAME=index_name,

+ 39 - 34
utils/mkrest.py

@@ -1,4 +1,3 @@
-
 #!/usr/bin/env python3
 
 ############################################################################
@@ -30,63 +29,67 @@ else:
 src_file = "%s.html" % pgm
 tmp_file = "%s.tmp.txt" % pgm
 
-#TODO add copyright
+# TODO add copyright
 
 footer_index = string.Template(
     """
 
 :doc:`Main Page <index>` - :doc:`${INDEXNAMECAP} index <${INDEXNAME}>` - :doc:`Full index <full_index>`
 2003-${YEAR} `GRASS Development Team <https://grass.osgeo.org>`_
-""")
+"""
+)
 
 footer_noindex = string.Template(
     """
 
 :doc:`Main Page <index>`  - :doc:`Full index <full_index>`
 2003-${YEAR} `GRASS Development Team <https://grass.osgeo.org>`_
-""")
+"""
+)
 
 
 def read_file(name):
     try:
-        f = open(name, 'rb')
+        f = open(name, "rb")
         s = f.read()
         f.close()
         return s
     except IOError:
         return ""
 
+
 replacement = {
-    '*`': '`',
-    '`* `': '`',
-    '>`_*': '>`_',
-    '>`_,*': '>`_,',
+    "*`": "`",
+    "`* `": "`",
+    ">`_*": ">`_",
+    ">`_,*": ">`_,",
     '``*\ "': '``"',
-    '***': '**'
+    "***": "**",
 }
 
 src_data = read_file(src_file)
 
-title = re.search('(<!-- meta page description:)(.*)(-->)', src_data, re.IGNORECASE)
+title = re.search("(<!-- meta page description:)(.*)(-->)", src_data, re.IGNORECASE)
 
 if title:
     title_name = title.group(2).strip()
     sys.stdout.write("%s\n" % title_name)
-    title_style = "=" * (len(title_name)+2)
+    title_style = "=" * (len(title_name) + 2)
     sys.stdout.write("%s\n\n" % title_style)
 
 tmp_data = read_file(tmp_file)
 if tmp_data:
     sys.stdout.write(tmp_data)
 
-process = subprocess.Popen('pandoc -s -r html %s -w rst' % src_file,
-                           shell=True, stdout=subprocess.PIPE)
+process = subprocess.Popen(
+    "pandoc -s -r html %s -w rst" % src_file, shell=True, stdout=subprocess.PIPE
+)
 html_text = process.communicate()[0]
 if html_text:
     for k, v in replacement.iteritems():
         html_text = html_text.replace(k, v)
 
-#TODO remove with space if string start with it, " vector..." -> "vector..."
+# TODO remove with space if string start with it, " vector..." -> "vector..."
 #     not if it is a tab: "     vector...." -> "    vector..."
 
 #    for line in html_text.splitlines(True):
@@ -95,33 +98,35 @@ if html_text:
 sys.stdout.write(html_text)
 
 index_names = {
-    'd': 'display',
-    'db': 'database',
-    'g': 'general',
-    'i': 'imagery',
-    'm': 'miscellaneous',
-    'ps': 'postscript',
-    'p': 'paint',
-    'r': 'raster',
-    'r3': 'raster3D',
-    's': 'sites',
-    't': 'temporal',
-    'v': 'vector'
+    "d": "display",
+    "db": "database",
+    "g": "general",
+    "i": "imagery",
+    "m": "miscellaneous",
+    "ps": "postscript",
+    "p": "paint",
+    "r": "raster",
+    "r3": "raster3D",
+    "s": "sites",
+    "t": "temporal",
+    "v": "vector",
 }
 
-index = re.search('(<!-- meta page index:)(.*)(-->)', src_data, re.IGNORECASE)
+index = re.search("(<!-- meta page index:)(.*)(-->)", src_data, re.IGNORECASE)
 
 if index:
     index_name = index.group(2).strip()
 else:
-    mod_class = pgm.split('.', 1)[0]
-    index_name = index_names.get(mod_class, '')
+    mod_class = pgm.split(".", 1)[0]
+    index_name = index_names.get(mod_class, "")
 
 if index_name:
-    sys.stdout.write(footer_index.substitute(INDEXNAME = index_name,
-                                             INDEXNAMECAP = index_name.title(),
-                                             YEAR = year))
+    sys.stdout.write(
+        footer_index.substitute(
+            INDEXNAME=index_name, INDEXNAMECAP=index_name.title(), YEAR=year
+        )
+    )
 else:
-    sys.stdout.write(footer_noindex.substitute(YEAR = year))
+    sys.stdout.write(footer_noindex.substitute(YEAR=year))
 
 sys.exit()

+ 15 - 14
utils/ppmrotate.py

@@ -29,6 +29,7 @@ def cleanup():
     if tmp_img:
         grass.try_remove(tmp_img)
 
+
 # def rotate(src, dst):
 #     grass.call(["convert", "-rotate", "90", src, dst])
 
@@ -40,21 +41,21 @@ def read_ppm(src):
     text = fh.read()
     fh.close()
     i = 0
-    j = text.find('\n', i)
-    if text[i:j] != 'P6':
+    j = text.find("\n", i)
+    if text[i:j] != "P6":
         raise IOError(text[i:j] + " != P6. Is the file PPM?")
     i = j + 1
-    j = text.find('\n', i)
+    j = text.find("\n", i)
     w, h = text[i:j].split()
     width = int(w)
     height = int(h)
     i = j + 1
-    j = text.find('\n', i)
+    j = text.find("\n", i)
     maxval = text[i:j]
     if int(maxval) != 255:
         raise IOError("Max value in image != 255")
     i = j + 1
-    return array.array('B', text[i:])
+    return array.array("B", text[i:])
 
 
 def write_ppm(dst, data):
@@ -67,7 +68,7 @@ def write_ppm(dst, data):
 
 
 def rotate_ppm(srcd):
-    dstd = array.array('B', len(srcd) * '\0')
+    dstd = array.array("B", len(srcd) * "\0")
     for y in range(height):
         for x in range(width):
             for c in range(3):
@@ -78,19 +79,19 @@ def rotate_ppm(srcd):
 
 
 def flip_ppm(srcd):
-    dstd = array.array('B', len(srcd) * '\0')
+    dstd = array.array("B", len(srcd) * "\0")
     stride = width * 3
     for y in range(height):
-        dy = (height - 1 - y)
-        dstd[dy * stride:(dy + 1) * stride] = srcd[y * stride:(y + 1) * stride]
+        dy = height - 1 - y
+        dstd[dy * stride : (dy + 1) * stride] = srcd[y * stride : (y + 1) * stride]
     return dstd
 
 
 def ppmtopng(dst, src):
-    if grass.find_program("g.ppmtopng", '--help'):
-        grass.run_command('g.ppmtopng', input=src, output=dst, quiet=True)
+    if grass.find_program("g.ppmtopng", "--help"):
+        grass.run_command("g.ppmtopng", input=src, output=dst, quiet=True)
     elif grass.find_program("pnmtopng"):
-        fh = open(dst, 'wb')
+        fh = open(dst, "wb")
         grass.call(["pnmtopng", src], stdout=fh)
         fh.close()
     elif grass.find_program("convert"):
@@ -107,7 +108,7 @@ def convert_and_rotate(src, dst, flip=False):
         ppm = flip_ppm(ppm)
     ppm = rotate_ppm(ppm)
     to_png = False
-    if dst.lower().endswith('.png'):
+    if dst.lower().endswith(".png"):
         to_png = True
     if to_png:
         tmp_img = grass.tempfile() + ".ppm"
@@ -120,7 +121,7 @@ def convert_and_rotate(src, dst, flip=False):
 
 
 def main():
-    os.environ['GRASS_OVERWRITE'] = '1'
+    os.environ["GRASS_OVERWRITE"] = "1"
 
     infile = sys.argv[1]
     outfile = sys.argv[2]

+ 73 - 44
utils/thumbnails.py

@@ -25,11 +25,13 @@ tmp_grad_rel = None
 
 def cleanup():
     if tmp_grad_rel:
-        grass.run_command('g.remove', flags='f', type='raster',
-                          name=tmp_grad_rel, quiet=True)
+        grass.run_command(
+            "g.remove", flags="f", type="raster", name=tmp_grad_rel, quiet=True
+        )
     if tmp_grad_abs:
-        grass.run_command('g.remove', flags='f', type='raster',
-                          name=tmp_grad_abs, quiet=True)
+        grass.run_command(
+            "g.remove", flags="f", type="raster", name=tmp_grad_abs, quiet=True
+        )
 
 
 def make_gradient(path):
@@ -47,8 +49,9 @@ def make_gradient(path):
             # skip empty lines
             continue
         records.append(line.split())
-    records = [record for record in records
-               if record[0] != 'nv' and record[0] != 'default']
+    records = [
+        record for record in records if record[0] != "nv" and record[0] != "default"
+    ]
     relative = False
     absolute = False
     for record in records:
@@ -66,7 +69,7 @@ def make_gradient(path):
             minval = float(records[0][0])
             # shift min up for floating point values so that
             # first color in color table is visible
-            if '.' in records[0][0]:
+            if "." in records[0][0]:
                 # assumes that 1% of min does not go to the next value
                 # and is still represented as float and does not make
                 # too much difference in color
@@ -74,24 +77,29 @@ def make_gradient(path):
                 minval += abs(minval / 100)
             maxval = float(records[-1][0])
             maxval = min(maxval, 2500000)
-        if os.path.basename(path) in ('ndvi', 'ndwi', 'ndwi2'):
+        if os.path.basename(path) in ("ndvi", "ndwi", "ndwi2"):
             minval = -1.0
             maxval = 1.0
-        if os.path.basename(path) == 'ndvi_MODIS':
+        if os.path.basename(path) == "ndvi_MODIS":
             minval = -10000.0
             maxval = 10000.0
-        if os.path.basename(path) == 'population_dens':
+        if os.path.basename(path) == "population_dens":
             maxval = 1000.0
-        if os.path.basename(path) == 'precipitation':
+        if os.path.basename(path) == "precipitation":
             maxval = 2000.0
-        if os.path.basename(path) in ('terrain', 'srtm', 'srtm_plus'):
+        if os.path.basename(path) in ("terrain", "srtm", "srtm_plus"):
             minval = -500.0
             maxval = 3000.0
         grad = tmp_grad_abs
-        grass.mapcalc("$grad = "
-                      " float($min) + (col() - 1) * "
-                      "  (float($max) - float($min)) / ncols()",
-                      grad=tmp_grad_abs, min=minval, max=maxval, quiet=True)
+        grass.mapcalc(
+            "$grad = "
+            " float($min) + (col() - 1) * "
+            "  (float($max) - float($min)) / ncols()",
+            grad=tmp_grad_abs,
+            min=minval,
+            max=maxval,
+            quiet=True,
+        )
     else:
         grad = tmp_grad_rel
 
@@ -100,14 +108,18 @@ def make_gradient(path):
 
 def make_image(output_dir, table, grad, height, width):
     outfile = os.path.join(output_dir, "colortables", "%s.png" % table)
-    os.environ['GRASS_RENDER_FILE'] = outfile
+    os.environ["GRASS_RENDER_FILE"] = outfile
 
     grass.run_command("r.colors", map=grad, color=table, quiet=True)
-    os.environ['GRASS_RENDER_FRAME'] = '%f,%f,%f,%f' % (0, height, 2, width - 2)
+    os.environ["GRASS_RENDER_FRAME"] = "%f,%f,%f,%f" % (0, height, 2, width - 2)
     grass.run_command("d.rast", map=grad, quiet=True)
     if 1:
-        os.environ['GRASS_RENDER_FRAME'] = '%f,%f,%f,%f' % (0, height, 0, width)
-        grass.write_command("d.graph", quiet=True, flags='m', stdin="""
+        os.environ["GRASS_RENDER_FRAME"] = "%f,%f,%f,%f" % (0, height, 0, width)
+        grass.write_command(
+            "d.graph",
+            quiet=True,
+            flags="m",
+            stdin="""
         width 1
         color {outcolor}
         polyline
@@ -123,9 +135,19 @@ def make_image(output_dir, table, grad, height, width):
         {x4} {y4}
         {x3} {y4}
         {x3} {y3}
-        """.format(x1=1, x2=width, y1=0, y2=height - 1,
-                   x3=2, x4=width - 1, y3=1, y4=height - 2,
-                   outcolor='white', incolor='black'))
+        """.format(
+                x1=1,
+                x2=width,
+                y1=0,
+                y2=height - 1,
+                x3=2,
+                x4=width - 1,
+                y3=1,
+                y4=height - 2,
+                outcolor="white",
+                incolor="black",
+            ),
+        )
 
 
 def main():
@@ -134,10 +156,10 @@ def main():
     height = 15
     width = 85
 
-    os.environ['GRASS_OVERWRITE'] = '1'
+    os.environ["GRASS_OVERWRITE"] = "1"
 
-    color_dir = os.path.join(os.environ['GISBASE'], "etc", "colors")
-    output_dir = os.path.join(os.environ['GISBASE'], "docs", "html")
+    color_dir = os.path.join(os.environ["GISBASE"], "etc", "colors")
+    output_dir = os.path.join(os.environ["GISBASE"], "docs", "html")
 
     if not os.path.exists(output_dir):
         os.makedirs(output_dir)
@@ -146,40 +168,47 @@ def main():
     tmp_grad_abs = "tmp_grad_abs_%d" % pid
     tmp_grad_rel = "tmp_grad_rel_%d" % pid
 
-    os.environ['GRASS_RENDER_WIDTH'] = '%d' % width
-    os.environ['GRASS_RENDER_HEIGHT'] = '%d' % height
-    os.environ['GRASS_RENDER_TRUECOLOR'] = 'TRUE'
+    os.environ["GRASS_RENDER_WIDTH"] = "%d" % width
+    os.environ["GRASS_RENDER_HEIGHT"] = "%d" % height
+    os.environ["GRASS_RENDER_TRUECOLOR"] = "TRUE"
     # for multiple d commands (requires to delete/move image each time)
-    os.environ['GRASS_RENDER_FILE_READ'] = 'TRUE'
-    os.environ['GRASS_RENDER_FILE_MAPPED'] = 'FALSE'
-    os.environ['GRASS_RENDER_TRANSPARENT'] = 'FALSE'
-    os.environ['GRASS_RENDER_BACKGROUNDCOLOR'] = 'ffffff'
-    os.environ['GRASS_RENDER_IMMEDIATE'] = 'cairo'
+    os.environ["GRASS_RENDER_FILE_READ"] = "TRUE"
+    os.environ["GRASS_RENDER_FILE_MAPPED"] = "FALSE"
+    os.environ["GRASS_RENDER_TRANSPARENT"] = "FALSE"
+    os.environ["GRASS_RENDER_BACKGROUNDCOLOR"] = "ffffff"
+    os.environ["GRASS_RENDER_IMMEDIATE"] = "cairo"
     # for one pixel wide lines
-    os.environ['GRASS_RENDER_ANTIALIAS'] = 'none'
+    os.environ["GRASS_RENDER_ANTIALIAS"] = "none"
 
-    for var in ['GRASS_RENDER_LINE_WIDTH']:
+    for var in ["GRASS_RENDER_LINE_WIDTH"]:
         if var in os.environ:
             del os.environ[var]
 
-    os.environ['GRASS_ANTIALIAS'] = 'none'
+    os.environ["GRASS_ANTIALIAS"] = "none"
 
     grass.use_temp_region()
-    grass.run_command('g.region', s=0, w=0, n=height, e=width,
-                      rows=height, cols=width, res=1, flags='a')
+    grass.run_command(
+        "g.region",
+        s=0,
+        w=0,
+        n=height,
+        e=width,
+        rows=height,
+        cols=width,
+        res=1,
+        flags="a",
+    )
 
     grass.mapcalc("$grad = float(col())", grad=tmp_grad_rel, quiet=True)
 
     for table in os.listdir(color_dir):
         path = os.path.join(color_dir, table)
         grad = make_gradient(path)
-        make_image(output_dir, table, grad,
-                   height=height, width=width)
+        make_image(output_dir, table, grad, height=height, width=width)
 
     grass.mapcalc("$grad = col()", grad=tmp_grad_abs, quiet=True)
-    for table in ['grey.eq', 'grey.log', 'random']:
-        make_image(output_dir, table, tmp_grad_abs,
-                   height=height, width=width)
+    for table in ["grey.eq", "grey.log", "random"]:
+        make_image(output_dir, table, tmp_grad_abs, height=height, width=width)
 
 
 if __name__ == "__main__":