From 3b4195c3751d4c62416d71e91cff4c5a698c35b5 Mon Sep 17 00:00:00 2001 From: Fredrik Unger Date: Tue, 3 Mar 2026 07:40:43 +0100 Subject: [PATCH] lint: ran ruff and pylint over treecutter 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 | 3 +- treecutter/directory.py | 19 +++++----- treecutter/docbook.py | 43 ++++++++++++++------- treecutter/image.py | 23 ++++++----- treecutter/link.py | 34 +++++++++++------ treecutter/main.py | 21 ++++++----- treecutter/page.py | 58 +++++++++++++--------------- treecutter/sitemap.py | 65 ++++++++++++++++--------------- treecutter/tools.py | 27 +++++++------ treecutter/trie.py | 84 ++++++++++++++++++++++------------------- 10 files changed, 207 insertions(+), 170 deletions(-) diff --git a/treecutter/constants.py b/treecutter/constants.py index 3ac29b0..07f8b31 100644 --- a/treecutter/constants.py +++ b/treecutter/constants.py @@ -1,4 +1,5 @@ -#!/usr/bin/python +"""module constants: Standard constants for treecutter""" + valid_scripts = [".py", ".pl"] PREFIXES = { diff --git a/treecutter/directory.py b/treecutter/directory.py index 1f2a3ad..cdda900 100644 --- a/treecutter/directory.py +++ b/treecutter/directory.py @@ -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) diff --git a/treecutter/docbook.py b/treecutter/docbook.py index 15118ad..ed9436d 100644 --- a/treecutter/docbook.py +++ b/treecutter/docbook.py @@ -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) diff --git a/treecutter/image.py b/treecutter/image.py index 04d2542..975e233 100644 --- a/treecutter/image.py +++ b/treecutter/image.py @@ -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() diff --git a/treecutter/link.py b/treecutter/link.py index a9ad1ec..1afaea9 100644 --- a/treecutter/link.py +++ b/treecutter/link.py @@ -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()) diff --git a/treecutter/main.py b/treecutter/main.py index b3aeca3..a11778d 100644 --- a/treecutter/main.py +++ b/treecutter/main.py @@ -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 diff --git a/treecutter/page.py b/treecutter/page.py index 2cc6024..92a65cc 100644 --- a/treecutter/page.py +++ b/treecutter/page.py @@ -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) diff --git a/treecutter/sitemap.py b/treecutter/sitemap.py index 6e192aa..a8ab6b5 100644 --- a/treecutter/sitemap.py +++ b/treecutter/sitemap.py @@ -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) diff --git a/treecutter/tools.py b/treecutter/tools.py index 44f6876..edae949 100644 --- a/treecutter/tools.py +++ b/treecutter/tools.py @@ -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) diff --git a/treecutter/trie.py b/treecutter/trie.py index b81fa77..3607c84 100644 --- a/treecutter/trie.py +++ b/treecutter/trie.py @@ -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 = "\n" % css - for l in trie: + """create a formated menue of the trie""" + html = f"\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 += '%s\n' % ( - sel, - subdir, - l.value().link(), - p.menu(), - ) + if p is not None: + link = leaf.value().link() + html += f'{p.menu()}\n' else: - link = l.value().link() + link = leaf.value().link() if link[-1] == "/": link = link + "index" - html += '%s\n' % ( - sel, - subdir, - link, - l.value().page("en").menu(), - ) - if l.children(): - html += self._menu(l.children(), lang, page, "", subdir) + html += f"""{leaf.value().page("en").menu()}\n""" + if leaf.children(): + html += self._menu(leaf.children(), lang, page, "", subdir) html += "\n" html += "\n" return html def menu(self, lang, page, cssclass, subdir): + """Create menue types of the trie""" css = "" if cssclass: css = ' class="' + cssclass + '"' -- 2.30.2