Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package python-resultsdb_api for
openSUSE:Factory checked in at 2026-06-25 10:58:16
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-resultsdb_api (Old)
and /work/SRC/openSUSE:Factory/.python-resultsdb_api.new.2088 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-resultsdb_api"
Thu Jun 25 10:58:16 2026 rev:6 rq:1361665 version:2.1.6
Changes:
--------
---
/work/SRC/openSUSE:Factory/python-resultsdb_api/python-resultsdb_api.changes
2026-01-27 16:15:21.873668338 +0100
+++
/work/SRC/openSUSE:Factory/.python-resultsdb_api.new.2088/python-resultsdb_api.changes
2026-06-25 11:00:08.463430787 +0200
@@ -1,0 +2,12 @@
+Wed Jun 24 20:08:58 UTC 2026 - Martin Pluskal <[email protected]>
+
+- Update to version 2.1.6:
+ * Replace the deprecated logger.warn() with logger.warning()
+ * More robust HTTP error handling: cope with responses whose
+ JSON body is missing the expected message or cannot be parsed
+ * Internal code-style cleanup
+- Drop support-pytest-9.patch (the patched testing/conftest.py was
+ removed upstream); run the now fully-mocked test suite via
+ plain pytest (the --functional gate was dropped upstream)
+
+-------------------------------------------------------------------
Old:
----
resultsdb_api-2.1.5.tar.gz
support-pytest-9.patch
New:
----
resultsdb_api-2.1.6.tar.gz
----------(Old B)----------
Old: * Internal code-style cleanup
- Drop support-pytest-9.patch (the patched testing/conftest.py was
removed upstream); run the now fully-mocked test suite via
----------(Old E)----------
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-resultsdb_api.spec ++++++
--- /var/tmp/diff_new_pack.0kb5W7/_old 2026-06-25 11:00:09.079452023 +0200
+++ /var/tmp/diff_new_pack.0kb5W7/_new 2026-06-25 11:00:09.083452161 +0200
@@ -17,14 +17,12 @@
Name: python-resultsdb_api
-Version: 2.1.5
+Version: 2.1.6
Release: 0
Summary: Library for simplifying the communication with ResultsDB
License: GPL-2.0-or-later
URL: https://pagure.io/taskotron/resultsdb_api
Source:
https://files.pythonhosted.org/packages/source/r/resultsdb_api/resultsdb_api-%{version}.tar.gz
-# PATCH-FIX-OPENSUSE Support pytest 9 changes
-Patch0: support-pytest-9.patch
BuildRequires: %{python_module pip}
BuildRequires: %{python_module setuptools}
BuildRequires: %{python_module wheel}
@@ -36,6 +34,7 @@
# SECTION test requirements
BuildRequires: %{python_module pytest >= 2.4.2}
BuildRequires: %{python_module requests >= 2.2.1}
+BuildRequires: %{python_module responses}
BuildRequires: %{python_module simplejson >= 3.5.3}
# /SECTION
%python_subpackages
@@ -54,10 +53,12 @@
%install
%pyproject_install
+# force hash-based .pyc (avoid python-bytecode-inconsistent-mtime)
+%python_expand $python -m compileall -q -f -o 0 -o 1 --invalidation-mode
unchecked-hash %{buildroot}%{$python_sitelib}
%python_expand %fdupes %{buildroot}%{$python_sitelib}
%check
-%pytest --functional testing/
+%pytest testing/
%files %{python_files}
%doc README.md
++++++ resultsdb_api-2.1.5.tar.gz -> resultsdb_api-2.1.6.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/resultsdb_api-2.1.5/.arcconfig
new/resultsdb_api-2.1.6/.arcconfig
--- old/resultsdb_api-2.1.5/.arcconfig 2018-03-27 17:28:16.000000000 +0200
+++ new/resultsdb_api-2.1.6/.arcconfig 1970-01-01 01:00:00.000000000 +0100
@@ -1,6 +0,0 @@
-{
- "project_id" : "resultsdb_api",
- "conduit_uri" : "https://phab.qa.fedoraproject.org",
- "arc.land.onto.default" : "develop",
- "arc.feature.start.default" : "develop"
-}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/resultsdb_api-2.1.5/.arclint
new/resultsdb_api-2.1.6/.arclint
--- old/resultsdb_api-2.1.5/.arclint 2018-03-28 15:14:06.000000000 +0200
+++ new/resultsdb_api-2.1.6/.arclint 1970-01-01 01:00:00.000000000 +0100
@@ -1,12 +0,0 @@
-{
- "linters": {
- "flake8": {
- "type": "flake8",
- "include": "(\\.py$)",
- "severity.rules": {
- "(^E)": "warning",
- "(^F)": "error"
- }
- }
- }
-}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/resultsdb_api-2.1.5/.forgejo/workflows/ai-review.yml
new/resultsdb_api-2.1.6/.forgejo/workflows/ai-review.yml
--- old/resultsdb_api-2.1.5/.forgejo/workflows/ai-review.yml 1970-01-01
01:00:00.000000000 +0100
+++ new/resultsdb_api-2.1.6/.forgejo/workflows/ai-review.yml 2026-02-26
22:34:21.000000000 +0100
@@ -0,0 +1,14 @@
+name: AI Code Review
+on:
+ pull_request_target:
+ types: [labeled]
+
+jobs:
+ ai-review:
+ runs-on: fedora
+ if: forgejo.event.label.name == 'ai-review-please'
+ uses: quality/workflows/.forgejo/workflows/ai-review.yml@main
+ with:
+ pr: ${{ forgejo.event.pull_request.number }}
+ secrets:
+ GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/resultsdb_api-2.1.5/.forgejo/workflows/ci.yml
new/resultsdb_api-2.1.6/.forgejo/workflows/ci.yml
--- old/resultsdb_api-2.1.5/.forgejo/workflows/ci.yml 1970-01-01
01:00:00.000000000 +0100
+++ new/resultsdb_api-2.1.6/.forgejo/workflows/ci.yml 2026-02-18
19:20:40.000000000 +0100
@@ -0,0 +1,20 @@
+name: CI via Tox
+on:
+ pull_request:
+ types: [opened, synchronize]
+
+jobs:
+ tox:
+ runs-on: fedora
+ container:
+ image: quay.io/fedora/fedora:latest
+ steps:
+ - name: Install required packages
+ run: dnf -y install nodejs tox git
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8
+ with:
+ fetch-depth: 0
+ - name: Install Python interpreters
+ run: for py in 3.6 3.10 3.11 3.12 3.13 3.14; do dnf -y install
python$py; done
+ - name: Test with tox
+ run: tox
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/resultsdb_api-2.1.5/Makefile
new/resultsdb_api-2.1.6/Makefile
--- old/resultsdb_api-2.1.5/Makefile 2021-11-14 10:41:38.000000000 +0100
+++ new/resultsdb_api-2.1.6/Makefile 2026-02-18 18:17:49.000000000 +0100
@@ -17,12 +17,10 @@
#
# general variables
-VENV=test_env
SRC=resultsdb_api
# Variables used for packaging
SPECFILE=python-$(SRC).spec
-BASEARCH:=$(shell uname -i)
DIST:=$(shell rpm --eval '%{dist}')
VERSION:=$(shell rpmspec -q --queryformat="%{VERSION}\n" $(SPECFILE) | uniq)
RELEASE:=$(subst $(DIST),,$(shell rpmspec -q --queryformat="%{RELEASE}\n"
$(SPECFILE) | uniq))
@@ -32,17 +30,6 @@
TARGETDIST:=fc$(TARGETVER)
BUILDTARGET:=fedora-$(TARGETVER)-x86_64
-.PHONY: test
-test: $(VENV)
- sh -c "set -e; . $(VENV)/bin/activate; \
- TEST='true' py.test --cov-report=term-missing --cov $(SRC)
testing/; \
- deactivate"
-
-.PHONY: test-ci
-test-ci: $(VENV)
- sh -c "set -e; . $(VENV)/bin/activate; \
- TEST='true' py.test --cov-report=xml --cov $(SRC) testing/;
deactivate"
-
.PHONY: pylint
pylint:
pylint -f parseable $(SRC) | tee pylint.out
@@ -51,9 +38,6 @@
pep8:
pep8 $(SRC)/*.py $(SRC)/*/*.py | tee pep8.out
-.PHONY: ci
-ci: test-ci pylint pep8
-
.PHONY: docs
docs:
sphinx-build -b html -d docs/_build/doctrees docs/source
docs/_build/html
@@ -90,16 +74,3 @@
.PHONY: nvr
nvr:
@echo $(NVR)
-
-.PHONY: cleanvenv
-cleanvenv:
- rm -rf $(VENV)
-
-.PHONY: virtualenv
-virtualenv: $(VENV)
-
-.PHONY: $(VENV)
-$(VENV):
- virtualenv $(VENV)
- sh -c "set -e; . $(VENV)/bin/activate; pip install -r install.requires
-r tests.requires; \
- deactivate"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/resultsdb_api-2.1.5/PKG-INFO
new/resultsdb_api-2.1.6/PKG-INFO
--- old/resultsdb_api-2.1.5/PKG-INFO 2021-11-14 10:46:06.048796400 +0100
+++ new/resultsdb_api-2.1.6/PKG-INFO 2026-03-26 18:24:11.362948000 +0100
@@ -1,12 +1,10 @@
-Metadata-Version: 2.1
+Metadata-Version: 2.4
Name: resultsdb_api
-Version: 2.1.5
+Version: 2.1.6
Summary: Library for simplifying the communication with ResultsDB
Home-page: https://pagure.io/taskotron/resultsdb_api
Author: Josef Skladanka
Author-email: [email protected]
-License: UNKNOWN
-Platform: UNKNOWN
Classifier: Development Status :: 2 - Pre-Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: GNU General Public License v2 or later
(GPLv2+)
@@ -19,6 +17,12 @@
Classifier: Topic :: Scientific/Engineering :: Interface Engine/Protocol
Translator
Classifier: Topic :: Software Development :: Libraries :: Python Modules
License-File: LICENSE
-
-UNKNOWN
-
+Requires-Dist: requests>=2.2.1
+Requires-Dist: simplejson>=3.5.3
+Dynamic: author
+Dynamic: author-email
+Dynamic: classifier
+Dynamic: home-page
+Dynamic: license-file
+Dynamic: requires-dist
+Dynamic: summary
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/resultsdb_api-2.1.5/ci.requires
new/resultsdb_api-2.1.6/ci.requires
--- old/resultsdb_api-2.1.5/ci.requires 1970-01-01 01:00:00.000000000 +0100
+++ new/resultsdb_api-2.1.6/ci.requires 2026-02-18 18:17:49.000000000 +0100
@@ -0,0 +1,5 @@
+black
+coverage[toml]
+diff-cover
+toml
+pylint
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/resultsdb_api-2.1.5/pyproject.toml
new/resultsdb_api-2.1.6/pyproject.toml
--- old/resultsdb_api-2.1.5/pyproject.toml 1970-01-01 01:00:00.000000000
+0100
+++ new/resultsdb_api-2.1.6/pyproject.toml 2026-02-18 18:17:49.000000000
+0100
@@ -0,0 +1,17 @@
+[build-system]
+requires = ["setuptools>=40.6.0", "setuptools-scm", "wheel"]
+build-backend = "setuptools.build_meta"
+
+[tool.coverage.run]
+parallel = true
+branch = true
+source = ["resultsdb_api"]
+
+[tool.coverage.paths]
+source = [".", ".tox/*/site-packages"]
+
+[tool.coverage.report]
+show_missing = true
+
+[tool.black]
+line-length = 99
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/resultsdb_api-2.1.5/pytest.ini
new/resultsdb_api-2.1.6/pytest.ini
--- old/resultsdb_api-2.1.5/pytest.ini 2018-03-27 17:28:16.000000000 +0200
+++ new/resultsdb_api-2.1.6/pytest.ini 1970-01-01 01:00:00.000000000 +0100
@@ -1,4 +0,0 @@
-[pytest]
-minversion = 2.0
-python_functions=test should
-python_files=test_* functest_*
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/resultsdb_api-2.1.5/python-resultsdb_api.spec
new/resultsdb_api-2.1.6/python-resultsdb_api.spec
--- old/resultsdb_api-2.1.5/python-resultsdb_api.spec 2021-11-14
10:41:38.000000000 +0100
+++ new/resultsdb_api-2.1.6/python-resultsdb_api.spec 2026-02-18
18:17:49.000000000 +0100
@@ -8,6 +8,8 @@
URL: https://pagure.io/taskotron/resultsdb_api
Source0:
https://qa.fedoraproject.org/releases/resultsdb_api/resultsdb_api-%{version}.tar.gz
+BuildRequires: python3-devel
+
BuildArch: noarch
%description
@@ -15,38 +17,32 @@
%package -n python3-resultsdb_api
Summary: %summary
-Requires: python3-simplejson
-Requires: python3-requests
-
-BuildRequires: python3-devel
-BuildRequires: python3-pytest-cov
-BuildRequires: python3-setuptools
-BuildRequires: python3-simplejson
-BuildRequires: python3-pytest
-BuildRequires: python3-requests
-BuildRequires: python3-virtualenv
%description -n python3-resultsdb_api
Python3 interface to resultsdb.
%prep
%autosetup -p1 -n resultsdb_api-%{version}
+# setuptools-scm is needed to build the source distribution, but not
+# for packaging, which *starts* from the source distribution
+sed -i -e 's., "setuptools-scm"..g' pyproject.toml
+
+%generate_buildrequires
+%pyproject_buildrequires -t
%build
-%py3_build
+%pyproject_wheel
%install
-%py3_install
+%pyproject_install
+%pyproject_save_files resultsdb_api
%check
-%pytest
+%tox
-%files -n python3-resultsdb_api
+%files -n python3-resultsdb_api -f %{pyproject_files}
%doc README.md
%license LICENSE
-%{python3_sitelib}/resultsdb_api.*
-%{python3_sitelib}/__pycache__/resultsdb_api.*
-%{python3_sitelib}/resultsdb_api-%{version}*.egg-info
%changelog
* Sun Nov 14 2021 Frantisek Zatloukal <[email protected]> - 2.1.5-1
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/resultsdb_api-2.1.5/release.sh
new/resultsdb_api-2.1.6/release.sh
--- old/resultsdb_api-2.1.5/release.sh 1970-01-01 01:00:00.000000000 +0100
+++ new/resultsdb_api-2.1.6/release.sh 2026-02-26 22:29:11.000000000 +0100
@@ -0,0 +1,26 @@
+#!/bin/bash
+
+baddeps=""
+# check deps
+python3 -m build.__init__ || baddeps="python3-build"
+rpm -q twine || baddeps="${baddeps} twine"
+if [ -n "${baddeps}" ]; then
+ echo "${baddeps} must be installed!"
+ exit 1
+fi
+
+if [ "$#" != "1" ]; then
+ echo "Must pass release version!"
+ exit 1
+fi
+
+version=$1
+name=resultsdb_api
+sed -i -e "s,version=\".*\",version=\"${version}\", g" setup.py
+git add setup.py
+git commit -s -m "Release ${version}"
+git push
+git tag -a -m "Release ${version}" ${version}
+git push origin ${version}
+python3 -m build .
+twine upload -r pypi dist/${name}-${version}*
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/resultsdb_api-2.1.5/resultsdb_api.egg-info/PKG-INFO
new/resultsdb_api-2.1.6/resultsdb_api.egg-info/PKG-INFO
--- old/resultsdb_api-2.1.5/resultsdb_api.egg-info/PKG-INFO 2021-11-14
10:46:05.000000000 +0100
+++ new/resultsdb_api-2.1.6/resultsdb_api.egg-info/PKG-INFO 2026-03-26
18:24:11.000000000 +0100
@@ -1,12 +1,10 @@
-Metadata-Version: 2.1
-Name: resultsdb-api
-Version: 2.1.5
+Metadata-Version: 2.4
+Name: resultsdb_api
+Version: 2.1.6
Summary: Library for simplifying the communication with ResultsDB
Home-page: https://pagure.io/taskotron/resultsdb_api
Author: Josef Skladanka
Author-email: [email protected]
-License: UNKNOWN
-Platform: UNKNOWN
Classifier: Development Status :: 2 - Pre-Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: GNU General Public License v2 or later
(GPLv2+)
@@ -19,6 +17,12 @@
Classifier: Topic :: Scientific/Engineering :: Interface Engine/Protocol
Translator
Classifier: Topic :: Software Development :: Libraries :: Python Modules
License-File: LICENSE
-
-UNKNOWN
-
+Requires-Dist: requests>=2.2.1
+Requires-Dist: simplejson>=3.5.3
+Dynamic: author
+Dynamic: author-email
+Dynamic: classifier
+Dynamic: home-page
+Dynamic: license-file
+Dynamic: requires-dist
+Dynamic: summary
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/resultsdb_api-2.1.5/resultsdb_api.egg-info/SOURCES.txt
new/resultsdb_api-2.1.6/resultsdb_api.egg-info/SOURCES.txt
--- old/resultsdb_api-2.1.5/resultsdb_api.egg-info/SOURCES.txt 2021-11-14
10:46:05.000000000 +0100
+++ new/resultsdb_api-2.1.6/resultsdb_api.egg-info/SOURCES.txt 2026-03-26
18:24:11.000000000 +0100
@@ -1,23 +1,24 @@
-.arcconfig
-.arclint
.gitignore
LICENSE
MANIFEST.in
Makefile
README.md
+ci.requires
install.requires
-pytest.ini
+pyproject.toml
python-resultsdb_api.spec
+release.sh
resultsdb_api.py
setup.py
tests.requires
tokengetter.py
tox.ini
+.forgejo/workflows/ai-review.yml
+.forgejo/workflows/ci.yml
resultsdb_api.egg-info/PKG-INFO
resultsdb_api.egg-info/SOURCES.txt
resultsdb_api.egg-info/dependency_links.txt
resultsdb_api.egg-info/requires.txt
resultsdb_api.egg-info/top_level.txt
testing/__init__.py
-testing/conftest.py
testing/test_api.py
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/resultsdb_api-2.1.5/resultsdb_api.py
new/resultsdb_api-2.1.6/resultsdb_api.py
--- old/resultsdb_api-2.1.5/resultsdb_api.py 2021-11-14 10:41:38.000000000
+0100
+++ new/resultsdb_api-2.1.6/resultsdb_api.py 2026-02-18 18:17:49.000000000
+0100
@@ -16,6 +16,9 @@
#
# Author: Josef Skladanka <[email protected]>
+# these are OK because we still kinda want to work on older Pythons
+# pylint:
disable=consider-using-f-string,super-with-arguments,raise-missing-from
+
import requests
from requests.adapters import HTTPAdapter
from requests.packages.urllib3.util.retry import Retry
@@ -24,9 +27,10 @@
import simplejson
import logging
-logger = logging.getLogger('resultsdb_api')
+logger = logging.getLogger("resultsdb_api")
logger.addHandler(logging.NullHandler())
+
def _fparams(expand_kwargs=True):
"""Gets the parameters of the function, from which _fparams is called
and returns the list of params, minus `self`"""
@@ -36,7 +40,7 @@
params = {}
for key in args:
- if key == 'self':
+ if key == "self":
continue
params[key] = values[key]
@@ -51,9 +55,9 @@
class ResultsDBapiException(Exception):
-
- def __init__(self, message='', response=None):
- ''':param response: :class:`requests.Response` object'''
+ def __init__(self, message="", response=None):
+ """:param response: :class:`requests.Response` object"""
+ super(ResultsDBapiException, self).__init__(message)
self.message = message
self.response = response
@@ -67,19 +71,20 @@
return r
try:
- logger.warn('Received HTTP failure status code %s for request: %s',
- r.status_code, r.url)
+ logger.warning(
+ "Received HTTP failure status code %s for request: %s",
r.status_code, r.url
+ )
+ raise ResultsDBapiException("%s (HTTP %s)" % (r.json()["message"],
r.status_code), r)
+ except simplejson.JSONDecodeError as err:
+ logger.debug("Could not parse JSON data: %s\n%s", err, r.text)
+ raise ResultsDBapiException("(HTTP %s)" % r.status_code, r)
+ except KeyError as err:
+ logger.debug("JSON data in unexpected format: %s\n%s", err, r.text)
raise ResultsDBapiException(
- '%s (HTTP %s)' % (r.json()['message'], r.status_code), r)
- except simplejson.JSONDecodeError as e:
- logger.debug('Could not parse JSON data: %s\n%s', e, r.text)
- raise ResultsDBapiException(
- '(HTTP %s)' % r.status_code, r)
- except KeyError:
- logger.debug('JSON data in unexpected format: %s\n%s', e, r.text)
- raise ResultsDBapiException('Unexpected JSON data (HTTP %s): %s' %
(r.status_code, r.json()), r)
+ "Unexpected JSON data (HTTP %s): %s" % (r.status_code,
r.json()), r
+ )
- raise ResultsDBapiException('Unknown Error', r)
+ raise ResultsDBapiException("Unknown Error", r)
def get(self, *args, **kwargs):
try:
@@ -89,7 +94,7 @@
message = e.message
except AttributeError:
message = str(e)
- raise ResultsDBapiException('Maximum number of retries exceeded:
%s' % message, None)
+ raise ResultsDBapiException("Maximum number of retries exceeded:
%s" % message, None)
return self.__resultsdb_raise_on_error(r)
def post(self, *args, **kwargs):
@@ -100,7 +105,7 @@
message = e.message
except AttributeError:
message = str(e)
- raise ResultsDBapiException('Maximum number of retries exceeded:
%s' % message, None)
+ raise ResultsDBapiException("Maximum number of retries exceeded:
%s" % message, None)
return self.__resultsdb_raise_on_error(r)
@@ -119,22 +124,23 @@
class ResultsDBapi(object):
-
- def __init__(self, api_url, auth_token=None, max_retries=3,
backoff_factor=1.0, request_auth=None):
+ def __init__(
+ self, api_url, auth_token=None, max_retries=3, backoff_factor=1.0,
request_auth=None
+ ):
# remove trailing slash(es), so we don't generate
# urls with a double slash which breaks werkzeug
# https://github.com/mitsuhiko/werkzeug/issues/491
- self.url = api_url.rstrip('/')
+ self.url = api_url.rstrip("/")
self.auth_token = auth_token
self.request_auth = request_auth
allowed_methods = list(Retry.DEFAULT_ALLOWED_METHODS) + ["POST"]
self._retry = Retry(
- total=max_retries,
- backoff_factor=backoff_factor,
- status_forcelist=(500, 502, 503, 504),
- allowed_methods=allowed_methods
- )
+ total=max_retries,
+ backoff_factor=backoff_factor,
+ status_forcelist=(500, 502, 503, 504),
+ allowed_methods=allowed_methods,
+ )
self._adapter = HTTPAdapter(max_retries=self._retry)
self.session = _ResultsDBSession()
self.session.mount("http://", self._adapter)
@@ -145,31 +151,30 @@
for key, value in params_all.items():
if value is None:
continue
- if key == 'raw_params':
+ if key == "raw_params":
continue
# if a param's name ends with _like, we treat it as if :like
filter should be applied
# for the rare case, where it really is supposed to be the name,
user should provide
# it in the 'raw_params' dict
- if key.endswith('_like'):
- key = "%s:like" % key[:-len('_like')]
+ if key.endswith("_like"):
+ key = "%s:like" % key[: -len("_like")]
if type(value) in (list, tuple):
- params[key] = ','.join([str(v) for v in value])
+ params[key] = ",".join([str(v) for v in value])
else:
params[key] = str(value)
- if 'raw_params' in params_all.keys() and params_all['raw_params']:
- raw_params = {
- key: str(value) for key, value in
params_all['raw_params'].items()}
+ if "raw_params" in params_all.keys() and params_all["raw_params"]:
+ raw_params = {key: str(value) for key, value in
params_all["raw_params"].items()}
params.update(raw_params)
return params
def create_group(self, uuid=None, ref_url=None, description=None):
url = "%s/groups" % self.url
- headers = {'Content-type': 'application/json', 'Accept': 'text/plain'}
+ headers = {"Content-type": "application/json", "Accept": "text/plain"}
data = _fparams()
- data['_auth_token'] = self.auth_token
+ data["_auth_token"] = self.auth_token
r = self.session.post(url, data=json.dumps(data), headers=headers,
auth=self.request_auth)
return r.json()
@@ -177,17 +182,17 @@
def update_group(self, uuid, ref_url=None, description=None):
data = {}
if ref_url is not None:
- data['ref_url'] = ref_url
+ data["ref_url"] = ref_url
if description is not None:
- data['description'] = description
+ data["description"] = description
if not data:
return self.get_group(uuid)
- data['uuid'] = uuid
- data['_auth_token'] = self.auth_token
+ data["uuid"] = uuid
+ data["_auth_token"] = self.auth_token
url = "%s/groups" % self.url
- headers = {'Content-type': 'application/json', 'Accept': 'text/plain'}
+ headers = {"Content-type": "application/json", "Accept": "text/plain"}
r = self.session.post(url, data=json.dumps(data), headers=headers,
auth=self.request_auth)
return r.json()
@@ -198,7 +203,15 @@
return r.json()
- def get_groups(self, page=None, limit=None, description=None,
description_like=None, uuid=None):
+ def get_groups(
+ # pylint: disable=unused-argument
+ self,
+ page=None,
+ limit=None,
+ description=None,
+ description_like=None,
+ uuid=None,
+ ):
url = "%s/groups" % self.url
r = self.session.get(url, params=self.__prepare_params(_fparams()))
@@ -207,8 +220,8 @@
def create_result(self, outcome, testcase, groups=None, note=None,
ref_url=None, **data):
url = "%s/results" % self.url
data = _fparams(expand_kwargs=False)
- data['_auth_token'] = self.auth_token
- headers = {'Content-type': 'application/json', 'Accept': 'text/plain'}
+ data["_auth_token"] = self.auth_token
+ headers = {"Content-type": "application/json", "Accept": "text/plain"}
r = self.session.post(url, data=json.dumps(data), headers=headers,
auth=self.request_auth)
return r.json()
@@ -219,7 +232,19 @@
return r.json()
- def get_results(self, page=None, limit=None, since=None, outcome=None,
groups=None, testcases=None, testcases_like=None, raw_params=None, **kwargs):
+ def get_results(
+ # pylint: disable=unused-argument
+ self,
+ page=None,
+ limit=None,
+ since=None,
+ outcome=None,
+ groups=None,
+ testcases=None,
+ testcases_like=None,
+ raw_params=None,
+ **kwargs
+ ):
url = "%s/results" % self.url
r = self.session.get(url, params=self.__prepare_params(_fparams()),
auth=self.request_auth)
@@ -228,8 +253,8 @@
def create_testcase(self, name, ref_url=None):
url = "%s/testcases" % self.url
data = _fparams()
- data['_auth_token'] = self.auth_token
- headers = {'Content-type': 'application/json', 'Accept': 'text/plain'}
+ data["_auth_token"] = self.auth_token
+ headers = {"Content-type": "application/json", "Accept": "text/plain"}
r = self.session.post(url, data=json.dumps(data), headers=headers,
auth=self.request_auth)
return r.json()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/resultsdb_api-2.1.5/setup.py
new/resultsdb_api-2.1.6/setup.py
--- old/resultsdb_api-2.1.5/setup.py 2021-11-14 10:41:38.000000000 +0100
+++ new/resultsdb_api-2.1.6/setup.py 2026-03-26 18:24:05.000000000 +0100
@@ -19,27 +19,26 @@
from setuptools import setup
-setup( name = 'resultsdb_api',
- py_modules = ['resultsdb_api'],
- version = '2.1.5',
- description = 'Library for simplifying the communication with
ResultsDB',
- author = 'Josef Skladanka',
- author_email = '[email protected]',
- url = "https://pagure.io/taskotron/resultsdb_api",
- install_requires = open('install.requires').read().splitlines(),
- classifiers = [
- "Development Status :: 2 - Pre-Alpha",
- "Intended Audience :: Developers",
- "License :: OSI Approved :: GNU General Public License v2 or later
(GPLv2+)",
- "Operating System :: OS Independent",
- "Programming Language :: Python",
- "Programming Language :: Python :: 2.6",
- "Programming Language :: Python :: 2.7",
- "Programming Language :: Python :: 3",
- "Topic :: Internet",
- "Topic :: Scientific/Engineering :: Interface Engine/Protocol
Translator",
- "Topic :: Software Development :: Libraries :: Python Modules",
- ],
-
- )
-
+setup(
+ name="resultsdb_api",
+ py_modules=["resultsdb_api"],
+ version="2.1.6",
+ description="Library for simplifying the communication with ResultsDB",
+ author="Josef Skladanka",
+ author_email="[email protected]",
+ url="https://pagure.io/taskotron/resultsdb_api",
+ install_requires=open("install.requires").read().splitlines(),
+ classifiers=[
+ "Development Status :: 2 - Pre-Alpha",
+ "Intended Audience :: Developers",
+ "License :: OSI Approved :: GNU General Public License v2 or later
(GPLv2+)",
+ "Operating System :: OS Independent",
+ "Programming Language :: Python",
+ "Programming Language :: Python :: 2.6",
+ "Programming Language :: Python :: 2.7",
+ "Programming Language :: Python :: 3",
+ "Topic :: Internet",
+ "Topic :: Scientific/Engineering :: Interface Engine/Protocol
Translator",
+ "Topic :: Software Development :: Libraries :: Python Modules",
+ ],
+)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/resultsdb_api-2.1.5/testing/conftest.py
new/resultsdb_api-2.1.6/testing/conftest.py
--- old/resultsdb_api-2.1.5/testing/conftest.py 2018-03-27 17:28:16.000000000
+0200
+++ new/resultsdb_api-2.1.6/testing/conftest.py 1970-01-01 01:00:00.000000000
+0100
@@ -1,27 +0,0 @@
-def pytest_addoption(parser):
- """
- Add an option to the py.test parser to detect when the functional tests
- should be detected and run
- """
-
- parser.addoption('-F', '--functional', action='store_true', default=False,
- help='Add functional tests')
-
-
-def pytest_ignore_collect(path, config):
- """Prevents collection of any files named functest* to speed up non
- integration tests"""
- if path.fnmatch('*functest*'):
- try:
- is_functional = config.getvalue('functional')
- except KeyError:
- return True
-
- return not is_functional
-
-
-def pytest_configure(config):
- """Called after command line options have been parsed and all plugins and
- initial conftest files been loaded."""
-
- pass
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/resultsdb_api-2.1.5/testing/test_api.py
new/resultsdb_api-2.1.6/testing/test_api.py
--- old/resultsdb_api-2.1.5/testing/test_api.py 2021-11-14 10:41:38.000000000
+0100
+++ new/resultsdb_api-2.1.6/testing/test_api.py 2026-02-18 18:17:49.000000000
+0100
@@ -17,16 +17,29 @@
# Authors:
# Martin Krizek <[email protected]>
+# these are all kinda inappropriate for pytest patterns
+# pylint: disable=no-init, protected-access, unused-argument,
too-many-instance-attributes
+# pylint: disable=too-few-public-methods, too-many-public-methods,
too-many-lines
+# docstrings are not really necessary for most test methods
+# pylint: disable=missing-function-docstring, missing-class-docstring
+# this is OK for xunit
+# pylint: disable=attribute-defined-outside-init
+# this is OK because we still kinda want to work on older Pythons
+# pylint: disable=consider-using-f-string
+
+
import resultsdb_api
import json
import pytest
import requests
+import requests.exceptions
+import responses
from unittest.mock import patch
-class TestAPI():
+class TestAPI:
def setup_method(self, method):
self.rdb_url = "http://0.0.0.0:5000/api/v1.0"
self.ref_url = "http://example.com/someref"
@@ -34,6 +47,7 @@
self.ref_testcase_name = "testcase"
self.ref_testcase_url = "http://fedoraqa.fedoraproject.org/testcase"
self.ref_outcome = "PASSED"
+ self.ref_outcome_list = ["PASSED", "FAILED"]
self.ref_content_type = "application/json"
self.ref_accept = "text/plain"
self.ref_job_id = 1
@@ -41,13 +55,13 @@
self.helper = resultsdb_api.ResultsDBapi(self.rdb_url)
- @patch('requests.Session.send')
+ @patch("requests.Session.send")
def test_create_testcase(self, mocksend):
auth = resultsdb_api.ResultsDBAuth.basic_auth("user", "pass")
authhelper = resultsdb_api.ResultsDBapi(self.rdb_url,
request_auth=auth)
# test twice to test authentication, once without, once with
- for (helper, authed) in ((self.helper, False), (authhelper, True)):
+ for helper, authed in ((self.helper, False), (authhelper, True)):
mocksend.reset_mock()
helper.create_testcase(self.ref_testcase_name,
self.ref_testcase_url)
mocksend.assert_called_once()
@@ -55,16 +69,16 @@
data = json.loads(request.body)
assert request.url == "%s/testcases" % self.rdb_url
- assert request.headers['Content-type'] == self.ref_content_type
- assert request.headers['Accept'] == self.ref_accept
+ assert request.headers["Content-type"] == self.ref_content_type
+ assert request.headers["Accept"] == self.ref_accept
if authed:
- assert request.headers['Authorization'] == "Basic dXNlcjpwYXNz"
+ assert request.headers["Authorization"] == "Basic dXNlcjpwYXNz"
else:
- assert 'Authorization' not in request.headers
- assert data['ref_url'] == self.ref_testcase_url
- assert data['name'] == self.ref_testcase_name
+ assert "Authorization" not in request.headers
+ assert data["ref_url"] == self.ref_testcase_url
+ assert data["name"] == self.ref_testcase_name
- @patch('requests.Session.send')
+ @patch("requests.Session.send")
def test_update_testcase(self, mocksend):
self.helper.update_testcase(self.ref_testcase_name,
self.ref_testcase_url)
@@ -73,12 +87,25 @@
data = json.loads(request.body)
assert request.url == "%s/testcases" % (self.rdb_url)
- assert request.headers['Content-type'] == self.ref_content_type
- assert request.headers['Accept'] == self.ref_accept
- assert data['ref_url'] == self.ref_testcase_url
- assert data['name'] == self.ref_testcase_name
+ assert request.headers["Content-type"] == self.ref_content_type
+ assert request.headers["Accept"] == self.ref_accept
+ assert data["ref_url"] == self.ref_testcase_url
+ assert data["name"] == self.ref_testcase_name
+
+ @patch("requests.Session.send")
+ def test_update_testcase_no_url(self, mocksend):
+ """
+ Test call to update_testcase with no URL (which should turn it
+ into a call to get_testcase).
+ """
+ self.helper.update_testcase(self.ref_testcase_name)
+
+ mocksend.assert_called_once()
+ request = mocksend.mock_calls[0][1][0]
- @patch('requests.Session.send')
+ assert request.url == "%s/testcases/%s" % (self.rdb_url,
self.ref_testcase_name)
+
+ @patch("requests.Session.send")
def test_get_testcase(self, mocksend):
self.helper.get_testcase(self.ref_testcase_name)
@@ -87,7 +114,7 @@
assert request.url == "%s/testcases/%s" % (self.rdb_url,
self.ref_testcase_name)
- @patch('requests.Session.send')
+ @patch("requests.Session.send")
def test_get_testcases(self, mocksend):
self.helper.get_testcases()
@@ -96,7 +123,7 @@
assert request.url == "%s/testcases" % self.rdb_url
- @patch('requests.Session.send')
+ @patch("requests.Session.send")
def test_create_result(self, mocksend):
self.helper.create_result(self.ref_outcome, self.ref_testcase_name)
@@ -105,12 +132,12 @@
data = json.loads(request.body)
assert request.url == "%s/results" % self.rdb_url
- assert request.headers['Content-type'] == self.ref_content_type
- assert request.headers['Accept'] == self.ref_accept
- assert data['testcase'] == self.ref_testcase_name
- assert data['outcome'] == self.ref_outcome
+ assert request.headers["Content-type"] == self.ref_content_type
+ assert request.headers["Accept"] == self.ref_accept
+ assert data["testcase"] == self.ref_testcase_name
+ assert data["outcome"] == self.ref_outcome
- @patch('requests.Session.send')
+ @patch("requests.Session.send")
def test_get_result(self, mocksend):
self.helper.get_result(self.ref_result_id)
@@ -121,9 +148,10 @@
def test_get_result_invalid(self):
with pytest.raises(TypeError):
+ # pylint: disable=no-value-for-parameter
self.helper.get_result()
- @patch('requests.Session.send')
+ @patch("requests.Session.send")
def test_get_results(self, mocksend):
self.helper.get_results()
@@ -132,14 +160,156 @@
assert request.url == "%s/results" % self.rdb_url
- @patch('requests.Session.request')
+ @patch("requests.Session.request")
def test_get_results_params(self, mockreq):
- self.helper.get_results(testcase_name=self.ref_testcase_name,
job_id=self.ref_job_id)
+ self.helper.get_results(
+ testcase_name_like=self.ref_testcase_name,
+ job_id=self.ref_job_id,
+ outcome=self.ref_outcome_list,
+ )
mockreq.assert_called_once()
rdb_url = mockreq.mock_calls[0][1][1]
- params = mockreq.mock_calls[0][2]['params']
+ params = mockreq.mock_calls[0][2]["params"]
assert rdb_url == "%s/results" % self.rdb_url
- assert params['testcase_name'] == self.ref_testcase_name
- assert params['job_id'] == str(self.ref_job_id)
+ assert params["testcase_name:like"] == self.ref_testcase_name
+ assert params["job_id"] == str(self.ref_job_id)
+ assert params["outcome"] == ",".join(self.ref_outcome_list)
+
+ @patch("requests.Session.request")
+ def test_get_results_raw_params(self, mockreq):
+ params = {"testcase_name": self.ref_testcase_name, "job_id":
self.ref_job_id}
+ self.helper.get_results(raw_params=params)
+
+ mockreq.assert_called_once()
+ rdb_url = mockreq.mock_calls[0][1][1]
+ params = mockreq.mock_calls[0][2]["params"]
+
+ assert rdb_url == "%s/results" % self.rdb_url
+ assert params["testcase_name"] == self.ref_testcase_name
+ assert params["job_id"] == str(self.ref_job_id)
+
+ @patch("requests.Session.send")
+ def test_create_group(self, mocksend):
+ ref_desc = "Example description"
+ self.helper.create_group(ref_url=self.ref_url, description=ref_desc)
+
+ mocksend.assert_called_once()
+ request = mocksend.mock_calls[0][1][0]
+ data = json.loads(request.body)
+
+ assert request.url == "%s/groups" % self.rdb_url
+ assert data["ref_url"] == self.ref_url
+ assert data["description"] == ref_desc
+
+ @patch("requests.Session.send")
+ def test_update_group(self, mocksend):
+ ref_uuid = "d2a14172-4bdf-11ec-88a1-9cb6d0d0d1bd"
+ ref_desc = "Example description"
+ self.helper.update_group(uuid=ref_uuid, ref_url=self.ref_url,
description=ref_desc)
+
+ mocksend.assert_called_once()
+ request = mocksend.mock_calls[0][1][0]
+ data = json.loads(request.body)
+
+ assert request.url == "%s/groups" % self.rdb_url
+ assert data["ref_url"] == self.ref_url
+ assert data["description"] == ref_desc
+ assert data["uuid"] == ref_uuid
+
+ @patch("requests.Session.send")
+ def test_update_group_no_update(self, mocksend):
+ """
+ Test a call to update_group that only specifies the UUID
+ (which should turn it into get_group).
+ """
+ ref_uuid = "d2a14172-4bdf-11ec-88a1-9cb6d0d0d1bd"
+ self.helper.update_group(uuid=ref_uuid)
+
+ mocksend.assert_called_once()
+ request = mocksend.mock_calls[0][1][0]
+
+ assert request.url == "%s/groups/%s" % (self.rdb_url, ref_uuid)
+
+ @patch("requests.Session.send")
+ def test_get_group(self, mocksend):
+ ref_uuid = "d2a14172-4bdf-11ec-88a1-9cb6d0d0d1bd"
+ self.helper.get_group(ref_uuid)
+
+ mocksend.assert_called_once()
+ request = mocksend.mock_calls[0][1][0]
+
+ assert request.url == "%s/groups/%s" % (self.rdb_url, ref_uuid)
+
+ @patch("requests.Session.request")
+ def test_get_groups(self, mockreq):
+ ref_limit = 30
+ ref_desc = "Example description"
+ self.helper.get_groups(limit=ref_limit, description_like=ref_desc)
+
+ mockreq.assert_called_once()
+ rdb_url = mockreq.mock_calls[0][1][1]
+ params = mockreq.mock_calls[0][2]["params"]
+
+ assert rdb_url == "%s/groups" % (self.rdb_url)
+ assert params["limit"] == str(ref_limit)
+ assert params["description:like"] == ref_desc
+
+ @patch("requests.Session.send")
+ def test_retry_errors(self, mocksend):
+ """Test correct exception is raised on RetryError."""
+ mocksend.side_effect = requests.exceptions.RetryError("oh no!")
+ with pytest.raises(resultsdb_api.ResultsDBapiException) as err:
+ self.helper.get_results()
+ assert err.message == "Maximum number of retries exceeded: oh no!"
+ with pytest.raises(resultsdb_api.ResultsDBapiException) as err:
+ self.helper.update_testcase(self.ref_testcase_name,
self.ref_testcase_url)
+ assert err.message == "Maximum number of retries exceeded: oh no!"
+
+ @responses.activate
+ def test_http_error_json(self):
+ """
+ Test correct exception is raised on HTTP error response
+ with valid JSON.
+ """
+ responses.add(
+ responses.GET,
+ "http://0.0.0.0:5000/api/v1.0/results",
+ json={"message": "Not found"},
+ status=404,
+ )
+ with pytest.raises(resultsdb_api.ResultsDBapiException) as err:
+ self.helper.get_results()
+ exc = err.value
+ assert exc.message == "Not found (HTTP 404)"
+ assert str(exc) == "'Not found (HTTP 404)'"
+
+ @responses.activate
+ def test_http_error_no_json(self):
+ """
+ Test correct exception is raised on HTTP error response
+ without valid JSON.
+ """
+ responses.add(responses.GET, "http://0.0.0.0:5000/api/v1.0/results",
json=None, status=404)
+ with pytest.raises(resultsdb_api.ResultsDBapiException) as err:
+ self.helper.get_results()
+ exc = err.value
+ assert exc.message == "(HTTP 404)"
+
+ @responses.activate
+ def test_http_error_unexpected_json(self):
+ """
+ Test correct exception is raised on HTTP error response
+ with unexpected JSON.
+ """
+ responses.add(
+ responses.GET,
+ "http://0.0.0.0:5000/api/v1.0/results",
+ json={"error": "Error!"},
+ status=404,
+ )
+ with pytest.raises(resultsdb_api.ResultsDBapiException) as err:
+ self.helper.get_results()
+ exc = err.value
+ assert exc.message == "Unexpected JSON data (HTTP 404): {'error':
'Error!'}"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/resultsdb_api-2.1.5/tests.requires
new/resultsdb_api-2.1.6/tests.requires
--- old/resultsdb_api-2.1.5/tests.requires 2021-11-14 10:41:38.000000000
+0100
+++ new/resultsdb_api-2.1.6/tests.requires 2026-02-18 18:17:49.000000000
+0100
@@ -1,2 +1,3 @@
pytest >= 2.4.2
pytest-cov >= 1.6
+responses
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/resultsdb_api-2.1.5/tokengetter.py
new/resultsdb_api-2.1.6/tokengetter.py
--- old/resultsdb_api-2.1.5/tokengetter.py 2018-03-28 15:14:06.000000000
+0200
+++ new/resultsdb_api-2.1.6/tokengetter.py 2026-02-18 18:17:49.000000000
+0100
@@ -3,21 +3,22 @@
from openidc_client import OpenIDCClient
import sys
-c = OpenIDCClient(app_identifier='resultsdb',
- id_provider='https://iddev.fedorainfracloud.org/openidc/',
- id_provider_mapping={'Token': 'Token',
- 'Authorization': 'Authorization'},
- client_id='python-fedora',
- client_secret='notsecret')
+c = OpenIDCClient(
+ app_identifier="resultsdb",
+ id_provider="https://iddev.fedorainfracloud.org/openidc/",
+ id_provider_mapping={"Token": "Token", "Authorization": "Authorization"},
+ client_id="python-fedora",
+ client_secret="notsecret",
+)
# IDEALLY, the below code should work... but I messed up
# c = OpenIDCBaseClient('resultsdb', 'https://iddev.fedorainfracloud.org/',
# 'python-fedora')
-token = c.get_token(['https://pagure.io/taskotron/resultsdb/access'])
+token = c.get_token(["https://pagure.io/taskotron/resultsdb/access"])
renew = False
try:
- if sys.argv[1] == 'renew':
+ if sys.argv[1] == "renew":
print("Renewing token...")
renew = True
except IndexError:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/resultsdb_api-2.1.5/tox.ini
new/resultsdb_api-2.1.6/tox.ini
--- old/resultsdb_api-2.1.5/tox.ini 2021-11-14 10:41:38.000000000 +0100
+++ new/resultsdb_api-2.1.6/tox.ini 2026-02-18 19:20:40.000000000 +0100
@@ -1,23 +1,21 @@
[tox]
-envlist = py37,py38,py39,py310
+envlist = py36,py310,py311,py312,py313,py314,coverage-report
skip_missing_interpreters = true
-
+isolated_build = true
[testenv]
deps =
-r{toxinidir}/install.requires
-r{toxinidir}/tests.requires
-
-commands=
- pytest
-
-[flake8]
-max-line-length=99
-
-[pep8]
-max-line-length=99
-
-[pytest]
-minversion=2.0
-python_functions=test should
-python_files=test_* functest_*
-addopts=--functional testing/ --cov resultsdb_api --cov-report=term-missing
+commands =
+ coverage run -m pytest {posargs}
+[testenv:coverage-report]
+deps = -r{toxinidir}/ci.requires
+skip_install = true
+ignore_errors = true
+commands =
+ black --check . testing/
+ coverage combine
+ coverage report
+ coverage xml
+ diff-cover coverage.xml --fail-under=90 --compare-branch=origin/develop
+ diff-quality --violations=pylint --fail-under=90
--compare-branch=origin/develop