diff --git a/0001-Fix-compatibility-with-setuptools-66.patch b/0001-Fix-compatibility-with-setuptools-66.patch deleted file mode 100644 index 9f167058f40c4200259004ea303050b3e1841ec0..0000000000000000000000000000000000000000 --- a/0001-Fix-compatibility-with-setuptools-66.patch +++ /dev/null @@ -1,163 +0,0 @@ -From 93acddd5f9c40a707cf5eb1b86d8dd6a3f69c695 Mon Sep 17 00:00:00 2001 -Message-Id: <93acddd5f9c40a707cf5eb1b86d8dd6a3f69c695.1686949946.git.ce+ubuntuone@sicherha.de> -From: Christoph Erhardt -Date: Sun, 30 Apr 2023 11:18:15 +0200 -Subject: [PATCH] Fix compatibility with setuptools >= 66 - -The Python world, including the `setuptools` package, has migrated to -the versioning scheme defined in PEP 440. Unfortunately, the versioning -of Jenkins plugins is less strict than that. As a consequence, -`pkg_resources.parse_version()` now rejects versions as invalid. - -Fix `PluginVersion` by salvaging the implementation of the old -`LegacyVersion` class, which used to be part of the `packaging` library -prior to version 22.0. The code is licensed under a 2-clause BSD -licence. - -For compatibility with older Python versions, remove type annotations -from the copied code. - -Change-Id: Iaa057dcd81620fed861cb11bed534ff7f9ab3f32 -Signed-off-by: Christoph Erhardt ---- - jenkins/plugins.py | 97 +++++++++++++++++++++++++++++++++++++++++++--- - requirements.txt | 2 - - 2 files changed, 91 insertions(+), 8 deletions(-) - -diff --git a/jenkins/plugins.py b/jenkins/plugins.py -index 9709d5d..cdaada9 100644 ---- a/jenkins/plugins.py -+++ b/jenkins/plugins.py -@@ -42,8 +42,6 @@ - import operator - import re - --import pkg_resources -- - - class Plugin(dict): - '''Dictionary object containing plugin metadata.''' -@@ -76,15 +74,13 @@ class PluginVersion(str): - '''Parse plugin version and store it for comparison.''' - - self._version = version -- self.parsed_version = pkg_resources.parse_version( -- self.__convert_version(version)) -+ self._key = _legacy_cmpkey(self.__convert_version(version)) - - def __convert_version(self, version): - return self._VERSION_RE.sub(r'\g<1>.preview', str(version)) - - def __compare(self, op, version): -- return op(self.parsed_version, pkg_resources.parse_version( -- self.__convert_version(version))) -+ return op(self._key, PluginVersion(version)._key) - - def __le__(self, version): - return self.__compare(operator.le, version) -@@ -109,3 +105,92 @@ class PluginVersion(str): - - def __repr__(self): - return str(self._version) -+ -+ -+############################################################################### -+""" -+The Python world has migrated to the versioning scheme defined in PEP 440, but -+the versioning of Jenkins plugins is less strict than that. The code below was -+salvaged from the implementation of the `LegacyVersion` class, which used to be -+part of the `packaging` library prior to version 22.0. -+ -+It is licensed as follows. -+ -+Copyright (c) Donald Stufft and individual contributors. -+All rights reserved. -+ -+Redistribution and use in source and binary forms, with or without -+modification, are permitted provided that the following conditions are met: -+ -+ 1. Redistributions of source code must retain the above copyright notice, -+ this list of conditions and the following disclaimer. -+ -+ 2. Redistributions in binary form must reproduce the above copyright -+ notice, this list of conditions and the following disclaimer in the -+ documentation and/or other materials provided with the distribution. -+ -+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+""" -+ -+_legacy_version_component_re = re.compile(r"(\d+ | [a-z]+ | \.| -)", re.VERBOSE) -+ -+_legacy_version_replacement_map = { -+ "pre": "c", -+ "preview": "c", -+ "-": "final-", -+ "rc": "c", -+ "dev": "@", -+} -+ -+ -+def _parse_version_parts(s): -+ for part in _legacy_version_component_re.split(s): -+ part = _legacy_version_replacement_map.get(part, part) -+ -+ if not part or part == ".": -+ continue -+ -+ if part[:1] in "0123456789": -+ # pad for numeric comparison -+ yield part.zfill(8) -+ else: -+ yield "*" + part -+ -+ # ensure that alpha/beta/candidate are before final -+ yield "*final" -+ -+ -+def _legacy_cmpkey(version): -+ -+ # We hardcode an epoch of -1 here. A PEP 440 version can only have a epoch -+ # greater than or equal to 0. This will effectively put the LegacyVersion, -+ # which uses the defacto standard originally implemented by setuptools, -+ # as before all PEP 440 versions. -+ epoch = -1 -+ -+ # This scheme is taken from pkg_resources.parse_version setuptools prior to -+ # it's adoption of the packaging library. -+ parts = [] -+ for part in _parse_version_parts(version.lower()): -+ if part.startswith("*"): -+ # remove "-" before a prerelease tag -+ if part < "*final": -+ while parts and parts[-1] == "*final-": -+ parts.pop() -+ -+ # remove trailing zeros from each series of numeric parts -+ while parts and parts[-1] == "00000000": -+ parts.pop() -+ -+ parts.append(part) -+ -+ return epoch, tuple(parts) -diff --git a/requirements.txt b/requirements.txt -index da41145..5c014cc 100644 ---- a/requirements.txt -+++ b/requirements.txt -@@ -1,5 +1,3 @@ --# Setuptools removed support for PEP 440 non-conforming versions --setuptools<66 - six>=1.3.0 - pbr>=0.8.2 - multi_key_dict --- -2.40.1 - diff --git a/0001-Remove-time_limit-and-testcase-with-no-module-multip.patch b/0001-Remove-time_limit-and-testcase-with-no-module-multip.patch new file mode 100644 index 0000000000000000000000000000000000000000..c7dc8508f160cd4866141563d56495be170169cb --- /dev/null +++ b/0001-Remove-time_limit-and-testcase-with-no-module-multip.patch @@ -0,0 +1,110 @@ +From c3757f0f138735559a8f63c56bfb2773019f11e5 Mon Sep 17 00:00:00 2001 +From: desert-sailor +Date: Wed, 23 Jul 2025 12:04:31 +0800 +Subject: [PATCH] Remove time_limit and testcase with no module multiprocess + +--- + tests/helper.py | 52 ----------------------------------- + tests/test_jenkins_sockets.py | 13 --------- + 2 files changed, 65 deletions(-) + +diff --git a/tests/helper.py b/tests/helper.py +index 6c5a84e..c825a2c 100644 +--- a/tests/helper.py ++++ b/tests/helper.py +@@ -1,7 +1,5 @@ + import functools + import json +-from multiprocess import Process +-from multiprocess import Queue + import traceback + + from mock import Mock +@@ -13,56 +11,6 @@ class TestsTimeoutException(Exception): + pass + + +-def time_limit(seconds, fp, func, *args, **kwargs): +- +- if fp: +- if not hasattr(fp, 'write'): +- raise TypeError("Expected 'file-like' object, got '%s'" % fp) +- else: +- def record(msg): +- fp.write(msg) +- else: +- def record(msg): +- return +- +- def capture_results(msg_queue, func, *args, **kwargs): +- try: +- result = func(*args, **kwargs) +- except Exception as e: +- msg_queue.put( +- "Running function '%s' resulted in exception '%s' with " +- "message: '%s'\n" % (func.__name__, e.__class__.__name__, e)) +- # no point re-raising an exception from the subprocess, instead +- # return False +- return False +- else: +- msg_queue.put( +- "Running function '%s' finished with result '%s', and" +- "stack:\n%s\n" % (func.__name__, result, +- traceback.format_stack())) +- return result +- +- messages = Queue() +- # although creating a separate process is expensive it's the only way to +- # ensure cross platform that we can cleanly terminate after timeout +- p = Process(target=functools.partial(capture_results, messages, func), +- args=args, kwargs=kwargs) +- p.start() +- p.join(seconds) +- if p.is_alive(): +- p.terminate() +- while not messages.empty(): +- record(messages.get()) +- record("Running function '%s' did not finish\n" % func.__name__) +- +- raise TestsTimeoutException +- else: +- while not messages.empty(): +- record(messages.get()) +- record("Running function '%s' finished with exit code '%s'\n" +- % (func.__name__, p.exitcode)) +- +- + class NullServer(socketserver.TCPServer): + + request_queue_size = 1 +diff --git a/tests/test_jenkins_sockets.py b/tests/test_jenkins_sockets.py +index 0b30085..4847cbf 100644 +--- a/tests/test_jenkins_sockets.py ++++ b/tests/test_jenkins_sockets.py +@@ -5,7 +5,6 @@ from testtools.content import text_content + import jenkins + from tests.helper import NullServer + from tests.helper import TestsTimeoutException +-from tests.helper import time_limit + + + class JenkinsRequestTimeoutTests(testtools.TestCase): +@@ -29,15 +28,3 @@ class JenkinsRequestTimeoutTests(testtools.TestCase): + # assert our request times out when no response + with testtools.ExpectedException(jenkins.TimeoutException): + j.jenkins_open(request, add_crumb=False) +- +- def test_jenkins_open_no_timeout(self): +- j = jenkins.Jenkins("http://%s:%s" % self.server.server_address, +- None, None) +- request = jenkins.requests.Request('GET', 'http://%s:%s/job/TestJob' % +- self.server.server_address) +- +- # assert we don't timeout quickly like previous test when +- # no timeout defined. +- with testtools.ExpectedException(TestsTimeoutException): +- time_limit(0.5, self.messages, +- j.jenkins_open, request, add_crumb=False) +-- +2.43.0 + diff --git a/python-jenkins-1.8.0.tar.gz b/python-jenkins-1.8.0.tar.gz deleted file mode 100644 index bc4525568483336f5d9d3ebe713fd4a6e26e9420..0000000000000000000000000000000000000000 Binary files a/python-jenkins-1.8.0.tar.gz and /dev/null differ diff --git a/python-jenkins-1.8.2.tar.gz b/python-jenkins-1.8.2.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..bb99b8433a823bbf7f6d4ef5907c5da2981b1e07 Binary files /dev/null and b/python-jenkins-1.8.2.tar.gz differ diff --git a/python-jenkins.spec b/python-jenkins.spec index ecc34aaada20e8a197984751f078443825340c74..0e041cfdfbf35ac54d93a25bbe4a57f7a3c5c7a6 100644 --- a/python-jenkins.spec +++ b/python-jenkins.spec @@ -1,12 +1,11 @@ Name: python-jenkins -Version: 1.8.0 +Version: 1.8.2 Release: 1 Summary: Python bindings for the remote Jenkins API License: BSD-3-Clause URL: http://git.openstack.org/cgit/openstack/python-jenkins -Source0: https://files.pythonhosted.org/packages/93/2e/8120831ac693483e3ac878c2f1c6bb3535dabb247b4a93117bb2da3b09f8/python-jenkins-1.8.0.tar.gz -# Contributed at https://review.opendev.org/c/jjb/python-jenkins/+/881904 -Patch0: 0001-Fix-compatibility-with-setuptools-66.patch +Source0: https://files.pythonhosted.org/packages/45/ac/2bc1d844609302f7f907594961ffba7d6edd5848705f958683a9c2d87901/python-jenkins-1.8.2.tar.gz +Patch1: 0001-Remove-time_limit-and-testcase-with-no-module-multip.patch BuildRequires: python3-sphinx BuildRequires: make @@ -21,6 +20,11 @@ build nodes. %package -n python3-jenkins Summary: %{summary} BuildRequires: python3-devel +BuildRequires: python3-setuptools +BuildRequires: python3-pbr +BuildRequires: python3-pip +BuildRequires: python3-wheel +BuildRequires: python3-hatchling BuildRequires: python3-kerberos BuildRequires: python3-mock BuildRequires: python3-multi_key_dict @@ -31,6 +35,7 @@ BuildRequires: python3-setuptools BuildRequires: python3-six >= 1.3.0 BuildRequires: python3-testscenarios BuildRequires: python3-testtools +BuildRequires: python3-eventlet %{?python_provide:%python_provide python3-jenkins} %if %{undefined __pythondist_requires} @@ -58,7 +63,7 @@ sed -i '1{s|^#!/usr/bin/env python||}' jenkins/__init__.py %build export PBR_VERSION=%{version} -%py3_build +%pyproject_build PYTHONDONTWRITEBYTECODE=1 \ PYTHONPATH=$PWD \ @@ -69,7 +74,7 @@ rm doc/build/html/.buildinfo %install export PBR_VERSION=%{version} -%py3_install +%pyproject_install install -D -m0644 -p doc/build/man/pythonjenkins.1 %{buildroot}%{_mandir}/man1/pythonjenkins.1 @@ -82,11 +87,14 @@ install -D -m0644 -p doc/build/man/pythonjenkins.1 %{buildroot}%{_mandir}/man1/p %doc README.rst doc/build/html %license COPYING %{python3_sitelib}/jenkins/ -%{python3_sitelib}/python_jenkins-%{version}-py%{python3_version}.egg-info/ +%{python3_sitelib}/python_jenkins-*.dist-info/ %{_mandir}/man1/pythonjenkins.1.* %changelog +* Tue Jul 22 2025 Dongxing Wang - 1.8.2-1 +- Update package to version 1.8.2 and fix build error + * Wed Aug 23 2023 jiangxinyu - 1.8.0-1 - Update package to version 1.8.0