aboutsummaryrefslogtreecommitdiffstats
path: root/lv2specgen
diff options
context:
space:
mode:
Diffstat (limited to 'lv2specgen')
-rwxr-xr-xlv2specgen/lv2docgen.py17
-rwxr-xr-xlv2specgen/lv2specgen.py148
-rw-r--r--lv2specgen/meson.build45
3 files changed, 115 insertions, 95 deletions
diff --git a/lv2specgen/lv2docgen.py b/lv2specgen/lv2docgen.py
index 9b1685a..271e434 100755
--- a/lv2specgen/lv2docgen.py
+++ b/lv2specgen/lv2docgen.py
@@ -3,6 +3,13 @@
# Copyright 2012 David Robillard <d@drobilla.net>
# SPDX-License-Identifier: ISC
+"""LV2 plugin documentation generator."""
+
+# pylint: disable=consider-using-f-string
+# pylint: disable=missing-function-docstring
+# pylint: disable=redefined-outer-name
+# pylint: disable=invalid-name
+
import errno
import os
import sys
@@ -93,10 +100,10 @@ def plugin_doc(model, plugin, style_uri):
html += get_doc(model, plugin)
ports_html = ""
- for p in model.triples([plugin, lv2.port, None]):
- ports_html += port_doc(model, p[2])
+ for link in model.triples([plugin, lv2.port, None]):
+ ports_html += port_doc(model, link[2])
- if len(ports_html):
+ if ports_html:
html += (
"""
<h2 class="sec">Ports</h2>
@@ -111,8 +118,6 @@ def plugin_doc(model, plugin, style_uri):
if __name__ == "__main__":
- "LV2 plugin documentation generator"
-
if len(sys.argv) < 2:
print("Usage: %s OUTDIR FILE..." % sys.argv[0])
sys.exit(1)
@@ -140,5 +145,5 @@ if __name__ == "__main__":
raise
print("Writing <%s> documentation to %s" % (plugin, outpath))
- with open(outpath, "w") as out:
+ with open(outpath, "w", encoding="utf-8") as out:
out.write(html)
diff --git a/lv2specgen/lv2specgen.py b/lv2specgen/lv2specgen.py
index d6e86f8..7927261 100755
--- a/lv2specgen/lv2specgen.py
+++ b/lv2specgen/lv2specgen.py
@@ -9,17 +9,39 @@
# Based on SpecGen:
# <http://forge.morfeo-project.org/wiki_en/index.php/SpecGen>
+"""Ontology specification generator tool."""
+
+# pylint: disable=broad-exception-caught
+# pylint: disable=cell-var-from-loop
+# pylint: disable=consider-using-f-string
+# pylint: disable=deprecated-module
+# pylint: disable=global-statement
+# pylint: disable=global-variable-not-assigned
+# pylint: disable=invalid-name
+# pylint: disable=missing-function-docstring
+# pylint: disable=no-member
+# pylint: disable=redefined-outer-name
+# pylint: disable=too-many-arguments
+# pylint: disable=too-many-boolean-expressions
+# pylint: disable=too-many-branches
+# pylint: disable=too-many-lines
+# pylint: disable=too-many-locals
+# pylint: disable=too-many-positional-arguments
+# pylint: disable=too-many-statements
+# pylint: disable=unused-argument
+
import datetime
-import markdown
-import markdown.extensions
import optparse
import os
import re
import sys
import time
-import xml.sax.saxutils
import xml.dom
import xml.dom.minidom
+import xml.sax.saxutils
+
+import markdown
+import markdown.extensions
__date__ = "2011-10-26"
__version__ = __date__.replace("-", ".")
@@ -123,21 +145,22 @@ def isLiteral(n):
def niceName(uri):
- global spec_bundle
if uri.startswith(spec_ns_str):
return uri.replace(spec_ns_str, "")
- elif uri == str(rdfs.seeAlso):
+
+ if uri == str(rdfs.seeAlso):
return "See also"
regexp = re.compile("^(.*[/#])([^/#]+)$")
rez = regexp.search(uri)
if not rez:
return uri
+
pref = rez.group(1)
if pref in ns_list:
return ns_list.get(pref, pref) + ":" + rez.group(2)
- else:
- return uri
+
+ return uri
def termName(m, urinode):
@@ -149,17 +172,17 @@ def getLabel(m, urinode):
statement = findOne(m, urinode, rdfs.label, None)
if statement:
return getLiteralString(getObject(statement))
- else:
- return ""
+
+ return ""
def linkifyCodeIdentifiers(string):
"Add links to code documentation for identifiers like LV2_Type"
- if linkmap == {}:
+ if not linkmap:
return string
- if string in linkmap.keys():
+ if string in linkmap:
# Exact match for complete string
return linkmap[string]
@@ -194,13 +217,14 @@ def linkifyVocabIdentifiers(m, string, classlist, proplist, instalist):
):
print("warning: Link to undefined resource <%s>\n" % text)
return '<a href="#%s">%s</a>' % (name, name)
- elif prefix in namespaces:
+
+ if prefix in namespaces:
return '<a href="%s">%s</a>' % (
namespaces[match.group(1)] + match.group(2),
match.group(0),
)
- else:
- return text
+
+ return text
return rgx.sub(translateLink, string)
@@ -256,15 +280,17 @@ def prettifyHtml(m, markup, subject, classlist, proplist, instalist):
or (proplist and uri in proplist)
):
return '%s<a href="#%s">%s</a>' % (space, name, name)
- else:
- print("warning: Link to undefined resource <%s>\n" % name)
- return text
+
+ print("warning: Link to undefined resource <%s>\n" % name)
+ return text
markup = rgx.sub(translateLocalLink, markup)
if not have_lxml:
print("warning: No Python lxml module found, output may be invalid")
else:
+ oldcwd = os.getcwd()
+
try:
# Parse and validate documentation as XHTML Basic 1.1
doc = (
@@ -283,7 +309,6 @@ def prettifyHtml(m, markup, subject, classlist, proplist, instalist):
</html>"""
)
- oldcwd = os.getcwd()
os.chdir(specgendir)
parser = etree.XMLParser(dtd_validation=True, no_network=True)
etree.fromstring(doc.encode("utf-8"), parser)
@@ -317,11 +342,11 @@ def formatDoc(m, urinode, literal, classlist, proplist, instalist):
doc = doc.replace("</%s>\n" % tag, "")
return prettifyHtml(m, doc, urinode, classlist, proplist, instalist)
- else:
- doc = xml.sax.saxutils.escape(string)
- doc = linkifyCodeIdentifiers(doc)
- doc = linkifyVocabIdentifiers(m, doc, classlist, proplist, instalist)
- return "<p>%s</p>" % doc
+
+ doc = xml.sax.saxutils.escape(string)
+ doc = linkifyCodeIdentifiers(doc)
+ doc = linkifyVocabIdentifiers(m, doc, classlist, proplist, instalist)
+ return "<p>%s</p>" % doc
def getComment(m, subject, classlist, proplist, instalist):
@@ -374,16 +399,11 @@ def getProperty(val, first=True):
def endProperties(first):
- if first:
- return "</tr>"
- else:
- return ""
+ return "</tr>" if first else ""
def rdfsPropertyInfo(term, m):
"""Generate HTML for properties: Domain, range"""
- global classranges
- global classdomains
doc = ""
label = getLabel(m, term)
@@ -478,8 +498,8 @@ def getTermLink(uri, subject=None, predicate=None):
extra,
niceName(uri),
)
- else:
- return '<a href="%s" %s>%s</a>' % (uri, extra, niceName(uri))
+
+ return '<a href="%s" %s>%s</a>' % (uri, extra, niceName(uri))
def owlRestrictionInfo(term, m):
@@ -537,8 +557,6 @@ def owlRestrictionInfo(term, m):
def rdfsClassInfo(term, m):
"""Generate rdfs-type information for Classes: ranges, and domains."""
- global classranges
- global classdomains
doc = ""
label = getLabel(m, term)
@@ -707,8 +725,8 @@ def owlInfo(term, m):
def owlTypeInfo(term, propertyType, name):
if findOne(m, term, rdf.type, propertyType):
return "<tr><th>Type</th><td>%s</td></tr>\n" % name
- else:
- return ""
+
+ return ""
res += owlTypeInfo(term, owl.DatatypeProperty, "Datatype Property")
res += owlTypeInfo(term, owl.ObjectProperty, "Object Property")
@@ -726,14 +744,14 @@ def isDeprecated(m, subject):
return deprecated and (str(deprecated[2]).find("true") >= 0)
-def docTerms(category, list, m, classlist, proplist, instalist):
+def docTerms(category, termlist, m, classlist, proplist, instalist):
"""
A wrapper class for listing all the terms in a specific class (either
Properties, or Classes. Category is 'Property' or 'Class', list is a
list of term URI strings, return value is a chunk of HTML.
"""
doc = ""
- for term in list:
+ for term in termlist:
if not term.startswith(spec_ns_str):
continue
@@ -792,17 +810,17 @@ def docTerms(category, list, m, classlist, proplist, instalist):
def getShortName(uri):
uri = str(uri)
if "#" in uri:
- return uri.split("#")[-1]
- else:
- return uri.split("/")[-1]
+ return uri.split("#", maxsplit=1)[-1]
+
+ return uri.split("/", maxsplit=1)[-1]
def getAnchor(uri):
uri = str(uri)
if uri.startswith(spec_ns_str):
return uri.replace(spec_ns_str, "").replace("/", "_")
- else:
- return getShortName(uri)
+
+ return getShortName(uri)
def buildIndex(m, classlist, proplist, instalist=None):
@@ -816,8 +834,8 @@ def buildIndex(m, classlist, proplist, instalist=None):
if str(t).startswith(spec_ns_str):
name = termName(m, t)
return '<a href="#%s">%s</a>' % (name, name)
- else:
- return '<a href="%s">%s</a>' % (str(t), str(t))
+
+ return '<a href="%s">%s</a>' % (str(t), str(t))
if len(classlist) > 0:
head += '<th><a href="#ref-classes" />Classes</th>'
@@ -900,22 +918,20 @@ def specInformation(m, ns):
and proplist. Global variables classranges and classdomains are also filled
as appropriate.
"""
- global classranges
- global classdomains
# Find the class information: Ranges, domains, and list of all names.
classtypes = [rdfs.Class, owl.Class, rdfs.Datatype]
classlist = []
for onetype in classtypes:
for classStatement in findStatements(m, None, rdf.type, onetype):
- for range in findStatements(
+ for rangelink in findStatements(
m, None, rdfs.range, getSubject(classStatement)
):
if not isBlank(getSubject(classStatement)):
add(
classranges,
str(getSubject(classStatement)),
- str(getSubject(range)),
+ str(getSubject(rangelink)),
)
for domain in findStatements(
m, None, rdfs.domain, getSubject(classStatement)
@@ -1002,15 +1018,16 @@ def specAuthors(m, subject):
maintdoc = ""
first = True
- for m in sorted(maint):
+ for name in sorted(maint):
if not first:
maintdoc += ", "
- maintdoc += (
- f'<span class="author" property="doap:maintainer">{m}</span>'
- )
+ maintdoc += '<span class="author" property="doap:maintainer">'
+ maintdoc += name
+ maintdoc += "</span>"
first = False
- if len(maint):
+
+ if maint:
label = "Maintainer" if len(maint) == 1 else "Maintainers"
doc += f'<tr><th class="metahead">{label}</th><td>{maintdoc}</td></tr>'
@@ -1096,12 +1113,12 @@ def load_tags(path, docdir):
anchor,
sym,
)
- else:
- return '<span><a href="%s/%s">%s</a></span>' % (
- docdir,
- filename,
- sym,
- )
+
+ return '<span><a href="%s/%s">%s</a></span>' % (
+ docdir,
+ filename,
+ sym,
+ )
tagdoc = xml.dom.minidom.parse(path)
root = tagdoc.documentElement
@@ -1151,14 +1168,12 @@ def specgen(
global spec_ns_str
global spec_ns
global spec_pre
- global ns_list
- global specgendir
global linkmap
spec_bundle = "file://%s/" % os.path.abspath(os.path.dirname(specloc))
# Template
- with open(template_path, "r") as f:
+ with open(template_path, "r", encoding="utf-8") as f:
template = f.read()
# Load code documentation link map from tags file
@@ -1243,6 +1258,7 @@ def specgen(
proplist = docTerms(
"Property", proplist, m, classlist, proplist, instalist
)
+ instlist = ""
if instances:
instlist = docTerms(
"Instance", instalist, m, classlist, proplist, instalist
@@ -1327,13 +1343,13 @@ def specgen(
template = template.replace("@DESCRIPTION@", docs)
now = int(os.environ.get("SOURCE_DATE_EPOCH", time.time()))
- build_date = datetime.datetime.utcfromtimestamp(now)
+ build_date = datetime.datetime.fromtimestamp(now, datetime.timezone.utc)
template = template.replace("@DATE@", build_date.strftime("%F"))
template = template.replace("@TIME@", build_date.strftime("%F %H:%M UTC"))
# Validate complete output page
+ oldcwd = os.getcwd()
try:
- oldcwd = os.getcwd()
os.chdir(specgendir)
etree.fromstring(
template.replace(
@@ -1354,7 +1370,7 @@ def specgen(
def save(path, text):
try:
- with open(path, "w") as f:
+ with open(path, "w", encoding="utf-8") as f:
f.write(text)
f.flush()
except Exception:
@@ -1413,8 +1429,6 @@ def _data_dirs():
if __name__ == "__main__":
- """Ontology specification generator tool"""
-
data_dir = None
for d in _data_dirs():
path = os.path.join(d, "lv2specgen")
diff --git a/lv2specgen/meson.build b/lv2specgen/meson.build
index 69b029b..bc3a616 100644
--- a/lv2specgen/meson.build
+++ b/lv2specgen/meson.build
@@ -1,4 +1,4 @@
-# Copyright 2022 David Robillard <d@drobilla.net>
+# Copyright 2022-2025 David Robillard <d@drobilla.net>
# SPDX-License-Identifier: 0BSD OR ISC
lv2specgen_py = files('lv2specgen.py')
@@ -11,8 +11,7 @@ lv2specgen_command_prefix = [
'--list-email=' + lv2_list_email,
'--list-page=' + lv2_list_page,
'--style-dir=' + lv2_source_root / 'doc' / 'style',
- '--template',
- files('template.html'),
+ '--template', files('template.html'),
]
if is_variable('lv2_tags')
@@ -21,24 +20,26 @@ if is_variable('lv2_tags')
]
endif
-install_data(
- files('lv2specgen.py'),
- install_dir: get_option('bindir'),
- install_mode: 'rwxr-xr-x',
-)
-
meson.override_find_program('lv2specgen.py', lv2specgen_py)
-install_data(
- files(
- '../doc/style/pygments.css',
- '../doc/style/style.css',
- 'template.html',
- ),
- install_dir: get_option('datadir') / 'lv2specgen',
-)
-
-install_subdir(
- 'DTD',
- install_dir: get_option('datadir') / 'lv2specgen',
-)
+if not get_option('tools').disabled()
+ install_data(
+ files('lv2specgen.py'),
+ install_dir: get_option('bindir'),
+ install_mode: 'rwxr-xr-x',
+ )
+
+ install_data(
+ files(
+ '../doc/style/pygments.css',
+ '../doc/style/style.css',
+ 'template.html',
+ ),
+ install_dir: get_option('datadir') / 'lv2specgen',
+ )
+
+ install_subdir(
+ 'DTD',
+ install_dir: get_option('datadir') / 'lv2specgen',
+ )
+endif