[Git][security-tracker-team/security-tracker][master] 8 commits: bugs.py: BugFromDB: speed up list construction
Emilio Pozuelo Monfort (@pochu)
pochu at debian.org
Mon Feb 16 08:59:40 GMT 2026
Emilio Pozuelo Monfort pushed to branch master at Debian Security Tracker / security-tracker
Commits:
87bb8cd3 by Helmut Grohne at 2026-02-15T13:32:47+01:00
bugs.py: BugFromDB: speed up list construction
When there are many NOTE entries for a bug, loading them can impact
performance. Optimize the loop using list.extend.
- - - - -
df2de9cf by Helmut Grohne at 2026-02-15T13:32:47+01:00
bugs.py: BugFromDB: inline private lookup functions
They used to be called several times until 20 years ago. Now that there
is only one invocation each, inline them.
- - - - -
f1af6f25 by Helmut Grohne at 2026-02-15T13:32:48+01:00
web_support.py: speed up escapeHTML*
- - - - -
06bb374a by Helmut Grohne at 2026-02-15T13:32:48+01:00
web_support.py: remove unnecessary branch in Tag.__init__
This is a hot code path in the security tracker. removeprefix is
available since Python 3.9 (bullseye).
- - - - -
005c817e by Helmut Grohne at 2026-02-15T13:32:48+01:00
web_support.py: improve Python 3 compatibility
sys.log was available in Python 2.x only.
- - - - -
1d4767ca by Helmut Grohne at 2026-02-15T13:32:48+01:00
web_support.py: drop Tag wrapper functions tag and emptyTag
While emptyTag has no uses left, the primary purpose of the tag wrapper
seems to have been turning keyword arguments into a passed dict. A
notable use here is allowing to pass attributes named "name" or
"contents". In Python versions >= 3.8 (bullseye), this can be achieved
using position-only arguments. We may now call Tag("input", name="spam")
and have the keyword passed via attribs. The wrapper was called a lot,
so we save a lot of unnecessary function calls.
- - - - -
d3e2982b by Helmut Grohne at 2026-02-15T13:32:48+01:00
web_support.py: fix wrong variable in error message
- - - - -
4dd115de by Emilio Pozuelo Monfort at 2026-02-16T08:59:35+00:00
Merge branch 'performance1' into 'master'
Improve web tracker performance
See merge request security-tracker-team/security-tracker!267
- - - - -
3 changed files:
- bin/tracker_service.py
- lib/python/bugs.py
- lib/python/web_support.py
Changes:
=====================================
bin/tracker_service.py
=====================================
@@ -71,8 +71,8 @@ class BugFilter:
else:
l.append(LABEL(INPUT(desc, type='checkbox', name='filter', value=prop, onChange='this.form.submit()'), rel=field))
- return FORM(tag("SPAN",l, id="filters"),
- tag("NOSCRIPT", [INPUT(type='submit', value='Apply')]),
+ return FORM(Tag("SPAN",l, id="filters"),
+ Tag("NOSCRIPT", [INPUT(type='submit', value='Apply')]),
method='get')
def urgencyFiltered(self, urg, vuln):
@@ -1532,7 +1532,7 @@ Debian bug number.'''),
return SPAN(contents, _class="green")
def make_mouseover(self, contents, text):
- return tag("SPAN", contents, title=text)
+ return Tag("SPAN", contents, title=text)
def make_dangerous(self, contents):
return SPAN(contents, _class="dangerous")
=====================================
lib/python/bugs.py
=====================================
@@ -303,29 +303,19 @@ class BugFromDB(Bug):
def __init__(self, cursor, name):
assert isinstance(name, str)
- def lookup(bug):
- for r in cursor.execute('SELECT * FROM bugs WHERE name = ?',
- (bug,)):
- return r
- else:
- return None
-
- def lookup_dsa(bug):
- for r in cursor.execute(
- """SELECT * FROM bugs
- WHERE name = ? OR name LIKE (? || '-%')
- ORDER BY release_date DESC
- LIMIT 1""", (bug, bug,)):
- return r
- else:
- return None
-
- r = lookup(name)
+ r = cursor.execute('SELECT * FROM bugs WHERE name = ?',
+ (name,)).fetchone()
if r is None:
name_components = name.split('-')
name_source = name_components[0]
if name_source == 'DSA' and 2 <= len(name_components) <= 3:
- r = lookup_dsa('DSA-' + name_components[1])
+ r = cursor.execute(
+ """SELECT * FROM bugs
+ WHERE name = ? OR name LIKE ?
+ ORDER BY release_date DESC
+ LIMIT 1""",
+ ('DSA-' + name_components[1],
+ 'DSA-' + name_components[1] + '-%',)).fetchone()
if r is None:
raise ValueError("unknown bug " + repr(name))
@@ -342,12 +332,11 @@ class BugFromDB(Bug):
for (x,) in cursor.execute\
('SELECT target FROM bugs_xref WHERE source = ?', (name,)):
self.xref.append(x)
- for (t, c) in cursor.execute\
+ self.comments.extend(cursor.execute\
("""SELECT typ, comment FROM bugs_notes
WHERE bug_name = ?
ORDER BY rowid""",
- (name,)):
- self.comments.append((t, c))
+ (name,)))
# temporary list required because loadBugs needs the cursor
for (nid, package, fixed_version, release, urgency, package_kind,
=====================================
lib/python/web_support.py
=====================================
@@ -94,9 +94,9 @@ class Service:
(magic, version, cli_size, cli_count, env_size, env_count) = \
struct.unpack("!6I", header)
if magic != 0x15fd34df:
- sys.log("unknown magic number %08X", magic)
+ self.log("unknown magic number %08X", magic)
if version != 1:
- sys.log("unknown version %08X", magic)
+ self.log("unknown version %08X", version)
cli = read(cli_size).split('\0')[:-1]
env = {}
for x in read(env_size).split('\0')[:-1]:
@@ -221,24 +221,24 @@ class URLFactory:
self.updateParamsDict(args)
charToHTML = {
- '<' : '<',
- '>' : '>',
- '&' : '&',
+ ord('<') : '<',
+ ord('>') : '>',
+ ord('&') : '&',
}
charToHTMLattr = {
- '&' : '&',
- '"' : '&34;',
+ ord('&') : '&',
+ ord('"') : '&34;',
}
def escapeHTML(str):
'''Replaces the characters <>& in the passed strings with their
HTML entities.'''
- return ''.join([charToHTML.get(ch, ch) for ch in str])
+ return str.translate(charToHTML)
def escapeHTMLattr(str):
'''Replaces the characters &" in the passed strings with their
HTML entities.'''
- return ''.join([charToHTMLattr.get(ch, ch) for ch in str])
+ return str.translate(charToHTMLattr)
class HTMLBase:
def flatten(self, write):
@@ -291,7 +291,14 @@ class Tag(HTMLBase):
re_name = re.compile(r'\A_?[a-zA-Z][a-zA-Z0-9]*\Z')
- def __init__(self, name, contents, attribs={}):
+ def __init__(self, name, contents=None, /, **attribs):
+ """Creates a new tag object.
+
+ name - name of the tag
+ contents - an optional sequence object (or iterator) for the enclosed
+ contents
+ attribs - keyword arguments forming attributes
+ """
self._check(name)
self.__name = name
attrs = []
@@ -301,10 +308,7 @@ class Tag(HTMLBase):
continue
self._check(key)
append(' ')
- if key[0] == '_':
- append(key[1:])
- else:
- append(key)
+ append(key.removeprefix('_'))
append('="')
append(escapeHTMLattr(str(value)))
append('"')
@@ -349,85 +353,68 @@ class Tag(HTMLBase):
self.flatten(r.write)
return r.getvalue()
-def tag(__name, __contents, **__attribs):
- """Creates a new tag object.
-
- name - name of the tag
- contents - a sequence objet (or iterator) for the enclosed contents
- attribs - keyword arguments forming attributes
- """
- return Tag(__name, __contents, __attribs)
-
-def emptyTag(__name, **__attribs):
- """A tag without contents.
-
- name - name of the tag
- attribs - keyword arguments forming attributes
- """
- return Tag(__name, None, __attribs)
-
def A(url, text=None):
if text is None:
text = url
- return tag('a', text, href=str(url))
+ return Tag('a', text, href=str(url))
def STYLE(contents, type='text/css'):
- return tag('style', contents, type=type)
+ return Tag('style', contents, type=type)
def SCRIPT(contents, type="text/javascript", src=""):
- return tag('script', contents, type=type, src=src)
+ return Tag('script', contents, type=type, src=src)
def LINK(contents, type="text/css", rel="stylesheet", href=""):
- return tag('link', contents, type=type, rel=rel, href=href)
+ return Tag('link', contents, type=type, rel=rel, href=href)
def TITLE(contents):
- return tag('title', contents)
+ return Tag('title', contents)
def HTML(head, body):
- return tag('html', (HEAD(head), BODY(body)))
+ return Tag('html', (HEAD(head), BODY(body)))
def HEAD(contents):
- return tag('head', contents)
+ return Tag('head', contents)
def BODY(contents, onload=None):
- return tag('body', contents, onload=onload)
+ return Tag('body', contents, onload=onload)
def H1(contents):
- return tag('h1', contents)
+ return Tag('h1', contents)
def H2(contents):
- return tag('h2', contents)
+ return Tag('h2', contents)
def H3(contents):
- return tag('h3', contents)
+ return Tag('h3', contents)
def P(*contents):
return Tag('p', contents)
def SPAN(*__contents, **__attribs):
- return Tag('span', __contents, __attribs)
+ return Tag('span', __contents, **__attribs)
def HR():
- return tag('hr', ())
+ return Tag('hr')
def BR():
- return tag('br', ())
+ return Tag('br')
def CODE(*contents):
- return tag('code', contents)
+ return Tag('code', contents)
def EM(*contents):
- return tag('em', contents)
+ return Tag('em', contents)
def B(contents):
- return tag('b', contents)
+ return Tag('b', contents)
def TABLE(contents):
- return tag('table', contents)
+ return Tag('table', contents)
def TR(*contents):
- return tag('tr', contents)
+ return Tag('tr', contents)
def TH(*contents):
- return tag('th', contents)
+ return Tag('th', contents)
def TD(*contents):
- return tag('td', contents)
+ return Tag('td', contents)
def FORM(*__contents, **__attribs):
- return Tag('form', __contents, __attribs)
+ return Tag('form', __contents, **__attribs)
def LABEL(*__contents, **__attribs):
- return Tag('label', __contents, __attribs)
+ return Tag('label', __contents, **__attribs)
def INPUT(*__contents, **__attribs):
- return Tag('input', __contents, __attribs)
+ return Tag('input', __contents, **__attribs)
def UL(contents):
- return tag('ul', contents)
+ return Tag('ul', contents)
def LI(*__contents, **__attribs):
- return Tag('li', __contents, __attribs)
+ return Tag('li', __contents, **__attribs)
def HEADER(*__contents, **__attribs):
- return Tag('header', __contents, __attribs)
+ return Tag('header', __contents, **__attribs)
def FOOTER(*__contents, **__attribs):
- return Tag('footer', __contents, __attribs)
+ return Tag('footer', __contents, **__attribs)
def NAV(*__contents, **__attribs):
- return Tag('nav', __contents, __attribs)
+ return Tag('nav', __contents, **__attribs)
def _linkify(match):
extra = match.group(2)
@@ -476,9 +463,9 @@ def make_pre(lines):
else:
append(group)
else:
- append(tag("SPAN",line))
+ append(Tag("SPAN", line))
append(BR())
- return tag('pre', pre)
+ return Tag('pre', pre)
def make_menu(convert, *entries):
"""Creates an unnumbered list of hyperlinks.
@@ -497,7 +484,7 @@ def make_menu(convert, *entries):
append(LI(A(convert(relurl), label)))
else:
append(LI(e))
- return tag('ul', ul)
+ return Tag('ul', ul)
def make_numbered_list(entries):
"""Creates a numbered list.
@@ -506,7 +493,7 @@ def make_numbered_list(entries):
append = ol.append
for e in entries:
append(LI(e))
- return tag('ol', ol)
+ return Tag('ol', ol)
def make_list(lst, separator=", "):
"""Creates a list of HTML elements."""
@@ -736,8 +723,8 @@ class WebServiceBase:
body_list = list(body)
body_list[:0] = (HEADER(H1(title)),)
- return tag('html',
- (HEAD(head_list), Tag('body', body_list, body_attribs)))
+ return Tag('html',
+ (HEAD(head_list), Tag('body', body_list, **body_attribs)))
def pre_dispatch(self, url):
"""Invoked by handle prior to calling the registered handler."""
View it on GitLab: https://salsa.debian.org/security-tracker-team/security-tracker/-/compare/030d1a1b68cff20299023b18f551a41601e75e5c...4dd115de0f0bf5ff9b30e35630c4769d47df045e
--
View it on GitLab: https://salsa.debian.org/security-tracker-team/security-tracker/-/compare/030d1a1b68cff20299023b18f551a41601e75e5c...4dd115de0f0bf5ff9b30e35630c4769d47df045e
You're receiving this email because of your account on salsa.debian.org.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/debian-security-tracker-commits/attachments/20260216/979f98fd/attachment-0001.htm>
More information about the debian-security-tracker-commits
mailing list