summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorScott Bahling <sbahling@suse.com>2020-02-06 22:16:02 +0100
committerScott Bahling <sbahling@suse.com>2020-02-06 22:35:43 +0100
commitcd12f43cd2c98826bb0ea092ef590a91e5842886 (patch)
treefc13c2f90a9e3190ab172b1556dc1eb3caa124b4
parentc86fdd52a30ca1833149d46b7fee9135a74e4598 (diff)
downloadobsapi-cd12f43cd2c98826bb0ea092ef590a91e5842886.tar.gz
obsapi-cd12f43cd2c98826bb0ea092ef590a91e5842886.tar.xz
obsapi-cd12f43cd2c98826bb0ea092ef590a91e5842886.zip
Handle passing bytes to the FileInfo class
Move class to own file and enhance tests
-rw-r--r--obsapi/__init__.py1
-rw-r--r--obsapi/core.py119
-rw-r--r--obsapi/fileinfo.py102
-rw-r--r--obsapi/helpers.py23
-rw-r--r--test/binary_fileinfo.xml40
-rw-r--r--test/test_api.py23
-rw-r--r--test/test_fileinfo.py26
7 files changed, 207 insertions, 127 deletions
diff --git a/obsapi/__init__.py b/obsapi/__init__.py
index 6b3af61..547af96 100644
--- a/obsapi/__init__.py
+++ b/obsapi/__init__.py
@@ -3,4 +3,3 @@ from obsapi.core import *
from ._version import get_versions
__version__ = get_versions()['version']
del get_versions
-
diff --git a/obsapi/core.py b/obsapi/core.py
index d4980dc..80067d6 100644
--- a/obsapi/core.py
+++ b/obsapi/core.py
@@ -1,14 +1,13 @@
# -*- coding: utf-8 -*-
#
import re
-from io import BytesIO
from lxml import etree
from collections import namedtuple
-from datetime import datetime
+from obsapi import helpers
from obsapi.sourceapi import ObsSourceApi
from obsapi.buildapi import ObsBuildApi
-from obsapi.formatter import Formatter
from obsapi.repoflags import RepoFlags
+from obsapi.fileinfo import FileInfo
LSItem = namedtuple('LSItem', 'name md5 size mtime')
@@ -25,102 +24,7 @@ emptyxml = '<empty></empty>'
EMPTYTREE = etree.fromstring(emptyxml)
EMPTY = EMPTYTREE.xpath('.')[0]
-
-class FileInfo(object):
- file_str_template = ('{filename}'
- 'size : {size}'
- 'mtime : {mtime}'
- )
-
- pkg_str_template = ('{filename}'
- 'Name : {name}'
- 'Version : {version}'
- 'Release : {release}'
- 'Architecture: {arch}'
- 'Size : {size}'
- 'Source RPM : {source}'
- 'Build Date : {mtime}'
- 'Summary : {summary}'
- 'Description :'
- '{description}'
- 'Provides :'
- '{provides}'
- )
-
- src_str_template = ('{filename}'
- 'Name : {name}'
- 'Version : {version}'
- 'Release : {release}'
- 'Architecture: {arch}'
- 'Size : {size}'
- 'Build Date : {mtime}'
- 'Summary : {summary}'
- 'Description :'
- '{description}'
- )
-
- def __init__(self, xml):
- self.finfo = etree.fromstring(xml)
- self.filename = self.finfo.get('filename', None)
- self.formatter = Formatter(self)
-
- @property
- def info(self):
- info = {'filename': [self.filename]}
- for item in self.finfo:
- info.setdefault(item.tag, []).append(item.text)
-
- for item, value in info.items():
- if len(value) == 1:
- info[item] = value[0]
- # info[item] = '\n'.join(value)
-
- return info
-
- def __str__(self):
- return self.formatter.render()
-
- def __getattr__(self, attr):
- try:
- values = [value.text for value in self.finfo.findall(attr)]
- except Exception:
- values = [None]
-
- if len(values) == 1:
- return values[0]
- else:
- return values
-
- @property
- def datetime(self):
- if self.mtime:
- return datetime.fromtimestamp(int(self.mtime))
-
- @property
- def xml(self):
- return etree.tostring(self.finfo)
-
- @property
- def is_pkg(self):
- if self.arch:
- return True
- else:
- return False
-
- @property
- def is_src(self):
- if self.source:
- return False
- else:
- return True
-
- @property
- def is_debug_info(self):
- if '-' in self.name:
- if self.name.split('-')[-1] in ('debuginfo', 'debugsource'):
- return True
-
- return False
+xml2etree = helpers.xml2etree
class ObsApi(object):
@@ -137,11 +41,6 @@ class ObsApi(object):
self.build.verify_ssl = True
self.lastapi = None
- def __xml2etree(self, xml):
- xml = xml.encode('utf-8')
- parser = etree.XMLParser(remove_blank_text=True)
- return etree.parse(BytesIO(xml), parser).xpath('.')[0]
-
def get_meta(self, prj, pkg=None):
return self.source.get_meta(prj, pkg=pkg)
@@ -162,7 +61,7 @@ class ObsApi(object):
if xml is None:
return []
- d = self.__xml2etree(xml)
+ d = xml2etree(xml)
lsitems = [e.get('name') for e in d.findall('entry')]
return lsitems
@@ -303,7 +202,7 @@ class ObsApi(object):
return RepoFlags(self.get_meta(prj, pkg))
def locked(self, prj, pkg=None):
- meta = self.__xml2etree(self.get_meta(prj, pkg))
+ meta = xml2etree(self.get_meta(prj, pkg))
if meta.find('lock') is not None:
return True
return False
@@ -328,7 +227,7 @@ class ObsApi(object):
if role is None:
role = '.*' # regex to match all
- meta = self.__xml2etree(xml)
+ meta = xml2etree(xml)
persons = meta.xpath('.//person[re:test(@role, role)]', namespaces={'re': REGEX_NS})
return [User(userid=p.get('userid'), role=p.get('role')) for p in persons]
@@ -340,7 +239,7 @@ class ObsApi(object):
if role is None:
role = '.*' # regex to match all
- meta = self.__xml2etree(xml)
+ meta = xml2etree(xml)
groups = meta.xpath('.//group[re:test(@role, role)]', namespaces={'re': REGEX_NS})
return [Group(groupid=g.get('groupid'), role=g.get('role')) for g in groups]
@@ -359,7 +258,7 @@ class ObsApi(object):
if xml is None:
raise Exception('unable to retrieve project meta')
- meta = self.__xml2etree(xml)
+ meta = xml2etree(xml)
etree.SubElement(meta, 'person', userid=userid, role=role)
return self.put_meta(prj, pkg, etree.tostring(meta))
@@ -378,7 +277,7 @@ class ObsApi(object):
if xml is None:
raise Exception('unable to retrieve project meta')
- meta = self.__xml2etree(xml)
+ meta = xml2etree(xml)
etree.SubElement(meta, 'group', groupid=groupid, role=role)
return self.put_meta(prj, pkg, etree.tostring(meta))
diff --git a/obsapi/fileinfo.py b/obsapi/fileinfo.py
new file mode 100644
index 0000000..7024bdd
--- /dev/null
+++ b/obsapi/fileinfo.py
@@ -0,0 +1,102 @@
+# -*- coding: utf-8 -*-
+
+from lxml import etree
+from datetime import datetime
+from obsapi.formatter import Formatter
+from obsapi.helpers import xml2etree
+
+class FileInfo(object):
+ file_str_template = ('{filename}'
+ 'size : {size}'
+ 'mtime : {mtime}'
+ )
+
+ pkg_str_template = ('{filename}'
+ 'Name : {name}'
+ 'Version : {version}'
+ 'Release : {release}'
+ 'Architecture: {arch}'
+ 'Size : {size}'
+ 'Source RPM : {source}'
+ 'Build Date : {mtime}'
+ 'Summary : {summary}'
+ 'Description :'
+ '{description}'
+ 'Provides :'
+ '{provides}'
+ )
+
+ src_str_template = ('{filename}'
+ 'Name : {name}'
+ 'Version : {version}'
+ 'Release : {release}'
+ 'Architecture: {arch}'
+ 'Size : {size}'
+ 'Build Date : {mtime}'
+ 'Summary : {summary}'
+ 'Description :'
+ '{description}'
+ )
+
+ def __init__(self, xml):
+ self.finfo = xml2etree(xml)
+ self.filename = self.finfo.get('filename', None)
+ self.formatter = Formatter(self)
+
+ @property
+ def info(self):
+ info = {'filename': [self.filename]}
+ for item in self.finfo:
+ info.setdefault(item.tag, []).append(item.text)
+
+ for item, value in info.items():
+ if len(value) == 1:
+ info[item] = value[0]
+ # info[item] = '\n'.join(value)
+
+ return info
+
+ def __str__(self):
+ return self.formatter.render()
+
+ def __getattr__(self, attr):
+ try:
+ values = [value.text for value in self.finfo.findall(attr)]
+ except Exception:
+ values = [None]
+
+ if len(values) == 1:
+ return values[0]
+ else:
+ return values
+
+ @property
+ def datetime(self):
+ if self.mtime:
+ return datetime.fromtimestamp(int(self.mtime))
+
+ @property
+ def xml(self):
+ return etree.tostring(self.finfo)
+
+ @property
+ def is_pkg(self):
+ if self.arch:
+ return True
+ else:
+ return False
+
+ @property
+ def is_src(self):
+ if self.source:
+ return False
+ else:
+ return True
+
+ @property
+ def is_debug_info(self):
+ if '-' in self.name:
+ if self.name.split('-')[-1] in ('debuginfo', 'debugsource'):
+ return True
+
+ return False
diff --git a/obsapi/helpers.py b/obsapi/helpers.py
new file mode 100644
index 0000000..6912035
--- /dev/null
+++ b/obsapi/helpers.py
@@ -0,0 +1,23 @@
+# -*- coding: utf-8 -*-
+"""
+ obsapi: helper module
+ ~~~~~~~~~~~~~~~~~~~~~
+
+ This module contains helper functions
+
+
+ :copyright: Copyright (c) 2020 Scott Bahling, SUSE Linux GmbH
+ :license: GPL-2.0, see COPYING for details
+"""
+from io import BytesIO
+from lxml import etree
+
+
+def xml2etree(xml):
+ try:
+ if not isinstance(xml, bytes):
+ xml = xml.encode('utf-8')
+ parser = etree.XMLParser(remove_blank_text=True)
+ return etree.parse(BytesIO(xml), parser).xpath('.')[0]
+ except Exception as e:
+ raise e
diff --git a/test/binary_fileinfo.xml b/test/binary_fileinfo.xml
new file mode 100644
index 0000000..28a8dd5
--- /dev/null
+++ b/test/binary_fileinfo.xml
@@ -0,0 +1,40 @@
+<fileinfo filename="apache2-2.4.41-12.1.src.rpm">
+ <name>apache2</name>
+ <version>2.4.41</version>
+ <release>12.1</release>
+ <arch>src</arch>
+ <summary>The Apache Web Server</summary>
+ <description>This version of httpd is a major release of the 2.4 stable branch,
+and represents the best available version of Apache HTTP Server.
+New features include Loadable MPMs, major improvements to OCSP support,
+mod_lua, Dynamic Reverse Proxy configuration, Improved Authentication/
+Authorization, FastCGI Proxy, New Expression Parser, and a Small Object
+Caching API.
+
+ See /usr/share/doc/packages/apache2/, http://httpd.apache.org/, and
+http://httpd.apache.org/docs-2.4/upgrading.html.</description>
+ <size>7657917</size>
+ <mtime>1580719265</mtime>
+ <requires>apache-rpm-macros-control</requires>
+ <requires>apr-devel &gt;= 1.5.0</requires>
+ <requires>apr-util-devel</requires>
+ <requires>automake</requires>
+ <requires>db-devel</requires>
+ <requires>ed</requires>
+ <requires>firewall-macros</requires>
+ <requires>libcap-devel</requires>
+ <requires>libxml2-devel</requires>
+ <requires>lua-devel</requires>
+ <requires>openldap2-devel</requires>
+ <requires>openssl-devel &gt;= 0.9.8a</requires>
+ <requires>pcre-devel</requires>
+ <requires>pkgconfig</requires>
+ <requires>pkgconfig(libbrotlidec)</requires>
+ <requires>pkgconfig(libbrotlienc)</requires>
+ <requires>pkgconfig(libnghttp2) &gt;= 1.2.1</requires>
+ <requires>pkgconfig(libsystemd)</requires>
+ <requires>pkgconfig(systemd)</requires>
+ <requires>systemd-rpm-macros</requires>
+ <requires>xz</requires>
+ <requires>zlib-devel</requires>
+</fileinfo>
diff --git a/test/test_api.py b/test/test_api.py
index 5769543..e45a284 100644
--- a/test/test_api.py
+++ b/test/test_api.py
@@ -48,6 +48,12 @@ def project_config():
@pytest.fixture
+def binary_fileinfo():
+ with open(os.path.join(test_dir, 'binary_fileinfo.xml'), 'rb') as f:
+ return f.read()
+
+
+@pytest.fixture
def source_info():
return """<sourceinfo package="suse-hello-1.0" rev="1" vrev="1" srcmd5="7054c47fb2ebde13fc62ee64d0a3b1bc" verifymd5="7054c47fb2ebde13fc62ee64d0a3b1bc">
<filename>suse-hello.spec</filename>
@@ -95,21 +101,6 @@ def binarylist():
@pytest.fixture
-def binary_fileinfo():
- return """<fileinfo filename="suse-hello-1.0-1.1.src.rpm">
-<name>suse-hello</name>i
-<version>1.0</version>
-<release>1.1</release>
-<arch>src</arch>
-<summary>Sample Kernel Module Package</summary>
-<description>This package contains the hello.ko module.</description>
-<size>5181</size><mtime>1507137122</mtime>
-<requires>kmod-compat</requires>
-<requires>kernel-syms</requires>
-</fileinfo>"""
-
-
-@pytest.fixture
def project_meta():
return """<project name="home:sbahling:obsapi:test">
<title>Test project for obsapi unit tests</title>
@@ -340,7 +331,7 @@ def test_source_info(requests_mock, source_info, rev):
def test_get_binary_fileinfo(requests_mock, binary_fileinfo):
matcher = re.compile('/build/.*/.*/.*/.*/.*?view=fileinfo')
- requests_mock.get(matcher, text=binary_fileinfo)
+ requests_mock.get(matcher, content=binary_fileinfo)
binary = 'suse-hello-1.0-1.1.src.rpm'
expected_bfinfo = etree.fromstring(binary_fileinfo)
diff --git a/test/test_fileinfo.py b/test/test_fileinfo.py
new file mode 100644
index 0000000..18d1f15
--- /dev/null
+++ b/test/test_fileinfo.py
@@ -0,0 +1,26 @@
+import os
+import pytest
+from lxml import etree
+from obsapi import FileInfo
+from . import test_dir
+
+
+with open(os.path.join(test_dir, 'binary_fileinfo.xml'), 'rb') as f:
+ xml_as_bytes = f.read()
+
+
+with open(os.path.join(test_dir, 'binary_fileinfo.xml'), 'r') as f:
+ xml_as_str = f.read()
+
+
+@pytest.mark.parametrize('xml', (xml_as_bytes, xml_as_str))
+def test_fileinfo(xml):
+ finfo = FileInfo(xml)
+ root = etree.fromstring(xml)
+ assert finfo.name == root.find('name').text
+ assert finfo.version == root.find('version').text
+ assert finfo.release == root.find('release').text
+ assert finfo.arch == root.find('arch').text
+ assert finfo.summary == root.find('summary').text
+ assert finfo.description == root.find('description').text
+ assert len(finfo.requires) == len(root.findall('requires'))