From 1dee863f0add8bd295552025ff00ba17acb28a395cafae376f57e4ddd077ae4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mark=C3=A9ta=20Machov=C3=A1?= Date: Tue, 17 Jun 2025 09:16:28 +0000 Subject: [PATCH 1/2] - Convert to libalternatives OBS-URL: https://build.opensuse.org/package/show/devel:languages:python/python-bugzillatools?expand=0&rev=24 --- .gitattributes | 23 ++ .gitignore | 1 + 0001-Working-on-both-2.7-and-3.4.patch | 408 +++++++++++++++++++++++++ bugzillatools-0.5.5.tar.gz | 3 + no-bzrlib-py3k.patch | 100 ++++++ python-bugzillatools.changes | 104 +++++++ python-bugzillatools.spec | 83 +++++ python312.patch | 102 +++++++ 8 files changed, 824 insertions(+) create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 0001-Working-on-both-2.7-and-3.4.patch create mode 100644 bugzillatools-0.5.5.tar.gz create mode 100644 no-bzrlib-py3k.patch create mode 100644 python-bugzillatools.changes create mode 100644 python-bugzillatools.spec create mode 100644 python312.patch diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..9b03811 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,23 @@ +## Default LFS +*.7z filter=lfs diff=lfs merge=lfs -text +*.bsp filter=lfs diff=lfs merge=lfs -text +*.bz2 filter=lfs diff=lfs merge=lfs -text +*.gem filter=lfs diff=lfs merge=lfs -text +*.gz filter=lfs diff=lfs merge=lfs -text +*.jar filter=lfs diff=lfs merge=lfs -text +*.lz filter=lfs diff=lfs merge=lfs -text +*.lzma filter=lfs diff=lfs merge=lfs -text +*.obscpio filter=lfs diff=lfs merge=lfs -text +*.oxt filter=lfs diff=lfs merge=lfs -text +*.pdf filter=lfs diff=lfs merge=lfs -text +*.png filter=lfs diff=lfs merge=lfs -text +*.rpm filter=lfs diff=lfs merge=lfs -text +*.tbz filter=lfs diff=lfs merge=lfs -text +*.tbz2 filter=lfs diff=lfs merge=lfs -text +*.tgz filter=lfs diff=lfs merge=lfs -text +*.ttf filter=lfs diff=lfs merge=lfs -text +*.txz filter=lfs diff=lfs merge=lfs -text +*.whl filter=lfs diff=lfs merge=lfs -text +*.xz filter=lfs diff=lfs merge=lfs -text +*.zip filter=lfs diff=lfs merge=lfs -text +*.zst filter=lfs diff=lfs merge=lfs -text diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..57affb6 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.osc diff --git a/0001-Working-on-both-2.7-and-3.4.patch b/0001-Working-on-both-2.7-and-3.4.patch new file mode 100644 index 0000000..422fb7f --- /dev/null +++ b/0001-Working-on-both-2.7-and-3.4.patch @@ -0,0 +1,408 @@ +From ae019ce73766ed38f74567459ae5cd74beb1c56f Mon Sep 17 00:00:00 2001 +From: Alex Lord +Date: Thu, 23 Jul 2015 21:20:05 -0700 +Subject: [PATCH] Working on both 2.7 and 3.4 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Matěj Cepl +--- + bzlib/bug.py | 7 ++-- + bzlib/bugzilla.py | 16 +++++--- + bzlib/command.py | 90 +++++++++++++++++++++--------------------- + bzlib/config.py | 5 ++- + bzlib/test_bugzilla.py | 10 ++--- + bzlib/ui.py | 2 +- + 6 files changed, 69 insertions(+), 61 deletions(-) + +diff --git a/bzlib/bug.py b/bzlib/bug.py +index 6586c16..ebcdba0 100644 +--- a/bzlib/bug.py ++++ b/bzlib/bug.py +@@ -101,7 +101,7 @@ class Bug(object): + kwargs[_in] = list(all_values - frozenset(kwargs[_not_in])) + del kwargs[_not_in] # delete the _not_in + +- unknowns = kwargs.viewkeys() - fields ++ unknowns = set(kwargs.keys()) - fields + if unknowns: + # unknown arguments + raise TypeError( +@@ -252,14 +252,13 @@ class Bug(object): + 'comment', + 'version', 'priority', + ]) +- unknowns = kwargs.viewkeys() - fields ++ unknowns = kwargs.keys() - fields + if unknowns: + # unknown arguments + raise TypeError('Invalid keyword arguments: {}.'.format(unknowns)) + + # filter out ``None``s +- kwargs = {k: v for k, v in kwargs.viewitems() if v is not None} +- ++ kwargs = {k: v for k, v in kwargs.keys() if v is not None} + # format deadline (YYYY-MM-DD) + if 'deadline' in kwargs: + date = kwargs['deadline'] +diff --git a/bzlib/bugzilla.py b/bzlib/bugzilla.py +index 14439bf..63822c2 100644 +--- a/bzlib/bugzilla.py ++++ b/bzlib/bugzilla.py +@@ -15,8 +15,14 @@ + # You should have received a copy of the GNU General Public License + # along with this program. If not, see . + +-import urlparse +-import xmlrpclib ++try: ++ import urllib.parse as urlparse ++except ImportError: ++ import urlparse ++try: ++ import xmlrpclib ++except ImportError: ++ import xmlrpc.client as xmlrpclib + + from . import bug + from . import config +@@ -58,7 +64,7 @@ class Bugzilla(object): + required, but may be ``None``. + """ + mandatory_args = set(['server', 'url', 'user', 'password']) +- mandatory_args -= kwargs.viewkeys() ++ mandatory_args -= set(kwargs.keys()) + if mandatory_args: + raise TypeError('Mandatory args ({}) not supplied'.format( + ', '.join("'{}'".format(arg) for arg in mandatory_args))) +@@ -81,8 +87,8 @@ class Bugzilla(object): + _server[k] = kwargs[k] + + mandatory_kwargs = {'url'} +- if mandatory_kwargs - _server.viewkeys(): +- missing_args = ', '.join(mandatory_kwargs - _server.viewkeys()) ++ if mandatory_kwargs - set(_server.keys()): ++ missing_args = ', '.join(mandatory_kwargs - _server.items()) + raise UserWarning("missing args: {}".format(missing_args)) + + return cls(**_server) +diff --git a/bzlib/command.py b/bzlib/command.py +index 59d591d..6c42e8a 100644 +--- a/bzlib/command.py ++++ b/bzlib/command.py +@@ -184,7 +184,7 @@ class Config(Command): + if args.list: + for section in conf.sections(): + for option, value in conf.items(section): +- print '{}={}'.format('.'.join((section, option)), value) ++ print('{}={}'.format('.'.join((section, option)), value)) + elif not args.name: + raise UserWarning('No configuration option given.') + else: +@@ -209,10 +209,10 @@ class Config(Command): + if conf.has_option(section, option) else None + conf.set(section, option, args.value) + conf.write() +- print '{}: {} => {}'.format(args.name, oldvalue, args.value) ++ print('{}: {} => {}'.format(args.name, oldvalue, args.value)) + else: + curvalue = conf.get(section, option) +- print '{}: {}'.format(args.name, curvalue) ++ print('{}: {}'.format(args.name, curvalue)) + + + class Help(Command): +@@ -227,12 +227,12 @@ class Help(Command): + self._parser.parse_args(['--help']) + else: + if self._args.subcommand in self._aliases: +- print "'{}': alias for {}".format( ++ print("'{}': alias for {}".format( + self._args.subcommand, + self._aliases[self._args.subcommand] +- ) ++ )) + elif self._args.subcommand not in self._commands: +- print "unknown subcommand: '{}'".format(self._args.subcommand) ++ print("unknown subcommand: '{}'".format(self._args.subcommand)) + else: + self._parser.parse_args([self._args.subcommand, '--help']) + +@@ -288,12 +288,12 @@ class Block(BugzillaCommand): + else: + # show blocked bugs + for bug in bugs: +- print 'Bug {}:'.format(bug.bugno) ++ print('Bug {}:'.format(bug.bugno)) + if bug.data['blocks']: +- print ' Blocked bugs: {}'.format( +- ', '.join(map(str, bug.data['blocks']))) ++ print(' Blocked bugs: {}'.format( ++ ', '.join(map(str, bug.data['blocks'])))) + else: +- print ' No blocked bugs' ++ print(' No blocked bugs') + + + @with_add_remove('given users', 'CC List', metavar='USER') +@@ -326,12 +326,12 @@ class CC(BugzillaCommand): + else: + # show CC List + for bug in bugs: +- print 'Bug {}:'.format(bug.bugno) ++ print('Bug {}:'.format(bug.bugno)) + if bug.data['cc']: +- print ' CC List: {}'.format( +- ', '.join(map(str, bug.data['cc']))) ++ print(' CC List: {}'.format( ++ ', '.join(map(str, bug.data['cc'])))) + else: +- print ' 0 users' ++ print(' 0 users') + + + @with_bugs +@@ -390,7 +390,7 @@ class Comment(BugzillaCommand): + and not (args.which and n not in args.which) + ) + ) +- print '\n'.join(map(cmtfmt, args.bugs)) ++ print('\n'.join(map(cmtfmt, args.bugs))) + + + @with_set('given bugs', 'depdendencies', metavar='BUG', type=int) +@@ -418,12 +418,12 @@ class Depend(BugzillaCommand): + else: + # show dependencies + for bug in bugs: +- print 'Bug {}:'.format(bug.bugno) ++ print('Bug {}:'.format(bug.bugno)) + if bug.data['depends_on']: +- print ' Dependencies: {}'.format( +- ', '.join(map(str, bug.data['depends_on']))) ++ print(' Dependencies: {}'.format( ++ ', '.join(map(str, bug.data['depends_on'])))) + else: +- print ' No dependencies' ++ print(' No dependencies') + + + @with_bugs +@@ -438,7 +438,7 @@ class Desc(BugzillaCommand): + bug, + self.formatstring.format(**desc) + ) +- print '\n'.join(_descfmt(bug) for bug in self._args.bugs) ++ print('\n'.join(_descfmt(bug) for bug in self._args.bugs)) + + + @with_bugs +@@ -446,7 +446,7 @@ class Dump(BugzillaCommand): + """Print internal representation of bug data.""" + def __call__(self): + bugs = (self.bz.bug(x) for x in self._args.bugs) +- print '\n'.join(str((x.data, x.comments)) for x in bugs) ++ print('\n'.join(str((x.data, x.comments)) for x in bugs)) + + + @with_bugs +@@ -480,18 +480,18 @@ class Fields(BugzillaCommand): + sorted(field['values'], None, keyfn), + keyfn + ) +- print field['name'], ':' ++ print("{} :".format(field['name'])) + for key, group in groups: + keyfn = lambda x: int(x.get('sortkey', -1)) + values = sorted(group, None, keyfn) + if key: +- print ' {}: {}'.format( ++ print(' {}: {}'.format( + ','.join(key), + ','.join(map(lambda x: x['name'], values)) +- ) ++ )) + else: + value_names = (v.get('name') for v in values) +- print ' ', ','.join(s for s in value_names if s) ++ print(' ', ','.join(s for s in value_names if s)) + + + def _format_history(history): +@@ -518,10 +518,10 @@ class History(BugzillaCommand): + _history[0][0] = h['who'] + _history[0][1] = h['when'] + history.extend(_history) +- print 'History of Bug {}:'.format(bug.bugno) ++ print('History of Bug {}:'.format(bug.bugno)) + for line in _format_history(history): +- print ' ' + line +- print ++ print(' ' + line) ++ print() + + + @with_bugs +@@ -531,12 +531,12 @@ class Info(BugzillaCommand): + args = self._args + fields = config.show_fields + for bug in map(self.bz.bug, args.bugs): +- print 'Bug {}:'.format(bug.bugno) ++ print('Bug {}:'.format(bug.bugno)) + fields = config.show_fields & bug.data.viewkeys() + width = max(map(len, fields)) - min(map(len, fields)) + 2 + for field in fields: +- print ' {:{}} {}'.format(field + ':', width, bug.data[field]) +- print ++ print(' {:{}} {}'.format(field + ':', width, bug.data[field])) ++ print() + + + @with_bugs +@@ -547,9 +547,9 @@ class List(BugzillaCommand): + lens = [len(str(x)) for x in args.bugs] + width = max(lens) - min(lens) + 2 + for bug in map(self.bz.bug, args.bugs): +- print 'Bug {:{}} {}'.format( ++ print('Bug {:{}} {}'.format( + str(bug.bugno) + ':', width, bug.data['summary'] +- ) ++ )) + + + class New(BugzillaCommand): +@@ -672,9 +672,9 @@ class Products(BugzillaCommand): + products = self.bz.get_products() + width = max(map(lambda x: len(x['name']), products)) + 1 + for product in products: +- print '{:{}} {}'.format( ++ print('{:{}} {}'.format( + product['name'] + ':', width, product['description'] +- ) ++ )) + + + @with_bugs +@@ -815,12 +815,12 @@ class Search(BugzillaCommand): + lens = [len(str(b.bugno)) for b in bugs] + + for _bug in bugs: +- print 'Bug {:{}} {}'.format( ++ print('Bug {:{}} {}'.format( + str(_bug.bugno) + ':', max(lens) - min(lens) + 2, + _bug.data['summary'] +- ) ++ )) + n = len(bugs) +- print '=> {} bug{} matched criteria'.format(n, 's' if n else '') ++ print('=> {} bug{} matched criteria'.format(n, 's' if n else '')) + + + @with_bugs +@@ -860,13 +860,13 @@ class Time(BugzillaCommand): + # be absent from bug data. first check that they're there. + time_fields = ('deadline', 'estimated_time', 'remaining_time') + if not all(x in bug.data for x in time_fields): +- print 'User is not in the time-tracking group.' ++ print('User is not in the time-tracking group.') + return +- print 'Bug {}:'.format(bug.bugno) +- print ' Estimated time: {}'.format(bug.data['estimated_time']) +- print ' Remaining time: {}'.format(bug.data['remaining_time']) +- print ' Deadline: {}'.format(bug.data['deadline']) +- print ' Time worked: {}'.format(bug.actual_time()) ++ print('Bug {}:'.format(bug.bugno)) ++ print(' Estimated time: {}'.format(bug.data['estimated_time'])) ++ print(' Remaining time: {}'.format(bug.data['remaining_time'])) ++ print(' Deadline: {}'.format(bug.data['deadline'])) ++ print(' Time worked: {}'.format(bug.actual_time())) + + + # the list got too long; metaprogram it ^_^ +@@ -874,5 +874,5 @@ commands = filter( + lambda x: type(x) == type # is a class \ + and issubclass(x, Command) # is a Command \ + and x not in [Command, BugzillaCommand], # not abstract +- locals().viewvalues() ++ locals().items() + ) +diff --git a/bzlib/config.py b/bzlib/config.py +index f363eb7..6548075 100644 +--- a/bzlib/config.py ++++ b/bzlib/config.py +@@ -14,7 +14,10 @@ + # You should have received a copy of the GNU General Public License + # along with this program. If not, see . + +-import ConfigParser ++try: ++ import ConfigParser ++except ImportError: ++ import configparser as ConfigParser + import os.path + import re + +diff --git a/bzlib/test_bugzilla.py b/bzlib/test_bugzilla.py +index d7238b5..7f6054e 100644 +--- a/bzlib/test_bugzilla.py ++++ b/bzlib/test_bugzilla.py +@@ -41,7 +41,7 @@ class URLTestCase(unittest.TestCase): + with self.assertRaises(bugzilla.URLError) as cm: + bugzilla.Bugzilla('bogus://bugzilla.example.com/', 'u', 'p') + self.assertEqual( +- cm.exception.message, ++ str(cm.exception), + "URL scheme 'bogus' not supported." + ) + +@@ -54,7 +54,7 @@ class URLTestCase(unittest.TestCase): + with self.assertRaises(bugzilla.URLError) as cm: + bugzilla.Bugzilla(url, 'u', 'p') + self.assertEqual( +- cm.exception.message, ++ str(cm.exception), + 'URL {!r} is not valid.'.format(url) + ) + +@@ -63,21 +63,21 @@ class URLTestCase(unittest.TestCase): + with self.assertRaises(bugzilla.URLError) as cm: + bugzilla.Bugzilla('http://bugzilla.example.com/;p', 'u', 'p') + self.assertEqual( +- cm.exception.message, ++ str(cm.exception), + 'URL params, queries and fragments not supported.' + ) + # query + with self.assertRaises(bugzilla.URLError) as cm: + bugzilla.Bugzilla('http://bugzilla.example.com/?q', 'u', 'p') + self.assertEqual( +- cm.exception.message, ++ str(cm.exception), + 'URL params, queries and fragments not supported.' + ) + # fragment + with self.assertRaises(bugzilla.URLError) as cm: + bugzilla.Bugzilla('http://bugzilla.example.com/#f', 'u', 'p') + self.assertEqual( +- cm.exception.message, ++ str(cm.exception), + 'URL params, queries and fragments not supported.' + ) + +diff --git a/bzlib/ui.py b/bzlib/ui.py +index 87895f6..0ec0360 100644 +--- a/bzlib/ui.py ++++ b/bzlib/ui.py +@@ -168,7 +168,7 @@ def filter_user(string, bugzilla=None, default=None): + + class UI(object): + def show(self, msg): +- print msg ++ print(msg) + + def bail(self, msg=None): + """Exit uncleanly with an optional message""" +-- +2.17.0 + diff --git a/bugzillatools-0.5.5.tar.gz b/bugzillatools-0.5.5.tar.gz new file mode 100644 index 0000000..e8efd33 --- /dev/null +++ b/bugzillatools-0.5.5.tar.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3e1dfa5a74c4ac071333ae5c450304e7cb5bb705cbada00a9da236670954b984 +size 41910 diff --git a/no-bzrlib-py3k.patch b/no-bzrlib-py3k.patch new file mode 100644 index 0000000..27694fe --- /dev/null +++ b/no-bzrlib-py3k.patch @@ -0,0 +1,100 @@ +--- a/plugin-bzr/__init__.py ++++ b/plugin-bzr/__init__.py +@@ -91,34 +91,36 @@ a bug URL and status in the revision met + + bzr commit -m 'fix bug 123' --fixes example:123 + """ ++import sys + +-import bzrlib.api +-import bzrlib.commands +-import bzrlib.trace +- +-import bzlib +- +-from . import hooks +- +-# plugin setup +-version_info = bzlib.version_info +- +-COMPATIBLE_BZR_VERSIONS = [ +- (2, 0, 0), +- (2, 1, 0), +- (2, 2, 0), +- (2, 3, 0), +-] +- +-bzrlib.api.require_any_api(bzrlib, COMPATIBLE_BZR_VERSIONS) +- +-if __name__ != 'bzrlib.plugins.bugzillatools': +- bzrlib.trace.warning( +- 'Not running as bzrlib.plugins.bugzillatools; things may break.') +- +-# install the get_command hook +-bzrlib.commands.Command.hooks.install_named_hook( +- 'get_command', +- hooks.get_command_hook, +- 'bugzilla plugin - extend cmd_commit' +-) ++if sys.version_info[0] == 2: ++ import bzrlib.api ++ import bzrlib.commands ++ import bzrlib.trace ++ ++ import bzlib ++ ++ from . import hooks ++ ++ # plugin setup ++ version_info = bzlib.version_info ++ ++ COMPATIBLE_BZR_VERSIONS = [ ++ (2, 0, 0), ++ (2, 1, 0), ++ (2, 2, 0), ++ (2, 3, 0), ++ ] ++ ++ bzrlib.api.require_any_api(bzrlib, COMPATIBLE_BZR_VERSIONS) ++ ++ if __name__ != 'bzrlib.plugins.bugzillatools': ++ bzrlib.trace.warning( ++ 'Not running as bzrlib.plugins.bugzillatools; things may break.') ++ ++ # install the get_command hook ++ bzrlib.commands.Command.hooks.install_named_hook( ++ 'get_command', ++ hooks.get_command_hook, ++ 'bugzilla plugin - extend cmd_commit' ++ ) +--- a/bzlib/config.py ++++ b/bzlib/config.py +@@ -40,7 +40,7 @@ def check_section(section): + raise ConfigError('invalid section: {}'.format(section)) + + +-class Config(ConfigParser.SafeConfigParser): ++class Config(ConfigParser.ConfigParser): + _instances = {} + + @classmethod +@@ -52,16 +52,16 @@ class Config(ConfigParser.SafeConfigPars + + def __init__(self, path): + path = os.path.expanduser(path) +- ConfigParser.SafeConfigParser.__init__(self) ++ ConfigParser.ConfigParser.__init__(self) + self._path = path + self.read(self._path) + + def write(self): + with open(self._path, 'w') as fp: +- ConfigParser.SafeConfigParser.write(self, fp) ++ ConfigParser.ConfigParser.write(self, fp) + + def add_section(self, section): +- ConfigParser.SafeConfigParser.add_section(self, check_section(section)) ++ ConfigParser.ConfigParser.add_section(self, check_section(section)) + + + NoSectionError = ConfigParser.NoSectionError diff --git a/python-bugzillatools.changes b/python-bugzillatools.changes new file mode 100644 index 0000000..f82c729 --- /dev/null +++ b/python-bugzillatools.changes @@ -0,0 +1,104 @@ +------------------------------------------------------------------- +Tue Jun 17 09:16:04 UTC 2025 - Markéta Machová + +- Convert to libalternatives + +------------------------------------------------------------------- +Fri Jun 6 05:30:56 UTC 2025 - Steve Kowalik + +- Switch to pyproject macros. + +------------------------------------------------------------------- +Tue Feb 20 18:37:51 UTC 2024 - Daniel Garcia + +- Add python312.patch to fix tests with python3.12 + +------------------------------------------------------------------- +Tue Aug 18 22:57:57 UTC 2020 - Matej Cepl + +- We can finally use %pyunittest macro + +------------------------------------------------------------------- +Wed May 27 09:36:32 UTC 2020 - Petr Gajdos + +- %python3_only -> %python_alternative + +------------------------------------------------------------------- +Tue Dec 4 12:46:20 UTC 2018 - Matej Cepl + +- Remove superfluous devel dependency for noarch package + +------------------------------------------------------------------- +Wed Jul 18 11:52:31 UTC 2018 - tchvatal@suse.com + +- Whitespace in prep phase to ensure we build on Leap 42 + +------------------------------------------------------------------- +Thu May 31 10:40:54 UTC 2018 - mcepl@suse.com + +- We want to conflict even package called literally python-bugzillatools + (without any expansions) + +------------------------------------------------------------------- +Fri May 25 14:09:50 UTC 2018 - mcepl@suse.com + +- Add upstream patch for porting to Python 3 (and fix some remaining + bugs) + * 0001-Working-on-both-2.7-and-3.4.patch patch combining all upstream + changes to port module to py3k + * no-bzrlib-py3k.patch my fixes for making test suite working with + as little fuss as possible +- Adjust SPEC file for adding testing + +------------------------------------------------------------------- +Wed May 23 13:23:07 UTC 2018 - mcepl@suse.com + +- Fix SPEC file with spec-cleaner + +------------------------------------------------------------------- +Thu Aug 24 13:33:33 UTC 2017 - jmatejek@suse.com + +- singlespec auto-conversion + +------------------------------------------------------------------- +Tue Apr 28 20:56:37 UTC 2015 - benoit.monin@gmx.fr + +- update to version 0.5.5: + * comment command learned the --private option + * fix comment enumeration order + * fix string encoding error when invoking editor which could lead + to invalid XML being sent to server +- additional changes from version 0.5.4: + * better error messages on missing server/account configuration + (#3) + * remove fields without name data from bug records (#5) + * make user and password configuration optional (#12) +- additional changes from version 0.5.3.1: + * fix installation error +- additional changes from version 0.5.3: + * editor: fix incorrect path to vi(1) when EDITOR is not defined + * create command: treat "defaulted" fields as mandatory in case + no default is set + * ui: fix some unicode encoding errors + * fields command: handle minor changes in result format in 4.4 + * correct the name of the platform field + (platform -> rep_platform) + * expand bzr plugin documentation +- replace README with README.rst: changed upstream + +------------------------------------------------------------------- +Mon Oct 21 13:13:33 UTC 2013 - speilicke@suse.com + +- Fix license to GPL-3.0+ (see sr#203363 for reference) + +------------------------------------------------------------------- +Wed Oct 9 13:34:05 UTC 2013 - speilicke@suse.com + +- Set license to MIT (according to code). + +------------------------------------------------------------------- +Tue Oct 8 14:04:03 UTC 2013 - speilicke@suse.com + +- Initial version + + diff --git a/python-bugzillatools.spec b/python-bugzillatools.spec new file mode 100644 index 0000000..fd7d32f --- /dev/null +++ b/python-bugzillatools.spec @@ -0,0 +1,83 @@ +# +# spec file for package python-bugzillatools +# +# Copyright (c) 2025 SUSE LLC +# +# All modifications and additions to the file contributed by third parties +# remain the property of their copyright owners, unless otherwise agreed +# upon. The license for this file, and modifications and additions to the +# file, is the same license as for the pristine package itself (unless the +# license for the pristine package is not an Open Source License, in which +# case the license is the MIT License). An "Open Source License" is a +# license that conforms to the Open Source Definition (Version 1.9) +# published by the Open Source Initiative. + +# Please submit bugfixes or comments via https://bugs.opensuse.org/ +# + + +%define oldpython python +%bcond_without libalternatives +Name: python-bugzillatools +Version: 0.5.5 +Release: 0 +Summary: Bugzilla CLI client, XML-RPC binding and VCS plugins +License: GPL-3.0-or-later +Group: Development/Languages/Python +URL: https://github.com/frasertweedale/bugzillatools +Source: https://files.pythonhosted.org/packages/source/b/bugzillatools/bugzillatools-%{version}.tar.gz +# Port to Python3 from yet unreleased commits in the upstream repo +Patch0: 0001-Working-on-both-2.7-and-3.4.patch +# Some more py3k fixes +# https://github.com/rawrgulmuffins/bugzillatools/pull/26 +Patch1: no-bzrlib-py3k.patch +# PATCH-FIX-OPENSUSE python312.patch +Patch2: python312.patch +BuildRequires: %{python_module pip} +BuildRequires: %{python_module setuptools} +BuildRequires: %{python_module wheel} +BuildRequires: alts +BuildRequires: fdupes +BuildRequires: python-rpm-macros +Requires: alts +# We want to conflict even package literally called python-bugzilla +# without the python version number +Conflicts: %{oldpython}-bugzilla +#Recommends: bzr +# File conflict for /usr/bin/bugzilla: +Conflicts: python-bugzilla +BuildArch: noarch +%python_subpackages + +%description +Provides a CLI program and Python library for interacting with the +Bugzilla_ bug tracking system, and plugins for version control +systems that enable interaction with Bugzilla installations. + +%prep +%autosetup -p1 -n bugzillatools-%{version} + +sed -i "/.bugzillarc.sample/d" setup.py + +%build +%pyproject_wheel + +%install +%pyproject_install +%python_clone -a %{buildroot}%{_bindir}/bugzilla +%python_expand %fdupes %{buildroot}%{$python_sitelib} + +%check +%pyunittest + +%pre +%python_libalternatives_reset_alternative bugzilla + +%files %{python_files} +%doc CHANGES README.rst gpl-3.0.txt +%python_alternative %{_bindir}/bugzilla +%{python_sitelib}/bzlib +%{python_sitelib}/bzrlib +%{python_sitelib}/bugzillatools-%{version}.dist-info + +%changelog diff --git a/python312.patch b/python312.patch new file mode 100644 index 0000000..050f05e --- /dev/null +++ b/python312.patch @@ -0,0 +1,102 @@ +Index: bugzillatools-0.5.5/bzlib/test_bug.py +=================================================================== +--- bugzillatools-0.5.5.orig/bzlib/test_bug.py ++++ bugzillatools-0.5.5/bzlib/test_bug.py +@@ -27,9 +27,9 @@ class BugTestCase(unittest.TestCase): + self.bz = bugzilla.Bugzilla('http://bugzilla.example.com/', 'u', 'p') + + def test_search(self): +- with self.assertRaisesRegexp(TypeError, r'\bfoobar\b'): ++ with self.assertRaisesRegex(TypeError, r'\bfoobar\b'): + bug.Bug.search(self.bz, foobar='baz') +- with self.assertRaisesRegexp(TypeError, r'\bfoobar\b'): ++ with self.assertRaisesRegex(TypeError, r'\bfoobar\b'): + bug.Bug.search(self.bz, not_foobar='baz') + fields = frozenset([ + 'alias', 'assigned_to', 'component', 'creation_time', 'creator', +Index: bugzillatools-0.5.5/bzlib/test_bugzilla.py +=================================================================== +--- bugzillatools-0.5.5.orig/bzlib/test_bugzilla.py ++++ bugzillatools-0.5.5/bzlib/test_bugzilla.py +@@ -86,13 +86,13 @@ class URLTestCase(unittest.TestCase): + + # no trailing '/' + bz = bugzilla.Bugzilla('http://' + host, 'u', 'p') +- self.assertEquals(bz.server._ServerProxy__host, host) +- self.assertEquals(bz.server._ServerProxy__handler, '/xmlrpc.cgi') ++ self.assertEqual(bz.server._ServerProxy__host, host) ++ self.assertEqual(bz.server._ServerProxy__handler, '/xmlrpc.cgi') + + # trailing '/' + bz = bugzilla.Bugzilla('http://' + host + '/', 'u', 'p') +- self.assertEquals(bz.server._ServerProxy__host, host) +- self.assertEquals(bz.server._ServerProxy__handler, '/xmlrpc.cgi') ++ self.assertEqual(bz.server._ServerProxy__host, host) ++ self.assertEqual(bz.server._ServerProxy__handler, '/xmlrpc.cgi') + + + class FromConfigTestCase(unittest.TestCase): +@@ -120,7 +120,7 @@ class FromConfigTestCase(unittest.TestCa + """Test that all mandatory args are checked.""" + mandatory_args = set(['server', 'url', 'user', 'password']) + for args in itertools.combinations(mandatory_args, 2): +- with self.assertRaisesRegexp(TypeError, '[Mm]andatory'): ++ with self.assertRaisesRegex(TypeError, '[Mm]andatory'): + bugzilla.Bugzilla.from_config( + self._conf, + **{k: None for k in args} +Index: bugzillatools-0.5.5/bzlib/test_ui.py +=================================================================== +--- bugzillatools-0.5.5.orig/bzlib/test_ui.py ++++ bugzillatools-0.5.5/bzlib/test_ui.py +@@ -24,31 +24,31 @@ class FilterTestCase(unittest.TestCase): + + def test_filter_int(self): + # 'start' arg +- with self.assertRaisesRegexp(ui.InvalidInputError, 'value too small'): ++ with self.assertRaisesRegex(ui.InvalidInputError, 'value too small'): + ui.filter_int('0', start=1) + self.assertEqual(ui.filter_int('0', start=0), 0) + + # 'stop' arg +- with self.assertRaisesRegexp(ui.InvalidInputError, 'value too large'): ++ with self.assertRaisesRegex(ui.InvalidInputError, 'value too large'): + ui.filter_int('2', stop=2) + self.assertEqual(ui.filter_int('1', stop=2), 1) + + # bogus input +- with self.assertRaisesRegexp(ui.InvalidInputError, 'not an int'): ++ with self.assertRaisesRegex(ui.InvalidInputError, 'not an int'): + ui.filter_int('a') + + # default +- with self.assertRaisesRegexp(ui.InvalidInputError, 'not an int'): ++ with self.assertRaisesRegex(ui.InvalidInputError, 'not an int'): + ui.filter_int('') + self.assertEqual(ui.filter_int('', default=100), 100) + + def test_filter_list(self): + # no filter +- with self.assertRaisesRegexp(TypeError, r'\bfilter\b'): ++ with self.assertRaisesRegex(TypeError, r'\bfilter\b'): + ui.filter_list('1 2 3') + + # duplicates +- with self.assertRaisesRegexp( ++ with self.assertRaisesRegex( + ui.InvalidInputError, + 'duplicate values are not allowed' + ): +@@ -77,10 +77,10 @@ class FilterTestCase(unittest.TestCase): + ) + + # min, max allowed +- with self.assertRaisesRegexp(ui.InvalidInputError, 'too few'): ++ with self.assertRaisesRegex(ui.InvalidInputError, 'too few'): + ui.filter_list('1 2 3', filter=ui.filter_int, min_allowed=4) + ui.filter_list('1 2 3', filter=ui.filter_int, min_allowed=3) +- with self.assertRaisesRegexp(ui.InvalidInputError, 'too many'): ++ with self.assertRaisesRegex(ui.InvalidInputError, 'too many'): + ui.filter_list('1 2 3', filter=ui.filter_int, max_allowed=2) + ui.filter_list('1 2 3', filter=ui.filter_int, max_allowed=3) + From 222b61d0425e411f3626bf53d571bc09028f0680100336ef8af196c2cc994fe0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mark=C3=A9ta=20Machov=C3=A1?= Date: Fri, 5 Sep 2025 10:48:44 +0000 Subject: [PATCH 2/2] try to hotfix libalternatives hysteria OBS-URL: https://build.opensuse.org/package/show/devel:languages:python/python-bugzillatools?expand=0&rev=25 --- python-bugzillatools.spec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/python-bugzillatools.spec b/python-bugzillatools.spec index fd7d32f..f845a27 100644 --- a/python-bugzillatools.spec +++ b/python-bugzillatools.spec @@ -44,8 +44,8 @@ Requires: alts # without the python version number Conflicts: %{oldpython}-bugzilla #Recommends: bzr -# File conflict for /usr/bin/bugzilla: -Conflicts: python-bugzilla +# File conflict for /usr/bin/bugzilla with all lang flavours: +Conflicts: %{python_module bugzilla} BuildArch: noarch %python_subpackages