diff --git a/osc/OscConfigParser.py b/osc/OscConfigParser.py
index d7338358..519a4722 100644
--- a/osc/OscConfigParser.py
+++ b/osc/OscConfigParser.py
@@ -114,7 +114,7 @@ class SectionLine(Line):
raise configparser.Error('value and line are mutually exclusive')
if value is not None:
- line = '%s%s%s' % (optname, sep, value)
+ line = f'{optname}{sep}{value}'
opt = self._find(optname)
if opt:
opt.format(line)
@@ -253,10 +253,10 @@ class OscConfigParser(configparser.ConfigParser):
#cursect[optname] = "%s\n%s" % (cursect[optname], value)
#self.set(cursect, optname, "%s\n%s" % (self.get(cursect, optname), value))
if cursect == configparser.DEFAULTSECT:
- self._defaults[optname] = "%s\n%s" % (self._defaults[optname], value)
+ self._defaults[optname] = f"{self._defaults[optname]}\n{value}"
else:
# use the raw value here (original version uses raw=False)
- self._sections[cursect]._find(optname).value = '%s\n%s' % (self.get(cursect, optname, raw=True), value)
+ self._sections[cursect]._find(optname).value = f'{self.get(cursect, optname, raw=True)}\n{value}'
# a section header or option header?
else:
# is it a section header?
@@ -342,7 +342,7 @@ class OscConfigParser(configparser.ConfigParser):
first = False
else:
ret.append('')
- ret.append('[%s]' % line.name)
+ ret.append(f'[{line.name}]')
for sline in line._lines:
if sline.name == '__name__':
continue
diff --git a/osc/babysitter.py b/osc/babysitter.py
index c4faed28..4129aea2 100644
--- a/osc/babysitter.py
+++ b/osc/babysitter.py
@@ -158,7 +158,7 @@ def run(prg, argv=None):
print(e, file=sys.stderr)
return 2
except oscerr.ExtRuntimeError as e:
- print(e.file + ':', e.msg, file=sys.stderr)
+ print(f"{e.file}:", e.msg, file=sys.stderr)
except oscerr.ServiceRuntimeError as e:
print(e.msg, file=sys.stderr)
except oscerr.WorkingCopyOutdated as e:
diff --git a/osc/checker.py b/osc/checker.py
index 347690ba..10a48bec 100644
--- a/osc/checker.py
+++ b/osc/checker.py
@@ -11,7 +11,7 @@ class KeyError(Exception):
self.key = key
def __str__(self):
- return '' + self.key + ' :' + ' '.join(self.args)
+ return f"{self.key} :{' '.join(self.args)}"
class Checker:
diff --git a/osc/cmdln.py b/osc/cmdln.py
index 3555d334..e3fafd7b 100644
--- a/osc/cmdln.py
+++ b/osc/cmdln.py
@@ -241,7 +241,7 @@ class Cmdln:
self.options, self.args = self.argparser.parse_known_args(argv[1:])
unrecognized = [i for i in self.args if i.startswith("-")]
if unrecognized:
- self.argparser.error(f"unrecognized arguments: " + " ".join(unrecognized))
+ self.argparser.error(f"unrecognized arguments: {' '.join(unrecognized)}")
self.post_argparse()
@@ -257,7 +257,7 @@ class Cmdln:
if arg_names == ["subcmd", "opts"]:
# positional args specified manually via @cmdln.option
if self.args:
- self.argparser.error(f"unrecognized arguments: " + " ".join(self.args))
+ self.argparser.error(f"unrecognized arguments: {' '.join(self.args)}")
cmd(self.options.command, self.options)
elif arg_names == ["subcmd", "opts", "args"]:
# positional args are the remaining (unrecognized) args
diff --git a/osc/commandline.py b/osc/commandline.py
index 1c85504d..f488794e 100644
--- a/osc/commandline.py
+++ b/osc/commandline.py
@@ -1088,7 +1088,7 @@ class Osc(cmdln.Cmdln):
override_verbose=self.options.verbose)
except oscerr.NoConfigfile as e:
print(e.msg, file=sys.stderr)
- print('Creating osc configuration file %s ...' % e.file, file=sys.stderr)
+ print(f'Creating osc configuration file {e.file} ...', file=sys.stderr)
conf.interactive_config_setup(e.file, self.options.apiurl)
print('done', file=sys.stderr)
self.post_argparse()
@@ -1171,21 +1171,21 @@ class Osc(cmdln.Cmdln):
if scm_url:
if package:
Package.init_package(apiurl, project, package, Path.cwd(), scm_url=scm_url)
- print('Initializing %s (Project: %s, Package: %s) as git repository' % (Path.cwd(), project, package))
+ print(f'Initializing {Path.cwd()} (Project: {project}, Package: {package}) as git repository')
else:
Project.init_project(apiurl, Path.cwd(), project, conf.config['do_package_tracking'],
getPackageList=False, scm_url=scm_url)
- print('Initializing %s (Project: %s) as scm repository' % (Path.cwd(), project))
+ print(f'Initializing {Path.cwd()} (Project: {project}) as scm repository')
return
if not package:
Project.init_project(apiurl, Path.cwd(), project, conf.config['do_package_tracking'],
getPackageList=False)
- print('Initializing %s (Project: %s)' % (Path.cwd(), project))
+ print(f'Initializing {Path.cwd()} (Project: {project})')
else:
Package.init_package(apiurl, project, package, Path.cwd())
store_write_string(Path.cwd(), '_files', show_files_meta(apiurl, project, package) + b'\n')
- print('Initializing %s (Project: %s, Package: %s)' % (Path.cwd(), project, package))
+ print(f'Initializing {Path.cwd()} (Project: {project}, Package: {package})')
@cmdln.alias('ls')
@cmdln.alias('ll')
@@ -1275,7 +1275,7 @@ class Osc(cmdln.Cmdln):
if opts.binaries:
if opts.repo:
if opts.repo != args[2]:
- raise oscerr.WrongArgs("conflicting repos specified ('%s' vs '%s')" % (opts.repo, args[2]))
+ raise oscerr.WrongArgs(f"conflicting repos specified ('{opts.repo}' vs '{args[2]}')")
else:
opts.repo = args[2]
else:
@@ -1286,7 +1286,7 @@ class Osc(cmdln.Cmdln):
raise oscerr.WrongArgs('Too many arguments')
if opts.arch:
if opts.arch != args[3]:
- raise oscerr.WrongArgs("conflicting archs specified ('%s' vs '%s')" % (opts.arch, args[3]))
+ raise oscerr.WrongArgs(f"conflicting archs specified ('{opts.arch}' vs '{args[3]}')")
else:
opts.arch = args[3]
@@ -1330,7 +1330,7 @@ class Osc(cmdln.Cmdln):
for result in results:
indent = ''
if len(results) > 1:
- print('%s/%s' % (result[0].name, result[0].arch))
+ print(f'{result[0].name}/{result[0].arch}')
indent = ' '
if opts.verbose:
@@ -1393,12 +1393,12 @@ class Osc(cmdln.Cmdln):
raise oscerr.LinkExpandError(project, package, li.error)
project, package, rev = li.project, li.package, li.rev
if not revision_is_empty(rev):
- print('# -> %s %s (%s)' % (project, package, rev))
+ print(f'# -> {project} {package} ({rev})')
else:
- print('# -> %s %s (latest)' % (project, package))
+ print(f'# -> {project} {package} (latest)')
opts.expand = True
if fname and print_not_found:
- print('file \'%s\' does not exist' % fname)
+ print(f'file \'{fname}\' does not exist')
return 1
@cmdln.option('--extend-package-names', default=False, action="store_true",
@@ -2046,7 +2046,7 @@ class Osc(cmdln.Cmdln):
try:
f = open(opts.file).read()
except:
- sys.exit('could not open file \'%s\'.' % opts.file)
+ sys.exit(f'could not open file \'{opts.file}\'.')
if cmd == 'prj':
edit_meta(metatype='prj',
@@ -2191,7 +2191,7 @@ class Osc(cmdln.Cmdln):
try:
opts.message = open(opts.file).read()
except:
- sys.exit('could not open file \'%s\'.' % opts.file)
+ sys.exit(f'could not open file \'{opts.file}\'.')
myreqs = []
if opts.supersede:
@@ -2252,13 +2252,13 @@ class Osc(cmdln.Cmdln):
actionxml = ""
options_block = ""
if src_update:
- options_block += """%s""" % (src_update)
+ options_block += f"""{src_update}"""
if opts.update_link:
options_block + """true """
options_block += ""
target_prj_block = ""
if target_project is not None:
- target_prj_block = """""" % target_project
+ target_prj_block = f""""""
s = """ %s %s """ % \
(project, target_prj_block, options_block)
actionxml += s
@@ -2290,7 +2290,7 @@ class Osc(cmdln.Cmdln):
if len(myreqs) > 0:
for req in myreqs:
change_request_state(apiurl, str(req), 'superseded',
- 'superseded by %s' % sr_ids[0], sr_ids[0])
+ f'superseded by {sr_ids[0]}', sr_ids[0])
sys.exit('Successfully finished')
@@ -2300,8 +2300,8 @@ class Osc(cmdln.Cmdln):
src_project = p.prjname
src_package = p.name
if p.apiurl != apiurl:
- print('The apiurl for the working copy of this package is %s' % p.apiurl)
- print('You cannot use this command with the -A %s option.' % self.options.apiurl)
+ print(f'The apiurl for the working copy of this package is {p.apiurl}')
+ print(f'You cannot use this command with the -A {self.options.apiurl} option.')
sys.exit(1)
apiurl = p.apiurl
if len(args) == 0 and p.islink():
@@ -2438,7 +2438,7 @@ Please submit there instead, or use --nodevelproject to force direct submission.
if supersede_existing:
for req in reqs:
change_request_state(apiurl, req.reqid, 'superseded',
- 'superseded by %s' % result, result)
+ f'superseded by {result}', result)
if opts.supersede:
change_request_state(apiurl, opts.supersede, 'superseded',
@@ -2588,8 +2588,8 @@ Please submit there instead, or use --nodevelproject to force direct submission.
package = ""
if len(args) > 1:
- package = """package="%s" """ % (args[1])
- actionxml = """ """ % (args[0], package)
+ package = f"""package="{args[1]}" """
+ actionxml = f""" """
return actionxml
def _changedevel_request(self, args, opts):
@@ -2701,7 +2701,7 @@ Please submit there instead, or use --nodevelproject to force direct submission.
project = self._process_project_name(args[1])
package = ""
if len(args) > 2:
- package = """package="%s" """ % (args[2])
+ package = f"""package="{args[2]}" """
if user.startswith('group:'):
group = user.replace('group:', '')
@@ -2770,7 +2770,7 @@ Please submit there instead, or use --nodevelproject to force direct submission.
options_block = ""
if src_update:
- options_block = """%s """ % (src_update)
+ options_block = f"""{src_update} """
args = slash_split(args)
@@ -2814,7 +2814,7 @@ Please submit there instead, or use --nodevelproject to force direct submission.
rid = root.get('id')
for srid in supersede:
change_request_state(apiurl, srid, 'superseded',
- 'superseded by %s' % rid, rid)
+ f'superseded by {rid}', rid)
return rid
@cmdln.option('-m', '--message', metavar='TEXT',
@@ -2954,7 +2954,7 @@ Please submit there instead, or use --nodevelproject to force direct submission.
% (package, project))
else:
footer = textwrap.TextWrapper(width=66).fill(
- 'please explain why you like to delete project %s' % project)
+ f'please explain why you like to delete project {project}')
opts.message = edit_message(footer)
r = Request()
@@ -3245,7 +3245,7 @@ Please submit there instead, or use --nodevelproject to force direct submission.
# clone all packages from a given request
if cmd in ['clone']:
# should we force a message?
- print('Cloned packages are available in project: %s' % clone_request(apiurl, reqid, opts.message))
+ print(f'Cloned packages are available in project: {clone_request(apiurl, reqid, opts.message)}')
# approve request
elif cmd == 'approve' or cmd == 'cancelapproval':
@@ -3295,7 +3295,7 @@ Please submit there instead, or use --nodevelproject to force direct submission.
else:
for s in state_list:
if s != 'all' and s not in states:
- raise oscerr.WrongArgs('Unknown state \'%s\', try one of %s' % (s, ','.join(states)))
+ raise oscerr.WrongArgs(f"Unknown state '{s}', try one of {','.join(states)}")
if opts.mine:
who = conf.get_apiurl_usr(apiurl)
if opts.user:
@@ -3396,7 +3396,7 @@ Please submit there instead, or use --nodevelproject to force direct submission.
print(result.reqid, ": ", end=' ')
r = change_request_state(apiurl,
result.reqid, 'accepted', opts.message or '', force=opts.force)
- print('Result of change request state: %s' % r)
+ print(f'Result of change request state: {r}')
else:
print('Aborted...', file=sys.stderr)
raise oscerr.UserAbort()
@@ -3429,7 +3429,7 @@ Please submit there instead, or use --nodevelproject to force direct submission.
raise oscerr.WrongOptions('\'--source-buildstatus\' not possible '
'(request has no \'submit\' actions)')
for action in sr_actions:
- print('Buildstatus for \'%s/%s\':' % (action.src_project, action.src_package))
+ print(f'Buildstatus for \'{action.src_project}/{action.src_package}\':')
print('\n'.join(get_results(apiurl, action.src_project, action.src_package)))
if opts.diff:
diff = b''
@@ -3487,13 +3487,13 @@ Please submit there instead, or use --nodevelproject to force direct submission.
body = e.read()
if e.code in [403]:
if review.by_user:
- print('No permission on review by user %s:' % review.by_user)
+ print(f'No permission on review by user {review.by_user}:')
if review.by_group:
- print('No permission on review by group %s' % review.by_group)
+ print(f'No permission on review by group {review.by_group}')
if review.by_package:
- print('No permission on review by package %s / %s' % (review.by_project, review.by_package))
+ print(f'No permission on review by package {review.by_project} / {review.by_package}')
elif review.by_project:
- print('No permission on review by project %s' % review.by_project)
+ print(f'No permission on review by project {review.by_project}')
print(e, file=sys.stderr)
else:
print('Request is closed, please reopen the request first before changing any reviews.')
@@ -3518,7 +3518,7 @@ Please submit there instead, or use --nodevelproject to force direct submission.
try:
r = change_request_state(apiurl,
reqid, state_map[cmd], opts.message or '', supersed=supersedid, force=opts.force, keep_packages_locked=opts.keep_packages_locked)
- print('Result of change request state: %s' % r)
+ print(f'Result of change request state: {r}')
except HTTPError as e:
print(e, file=sys.stderr)
details = e.hdrs.get('X-Opensuse-Errorcode')
@@ -3544,7 +3544,7 @@ Please submit there instead, or use --nodevelproject to force direct submission.
sr_actions = rq.get_actions('submit')
for action in sr_actions:
u = makeurl(apiurl, ['/search/package'], {
- 'match': "([devel[@project='%s' and @package='%s']])" % (action.tgt_project, action.tgt_package)
+ 'match': f"([devel[@project='{action.tgt_project}' and @package='{action.tgt_package}']])"
})
f = http_GET(u)
root = ET.parse(f).getroot()
@@ -3564,9 +3564,9 @@ Please submit there instead, or use --nodevelproject to force direct submission.
links_to_package = link_node.get('package') or package
except HTTPError as e:
if e.code != 404:
- print('Cannot get list of files for %s/%s: %s' % (project, package, e), file=sys.stderr)
+ print(f'Cannot get list of files for {project}/{package}: {e}', file=sys.stderr)
except SyntaxError as e:
- print('Cannot parse list of files for %s/%s: %s' % (project, package, e), file=sys.stderr)
+ print(f'Cannot parse list of files for {project}/{package}: {e}', file=sys.stderr)
if links_to_project == action.tgt_project and links_to_package == action.tgt_package:
# links to my request target anyway, no need to forward submit
continue
@@ -3578,14 +3578,14 @@ Please submit there instead, or use --nodevelproject to force direct submission.
if repl.lower() == 'y' or repl == '':
(supersede, reqs) = check_existing_requests(apiurl, action.tgt_project, action.tgt_package,
project, package)
- msg = "%s (forwarded request %s from %s)" % (rq.description, reqid, rq.creator)
+ msg = f"{rq.description} (forwarded request {reqid} from {rq.creator})"
rid = create_submit_request(apiurl, action.tgt_project, action.tgt_package,
project, package, msg)
print(msg)
print("New request #", rid)
for req in reqs:
change_request_state(apiurl, req.reqid, 'superseded',
- 'superseded by %s' % rid, rid)
+ f'superseded by {rid}', rid)
@cmdln.option('-r', '--revision', metavar='rev',
help='use the specified revision.')
@@ -3712,7 +3712,7 @@ Please submit there instead, or use --nodevelproject to force direct submission.
else:
raise oscerr.LinkExpandError(project, package, li.error)
elif not li.islink():
- print('package \'%s/%s\' is no link' % (project, package), file=sys.stderr)
+ print(f'package \'{project}/{package}\' is no link', file=sys.stderr)
else:
raise e
@@ -3828,7 +3828,7 @@ Please submit there instead, or use --nodevelproject to force direct submission.
for pair in opts.map_repo.split(','):
src_tgt = pair.split('=')
if len(src_tgt) != 2:
- raise oscerr.WrongOptions('map "%s" must be SRC=TARGET[,SRC=TARGET]' % opts.map_repo)
+ raise oscerr.WrongOptions(f'map "{opts.map_repo}" must be SRC=TARGET[,SRC=TARGET]')
repo_map[src_tgt[0]] = src_tgt[1]
aggregate_pac(src_project, src_package, tgt_project, tgt_package, repo_map, opts.disable_publish, opts.nosources)
@@ -3895,7 +3895,7 @@ Please submit there instead, or use --nodevelproject to force direct submission.
comment = opts.message
else:
src_rev = rev or show_upstream_rev(src_apiurl, src_project, src_package)
- comment = 'osc copypac from project:%s package:%s revision:%s' % (src_project, src_package, src_rev)
+ comment = f'osc copypac from project:{src_project} package:{src_package} revision:{src_rev}'
if opts.keep_link:
comment += ", using keep-link"
if opts.expand:
@@ -4053,14 +4053,14 @@ Please submit there instead, or use --nodevelproject to force direct submission.
if len(args) == 1:
target_project = self._process_project_name(args[0])
else:
- xpath = 'attribute/@name = \'%s\'' % maintenance_attribute
+ xpath = f'attribute/@name = \'{maintenance_attribute}\''
res = search(apiurl, project_id=xpath)
root = res['project_id']
project = root.find('project')
if project is None:
sys.exit('Unable to find defined OBS:MaintenanceProject project on server.')
target_project = project.get('name')
- print('Using target project \'%s\'' % target_project)
+ print(f'Using target project \'{target_project}\'')
query = {'cmd': 'createmaintenanceincident'}
if opts.noaccess:
@@ -4155,7 +4155,7 @@ Please submit there instead, or use --nodevelproject to force direct submission.
if opts.cleanup:
opt_sourceupdate = 'cleanup'
if not opts.no_cleanup:
- default_branch = 'home:%s:branches:' % (conf.get_apiurl_usr(apiurl))
+ default_branch = f'home:{conf.get_apiurl_usr(apiurl)}:branches:'
if source_project.startswith(default_branch):
opt_sourceupdate = 'cleanup'
@@ -4165,7 +4165,7 @@ Please submit there instead, or use --nodevelproject to force direct submission.
if opts.incident_project:
target_project = opts.incident_project
else:
- xpath = 'attribute/@name = \'%s\'' % maintenance_attribute
+ xpath = f'attribute/@name = \'{maintenance_attribute}\''
res = search(apiurl, project_id=xpath)
root = res['project_id']
project = root.find('project')
@@ -4176,8 +4176,8 @@ Please submit there instead, or use --nodevelproject to force direct submission.
target_project += ":" + opts.incident
release_in = ''
if release_project is not None:
- release_in = '. (release in \'%s\')' % release_project
- print('Using target project \'%s\'%s' % (target_project, release_in))
+ release_in = f'. (release in \'{release_project}\')'
+ print(f'Using target project \'{target_project}\'{release_in}')
if not opts.message:
opts.message = edit_message()
@@ -4200,7 +4200,7 @@ Please submit there instead, or use --nodevelproject to force direct submission.
if supersede_existing:
for req in reqs:
change_request_state(apiurl, req.reqid, 'superseded',
- 'superseded by %s' % r.reqid, r.reqid)
+ f'superseded by {r.reqid}', r.reqid)
if opts.supersede:
change_request_state(apiurl, opts.supersede, 'superseded',
@@ -4278,21 +4278,21 @@ Please submit there instead, or use --nodevelproject to force direct submission.
if opts.dryrun:
for r in result.findall('package'):
- line = "%s/%s" % (r.get('project'), r.get('package'))
+ line = f"{r.get('project')}/{r.get('package')}"
if opts.version:
sr = get_source_rev(apiurl, r.get('project'), r.get('package'))
version = sr.get('version')
if not version or version == 'unknown':
version = 'unknown'
- line = line + (' (version: %s)' % version)
+ line = line + f' (version: {version})'
for d in r.findall('devel'):
- line += " using sources from %s/%s" % (d.get('project'), d.get('package'))
+ line += f" using sources from {d.get('project')}/{d.get('package')}"
print(line)
return
apiopt = ''
if conf.get_configParser().get("general", "apiurl", fallback=None) != apiurl:
- apiopt = '-A %s ' % apiurl
+ apiopt = f'-A {apiurl} '
print('A working copy of the maintenance branch can be checked out with:\n\n'
'osc %sco %s'
% (apiopt, result))
@@ -4381,7 +4381,7 @@ Please submit there instead, or use --nodevelproject to force direct submission.
if subcmd in ('getpac', 'bco') and len(args) == 1:
def_p = find_default_project(self.get_api_url(), args[0])
- print('defaulting to %s/%s' % (def_p, args[0]), file=sys.stderr)
+ print(f'defaulting to {def_p}/{args[0]}', file=sys.stderr)
# python has no args.unshift ???
args = [def_p, args[0]]
@@ -4393,7 +4393,7 @@ Please submit there instead, or use --nodevelproject to force direct submission.
apiurl = self.get_api_url()
- expected = 'home:%s:branches:%s' % (conf.get_apiurl_usr(apiurl), args[0])
+ expected = f'home:{conf.get_apiurl_usr(apiurl)}:branches:{args[0]}'
if len(args) >= 3:
expected = tproject = self._process_project_name(args[2])
if len(args) >= 4:
@@ -4434,7 +4434,7 @@ Please submit there instead, or use --nodevelproject to force direct submission.
disable_build=opts.disable_build)
if exists:
- print('Using existing branch project: %s' % targetprj, file=sys.stderr)
+ print(f'Using existing branch project: {targetprj}', file=sys.stderr)
devloc = None
if not exists and (srcprj != self._process_project_name(args[0]) or srcpkg != args[1]):
@@ -4463,7 +4463,7 @@ Please submit there instead, or use --nodevelproject to force direct submission.
else:
apiopt = ''
if conf.get_configParser().get("general", "apiurl", fallback=None) != apiurl:
- apiopt = '-A %s ' % apiurl
+ apiopt = f'-A {apiurl} '
print('A working copy of the branched package can be checked out with:\n\n'
'osc %sco %s/%s'
% (apiopt, targetprj, package))
@@ -4671,7 +4671,7 @@ Please submit there instead, or use --nodevelproject to force direct submission.
if pacs:
print("diff working copy against last committed version\n")
else:
- print("diff committed package against linked revision %s\n" % baserev)
+ print(f"diff committed package against linked revision {baserev}\n")
run_pager(
highlight_diff(
server_diff(
@@ -4701,7 +4701,7 @@ Please submit there instead, or use --nodevelproject to force direct submission.
else:
return
except:
- print('Revision \'%s\' not an integer' % opts.change, file=sys.stderr)
+ print(f'Revision \'{opts.change}\' not an integer', file=sys.stderr)
return
else:
rev1, rev2 = parseRevisionOption(opts.revision)
@@ -4792,7 +4792,7 @@ Please submit there instead, or use --nodevelproject to force direct submission.
else:
return
except:
- print('Revision \'%s\' not an integer' % opts.change, file=sys.stderr)
+ print(f'Revision \'{opts.change}\' not an integer', file=sys.stderr)
return
else:
if opts.revision:
@@ -4811,7 +4811,7 @@ Please submit there instead, or use --nodevelproject to force direct submission.
run_pager(highlight_diff(rdiff))
def _pdiff_raise_non_existing_package(self, project, package, msg=None):
- raise oscerr.PackageMissing(project, package, msg or '%s/%s does not exist.' % (project, package))
+ raise oscerr.PackageMissing(project, package, msg or f'{project}/{package} does not exist.')
def _pdiff_package_exists(self, apiurl, project, package):
try:
@@ -4819,7 +4819,7 @@ Please submit there instead, or use --nodevelproject to force direct submission.
return True
except HTTPError as e:
if e.code != 404:
- print('Cannot check that %s/%s exists: %s' % (project, package, e), file=sys.stderr)
+ print(f'Cannot check that {project}/{package} exists: {e}', file=sys.stderr)
return False
def _pdiff_guess_parent(self, apiurl, project, package, check_exists_first=False):
@@ -4848,7 +4848,7 @@ Please submit there instead, or use --nodevelproject to force direct submission.
except HTTPError as e:
return (None, None)
except SyntaxError as e:
- print('Cannot parse %s/%s/_link: %s' % (project, package, e), file=sys.stderr)
+ print(f'Cannot parse {project}/{package}/_link: {e}', file=sys.stderr)
return (None, None)
parent_project = root.get('project')
@@ -4866,10 +4866,10 @@ Please submit there instead, or use --nodevelproject to force direct submission.
root = ET.parse(file).getroot()
except HTTPError as e:
if e.code != 404:
- print('Cannot get list of files for %s/%s: %s' % (project, package, e), file=sys.stderr)
+ print(f'Cannot get list of files for {project}/{package}: {e}', file=sys.stderr)
return (None, None, None)
except SyntaxError as e:
- print('Cannot parse list of files for %s/%s: %s' % (project, package, e), file=sys.stderr)
+ print(f'Cannot parse list of files for {project}/{package}: {e}', file=sys.stderr)
return (None, None, None)
link_node = root.find('linkinfo')
@@ -4880,7 +4880,7 @@ Please submit there instead, or use --nodevelproject to force direct submission.
parent_package = link_node.get('package') or package
if parent_project is None:
- raise oscerr.APIError('%s/%s is a link with no parent?' % (project, package))
+ raise oscerr.APIError(f'{project}/{package} is a link with no parent?')
return (True, parent_project, parent_package)
@@ -4941,10 +4941,10 @@ Please submit there instead, or use --nodevelproject to force direct submission.
if not parent_project:
(parent_project, parent_package) = self._pdiff_guess_parent(apiurl, project, package, check_exists_first=False)
if parent_project and parent_package:
- print('Guessed that %s/%s is the parent package.' % (parent_project, parent_package))
+ print(f'Guessed that {parent_project}/{parent_package} is the parent package.')
if not parent_project or not parent_package:
- print('Cannot find a parent for %s/%s to diff against.' % (project, package), file=sys.stderr)
+ print(f'Cannot find a parent for {project}/{package} to diff against.', file=sys.stderr)
return 1
if not noparentok and not self._pdiff_package_exists(apiurl, parent_project, parent_package):
@@ -5081,7 +5081,7 @@ Please submit there instead, or use --nodevelproject to force direct submission.
if pkg not in new_packages:
if opts.show_not_in_new:
- print("old only: %s" % pkg)
+ print(f"old only: {pkg}")
continue
rdiff = server_diff_noex(
@@ -5092,13 +5092,13 @@ Please submit there instead, or use --nodevelproject to force direct submission.
)
if rdiff:
- print("differs: %s" % pkg)
+ print(f"differs: {pkg}")
self._prdiff_output_diff(opts, rdiff)
if opts.requests:
self._prdiff_output_matching_requests(opts, requests, newprj, pkg)
else:
- print("identical: %s" % pkg)
+ print(f"identical: {pkg}")
for pkg in new_packages:
if self._prdiff_skip_package(opts, pkg):
@@ -5106,7 +5106,7 @@ Please submit there instead, or use --nodevelproject to force direct submission.
if pkg not in old_packages:
if opts.show_not_in_old:
- print("new only: %s" % pkg)
+ print(f"new only: {pkg}")
def do_repourls(self, subcmd, opts, *args):
"""
@@ -5286,7 +5286,7 @@ Please submit there instead, or use --nodevelproject to force direct submission.
rev = "latest"
if not revision_is_empty(rev) and rev != "latest" and not checkRevision(project, package, rev):
- print('Revision \'%s\' does not exist' % rev, file=sys.stderr)
+ print(f'Revision \'{rev}\' does not exist', file=sys.stderr)
sys.exit(1)
if filename:
@@ -5314,7 +5314,7 @@ Please submit there instead, or use --nodevelproject to force direct submission.
chosen_output = opts.output_dir if opts.output_dir else project
prj_dir = Path(chosen_output.replace(':', sep))
if os.path.exists(prj_dir):
- sys.exit('osc: project directory \'%s\' already exists' % prj_dir)
+ sys.exit(f'osc: project directory \'{prj_dir}\' already exists')
# check if the project does exist (show_project_meta will throw an exception)
show_project_meta(apiurl, project)
@@ -5579,12 +5579,12 @@ Please submit there instead, or use --nodevelproject to force direct submission.
pattern = re.compile("No such file")
if "No such file" in e.msg:
editor = os.getenv('EDITOR', default=get_default_editor())
- print("Editor %s not found" % editor)
+ print(f"Editor {editor} not found")
return 1
print("ERROR: service run failed", e, file=sys.stderr)
return 1
except oscerr.PackageNotInstalled as e:
- print("ERROR: please install %s " % e.args, end='')
+ print(f"ERROR: please install {e.args} ", end='')
print("or use the --noservice option")
return 1
@@ -5601,7 +5601,7 @@ Please submit there instead, or use --nodevelproject to force direct submission.
try:
msg = open(opts.file).read()
except:
- sys.exit('could not open file \'%s\'.' % opts.file)
+ sys.exit(f'could not open file \'{opts.file}\'.')
skip_local_service_run = False
if not conf.config['local_service_run'] or opts.skip_local_service_run:
@@ -5789,7 +5789,7 @@ Please submit there instead, or use --nodevelproject to force direct submission.
if opts.revision and len(args) == 1:
rev, dummy = parseRevisionOption(opts.revision)
if not checkRevision(pacs[0].prjname, pacs[0].name, rev, pacs[0].apiurl):
- print('Revision \'%s\' does not exist' % rev, file=sys.stderr)
+ print(f'Revision \'{rev}\' does not exist', file=sys.stderr)
sys.exit(1)
if opts.expand_link or opts.unexpand_link:
meta = show_files_meta(pacs[0].apiurl, pacs[0].prjname,
@@ -5799,7 +5799,7 @@ Please submit there instead, or use --nodevelproject to force direct submission.
directory = ET.fromstring(meta)
li_node = directory.find('linkinfo')
if li_node is None:
- print('Revision \'%s\' is no link' % rev, file=sys.stderr)
+ print(f'Revision \'{rev}\' is no link', file=sys.stderr)
sys.exit(1)
li = Linkinfo()
li.read(li_node)
@@ -5818,7 +5818,7 @@ Please submit there instead, or use --nodevelproject to force direct submission.
for p in pacs:
if len(pacs) > 1:
- print('Updating %s' % p.name)
+ print(f'Updating {p.name}')
# this shouldn't be needed anymore with the new update mechanism
# an expand/unexpand update is treated like a normal update (there's nothing special)
@@ -5918,11 +5918,11 @@ Please submit there instead, or use --nodevelproject to force direct submission.
print(statfrmt('D', os.path.join(pathn, filename)))
continue
if state == '?':
- sys.exit('\'%s\' is not under version control' % filename)
+ sys.exit(f'\'{filename}\' is not under version control')
elif state in ('A', 'M') and not opts.force:
- sys.exit('\'%s\' has local modifications (use --force to remove this file)' % filename)
+ sys.exit(f'\'{filename}\' has local modifications (use --force to remove this file)')
elif state == 'S':
- sys.exit('\'%s\' is marked as skipped and no local file with this name exists' % filename)
+ sys.exit(f'\'{filename}\' is marked as skipped and no local file with this name exists')
def do_resolved(self, subcmd, opts, *args):
"""
@@ -5951,7 +5951,7 @@ Please submit there instead, or use --nodevelproject to force direct submission.
for p in pacs:
for filename in p.todo:
- print('Resolved conflicted state of "%s"' % filename)
+ print(f'Resolved conflicted state of "{filename}"')
p.clear_from_conflictlist(filename)
@cmdln.alias('dists')
@@ -5998,7 +5998,7 @@ Please submit there instead, or use --nodevelproject to force direct submission.
for filename in files:
if not opts.force:
- resp = raw_input("rm: remove source file `%s' from `%s/%s'? (yY|nN) " % (filename, project, package))
+ resp = raw_input(f"rm: remove source file `{filename}' from `{project}/{package}'? (yY|nN) ")
if resp not in ('y', 'Y'):
continue
try:
@@ -6439,7 +6439,7 @@ Please submit there instead, or use --nodevelproject to force direct submission.
offset = int(opts.offset)
logfile = os.path.join(buildroot, '.build.log')
if not os.path.isfile(logfile):
- raise oscerr.OscIOError(None, 'logfile \'%s\' does not exist' % logfile)
+ raise oscerr.OscIOError(None, f'logfile \'{logfile}\' does not exist')
f = open(logfile, 'rb')
f.seek(offset)
data = f.read(BUFSIZE)
@@ -6508,7 +6508,7 @@ Please submit there instead, or use --nodevelproject to force direct submission.
else:
reason = root.find('explain').text
triggertime = time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime(int(root.find('time').text)))
- print("%s (at %s)" % (reason, triggertime))
+ print(f"{reason} (at {triggertime})")
if reason == "meta change":
print("changed keys:")
for package in root.findall('packagechange'):
@@ -6681,7 +6681,7 @@ Please submit there instead, or use --nodevelproject to force direct submission.
if opts.prefer_pkgs and build_descr_data is None:
raise oscerr.WrongArgs('error: a build description is needed if \'--prefer-pkgs\' is used')
elif opts.prefer_pkgs:
- print('Scanning the following dirs for local packages: %s' % ', '.join(opts.prefer_pkgs))
+ print(f"Scanning the following dirs for local packages: {', '.join(opts.prefer_pkgs)}")
cpiodata = cpio.CpioWrite()
prefer_pkgs = osc_build.get_prefer_pkgs(opts.prefer_pkgs, arch,
os.path.splitext(build_descr)[1],
@@ -6938,7 +6938,7 @@ Please submit there instead, or use --nodevelproject to force direct submission.
apiurl = self.get_api_url()
repositories = list(get_repos_of_project(apiurl, project))
if not repositories:
- raise oscerr.WrongArgs('no repositories defined for project \'%s\'' % project)
+ raise oscerr.WrongArgs(f'no repositories defined for project \'{project}\'')
if alternative_project is None:
# only persist our own repos
Repo.tofile(repolistfile, repositories)
@@ -6961,10 +6961,10 @@ Please submit there instead, or use --nodevelproject to force direct submission.
raise oscerr.WrongArgs('please specify a repository')
if not noinit:
if arg_repository not in repo_names:
- raise oscerr.WrongArgs('%s is not a valid repository, use one of: %s' % (arg_repository, ', '.join(repo_names)))
+ raise oscerr.WrongArgs(f"{arg_repository} is not a valid repository, use one of: {', '.join(repo_names)}")
arches = [r.arch for r in repositories if r.name == arg_repository and r.arch]
if arches and arg_arch not in arches:
- raise oscerr.WrongArgs('%s is not a valid arch for the repository %s, use one of: %s' % (arg_arch, arg_repository, ', '.join(arches)))
+ raise oscerr.WrongArgs(f"{arg_arch} is not a valid arch for the repository {arg_repository}, use one of: {', '.join(arches)}")
# can be implemented using
# reduce(lambda x, y: x + y, (glob.glob(x) for x in ('*.spec', '*.dsc', '*.kiwi')))
@@ -6992,7 +6992,7 @@ Please submit there instead, or use --nodevelproject to force direct submission.
else:
queryconfig = '/usr/lib/build/queryconfig'
if noinit:
- bc_filename = '_buildconfig-%s-%s' % (arg_repository, arg_arch)
+ bc_filename = f'_buildconfig-{arg_repository}-{arg_arch}'
if is_package_dir('.'):
bc_filename = os.path.join(Path.cwd(), store, bc_filename)
else:
@@ -7020,17 +7020,17 @@ Please submit there instead, or use --nodevelproject to force direct submission.
else:
cands = [d for d in descr if d.endswith('.' + recipe)]
if len(cands) > 1:
- repo_cands = [d for d in cands if d == '%s-%s.%s' % (pac, arg_repository, recipe)]
+ repo_cands = [d for d in cands if d == f'{pac}-{arg_repository}.{recipe}']
if repo_cands:
cands = repo_cands
else:
- pac_cands = [d for d in cands if d == '%s.%s' % (pac, recipe)]
+ pac_cands = [d for d in cands if d == f'{pac}.{recipe}']
if pac_cands:
cands = pac_cands
if len(cands) == 1:
arg_descr = cands[0]
if not arg_descr:
- msg = 'Multiple build description files found: %s' % ', '.join(cands)
+ msg = f"Multiple build description files found: {', '.join(cands)}"
elif not ignore_descr:
msg = 'Missing argument: build description (for example a spec, dsc or kiwi file)'
try:
@@ -7238,7 +7238,7 @@ Please submit there instead, or use --nodevelproject to force direct submission.
# OSC_PACKAGECACHEDIR overrides the setting of packagecachedir.
"""
if which(conf.config['build-cmd']) is None:
- print('Error: build (\'%s\') command not found' % conf.config['build-cmd'], file=sys.stderr)
+ print(f"Error: build ('{conf.config['build-cmd']}') command not found", file=sys.stderr)
print('Install the build package from http://download.opensuse.org/repositories/openSUSE:/Tools/', file=sys.stderr)
return 1
@@ -7298,7 +7298,7 @@ Please submit there instead, or use --nodevelproject to force direct submission.
build_root = osc_build.calculate_build_root(apihost, prj, pac, repo, arch, user)
if opts.wipe and not opts.force:
# Confirm delete
- print("Really wipe '%s'? [y/N]: " % build_root, end="")
+ print(f"Really wipe '{build_root}'? [y/N]: ", end="")
choice = raw_input().lower()
if choice != 'y':
print('Aborting')
@@ -7308,7 +7308,7 @@ Please submit there instead, or use --nodevelproject to force direct submission.
build_args.append('--wipe')
sys.exit(osc_build.run_build(opts, *build_args))
elif subcmd in ('shell', 'chroot') or opts.shell:
- print('--shell in combination with build-type %s is experimental.' % vm_chroot)
+ print(f'--shell in combination with build-type {vm_chroot} is experimental.')
print('The semantics may change at any time!')
opts.shell = True
@@ -7330,14 +7330,14 @@ Please submit there instead, or use --nodevelproject to force direct submission.
if opts.keep_pkgs and not os.path.isdir(opts.keep_pkgs):
if os.path.exists(opts.keep_pkgs):
- raise oscerr.WrongOptions('Preferred save location \'%s\' is not a directory' % opts.keep_pkgs)
+ raise oscerr.WrongOptions(f'Preferred save location \'{opts.keep_pkgs}\' is not a directory')
else:
os.makedirs(opts.keep_pkgs)
if opts.prefer_pkgs:
for d in opts.prefer_pkgs:
if not os.path.isdir(d):
- raise oscerr.WrongOptions('Preferred package location \'%s\' is not a directory' % d)
+ raise oscerr.WrongOptions(f'Preferred package location \'{d}\' is not a directory')
if opts.offline and opts.preload:
raise oscerr.WrongOptions('--offline and --preload are mutually exclusive')
@@ -7353,7 +7353,7 @@ Please submit there instead, or use --nodevelproject to force direct submission.
if opts.preload:
opts.nopreinstallimage = True
- print('Building %s for %s/%s' % (args[2], args[0], args[1]))
+ print(f'Building {args[2]} for {args[0]}/{args[1]}')
if not opts.host:
return osc_build.main(self.get_api_url(), store, opts, args)
else:
@@ -7388,15 +7388,15 @@ Please submit there instead, or use --nodevelproject to force direct submission.
hostprefer = os.path.join(
hostpath,
basename,
- "%s__" % (long_name.replace('-', '_')),
+ f"{long_name.replace('-', '_')}__",
os.path.basename(os.path.abspath(pdir)))
hostargs.append(long_name)
hostargs.append(hostprefer)
rsync_prefer_cmd = ['rsync', '-az', '--delete', '-e', 'ssh',
pdir,
- "%s:%s" % (hostname, os.path.dirname(hostprefer))]
- print('Run: %s' % " ".join(rsync_prefer_cmd))
+ f"{hostname}:{os.path.dirname(hostprefer)}"]
+ print(f"Run: {' '.join(rsync_prefer_cmd)}")
ret = run_external(rsync_prefer_cmd[0], *rsync_prefer_cmd[1:])
if ret != 0:
return ret
@@ -7444,8 +7444,8 @@ Please submit there instead, or use --nodevelproject to force direct submission.
### run all commands ###
# 1.) rsync sources
- rsync_source_cmd = ['rsync', '-az', '--delete', '-e', 'ssh', cwd, "%s:%s" % (hostname, hostpath)]
- print('Run: %s' % " ".join(rsync_source_cmd))
+ rsync_source_cmd = ['rsync', '-az', '--delete', '-e', 'ssh', cwd, f"{hostname}:{hostpath}"]
+ print(f"Run: {' '.join(rsync_source_cmd)}")
ret = run_external(rsync_source_cmd[0], *rsync_source_cmd[1:])
if ret != 0:
return ret
@@ -7467,7 +7467,7 @@ Please submit there instead, or use --nodevelproject to force direct submission.
osc_cmd = "osc"
for var in ('OSC_SU_WRAPPER', 'OSC_BUILD_ROOT', 'OSC_PACKAGECACHEDIR'):
if os.getenv(var):
- osc_cmd = "%s=%s %s" % (var, os.getenv(var), osc_cmd)
+ osc_cmd = f"{var}={os.getenv(var)} {osc_cmd}"
ssh_cmd = \
['ssh', '-t', hostname,
@@ -7477,15 +7477,15 @@ Please submit there instead, or use --nodevelproject to force direct submission.
global_args=" ".join(hostglobalargs),
local_args=" ".join(hostargs))
]
- print('Run: %s' % " ".join(ssh_cmd))
+ print(f"Run: {' '.join(ssh_cmd)}")
build_ret = run_external(ssh_cmd[0], *ssh_cmd[1:])
if build_ret != 0:
return build_ret
# 4.) get keep-pkgs back
if opts.keep_pkgs:
- ret = rsync_keep_cmd = ['rsync', '-az', '-e', 'ssh', "%s:%s" % (hostname, hostkeep), opts.keep_pkgs]
- print('Run: %s' % " ".join(rsync_keep_cmd))
+ ret = rsync_keep_cmd = ['rsync', '-az', '-e', 'ssh', f"{hostname}:{hostkeep}", opts.keep_pkgs]
+ print(f"Run: {' '.join(rsync_keep_cmd)}")
ret = run_external(rsync_keep_cmd[0], *rsync_keep_cmd[1:])
if ret != 0:
return ret
@@ -7617,7 +7617,7 @@ Please submit there instead, or use --nodevelproject to force direct submission.
rev, rev_upper = parseRevisionOption(opts.revision)
if not revision_is_empty(rev) and not checkRevision(project, package, rev, apiurl, opts.meta):
- print('Revision \'%s\' does not exist' % rev, file=sys.stderr)
+ print(f'Revision \'{rev}\' does not exist', file=sys.stderr)
sys.exit(1)
format = 'text'
@@ -8060,7 +8060,7 @@ Please submit there instead, or use --nodevelproject to force direct submission.
repos = list(get_repos_of_project(apiurl, project))
if not [i for i in repos if repository == i.name]:
- self.print_repos(exc_msg='Invalid repository \'%s\'' % repository, project=project)
+ self.print_repos(exc_msg=f'Invalid repository \'{repository}\'', project=project)
arches = [architecture]
if architecture is None:
@@ -8082,7 +8082,7 @@ Please submit there instead, or use --nodevelproject to force direct submission.
# Set binary target directory and create if not existing
target_dir = os.path.normpath(opts.destdir)
if not os.path.isdir(target_dir):
- print('Creating directory "%s"' % target_dir)
+ print(f'Creating directory "{target_dir}"')
os.makedirs(target_dir, 0o755)
for arch in arches:
@@ -8106,14 +8106,14 @@ Please submit there instead, or use --nodevelproject to force direct submission.
if package_specified:
# if package is specified, download everything into the target dir
- fname = '%s/%s' % (target_dir, i.name)
+ fname = f'{target_dir}/{i.name}'
elif i.name.startswith("_") or i.name.endswith(".log"):
# download logs and metadata into subdirs
# to avoid overwriting them with files with indentical names
- fname = '%s/%s/%s' % (target_dir, pac, i.name)
+ fname = f'{target_dir}/{pac}/{i.name}'
else:
# always download packages into the target dir
- fname = '%s/%s' % (target_dir, i.name)
+ fname = f'{target_dir}/{i.name}'
if os.path.exists(fname):
st = os.stat(fname)
@@ -8214,7 +8214,7 @@ Please submit there instead, or use --nodevelproject to force direct submission.
print(r.list_view(), '\n')
return
elif type not in args_pkg:
- raise oscerr.WrongArgs("invalid type %s" % type)
+ raise oscerr.WrongArgs(f"invalid type {type}")
role_filter = ''
if opts.maintainer:
@@ -8228,7 +8228,7 @@ Please submit there instead, or use --nodevelproject to force direct submission.
if list_patchinfos:
u = makeurl(apiurl, ['/search/package'], {
- 'match': "([kind='patchinfo' and issue[@state='OPEN' and owner/@login='%s']])" % user
+ 'match': f"([kind='patchinfo' and issue[@state='OPEN' and owner/@login='{user}']])"
})
f = http_GET(u)
root = ET.parse(f).getroot()
@@ -8329,7 +8329,7 @@ Please submit there instead, or use --nodevelproject to force direct submission.
roles[i.get('name')] = [p.get('role') for p in i.findall('person') if p.get('userid') == user]
for i in res.get('package_id', res.get('package', dummy_elm)).findall('package'):
prj = i.get('project')
- roles['/'.join([prj, i.get('name')])] = [p.get('role') for p in i.findall('person') if p.get('userid') == user]
+ roles[f"{prj}/{i.get('name')}"] = [p.get('role') for p in i.findall('person') if p.get('userid') == user]
if prj not in request_todo or request_todo[prj] != []:
request_todo.setdefault(prj, []).append(i.get('name'))
else:
@@ -8345,14 +8345,14 @@ Please submit there instead, or use --nodevelproject to force direct submission.
print(" -> try also 'osc my sr' to see more.")
else:
for i in sorted(roles.keys()):
- out = '%s' % i
+ out = f'{i}'
prjpac = i.split('/')
if type in args_pkg and len(prjpac) == 1 and not opts.verbose:
continue
if opts.verbose:
- out = '%s (%s)' % (i, ', '.join(sorted(roles[i])))
+ out = f"{i} ({', '.join(sorted(roles[i]))})"
if len(prjpac) == 2:
- out = ' %s (%s)' % (prjpac[1], ', '.join(sorted(roles[i])))
+ out = f" {prjpac[1]} ({', '.join(sorted(roles[i]))})"
print(out)
@cmdln.option('--repos-baseurl', action='store_true',
@@ -8406,9 +8406,9 @@ Please submit there instead, or use --nodevelproject to force direct submission.
"""
def build_xpath(attr, what, substr=False):
if substr:
- return 'contains(%s, \'%s\')' % (attr, what)
+ return f'contains({attr}, \'{what}\')'
else:
- return '%s = \'%s\'' % (attr, what)
+ return f'{attr} = \'{what}\''
search_term = ''
if len(args) > 1:
@@ -8471,28 +8471,28 @@ Please submit there instead, or use --nodevelproject to force direct submission.
search_id = search_dict[search_type]
except KeyError:
search_type, search_id = ['person', 'userid']
- xpath = xpath_join(xpath, '%s/@%s = \'%s\'' % (search_type, search_id, search_term), inner=True)
- role_filter = '%s (%s)' % (search_term, search_type)
+ xpath = xpath_join(xpath, f'{search_type}/@{search_id} = \'{search_term}\'', inner=True)
+ role_filter = f'{search_term} ({search_type})'
role_filter_xpath = xpath
if opts.bugowner and not opts.maintainer:
- xpath = xpath_join(xpath, '%s/@role=\'bugowner\'' % search_type, op='and')
+ xpath = xpath_join(xpath, f'{search_type}/@role=\'bugowner\'', op='and')
role_filter = 'bugowner'
elif not opts.bugowner and opts.maintainer:
- xpath = xpath_join(xpath, '%s/@role=\'maintainer\'' % search_type, op='and')
+ xpath = xpath_join(xpath, f'{search_type}/@role=\'maintainer\'', op='and')
role_filter = 'maintainer'
if opts.limit_to_attribute:
- xpath = xpath_join(xpath, 'attribute/@name=\'%s\'' % opts.limit_to_attribute, op='and')
+ xpath = xpath_join(xpath, f'attribute/@name=\'{opts.limit_to_attribute}\'', op='and')
if opts.baseproject:
- xpath = xpath_join(xpath, 'path/@project=\'%s\'' % self._process_project_name(opts.baseproject), op='and')
+ xpath = xpath_join(xpath, f'path/@project=\'{self._process_project_name(opts.baseproject)}\'', op='and')
if opts.binaryversion:
m = re.match(r'(.+)-(.*?)$', opts.binaryversion)
if m:
if m.group(2) != '':
- xpath = xpath_join(xpath, '@versrel=\'%s\'' % opts.binaryversion, op='and')
+ xpath = xpath_join(xpath, f'@versrel=\'{opts.binaryversion}\'', op='and')
else:
- xpath = xpath_join(xpath, '@version=\'%s\'' % m.group(1), op='and')
+ xpath = xpath_join(xpath, f'@version=\'{m.group(1)}\'', op='and')
else:
- xpath = xpath_join(xpath, '@version=\'%s\'' % opts.binaryversion, op='and')
+ xpath = xpath_join(xpath, f'@version=\'{opts.binaryversion}\'', op='and')
if not xpath:
xpath = xpath_join(xpath, build_xpath('@name', search_term, opts.substring), inner=True)
@@ -8512,12 +8512,12 @@ Please submit there instead, or use --nodevelproject to force direct submission.
raise e
# backward compatibility: local role filtering
if opts.limit_to_attribute:
- role_filter_xpath = xpath_join(role_filter_xpath, 'attribute/@name=\'%s\'' % opts.limit_to_attribute, op='and')
+ role_filter_xpath = xpath_join(role_filter_xpath, f'attribute/@name=\'{opts.limit_to_attribute}\'', op='and')
what = {kind: role_filter_xpath for kind in what.keys()}
res = search(apiurl, **what)
filter_role(res, search_term, role_filter)
if role_filter:
- role_filter = '%s (%s)' % (search_term, role_filter)
+ role_filter = f'{search_term} ({role_filter})'
kind_map = {'published/binary/id': 'binary'}
for kind, root in res.items():
results = []
@@ -8566,13 +8566,13 @@ Please submit there instead, or use --nodevelproject to force direct submission.
if opts.repos_baseurl:
# FIXME: no hardcoded URL of instance
- result.append('http://download.opensuse.org/repositories/%s/' % project.replace(':', ':/'))
+ result.append(f"http://download.opensuse.org/repositories/{project.replace(':', ':/')}/")
if kind == 'published/binary/id':
result.append(node.get('filepath'))
results.append(result)
if not results:
- print('No matches found for \'%s\' in %ss' % (role_filter or search_term, kind))
+ print(f'No matches found for \'{role_filter or search_term}\' in {kind}s')
continue
# construct a sorted, flat list
# Sort by first column, follwed by second column if we have two columns, else sort by first.
@@ -8606,7 +8606,7 @@ Please submit there instead, or use --nodevelproject to force direct submission.
if not opts.csv:
if len(what.keys()) > 1:
print('#' * 68)
- print('matches for \'%s\' in %ss:\n' % (role_filter or search_term, kind))
+ print(f'matches for \'{role_filter or search_term}\' in {kind}s:\n')
for row in build_table(len(headline), results, headline, 2, csv=opts.csv):
print(row)
@@ -8650,7 +8650,7 @@ Please submit there instead, or use --nodevelproject to force direct submission.
if '://' in srpm:
if srpm.endswith('/'):
- print('%s is not a valid link. It must not end with /' % srpm)
+ print(f'{srpm} is not a valid link. It must not end with /')
sys.exit(1)
print('trying to fetch', srpm)
OscFileGrabber().urlgrab(srpm)
@@ -8658,7 +8658,7 @@ Please submit there instead, or use --nodevelproject to force direct submission.
srpm = os.path.abspath(srpm)
if not os.path.isfile(srpm):
- print('file \'%s\' does not exist' % srpm, file=sys.stderr)
+ print(f'file \'{srpm}\' does not exist', file=sys.stderr)
sys.exit(1)
if opts.project:
@@ -8667,7 +8667,7 @@ Please submit there instead, or use --nodevelproject to force direct submission.
project_dir = str(Path.cwd())
if not is_project_dir(project_dir):
- raise oscerr.WrongArgs("'%s' is no project working copy" % project_dir)
+ raise oscerr.WrongArgs(f"'{project_dir}' is no project working copy")
if conf.config['do_package_tracking']:
project = Project(project_dir)
@@ -8725,7 +8725,7 @@ Please submit there instead, or use --nodevelproject to force direct submission.
p = Package(os.path.join(project_dir, pac))
if len(p.filenamelist) == 0 and opts.commit:
print('Adding files to working copy...')
- addFiles(glob.glob('%s/*' % os.path.join(project_dir, pac)))
+ addFiles(glob.glob(f'{os.path.join(project_dir, pac)}/*'))
if conf.config['do_package_tracking']:
project.commit((pac, ))
else:
@@ -8742,10 +8742,10 @@ Please submit there instead, or use --nodevelproject to force direct submission.
else:
print('No files were committed to the server. Please '
'commit them manually.')
- print('Package \'%s\' only imported locally' % pac)
+ print(f'Package \'{pac}\' only imported locally')
sys.exit(1)
- print('Package \'%s\' imported successfully' % pac)
+ print(f'Package \'{pac}\' imported successfully')
@cmdln.option('-X', '-m', '--method', default='GET', metavar='HTTP_METHOD',
choices=('HEAD', 'GET', 'PUT', 'POST', 'DELETE'),
@@ -9031,7 +9031,7 @@ Please submit there instead, or use --nodevelproject to force direct submission.
prj = d.get('project', prj)
pac = d.get('package', pac)
if opts.verbose:
- print("Following to the development space: %s/%s" % (prj, pac))
+ print(f"Following to the development space: {prj}/{pac}")
m = show_package_meta(apiurl, prj, pac)
metaroot = ET.fromstring(b''.join(m))
if not metaroot.findall('person') and not metaroot.findall('group'):
@@ -9077,7 +9077,7 @@ Please submit there instead, or use --nodevelproject to force direct submission.
definingpackage = maintainers.get("package")
indent = " "
if definingpackage:
- print("Defined in package: %s/%s " % (definingproject, definingpackage))
+ print(f"Defined in package: {definingproject}/{definingpackage} ")
else:
print("Defined in project: ", definingproject)
@@ -9087,9 +9087,9 @@ Please submit there instead, or use --nodevelproject to force direct submission.
if opts.bugowner and not maintainers.get(role, []):
role = 'maintainer'
if pac:
- print("%s%s of %s/%s : " % (indent, role, prj, pac))
+ print(f"{indent}{role} of {prj}/{pac} : ")
else:
- print("%s%s of %s : " % (indent, role, prj))
+ print(f"{indent}{role} of {prj} : ")
if opts.email:
emails = []
for maintainer in maintainers.get(role, []):
@@ -9104,7 +9104,7 @@ Please submit there instead, or use --nodevelproject to force direct submission.
user = get_maintainer_data(apiurl, maintainer, verbose=True)
userdata.append(user[0])
if user[1] != '-':
- userdata.append("%s <%s>" % (user[1], user[2]))
+ userdata.append(f"{user[1]} <{user[2]}>")
else:
userdata.append(user[2])
for row in build_table(2, userdata, None, 3):
@@ -9131,7 +9131,7 @@ Please submit there instead, or use --nodevelproject to force direct submission.
for name in usernames:
user = get_user_data(apiurl, name, 'login', 'realname', 'email')
if len(user) == 3:
- print("%s: \"%s\" <%s>" % (user[0], user[1], user[2]))
+ print(f"{user[0]}: \"{user[1]}\" <{user[2]}>")
@cmdln.name("create-pbuild-config")
@cmdln.alias('cpc')
@@ -9445,7 +9445,7 @@ Please submit there instead, or use --nodevelproject to force direct submission.
pac.write_deletelist()
pac.write_conflictlist()
print()
- print('Please change into the \'%s\' directory,' % destdir)
+ print(f'Please change into the \'{destdir}\' directory,')
print('fix the conflicts (files marked with \'C\' above),')
print('run \'osc resolved ...\', and commit the changes.')
@@ -9653,7 +9653,7 @@ Please submit there instead, or use --nodevelproject to force direct submission.
l = prj.rsplit(':', 1)
# try key from parent project
if not opts.notraverse and len(l) > 1 and l[0] and l[1] and e.code == 404:
- print('%s has no key, trying %s' % (prj, l[0]))
+ print(f'{prj} has no key, trying {l[0]}')
prj = l[0]
else:
raise
@@ -9717,7 +9717,7 @@ Please submit there instead, or use --nodevelproject to force direct submission.
return 1
cmd_list = ['/usr/bin/vc']
elif which(cmd_list[0]) is None:
- print('Error: vc (\'%s\') command not found' % cmd_list[0], file=sys.stderr)
+ print(f'Error: vc (\'{cmd_list[0]}\') command not found', file=sys.stderr)
print('Install the build package from http://download.opensuse.org/repositories/openSUSE:/Tools/', file=sys.stderr)
return 1
@@ -9737,7 +9737,7 @@ Please submit there instead, or use --nodevelproject to force direct submission.
if len(args) > 1:
raise oscerr.WrongOptions('--file and file_with_comment are mutually exclusive')
elif not os.path.isfile(opts.file):
- raise oscerr.WrongOptions('\'%s\': is no file' % opts.file)
+ raise oscerr.WrongOptions(f'\'{opts.file}\': is no file')
args = list(args)
if not args:
args.append('')
@@ -9765,17 +9765,17 @@ Please submit there instead, or use --nodevelproject to force direct submission.
dest = opts.dest
if not os.path.isfile(source):
- raise oscerr.WrongArgs("Source file '%s' does not exist or is not a file" % source)
+ raise oscerr.WrongArgs(f"Source file '{source}' does not exist or is not a file")
if not opts.force and os.path.isfile(dest):
- raise oscerr.WrongArgs("Dest file '%s' already exists" % dest)
+ raise oscerr.WrongArgs(f"Dest file '{dest}' already exists")
if os.path.isdir(dest):
dest = os.path.join(dest, os.path.basename(source))
src_pkg = Package(source)
tgt_pkg = Package(dest)
if not src_pkg:
- raise oscerr.NoWorkingCopy("Error: \"%s\" is not located in an osc working copy." % os.path.abspath(source))
+ raise oscerr.NoWorkingCopy(f"Error: \"{os.path.abspath(source)}\" is not located in an osc working copy.")
if not tgt_pkg:
- raise oscerr.NoWorkingCopy("Error: \"%s\" does not point to an osc working copy." % os.path.abspath(dest))
+ raise oscerr.NoWorkingCopy(f"Error: \"{os.path.abspath(dest)}\" does not point to an osc working copy.")
os.rename(source, dest)
try:
@@ -9832,7 +9832,7 @@ Please submit there instead, or use --nodevelproject to force direct submission.
elif opts.dump or opts.dump_full:
cp = conf.get_configParser(conf.config['conffile'])
for sect in cp.sections():
- print('[%s]' % sect)
+ print(f'[{sect}]')
for opt in sorted(cp.options(sect)):
if sect == 'general' and opt in conf.api_host_options or \
sect != 'general' and opt not in conf.api_host_options:
@@ -9842,7 +9842,7 @@ Please submit there instead, or use --nodevelproject to force direct submission.
val = str(cp.get(sect, opt, raw=True))
# special handling for continuation lines
val = '\n '.join(val.split('\n'))
- print('%s = %s' % (opt, val))
+ print(f'{opt} = {val}')
print()
return
@@ -9871,17 +9871,17 @@ Please submit there instead, or use --nodevelproject to force direct submission.
orig_opt = opt
opt, newval = conf.config_set_option(section, opt, ' '.join(val), delete=opts.delete, update=True, creds_mgr_descr=creds_mgr_descr)
if newval is None and opts.delete:
- print('\'%s\': \'%s\' got removed' % (section, opt))
+ print(f'\'{section}\': \'{opt}\' got removed')
elif newval is None:
- print('\'%s\': \'%s\' is not set' % (section, opt))
+ print(f'\'{section}\': \'{opt}\' is not set')
else:
if orig_opt == 'pass':
print('Password has been changed.')
elif opts.no_echo:
# supress value
- print('\'%s\': set \'%s\'' % (section, opt))
+ print(f'\'{section}\': set \'{opt}\'')
else:
- print('\'%s\': \'%s\' is set to \'%s\'' % (section, opt, newval))
+ print(f'\'{section}\': \'{opt}\' is set to \'{newval}\'')
@cmdln.option('file', nargs='+')
def do_revert(self, subcmd, opts):
@@ -9924,9 +9924,9 @@ Please submit there instead, or use --nodevelproject to force direct submission.
try:
num = int(num)
except ValueError:
- raise oscerr.WrongArgs('\'%s\' is not a number. Aborting' % num)
+ raise oscerr.WrongArgs(f'\'{num}\' is not a number. Aborting')
if num < 0 or num >= len(apiurls):
- raise oscerr.WrongArgs('number \'%s\' out of range. Aborting' % num)
+ raise oscerr.WrongArgs(f'number \'{num}\' out of range. Aborting')
return apiurls[num]
args = parseargs(args)
@@ -9962,9 +9962,9 @@ Please submit there instead, or use --nodevelproject to force direct submission.
apiurl = get_apiurl(apiurls)
p = Package(pdir, wc_check=False)
p.wc_repair(apiurl)
- print('done. Please check the state of the wc (via \'osc status %s\').' % i)
+ print(f'done. Please check the state of the wc (via \'osc status {i}\').')
else:
- print('osc: working copy \'%s\' is not inconsistent' % i, file=sys.stderr)
+ print(f'osc: working copy \'{i}\' is not inconsistent', file=sys.stderr)
@cmdln.option('-n', '--dry-run', action='store_true',
help='print the results without actually removing a file')
@@ -9983,7 +9983,7 @@ Please submit there instead, or use --nodevelproject to force direct submission.
# do a sanity check first
for pac in pacs:
if not is_package_dir(pac):
- raise oscerr.WrongArgs('\'%s\' is no package working copy' % pac)
+ raise oscerr.WrongArgs(f'\'{pac}\' is no package working copy')
for pdir in pacs:
p = Package(pdir)
pdir = getTransActPath(pdir)
@@ -9994,7 +9994,7 @@ Please submit there instead, or use --nodevelproject to force direct submission.
if os.path.isfile(fname) and p.status(fname) == '?':
todo.append(fname)
for filename in todo:
- print('Removing: %s' % os.path.join(pdir, filename))
+ print(f'Removing: {os.path.join(pdir, filename)}')
if not opts.dry_run:
os.unlink(os.path.join(p.absdir, filename))
@@ -10103,10 +10103,10 @@ Please submit there instead, or use --nodevelproject to force direct submission.
setattr(self.__class__, name, data)
except (SyntaxError, NameError, ImportError) as e:
if os.environ.get('OSC_PLUGIN_FAIL_IGNORE'):
- print("%s: %s\n" % (os.path.join(plugin_dir, extfile), e), file=sys.stderr)
+ print(f"{os.path.join(plugin_dir, extfile)}: {e}\n", file=sys.stderr)
else:
traceback.print_exc(file=sys.stderr)
- print('\n%s: %s' % (os.path.join(plugin_dir, extfile), e), file=sys.stderr)
+ print(f'\n{os.path.join(plugin_dir, extfile)}: {e}', file=sys.stderr)
print("\n Try 'env OSC_PLUGIN_FAIL_IGNORE=1 osc ...'", file=sys.stderr)
sys.exit(1)
diff --git a/osc/conf.py b/osc/conf.py
index 779799e6..97503aea 100644
--- a/osc/conf.py
+++ b/osc/conf.py
@@ -1383,10 +1383,10 @@ def _model_to_rst(cls, title=None, description=None, sections=None, output_file=
ini_key = extra.get("ini_key", name)
- x = bold(ini_key) + " : " + get_type(name, field)
+ x = f"{bold(ini_key)} : {get_type(name, field)}"
default = get_default(name, field)
if default:
- x += " = " + italic(default)
+ x += f" = {italic(default)}"
result.append(x)
result.append("")
desc = extra.get("ini_description", None) or field.description or ""
@@ -1499,13 +1499,13 @@ def parse_apisrv_url(scheme, apisrv):
elif scheme is not None:
url = scheme + apisrv
else:
- url = "https://" + apisrv
+ url = f"https://{apisrv}"
scheme, url, path = urlsplit(url)[0:3]
return scheme, url, path.rstrip('/')
def urljoin(scheme, apisrv, path=''):
- return '://'.join([scheme, apisrv]) + path
+ return f"{scheme}://{apisrv}" + path
def is_known_apiurl(url):
@@ -1541,7 +1541,7 @@ def get_apiurl_api_host_options(apiurl):
apiurl = sanitize_apiurl(apiurl)
if is_known_apiurl(apiurl):
return config['api_host_options'][apiurl]
- raise oscerr.ConfigMissingApiurl('missing credentials for apiurl: \'%s\'' % apiurl,
+ raise oscerr.ConfigMissingApiurl(f'missing credentials for apiurl: \'{apiurl}\'',
'', apiurl)
@@ -1602,14 +1602,14 @@ def write_config(fname, cp):
if e.errno != errno.EEXIST:
raise
- with open(fname + '.new', 'w') as f:
+ with open(f"{fname}.new", 'w') as f:
cp.write(f, comments=True)
try:
- os.rename(fname + '.new', fname)
+ os.rename(f"{fname}.new", fname)
os.chmod(fname, 0o600)
except:
- if os.path.exists(fname + '.new'):
- os.unlink(fname + '.new')
+ if os.path.exists(f"{fname}.new"):
+ os.unlink(f"{fname}.new")
raise
@@ -1642,10 +1642,10 @@ def config_set_option(section, opt, val=None, delete=False, update=True, creds_m
section = sections.get(section.rstrip('/'), section)
if section not in cp.sections():
- raise oscerr.ConfigError('unknown section \'%s\'' % section, config['conffile'])
+ raise oscerr.ConfigError(f'unknown section \'{section}\'', config['conffile'])
if section == 'general' and opt not in general_opts or \
section != 'general' and opt not in api_host_options:
- raise oscerr.ConfigError('unknown config option \'%s\'' % opt, config['conffile'])
+ raise oscerr.ConfigError(f'unknown config option \'{opt}\'', config['conffile'])
if not val and not delete and opt == 'pass' and creds_mgr_descr is not None:
# change password store
@@ -1758,7 +1758,7 @@ def _get_credentials_manager(url, cp):
if cp.has_option(url, credentials.AbstractCredentialsManager.config_entry):
creds_mgr = credentials.create_credentials_manager(url, cp)
if creds_mgr is None:
- msg = 'Unable to instantiate creds mgr (section: %s)' % url
+ msg = f'Unable to instantiate creds mgr (section: {url})'
conffile = get_configParser.conffile
raise oscerr.ConfigMissingCredentialsError(msg, conffile, url)
return creds_mgr
@@ -1977,7 +1977,7 @@ def identify_conf():
return '~/.oscrc'
if os.environ.get('XDG_CONFIG_HOME', '') != '':
- conffile = os.environ.get('XDG_CONFIG_HOME') + '/osc/oscrc'
+ conffile = f"{os.environ.get('XDG_CONFIG_HOME')}/osc/oscrc"
else:
conffile = '~/.config/osc/oscrc'
diff --git a/osc/connection.py b/osc/connection.py
index 6eaae181..a5223a7c 100644
--- a/osc/connection.py
+++ b/osc/connection.py
@@ -488,7 +488,7 @@ class CookieJarAuthHandler(AuthHandlerBase):
# doing expensive signature auth in multiple processes.
# This usually happens when a user runs multiple osc instances
# from the command-line in parallel.
- self.cookiejar_lock_path = self.cookiejar_path + ".lock"
+ self.cookiejar_lock_path = f"{self.cookiejar_path}.lock"
self.cookiejar_lock_fd = None
@property
@@ -633,7 +633,7 @@ class SignatureAuthHandler(AuthHandlerBase):
keyfile = self.guess_keyfile()
else:
if '/' not in keyfile:
- keyfile = '~/.ssh/' + keyfile
+ keyfile = f"~/.ssh/{keyfile}"
keyfile = os.path.expanduser(keyfile)
cmd = [self.ssh_keygen_path, '-Y', 'sign', '-f', keyfile, '-n', namespace, '-q']
@@ -668,7 +668,7 @@ class SignatureAuthHandler(AuthHandlerBase):
auth = self.get_authorization(chal)
if not auth:
return False
- auth_val = 'Signature %s' % auth
+ auth_val = f'Signature {auth}'
req.add('Authorization', auth_val)
return True
diff --git a/osc/core.py b/osc/core.py
index 3a5543dc..a9bb3b68 100644
--- a/osc/core.py
+++ b/osc/core.py
@@ -329,8 +329,8 @@ class Serviceinfo:
elementtree node.
"""
def error(msg, xml):
- data = 'invalid service format:\n%s' % ET.tostring(xml, encoding=ET_ENCODING)
- raise ValueError("%s\n\n%s" % (data, msg))
+ data = f'invalid service format:\n{ET.tostring(xml, encoding=ET_ENCODING)}'
+ raise ValueError(f"{data}\n\n{msg}")
if serviceinfo_node is None:
return
@@ -343,14 +343,14 @@ class Serviceinfo:
if name is None:
error("invalid service definition. Attribute name missing.", service)
if len(name) < 3 or '/' in name:
- error("invalid service name: %s" % name, service)
+ error(f"invalid service name: {name}", service)
mode = service.get('mode', '')
data = {'name': name, 'mode': mode}
command = [name]
for param in service.findall('param'):
option = param.get('name')
if option is None:
- error("%s: a parameter requires a name" % name, service)
+ error(f"{name}: a parameter requires a name", service)
value = ''
if param.text:
value = param.text
@@ -516,10 +516,10 @@ class Serviceinfo:
continue
temp_dir = None
try:
- temp_dir = tempfile.mkdtemp(dir=dir, suffix='.%s.service' % service['name'])
+ temp_dir = tempfile.mkdtemp(dir=dir, suffix=f".{service['name']}.service")
cmd = service['command']
if not os.path.exists("/usr/lib/obs/service/" + cmd[0]):
- raise oscerr.PackageNotInstalled("obs-service-%s" % cmd[0])
+ raise oscerr.PackageNotInstalled(f"obs-service-{cmd[0]}")
cmd[0] = "/usr/lib/obs/service/" + cmd[0]
cmd = cmd + ["--outdir", temp_dir]
_private.print_msg("Run source service:", " ".join(cmd), print_to="verbose")
@@ -795,7 +795,7 @@ class Project:
for pac in self.pacs_missing:
if conf.config['do_package_tracking'] and pac in self.pacs_unvers:
# pac is not under version control but a local file/dir exists
- msg = 'can\'t add package \'%s\': Object already exists' % pac
+ msg = f'can\'t add package \'{pac}\': Object already exists'
raise oscerr.PackageExists(self.name, pac, msg)
if not (expand_link or unexpand_link):
@@ -808,10 +808,10 @@ class Project:
# hmm what about a linkerror (sinfo.get('lsrcmd5') is None)?
# Should we skip the package as well or should we it out?
# let's skip it for now
- print('Skipping %s (link to package %s)' % (pac, linked.get('package')))
+ print(f"Skipping {pac} (link to package {linked.get('package')})")
continue
- print('checking out new package %s' % pac)
+ print(f'checking out new package {pac}')
checkout_package(self.apiurl, self.name, pac,
pathname=getTransActPath(os.path.join(self.dir, pac)),
prj_obj=self, prj_dir=self.dir,
@@ -823,7 +823,7 @@ class Project:
if st is None and exists:
return '?'
elif st is None:
- raise oscerr.OscIOError(None, 'osc: \'%s\' is not under version control' % pac)
+ raise oscerr.OscIOError(None, f'osc: \'{pac}\' is not under version control')
elif st in ('A', ' ') and not exists:
return '!'
elif st == 'D' and not exists:
@@ -890,7 +890,7 @@ class Project:
try:
result = ET.parse(packages_file)
except:
- msg = 'Cannot read package file \'%s\'. ' % packages_file
+ msg = f'Cannot read package file \'{packages_file}\'. '
msg += 'You can try to remove it and then run osc repairwc.'
raise oscerr.OscIOError(None, msg)
return result
@@ -914,7 +914,7 @@ class Project:
def addPackage(self, pac):
for i in conf.config['exclude_glob']:
if fnmatch.fnmatch(pac, i):
- msg = 'invalid package name: \'%s\' (see \'exclude_glob\' config option)' % pac
+ msg = f'invalid package name: \'{pac}\' (see \'exclude_glob\' config option)'
raise oscerr.OscIOError(None, msg)
state = self.get_state(pac)
if state is None or state == 'D':
@@ -925,7 +925,7 @@ class Project:
if pac in self.pacs_unvers:
self.pacs_unvers.remove(pac)
else:
- raise oscerr.PackageExists(self.name, pac, 'package \'%s\' is already under version control' % pac)
+ raise oscerr.PackageExists(self.name, pac, f'package \'{pac}\' is already under version control')
def delPackage(self, pac, force=False):
state = self.get_state(pac.name)
@@ -951,7 +951,7 @@ class Project:
self.set_state(pac.name, 'D')
self.write_packages()
else:
- print('package \'%s\' has local modifications (see osc st for details)' % pac.name)
+ print(f'package \'{pac.name}\' has local modifications (see osc st for details)')
elif state == 'A':
if force:
delete_dir(pac.absdir)
@@ -959,7 +959,7 @@ class Project:
self.write_packages()
print(statfrmt('D', pac.name))
else:
- print('package \'%s\' has local modifications (see osc st for details)' % pac.name)
+ print(f'package \'{pac.name}\' has local modifications (see osc st for details)')
elif state is None:
print('package is not under version control')
else:
@@ -1033,11 +1033,11 @@ class Project:
needs_update = True
else:
needs_update = p.update_needed(sinfos[p.name])
- print('Updating %s' % p.name)
+ print(f'Updating {p.name}')
if needs_update:
p.update(rev, service_files)
else:
- print('At revision %s.' % p.rev)
+ print(f'At revision {p.rev}.')
if unexpand_link:
p.unmark_frozen()
elif state == 'D':
@@ -1047,13 +1047,13 @@ class Project:
p.update()
elif state == 'A' and pac in self.pacs_available:
# file/dir called pac already exists and is under version control
- msg = 'can\'t add package \'%s\': Object already exists' % pac
+ msg = f'can\'t add package \'{pac}\': Object already exists'
raise oscerr.PackageExists(self.name, pac, msg)
elif state == 'A':
# do nothing
pass
else:
- print('unexpected state.. package \'%s\'' % pac)
+ print(f'unexpected state.. package \'{pac}\'')
self.checkout_missing_pacs(sinfos, expand_link, unexpand_link)
finally:
@@ -1081,9 +1081,9 @@ class Project:
p.todo = todo
p.commit(msg, verbose=verbose, skip_local_service_run=skip_local_service_run, can_branch=can_branch, force=force)
elif pac in self.pacs_unvers and not is_package_dir(os.path.join(self.dir, pac)):
- print('osc: \'%s\' is not under version control' % pac)
+ print(f'osc: \'{pac}\' is not under version control')
elif pac in self.pacs_broken or not os.path.exists(os.path.join(self.dir, pac)):
- print('osc: \'%s\' package not found' % pac)
+ print(f'osc: \'{pac}\' package not found')
elif state is None:
self.commitExtPackage(pac, msg, todo, verbose=verbose, skip_local_service_run=skip_local_service_run)
finally:
@@ -1092,7 +1092,7 @@ class Project:
# if we have packages marked as '!' we cannot commit
for pac in self.pacs_broken:
if self.get_state(pac) != 'D':
- msg = 'commit failed: package \'%s\' is missing' % pac
+ msg = f'commit failed: package \'{pac}\' is missing'
raise oscerr.PackageMissing(self.name, pac, msg)
try:
for pac in self.pacs_have:
@@ -1111,7 +1111,7 @@ class Project:
"""creates and commits a new package if it does not exist on the server"""
files = files or []
if pac in self.pacs_available:
- print('package \'%s\' already exists' % pac)
+ print(f'package \'{pac}\' already exists')
else:
user = conf.get_apiurl_usr(self.apiurl)
edit_meta(metatype='pkg',
@@ -1183,9 +1183,9 @@ class Project:
def __str__(self):
r = []
r.append('*****************************************************')
- r.append('Project %s (dir=%s, absdir=%s)' % (self.name, self.dir, self.absdir))
- r.append('have pacs:\n%s' % ', '.join(self.pacs_have))
- r.append('missing pacs:\n%s' % ', '.join(self.pacs_missing))
+ r.append(f'Project {self.name} (dir={self.dir}, absdir={self.absdir})')
+ r.append(f"have pacs:\n{', '.join(self.pacs_have)}")
+ r.append(f"missing pacs:\n{', '.join(self.pacs_missing)}")
r.append('*****************************************************')
return '\n'.join(r)
@@ -1206,9 +1206,9 @@ class Project:
# use makedirs (checkout_no_colon config option might be enabled)
os.makedirs(dir)
elif not os.path.isdir(dir):
- raise oscerr.OscIOError(None, 'error: \'%s\' is no directory' % dir)
+ raise oscerr.OscIOError(None, f'error: \'{dir}\' is no directory')
if os.path.exists(os.path.join(dir, store)):
- raise oscerr.OscIOError(None, 'error: \'%s\' is already an initialized osc working copy' % dir)
+ raise oscerr.OscIOError(None, f'error: \'{dir}\' is already an initialized osc working copy')
else:
os.mkdir(os.path.join(dir, store))
@@ -1416,13 +1416,13 @@ class Package:
def addfile(self, n):
if not os.path.exists(os.path.join(self.absdir, n)):
- raise oscerr.OscIOError(None, 'error: file \'%s\' does not exist' % n)
+ raise oscerr.OscIOError(None, f'error: file \'{n}\' does not exist')
if n in self.to_be_deleted:
self.to_be_deleted.remove(n)
# self.delete_storefile(n)
self.write_deletelist()
elif n in self.filenamelist or n in self.to_be_added:
- raise oscerr.PackageFileConflict(self.prjname, self.name, n, 'osc: warning: \'%s\' is already under version control' % n)
+ raise oscerr.PackageFileConflict(self.prjname, self.name, n, f'osc: warning: \'{n}\' is already under version control')
# shutil.copyfile(os.path.join(self.dir, n), os.path.join(self.storedir, n))
if self.dir != '.':
pathname = os.path.join(self.dir, n)
@@ -1665,7 +1665,7 @@ class Package:
print(statfrmt('Sending', os.path.join(pathn, filename)))
elif st in (' ', '!', 'S'):
if st == '!' and filename in self.to_be_added:
- print('file \'%s\' is marked as \'A\' but does not exist' % filename)
+ print(f'file \'{filename}\' is marked as \'A\' but does not exist')
return 1
f = self.findfilebyname(filename)
if f is None:
@@ -1697,7 +1697,7 @@ class Package:
sha256sums[filename] = sha256_dgst(storefile)
if not force and not real_send and not todo_delete and not self.islinkrepair() and not self.ispulled():
- print('nothing to do for package %s' % self.name)
+ print(f'nothing to do for package {self.name}')
return 1
print('Transmitting file data', end=' ')
@@ -1716,7 +1716,7 @@ class Package:
'commit again afterwards.'
print(msg % filename)
return 1
- fileelem.set('hash', 'sha256:%s' % sha256sums[filename])
+ fileelem.set('hash', f'sha256:{sha256sums[filename]}')
sfilelist = self.__send_commitlog(msg, filelist)
send = self.commit_get_missing(sfilelist)
real_send = [i for i in real_send if i not in send]
@@ -1751,7 +1751,7 @@ class Package:
shutil.rmtree(tdir)
self.rev = sfilelist.get('rev')
print()
- print('Committed revision %s.' % self.rev)
+ print(f'Committed revision {self.rev}.')
if self.ispulled():
os.unlink(os.path.join(self.storedir, '_pulled'))
@@ -1765,7 +1765,7 @@ class Package:
li = Linkinfo()
li.read(sfilelist.find('linkinfo'))
if li.xsrcmd5 is None:
- raise oscerr.APIError('linkinfo has no xsrcmd5 attr:\n%s\n' % ET.tostring(sfilelist, encoding=ET_ENCODING))
+ raise oscerr.APIError(f'linkinfo has no xsrcmd5 attr:\n{ET.tostring(sfilelist, encoding=ET_ENCODING)}\n')
sfilelist = ET.fromstring(self.get_files_meta(revision=li.xsrcmd5))
for i in sfilelist.findall('entry'):
if i.get('name') in self.skipped:
@@ -1815,7 +1815,7 @@ class Package:
def updatefile(self, n, revision, mtime=None):
filename = os.path.join(self.dir, n)
storefilename = os.path.join(self.storedir, n)
- origfile_tmp = os.path.join(self.storedir, '_in_update', '%s.copy' % n)
+ origfile_tmp = os.path.join(self.storedir, '_in_update', f'{n}.copy')
origfile = os.path.join(self.storedir, '_in_update', n)
if os.path.isfile(filename):
shutil.copyfile(filename, origfile_tmp)
@@ -1837,7 +1837,7 @@ class Package:
storefilename = os.path.join(self.storedir, n)
myfilename = os.path.join(self.dir, n + '.mine')
upfilename = os.path.join(self.dir, n + '.new')
- origfile_tmp = os.path.join(self.storedir, '_in_update', '%s.copy' % n)
+ origfile_tmp = os.path.join(self.storedir, '_in_update', f'{n}.copy')
origfile = os.path.join(self.storedir, '_in_update', n)
shutil.copyfile(filename, origfile_tmp)
os.rename(origfile_tmp, origfile)
@@ -1881,7 +1881,7 @@ class Package:
return 'C'
else:
merge_cmd = 'diff3 ' + ' '.join(args)
- raise oscerr.ExtRuntimeError('diff3 failed with exit code: %s' % ret, merge_cmd)
+ raise oscerr.ExtRuntimeError(f'diff3 failed with exit code: {ret}', merge_cmd)
def update_local_filesmeta(self, revision=None):
"""
@@ -2172,7 +2172,7 @@ class Package:
state = '?'
else:
# this case shouldn't happen (except there was a typo in the filename etc.)
- raise oscerr.OscIOError(None, 'osc: \'%s\' is not under version control' % n)
+ raise oscerr.OscIOError(None, f'osc: \'{n}\' is not under version control')
return state
@@ -2252,7 +2252,7 @@ class Package:
raise oscerr.OscIOError(None, 'file \'%s\' is marked as \'A\' but does not exist\n'
'(either add the missing file or revert it)' % fname)
elif not ignoreUnversioned:
- raise oscerr.OscIOError(None, 'file \'%s\' is not under version control' % fname)
+ raise oscerr.OscIOError(None, f'file \'{fname}\' is not under version control')
else:
fm = self.get_files_meta(revision=revision)
root = ET.fromstring(fm)
@@ -2390,7 +2390,7 @@ rev: %s
def mark_frozen(self):
store_write_string(self.absdir, '_frozenlink', '')
print()
- print("The link in this package (\"%s\") is currently broken. Checking" % self.name)
+ print(f"The link in this package (\"{self.name}\") is currently broken. Checking")
print("out the last working version instead; please use 'osc pull'")
print("to merge the conflicts.")
print()
@@ -2424,11 +2424,11 @@ rev: %s
def __get_files(self, fmeta_root):
f = []
if fmeta_root.get('rev') is None and len(fmeta_root.findall('entry')) > 0:
- raise oscerr.APIError('missing rev attribute in _files:\n%s' % ''.join(ET.tostring(fmeta_root, encoding=ET_ENCODING)))
+ raise oscerr.APIError(f"missing rev attribute in _files:\n{''.join(ET.tostring(fmeta_root, encoding=ET_ENCODING))}")
for i in fmeta_root.findall('entry'):
error = i.get('error')
if error is not None:
- raise oscerr.APIError('broken files meta: %s' % error)
+ raise oscerr.APIError(f'broken files meta: {error}')
skipped = i.get('skipped') is not None
f.append(File(i.get('name'), i.get('md5'),
int(i.get('size')), int(i.get('mtime')), skipped))
@@ -2578,7 +2578,7 @@ rev: %s
for f in added:
if f.name in self.filenamelist_unvers:
raise oscerr.PackageFileConflict(self.prjname, self.name, f.name,
- 'failed to add file \'%s\' file/dir with the same name already exists' % f.name)
+ f'failed to add file \'{f.name}\' file/dir with the same name already exists')
# ok, the update can't fail due to existing files
for f in added:
self.updatefile(f.name, rev, f.mtime)
@@ -2611,12 +2611,12 @@ rev: %s
print(statfrmt(merge_status, os.path.join(pathn, f.name)))
elif state == '!':
self.updatefile(f.name, rev, f.mtime)
- print('Restored \'%s\'' % os.path.join(pathn, f.name))
+ print(f'Restored \'{os.path.join(pathn, f.name)}\'')
elif state == 'C':
get_source_file(self.apiurl, self.prjname, self.name, f.name,
targetfilename=os.path.join(self.storedir, f.name), revision=rev,
progress_obj=self.progress_obj, mtime=f.mtime, meta=self.meta)
- print('skipping \'%s\' (this is due to conflicts)' % f.name)
+ print(f'skipping \'{f.name}\' (this is due to conflicts)')
elif state == 'D' and self.findfilebyname(f.name).md5 != f.md5:
# XXX: in the worst case we might end up with f.name being
# in _to_be_deleted and in _in_conflict... this needs to be checked
@@ -2647,7 +2647,7 @@ rev: %s
self.update_local_pacmeta()
self.update_datastructs()
- print('At revision %s.' % self.rev)
+ print(f'At revision {self.rev}.')
def run_source_services(self, mode=None, singleservice=None, verbose=None):
if self.name.startswith("_"):
@@ -2660,7 +2660,7 @@ rev: %s
service = ET.parse(os.path.join(self.absdir, '_service')).getroot()
except ET.ParseError as v:
line, column = v.position
- print('XML error in _service file on line %s, column %s' % (line, column))
+ print(f'XML error in _service file on line {line}, column {column}')
sys.exit(1)
si.read(service)
si.getProjectGlobalServices(self.apiurl, self.prjname, self.name)
@@ -2670,9 +2670,9 @@ rev: %s
def revert(self, filename):
if filename not in self.filenamelist and filename not in self.to_be_added:
- raise oscerr.OscIOError(None, 'file \'%s\' is not under version control' % filename)
+ raise oscerr.OscIOError(None, f'file \'{filename}\' is not under version control')
elif filename in self.skipped:
- raise oscerr.OscIOError(None, 'file \'%s\' is marked as skipped and cannot be reverted' % filename)
+ raise oscerr.OscIOError(None, f'file \'{filename}\' is marked as skipped and cannot be reverted')
if filename in self.filenamelist and not os.path.exists(os.path.join(self.storedir, filename)):
msg = f"file '{filename}' is listed in filenamelist but no storefile exists"
raise oscerr.PackageInternalError(self.prjname, self.name, msg)
@@ -2695,9 +2695,9 @@ rev: %s
if not os.path.exists(dir):
os.mkdir(dir)
elif not os.path.isdir(dir):
- raise oscerr.OscIOError(None, 'error: \'%s\' is no directory' % dir)
+ raise oscerr.OscIOError(None, f'error: \'{dir}\' is no directory')
if os.path.exists(os.path.join(dir, store)):
- raise oscerr.OscIOError(None, 'error: \'%s\' is already an initialized osc working copy' % dir)
+ raise oscerr.OscIOError(None, f'error: \'{dir}\' is already an initialized osc working copy')
else:
os.mkdir(os.path.join(dir, store))
store_write_project(dir, project)
@@ -2931,11 +2931,11 @@ class Action:
self._src_pkg_object = None
self._tgt_pkg_object = None
if type not in Action.type_args.keys():
- raise oscerr.WrongArgs('invalid action type: \'%s\'' % type)
+ raise oscerr.WrongArgs(f'invalid action type: \'{type}\'')
self.type = type
for i in kwargs.keys():
if i not in Action.type_args[type]:
- raise oscerr.WrongArgs('invalid argument: \'%s\'' % i)
+ raise oscerr.WrongArgs(f'invalid argument: \'{i}\'')
# set all type specific attributes
for i in Action.type_args[type]:
setattr(self, i, kwargs.get(i))
@@ -3051,9 +3051,9 @@ class Action:
for node in action_node:
prefix = elm_to_prefix.get(node.tag, node.tag)
if prefix == 'opt':
- data = [('opt_%s' % opt.tag, opt.text.strip()) for opt in node if opt.text]
+ data = [(f'opt_{opt.tag}', opt.text.strip()) for opt in node if opt.text]
else:
- data = [('%s_%s' % (prefix, k), v) for k, v in node.items()]
+ data = [(f'{prefix}_{k}', v) for k, v in node.items()]
# it would be easier to store everything in a list but in
# this case we would lose some "structure" (see to_xml)
for k, v in data:
@@ -3117,13 +3117,13 @@ class Request:
self._init_attributes()
self.apiurl = apiurl
if not root.get('id'):
- raise oscerr.APIError('invalid request: %s\n' % ET.tostring(root, encoding=ET_ENCODING))
+ raise oscerr.APIError(f'invalid request: {ET.tostring(root, encoding=ET_ENCODING)}\n')
self.reqid = root.get('id')
if root.get('creator'):
# OBS 2.8 and later is delivering creator informations
self.creator = root.get('creator')
if root.find('state') is None:
- raise oscerr.APIError('invalid request (state expected): %s\n' % ET.tostring(root, encoding=ET_ENCODING))
+ raise oscerr.APIError(f'invalid request (state expected): {ET.tostring(root, encoding=ET_ENCODING)}\n')
self.state = RequestState(root.find('state'))
action_nodes = root.findall('action')
if not action_nodes:
@@ -3203,21 +3203,21 @@ class Request:
A dict which contains the formatted str's is returned.
"""
- d = {'state': '%s:' % review.state}
+ d = {'state': f'{review.state}:'}
if review.by_package:
- d['by'] = '%s/%s' % (review.by_project, review.by_package)
+ d['by'] = f'{review.by_project}/{review.by_package}'
d['type'] = 'Package'
elif review.by_project:
- d['by'] = '%s' % review.by_project
+ d['by'] = f'{review.by_project}'
d['type'] = 'Project'
elif review.by_group:
- d['by'] = '%s' % review.by_group
+ d['by'] = f'{review.by_group}'
d['type'] = 'Group'
else:
- d['by'] = '%s' % review.by_user
+ d['by'] = f'{review.by_user}'
d['type'] = 'User'
if review.who:
- d['by'] += '(%s)' % review.who
+ d['by'] += f'({review.who})'
return d
def format_action(self, action: Action, show_srcupdate=False):
@@ -3229,44 +3229,44 @@ class Request:
if not pkg:
if not repository:
return prj or ''
- return '%s(%s)' % (prj, repository)
- return '%s/%s' % (prj, pkg)
+ return f'{prj}({repository})'
+ return f'{prj}/{pkg}'
- d = {'type': '%s:' % action.type}
+ d = {'type': f'{action.type}:'}
if action.type == 'set_bugowner':
if action.person_name:
d['source'] = action.person_name
if action.group_name:
- d['source'] = 'group:%s' % action.group_name
+ d['source'] = f'group:{action.group_name}'
d['target'] = prj_pkg_join(action.tgt_project, action.tgt_package)
elif action.type == 'change_devel':
d['source'] = prj_pkg_join(action.tgt_project, action.tgt_package)
- d['target'] = 'developed in %s' % prj_pkg_join(action.src_project, action.src_package)
+ d['target'] = f'developed in {prj_pkg_join(action.src_project, action.src_package)}'
elif action.type == 'maintenance_incident':
- d['source'] = '%s ->' % action.src_project
+ d['source'] = f'{action.src_project} ->'
if action.src_package:
- d['source'] = '%s' % prj_pkg_join(action.src_project, action.src_package)
+ d['source'] = f'{prj_pkg_join(action.src_project, action.src_package)}'
if action.src_rev:
- d['source'] = d['source'] + '@%s' % action.src_rev
+ d['source'] = d['source'] + f'@{action.src_rev}'
d['source'] = d['source'] + ' ->'
d['target'] = action.tgt_project
if action.tgt_releaseproject:
d['target'] += " (release in " + action.tgt_releaseproject + ")"
srcupdate = ' '
if action.opt_sourceupdate and show_srcupdate:
- srcupdate = '(%s)' % action.opt_sourceupdate
+ srcupdate = f'({action.opt_sourceupdate})'
elif action.type in ('maintenance_release', 'release'):
- d['source'] = '%s' % prj_pkg_join(action.src_project, action.src_package)
+ d['source'] = f'{prj_pkg_join(action.src_project, action.src_package)}'
if action.src_rev:
- d['source'] = d['source'] + '@%s' % action.src_rev
+ d['source'] = d['source'] + f'@{action.src_rev}'
d['source'] = d['source'] + ' ->'
d['target'] = prj_pkg_join(action.tgt_project, action.tgt_package)
elif action.type == 'submit':
- d['source'] = '%s' % prj_pkg_join(action.src_project, action.src_package)
+ d['source'] = f'{prj_pkg_join(action.src_project, action.src_package)}'
if action.src_rev:
- d['source'] = d['source'] + '@%s' % action.src_rev
+ d['source'] = d['source'] + f'@{action.src_rev}'
if action.opt_sourceupdate and show_srcupdate:
- d['source'] = d['source'] + '(%s)' % action.opt_sourceupdate
+ d['source'] = d['source'] + f'({action.opt_sourceupdate})'
d['source'] = d['source'] + ' ->'
tgt_package = action.tgt_package
if action.src_package == action.tgt_package:
@@ -3279,9 +3279,9 @@ class Request:
elif action.type == 'add_role':
roles = []
if action.person_name and action.person_role:
- roles.append('person: %s as %s' % (action.person_name, action.person_role))
+ roles.append(f'person: {action.person_name} as {action.person_role}')
if action.group_name and action.group_role:
- roles.append('group: %s as %s' % (action.group_name, action.group_role))
+ roles.append(f'group: {action.group_name} as {action.group_role}')
d['source'] = ', '.join(roles)
d['target'] = prj_pkg_join(action.tgt_project, action.tgt_package)
elif action.type == 'delete':
@@ -3297,7 +3297,7 @@ class Request:
d['source'] = ', '.join(l) + ' ->'
d['target'] = self.reqid
else:
- raise oscerr.APIError('Unknown action type %s\n' % action.type)
+ raise oscerr.APIError(f'Unknown action type {action.type}\n')
return d
def list_view(self):
@@ -3313,9 +3313,9 @@ class Request:
tmpl = ' Review by %(type)-10s is %(state)-10s %(by)-50s'
for review in self.reviews:
lines.append(tmpl % Request.format_review(review))
- history = ['%s: %s' % (hist.description, hist.who) for hist in self.statehistory]
+ history = [f'{hist.description}: {hist.who}' for hist in self.statehistory]
if history:
- lines.append(' From: %s' % ' -> '.join(history))
+ lines.append(f" From: {' -> '.join(history)}")
if self.description:
lines.append(textwrap.fill(self.description, width=80, initial_indent=' Descr: ',
subsequent_indent=' '))
@@ -3431,7 +3431,7 @@ def parse_disturl(disturl: str):
m = DISTURL_RE.match(disturl)
if not m:
- raise oscerr.WrongArgs("`%s' does not look like disturl" % disturl)
+ raise oscerr.WrongArgs(f"`{disturl}' does not look like disturl")
apiurl = m.group('apiurl')
if apiurl.split('.')[0] != 'api':
@@ -3447,7 +3447,7 @@ def parse_buildlogurl(buildlogurl: str):
m = BUILDLOGURL_RE.match(buildlogurl)
if not m:
- raise oscerr.WrongArgs('\'%s\' does not look like url with a build log' % buildlogurl)
+ raise oscerr.WrongArgs(f'\'{buildlogurl}\' does not look like url with a build log')
return (m.group('apiurl'), m.group('project'), m.group('package'), m.group('repository'), m.group('arch'))
@@ -3530,19 +3530,19 @@ def findpacs(files, progress_obj=None, fatal=True):
def read_filemeta(dir):
global store
- msg = '\'%s\' is not a valid working copy.' % dir
+ msg = f'\'{dir}\' is not a valid working copy.'
filesmeta = os.path.join(dir, store, '_files')
if not is_package_dir(dir):
raise oscerr.NoWorkingCopy(msg)
if os.path.isfile(os.path.join(dir, store, '_scm')):
raise oscerr.NoWorkingCopy("Is managed via scm")
if not os.path.isfile(filesmeta):
- raise oscerr.NoWorkingCopy('%s (%s does not exist)' % (msg, filesmeta))
+ raise oscerr.NoWorkingCopy(f'{msg} ({filesmeta} does not exist)')
try:
r = ET.parse(filesmeta)
except SyntaxError as e:
- raise oscerr.NoWorkingCopy('%s\nWhen parsing .osc/_files, the following error was encountered:\n%s' % (msg, e))
+ raise oscerr.NoWorkingCopy(f'{msg}\nWhen parsing .osc/_files, the following error was encountered:\n{e}')
return r
@@ -3595,7 +3595,7 @@ def parseargs(list_of_args):
def statfrmt(statusletter, filename):
- return '%s %s' % (statusletter, filename)
+ return f'{statusletter} {filename}'
def pathjoin(a, *p):
@@ -3652,7 +3652,7 @@ def check_store_version(dir):
v = ''
if v == '':
- msg = 'Error: "%s" is not an osc package working copy.' % os.path.abspath(dir)
+ msg = f'Error: "{os.path.abspath(dir)}" is not an osc package working copy.'
if os.path.exists(os.path.join(dir, '.svn')):
msg = msg + '\nTry svn instead of osc.'
raise oscerr.NoWorkingCopy(msg)
@@ -3664,8 +3664,8 @@ def check_store_version(dir):
f.write(__store_version__ + '\n')
f.close()
return
- msg = 'The osc metadata of your working copy "%s"' % dir
- msg += '\nhas __store_version__ = %s, but it should be %s' % (v, __store_version__)
+ msg = f'The osc metadata of your working copy "{dir}"'
+ msg += f'\nhas __store_version__ = {v}, but it should be {__store_version__}'
msg += '\nPlease do a fresh checkout or update your client. Sorry about the inconvenience.'
raise oscerr.WorkingCopyWrongVersion(msg)
@@ -3755,7 +3755,7 @@ def show_project_meta(apiurl: str, prj: str, rev=None, blame=None):
error_help = "%s (%d) project: %s" % (os_err, e.code, prj)
if e.code == 404 and os_err == 'unknown_package':
error_help = 'option -r|--revision is not supported by this OBS version'
- e.osc_msg = 'BuildService API error: %s' % error_help
+ e.osc_msg = f'BuildService API error: {error_help}'
raise
else:
if blame:
@@ -3786,7 +3786,7 @@ def show_package_trigger_reason(apiurl: str, prj: str, pac: str, repo: str, arch
f = http_GET(url)
return f.read()
except HTTPError as e:
- e.osc_msg = 'Error getting trigger reason for project \'%s\' package \'%s\'' % (prj, pac)
+ e.osc_msg = f'Error getting trigger reason for project \'{prj}\' package \'{pac}\''
raise
@@ -3803,7 +3803,7 @@ def show_package_meta(apiurl: str, prj: str, pac: str, meta=False, blame=None):
f = http_GET(url)
return f.readlines()
except HTTPError as e:
- e.osc_msg = 'Error getting meta for project \'%s\' package \'%s\'' % (unquote(prj), pac)
+ e.osc_msg = f'Error getting meta for project \'{unquote(prj)}\' package \'{pac}\''
raise
@@ -3828,7 +3828,7 @@ def show_attribute_meta(apiurl: str, prj: str, pac, subpac, attribute, with_defa
f = http_GET(url)
return f.readlines()
except HTTPError as e:
- e.osc_msg = 'Error getting meta for project \'%s\' package \'%s\'' % (prj, pac)
+ e.osc_msg = f'Error getting meta for project \'{prj}\' package \'{pac}\''
raise
@@ -3921,7 +3921,7 @@ def show_pattern_metalist(apiurl: str, prj: str):
f = http_GET(url)
tree = ET.parse(f)
except HTTPError as e:
- e.osc_msg = 'show_pattern_metalist: Error getting pattern list for project \'%s\'' % prj
+ e.osc_msg = f'show_pattern_metalist: Error getting pattern list for project \'{prj}\''
raise
r = sorted(node.get('name') for node in tree.getroot())
return r
@@ -3933,7 +3933,7 @@ def show_pattern_meta(apiurl: str, prj: str, pattern: str):
f = http_GET(url)
return f.readlines()
except HTTPError as e:
- e.osc_msg = 'show_pattern_meta: Error getting pattern \'%s\' for project \'%s\'' % (pattern, prj)
+ e.osc_msg = f'show_pattern_meta: Error getting pattern \'{pattern}\' for project \'{prj}\''
raise
@@ -4041,7 +4041,7 @@ class metafile:
def discard(self):
if os.path.exists(self.filename):
- print('discarding %s' % self.filename)
+ print(f'discarding {self.filename}')
os.unlink(self.filename)
@@ -4110,7 +4110,7 @@ def make_meta_url(
if not apiurl:
apiurl = conf.config['apiurl']
if metatype not in metatypes.keys():
- raise AttributeError('make_meta_url(): Unknown meta type \'%s\'' % metatype)
+ raise AttributeError(f'make_meta_url(): Unknown meta type \'{metatype}\'')
path = metatypes[metatype]['path']
if path_args:
@@ -4176,8 +4176,8 @@ def edit_meta(
if orgprj is not None and unquote(project) != orgprj:
print('The package is linked from a different project.')
print('If you want to edit the meta of the package create first a branch.')
- print(' osc branch %s %s %s' % (orgprj, package, unquote(project)))
- print(' osc meta pkg %s %s -e' % (unquote(project), package))
+ print(f' osc branch {orgprj} {package} {unquote(project)}')
+ print(f' osc meta pkg {unquote(project)} {package} -e')
return
def delegate(force=force):
@@ -4271,7 +4271,7 @@ def show_upstream_xsrcmd5(
def show_project_sourceinfo(apiurl: str, project: str, nofilename: bool, *packages):
query = ['view=info']
if packages:
- query.extend(['package=%s' % quote_plus(p) for p in packages])
+ query.extend([f'package={quote_plus(p)}' for p in packages])
if nofilename:
query.append('nofilename=1')
f = http_GET(makeurl(apiurl, ['source', project], query=query))
@@ -4290,7 +4290,7 @@ def get_project_sourceinfo(apiurl: str, project: str, nofilename: bool, *package
if e.code not in (414, 500):
raise
if len(packages) == 1:
- raise oscerr.APIError('package name too long: %s' % packages[0])
+ raise oscerr.APIError(f'package name too long: {packages[0]}')
n = int(len(packages) / 2)
pkgs = packages[:n]
res = get_project_sourceinfo(apiurl, project, nofilename, *pkgs)
@@ -4338,7 +4338,7 @@ def read_meta_from_spec(specfile, *args):
"""
if not os.path.isfile(specfile):
- raise oscerr.OscIOError(None, '\'%s\' is not a regular file' % specfile)
+ raise oscerr.OscIOError(None, f'\'{specfile}\' is not a regular file')
try:
lines = codecs.open(specfile, 'r', locale.getpreferredencoding()).readlines()
@@ -4489,7 +4489,7 @@ def _edit_message_open_editor(filename, data, orig_mtime):
with tempfile.NamedTemporaryFile() as f:
f.write(data)
f.flush()
- editor.extend(['-c', ':r %s' % f.name, filename])
+ editor.extend(['-c', f':r {f.name}', filename])
run_external(editor[0], *editor[1:])
else:
with open(filename, 'wb') as f:
@@ -4559,7 +4559,7 @@ def edit_text(data='', delim=None, suffix='.txt', template=''):
reason = 'Log message not specified'
if template == msg:
reason = 'Default log message was not changed. Press \'c\' to continue.'
- ri = raw_input('%s\na)bort, c)ontinue, e)dit: ' % reason)
+ ri = raw_input(f'{reason}\na)bort, c)ontinue, e)dit: ')
if ri in 'aA':
raise oscerr.UserAbort()
elif ri in 'cC':
@@ -4567,7 +4567,7 @@ def edit_text(data='', delim=None, suffix='.txt', template=''):
elif ri in 'eE':
ri_err = False
else:
- print("%s is not a valid option." % ri)
+ print(f"{ri} is not a valid option.")
ri_err = True
finally:
os.unlink(filename)
@@ -4584,7 +4584,7 @@ def clone_request(apiurl: str, reqid, msg=None):
if i.get('name') == 'targetproject':
project = i.text.strip()
if not project:
- raise oscerr.APIError('invalid data from clone request:\n%s\n' % ET.tostring(root, encoding=ET_ENCODING))
+ raise oscerr.APIError(f'invalid data from clone request:\n{ET.tostring(root, encoding=ET_ENCODING)}\n')
return project
# create a maintenance release request
@@ -4637,10 +4637,10 @@ def create_submit_request(
options_block = ""
package = ""
if src_package:
- package = """package="%s" """ % (src_package)
+ package = f"""package="{src_package}" """
options_block = ""
if src_update:
- options_block += """%s""" % (src_update)
+ options_block += f"""{src_update}"""
if dst_updatelink:
options_block += """true"""
options_block += ""
@@ -4650,8 +4650,8 @@ def create_submit_request(
if dst_project:
packagexml = ""
if dst_package:
- packagexml = """package="%s" """ % (dst_package)
- targetxml = """ """ % (dst_project, packagexml)
+ packagexml = f"""package="{dst_package}" """
+ targetxml = f""" """
# XXX: keep the old template for now in order to work with old obs instances
xml = """\
@@ -4681,13 +4681,13 @@ def create_submit_request(
print('WARNING: As the project is in maintenance, a maintenance incident request is')
print('WARNING: being created (instead of a regular submit request). If this is not your')
print('WARNING: intention please revoke it to avoid unnecessary work for all involved parties.')
- xpath = 'maintenance/maintains/@project = \'%s\' and attribute/@name = \'%s\'' % (dst_project, conf.config['maintenance_attribute'])
+ xpath = f"maintenance/maintains/@project = '{dst_project}' and attribute/@name = '{conf.config['maintenance_attribute']}'"
res = search(apiurl, project_id=xpath)
root = res['project_id']
project = root.find('project')
if project is None:
- print("WARNING: This project is not maintained in the maintenance project specified by '%s', looking elsewhere" % conf.config['maintenance_attribute'])
- xpath = 'maintenance/maintains/@project = \'%s\'' % dst_project
+ print(f"WARNING: This project is not maintained in the maintenance project specified by '{conf.config['maintenance_attribute']}', looking elsewhere")
+ xpath = f'maintenance/maintains/@project = \'{dst_project}\''
res = search(apiurl, project_id=xpath)
root = res['project_id']
project = root.find('project')
@@ -4752,7 +4752,7 @@ def change_request_state_template(req, newstate):
if not req.actions:
return ''
action = req.actions[0]
- tmpl_name = '%srequest_%s_template' % (action.type, newstate)
+ tmpl_name = f'{action.type}request_{newstate}_template'
tmpl = conf.config.get(tmpl_name, "") or ""
tmpl = tmpl.replace('\\t', '\t').replace('\\n', '\n')
data = {'reqid': req.reqid, 'type': action.type, 'who': req.creator}
@@ -4764,7 +4764,7 @@ def change_request_state_template(req, newstate):
try:
return tmpl % data
except KeyError as e:
- print('error: cannot interpolate \'%s\' in \'%s\'' % (e.args[0], tmpl_name), file=sys.stderr)
+ print(f'error: cannot interpolate \'{e.args[0]}\' in \'{tmpl_name}\'', file=sys.stderr)
return ''
@@ -4774,39 +4774,39 @@ def get_review_list(
# this is so ugly...
def build_by(xpath, val):
if 'all' in states:
- return xpath_join(xpath, 'review/%s' % val, op='and')
+ return xpath_join(xpath, f'review/{val}', op='and')
elif states:
s_xp = ''
for state in states:
- s_xp = xpath_join(s_xp, '@state=\'%s\'' % state, inner=True)
+ s_xp = xpath_join(s_xp, f'@state=\'{state}\'', inner=True)
val = val.strip('[').strip(']')
- return xpath_join(xpath, 'review[%s and (%s)]' % (val, s_xp), op='and')
+ return xpath_join(xpath, f'review[{val} and ({s_xp})]', op='and')
else:
# default case
- return xpath_join(xpath, 'review[%s and @state=\'new\']' % val, op='and')
+ return xpath_join(xpath, f'review[{val} and @state=\'new\']', op='and')
return ''
xpath = ''
# By default we're interested only in reviews of requests that are in state review.
for req_state in req_states:
- xpath = xpath_join(xpath, "state/@name='%s'" % req_state, inner=True)
+ xpath = xpath_join(xpath, f"state/@name='{req_state}'", inner=True)
- xpath = "(%s)" % xpath
+ xpath = f"({xpath})"
if states == ():
xpath = xpath_join(xpath, 'review/@state=\'new\'', op='and')
if byuser:
- xpath = build_by(xpath, '@by_user=\'%s\'' % byuser)
+ xpath = build_by(xpath, f'@by_user=\'{byuser}\'')
if bygroup:
- xpath = build_by(xpath, '@by_group=\'%s\'' % bygroup)
+ xpath = build_by(xpath, f'@by_group=\'{bygroup}\'')
if bypackage:
- xpath = build_by(xpath, '@by_project=\'%s\' and @by_package=\'%s\'' % (byproject, bypackage))
+ xpath = build_by(xpath, f'@by_project=\'{byproject}\' and @by_package=\'{bypackage}\'')
elif byproject:
- xpath = build_by(xpath, '@by_project=\'%s\'' % byproject)
+ xpath = build_by(xpath, f'@by_project=\'{byproject}\'')
if req_type:
- xpath = xpath_join(xpath, 'action/@type=\'%s\'' % req_type, op='and')
+ xpath = xpath_join(xpath, f'action/@type=\'{req_type}\'', op='and')
# XXX: we cannot use the '|' in the xpath expression because it is not supported
# in the backend
@@ -4948,20 +4948,20 @@ def get_exact_request_list(
xpath = ""
if "all" not in req_state:
for state in req_state:
- xpath = xpath_join(xpath, 'state/@name=\'%s\'' % state, op='or', inner=True)
- xpath = '(%s)' % xpath
+ xpath = xpath_join(xpath, f'state/@name=\'{state}\'', op='or', inner=True)
+ xpath = f'({xpath})'
if req_who:
xpath = xpath_join(xpath, '(state/@who=\'%(who)s\' or history/@who=\'%(who)s\')' % {'who': req_who}, op='and')
- xpath += " and action[source/@project='%s'" % src_project
+ xpath += f" and action[source/@project='{src_project}'"
if src_package:
- xpath += " and source/@package='%s'" % src_package
- xpath += " and target/@project='%s'" % dst_project
+ xpath += f" and source/@package='{src_package}'"
+ xpath += f" and target/@project='{dst_project}'"
if dst_package:
- xpath += " and target/@package='%s'" % dst_package
+ xpath += f" and target/@package='{dst_package}'"
xpath += "]"
if req_type:
- xpath += " and action/@type=\'%s\'" % req_type
+ xpath += f" and action/@type='{req_type}'"
_private.print_msg(f"[ {xpath} ]", print_to="debug")
@@ -5035,19 +5035,19 @@ def get_user_projpkgs_request_list(
xpath = ''
for prj, pacs in projpkgs.items():
if not pacs:
- xpath = xpath_join(xpath, 'action/target/@project=\'%s\'' % prj, inner=True)
+ xpath = xpath_join(xpath, f'action/target/@project=\'{prj}\'', inner=True)
else:
xp = ''
for p in pacs:
- xp = xpath_join(xp, 'action/target/@package=\'%s\'' % p, inner=True)
- xp = xpath_join(xp, 'action/target/@project=\'%s\'' % prj, op='and')
+ xp = xpath_join(xp, f'action/target/@package=\'{p}\'', inner=True)
+ xp = xpath_join(xp, f'action/target/@project=\'{prj}\'', op='and')
xpath = xpath_join(xpath, xp, inner=True)
if req_type:
- xpath = xpath_join(xpath, 'action/@type=\'%s\'' % req_type, op='and')
+ xpath = xpath_join(xpath, f'action/@type=\'{req_type}\'', op='and')
if 'all' not in req_state:
xp = ''
for state in req_state:
- xp = xpath_join(xp, 'state/@name=\'%s\'' % state, inner=True)
+ xp = xpath_join(xp, f'state/@name=\'{state}\'', inner=True)
xpath = xpath_join(xp, xpath, op='and', nexpr_parentheses=True)
res = search(apiurl, request=xpath)
result = []
@@ -5096,12 +5096,11 @@ def check_existing_requests(
if len(reqs) > 1:
open_request_string = "The following submit requests are already open:"
supersede_request_string = "Supersede the old requests?"
- print('%s %s.' %
- (open_request_string, ', '.join([i.reqid for i in reqs])))
- repl = raw_input('%s (y/n/c) ' % supersede_request_string)
+ print(f"{open_request_string} {', '.join([i.reqid for i in reqs])}.")
+ repl = raw_input(f'{supersede_request_string} (y/n/c) ')
while repl.lower() not in ['c', 'y', 'n']:
- print('%s is not a valid option.' % repl)
- repl = raw_input('%s (y/n/c) ' % supersede_request_string)
+ print(f'{repl} is not a valid option.')
+ repl = raw_input(f'{supersede_request_string} (y/n/c) ')
if repl.lower() == 'c':
print('Aborting', file=sys.stderr)
raise oscerr.UserAbort()
@@ -5131,12 +5130,11 @@ def check_existing_maintenance_requests(
if len(reqs) > 1:
open_request_string = "The following maintenance incident requests are already open:"
supersede_request_string = "Supersede the old requests?"
- print('%s %s.' %
- (open_request_string, ', '.join([i.reqid for i in reqs])))
- repl = raw_input('%s (y/n/c) ' % supersede_request_string)
+ print(f"{open_request_string} {', '.join([i.reqid for i in reqs])}.")
+ repl = raw_input(f'{supersede_request_string} (y/n/c) ')
while repl.lower() not in ['c', 'y', 'n']:
- print('%s is not a valid option.' % repl)
- repl = raw_input('%s (y/n/c) ' % supersede_request_string)
+ print(f'{repl} is not a valid option.')
+ repl = raw_input(f'{supersede_request_string} (y/n/c) ')
if repl.lower() == 'c':
print('Aborting', file=sys.stderr)
raise oscerr.UserAbort()
@@ -5156,7 +5154,7 @@ def get_group_meta(apiurl: str, group: str):
f = http_GET(u)
return b''.join(f.readlines())
except HTTPError:
- print('group \'%s\' not found' % group)
+ print(f'group \'{group}\' not found')
return None
@@ -5166,7 +5164,7 @@ def get_user_meta(apiurl: str, user: str):
f = http_GET(u)
return b''.join(f.readlines())
except HTTPError:
- print('user \'%s\' not found' % user)
+ print(f'user \'{user}\' not found')
return None
@@ -5521,7 +5519,7 @@ def get_request_issues(apiurl: str, reqid):
issue_list = []
for elem in request_tree.iterfind('action/sourcediff/issues/issue'):
issue_id = elem.get('name')
- encode_search = '@name=\'%s\'' % issue_id
+ encode_search = f'@name=\'{issue_id}\''
u = makeurl(apiurl, ['search/issue'], query={'match': encode_search})
f = http_GET(u)
collection = ET.parse(f).getroot()
@@ -5761,7 +5759,7 @@ def link_to_branch(apiurl: str, project: str, package: str):
u = makeurl(apiurl, ['source', project, package], 'cmd=linktobranch')
http_POST(u)
else:
- raise oscerr.OscIOError(None, 'no _link file inside project \'%s\' package \'%s\'' % (project, package))
+ raise oscerr.OscIOError(None, f'no _link file inside project \'{project}\' package \'{package}\'')
def link_pac(
@@ -5806,7 +5804,7 @@ def link_pac(
meta_change = True
if meta_change:
if missing_target:
- dst_meta = '' % dst_package
+ dst_meta = f''
else:
src_meta = show_package_meta(apiurl, src_project, src_package)
dst_meta = replace_pkg_meta(src_meta, dst_package, dst_project)
@@ -5846,12 +5844,12 @@ def link_pac(
sys.exit(1)
if not revision_is_empty(rev):
- rev = ' rev="%s"' % rev
+ rev = f' rev="{rev}"'
else:
rev = ''
if vrev:
- vrev = ' vrev="%s"' % vrev
+ vrev = f' vrev="{vrev}"'
else:
vrev = ''
@@ -5860,7 +5858,7 @@ def link_pac(
missingok = ' missingok="true"'
if cicount:
- cicount = ' cicount="%s"' % cicount
+ cicount = f' cicount="{cicount}"'
else:
cicount = ''
@@ -5868,7 +5866,7 @@ def link_pac(
project = ''
if src_project != dst_project:
- project = 'project="%s"' % src_project
+ project = f'project="{src_project}"'
link_template = """\
@@ -5990,23 +5988,20 @@ def aggregate_pac(
sys.exit(1)
print('Creating _aggregate...', end=' ')
- aggregate_template = """\
-
-
-""" % (src_project)
+ aggregate_template = f"""
+
+"""
- aggregate_template += """\
- %s
-""" % (src_package)
+ aggregate_template += f""" {src_package}
+"""
if nosources:
aggregate_template += """\
"""
for src, tgt in repo_map.items():
- aggregate_template += """\
-
-""" % (tgt, src)
+ aggregate_template += f"""
+"""
aggregate_template += """\
@@ -6065,7 +6060,7 @@ def attribute_branch_pkg(
summary = root.find('summary')
if summary is not None and summary.text is not None:
raise oscerr.APIError(summary.text)
- msg = 'unexpected response: %s' % ET.tostring(root, encoding=ET_ENCODING)
+ msg = f'unexpected response: {ET.tostring(root, encoding=ET_ENCODING)}'
raise oscerr.APIError(msg)
r = None
@@ -6150,9 +6145,9 @@ def branch_pkg(
raise oscerr.NotMissing("Package exists already via project link, but link will point to given project")
summary = root.find('summary')
if summary is None:
- raise oscerr.APIError('unexpected response:\n%s' % ET.tostring(root, encoding=ET_ENCODING))
+ raise oscerr.APIError(f'unexpected response:\n{ET.tostring(root, encoding=ET_ENCODING)}')
if not return_existing:
- raise oscerr.APIError('failed to branch: %s' % summary.text)
+ raise oscerr.APIError(f'failed to branch: {summary.text}')
m = re.match(r"branch target package already exists: (\S+)/(\S+)", summary.text)
if not m:
e.msg += '\n' + summary.text
@@ -6276,7 +6271,7 @@ def copy_pac(
filelist, msg=comment)
todo = Package.commit_get_missing(tfilelist)
if todo:
- raise oscerr.APIError('failed to copy: %s' % ', '.join(todo))
+ raise oscerr.APIError(f"failed to copy: {', '.join(todo)}")
return 'Done.'
@@ -6369,7 +6364,7 @@ def delete_project(apiurl: str, prj: str, force=False, msg=None, recursive=False
def delete_files(apiurl: str, prj: str, pac: str, files):
for filename in files:
- u = makeurl(apiurl, ['source', prj, pac, filename], query={'comment': 'removed %s' % (filename, )})
+ u = makeurl(apiurl, ['source', prj, pac, filename], query={'comment': f'removed {filename}'})
http_DELETE(u)
@@ -6428,7 +6423,7 @@ class Repo:
return self.repo_line_templ % (self.name, self.arch)
def __repr__(self):
- return 'Repo(%s %s)' % (self.name, self.arch)
+ return f'Repo({self.name} {self.arch})'
@staticmethod
def fromfile(filename):
@@ -6449,7 +6444,7 @@ class Repo:
def tofile(filename, repos):
with open(filename, 'w') as f:
for repo in repos:
- f.write('%s %s\n' % (repo.name, repo.arch))
+ f.write(f'{repo.name} {repo.arch}\n')
def get_repos_of_project(apiurl, prj):
@@ -6508,9 +6503,9 @@ def show_results_meta(
arch = arch or []
query = []
if package:
- query.append('package=%s' % quote_plus(package))
+ query.append(f'package={quote_plus(package)}')
if oldstate:
- query.append('oldstate=%s' % quote_plus(oldstate))
+ query.append(f'oldstate={quote_plus(oldstate)}')
if lastbuild:
query.append('lastbuild=1')
if multibuild:
@@ -6518,11 +6513,11 @@ def show_results_meta(
if locallink:
query.append('locallink=1')
if code:
- query.append('code=%s' % quote_plus(code))
+ query.append(f'code={quote_plus(code)}')
for repo in repository:
- query.append('repository=%s' % quote_plus(repo))
+ query.append(f'repository={quote_plus(repo)}')
for a in arch:
- query.append('arch=%s' % quote_plus(a))
+ query.append(f'arch={quote_plus(a)}')
u = makeurl(apiurl, ['build', prj, '_result'], query=query)
f = http_GET(u)
return f.readlines()
@@ -6617,13 +6612,13 @@ def get_results(apiurl: str, project: str, package: str, verbose=False, printJoi
lines = res['details'].split(',')
res['status'] += ': \n ' + '\n '.join(lines)
else:
- res['status'] += ': %s' % res['details']
+ res['status'] += f": {res['details']}"
elif res['code'] in ('scheduled', ) and res['details']:
# highlight scheduled jobs with possible dispatch problems
res['status'] += '*'
if res['dirty']:
if verbose:
- res['status'] = 'outdated (was: %s)' % res['status']
+ res['status'] = f"outdated (was: {res['status']})"
else:
res['status'] += '*'
elif res['code'] in ('succeeded', ) and res['repostate'] != "published":
@@ -6813,7 +6808,7 @@ def get_prj_results(
for repo, state in repo_states.items():
if filters and state not in filters:
continue
- r.append('%s %s %s %s' % (pac, repo[0], repo[1], state))
+ r.append(f'{pac} {repo[0]} {repo[1]} {state}')
return r
if not vertical:
@@ -6837,7 +6832,7 @@ def get_prj_results(
try:
st = buildstatus_symbols[status[pac][tg]]
except:
- print('osc: warn: unknown status \'%s\'...' % status[pac][tg])
+ print(f'osc: warn: unknown status \'{status[pac][tg]}\'...')
print('please edit osc/core.py, and extend the buildstatus_symbols dictionary.')
st = '?'
buildstatus_symbols[status[pac][tg]] = '?'
@@ -6866,7 +6861,7 @@ def get_prj_results(
try:
st = buildstatus_symbols[status[pac][tg]]
except:
- print('osc: warn: unknown status \'%s\'...' % status[pac][tg])
+ print(f'osc: warn: unknown status \'{status[pac][tg]}\'...')
print('please edit osc/core.py, and extend the buildstatus_symbols dictionary.')
st = '?'
buildstatus_symbols[status[pac][tg]] = '?'
@@ -6915,7 +6910,7 @@ def streamfile(url: str, http_meth=http_GET, bufsize=8192, data=None, progress_o
# Server (or iChain) is corrupting data at some point, see bnc#656281
while cl == '':
if retries >= int(conf.config['http_retries']):
- raise oscerr.OscIOError(None, 'Content-Length is empty for %s, protocol violation' % url)
+ raise oscerr.OscIOError(None, f'Content-Length is empty for {url}, protocol violation')
retries = retries + 1
if retries > 1 and conf.config['http_debug']:
print('\n\nRetry %d --' % (retries - 1), url, file=sys.stderr)
@@ -6994,7 +6989,7 @@ def print_buildlog(
# to protect us against control characters (CVE-2012-1095)
all_bytes = bytes.maketrans(b'', b'')
remove_bytes = all_bytes[:8] + all_bytes[14:32] # accept tabs and newlines
- query = {'nostream': '1', 'start': '%s' % offset}
+ query = {'nostream': '1', 'start': f'{offset}'}
if last:
query['last'] = 1
if lastsucceeded:
@@ -7025,7 +7020,7 @@ def get_dependson(apiurl: str, project: str, repository: str, arch: str, package
query = []
if packages:
for i in packages:
- query.append('package=%s' % quote_plus(i))
+ query.append(f'package={quote_plus(i)}')
if reverse:
query.append('view=revpkgnames')
@@ -7043,7 +7038,7 @@ def get_buildinfo(
query = []
if addlist:
for i in addlist:
- query.append('add=%s' % quote_plus(i))
+ query.append(f'add={quote_plus(i)}')
if debug:
query.append('debug=1')
@@ -7060,7 +7055,7 @@ def get_buildconfig(apiurl: str, prj: str, repository: str, path=None):
query = []
if path:
for prp in path:
- query.append('path=%s' % quote_plus(prp))
+ query.append(f'path={quote_plus(prp)}')
u = makeurl(apiurl, ['build', prj, repository, '_buildconfig'], query=query)
f = http_GET(u)
return f.read()
@@ -7173,7 +7168,7 @@ def print_jobhistory(apiurl: str, prj: str, current_package: str, repository: st
waitbuild = " %2dm %2ds" % (waittm / 60, waittm % 60)
if format == 'csv':
- print('%s|%s|%s|%s|%s|%s' % (endtime, package, reason, code, waitbuild, worker))
+ print(f'{endtime}|{package}|{reason}|{code}|{waitbuild}|{worker}')
else:
print('%s %-50s %-16s %-16s %-16s %-16s' % (endtime, package[0:49], reason[0:15], code[0:15], waitbuild, worker))
@@ -7236,17 +7231,17 @@ def get_commitlog(
r.append(s)
elif format == 'xml':
r.append('' % (rev, srcmd5))
- r.append('%s' % user)
- r.append('%s' % t)
- r.append('%s' % requestid)
- r.append('%s' % _private.api.xml_escape(decode_it(comment)))
+ r.append(f' revision="{rev}" srcmd5="{srcmd5}">')
+ r.append(f'{user}')
+ r.append(f'{t}')
+ r.append(f'{requestid}')
+ r.append(f'{_private.api.xml_escape(decode_it(comment))}')
r.append('')
else:
if requestid:
requestid = decode_it(b"rq" + requestid)
s = '-' * 76 + \
- '\nr%s | %s | %s | %s | %s | %s\n' % (rev, user, t, srcmd5, version, requestid) + \
+ f'\nr{rev} | {user} | {t} | {srcmd5} | {version} | {requestid}\n' + \
'\n' + decode_it(comment)
r.append(s)
@@ -7263,7 +7258,7 @@ def runservice(apiurl: str, prj: str, package: str):
try:
f = http_POST(u)
except HTTPError as e:
- e.osc_msg = 'could not trigger service run for project \'%s\' package \'%s\'' % (prj, package)
+ e.osc_msg = f'could not trigger service run for project \'{prj}\' package \'{package}\''
raise
root = ET.parse(f).getroot()
@@ -7276,7 +7271,7 @@ def waitservice(apiurl: str, prj: str, package: str):
try:
f = http_POST(u)
except HTTPError as e:
- e.osc_msg = 'The service for project \'%s\' package \'%s\' failed' % (prj, package)
+ e.osc_msg = f'The service for project \'{prj}\' package \'{package}\' failed'
raise
root = ET.parse(f).getroot()
@@ -7293,7 +7288,7 @@ def mergeservice(apiurl: str, prj: str, package: str):
try:
f = http_POST(u)
except HTTPError as e:
- e.osc_msg = 'could not merge service files in project \'%s\' package \'%s\'' % (prj, package)
+ e.osc_msg = f'could not merge service files in project \'{prj}\' package \'{package}\''
raise
root = ET.parse(f).getroot()
@@ -7315,7 +7310,7 @@ def rebuild(apiurl: str, prj: str, package: str, repo: str, arch: str, code=None
try:
f = http_POST(u)
except HTTPError as e:
- e.osc_msg = 'could not trigger rebuild for project \'%s\' package \'%s\'' % (prj, package)
+ e.osc_msg = f'could not trigger rebuild for project \'{prj}\' package \'{package}\''
raise
root = ET.parse(f).getroot()
@@ -7329,7 +7324,7 @@ def store_read_project(dir):
with open(os.path.join(dir, store, '_project')) as f:
p = f.readline().strip()
except OSError:
- msg = 'Error: \'%s\' is not an osc project dir or working copy' % os.path.abspath(dir)
+ msg = f'Error: \'{os.path.abspath(dir)}\' is not an osc project dir or working copy'
if os.path.exists(os.path.join(dir, '.svn')):
msg += '\nTry svn instead of osc.'
raise oscerr.NoWorkingCopy(msg)
@@ -7343,7 +7338,7 @@ def store_read_package(dir):
with open(os.path.join(dir, store, '_package')) as f:
p = f.readline().strip()
except OSError:
- msg = 'Error: \'%s\' is not an osc package working copy' % os.path.abspath(dir)
+ msg = f'Error: \'{os.path.abspath(dir)}\' is not an osc package working copy'
if os.path.exists(os.path.join(dir, '.svn')):
msg += '\nTry svn instead of osc.'
raise oscerr.NoWorkingCopy(msg)
@@ -7487,17 +7482,17 @@ def cmdbuild(
try:
f = http_POST(u)
except HTTPError as e:
- e.osc_msg = '%s command failed for project %s' % (cmd, project)
+ e.osc_msg = f'{cmd} command failed for project {project}'
if package:
- e.osc_msg += ' package %s' % package
+ e.osc_msg += f' package {package}'
if arch:
- e.osc_msg += ' arch %s' % arch
+ e.osc_msg += f' arch {arch}'
if repo:
- e.osc_msg += ' repository %s' % repo
+ e.osc_msg += f' repository {repo}'
if code:
- e.osc_msg += ' code=%s' % code
+ e.osc_msg += f' code={code}'
if sysrq:
- e.osc_msg += ' sysrq=%s' % code
+ e.osc_msg += f' sysrq={code}'
raise
root = ET.parse(f).getroot()
@@ -7636,10 +7631,10 @@ def xpath_join(expr, new_expr, op='or', inner=False, nexpr_parentheses=False):
parentheses = True
break
if parentheses:
- expr = '(%s)' % expr
+ expr = f'({expr})'
if nexpr_parentheses:
- new_expr = '(%s)' % new_expr
- return '%s %s %s' % (expr, op, new_expr)
+ new_expr = f'({new_expr})'
+ return f'{expr} {op} {new_expr}'
def search(apiurl: str, queries=None, **kwargs):
@@ -7720,7 +7715,7 @@ def set_link_rev(apiurl: str, project: str, package: str, revision="", expand=Fa
f = http_GET(url)
root = ET.parse(f).getroot()
except HTTPError as e:
- e.osc_msg = 'Unable to get _link file in package \'%s\' for project \'%s\'' % (package, project)
+ e.osc_msg = f'Unable to get _link file in package \'{package}\' for project \'{project}\''
raise
revision = _set_link_rev(apiurl, project, package, root, revision, expand=expand)
l = ET.tostring(root, encoding=ET_ENCODING)
@@ -7795,7 +7790,7 @@ def unpack_srcrpm(srpm, dir, *files):
only this files will be unpacked.
"""
if not is_srcrpm(srpm):
- print('error - \'%s\' is not a source rpm.' % srpm, file=sys.stderr)
+ print(f'error - \'{srpm}\' is not a source rpm.', file=sys.stderr)
sys.exit(1)
curdir = os.getcwd()
if os.path.isdir(dir):
@@ -7817,7 +7812,7 @@ def unpack_srcrpm(srpm, dir, *files):
if not ret:
ret = cpio_proc.returncode
if ret != 0:
- print('error \'%s\' - cannot extract \'%s\'' % (ret, srpm), file=sys.stderr)
+ print(f'error \'{ret}\' - cannot extract \'{srpm}\'', file=sys.stderr)
sys.exit(1)
os.chdir(curdir)
@@ -7885,7 +7880,7 @@ def addPerson(apiurl: str, prj: str, pac: str, user: str, role="maintainer"):
if not found:
# the xml has a fixed structure
root.insert(2, ET.Element('person', role=role, userid=user))
- print('user \'%s\' added to \'%s\'' % (user, pac or prj))
+ print(f'user \'{user}\' added to \'{pac or prj}\'')
edit_meta(metatype=kind,
path_args=path,
data=ET.tostring(root, encoding=ET_ENCODING))
@@ -7916,13 +7911,13 @@ def delPerson(apiurl: str, prj: str, pac: str, user: str, role="maintainer"):
if person.get('userid') == user and person.get('role') == role:
root.remove(person)
found = True
- print("user \'%s\' removed" % user)
+ print(f"user '{user}' removed")
if found:
edit_meta(metatype=kind,
path_args=path,
data=ET.tostring(root, encoding=ET_ENCODING))
else:
- print("user \'%s\' not found in \'%s\'" % (user, pac or prj))
+ print(f"user '{user}' not found in '{pac or prj}'")
else:
print("an error occured")
@@ -8004,9 +7999,9 @@ def createPackageDir(pathname, prj_obj=None):
prj.addPackage(pac_dir)
print(statfrmt('A', os.path.normpath(pathname)))
else:
- raise oscerr.OscIOError(None, 'file or directory \'%s\' already exists' % pathname)
+ raise oscerr.OscIOError(None, f'file or directory \'{pathname}\' already exists')
else:
- msg = '\'%s\' is not a working copy' % prj_dir
+ msg = f'\'{prj_dir}\' is not a working copy'
if os.path.exists(os.path.join(prj_dir, '.svn')):
msg += '\ntry svn instead of osc.'
raise oscerr.NoWorkingCopy(msg)
@@ -8090,7 +8085,7 @@ def addDownloadUrlService(url):
def addFiles(filenames, prj_obj=None, force=False):
for filename in filenames:
if not os.path.exists(filename):
- raise oscerr.OscIOError(None, 'file \'%s\' does not exist' % filename)
+ raise oscerr.OscIOError(None, f'file \'{filename}\' does not exist')
# TODO: this function needs improvement
# it should check if we're in a project or a package working copy and behave accordingly
@@ -8107,7 +8102,7 @@ def addFiles(filenames, prj_obj=None, force=False):
prj_apiurl = store.apiurl
Package.init_package(prj_apiurl, prj_name, pac_dir, filename)
elif is_package_dir(filename) and conf.config['do_package_tracking']:
- print('osc: warning: \'%s\' is already under version control' % filename)
+ print(f'osc: warning: \'{filename}\' is already under version control')
pacs.remove(filename)
elif os.path.isdir(filename) and is_project_dir(prj_dir):
raise oscerr.WrongArgs('osc: cannot add a directory to a project unless '
@@ -8118,12 +8113,12 @@ def addFiles(filenames, prj_obj=None, force=False):
filename = os.path.normpath(filename)
directory = os.path.join(filename, os.pardir)
if not is_package_dir(directory):
- print('osc: warning: \'%s\' cannot be associated to a package' % filename)
+ print(f'osc: warning: \'{filename}\' cannot be associated to a package')
continue
- resp = raw_input("%s is a directory, do you want to archive it for submission? (y/n) " % (filename))
+ resp = raw_input(f"{filename} is a directory, do you want to archive it for submission? (y/n) ")
if resp not in ('y', 'Y'):
continue
- archive = "%s.obscpio" % filename
+ archive = f"{filename}.obscpio"
todo = [os.path.join(p, elm)
for p, dirnames, fnames in os.walk(filename, followlinks=False)
for elm in dirnames + fnames]
@@ -8142,22 +8137,22 @@ def addFiles(filenames, prj_obj=None, force=False):
print(statfrmt('A', getTransActPath(os.path.join(pac.dir, os.pardir, pac.name))))
for filename in pac.filenamelist_unvers:
if os.path.isdir(os.path.join(pac.dir, filename)):
- print('skipping directory \'%s\'' % os.path.join(pac.dir, filename))
+ print(f'skipping directory \'{os.path.join(pac.dir, filename)}\'')
else:
pac.todo.append(filename)
elif pac.name in prj.pacs_have:
- print('osc: warning: \'%s\' is already under version control' % pac.name)
+ print(f'osc: warning: \'{pac.name}\' is already under version control')
for filename in pac.todo:
if filename in pac.skipped:
continue
if filename in pac.excluded and not force:
- print('osc: warning: \'%s\' is excluded from a working copy' % filename, file=sys.stderr)
+ print(f'osc: warning: \'{filename}\' is excluded from a working copy', file=sys.stderr)
continue
try:
pac.addfile(filename)
except oscerr.PackageFileConflict as e:
fname = os.path.join(getTransActPath(pac.dir), filename)
- print('osc: warning: \'%s\' is already under version control' % fname)
+ print(f'osc: warning: \'{fname}\' is already under version control')
def getPrjPacPaths(path):
@@ -8255,7 +8250,7 @@ def get_commit_msg(wc_dir, pacs):
changed = [statfrmt(st, os.path.normpath(os.path.join(p.dir, filename))) for st, filename in states]
if changed:
footer += changed
- footer.append('\nDiff for working copy: %s' % p.dir)
+ footer.append(f'\nDiff for working copy: {p.dir}')
footer.extend([''.join(decode_list(i)) for i in p.get_diff(ignoreUnversioned=True)])
lines.extend(get_commit_message_template(p))
if template is None:
@@ -8287,7 +8282,7 @@ def print_request_list(apiurl, project, package=None, states=("new", "review"),
if package is None and requests:
print(msg % ('project', project, len(requests)))
elif requests:
- print(msg % ('package', '/'.join([project, package]), len(requests)))
+ print(msg % ('package', f"{project}/{package}", len(requests)))
for r in requests:
print(r.list_view(), '\n')
@@ -8388,13 +8383,13 @@ def request_interactive_review(apiurl, request, initial_cmd='', group=None,
if newline:
print()
for action in src_actions:
- print('%s/%s:' % (action.src_project, action.src_package))
+ print(f'{action.src_project}/{action.src_package}:')
try:
print('\n'.join(get_results(apiurl, action.src_project, action.src_package)))
except HTTPError as e:
if e.code != 404:
raise
- print('unable to retrieve the buildstatus: %s' % e)
+ print(f'unable to retrieve the buildstatus: {e}')
def get_formatted_issues(apiurl, reqid):
"""get issue_list and return a printable string"""
@@ -8474,7 +8469,7 @@ def request_interactive_review(apiurl, request, initial_cmd='', group=None,
print_request(request)
print_comments(apiurl, 'request', request.reqid)
elif repl == 's':
- print('skipping: #%s' % request.reqid, file=sys.stderr)
+ print(f'skipping: #{request.reqid}', file=sys.stderr)
break
elif repl == 'c':
print('Aborting', file=sys.stderr)
@@ -8505,7 +8500,7 @@ def request_interactive_review(apiurl, request, initial_cmd='', group=None,
state_map = {'a': 'accepted', 'd': 'declined', 'r': 'revoked'}
mo = re.search(r'^([adrl])(?:\s+(-f)?\s*-m\s+(.*))?$', repl)
if mo is None or orequest and mo.group(1) != 'a':
- print('invalid choice: \'%s\'' % repl, file=sys.stderr)
+ print(f'invalid choice: \'{repl}\'', file=sys.stderr)
continue
state = state_map.get(mo.group(1))
force = mo.group(2) is not None
@@ -8538,7 +8533,7 @@ def request_interactive_review(apiurl, request, initial_cmd='', group=None,
repl = raw_input('Supersede original request? (y|N) ')
if repl in ('y', 'Y'):
safe_change_request_state(apiurl, orequest.reqid, 'superseded',
- 'superseded by %s' % request.reqid, request.reqid, force=force)
+ f'superseded by {request.reqid}', request.reqid, force=force)
elif state is None:
clone_request(apiurl, request.reqid, msg)
else:
@@ -8565,10 +8560,10 @@ def request_interactive_review(apiurl, request, initial_cmd='', group=None,
try:
num = int(num)
except ValueError:
- print('\'%s\' is not a number.' % num)
+ print(f'\'{num}\' is not a number.')
continue
if num < 0 or num >= len(reviews):
- print('number \'%s\' out of range.' % num)
+ print(f'number \'{num}\' out of range.')
continue
review = reviews[num]
change_review_state(apiurl, request.reqid, state, by_user=review.by_user,
@@ -8593,14 +8588,14 @@ def edit_submitrequest(apiurl, project, orequest, new_request=None):
# it is safe to use orequest because currently the formatting
# of a submit action does not need instance specific data
fmt = orequest.format_action(actions[i])
- print('(%i)' % i, '%(source)s %(target)s' % fmt)
+ print('(%i)' % i, f"{fmt['source']} {fmt['target']}")
num = raw_input('> ')
try:
num = int(num)
except ValueError:
- raise oscerr.WrongArgs('\'%s\' is not a number.' % num)
+ raise oscerr.WrongArgs(f'\'{num}\' is not a number.')
if num < 0 or num >= len(orequest.actions):
- raise oscerr.WrongArgs('number \'%s\' out of range.' % num)
+ raise oscerr.WrongArgs(f'number \'{num}\' out of range.')
# the api replaced ':' with '_' in prj and pkg names (clone request)
package = '%s.%s' % (oactions[num].src_package.replace(':', '_'),
@@ -8635,7 +8630,7 @@ def edit_submitrequest(apiurl, project, orequest, new_request=None):
if cleanup:
shutil.rmtree(tmpdir)
else:
- print('Please remove the dir \'%s\' manually' % tmpdir)
+ print(f'Please remove the dir \'{tmpdir}\' manually')
r = Request()
for action in orequest.get_actions():
new_action = Action.from_xml(action.to_xml())
@@ -8652,15 +8647,15 @@ def edit_submitrequest(apiurl, project, orequest, new_request=None):
def get_user_projpkgs(apiurl, user, role=None, exclude_projects=None, proj=True, pkg=True, maintained=False, metadata=False):
"""Return all project/packages where user is involved."""
exclude_projects = exclude_projects or []
- xpath = 'person/@userid = \'%s\'' % user
+ xpath = f'person/@userid = \'{user}\''
excl_prj = ''
excl_pkg = ''
for i in exclude_projects:
- excl_prj = xpath_join(excl_prj, 'not(@name = \'%s\')' % i, op='and')
- excl_pkg = xpath_join(excl_pkg, 'not(@project = \'%s\')' % i, op='and')
+ excl_prj = xpath_join(excl_prj, f'not(@name = \'{i}\')', op='and')
+ excl_pkg = xpath_join(excl_pkg, f'not(@project = \'{i}\')', op='and')
role_filter_xpath = xpath
if role:
- xpath = xpath_join(xpath, 'person/@role = \'%s\'' % role, inner=True, op='and')
+ xpath = xpath_join(xpath, f'person/@role = \'{role}\'', inner=True, op='and')
xpath_pkg = xpath_join(xpath, excl_pkg, op='and')
xpath_prj = xpath_join(xpath, excl_prj, op='and')
@@ -8880,13 +8875,13 @@ def checkout_deleted_package(apiurl: str, proj: str, pkg: str, dst):
query['deleted'] = 1
if os.path.isdir(dst):
- print('Restoring in existing directory %s' % dst)
+ print(f'Restoring in existing directory {dst}')
else:
- print('Creating %s' % dst)
+ print(f'Creating {dst}')
os.makedirs(dst)
for filename in pl:
- print('Restoring %s to %s' % (filename, dst))
+ print(f'Restoring {filename} to {dst}')
full_file_path = os.path.join(dst, filename)
u = makeurl(apiurl, ['source', proj, pkg, filename], query=query)
with open(full_file_path, 'wb') as f:
@@ -8920,7 +8915,7 @@ def vc_export_env(apiurl: str, quiet=False):
if val != '-':
tag2val[tag] = val
elif not quiet:
- msg = 'Try env %s=...' % tag2envs[tag][0]
+ msg = f'Try env {tag2envs[tag][0]}=...'
print(msg, file=sys.stderr)
for (tag, val) in tag2val.items():
diff --git a/osc/credentials.py b/osc/credentials.py
index 8b77de31..0674a8d9 100644
--- a/osc/credentials.py
+++ b/osc/credentials.py
@@ -211,7 +211,7 @@ class KeyringCredentialsManager(AbstractCredentialsManager):
def set_password(self, url, user, password):
self._load_backend()
keyring.set_password(urlsplit(url)[1], user, password)
- config_value = self._qualified_name() + ':' + self._backend_cls_name
+ config_value = f"{self._qualified_name()}:{self._backend_cls_name}"
self._cp.set(url, self.config_entry, config_value)
def delete_password(self, url, user):
@@ -317,7 +317,7 @@ def create_credentials_manager(url, cp):
def qualified_name(obj):
- return obj.__module__ + '.' + obj.__class__.__name__
+ return f"{obj.__module__}.{obj.__class__.__name__}"
def has_keyring_support():
diff --git a/osc/fetch.py b/osc/fetch.py
index bcee5dde..8ef1a799 100644
--- a/osc/fetch.py
+++ b/osc/fetch.py
@@ -45,23 +45,23 @@ class Fetcher:
self.gr = OscFileGrabber(progress_obj=self.progress_obj)
def __add_cpio(self, pac):
- prpap = '%s/%s/%s/%s' % (pac.project, pac.repository, pac.repoarch, pac.repopackage)
+ prpap = f'{pac.project}/{pac.repository}/{pac.repoarch}/{pac.repopackage}'
self.cpio.setdefault(prpap, {})[pac.repofilename] = pac
def __download_cpio_archive(self, apiurl, project, repo, arch, package, **pkgs):
if not pkgs:
return
- query = ['binary=%s' % quote_plus(i) for i in pkgs]
+ query = [f'binary={quote_plus(i)}' for i in pkgs]
query.append('view=cpio')
for module in self.modules:
- query.append('module=' + module)
+ query.append(f"module={module}")
try:
url = makeurl(apiurl, ['build', project, repo, arch, package], query=query)
sys.stdout.write("preparing download ...\r")
sys.stdout.flush()
with tempfile.NamedTemporaryFile(prefix='osc_build_cpio') as tmparchive:
self.gr.urlgrab(url, filename=tmparchive.name,
- text='fetching packages for \'%s\'' % project)
+ text=f'fetching packages for \'{project}\'')
archive = cpio.CpioRead(tmparchive.name)
archive.read()
for hdr in archive:
@@ -133,7 +133,7 @@ class Fetcher:
mg = OscMirrorGroup(self.gr, pac.urllist)
if self.http_debug:
- print('\nURLs to try for package \'%s\':' % pac, file=sys.stderr)
+ print(f'\nURLs to try for package \'{pac}\':', file=sys.stderr)
print('\n'.join(pac.urllist), file=sys.stderr)
print(file=sys.stderr)
@@ -141,7 +141,7 @@ class Fetcher:
with tempfile.NamedTemporaryFile(prefix='osc_build',
delete=False) as tmpfile:
mg_stat = mg.urlgrab(pac.filename, filename=tmpfile.name,
- text='%s(%s) %s' % (prefix, pac.project, pac.filename))
+ text=f'{prefix}({pac.project}) {pac.filename}')
if mg_stat:
self.move_package(tmpfile.name, pac.localdir, pac)
@@ -198,7 +198,7 @@ class Fetcher:
if self.download_api_only:
return []
urllist = self.urllist
- key = '%s/%s' % (pac.project, pac.repository)
+ key = f'{pac.project}/{pac.repository}'
project_repo_url = buildinfo.urls.get(key)
if project_repo_url is not None:
urllist = [project_repo_url]
@@ -290,7 +290,7 @@ class Fetcher:
prjs = list(buildinfo.projects.keys())
for i in prjs:
- dest = "%s/%s" % (self.cachedir, i)
+ dest = f"{self.cachedir}/{i}"
if not os.path.exists(dest):
os.makedirs(dest, mode=0o755)
dest += '/_pubkey'
@@ -322,8 +322,8 @@ class Fetcher:
if try_parent:
if self.http_debug:
- print("can't fetch key for %s" % (i), file=sys.stderr)
- print("url: %s" % url, file=sys.stderr)
+ print(f"can't fetch key for {i}", file=sys.stderr)
+ print(f"url: {url}", file=sys.stderr)
if os.path.exists(dest):
os.unlink(dest)
diff --git a/osc/meter.py b/osc/meter.py
index bf84b402..b0317770 100644
--- a/osc/meter.py
+++ b/osc/meter.py
@@ -17,10 +17,10 @@ class PBTextMeter:
def start(self, basename, size=None):
if size is None:
- widgets = [basename + ': ', pb.AnimatedMarker(), ' ', pb.Timer()]
+ widgets = [f"{basename}: ", pb.AnimatedMarker(), ' ', pb.Timer()]
self.bar = pb.ProgressBar(widgets=widgets, maxval=pb.UnknownLength)
else:
- widgets = [basename + ': ', pb.Bar(), ' ', pb.ETA()]
+ widgets = [f"{basename}: ", pb.Bar(), ' ', pb.ETA()]
if size:
# if size is 0, using pb.Percentage will result in
# a ZeroDivisionException
diff --git a/osc/oscerr.py b/osc/oscerr.py
index afd272d6..686a4161 100644
--- a/osc/oscerr.py
+++ b/osc/oscerr.py
@@ -189,7 +189,7 @@ class OscInvalidRevision(OscValueError):
"""
def __str__(self):
- return "Invalid revision value: {}".format("".join(self.args))
+ return f"Invalid revision value: {''.join(self.args)}"
class PackageNotInstalled(OscBaseError):
@@ -201,7 +201,7 @@ class PackageNotInstalled(OscBaseError):
super().__init__((pkg,))
def __str__(self):
- return 'Package %s is required for this operation' % self.args
+ return f'Package {self.args} is required for this operation'
class SignalInterrupt(Exception):
diff --git a/osc/store.py b/osc/store.py
index 29eeb34a..91b569d8 100644
--- a/osc/store.py
+++ b/osc/store.py
@@ -137,7 +137,7 @@ class Store:
if not isinstance(value, str):
msg = f"The argument `value` should be str, not {type(value).__name__}"
raise TypeError(msg)
- self.write_file(fn, value + "\n", subdir=subdir)
+ self.write_file(fn, f"{value}\n", subdir=subdir)
def read_int(self, fn):
if not self.exists(fn):