lint: ran ruff and pylint over treecutter
authorFredrik Unger <fred@tree.se>
Tue, 3 Mar 2026 06:40:43 +0000 (07:40 +0100)
committerFredrik Unger <fred@tree.se>
Tue, 3 Mar 2026 06:40:43 +0000 (07:40 +0100)
In refactoring the application to python3 ran the ruff and pylint
linters. ruff now passes while pylint still have some open issues.
Your code has been rated at 9.44/10
There are some library issues, that have to be solved on the
different platforms (debian, ubuntu)

treecutter/constants.py
treecutter/directory.py
treecutter/docbook.py
treecutter/image.py
treecutter/link.py
treecutter/main.py
treecutter/page.py
treecutter/sitemap.py
treecutter/tools.py
treecutter/trie.py

index 3ac29b0639bf56da766907cb184cbdcb33cc3245..07f8b31aa5b3f60da123cb5df940d352880dd3ee 100644 (file)
@@ -1,4 +1,5 @@
-#!/usr/bin/python
+"""module constants: Standard constants for treecutter"""
+
 valid_scripts = [".py", ".pl"]
 
 PREFIXES = {
index 1f2a3ad3dc64da0afe90377b045b1bccee79b87b..cdda900ae017abb544fad5a2e2215f148cad7ce7 100644 (file)
@@ -1,12 +1,12 @@
-#!/usr/bin/python
+"""module directory: scanning for content"""
+
 import os
 import fnmatch
-from lxml import etree
-import treecutter.constants as const
-from treecutter.docbook import Docbook
 import re
 from itertools import chain
 
+from treecutter.docbook import Docbook
+
 
 class Directory:
     """Class containing the state of the directory with articles"""
@@ -18,8 +18,9 @@ class Directory:
         self._basepath = re.compile(r"[/\w\._-]*/[\w-]+")
 
     def translations(self, directory):
+        """look for translation files"""
         paths = (self._cwd, directory)
-        for dirname, dirnames, filenames in chain.from_iterable(
+        for dirname, _, filenames in chain.from_iterable(
             os.walk(path) for path in paths
         ):
             for filename in filenames:
@@ -29,7 +30,8 @@ class Directory:
         return self._translations
 
     def scan(self, draftflag, levelflag):
-        for dirname, dirnames, filenames in os.walk(self._cwd):
+        """scan for xml files to include"""
+        for dirname, _, filenames in os.walk(self._cwd):
             for filename in filenames:
                 if fnmatch.fnmatch(filename, "*.xml"):
                     file_ = os.path.join(dirname, filename)
@@ -38,10 +40,6 @@ class Directory:
                     draft = doc.status() == "draft"
                     level = doc.userlevel()
 
-                    #                    doc = etree.parse(file_)
-                    #                    title = doc.xpath(u'/db:article/db:info/db:title',namespaces=const.XPATH)
-                    #                    menu  = doc.xpath(u'/db:article/db:info/db:titleabbrev',namespaces=const.XPATH)
-                    #                    draft = doc.xpath(u'/db:article[@status="draft"]',namespaces=const.XPATH)
                     if draft and draftflag:
                         draft = False
                     if title and menu and not draft and level <= levelflag:
@@ -50,4 +48,5 @@ class Directory:
                         self._tree.append(link)
 
     def set(self):
+        """Return the simple set of the tree"""
         return set(self._tree)
index 15118ad33df10441f3dd73291115a77b893d1edf..ed9436d17bc464c99cedea2acfdc1c8cabfdcb3e 100644 (file)
@@ -1,20 +1,20 @@
-#!/usr/bin/python
+"""module docbook: Docbook operations"""
 
 import os
 import subprocess
 import re
+from time import time
+import getpass
+import gnupg
 
 from lxml import etree
 from lxml.builder import ElementMaker
 
 from pkg_resources import resource_filename, resource_listdir
-from time import time
 
 import treecutter.constants as const
 from treecutter.image import Image
 
-# from treecutter.tools import warning
-
 
 class Docbook:
     """Class representing a docbook document"""
@@ -25,6 +25,7 @@ class Docbook:
         self._dirname = os.path.dirname(self._filename)
 
     def title(self):
+        """Find the title in the document"""
         t = self._doc.xpath(
             "/db:article/db:info/db:title", namespaces=const.XPATH
         )
@@ -44,6 +45,7 @@ class Docbook:
         return (t, ta)
 
     def status(self):
+        """Get the status from the document"""
         status = self._doc.xpath(
             "/db:article[@status]", namespaces=const.XPATH
         )
@@ -52,12 +54,14 @@ class Docbook:
         return None
 
     def role(self):
+        """Get the role from the document"""
         art = self._doc.xpath("/db:article[@role]", namespaces=const.XPATH)
         if art:
             return art[0].get("role")
         return "index"
 
     def userlevel(self):
+        """Get the userlevel from the document"""
         lvl = self._doc.xpath(
             "/db:article[@userlevel]", namespaces=const.XPATH
         )
@@ -73,6 +77,7 @@ class Docbook:
         return 0
 
     def expand_imageobjects(self):
+        """Work through the image objects and adust them"""
         cwd = os.getcwd()
         db = ElementMaker(namespace=const.DB_NS, nsmap=const.NSMAP)
         images = self._doc.xpath(
@@ -105,6 +110,7 @@ class Docbook:
             os.chdir(cwd)
 
     def parse_xincludes(self):
+        """Parse xincludes and if needed execute scripts"""
         cwd = os.getcwd()
         for c in self._doc.xpath(
             "//xi:include[@parse='text']", namespaces=const.XPATH
@@ -112,7 +118,7 @@ class Docbook:
             href = c.get("href")
             alang = c.get("accept-language")
             xpointer = c.get("xpointer")
-            (p, ext) = os.path.splitext(href)
+            (_, ext) = os.path.splitext(href)
             if ext in const.valid_scripts:
                 exe = []
                 script = os.path.join(
@@ -136,15 +142,15 @@ class Docbook:
                     exe.append("lang=" + alang)
                 if xpointer:
                     exe.append("xptr=" + xpointer)
-                if exe == []:
+                if not exe:
                     continue
-                print("  executing %15s" % (href)),
+                print(f"  executing {href:>15}", end="")
                 ts = time()
                 os.chdir(self._dirname)
-                xml = subprocess.Popen(
+                with subprocess.Popen(
                     exe, stdout=subprocess.PIPE, stderr=subprocess.PIPE
-                )
-                (stdout, stderr) = xml.communicate()
+                ) as xml:
+                    stdout, _ = xml.communicate()
                 # print xml.returnvalue
                 #                if stderr:
                 #                    warning("%s : %s" % (" ".join(exe),stderr))
@@ -152,7 +158,7 @@ class Docbook:
                 #                    exit
                 os.chdir(cwd)
                 te = time()
-                print(" [%5.2f s]  (%s)" % (round(te - ts, 2), xpointer))
+                print(f" [{te - ts:5.2f} s]  ({xpointer})")
                 xstr = etree.fromstring(stdout)
                 # inserting the generated code and remove the xinclude reference
                 idp = c.getparent()
@@ -160,9 +166,11 @@ class Docbook:
                 idp.remove(c)
 
     def xinclude(self):
+        """xinclude handling"""
         self._doc.xinclude()
 
     def collect_links(self):
+        """Collect all links in the document"""
         res = []
         for r in self._doc.xpath(
             "//db:link[@xlink:href]", namespaces=const.XPATH
@@ -172,7 +180,7 @@ class Docbook:
                 if r.get("security") == "encrypt":
                     with open(rf, "rb") as f:
                         gpg = gnupg.GPG()
-                        status = gpg.encrypt_file(
+                        gpg.encrypt_file(
                             f,
                             None,
                             passphrase=getpass.getpass(rf + " password:"),
@@ -188,6 +196,7 @@ class Docbook:
         return res
 
     def collect_images(self):
+        """Collect all images of the document"""
         res = []
         for i in self._doc.xpath(
             "//db:imagedata[@fileref]", namespaces=const.XPATH
@@ -200,6 +209,7 @@ class Docbook:
         return res
 
     def collect_videos(self):
+        """Collect all videos of the document"""
         res = []
         for i in self._doc.xpath(
             "//db:videodata[@fileref]", namespaces=const.XPATH
@@ -212,30 +222,35 @@ class Docbook:
         return res
 
     def collect_forms(self):
+        """Collect all forms of the document"""
         res = []
         for i in self._doc.xpath(
             "//html:form[@action]", namespaces=const.XPATH
         ):
-            pyscript = re.split("\.py", i.get("action"), 1)[0] + ".py"
+            pyscript = re.split(r"\.py", i.get("action"), 1)[0] + ".py"
             im = os.path.join(self._dirname, pyscript)
             if os.path.isfile(im):
                 res.append(im)
         return res
 
     def tostring(self):
+        """Docbook to string"""
         return etree.tostring(self._doc, encoding="UTF-8", pretty_print=False)
 
     def xslt(self, transform):
+        """XSLT transform"""
         return etree.tostring(transform(self._doc))
 
     def clean(self):
+        """cleaning xml"""
+
         def recursively_empty(e):
             if e.text:
                 return False
             return all((recursively_empty(c) for c in e.iterchildren()))
 
         context = etree.iterwalk(self._doc)
-        for action, elem in context:
+        for _, elem in context:
             parent = elem.getparent()
             if recursively_empty(elem):
                 parent.remove(elem)
index 04d254281a9579c06d326fb4f13f942bf751d8bb..975e233f9f4e54e82b334205ade934e3cf204a7f 100644 (file)
@@ -1,13 +1,13 @@
-#!/usr/bin/python
+"""module image: image tools"""
+
+import os
+import subprocess
 
 from PIL import Image as PIL_Image
 from libxmp import consts
 from libxmp import XMPFiles
-from treecutter.tools import sizeof_fmt
-import os
 
-import subprocess
-import errno
+from treecutter.tools import sizeof_fmt
 
 
 class Image:
@@ -18,19 +18,22 @@ class Image:
         self._format = {}
 
     def filename(self):
+        """Return filename"""
         return self._filename
 
     def infostr(self):
+        """Get infostring"""
         im = PIL_Image.open(self._filename)
         w, d = im.size
         im.close()
         byte = os.path.getsize(self._filename)
-        return "[%dx%d (%s)]" % (w, d, sizeof_fmt(byte))
+        return f"[{w}x{d} ({sizeof_fmt(byte)})]"
 
     def resize(self, x, y, pad=0):
+        """Resize image"""
         size = (x, y)
         outfile, ext = os.path.splitext(self._filename)
-        outfile = "%s.%dx%d%s" % (outfile, size[0], size[1], ext)
+        outfile = f"{outfile}.{size[0]}x{size[1]}{ext}"
         if not os.path.exists(outfile):
             im = PIL_Image.open(self._filename)
             im.thumbnail(size, PIL_Image.LANCZOS)
@@ -69,7 +72,6 @@ class Image:
                             + str(retcode)
                             + "]"
                         )
-                        exit
             else:
                 cmd = [
                     "exiftool",
@@ -87,12 +89,12 @@ class Image:
                         + str(retcode)
                         + "]"
                     )
-                    exit
             xmpfile.close_file()
             self._format[size] = outfile
         return outfile
 
     def generated(self):
+        """Mark generated files in XMP"""
         xmpfile = XMPFiles(file_path=self._filename)
         xmp = xmpfile.get_xmp()
         if not xmp:
@@ -103,12 +105,15 @@ class Image:
         return cr == "treecutter"
 
     def thumbnail(self):
+        """Create thumbnail"""
         return self.resize(50, 50, 1)
 
     def slider(self):
+        """Create website slider"""
         return self.resize(700, 438, 1)
 
     def caption(self):
+        """Add captions"""
         cap = "Beskrivning saknas"
         xmpfile = XMPFiles(file_path=self._filename)
         xmp = xmpfile.get_xmp()
index a9ad1ec3a0e8bbe7be4174d944d3341a19c67a48..1afaea9cf5d6db68eb0731712ac2290fd009906e 100644 (file)
@@ -1,4 +1,5 @@
-#!/usr/bin/python
+"""link module: module handling the website links"""
+
 import re
 import glob
 from treecutter.page import Page
@@ -11,52 +12,61 @@ class Link:
         self._link = link
         # find the representations of the link.
         self._pages = []
-        self._langregexp = re.compile(".*\.(\w\w)\.xml")
+        self._langregexp = re.compile(r".*\.(\w\w)\.xml")
         path = link
         if self._link[-1] == "/":
             path = path + "index"
-        lang = self._scan_languages(path)
-        for l in lang:
-            self._pages.append(Page(self, l))
+        languages = self._scan_languages(path)
+        for lang in languages:
+            self._pages.append(Page(self, lang))
 
-    def add_page(self, l):
-        self._pages.append(Page(self, l))
+    def add_page(self, lang):
+        """Add webpage to the page collection"""
+        self._pages.append(Page(self, lang))
 
     def _scan_languages(self, path):
-        lang = []
-        for l in glob.glob("." + path + "*.xml"):
-            langcode = self._langregexp.search(l).group(1)
-            lang.append((langcode, l))
-        return lang
+        """Scan availible languages"""
+        languages = []
+        for lang in glob.glob("." + path + "*.xml"):
+            langcode = self._langregexp.search(lang).group(1)
+            languages.append((langcode, lang))
+        return languages
 
     def link(self):
+        """Return internal link"""
         return self._link
 
     def prepare(self):
+        """Setup the pages"""
         for page in self._pages:
             page.prepare()
 
     def languages(self):
+        """Return availible languages"""
         p = []
         for page in self._pages:
             p.append(page.language())
         return p
 
     def render(self, transform):
+        """Render the page collection"""
         for page in self._pages:
             page.render(transform)
 
     def template(self, sitemap, style, tdir, subdir):
+        """Template the page collection"""
         for page in self._pages:
             page.template(sitemap, style, tdir, subdir)
 
     def page(self, lang):
+        """Return page in language lang"""
         for page in self._pages:
             if page.language() == lang:
                 return page
         return None
 
     def resources(self):
+        """Return page resources"""
         res = set()
         for page in self._pages:
             res = res.union(page.resources())
index b3aeca3ba7fe2750d5b16cf66922b01db7d9bfa3..a11778d0bb3d7caeb6ef29719a0eaf0240cb0a54 100644 (file)
@@ -1,14 +1,16 @@
-#!/usr/bin/python
+"""Main module: main function module to start the core."""
+
 import os
 from time import time
 import argparse
+import sys
 from treecutter.directory import Directory
 from treecutter.sitemap import Sitemap
 from treecutter.tools import translate
 
 
 def main():
-
+    """Runs the treecutter application"""
     parser = argparse.ArgumentParser(
         description="Process docbook article tree."
     )
@@ -35,12 +37,11 @@ def main():
     dir_ = Directory()
     t1 = time()
     totrans = dir_.translations(args.style)
-    print("Translate [%d] : [" % (len(totrans))),
+    print(f"Translate [{len(totrans)}] : [", end="")
     translate(totrans)
     print("]")
     t2 = time()
-    print("Translate[%5.2f s]" % (round(t2 - t1, 2)))
-
+    print(f"Translate[{t2 - t1:5.2f} s]")
     sitemap = Sitemap(args)
 
     # Scanning current directory and subdirectory for docbook articles
@@ -62,9 +63,9 @@ def main():
         sitemap.write_map()
 
     dirsitemap = Sitemap(args)
-    for l in sitemap.linklist():
-        if l in dirset:
-            dirsitemap.add_link(l)
+    for link in sitemap.linklist():
+        if link in dirset:
+            dirsitemap.add_link(link)
 
     # Generate a pygraphviz image of the site (TODO: currently not used)
     dirsitemap.graph()
@@ -75,8 +76,8 @@ def main():
     t1 = time()
     dirsitemap.publish()
     t2 = time()
-    print("Publish  [%5.2f s]" % (round(t2 - t1, 2)))
-    print("Total    [%5.2f s]" % (round(t2 - ts, 2)))
+    print(f"Publish [{t2 - t1:5.2f} s]")
+    print(f"Total   [{t2 - ts:5.2f} s]")
     return 0
 
 
index 2cc60247de2b2f2b8e1ab1b3df22383aca6a273f..92a65cc08821f19b4c8807157dd890e9a6aff006 100644 (file)
@@ -1,19 +1,9 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
+"""Page module: representing a page"""
+
 import os
-import subprocess
-import tempfile
-import re
-import getpass
-import gnupg
 import codecs
-from lxml import etree
-from lxml.builder import ElementMaker
-
-# from jinja2 import Template
 import jinja2
-from time import time
-import treecutter.constants as const
+
 from treecutter.docbook import Docbook
 from treecutter.tools import mkdir_p
 
@@ -21,6 +11,8 @@ from treecutter.tools import mkdir_p
 class Page:
     """Class representing a version of a webpage"""
 
+    # pylint: disable=too-many-instance-attributes
+    # not yet clear if this can be cut down to 7
     def __init__(self, link, page):
         self._link = link
         self._file = page[1]
@@ -34,18 +26,23 @@ class Page:
         self._status = None
 
     def language(self):
+        """Returns language of the page"""
         return self._lang
 
     def resources(self):
+        """Return the resources for the page (images etc.)"""
         return set(self._resources)
 
     def menu(self):
+        """Menu item of the page"""
         return self._menu
 
     def set_article(self, art):
+        """Set the article to be rendered for the page"""
         self._rendered_article = art
 
     def prepare(self):
+        """Collect all collaterals to the page"""
         self._doc = Docbook(self._file)
         (self._title, self._menu) = self._doc.title()
         self._doc.expand_imageobjects()
@@ -60,32 +57,29 @@ class Page:
         self._resources = doc + img + vid + form
 
     def render(self, transform):
+        """Render the page to xhtml5"""
         self._rendered_article = self._doc.xslt(transform["xhtml5"])
 
     def template(self, sitemap, style, tdir, subdir):
-        htmlmenu = sitemap.gen_menu(self._lang, None, "links")
-        levelmenu = sitemap.gen_menu(self._lang, self, "tree")
-        langmenu = sitemap.lang_menu(self._lang, self._link)
-        article = self._rendered_article
-        templateLoader = jinja2.FileSystemLoader(searchpath="/")
-        templateEnv = jinja2.Environment(loader=templateLoader)
-
-        templateVars = {
+        """Template the page to html"""
+
+        templateloader = jinja2.FileSystemLoader(searchpath="/")
+        templateenv = jinja2.Environment(loader=templateloader)
+
+        templatevars = {
             "title": self._title,
-            "menu": htmlmenu,
-            "article": article,
-            "levelmenu": levelmenu,
-            "langmen": langmenu,
+            "menu": sitemap.gen_menu(self._lang, None, "links"),
+            "article": self._rendered_article,
+            "levelmenu": sitemap.gen_menu(self._lang, self, "tree"),
+            "langmen": sitemap.lang_menu(self._lang, self._link),
             "subdir": subdir,
         }
 
-        s = style
-        t = s + self._template + "." + self._lang + ".html.tmpl"
-        template = templateEnv.get_template(t)
-        templateout = template.render(templateVars)
+        t = style + self._template + "." + self._lang + ".html.tmpl"
+        template = templateenv.get_template(t)
+        templateout = template.render(templatevars)
 
         outfile = tdir + "html".join(self._file.rsplit("xml", 1))
         mkdir_p(os.path.dirname(outfile))
-        out = codecs.open(outfile, "w", "utf-8")
-        out.write(templateout)
-        out.close()
+        with codecs.open(outfile, "w", "utf-8") as out:
+            out.write(templateout)
index 6e192aacdebe7d4ff79bc17d075ea61ed6c6e34f..a8ab6b5c716b8cfa09d6788d38862622eca5653e 100644 (file)
@@ -1,15 +1,15 @@
-#!/usr/bin/python
+"""module sitemap: generate sitemap and structure"""
+
 import os
 import codecs
 import re
 import shutil
-import sys
 import gettext
 import tempfile
+from time import time
 from lxml import etree
 from lxml.builder import ElementMaker
-from time import time
-from treecutter import constants as const
+
 from treecutter.trie import Trie
 from treecutter.link import Link
 from treecutter.tools import (
@@ -35,11 +35,11 @@ class Sitemap:
         self._tranlang = {}
         self._tmptarget = tempfile.mkdtemp() + "/"
 
-    # The sitemap uses a trie structure to keep track of links
-    # A link represents the path to the document and the link
-    # representing the text on the site.
-    # A link can have several pages in different languages.
     def add_link(self, link):
+        """The sitemap uses a trie structure to keep track of links
+        A link represents the path to the document and the link
+        representing the text on the site.
+        A link can have several pages in different languages."""
         tokens = list(
             filter(
                 None,
@@ -53,12 +53,14 @@ class Sitemap:
         self._tree.add(tokens, Link(link))
 
     def write_map(self):
+        """Write sitemap.txt"""
         f = codecs.open(self._file, "w", "utf-8")
         s = "\n".join(link.link() for link in self._tree)
         f.write(s)
         f.close()
 
     def read_map(self):
+        """Read sitemap.txt"""
         try:
             f = codecs.open(self._file, "r", "utf-8")
             sml = f.read().split()
@@ -68,22 +70,22 @@ class Sitemap:
         except IOError:
             print("INFO: Could not read sitemap.txt - one will be created")
 
-    # Create a set of the current tree for comparison with the
-    # directory scan
     def set(self):
+        """Create a set of the current tree for comparison with the directory scan"""
         return set(link.link() for link in self._tree)
 
     def linklist(self):
+        """Return link list of tree"""
         return [link.link() for link in self._tree]
 
-    # Main driver in the application processing the documents
-    # in the collected sitemap
     def process(self):
+        """Main driver in the application processing the documents in
+        the collected sitemap"""
         t1 = time()
         for link in self._tree:
             link.prepare()
         t2 = time()
-        print("Prepare  [%5.2f s]" % (round(t2 - t1, 2)))
+        print(f"Prepare  [{t2 - t1:5.2f} s]")
         for link in self._tree:
             self._sitelang = self._sitelang.union(set(link.languages()))
         for tran in self._sitelang:
@@ -92,7 +94,7 @@ class Sitemap:
                     "iso_639_3", languages=[tran]
                 )
         t3 = time()
-        print("Language [%5.2f s]" % (round(t3 - t2, 2)))
+        print(f"Language [{t3 - t2:5.2f} s]")
         transform = {}
         transform["xhtml5"] = etree.XSLT(
             etree.parse(self._style + "docbook.xhtml5.xsl")
@@ -100,11 +102,11 @@ class Sitemap:
         for link in self._tree:
             link.render(transform)
         t4 = time()
-        print("Render   [%5.2f s]" % (round(t4 - t3, 2)))
+        print(f"Render   [{t4 - t3:5.2f} s]")
         for link in self._tree:
             link.template(self, self._style, self._tmptarget, self._subdir)
         t5 = time()
-        print("Template [%5.2f s]" % (round(t5 - t4, 2)))
+        print(f"Template [{t5 - t4:5.2f} s]")
         t6 = time()
         res = set()
         # Collect all files used by the documents
@@ -114,48 +116,51 @@ class Sitemap:
             outfile = self._tmptarget + f
             mkdir_p(os.path.dirname(outfile))
             shutil.copyfile(f, outfile)
-        print("Resources[%5.2f s]" % (round(t6 - t5, 2)))
+        print(f"Resources[{t6 - t5:5.2f} s]")
         # TODO: Improve the sitemap, it is a page that is generated from
         #       the ground up and added a bit adhoc.
         sitmaplink = Link("/sitemap")
-        for l in self._sitelang:
-            sitmaplink.add_page((l, "/sitemap." + l + ".xml"))
-        for l in self._sitelang:
-            txtmenu = self.gen_menu(l, None, "tree sitemap")
-            sitmaplink.page(l).set_article(txtmenu)
-            f = open(self._tmptarget + "sitemap." + l + ".txt", "w")
+        for lang in self._sitelang:
+            sitmaplink.add_page((lang, "/sitemap." + lang + ".xml"))
+        for lang in self._sitelang:
+            txtmenu = self.gen_menu(lang, None, "tree sitemap")
+            sitmaplink.page(lang).set_article(txtmenu)
+            f = open(self._tmptarget + "sitemap." + lang + ".txt", "w")
             f.write(txtmenu)
             f.close()
-            sitmaplink.page(l).template(
+            sitmaplink.page(lang).template(
                 self, self._style, self._tmptarget, self._subdir
             )
         t7 = time()
-        print("Sitemap  [%5.2f s]" % (round(t7 - t6, 2)))
+        print(f"Sitemap   [{t7 - t6:5.2f} s]")
 
     def graph(self):
+        """Return graph"""
         self._tree.graph()
 
     def gen_menu(self, lang, page, cssclass):
+        """Generate menu in html"""
         return self._tree.menu(lang, page, cssclass, self._subdir)
 
     def lang_menu(self, lang, link):
+        """Generate language menu"""
         html = ElementMaker()
         menu = html.ul()
-        for l in link.languages():
-            isoxml = "//iso_639_3_entry[@*='" + l + "']"
+        for lang in link.languages():
+            isoxml = "//iso_639_3_entry[@*='" + lang + "']"
             ln = self._isocode.xpath(isoxml)[0].get("name")
             if lang != "en":
                 ln = self._tranlang[lang].ugettext(ln)
             p = link.link()
             if p[-1] == "/":
                 p = p + "index"
-            p = p + "." + l
-            li = html.li(html.a(ln, href=self._subdir + p, hreflang=l))
+            p = p + "." + lang
+            li = html.li(html.a(ln, href=self._subdir + p, hreflang=lang))
             menu.append(li)
-        #            print type(etree.tostring(menu,encoding='unicode',pretty_print=False))
         return etree.tostring(menu, encoding="unicode", pretty_print=False)
 
     def publish(self):
+        """Publish the site"""
         print("Size [ %7s ]" % (sizeof_fmt(get_folder_size(self._tmptarget))))
         ssh_cmd(self._output, "mkdir -p")
         publish(self._tmptarget, self._output)
index 44f687649784277ffcef21a8bb06fb399254ee59..edae9495a98d70ee75af89b97fc0021fb5db3a62 100644 (file)
@@ -1,5 +1,5 @@
-#!/usr/bin/python
-# from __future__ import print_function
+"""tools module: contain simple tools for treecutter"""
+
 import os
 import subprocess
 import errno
@@ -7,6 +7,7 @@ import sys
 
 
 def mkdir_p(path):
+    """Make a directory structure like mkdir -p"""
     try:
         os.makedirs(path)
     except OSError as exc:  # Python >2.5
@@ -17,13 +18,15 @@ def mkdir_p(path):
 
 
 def publish(src, target):
+    """Publish the website to the final destination"""
     cmd = ["rsync", "-a", "--copy-links", "--partial", src, target]
     retcode = subprocess.call(cmd)
     if retcode:
-        error("%s : retruncode %s" % (" ".join(cmd), str(retcode)))
+        print(f"{cmd} : retruncode {retcode}")
 
 
 def ssh_cmd(target, command):
+    """ssh to another site"""
     t = target.split(":")
     c = command.split()
     if len(t) == 1:
@@ -32,18 +35,20 @@ def ssh_cmd(target, command):
         cmd = ["ssh", t[0], c[0], c[1], t[1]]
     retcode = subprocess.call(cmd)
     if retcode:
-        error("%s : retruncode %s" % (" ".join(cmd), str(retcode)))
+        print(f"{cmd} : retruncode {retcode}")
 
 
 def sizeof_fmt(num, suffix="B"):
+    """Summarize directory size"""
     for unit in ["", "Ki", "Mi", "Gi", "Ti", "Pi", "Ei", "Zi"]:
         if abs(num) < 1024.0:
-            return "%3.1f%s%s" % (num, unit, suffix)
+            return f"{num:3.1f}{unit}{suffix}"
         num /= 1024.0
-    return "%.1f%s%s" % (num, "Yi", suffix)
+    return f"{num:.1f}Yi{suffix}"
 
 
 def get_folder_size(folder):
+    """Get foldersize recursivley"""
     total_size = os.path.getsize(folder)
     if os.path.isfile(folder):
         return total_size
@@ -58,13 +63,7 @@ def get_folder_size(folder):
 
 # proc = subprocess.Popen(args, env={'PATH': os.getenv('PATH')})
 def translate(files):
+    """translate availible files"""
     for f in files:
-        out = subprocess.check_output(["translate.sh", f])
+        subprocess.check_output(["translate.sh", f])
         sys.stdout.write("#")
-
-
-# def warning(*objs):
-#    print("WARNING: ", *objs, file=sys.stderr)
-
-# def error(*objs):
-#    print("ERROR: ", *objs, file=sys.stderr)
index b81fa77bd2193c535f6b7d0a3f4dc5d771fda0df..3607c84401bf7dc42d652d5eea4b17f4aff7438b 100644 (file)
@@ -1,37 +1,48 @@
-#!/usr/bin/python
+"""module trie: Trie structure to reperesent the website"""
+
 import pygraphviz as pgv
 
 
 class Node:
+    """Node of a trie with content"""
+
     def __init__(self, token, value):
         self._token = token
         self._value = value
         self._children = []
 
     def token(self):
+        """Internal token"""
         return self._token
 
     def value(self):
+        """Value"""
         return self._value
 
     def children(self):
+        """Node children"""
         return self._children
 
 
 class Trie:
+    """Trie class structure"""
+
     def __init__(self):
         self._root = []
 
     def __iter__(self):
+        """Trie iterator"""
         return self.inorder(self._root)
 
-    def inorder(self, t):
-        for l in t:
-            yield l.value()
-            for x in self.inorder(l.children()):
-                yield x
+    def inorder(self, tree):
+        """inorder traversal of the trie tree"""
+        for leaf in tree:
+            yield leaf.value()
+            # Delegate the recursive call directly
+            yield from self.inorder(leaf.children())
 
     def _add(self, trie, key, content):
+        """internal add function"""
         # is the key a leaf
         k = key.pop(0)
         if key == []:
@@ -43,57 +54,54 @@ class Trie:
                     self._add(ch.children(), key, content)
 
     def add(self, key, content):
+        """Add node to the trie"""
         self._add(self._root, key, content)
 
-    def _graph(self, trie, G):
-        for l in trie:
-            G.add_node(l.token())
-            for ch in l.children():
-                G.add_edge(l.token(), ch.token())
-                self._graph(l.children(), G)
+    def _graph(self, trie, g):
+        """Generate a graph of the trie - internal"""
+        for leaf in trie:
+            g.add_node(leaf.token())
+            for ch in leaf.children():
+                g.add_edge(leaf.token(), ch.token())
+                self._graph(leaf.children(), g)
 
     def graph(self):
-        G = pgv.AGraph(directed=True)
-        G.add_node("sitemap")
+        """Generate a sitemap graph of the site"""
+        g = pgv.AGraph(directed=True)
+        g.add_node("sitemap")
         for ch in self._root:
-            G.add_edge("sitemap", ch.token())
-        self._graph(self._root, G)
+            g.add_edge("sitemap", ch.token())
+        self._graph(self._root, g)
 
-    #        G.layout('dot')
-    #        G.draw('g.png')
-    #        print G.string()
+    #        g.layout('dot')
+    #        g.draw('g.png')
+    #        print g.string()
 
     def _menu(self, trie, lang, page, css, subdir):
-        html = "<ul%s>\n" % css
-        for l in trie:
+        """create a formated menue of the trie"""
+        html = f"<ul{css}>\n"
+        for leaf in trie:
             sel = ""
-            p = l.value().page(lang)
+            p = leaf.value().page(lang)
             if p == page:
                 sel = ' class="selected"'
-            if p != None:
-                html += '<li%s><a href="%s%s">%s</a>\n' % (
-                    sel,
-                    subdir,
-                    l.value().link(),
-                    p.menu(),
-                )
+            if p is not None:
+                link = leaf.value().link()
+                html += f'<li{sel}><a href="{subdir}{link}">{p.menu()}</a>\n'
             else:
-                link = l.value().link()
+                link = leaf.value().link()
                 if link[-1] == "/":
                     link = link + "index"
-                html += '<li%s><a href="%s%s.en" hreflang="en">%s</a>\n' % (
-                    sel,
-                    subdir,
-                    link,
-                    l.value().page("en").menu(),
-                )
-            if l.children():
-                html += self._menu(l.children(), lang, page, "", subdir)
+                html += f"""<li{sel}><a href="{subdir}{link}.en"
+                        hreflang="en">{leaf.value().page("en").menu()}</a>\n"""
+            if leaf.children():
+                html += self._menu(leaf.children(), lang, page, "", subdir)
             html += "</li>\n"
         html += "</ul>\n"
         return html
 
     def menu(self, lang, page, cssclass, subdir):
+        """Create menue types of the trie"""
         css = ""
         if cssclass:
             css = ' class="' + cssclass + '"'