move to use elementtree

This commit is contained in:
Louis Abel 2023-09-07 02:12:08 -07:00
parent 98a1737764
commit 21f8ced3dc
Signed by: label
GPG Key ID: B37E62D143879B36

View File

@ -8,10 +8,15 @@ import os
import argparse
import time
import binascii
# The old yum-utils repo-rss used string manipulation. We're instead going to
# use the XML python library to do the work for us. This is cleaner, imo.
from xml.sax.saxutils import escape as xmlescape
from xml.etree.ElementTree import ElementTree, TreeBuilder, tostring
from xml.dom import minidom
import dnf
import dnf.exceptions
#from dnf.comps import Comps
import libxml2
#import libxml2
def to_unicode(string: str) -> str:
"""
@ -43,6 +48,8 @@ class DnfQuiet(dnf.Base):
else:
available = self.sack.query().available().filter(latest_per_arch=1)
available.run()
for package in available:
ftime = int(package.buildtime)
if ftime > recentlimit:
@ -60,45 +67,58 @@ class DnfQuiet(dnf.Base):
class RepoRSS:
def __init__(self, filename='repo-rss.xml'):
self.description = 'Repository RSS'
self.link = 'http://dnf.baseurl.org'
self.link = 'https://github.com/rpm-software-management/dnf'
self.title = 'Recent Packages'
self.do_file(filename)
self.do_doc()
def do_doc(self):
self.doc = libxml2.newDoc('1.0')
self.xmlescape = self.doc.encodeEntitiesReentrant
rss = self.doc.newChild(None, 'rss', None)
rss.setProp('version', '2.0')
self.rssnode = rss.newChild(None, 'channel', None)
def do_file(self, filename):
if filename[0] != '/':
cwd = os.getcwd()
self.filename = os.path.join(cwd, filename)
else:
self.filename = filename
try:
self.file_open = open(self.filename, 'w+')
except IOError as exc:
print(f'Error opening file {self.filename}: {exc}', file=sys.stderr)
sys.exit(1)
def rsspackage(self, packages):
file = self.filename
rfc822_format = "%a, %d %b %Y %X GMT"
now = time.strftime(rfc822_format, time.gmtime())
etbobj = TreeBuilder()
# start rss
etbobj.start('rss', {'version': '2.0'})
# start channel
etbobj.start('channel', {})
# start title
etbobj.start('title', {})
etbobj.data(self.title)
etbobj.end('title')
# end title
# start link
etbobj.start('link', {})
etbobj.data(self.link)
etbobj.end('link')
# end link
# start description
etbobj.start('description', {})
etbobj.data(self.description)
etbobj.end('description')
# end description
# start pubDate
etbobj.start('pubDate', {})
etbobj.data(now)
etbobj.end('pubDate')
# end pubDate
# start generator
etbobj.start('generator', {})
etbobj.data('DNF')
etbobj.end('generator')
# end generator
def rsspackage(self, package):
rfc822_format = "%a, %d %b %Y %X GMT"
changelog_format = "%a, %d %b %Y GMT"
for package in packages:
package_hex = binascii.hexlify(package.chksum[1]).decode()
item = self.rssnode.newChild(None, 'item', None)
title = self.xmlescape(str(package))
description = package.description
item.newChild(None, 'title', title)
title = xmlescape(str(package))
date = time.gmtime(float(package.buildtime))
item.newChild(None, 'pubDate', time.strftime(rfc822_format, date))
# pylint: disable=line-too-long
item.newChild(None, 'guid', package_hex).setProp("isPermaLink", "false")
description = package.description
link = package.remote_location()
item.newChild(None, 'link', self.xmlescape(link))
# form description
changelog = ''
count = 0
if package.changelogs is not None:
@ -114,54 +134,59 @@ class RepoRSS:
author = meta['author']
desc = meta['text']
changelog += f'{date} - {author}\n{desc}\n\n'
# pylint: disable=line-too-long,consider-using-f-string
description = '<p><strong>{}</strong> - {}</p>\n\n'.format(self.xmlescape(package.name), self.xmlescape(package.summary))
description += '<p>%s</p>\n\n<p><strong>Change Log:</strong></p>\n\n' % self.xmlescape(description.replace("\n", "<br />\n"))
description += self.xmlescape('<pre>%s</pre>' % self.xmlescape(changelog))
item.newChild(None, 'description', description)
return item
description = f'<p><strong>{package.name}</strong> - {package.summary}</p>\n\n'
description += '<p>%s</p>\n\n<p><strong>Change Log:</strong></p>\n\n' % description.replace("\n", "<br />\n")
description += f'<pre>{changelog}</pre>'
def start_rss(self):
"""return string representation of rss preamble"""
rfc822_format = "%a, %d %b %Y %X GMT"
now = time.strftime(rfc822_format, time.gmtime())
rssheader = f"""<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
<channel>
<title>{self.title}</title>
<link>{self.link}</link>
<description>{self.description}</description>
<pubDate>{now}</pubDate>
<generator>DNF</generator>
"""
# start item
etbobj.start('item', {})
# start title
etbobj.start('title', {})
etbobj.data(title)
etbobj.end('title')
# end title
# start pubDate
etbobj.start('pubDate', {})
etbobj.data(date)
etbobj.end('pubDate')
# end pubDate
# start guid
etbobj.start('guid', {'isPermaLink': 'false'})
etbobj.data(package_hex)
etbobj.end('guid',)
# end guid
# start link
etbobj.start('link', {})
etbobj.data(link)
etbobj.end('link')
# end link
# start description
etbobj.start('description', {})
etbobj.data(xmlescape(description))
etbobj.end('description')
# end description
etbobj.end('item')
# end item
self.file_open.write(rssheader)
etbobj.end('channel')
# end channel
etbobj.end('rss')
# end rss
rss = etbobj.close()
etree = ElementTree(rss)
some_string = tostring(etree.getroot(), encoding='utf-8')
xmlstr = minidom.parseString(some_string).toprettyxml(indent=" ")
#etree.write(file, encoding='utf-8')
with open(file, 'w+', encoding='utf-8') as f:
f.write(xmlstr)
f.close()
def do_package(self, package):
item = self.rsspackage(package)
self.file_open.write(item.serialize("utf-8", 1))
item.unlinkNode()
item.freeNode()
del item
def close_rss(self):
end="\n </channel>\n</rss>\n"
self.file_open.write(end)
self.file_open.close()
del self.file_open
self.doc.freeDoc()
del self.doc
def make_rss_feed(filename, title, link, description, recent, dnfobj):
def make_rss_feed(filename, title, link, description, recent):
rssobj = RepoRSS(filename)
rssobj.title = title
rssobj.link = link
rssobj.description = description
rssobj.start_rss()
if len(recent) > 0:
for package in recent:
rssobj.do_package(package)
rssobj.close_rss()
rssobj.rsspackage(recent)
def main(options):
days = options.days
@ -198,7 +223,7 @@ def main(options):
repoobj.load_metadata_other = True
print('Getting repo data')
print('Getting repo data for requested repos')
try:
dnfobj.fill_sack()
except:
@ -206,10 +231,13 @@ def main(options):
sys.exit(1)
sack_query = dnfobj.sack.query().available()
recent = sack_query.filter(latest_per_arch=1)
sorted_recents = sorted(set(recent.run()), key=lambda pkg: pkg.buildtime)
#recent = sack_query.filter(latest_per_arch=1)
recent = dnfobj.get_recent(days=days)
#sorted_recents = sorted(set(recent.run()), key=lambda pkg: pkg.buildtime)
sorted_recents = sorted(set(recent), key=lambda pkg: pkg.buildtime)
sorted_recents.reverse()
make_rss_feed(options.filename, options.title, options.link, options.description, sorted_recents, dnfobj)
make_rss_feed(options.filename, options.title, options.link,
options.description, sorted_recents)
if __name__ == "__main__":
parser = argparse.ArgumentParser()