diff --git a/osc/OscConfigParser.py b/osc/OscConfigParser.py index 475845fa..eb718dc2 100644 --- a/osc/OscConfigParser.py +++ b/osc/OscConfigParser.py @@ -26,6 +26,7 @@ class ConfigLineOrder: It keeps track of all lines (including comments) in the _lines list. This list either contains SectionLine() instances or CommentLine() instances. """ + def __init__(self): self._lines = [] @@ -56,7 +57,7 @@ class ConfigLineOrder: self._append(CommentLine(line)) def keys(self): - return [ i.name for i in self._lines if i.type == 'section' ] + return [i.name for i in self._lines if i.type == 'section'] def __setitem__(self, key, value): section = SectionLine(key) @@ -75,27 +76,30 @@ class ConfigLineOrder: self._lines.remove(line) def __iter__(self): - #return self._lines.__iter__() + # return self._lines.__iter__() for line in self._lines: if line.type == 'section': yield line.name + class Line: """Base class for all line objects""" + def __init__(self, name, type): self.name = name self.type = type + class SectionLine(Line): """ This class represents a [section]. It stores all lines which belongs to this certain section in the _lines list. The _lines list either contains CommentLine() or OptionLine() instances. """ - def __init__(self, sectname, dict = {}): - Line.__init__(self, sectname, 'section') + + def __init__(self, sectname): + super().__init__(sectname, 'section') self._lines = [] - self._dict = dict def _find(self, name): for line in self._lines: @@ -103,7 +107,7 @@ class SectionLine(Line): return line return None - def _add_option(self, optname, value = None, line = None, sep = '='): + def _add_option(self, optname, value=None, line=None, sep='='): if value is None and line is None: raise configparser.Error('Either value or line must be passed in') elif value and line: @@ -124,10 +128,10 @@ class SectionLine(Line): return dict(self.items()) def items(self): - return [ (i.name, i.value) for i in self._lines if i.type == 'option' ] + return [(i.name, i.value) for i in self._lines if i.type == 'option'] def keys(self): - return [ i.name for i in self._lines ] + return [i.name for i in self._lines] def __setitem__(self, key, val): self._add_option(key, val) @@ -155,12 +159,14 @@ class SectionLine(Line): class CommentLine(Line): """Store a commentline""" + def __init__(self, line): - Line.__init__(self, line.strip('\n'), 'comment') + super().__init__(line.strip('\n'), 'comment') def __str__(self): return self.name + class OptionLine(Line): """ This class represents an option. The class' ``name`` attribute is used @@ -177,7 +183,7 @@ class OptionLine(Line): """ def __init__(self, optname, line): - Line.__init__(self, optname, 'option') + super().__init__(optname, 'option') self.name = optname self.format(line) @@ -203,8 +209,9 @@ class OscConfigParser(configparser.ConfigParser): In order to keep the order and the format it makes use of the ConfigLineOrder() class. """ - def __init__(self, defaults={}): - super().__init__(defaults) + + def __init__(self, defaults=None): + super().__init__(defaults or {}) self._sections = ConfigLineOrder() # XXX: unfortunately we have to override the _read() method from the ConfigParser() @@ -280,7 +287,7 @@ class OscConfigParser(configparser.ConfigParser): # ';' is a comment delimiter only if it follows # a spacing character pos = optval.find(';') - if pos != -1 and optval[pos-1].isspace(): + if pos != -1 and optval[pos - 1].isspace(): optval = optval[:pos] optval = optval.strip() # allow empty values @@ -301,9 +308,9 @@ class OscConfigParser(configparser.ConfigParser): e.append(lineno, repr(line)) # if any parsing errors occurred, raise an exception if e: - raise e # pylint: disable-msg=E0702 + raise e # pylint: disable-msg=E0702 - def write(self, fp, comments = False): + def write(self, fp, comments=False): """ write the configuration file. If comments is True all comments etc. will be written to fp otherwise the ConfigParsers' default write method diff --git a/osc/babysitter.py b/osc/babysitter.py index 20080afb..750e140d 100644 --- a/osc/babysitter.py +++ b/osc/babysitter.py @@ -111,7 +111,7 @@ def run(prg, argv=None): if b'' in body: msg = body.split(b'')[1] msg = msg.split(b'')[0] - msg = msg.replace(b'<', b'<').replace(b'>' , b'>').replace(b'&', b'&') + msg = msg.replace(b'<', b'<').replace(b'>', b'>').replace(b'&', b'&') print(decode_it(msg), file=sys.stderr) if e.code >= 500 and e.code <= 599: print('\nRequest: %s' % e.filename) @@ -164,9 +164,9 @@ def run(prg, argv=None): except (oscerr.PackageExists, oscerr.PackageMissing, oscerr.WorkingCopyInconsistent) as e: print(e.msg, file=sys.stderr) except oscerr.PackageInternalError as e: - print('a package internal error occured\n' \ - 'please file a bug and attach your current package working copy ' \ - 'and the following traceback to it:', file=sys.stderr) + print('a package internal error occured\n' + 'please file a bug and attach your current package working copy ' + 'and the following traceback to it:', file=sys.stderr) print(e.msg, file=sys.stderr) traceback.print_exc(file=sys.stderr) except oscerr.PackageError as e: diff --git a/osc/build.py b/osc/build.py index fab14b13..482fea50 100644 --- a/osc/build.py +++ b/osc/build.py @@ -3,6 +3,7 @@ # and distributed under the terms of the GNU General Public Licence, # either version 2, or (at your option) any later version. +import glob import os import re import shutil @@ -22,54 +23,58 @@ from .core import get_buildinfo, store_read_project, store_read_package, meta_ex from .core import get_binarylist, get_binary_file, run_external, return_external, raw_input from .fetch import Fetcher, OscFileGrabber, verify_pacs from .meter import create_text_meter -from .util import rpmquery, debquery, archquery +from .util import cpio +from .util import archquery, debquery, packagequery, rpmquery +from .util import repodata from .util.helper import decode_it change_personality = { - 'i686': 'linux32', - 'i586': 'linux32', - 'i386': 'linux32', - 'ppc': 'powerpc32', - 's390': 's390', - 'sparc': 'linux32', - 'sparcv8': 'linux32', - } + 'i686': 'linux32', + 'i586': 'linux32', + 'i386': 'linux32', + 'ppc': 'powerpc32', + 's390': 's390', + 'sparc': 'linux32', + 'sparcv8': 'linux32', +} can_also_build = { - 'aarch64': ['aarch64'], # only needed due to used heuristics in build parameter evaluation - 'armv6l': [ 'armv4l', 'armv5l', 'armv6l', 'armv5el', 'armv6el' ], - 'armv7l': [ 'armv4l', 'armv5l', 'armv6l', 'armv7l', 'armv5el', 'armv6el', 'armv7el' ], - 'armv5el': [ 'armv4l', 'armv5l', 'armv5el' ], # not existing arch, just for compatibility - 'armv6el': [ 'armv4l', 'armv5l', 'armv6l', 'armv5el', 'armv6el' ], # not existing arch, just for compatibility - 'armv6hl': [ 'armv4l', 'armv5l', 'armv6l', 'armv5el', 'armv6el' ], - 'armv7el': [ 'armv4l', 'armv5l', 'armv6l', 'armv7l', 'armv5el', 'armv6el', 'armv7el' ], # not existing arch, just for compatibility - 'armv7hl': [ 'armv7hl' ], # not existing arch, just for compatibility - 'armv8el': [ 'armv4l', 'armv5el', 'armv6el', 'armv7el', 'armv8el' ], # not existing arch, just for compatibility - 'armv8l': [ 'armv4l', 'armv5el', 'armv6el', 'armv7el', 'armv8el' ], # not existing arch, just for compatibility - 'armv5tel': [ 'armv4l', 'armv5el', 'armv5tel' ], - 's390x': ['s390' ], - 'ppc64': [ 'ppc', 'ppc64', 'ppc64p7', 'ppc64le' ], - 'ppc64le': [ 'ppc64le', 'ppc64' ], - 'i586': [ 'i386' ], - 'i686': [ 'i586', 'i386' ], - 'x86_64': ['i686', 'i586', 'i386' ], - 'sparc64': ['sparc64v', 'sparcv9v', 'sparcv9', 'sparcv8', 'sparc'], - 'parisc': ['hppa'], - } + 'aarch64': ['aarch64'], # only needed due to used heuristics in build parameter evaluation + 'armv6l': ['armv4l', 'armv5l', 'armv6l', 'armv5el', 'armv6el'], + 'armv7l': ['armv4l', 'armv5l', 'armv6l', 'armv7l', 'armv5el', 'armv6el', 'armv7el'], + 'armv5el': ['armv4l', 'armv5l', 'armv5el'], # not existing arch, just for compatibility + 'armv6el': ['armv4l', 'armv5l', 'armv6l', 'armv5el', 'armv6el'], # not existing arch, just for compatibility + 'armv6hl': ['armv4l', 'armv5l', 'armv6l', 'armv5el', 'armv6el'], + 'armv7el': ['armv4l', 'armv5l', 'armv6l', 'armv7l', 'armv5el', 'armv6el', 'armv7el'], # not existing arch, just for compatibility + 'armv7hl': ['armv7hl'], # not existing arch, just for compatibility + 'armv8el': ['armv4l', 'armv5el', 'armv6el', 'armv7el', 'armv8el'], # not existing arch, just for compatibility + 'armv8l': ['armv4l', 'armv5el', 'armv6el', 'armv7el', 'armv8el'], # not existing arch, just for compatibility + 'armv5tel': ['armv4l', 'armv5el', 'armv5tel'], + 's390x': ['s390'], + 'ppc64': ['ppc', 'ppc64', 'ppc64p7', 'ppc64le'], + 'ppc64le': ['ppc64le', 'ppc64'], + 'i586': ['i386'], + 'i686': ['i586', 'i386'], + 'x86_64': ['i686', 'i586', 'i386'], + 'sparc64': ['sparc64v', 'sparcv9v', 'sparcv9', 'sparcv8', 'sparc'], + 'parisc': ['hppa'], +} # real arch of this machine hostarch = os.uname()[4] -if hostarch == 'i686': # FIXME +if hostarch == 'i686': # FIXME hostarch = 'i586' if hostarch == 'parisc': hostarch = 'hppa' + class Buildinfo: """represent the contents of a buildinfo file""" - def __init__(self, filename, apiurl, buildtype = 'spec', localpkgs = [], binarytype = 'rpm'): + def __init__(self, filename, apiurl, buildtype='spec', localpkgs=None, binarytype='rpm'): + localpkgs = localpkgs or [] try: tree = ET.parse(filename) except: @@ -81,7 +86,7 @@ class Buildinfo: self.apiurl = apiurl - if root.find('error') != None: + if root.find('error') is not None: sys.stderr.write('buildinfo is broken... it says:\n') error = root.find('error').text if error.startswith('unresolvable: '): @@ -118,16 +123,16 @@ class Buildinfo: # hostarch: The architecture of the build environment (build arch in GNU defintion) # crossarch: Same as hostarch, but indicating that a sysroot with an incompatible architecture exists self.buildarch = root.find('arch').text - if root.find('crossarch') != None: + if root.find('crossarch') is not None: self.crossarch = root.find('crossarch').text else: self.crossarch = None - if root.find('hostarch') != None: + if root.find('hostarch') is not None: self.hostarch = root.find('hostarch').text else: self.hostarch = None - if root.find('release') != None: + if root.find('release') is not None: self.release = root.find('release').text else: self.release = None @@ -141,7 +146,7 @@ class Buildinfo: self.downloadurl = root.get('downloadurl') self.debuginfo = 0 - if root.find('debuginfo') != None: + if root.find('debuginfo') is not None: try: self.debuginfo = int(root.find('debuginfo').text) except ValueError: @@ -162,8 +167,8 @@ class Buildinfo: apiurl, localpkgs) else: pac_arch = self.crossarch - if pac_arch == None: - pac_arch = self.buildarch + if pac_arch is None: + pac_arch = self.buildarch p = Pac(node, pac_arch, self.pacsuffix, apiurl, localpkgs) if p.project: @@ -172,27 +177,26 @@ class Buildinfo: for node in root.findall('path'): # old simple list for compatibility # XXX: really old? This is currently used for kiwi builds - self.pathes.append(node.get('project')+"/"+node.get('repository')) + self.pathes.append(node.get('project') + "/" + node.get('repository')) # a hash providing the matching URL for specific repos for newer OBS instances if node.get('url'): baseurl = node.get('url').replace('%', '%%') if config['api_host_options'][apiurl]['downloadurl']: # Add the path element to the download url override. baseurl = config['api_host_options'][apiurl]['downloadurl'] + urlsplit(node.get('url'))[2] - self.urls[node.get('project')+"/"+node.get('repository')] = baseurl + '/%(arch)s/%(filename)s' + self.urls[node.get('project') + "/" + node.get('repository')] = baseurl + '/%(arch)s/%(filename)s' - self.vminstall_list = [ dep.name for dep in self.deps if dep.vminstall ] - self.preinstall_list = [ dep.name for dep in self.deps if dep.preinstall ] - self.runscripts_list = [ dep.name for dep in self.deps if dep.runscripts ] - self.noinstall_list = [ dep.name for dep in self.deps if dep.noinstall ] - self.installonly_list = [ dep.name for dep in self.deps if dep.installonly ] + self.vminstall_list = [dep.name for dep in self.deps if dep.vminstall] + self.preinstall_list = [dep.name for dep in self.deps if dep.preinstall] + self.runscripts_list = [dep.name for dep in self.deps if dep.runscripts] + self.noinstall_list = [dep.name for dep in self.deps if dep.noinstall] + self.installonly_list = [dep.name for dep in self.deps if dep.installonly] - if root.find('preinstallimage') != None: + if root.find('preinstallimage') is not None: self.preinstallimage = root.find('preinstallimage') else: self.preinstallimage = None - def has_dep(self, name): for i in self.deps: if i.name == name: @@ -211,15 +215,16 @@ class Pac: We build a map that's later used to fill our URL templates """ - def __init__(self, node, buildarch, pacsuffix, apiurl, localpkgs = []): + def __init__(self, node, buildarch, pacsuffix, apiurl, localpkgs=None): + localpkgs = localpkgs or [] self.mp = {} for i in ['binary', 'package', 'epoch', 'version', 'release', 'hdrmd5', 'project', 'repository', 'sysroot', 'preinstall', 'vminstall', 'runscripts', 'noinstall', 'installonly', 'notmeta', - ]: + ]: self.mp[i] = node.get(i) self.mp['buildarch'] = buildarch @@ -229,10 +234,10 @@ class Pac: self.mp['name'] = node.get('name') or self.mp['binary'] # this is not the ideal place to check if the package is a localdep or not - localdep = self.mp['name'] in localpkgs # and not self.mp['noinstall'] + localdep = self.mp['name'] in localpkgs # and not self.mp['noinstall'] if not localdep and not (node.get('project') and node.get('repository')): raise oscerr.APIError('incomplete information for package %s, may be caused by a broken project configuration.' - % self.mp['name'] ) + % self.mp['name']) if not localdep: self.mp['extproject'] = node.get('project').replace(':', ':/') @@ -243,7 +248,7 @@ class Pac: if pacsuffix == 'deb' and not (self.mp['name'] and self.mp['arch'] and self.mp['version']): raise oscerr.APIError( "buildinfo for package %s/%s/%s is incomplete" - % (self.mp['name'], self.mp['arch'], self.mp['version'])) + % (self.mp['name'], self.mp['arch'], self.mp['version'])) self.mp['apiurl'] = apiurl @@ -278,7 +283,6 @@ class Pac: # make the content of the dictionary accessible as class attributes self.__dict__.update(self.mp) - def makeurls(self, cachedir, urllist): self.localdir = '%s/%s/%s/%s' % (cachedir, self.project, self.repository, self.repoarch) self.fullfilename = os.path.join(self.localdir, self.canonname) @@ -347,6 +351,7 @@ def get_preinstall_image(apiurl, arch, cache_dir, img_info, offline=False): os.rename(ifile_path_part, ifile_path) return (imagefile, imagesource, img_bins) + def get_built_files(pacdir, buildtype): if buildtype == 'spec': debs_dir = os.path.join(pacdir, 'DEBS') @@ -438,6 +443,7 @@ def get_built_files(pacdir, buildtype): s_built = '' return s_built, b_built + def get_repo(path): """Walks up path looking for any repodata directories. @@ -464,9 +470,8 @@ def get_repo(path): return repositoryDirectory + def get_prefer_pkgs(dirs, wanted_arch, type, cpio): - import glob - from .util import repodata, packagequery paths = [] repositories = [] @@ -501,7 +506,7 @@ def get_prefer_pkgs(dirs, wanted_arch, type, cpio): packageQueries.add(packageQuery) prefer_pkgs = {decode_it(name): packageQuery.path() - for name, packageQuery in packageQueries.items()} + for name, packageQuery in packageQueries.items()} depfile = create_deps(packageQueries.values()) cpio.add(b'deps', b'\n'.join(depfile)) @@ -539,14 +544,16 @@ trustprompt = """Would you like to ... 1 - always trust packages from '%(project)s' 2 - trust packages just this time ? """ + + def check_trusted_projects(apiurl, projects): trusted = config['api_host_options'][apiurl]['trusted_prj'] tlen = len(trusted) for prj in projects: - if not prj in trusted: + if prj not in trusted: print("\nThe build root needs packages from project '%s'." % prj) print("Note that malicious packages can compromise the build result or even your system.") - r = raw_input(trustprompt % { 'project': prj }) + r = raw_input(trustprompt % {'project': prj}) if r == '1': print("adding '%s' to oscrc: ['%s']['trusted_prj']" % (prj, apiurl)) trusted.append(prj) @@ -558,6 +565,7 @@ def check_trusted_projects(apiurl, projects): config['api_host_options'][apiurl]['trusted_prj'] = trusted conf.config_set_option(apiurl, 'trusted_prj', ' '.join(trusted)) + def get_kiwipath_from_buildinfo(bi, prj, repo): # If the project does not have a path defined we need to get the config # via the repositories in the kiwi file. Unfortunately the buildinfo @@ -573,6 +581,7 @@ def get_kiwipath_from_buildinfo(bi, prj, repo): kiwipath.insert(0, myprp) return kiwipath + def calculate_prj_pac(opts, descr): project = opts.alternative_project or store_read_project('.') if opts.local_package: @@ -581,16 +590,19 @@ def calculate_prj_pac(opts, descr): package = store_read_package('.') return project, package + def calculate_build_root(apihost, prj, pac, repo, arch): buildroot = os.environ.get('OSC_BUILD_ROOT', config['build-root']) \ - % {'repo': repo, 'arch': arch, 'project': prj, 'package': pac, 'apihost': apihost} + % {'repo': repo, 'arch': arch, 'project': prj, 'package': pac, 'apihost': apihost} return buildroot + def build_as_user(): if os.environ.get('OSC_SU_WRAPPER', config['su-wrapper']).split(): return False return True + def su_wrapper(cmd): sucmd = os.environ.get('OSC_SU_WRAPPER', config['su-wrapper']).split() if sucmd: @@ -602,6 +614,7 @@ def su_wrapper(cmd): cmd = sucmd + cmd return cmd + def run_build(opts, *args): cmd = [config['build-cmd']] cmd += args @@ -612,6 +625,7 @@ def run_build(opts, *args): cmd.append('--norootforbuild') return run_external(cmd[0], *cmd[1:]) + def main(apiurl, opts, argv): repo = argv[0] @@ -758,7 +772,8 @@ def main(apiurl, opts, argv): for var in ['OSC_PACKAGECACHEDIR', 'OSC_SU_WRAPPER', 'OSC_BUILD_ROOT']: val = os.getenv(var) if val: - if var.startswith('OSC_'): var = var[4:] + if var.startswith('OSC_'): + var = var[4:] var = var.lower().replace('_', '-') if var in config: print('Overriding config value for %s=\'%s\' with \'%s\'' % (var, config[var], val)) @@ -781,7 +796,7 @@ def main(apiurl, opts, argv): build_root = config['api_host_options'][apiurl].get('build-root', build_root) try: build_root = build_root % {'repo': repo, 'arch': arch, - 'project': prj, 'package': pacname, 'apihost': apihost} + 'project': prj, 'package': pacname, 'apihost': apihost} except: pass @@ -887,13 +902,11 @@ def main(apiurl, opts, argv): else: print('Using local buildenv file: %s' % os.path.basename(buildenvfile)) if buildenvfile or servicefile: - from .util import cpio if not cpiodata: cpiodata = cpio.CpioWrite() if opts.prefer_pkgs: print('Scanning the following dirs for local packages: %s' % ', '.join(opts.prefer_pkgs)) - from .util import cpio if not cpiodata: cpiodata = cpio.CpioWrite() prefer_pkgs = get_prefer_pkgs(opts.prefer_pkgs, arch, build_type, cpiodata) @@ -919,12 +932,12 @@ def main(apiurl, opts, argv): myrsyncdest = os.path.expandvars(opts.rsyncdest) if not os.path.isabs(myrsyncdest): raise oscerr.WrongOptions('--rsync-dest %s is no absolute path (starting with \'/\')!' % opts.rsyncdest) - specialcmdopts = ['--rsync-src='+myrsyncsrc, '--rsync-dest='+myrsyncdest] + specialcmdopts = ['--rsync-src=' + myrsyncsrc, '--rsync-dest=' + myrsyncdest] if opts.overlay: myoverlay = os.path.abspath(os.path.expanduser(os.path.expandvars(opts.overlay))) if not os.path.isdir(myoverlay): raise oscerr.WrongOptions('--overlay %s is no valid directory!' % opts.overlay) - specialcmdopts += ['--overlay='+myoverlay] + specialcmdopts += ['--overlay=' + myoverlay] try: if opts.noinit: @@ -954,12 +967,12 @@ def main(apiurl, opts, argv): print('Getting buildinfo from server and store to %s' % bi_filename) bi_text = decode_it(get_buildinfo(apiurl, - prj, - pac, - repo, - arch, - specfile=build_descr_data, - addlist=extra_pkgs)) + prj, + pac, + repo, + arch, + specfile=build_descr_data, + addlist=extra_pkgs)) if not bi_file: bi_file = open(bi_filename, 'w') # maybe we should check for errors before saving the file @@ -982,19 +995,19 @@ def main(apiurl, opts, argv): try: # take care, not to run into double trouble. pkg_meta_e = meta_exists(metatype='pkg', path_args=(quote_plus(prj), - quote_plus(pac)), template_args=None, create_new=False, - apiurl=apiurl) + quote_plus(pac)), template_args=None, create_new=False, + apiurl=apiurl) except: pass if pkg_meta_e: print('ERROR: Either wrong repo/arch as parameter or a parse error of .spec/.dsc/.kiwi file due to syntax error', file=sys.stderr) else: - print('The package \'%s\' does not exist - please ' \ - 'rerun with \'--local-package\'' % pac, file=sys.stderr) + print('The package \'%s\' does not exist - please ' + 'rerun with \'--local-package\'' % pac, file=sys.stderr) else: - print('The project \'%s\' does not exist - please ' \ - 'rerun with \'--alternative-project \'' % prj, file=sys.stderr) + print('The project \'%s\' does not exist - please ' + 'rerun with \'--alternative-project \'' % prj, file=sys.stderr) sys.exit(1) else: raise @@ -1030,12 +1043,12 @@ def main(apiurl, opts, argv): # vs. # arch we are supposed to build for if vm_type != "emulator" and vm_type != "qemu": - if bi.hostarch != None: - if hostarch != bi.hostarch and not bi.hostarch in can_also_build.get(hostarch, []): + if bi.hostarch is not None: + if hostarch != bi.hostarch and bi.hostarch not in can_also_build.get(hostarch, []): print('Error: hostarch \'%s\' is required.' % (bi.hostarch), file=sys.stderr) return 1 elif hostarch != bi.buildarch: - if not bi.buildarch in can_also_build.get(hostarch, []): + if bi.buildarch not in can_also_build.get(hostarch, []): print('WARNING: It is guessed to build on hostarch \'%s\' for \'%s\' via QEMU user emulation.' % (hostarch, bi.buildarch), file=sys.stderr) rpmlist_prefers = [] @@ -1060,7 +1073,7 @@ def main(apiurl, opts, argv): if 'urllist' in config: if isinstance(config['urllist'], str): re_clist = re.compile('[, ]+') - urllist = [ i.strip() for i in re_clist.split(config['urllist'].strip()) ] + urllist = [i.strip() for i in re_clist.split(config['urllist'].strip())] else: urllist = config['urllist'] @@ -1070,21 +1083,20 @@ def main(apiurl, opts, argv): if bi.downloadurl: urllist.append(bi.downloadurl.replace('%', '%%') + '/%(extproject)s/%(extrepository)s/%(arch)s/%(filename)s') if opts.disable_cpio_bulk_download: - urllist.append( '%(apiurl)s/build/%(project)s/%(repository)s/%(repoarch)s/%(repopackage)s/%(repofilename)s' ) + urllist.append('%(apiurl)s/build/%(project)s/%(repository)s/%(repoarch)s/%(repopackage)s/%(repofilename)s') fetcher = Fetcher(cache_dir, - urllist = urllist, - api_host_options = config['api_host_options'], - offline = opts.noinit or opts.offline, - http_debug = config['http_debug'], - modules = bi.modules, + urllist=urllist, + offline=opts.noinit or opts.offline, + http_debug=config['http_debug'], + modules=bi.modules, enable_cpio=not opts.disable_cpio_bulk_download and bi.enable_cpio, cookiejar=connection.CookieJarAuthHandler(apiurl, os.path.expanduser(conf.config["cookiejar"]))._cookiejar, download_api_only=opts.download_api_only) if not opts.trust_all_projects: # implicitly trust the project we are building for - check_trusted_projects(apiurl, [ i for i in bi.projects.keys() if not i == prj ]) + check_trusted_projects(apiurl, [i for i in bi.projects.keys() if not i == prj]) imagefile = '' imagesource = '' @@ -1116,7 +1128,7 @@ def main(apiurl, opts, argv): if opts.oldpackages: old_pkg_dir = opts.oldpackages if not old_pkg_dir.startswith('/') and not opts.offline: - data = [ prj, pacname, repo, arch] + data = [prj, pacname, repo, arch] if old_pkg_dir == '_link': p = core.findpacs(os.curdir)[0] if not p.islink(): @@ -1144,15 +1156,20 @@ def main(apiurl, opts, argv): if binaries: class mytmpdir: """ temporary directory that removes itself""" + def __init__(self, *args, **kwargs): self.name = mkdtemp(*args, **kwargs) _rmtree = staticmethod(shutil.rmtree) + def cleanup(self): self._rmtree(self.name) + def __del__(self): self.cleanup() + def __exit__(self): self.cleanup() + def __str__(self): return self.name @@ -1170,12 +1187,12 @@ def main(apiurl, opts, argv): data[0], data[2], data[3], i.name, - package = data[1], - target_filename = fname, - target_mtime = i.mtime, - progress_meter = True) + package=data[1], + target_filename=fname, + target_mtime=i.mtime, + progress_meter=True) - if old_pkg_dir != None: + if old_pkg_dir is not None: buildargs.append('--oldpackages=%s' % old_pkg_dir) # Make packages from buildinfo available as repos for kiwi/docker/fissile @@ -1203,22 +1220,22 @@ def main(apiurl, opts, argv): filename = sffn.split("/")[-1] # project/repo if i.name.startswith("container:"): - prdir = "containers/"+pdir+"/"+rdir + prdir = "containers/" + pdir + "/" + rdir pradir = prdir filename = filename[10:] if build_type == 'kiwi': buildargs.append('--kiwi-parameter') buildargs.append('--set-container-derived-from=dir://./' + prdir + "/" + filename) else: - prdir = "repos/"+pdir+"/"+rdir + prdir = "repos/" + pdir + "/" + rdir # project/repo/arch - pradir = prdir+"/"+adir + pradir = prdir + "/" + adir # target fullfilename - tffn = pradir+"/"+filename + tffn = pradir + "/" + filename if not os.path.exists(os.path.join(pradir)): os.makedirs(os.path.join(pradir)) if not os.path.exists(tffn): - print("Using package: "+sffn) + print("Using package: " + sffn) if opts.linksources: os.link(sffn, tffn) else: @@ -1277,19 +1294,19 @@ def main(apiurl, opts, argv): for xml in root.findall('repository'): if xml.find('source').get('path') == 'obsrepositories:/': for path in bi.pathes: - if not os.path.isdir("repos/"+path): + if not os.path.isdir("repos/" + path): continue buildargs.append('--kiwi-parameter') buildargs.append('--add-repo') buildargs.append('--kiwi-parameter') - buildargs.append("dir://./repos/"+path) + buildargs.append("dir://./repos/" + path) buildargs.append('--kiwi-parameter') buildargs.append('--add-repotype') buildargs.append('--kiwi-parameter') buildargs.append('rpm-md') if xml.get('priority'): buildargs.append('--kiwi-parameter') - buildargs.append('--add-repoprio='+xml.get('priority')) + buildargs.append('--add-repoprio=' + xml.get('priority')) else: m = re.match(r"obs://[^/]+/([^/]+)/(\S+)", xml.find('source').get('path')) if not m: @@ -1300,14 +1317,14 @@ def main(apiurl, opts, argv): buildargs.append('--kiwi-parameter') buildargs.append('--add-repo') buildargs.append('--kiwi-parameter') - buildargs.append("dir://./repos/"+project+"/"+repo) + buildargs.append("dir://./repos/" + project + "/" + repo) buildargs.append('--kiwi-parameter') buildargs.append('--add-repotype') buildargs.append('--kiwi-parameter') buildargs.append('rpm-md') if xml.get('priority'): buildargs.append('--kiwi-parameter') - buildargs.append('--add-repopriority='+xml.get('priority')) + buildargs.append('--add-repopriority=' + xml.get('priority')) if vm_type == "xen" or vm_type == "kvm" or vm_type == "lxc" or vm_type == "nspawn": print('Skipping verification of package signatures due to secure VM build') @@ -1329,7 +1346,6 @@ def main(apiurl, opts, argv): if i.hdrmd5: if not i.name.startswith('container:') and i.pacsuffix != 'rpm': continue - from .util import packagequery if i.name.startswith('container:'): hdrmd5 = dgst(i.fullfilename) else: @@ -1355,7 +1371,7 @@ def main(apiurl, opts, argv): rpmlist.append('%s %s\n' % (dep.name, dep.fullfilename)) for i in imagebins: rpmlist.append('%s preinstallimage\n' % i) - rpmlist += [ '%s %s\n' % (i[0], i[1]) for i in rpmlist_prefers ] + rpmlist += ['%s %s\n' % (i[0], i[1]) for i in rpmlist_prefers] if imagefile: rpmlist.append('preinstallimage: %s\n' % imagefile) @@ -1394,50 +1410,49 @@ def main(apiurl, opts, argv): else: my_build_swap = build_root + '/swap' - vm_options = [ '--vm-type=%s' % vm_type ] + vm_options = ['--vm-type=%s' % vm_type] if vm_telnet: - vm_options += [ '--vm-telnet=' + vm_telnet ] + vm_options += ['--vm-telnet=' + vm_telnet] if vm_memory: - vm_options += [ '--memory=' + vm_memory ] + vm_options += ['--memory=' + vm_memory] if vm_type != 'lxc' and vm_type != 'nspawn': - vm_options += [ '--vm-disk=' + my_build_device ] - vm_options += [ '--vm-swap=' + my_build_swap ] - vm_options += [ '--logfile=%s/.build.log' % build_root ] + vm_options += ['--vm-disk=' + my_build_device] + vm_options += ['--vm-swap=' + my_build_swap] + vm_options += ['--logfile=%s/.build.log' % build_root] if vm_type == 'kvm': if config['build-kernel']: - vm_options += [ '--vm-kernel=' + config['build-kernel'] ] + vm_options += ['--vm-kernel=' + config['build-kernel']] if config['build-initrd']: - vm_options += [ '--vm-initrd=' + config['build-initrd'] ] + vm_options += ['--vm-initrd=' + config['build-initrd']] build_root += '/.mount' if vm_disk_size: - vm_options += [ '--vmdisk-rootsize=' + vm_disk_size ] + vm_options += ['--vmdisk-rootsize=' + vm_disk_size] if config['build-vmdisk-swapsize']: - vm_options += [ '--vmdisk-swapsize=' + config['build-vmdisk-swapsize'] ] + vm_options += ['--vmdisk-swapsize=' + config['build-vmdisk-swapsize']] if config['build-vmdisk-filesystem']: - vm_options += [ '--vmdisk-filesystem=' + config['build-vmdisk-filesystem'] ] + vm_options += ['--vmdisk-filesystem=' + config['build-vmdisk-filesystem']] if config['build-vm-user']: - vm_options += [ '--vm-user=' + config['build-vm-user'] ] - + vm_options += ['--vm-user=' + config['build-vm-user']] if opts.preload: print("Preload done for selected repo/arch.") sys.exit(0) print('Running build') - cmd = [ config['build-cmd'], '--root='+build_root, - '--rpmlist='+rpmlist_filename, - '--dist='+bc_filename, - '--arch='+bi.buildarch ] + cmd = [config['build-cmd'], '--root=' + build_root, + '--rpmlist=' + rpmlist_filename, + '--dist=' + bc_filename, + '--arch=' + bi.buildarch] cmd += specialcmdopts + vm_options + buildargs - cmd += [ build_descr ] + cmd += [build_descr] cmd = su_wrapper(cmd) # change personality, if needed if hostarch != bi.buildarch and bi.buildarch in change_personality: - cmd = [ change_personality[bi.buildarch] ] + cmd + cmd = [change_personality[bi.buildarch]] + cmd # record our settings for later builds if is_package_dir(os.curdir): @@ -1464,7 +1479,8 @@ def main(apiurl, opts, argv): (s_built, b_built) = get_built_files(pacdir, bi.buildtype) print() - if s_built: print(decode_it(s_built)) + if s_built: + print(decode_it(s_built)) print() print(decode_it(b_built)) diff --git a/osc/checker.py b/osc/checker.py index 8e387b2e..4acbe9eb 100644 --- a/osc/checker.py +++ b/osc/checker.py @@ -8,11 +8,13 @@ import rpm class KeyError(Exception): def __init__(self, key, *args): - Exception.__init__(self) + super().__init__() self.args = args self.key = key + def __str__(self): - return ''+self.key+' :'+' '.join(self.args) + return '' + self.key + ' :' + ' '.join(self.args) + class Checker: def __init__(self): @@ -23,9 +25,10 @@ class Checker: self.ts.initDB() self.ts.openDB() self.ts.setVSFlags(0) - #self.ts.Debug(1) + # self.ts.Debug(1) - def readkeys(self, keys=[]): + def readkeys(self, keys=None): + keys = keys or [] rpm.addMacro('_dbpath', self.dbdir) for key in keys: try: @@ -33,7 +36,7 @@ class Checker: except KeyError as e: print(e) - if not len(self.imported): + if not self.imported: raise KeyError('', "no key imported") rpm.delMacro("_dbpath") @@ -68,7 +71,7 @@ class Checker: if line[0:12] == "-----END PGP": break line = line.rstrip() - if (line[0] == '='): + if line[0] == '=': crc = line[1:] line = fd.readline() break @@ -100,6 +103,7 @@ class Checker: if fd is not None: os.close(fd) + if __name__ == "__main__": import sys keyfiles = [] diff --git a/osc/commandline.py b/osc/commandline.py index e00d6e68..076298ad 100644 --- a/osc/commandline.py +++ b/osc/commandline.py @@ -4,22 +4,32 @@ # either version 2, or version 3 (at your option). import argparse +import getpass +import glob import importlib.util import inspect import os +import re +import subprocess import sys +import textwrap +import tempfile import time +import traceback from functools import cmp_to_key from operator import itemgetter from optparse import SUPPRESS_HELP from urllib.parse import urlsplit from urllib.error import HTTPError +from . import build as osc_build from . import cmdln from . import conf from . import oscerr from .core import * -from .util import safewriter +from .grabber import OscFileGrabber +from .meter import create_text_meter +from .util import cpio, rpmquery, safewriter from .util.helper import _html_escape, format_table @@ -157,15 +167,15 @@ class Osc(cmdln.Cmdln): return try: - conf.get_config(override_conffile = self.options.conffile, - override_apiurl = self.options.apiurl, - override_debug = self.options.debug, - override_http_debug = self.options.http_debug, - override_http_full_debug = self.options.http_full_debug, - override_traceback = self.options.traceback, - override_post_mortem = self.options.post_mortem, - override_no_keyring = self.options.no_keyring, - override_verbose = self.options.verbose) + conf.get_config(override_conffile=self.options.conffile, + override_apiurl=self.options.apiurl, + override_debug=self.options.debug, + override_http_debug=self.options.http_debug, + override_http_full_debug=self.options.http_full_debug, + override_traceback=self.options.traceback, + override_post_mortem=self.options.post_mortem, + override_no_keyring=self.options.no_keyring, + 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) @@ -188,14 +198,13 @@ class Osc(cmdln.Cmdln): self.options.verbose = conf.config['verbose'] self.download_progress = None if conf.config.get('show_download_progress', False): - from .meter import create_text_meter self.download_progress = create_text_meter() def get_api_url(self): try: localdir = os.getcwd() except Exception as e: - ## check for Stale NFS file handle: '.' + # check for Stale NFS file handle: '.' try: os.stat('.') except Exception as ee: @@ -218,7 +227,6 @@ class Osc(cmdln.Cmdln): print(get_osc_version()) - def do_init(self, subcmd, opts, project, package=None, scm_url=None): """ Initialize a directory as working copy @@ -371,7 +379,6 @@ class Osc(cmdln.Cmdln): else: opts.arch = args[3] - if opts.binaries and opts.expand: raise oscerr.WrongOptions('Sorry, --binaries and --expand are mutual exclusive.') @@ -427,7 +434,7 @@ class Osc(cmdln.Cmdln): print("%9d %s %-40s" % (f.size, shorttime(f.mtime), f.name)) else: for f in result[1]: - print(indent+f) + print(indent + f) # list sources elif not opts.binaries: @@ -436,26 +443,26 @@ class Osc(cmdln.Cmdln): print(prj) elif len(args) == 1: - for pkg in meta_get_packagelist(apiurl, project, deleted = opts.deleted, expand = opts.expand): + for pkg in meta_get_packagelist(apiurl, project, deleted=opts.deleted, expand=opts.expand): print(pkg) elif len(args) == 2 or len(args) == 3: link_seen = False print_not_found = True rev = opts.revision - for i in [ 1, 2 ]: + for i in [1, 2]: l = meta_get_filelist(apiurl, - project, - package, - verbose=opts.verbose, - expand=opts.expand, - meta=opts.meta, - deleted=opts.deleted, - revision=rev) + project, + package, + verbose=opts.verbose, + expand=opts.expand, + meta=opts.meta, + deleted=opts.deleted, + revision=rev) link_seen = '_link' in l if opts.verbose: - out = [ '%s %7s %9d %s %s' % (i.md5, i.rev, i.size, shorttime(i.mtime), i.name) \ - for i in l if not fname or fname == i.name ] + out = ['%s %7s %9d %s %s' % (i.md5, i.rev, i.size, shorttime(i.mtime), i.name) + for i in l if not fname or fname == i.name] if len(out) > 0: print_not_found = False print('\n'.join(out)) @@ -483,7 +490,6 @@ class Osc(cmdln.Cmdln): print('file \'%s\' does not exist' % fname) return 1 - @cmdln.option('--extend-package-names', default=False, action="store_true", help='Extend packages names with project name as suffix') def do_addcontainers(self, subcmd, opts, *args): @@ -509,7 +515,7 @@ class Osc(cmdln.Cmdln): project = self._process_project_name(args[0]) package = args[1] - if project == None or package == None: + if project is None or package is None: raise oscerr.WrongArgs('Either specify project and package or call it from a package working copy') query = {'cmd': 'addcontainers'} @@ -658,7 +664,7 @@ class Osc(cmdln.Cmdln): except HTTPError: pass - if opts.force or not filelist or not '_patchinfo' in filelist: + if opts.force or not filelist or '_patchinfo' not in filelist: print("Creating new patchinfo...") query = 'cmd=createpatchinfo&name=' + patchinfo if opts.force: @@ -764,7 +770,6 @@ class Osc(cmdln.Cmdln): set_devel_project(apiurl, project, package, devprj, devpkg) - def do_showlinked(self, subcmd, opts, *args): """ Show all packages linking to a given one @@ -800,8 +805,8 @@ class Osc(cmdln.Cmdln): help='Default is "runservice", but "branch", "release", "rebuild", or "workflow" can also be used') @cmdln.option('-t', '--trigger', metavar='TOKENSTRING', help='Trigger the action of a token') - @cmdln.option('', '--scm-token', metavar ='SCM_TOKEN', - help='The scm\'s access token (only in combination with a --operation=workflow option)') + @cmdln.option('', '--scm-token', metavar='SCM_TOKEN', + help='The scm\'s access token (only in combination with a --operation=workflow option)') def do_token(self, subcmd, opts, *args): """ Show and manage authentication token @@ -874,15 +879,14 @@ class Osc(cmdln.Cmdln): for data in streamfile(url, http_GET): sys.stdout.write(decode_it(data)) - @cmdln.option('-a', '--attribute', metavar='ATTRIBUTE', help='affect only a given attribute') @cmdln.option('--attribute-defaults', action='store_true', - help='include defined attribute defaults') + help='include defined attribute defaults') @cmdln.option('--attribute-project', action='store_true', - help='include project values, if missing in packages ') + help='include project values, if missing in packages ') @cmdln.option('--blame', action='store_true', - help='show author and time of each line') + help='show author and time of each line') @cmdln.option('-f', '--force', action='store_true', help='force the save operation, allows one to ignores some errors like depending repositories. For prj meta only.') @cmdln.option('-F', '--file', metavar='FILE', @@ -901,7 +905,7 @@ class Osc(cmdln.Cmdln): @cmdln.option('-s', '--set', metavar='ATTRIBUTE_VALUES', help='set attribute values') @cmdln.option('--delete', action='store_true', - help='delete a pattern or attribute') + help='delete a pattern or attribute') def do_meta(self, subcmd, opts, *args): """ Show meta information, or edit it @@ -949,8 +953,8 @@ class Osc(cmdln.Cmdln): args = slash_split(args) if not args or args[0] not in metatypes.keys(): - raise oscerr.WrongArgs('Unknown meta type. Choose one of %s.' \ - % ', '.join(metatypes)) + raise oscerr.WrongArgs('Unknown meta type. Choose one of %s.' + % ', '.join(metatypes)) cmd = args[0] del args[0] @@ -1041,7 +1045,7 @@ class Osc(cmdln.Cmdln): sys.stdout.write(decode_it(b''.join(show_package_meta(apiurl, project, package, blame=opts.blame)))) elif cmd == 'attribute': sys.stdout.write(decode_it(b''.join(show_attribute_meta(apiurl, project, package, subpackage, - opts.attribute, opts.attribute_defaults, opts.attribute_project)))) + opts.attribute, opts.attribute_defaults, opts.attribute_project)))) elif cmd == 'prjconf': sys.stdout.write(decode_it(b''.join(show_project_conf(apiurl, project, rev=opts.revision, blame=opts.blame)))) elif cmd == 'user': @@ -1071,24 +1075,24 @@ class Osc(cmdln.Cmdln): remove_linking_repositories=opts.remove_linking_repositories, path_args=quote_plus(project), apiurl=apiurl, - msg = opts.message, + msg=opts.message, template_args=({ - 'name': project, - 'user': conf.get_apiurl_usr(apiurl)})) + 'name': project, + 'user': conf.get_apiurl_usr(apiurl)})) elif cmd == 'pkg': edit_meta(metatype='pkg', edit=True, path_args=(quote_plus(project), quote_plus(package)), apiurl=apiurl, template_args=({ - 'name': package, - 'user': conf.get_apiurl_usr(apiurl)})) + 'name': package, + 'user': conf.get_apiurl_usr(apiurl)})) elif cmd == 'prjconf': edit_meta(metatype='prjconf', edit=True, path_args=quote_plus(project), apiurl=apiurl, - msg = opts.message, + msg=opts.message, template_args=None) elif cmd == 'user': edit_meta(metatype='user', @@ -1144,7 +1148,7 @@ class Osc(cmdln.Cmdln): force=opts.force, remove_linking_repositories=opts.remove_linking_repositories, apiurl=apiurl, - msg = opts.message, + msg=opts.message, path_args=quote_plus(project)) elif cmd == 'pkg': edit_meta(metatype='pkg', @@ -1157,7 +1161,7 @@ class Osc(cmdln.Cmdln): data=f, edit=opts.edit, apiurl=apiurl, - msg = opts.message, + msg=opts.message, path_args=quote_plus(project)) elif cmd == 'user': edit_meta(metatype='user', @@ -1178,7 +1182,6 @@ class Osc(cmdln.Cmdln): apiurl=apiurl, path_args=(project, pattern)) - # delete if opts.delete: path = metatypes[cmd]['path'] @@ -1196,7 +1199,6 @@ class Osc(cmdln.Cmdln): else: raise oscerr.WrongOptions('The --delete switch is only for pattern metadata or attributes.') - # TODO: rewrite and consolidate the current submitrequest/createrequest "mess" @cmdln.option('-m', '--message', metavar='TEXT', @@ -1208,7 +1210,7 @@ class Osc(cmdln.Cmdln): @cmdln.option('-s', '--supersede', metavar='REQUEST_ID', help='Superseding another request by this one') @cmdln.option('--nodevelproject', action='store_true', - help='do not follow a defined devel project ' \ + help='do not follow a defined devel project ' '(primary project where a package is developed)') @cmdln.option('--separate-requests', action='store_true', help='Create multiple requests instead of a single one (when command is used for entire project)') @@ -1257,7 +1259,6 @@ class Osc(cmdln.Cmdln): print('\n'.join(error.text.split('\\n'))) sys.exit('\nPlease fix this first') - if opts.cleanup and opts.no_cleanup: raise oscerr.WrongOptions('\'--cleanup\' and \'--no-cleanup\' are mutually exclusive') @@ -1317,7 +1318,7 @@ class Osc(cmdln.Cmdln): root = ET.parse(f).getroot() _check_service(root) linkinfo = root.find('linkinfo') - if linkinfo == None: + if linkinfo is None: if len(args) < 1: print("Package ", p, " is not a source link and no target specified.") sys.exit("This is currently not supported.") @@ -1352,10 +1353,10 @@ class Osc(cmdln.Cmdln): if target_project is not None: target_prj_block = """""" % target_project s = """ %s %s """ % \ - (project, target_prj_block, options_block) + (project, target_prj_block, options_block) actionxml += s xml = """ %s %s """ % \ - (actionxml, _html_escape(opts.message or "")) + (actionxml, _html_escape(opts.message or "")) u = makeurl(apiurl, ['request'], query='cmd=create&addrevision=1') f = http_POST(u, data=xml) @@ -1373,16 +1374,16 @@ class Osc(cmdln.Cmdln): value = root.findtext('attribute/value') if value and not opts.yes: repl = '' - print('\n\nThere are already following submit request: %s.' % \ - ', '.join([str(i) for i in myreqs ])) + print('\n\nThere are already following submit request: %s.' % + ', '.join([str(i) for i in myreqs])) repl = raw_input('\nSupersede the old requests? (y/n) ') if repl.lower() == 'y': - myreqs += [ value ] + myreqs += [value] if len(myreqs) > 0: for req in myreqs: change_request_state(apiurl, str(req), 'superseded', - 'superseded by %s' % sr_ids[0], sr_ids[0]) + 'superseded by %s' % sr_ids[0], sr_ids[0]) sys.exit('Successfully finished') @@ -1441,8 +1442,8 @@ class Osc(cmdln.Cmdln): devloc, _ = show_devel_project(apiurl, dst_project, dst_package) except HTTPError: print("""\ -Warning: failed to fetch meta data for '%s' package '%s' (new package?) """ \ - % (dst_project, dst_package), file=sys.stderr) +Warning: failed to fetch meta data for '%s' package '%s' (new package?) """ + % (dst_project, dst_package), file=sys.stderr) if devloc and \ dst_project != devloc and \ @@ -1450,8 +1451,8 @@ Warning: failed to fetch meta data for '%s' package '%s' (new package?) """ \ print("""\ A different project, %s, is defined as the place where development of the package %s primarily takes place. -Please submit there instead, or use --nodevelproject to force direct submission.""" \ - % (devloc, dst_package)) +Please submit there instead, or use --nodevelproject to force direct submission.""" + % (devloc, dst_package)) if not opts.diff: sys.exit(1) @@ -1462,7 +1463,7 @@ Please submit there instead, or use --nodevelproject to force direct submission. f = http_GET(u) root = ET.parse(f).getroot() linkinfo = root.find('linkinfo') - if linkinfo == None: + if linkinfo is None: rev = root.get('rev') else: if linkinfo.get('project') != dst_project or linkinfo.get('package') != dst_package: @@ -1475,8 +1476,8 @@ Please submit there instead, or use --nodevelproject to force direct submission. try: rdiff = b'old: %s/%s\nnew: %s/%s rev %s\n' % (dst_project.encode(), dst_package.encode(), src_project.encode(), src_package.encode(), str(rev).encode()) rdiff += server_diff(apiurl, - dst_project, dst_package, None, - src_project, src_package, rev, True) + dst_project, dst_package, None, + src_project, src_package, rev, True) except: rdiff = b'' @@ -1496,11 +1497,11 @@ Please submit there instead, or use --nodevelproject to force direct submission. dst_package, not opts.yes) if not supersede_existing: - (supersede_existing, reqs) = check_existing_maintenance_requests(apiurl, - src_project, - [src_package], - dst_project, None, - not opts.yes) + (supersede_existing, reqs) = check_existing_maintenance_requests(apiurl, + src_project, + [src_package], + dst_project, None, + not opts.yes) if not opts.message: difflines = [] doappend = False @@ -1519,7 +1520,7 @@ Please submit there instead, or use --nodevelproject to force direct submission. src_project, src_package, dst_project, dst_package, opts.message, orev=rev, - src_update=src_update, dst_updatelink=opts.update_link) + src_update=src_update, dst_updatelink=opts.update_link) print('created request id', result) if conf.config['print_web_links']: @@ -1543,7 +1544,7 @@ Please submit there instead, or use --nodevelproject to force direct submission. value = [] if not hasattr(parser.values, 'actiondata'): setattr(parser.values, 'actiondata', []) - if parser.values.actions == None: + if parser.values.actions is None: parser.values.actions = [] rargs = parser.rargs @@ -1581,7 +1582,7 @@ Please submit there instead, or use --nodevelproject to force direct submission. f = http_GET(u) root = ET.parse(f).getroot() linkinfo = root.find('linkinfo') - if linkinfo == None: + if linkinfo is None: print("Package ", p, " is not a source link.") sys.exit("This is currently not supported.") if linkinfo.get('error'): @@ -1599,21 +1600,21 @@ Please submit there instead, or use --nodevelproject to force direct submission. targetprojects.append(t) pac.append(p) else: - print("Skipping package ", p, " since it has no difference with the target package.") + print("Skipping package ", p, " since it has no difference with the target package.") else: - print("Skipping package ", p, " since it is a source link pointing inside the project.") + print("Skipping package ", p, " since it is a source link pointing inside the project.") # loop via all packages to do the action for p in pac: - s = """ %s """ % \ - (project, p, opts.revision or show_upstream_rev(apiurl, project, p), t, p, options_block) + s = """ %s """ % \ + (project, p, opts.revision or show_upstream_rev(apiurl, project, p), t, p, options_block) actionxml += s # create submit requests for all found patchinfos for p in pi: for t in targetprojects: - s = """ %s """ % \ - (project, p, t, p, options_block) + s = """ %s """ % \ + (project, p, t, p, options_block) actionxml += s return actionxml, [] @@ -1659,8 +1660,8 @@ Please submit there instead, or use --nodevelproject to force direct submission. devloc, _ = show_devel_project(apiurl, dst_project, dst_package) except HTTPError: print("""\ -Warning: failed to fetch meta data for '%s' package '%s' (new package?) """ \ - % (dst_project, dst_package), file=sys.stderr) +Warning: failed to fetch meta data for '%s' package '%s' (new package?) """ + % (dst_project, dst_package), file=sys.stderr) if devloc and \ dst_project != devloc and \ @@ -1668,17 +1669,17 @@ Warning: failed to fetch meta data for '%s' package '%s' (new package?) """ \ print("""\ A different project, %s, is defined as the place where development of the package %s primarily takes place. -Please submit there instead, or use --nodevelproject to force direct submission.""" \ - % (devloc, dst_package)) +Please submit there instead, or use --nodevelproject to force direct submission.""" + % (devloc, dst_package)) sys.exit(1) reqs = get_request_list(apiurl, dst_project, dst_package, req_type='submit', req_state=['new', 'review']) user = conf.get_apiurl_usr(apiurl) - myreqs = [ i for i in reqs if i.state.who == user and i.reqid != opts.supersede ] + myreqs = [i for i in reqs if i.state.who == user and i.reqid != opts.supersede] myreq_ids = [r.reqid for r in myreqs] repl = 'y' if len(myreqs) > 0 and not opts.yes: - print('You already created the following submit request: %s.' % \ + print('You already created the following submit request: %s.' % ', '.join(myreq_ids)) repl = raw_input('Supersede the old requests? (y/n/c) ') if repl.lower() == 'c': @@ -1687,12 +1688,12 @@ Please submit there instead, or use --nodevelproject to force direct submission. elif repl.lower() != 'y': myreqs = [] - actionxml = """ %s """ % \ - (src_project, src_package, opts.revision or show_upstream_rev(apiurl, src_project, src_package), dst_project, dst_package, options_block) + actionxml = """ %s """ % \ + (src_project, src_package, opts.revision or show_upstream_rev(apiurl, src_project, src_package), dst_project, dst_package, options_block) if opts.supersede: myreq_ids.append(opts.supersede) - #print 'created request id', result + # print 'created request id', result return actionxml, myreq_ids def _delete_request(self, args, opts): @@ -1728,7 +1729,7 @@ Please submit there instead, or use --nodevelproject to force direct submission. devel_package = self._process_project_name(args[3]) actionxml = """ """ % \ - (devel_project, devel_package, project, package) + (devel_project, devel_package, project, package) return actionxml @@ -1744,14 +1745,14 @@ Please submit there instead, or use --nodevelproject to force direct submission. role = args[0] project = self._process_project_name(args[1]) actionxml = """ """ % \ - (project, user, role) + (project, user, role) if len(args) > 2: package = args[2] actionxml = """ """ % \ (project, package, user, role) - if get_user_meta(apiurl, user) == None: + if get_user_meta(apiurl, user) is None: raise oscerr.WrongArgs('osc: an error occurred.') return actionxml @@ -1768,14 +1769,14 @@ Please submit there instead, or use --nodevelproject to force direct submission. role = args[1] project = self._process_project_name(args[2]) actionxml = """ """ % \ - (project, user, role) + (project, user, role) if len(args) > 3: package = args[3] actionxml = """ """ % \ (project, package, user, role) - if get_user_meta(apiurl, user) == None: + if get_user_meta(apiurl, user) is None: raise oscerr.WrongArgs('osc: an error occured.') return actionxml @@ -1792,14 +1793,14 @@ Please submit there instead, or use --nodevelproject to force direct submission. role = args[1] project = self._process_project_name(args[2]) actionxml = """ """ % \ - (project, group, role) + (project, group, role) if len(args) > 3: package = args[3] actionxml = """ """ % \ (project, package, group, role) - if get_group_meta(apiurl, group) == None: + if get_group_meta(apiurl, group) is None: raise oscerr.WrongArgs('osc: an error occured.') return actionxml @@ -1821,16 +1822,15 @@ Please submit there instead, or use --nodevelproject to force direct submission. if user.startswith('group:'): group = user.replace('group:', '') actionxml = """ """ % \ - (project, package, group) - if get_group_meta(apiurl, group) == None: + (project, package, group) + if get_group_meta(apiurl, group) is None: raise oscerr.WrongArgs('osc: an error occurred.') else: actionxml = """ """ % \ - (project, package, user) - if get_user_meta(apiurl, user) == None: + (project, package, user) + if get_user_meta(apiurl, user) is None: raise oscerr.WrongArgs('osc: an error occured.') - return actionxml # TODO: fix ValueError: unknown action "callback" @@ -1843,7 +1843,7 @@ Please submit there instead, or use --nodevelproject to force direct submission. @cmdln.option('-s', '--supersede', metavar='REQUEST_ID', help='Superseding another request by this one') @cmdln.option('--nodevelproject', action='store_true', - help='do not follow a defined devel project ' \ + help='do not follow a defined devel project ' '(primary project where a package is developed)') @cmdln.option('--cleanup', action='store_true', help='remove package if submission gets accepted (default for home::branch projects)') @@ -1899,34 +1899,34 @@ Please submit there instead, or use --nodevelproject to force direct submission. for ai in opts.actions: if ai == 'submit': args = opts.actiondata[i] - i = i+1 + i = i + 1 actions, to_supersede = self._submit_request(args, opts, options_block) actionsxml += actions supersede.update(to_supersede) elif ai == 'delete': args = opts.actiondata[i] actionsxml += self._delete_request(args, opts) - i = i+1 + i = i + 1 elif ai == 'change_devel': args = opts.actiondata[i] actionsxml += self._changedevel_request(args, opts) - i = i+1 + i = i + 1 elif ai == 'add_me': args = opts.actiondata[i] actionsxml += self._add_me(args, opts) - i = i+1 + i = i + 1 elif ai == 'add_group': args = opts.actiondata[i] actionsxml += self._add_group(args, opts) - i = i+1 + i = i + 1 elif ai == 'add_role': args = opts.actiondata[i] actionsxml += self._add_user(args, opts) - i = i+1 + i = i + 1 elif ai == 'set_bugowner': args = opts.actiondata[i] actionsxml += self._set_bugowner(args, opts) - i = i+1 + i = i + 1 else: raise oscerr.WrongArgs('Unsupported action %s' % ai) if actionsxml == "": @@ -1947,11 +1947,10 @@ Please submit there instead, or use --nodevelproject to force direct submission. 'superseded by %s' % rid, rid) return rid - @cmdln.option('-m', '--message', metavar='TEXT', help='specify message TEXT') @cmdln.option('-r', '--role', metavar='role', - help='specify user role (default: maintainer)') + help='specify user role (default: maintainer)') @cmdln.alias("reqbugownership") @cmdln.alias("requestbugownership") @cmdln.alias("reqmaintainership") @@ -2002,11 +2001,11 @@ Please submit there instead, or use --nodevelproject to force direct submission. raise oscerr.WrongArgs('Wrong number of arguments.') role = 'maintainer' - if subcmd in ( 'reqbugownership', 'requestbugownership', 'reqbs' ): + if subcmd in ('reqbugownership', 'requestbugownership', 'reqbs'): role = 'bugowner' if opts.role: role = opts.role - if not role in ('maintainer', 'bugowner'): + if role not in ('maintainer', 'bugowner'): raise oscerr.WrongOptions('invalid \'--role\': either specify \'maintainer\' or \'bugowner\'') if not opts.message: opts.message = edit_message() @@ -2022,10 +2021,10 @@ Please submit there instead, or use --nodevelproject to force direct submission. group_name=group, group_role=role) elif role == 'bugowner': r.add_action('set_bugowner', tgt_project=project, tgt_package=package, - person_name=user) + person_name=user) else: r.add_action('add_role', tgt_project=project, tgt_package=package, - person_name=user, person_role=role) + person_name=user, person_role=role) r.description = opts.message r.create(apiurl) print(r.reqid) @@ -2035,7 +2034,7 @@ Please submit there instead, or use --nodevelproject to force direct submission. @cmdln.option('-r', '--repository', metavar='REPOSITORY', help='specify repository') @cmdln.option('--all', action='store_true', - help='deletes entire project with packages inside') + help='deletes entire project with packages inside') @cmdln.option('--accept-in-hours', metavar='HOURS', help='specify time when request shall get accepted automatically. Only works with write permissions in target.') @cmdln.alias("dr") @@ -2079,14 +2078,13 @@ Please submit there instead, or use --nodevelproject to force direct submission. repository = opts.repository if not opts.message: - import textwrap if package is not None: - footer = textwrap.TextWrapper(width = 66).fill( - 'please explain why you like to delete package %s of project %s' - % (package, project)) + footer = textwrap.TextWrapper(width=66).fill( + 'please explain why you like to delete package %s of project %s' + % (package, project)) else: - footer = textwrap.TextWrapper(width = 66).fill( - 'please explain why you like to delete project %s' % project) + footer = textwrap.TextWrapper(width=66).fill( + 'please explain why you like to delete project %s' % project) opts.message = edit_message(footer) r = Request() @@ -2097,7 +2095,6 @@ Please submit there instead, or use --nodevelproject to force direct submission. r.create(self.get_api_url()) print(r.reqid) - @cmdln.option('-m', '--message', metavar='TEXT', help='specify message TEXT') @cmdln.alias("cr") @@ -2132,20 +2129,18 @@ Please submit there instead, or use --nodevelproject to force direct submission. devel_package = args[3] if not opts.message: - import textwrap - footer = textwrap.TextWrapper(width = 66).fill( - 'please explain why you like to change the devel project of %s/%s to %s/%s' - % (project, package, devel_project, devel_package)) + footer = textwrap.TextWrapper(width=66).fill( + 'please explain why you like to change the devel project of %s/%s to %s/%s' + % (project, package, devel_project, devel_package)) opts.message = edit_message(footer) r = Request() r.add_action('change_devel', src_project=devel_project, src_package=devel_package, - tgt_project=project, tgt_package=package) + tgt_project=project, tgt_package=package) r.description = opts.message r.create(self.get_api_url()) print(r.reqid) - @cmdln.option('-d', '--diff', action='store_true', help='generate a diff') @cmdln.option('-S', '--superseded-request', metavar='SUPERSEDED_REQUEST', @@ -2185,19 +2180,19 @@ Please submit there instead, or use --nodevelproject to force direct submission. @cmdln.option('-i', '--interactive', action='store_true', help='interactive review of request') @cmdln.option('--or-revoke', action='store_true', - help='For automation scripts: accepts (if using with accept argument) a request when it is in new or review state. Or revoke it when it got declined. Otherwise just do nothing.') + help='For automation scripts: accepts (if using with accept argument) a request when it is in new or review state. Or revoke it when it got declined. Otherwise just do nothing.') @cmdln.option('--non-interactive', action='store_true', - help='non-interactive review of request') + help='non-interactive review of request') @cmdln.option('--exclude-target-project', action='append', - help='exclude target project from request list') + help='exclude target project from request list') @cmdln.option('--incoming', action='store_true', - help='Show only requests where the project is target') + help='Show only requests where the project is target') @cmdln.option('--involved-projects', action='store_true', - help='show all requests for project/packages where USER is involved') + help='show all requests for project/packages where USER is involved') @cmdln.option('--target-package-filter', metavar='TARGET_PACKAGE_FILTER', - help='only list requests for the packages matching the package filter. A (python) regular expression is expected.') + help='only list requests for the packages matching the package filter. A (python) regular expression is expected.') @cmdln.option('--source-buildstatus', action='store_true', - help='print the buildstatus of the source package (only works with "show" and the interactive review)') + help='print the buildstatus of the source package (only works with "show" and the interactive review)') @cmdln.alias("rq") @cmdln.alias("review") # FIXME: rewrite this mess and split request and review @@ -2284,17 +2279,17 @@ Please submit there instead, or use --nodevelproject to force direct submission. args = slash_split(args) if opts.all and opts.state: - raise oscerr.WrongOptions('Sorry, the options \'--all\' and \'--state\' ' \ - 'are mutually exclusive.') + raise oscerr.WrongOptions('Sorry, the options \'--all\' and \'--state\' ' + 'are mutually exclusive.') if opts.mine and opts.user: - raise oscerr.WrongOptions('Sorry, the options \'--user\' and \'--mine\' ' \ - 'are mutually exclusive.') + raise oscerr.WrongOptions('Sorry, the options \'--user\' and \'--mine\' ' + 'are mutually exclusive.') if opts.interactive and opts.non_interactive: - raise oscerr.WrongOptions('Sorry, the options \'--interactive\' and ' \ - '\'--non-interactive\' are mutually exclusive') + raise oscerr.WrongOptions('Sorry, the options \'--interactive\' and ' + '\'--non-interactive\' are mutually exclusive') if not args: - args = [ 'list' ] + args = ['list'] opts.mine = 1 if opts.state == '': opts.state = 'all' @@ -2308,12 +2303,12 @@ Please submit there instead, or use --nodevelproject to force direct submission. cmds = ['list', 'ls', 'log', 'show', 'decline', 'reopen', 'clone', 'accept', 'approve', 'cancelapproval', 'approvenew', 'wipe', 'setincident', 'supersede', 'revoke', 'checkout', 'co', 'priorize', 'prioritize'] if subcmd != 'review' and args[0] not in cmds: - raise oscerr.WrongArgs('Unknown request action %s. Choose one of %s.' \ - % (args[0], ', '.join(cmds))) + raise oscerr.WrongArgs('Unknown request action %s. Choose one of %s.' + % (args[0], ', '.join(cmds))) cmds = ['show', 'list', 'add', 'decline', 'accept', 'reopen', 'supersede'] if subcmd == 'review' and args[0] not in cmds: - raise oscerr.WrongArgs('Unknown review action %s. Choose one of %s.' \ - % (args[0], ', '.join(cmds))) + raise oscerr.WrongArgs('Unknown review action %s. Choose one of %s.' + % (args[0], ', '.join(cmds))) cmd = args[0] del args[0] @@ -2377,28 +2372,28 @@ Please submit there instead, or use --nodevelproject to force direct submission. # approve request elif cmd == 'approve' or cmd == 'cancelapproval': - query = { 'cmd': cmd } + query = {'cmd': cmd} url = makeurl(apiurl, ['request', reqid], query) r = http_POST(url, data=opts.message) print(ET.parse(r).getroot().get('code')) # change incidents elif cmd == 'setincident': - query = { 'cmd': 'setincident', 'incident': incident } + query = {'cmd': 'setincident', 'incident': incident} url = makeurl(apiurl, ['request', reqid], query) r = http_POST(url, data=opts.message) print(ET.parse(r).getroot().get('code')) # change priority elif cmd in ['prioritize', 'priorize']: - query = { 'cmd': 'setpriority', 'priority': priority } + query = {'cmd': 'setpriority', 'priority': priority} url = makeurl(apiurl, ['request', reqid], query) r = http_POST(url, data=opts.message) print(ET.parse(r).getroot().get('code')) # add new reviewer to existing request elif cmd in ['add'] and subcmd == 'review': - query = { 'cmd': 'addreview' } + query = {'cmd': 'addreview'} if opts.user: query['by_user'] = opts.user if opts.group: @@ -2428,14 +2423,14 @@ Please submit there instead, or use --nodevelproject to force direct submission. state_list = ['all'] else: for s in state_list: - if not s in states and not s == 'all': + if s not in states and not s == 'all': raise oscerr.WrongArgs('Unknown state \'%s\', try one of %s' % (s, ','.join(states))) if opts.mine: who = conf.get_apiurl_usr(apiurl) if opts.user: who = opts.user - ## FIXME -B not implemented! + # FIXME -B not implemented! if opts.bugowner: self._debug('list: option --bugowner ignored: not impl.') @@ -2482,17 +2477,16 @@ Please submit there instead, or use --nodevelproject to force direct submission. except ValueError: days = 0 if days > 0: - since = time.strftime('%Y-%m-%dT%H:%M:%S', time.localtime(time.time()-days*24*3600)) + since = time.strftime('%Y-%m-%dT%H:%M:%S', time.localtime(time.time() - days * 24 * 3600)) skipped = 0 - ## bs has received 2009-09-20 a new xquery compare() function - ## which allows us to limit the list inside of get_request_list - ## That would be much faster for coolo. But counting the remainder - ## would not be possible with current xquery implementation. - ## Workaround: fetch all, and filter on client side. - - ## FIXME: date filtering should become implemented on server side + # bs has received 2009-09-20 a new xquery compare() function + # which allows us to limit the list inside of get_request_list + # That would be much faster for coolo. But counting the remainder + # would not be possible with current xquery implementation. + # Workaround: fetch all, and filter on client side. + # FIXME: date filtering should become implemented on server side if opts.target_package_filter: filter_pattern = re.compile(opts.target_package_filter) @@ -2527,7 +2521,7 @@ Please submit there instead, or use --nodevelproject to force direct submission. for result in results: print(result.reqid, ": ", end=' ') r = change_request_state(apiurl, - result.reqid, 'accepted', opts.message or '', force=opts.force) + result.reqid, 'accepted', opts.message or '', force=opts.force) print('Result of change request state: %s' % r) else: print('Aborted...', file=sys.stderr) @@ -2544,8 +2538,8 @@ Please submit there instead, or use --nodevelproject to force direct submission. print(r.list_view()) elif opts.edit: if not r.get_actions('submit'): - raise oscerr.WrongOptions('\'--edit\' not possible ' \ - '(request has no \'submit\' action)') + raise oscerr.WrongOptions('\'--edit\' not possible ' + '(request has no \'submit\' action)') return request_interactive_review(apiurl, r, 'e') elif (opts.interactive or conf.config['request_show_interactive']) and not opts.non_interactive: ignore_reviews = subcmd != 'review' @@ -2558,8 +2552,8 @@ Please submit there instead, or use --nodevelproject to force direct submission. if source_buildstatus: sr_actions = r.get_actions('submit') if not sr_actions: - raise oscerr.WrongOptions( '\'--source-buildstatus\' not possible ' \ - '(request has no \'submit\' actions)') + 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('\n'.join(get_results(apiurl, action.src_project, action.src_package))) @@ -2582,7 +2576,7 @@ Please submit there instead, or use --nodevelproject to force direct submission. raise oscerr.WrongOptions('\'--diff\' not possible (request has no supported actions)') for action in sr_actions: diff += b'old: %s/%s\nnew: %s/%s\n' % (action.src_project.encode(), action.src_package.encode(), - action.tgt_project.encode(), action.tgt_package.encode()) + action.tgt_project.encode(), action.tgt_package.encode()) diff += submit_action_diff(apiurl, action) diff += b'\n\n' run_pager(diff, tmp_suffix='') @@ -2594,8 +2588,8 @@ Please submit there instead, or use --nodevelproject to force direct submission. if not sr_actions: raise oscerr.WrongArgs('\'checkout\' not possible (request has no \'submit\' actions)') for action in sr_actions: - checkout_package(apiurl, action.src_project, action.src_package, \ - action.src_rev, expand_link=True, prj_dir=action.src_project) + checkout_package(apiurl, action.src_project, action.src_package, + action.src_rev, expand_link=True, prj_dir=action.src_project) else: state_map = {'reopen': 'new', 'accept': 'accepted', 'decline': 'declined', 'wipe': 'deleted', 'revoke': 'revoked', 'supersede': 'superseded'} @@ -2606,7 +2600,7 @@ Please submit there instead, or use --nodevelproject to force direct submission. if cmd in ['accept', 'decline', 'reopen', 'supersede']: if opts.user or opts.group or opts.project or opts.package: r = change_review_state(apiurl, reqid, state_map[cmd], opts.user, opts.group, opts.project, - opts.package, opts.message or '', supersed=supersedid) + opts.package, opts.message or '', supersed=supersedid) print(r) else: rq = get_request(apiurl, reqid) @@ -2614,7 +2608,7 @@ Please submit there instead, or use --nodevelproject to force direct submission. for review in rq.reviews: # try all, but do not fail on error try: r = change_review_state(apiurl, reqid, state_map[cmd], review.by_user, review.by_group, - review.by_project, review.by_package, opts.message or '', supersed=supersedid) + review.by_project, review.by_package, opts.message or '', supersed=supersedid) print(r) except HTTPError as e: body = e.read() @@ -2639,7 +2633,7 @@ Please submit there instead, or use --nodevelproject to force direct submission. elif rq.state.name != "new" and rq.state.name != "review": return 0 if rq.state.name == state_map[cmd]: - repl = raw_input("\n *** The state of the request (#%s) is already '%s'. Change state anyway? [y/n] *** " % \ + repl = raw_input("\n *** The state of the request (#%s) is already '%s'. Change state anyway? [y/n] *** " % (reqid, rq.state.name)) if repl.lower() != 'y': print('Aborted...', file=sys.stderr) @@ -2650,7 +2644,7 @@ Please submit there instead, or use --nodevelproject to force direct submission. opts.message = edit_message(template=tmpl) try: r = change_request_state(apiurl, - reqid, state_map[cmd], opts.message or '', supersed=supersedid, force=opts.force) + reqid, state_map[cmd], opts.message or '', supersed=supersedid, force=opts.force) print('Result of change request state: %s' % r) except HTTPError as e: print(e, file=sys.stderr) @@ -2659,23 +2653,22 @@ Please submit there instead, or use --nodevelproject to force direct submission. print(details, file=sys.stderr) root = ET.fromstring(e.read()) summary = root.find('summary') - if not summary is None: + if summary is not None: print(summary.text) if opts.or_revoke: - if e.code in [ 400, 403, 404, 500 ]: + if e.code in [400, 403, 404, 500]: print('Revoking it ...') r = change_request_state(apiurl, - reqid, 'revoked', opts.message or '', supersed=supersedid, force=opts.force) + reqid, 'revoked', opts.message or '', supersed=supersedid, force=opts.force) sys.exit(1) - # check for devel instances after accepted requests if cmd in ['accept']: 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) - }) + }) f = http_GET(u) root = ET.parse(f).getroot() if root.findall('package') and not opts.no_devel: @@ -2689,7 +2682,7 @@ Please submit there instead, or use --nodevelproject to force direct submission. file = http_GET(link_url) root = ET.parse(file).getroot() link_node = root.find('linkinfo') - if link_node != None: + if link_node is not None: links_to_project = link_node.get('project') or project links_to_package = link_node.get('package') or package except HTTPError as e: @@ -2770,7 +2763,6 @@ Please submit there instead, or use --nodevelproject to force direct submission. else: print('set revision to %s for package %s' % (rev, p)) - def do_linktobranch(self, subcmd, opts, *args): """ Convert a package containing a classic link with patch to a branch @@ -2805,7 +2797,6 @@ Please submit there instead, or use --nodevelproject to force direct submission. pac = Package(wd) pac.update(rev=pac.latest_rev()) - @cmdln.option('-m', '--message', metavar='TEXT', help='specify message TEXT') def do_detachbranch(self, subcmd, opts, *args): @@ -2852,7 +2843,6 @@ Please submit there instead, or use --nodevelproject to force direct submission. else: raise e - @cmdln.option('-C', '--cicount', choices=['add', 'copy', 'local'], help='cicount attribute in the link, known values are add, copy, and local, default in buildservice is currently add.') @cmdln.option('-c', '--current', action='store_true', @@ -2917,7 +2907,7 @@ Please submit there instead, or use --nodevelproject to force direct submission. if opts.current and not opts.new_package: rev, vrev = show_upstream_rev_vrev(apiurl, src_project, src_package, expand=True) - if rev == None or len(rev) < 32: + if rev is None or len(rev) < 32: # vrev is only needed for srcmd5 and OBS instances < 2.1.17 do not support it vrev = None @@ -2978,7 +2968,6 @@ Please submit there instead, or use --nodevelproject to force direct submission. aggregate_pac(src_project, src_package, dst_project, dst_package, repo_map, opts.disable_publish, opts.nosources) - @cmdln.option('-c', '--client-side-copy', action='store_true', help='do a (slower) client-side copy') @cmdln.option('-k', '--keep-maintainers', action='store_true', @@ -3044,7 +3033,7 @@ Please submit there instead, or use --nodevelproject to force direct submission. else: if not rev: rev = show_upstream_rev(src_apiurl, src_project, src_package) - comment = 'osc copypac from project:%s package:%s revision:%s' % ( src_project, src_package, rev ) + comment = 'osc copypac from project:%s package:%s revision:%s' % (src_project, src_package, rev) if opts.keep_link: comment += ", using keep-link" if opts.expand: @@ -3069,7 +3058,6 @@ Please submit there instead, or use --nodevelproject to force direct submission. keep_link=opts.keep_link) print(decode_it(r)) - @cmdln.option('-r', '--repo', metavar='REPO', help='Release only binaries from the specified repository') @cmdln.option('--target-project', metavar='TARGETPROJECT', @@ -3112,7 +3100,7 @@ Please submit there instead, or use --nodevelproject to force direct submission. if len(args) > 1: source_package = args[1] - query = { 'cmd': 'release' } + query = {'cmd': 'release'} if opts.target_project: query["target_project"] = opts.target_project if opts.target_repository: @@ -3134,7 +3122,6 @@ Please submit there instead, or use --nodevelproject to force direct submission. break sys.stdout.write(decode_it(buf)) - @cmdln.option('-m', '--message', metavar='TEXT', help='specify message TEXT') @cmdln.option('-p', '--package', metavar='PKG', action='append', @@ -3199,12 +3186,10 @@ Please submit there instead, or use --nodevelproject to force direct submission. r.create(apiurl) print(r.reqid) - - @cmdln.option('-a', '--attribute', metavar='ATTRIBUTE', help='Use this attribute to find default maintenance project (default is OBS:MaintenanceProject)') @cmdln.option('--noaccess', action='store_true', - help='Create a hidden project') + help='Create a hidden project') @cmdln.option('-m', '--message', metavar='TEXT', help='specify message TEXT') def do_createincident(self, subcmd, opts, *args): @@ -3246,7 +3231,7 @@ Please submit there instead, or use --nodevelproject to force direct submission. target_project = project.get('name') print('Using target project \'%s\'' % target_project) - query = { 'cmd': 'createmaintenanceincident' } + query = {'cmd': 'createmaintenanceincident'} if opts.noaccess: query["noaccess"] = 1 url = makeurl(apiurl, ['source', target_project], query=query) @@ -3261,13 +3246,12 @@ Please submit there instead, or use --nodevelproject to force direct submission. print(ET.parse(r).getroot().get('code')) print(ET.parse(r).getroot().get('error')) - @cmdln.option('-a', '--attribute', metavar='ATTRIBUTE', help='Use this attribute to find default maintenance project (default is OBS:MaintenanceProject)') @cmdln.option('-m', '--message', metavar='TEXT', help='specify message TEXT') @cmdln.option('--release-project', metavar='RELEASEPROJECT', - help='Specify the release project') + help='Specify the release project') @cmdln.option('--enforce-branching', action='store_true', help='submit from a fresh branched project') @cmdln.option('--no-cleanup', action='store_true', @@ -3275,9 +3259,9 @@ Please submit there instead, or use --nodevelproject to force direct submission. @cmdln.option('--cleanup', action='store_true', help='do remove source project on accept') @cmdln.option('--incident', metavar='INCIDENT', - help='specify incident number to merge in') + help='specify incident number to merge in') @cmdln.option('--incident-project', metavar='INCIDENT_PROJECT', - help='specify incident project to merge in') + help='specify incident project to merge in') @cmdln.option('-s', '--supersede', metavar='REQUEST_ID', help='Superseding another request by this one') @cmdln.alias("mr") @@ -3301,7 +3285,7 @@ Please submit there instead, or use --nodevelproject to force direct submission. to the release project this package links to. This syntax is only valid when specified from a package subdirectory. """ - #FIXME: the follow syntax would make more sense and would obsolete the --release-project parameter + # FIXME: the follow syntax would make more sense and would obsolete the --release-project parameter # but is incompatible with the current one # osc maintenancerequest [ SOURCEPROJECT [ RELEASEPROJECT [ SOURCEPACKAGES ] ] @@ -3371,10 +3355,10 @@ Please submit there instead, or use --nodevelproject to force direct submission. reqs = [] if not opts.supersede: (supersede_existing, reqs) = check_existing_maintenance_requests(apiurl, - source_project, - source_packages, - target_project, - None) # unspecified release project + source_project, + source_packages, + target_project, + None) # unspecified release project r = create_maintenance_request(apiurl, source_project, source_packages, target_project, release_project, opt_sourceupdate, opts.message, opts.enforce_branching) print(r.reqid) @@ -3395,23 +3379,22 @@ Please submit there instead, or use --nodevelproject to force direct submission. change_request_state(apiurl, opts.supersede, 'superseded', opts.message or '', r.reqid) - @cmdln.option('-c', '--checkout', action='store_true', - help='Checkout branched package afterwards ' \ - '(\'osc bco\' is a shorthand for this option)' ) + help='Checkout branched package afterwards ' + '(\'osc bco\' is a shorthand for this option)') @cmdln.option('-a', '--attribute', metavar='ATTRIBUTE', help='Use this attribute to find affected packages (default is OBS:Maintained)') @cmdln.option('-u', '--update-project-attribute', metavar='UPDATE_ATTRIBUTE', help='Use this attribute to find update projects (default is OBS:UpdateProject) ') @cmdln.option('--dryrun', action='store_true', - help='Just simulate the action and report back the result.') + help='Just simulate the action and report back the result.') @cmdln.option('--noaccess', action='store_true', - help='Create a hidden project') + help='Create a hidden project') @cmdln.option('--nodevelproject', action='store_true', - help='do not follow a defined devel project ' \ - '(primary project where a package is developed)') + help='do not follow a defined devel project ' + '(primary project where a package is developed)') @cmdln.option('--version', action='store_true', - help='print version of maintained package') + help='print version of maintained package') @cmdln.alias('sm') @cmdln.alias('maintained') def do_mbranch(self, subcmd, opts, *args): @@ -3449,7 +3432,7 @@ Please submit there instead, or use --nodevelproject to force direct submission. if opts.update_project_attribute: maintained_update_project_attribute = opts.update_project_attribute - if not len(args) or len(args) > 2: + if not args or len(args) > 2: raise oscerr.WrongArgs('Wrong number of arguments.') if len(args) >= 1: package = args[0] @@ -3459,8 +3442,8 @@ Please submit there instead, or use --nodevelproject to force direct submission. if subcmd == 'sm' or subcmd == 'maintained': opts.dryrun = 1 - result = attribute_branch_pkg(apiurl, maintained_attribute, maintained_update_project_attribute, \ - package, tproject, noaccess = opts.noaccess, nodevelproject=opts.nodevelproject, dryrun=opts.dryrun) + result = attribute_branch_pkg(apiurl, maintained_attribute, maintained_update_project_attribute, + package, tproject, noaccess=opts.noaccess, nodevelproject=opts.nodevelproject, dryrun=opts.dryrun) if result is None: print('ERROR: Attribute branch call came not back with a project.', file=sys.stderr) @@ -3483,9 +3466,9 @@ Please submit there instead, or use --nodevelproject to force direct submission. apiopt = '' if conf.get_configParser().get('general', 'apiurl') != apiurl: apiopt = '-A %s ' % apiurl - print('A working copy of the maintenance branch can be checked out with:\n\n' \ - 'osc %sco %s' \ - % (apiopt, result)) + print('A working copy of the maintenance branch can be checked out with:\n\n' + 'osc %sco %s' + % (apiopt, result)) if opts.checkout: Project.init_project(apiurl, result, result, conf.config['do_package_tracking']) @@ -3494,23 +3477,22 @@ Please submit there instead, or use --nodevelproject to force direct submission. # all packages for package in meta_get_packagelist(apiurl, result): try: - checkout_package(apiurl, result, package, expand_link = True, prj_dir = result) + checkout_package(apiurl, result, package, expand_link=True, prj_dir=result) except: print('Error while checkout package:\n', package, file=sys.stderr) if conf.config['verbose']: print('Note: You can use "osc delete" or "osc submitpac" when done.\n') - @cmdln.alias('branchco') @cmdln.alias('bco') @cmdln.alias('getpac') @cmdln.option('--nodevelproject', action='store_true', - help='do not follow a defined devel project ' \ - '(primary project where a package is developed)') + help='do not follow a defined devel project ' + '(primary project where a package is developed)') @cmdln.option('-c', '--checkout', action='store_true', - help='Checkout branched package afterwards using "co -e -S"' \ - '(\'osc bco\' is a shorthand for this option)' ) + help='Checkout branched package afterwards using "co -e -S"' + '(\'osc bco\' is a shorthand for this option)') @cmdln.option('-f', '--force', default=False, action="store_true", help='force branch, overwrite target') @cmdln.option('--add-repositories', default=False, action="store_true", @@ -3518,7 +3500,7 @@ Please submit there instead, or use --nodevelproject to force direct submission. @cmdln.option('--extend-package-names', default=False, action="store_true", help='Extend packages names with project name as suffix') @cmdln.option('--noaccess', action='store_true', - help='Create a hidden project') + help='Create a hidden project') @cmdln.option('-m', '--message', metavar='TEXT', help='specify message TEXT') @cmdln.option('-M', '--maintenance', default=False, action="store_true", @@ -3528,11 +3510,11 @@ Please submit there instead, or use --nodevelproject to force direct submission. @cmdln.option('-r', '--revision', metavar='rev', help='branch against a specific revision') @cmdln.option('--linkrev', metavar='linkrev', - help='specify the used revision in the link target.') + help='specify the used revision in the link target.') @cmdln.option('--add-repositories-block', metavar='add_repositories_block', - help='specify the used block strategy for new repositories') + help='specify the used block strategy for new repositories') @cmdln.option('--add-repositories-rebuild', metavar='add_repositories_rebuild', - help='specify the used rebuild strategy for new repositories') + help='specify the used rebuild strategy for new repositories') def do_branch(self, subcmd, opts, *args): """ Branch a package @@ -3573,7 +3555,7 @@ Please submit there instead, or use --nodevelproject to force direct submission. def_p = find_default_project(self.get_api_url(), args[0]) print('defaulting to %s/%s' % (def_p, args[0]), file=sys.stderr) # python has no args.unshift ??? - args = [ def_p, args[0] ] + args = [def_p, args[0]] if len(args) == 0 and is_package_dir('.'): args = (store_read_project('.'), store_read_package('.')) @@ -3628,19 +3610,19 @@ Please submit there instead, or use --nodevelproject to force direct submission. if not exists and (srcprj != self._process_project_name(args[0]) or srcpkg != args[1]): try: root = ET.fromstring(b''.join(show_attribute_meta(apiurl, args[0], None, None, - conf.config['maintained_update_project_attribute'], False, False))) + conf.config['maintained_update_project_attribute'], False, False))) # this might raise an AttributeError uproject = root.find('attribute').find('value').text - print('\nNote: The branch has been created from the configured update project: %s' \ - % uproject) + print('\nNote: The branch has been created from the configured update project: %s' + % uproject) except (AttributeError, HTTPError) as e: devloc = srcprj - print('\nNote: The branch has been created of a different project,\n' \ - ' %s,\n' \ - ' which is the primary location of where development for\n' \ - ' that package takes place.\n' \ - ' That\'s also where you would normally make changes against.\n' \ - ' A direct branch of the specified package can be forced\n' \ + print('\nNote: The branch has been created of a different project,\n' + ' %s,\n' + ' which is the primary location of where development for\n' + ' that package takes place.\n' + ' That\'s also where you would normally make changes against.\n' + ' A direct branch of the specified package can be forced\n' ' with the --nodevelproject option.\n' % devloc) package = targetpkg or args[1] @@ -3653,14 +3635,13 @@ Please submit there instead, or use --nodevelproject to force direct submission. apiopt = '' if conf.get_configParser().get('general', 'apiurl') != apiurl: apiopt = '-A %s ' % apiurl - print('A working copy of the branched package can be checked out with:\n\n' \ - 'osc %sco %s/%s' \ - % (apiopt, targetprj, package)) + print('A working copy of the branched package can be checked out with:\n\n' + 'osc %sco %s/%s' + % (apiopt, targetprj, package)) print_request_list(apiurl, args[0], args[1]) if devloc: print_request_list(apiurl, devloc, srcpkg) - @cmdln.option('-m', '--message', metavar='TEXT', help='specify log message TEXT') def do_undelete(self, subcmd, opts, *args): @@ -3695,7 +3676,6 @@ Please submit there instead, or use --nodevelproject to force direct submission. else: undelete_project(apiurl, prj, msg) - @cmdln.option('-r', '--recursive', action='store_true', help='deletes a project with packages inside') @cmdln.option('-f', '--force', action='store_true', @@ -3732,36 +3712,35 @@ Please submit there instead, or use --nodevelproject to force direct submission. msg = edit_message() # empty arguments result in recursive project delete ... - if not len(prj): + if not prj: raise oscerr.WrongArgs('Project argument is empty') if len(args) > 1: pkg = args[1] - if not len(pkg): + if not pkg: raise oscerr.WrongArgs('Package argument is empty') - ## FIXME: core.py:commitDelPackage() should have something similar + # FIXME: core.py:commitDelPackage() should have something similar rlist = get_request_list(apiurl, prj, pkg) for rq in rlist: print(rq) if len(rlist) >= 1 and not opts.force: - print('Package has pending requests. Deleting the package will break them. '\ - 'They should be accepted/declined/revoked before deleting the package. '\ + print('Package has pending requests. Deleting the package will break them. ' + 'They should be accepted/declined/revoked before deleting the package. ' 'Or just use \'--force\'.', file=sys.stderr) sys.exit(1) delete_package(apiurl, prj, pkg, opts.force, msg) elif (not opts.recursive) and len(meta_get_packagelist(apiurl, prj)) >= 1: - print('Project contains packages. It must be empty before deleting it. ' \ - 'If you are sure that you want to remove this project and all its ' \ - 'packages use the \'--recursive\' switch.', file=sys.stderr) + print('Project contains packages. It must be empty before deleting it. ' + 'If you are sure that you want to remove this project and all its ' + 'packages use the \'--recursive\' switch.', file=sys.stderr) sys.exit(1) else: delete_project(apiurl, prj, opts.force, msg) - @cmdln.option('-m', '--message', metavar='TEXT', help='specify log message TEXT') def do_lock(self, subcmd, opts, project, package=None): @@ -3789,7 +3768,6 @@ Please submit there instead, or use --nodevelproject to force direct submission. meta = ET.tostring(root) edit_meta(kind, path_args=path_args, data=meta, msg=opts.message) - @cmdln.option('-m', '--message', metavar='TEXT', help='specify log message TEXT') def do_unlock(self, subcmd, opts, *args): @@ -3816,13 +3794,13 @@ Please submit there instead, or use --nodevelproject to force direct submission. msg = edit_message() # empty arguments result in recursive project delete ... - if not len(prj): + if not prj: raise oscerr.WrongArgs('Project argument is empty') if len(args) > 1: pkg = args[1] - if not len(pkg): + if not pkg: raise oscerr.WrongArgs('Package argument is empty') unlock_package(apiurl, prj, pkg, msg) @@ -3851,7 +3829,6 @@ Please submit there instead, or use --nodevelproject to force direct submission. p.read_meta_from_spec(specfile) p.update_package_meta() - @cmdln.alias('linkdiff') @cmdln.alias('ldiff') @cmdln.alias('di') @@ -3870,7 +3847,7 @@ Please submit there instead, or use --nodevelproject to force direct submission. @cmdln.option('-l', '--link', action='store_true', help='(osc linkdiff): compare against the base revision of the link') @cmdln.option('--missingok', action='store_true', - help='do not fail if the source or target project/package does not exist on the server') + help='do not fail if the source or target project/package does not exist on the server') @cmdln.option('-u', '--unexpand', action='store_true', help='Local changes only, ignore changes in linked package sources') def do_diff(self, subcmd, opts, *args): @@ -3901,9 +3878,8 @@ Please submit there instead, or use --nodevelproject to force direct submission. if not opts.link or not len(args) == 2: pacs = findpacs(args) - if opts.link: - query = { 'rev': 'latest' } + query = {'rev': 'latest'} if pacs: u = makeurl(pacs[0].apiurl, ['source', pacs[0].prjname, pacs[0].name], query=query) else: @@ -3911,7 +3887,7 @@ Please submit there instead, or use --nodevelproject to force direct submission. f = http_GET(u) root = ET.parse(f).getroot() linkinfo = root.find('linkinfo') - if linkinfo == None: + if linkinfo is None: raise oscerr.APIError('package is not a source link') baserev = linkinfo.get('baserev') opts.revision = baserev @@ -3920,7 +3896,7 @@ Please submit there instead, or use --nodevelproject to force direct submission. else: print("diff committed package against linked revision %s\n" % baserev) run_pager(server_diff(self.get_api_url(), linkinfo.get('project'), linkinfo.get('package'), baserev, - args[0], args[1], linkinfo.get('lsrcmd5'), not opts.plain, opts.missingok)) + args[0], args[1], linkinfo.get('lsrcmd5'), not opts.plain, opts.missingok)) return if opts.change: @@ -3946,13 +3922,12 @@ Please submit there instead, or use --nodevelproject to force direct submission. diff += b''.join(i) else: diff += server_diff_noex(pac.apiurl, pac.prjname, pac.name, rev1, - pac.prjname, pac.name, rev2, - not opts.plain, opts.missingok, opts.meta, not opts.unexpand) + pac.prjname, pac.name, rev2, + not opts.plain, opts.missingok, opts.meta, not opts.unexpand) run_pager(diff) - @cmdln.option('--issues-only', action='store_true', - help='show only issues in diff') + help='show only issues in diff') @cmdln.option('-M', '--meta', action='store_true', help='diff meta data') @cmdln.option('-r', '--revision', metavar='N[:M]', @@ -3964,11 +3939,11 @@ Please submit there instead, or use --nodevelproject to force direct submission. help='the change made by revision rev (like -r rev-1:rev). ' 'If rev is negative this is like -r rev:rev-1.') @cmdln.option('--missingok', action='store_true', - help='do not fail if the source or target project/package does not exist on the server') + help='do not fail if the source or target project/package does not exist on the server') @cmdln.option('-u', '--unexpand', action='store_true', help='diff unexpanded version if sources are linked') @cmdln.option('--xml', action='store_true', - help='show diff as xml (only for issues diff)') + help='show diff as xml (only for issues diff)') def do_rdiff(self, subcmd, opts, *args): """ Server-side "pretty" diff of two packages @@ -4031,18 +4006,18 @@ Please submit there instead, or use --nodevelproject to force direct submission. rev1, rev2 = parseRevisionOption(opts.revision) rdiff = server_diff_noex(apiurl, - old_project, old_package, rev1, - new_project, new_package, rev2, not opts.plain, opts.missingok, - meta=opts.meta, - expand=not opts.unexpand, - onlyissues=opts.issues_only, - xml=opts.xml) + old_project, old_package, rev1, + new_project, new_package, rev2, not opts.plain, opts.missingok, + meta=opts.meta, + expand=not opts.unexpand, + onlyissues=opts.issues_only, + xml=opts.xml) if opts.issues_only: print(decode_it(rdiff)) else: run_pager(rdiff) - def _pdiff_raise_non_existing_package(self, project, package, msg = None): + 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)) def _pdiff_package_exists(self, apiurl, project, package): @@ -4054,7 +4029,7 @@ Please submit there instead, or use --nodevelproject to force direct submission. print('Cannot check that %s/%s exists: %s' % (project, package, e), file=sys.stderr) return False - def _pdiff_guess_parent(self, apiurl, project, package, check_exists_first = False): + def _pdiff_guess_parent(self, apiurl, project, package, check_exists_first=False): # Make sure the parent exists if check_exists_first and not self._pdiff_package_exists(apiurl, project, package): self._pdiff_raise_non_existing_package(project, package) @@ -4157,11 +4132,11 @@ Please submit there instead, or use --nodevelproject to force direct submission. else: raise RuntimeError('Internal error: bad check for arguments.') - ## Find parent package + # Find parent package # Old way, that does one more request to api #(parent_project, parent_package) = self._pdiff_get_parent_from_link(apiurl, project, package) - #if not parent_project: + # if not parent_project: # (parent_project, parent_package) = self._pdiff_guess_parent(apiurl, project, package, check_exists_first = True) # if parent_project and parent_package: # print 'Guessed that %s/%s is the parent package.' % (parent_project, parent_package) @@ -4171,7 +4146,7 @@ Please submit there instead, or use --nodevelproject to force direct submission. if not exists: self._pdiff_raise_non_existing_package(project, package) if not parent_project: - (parent_project, parent_package) = self._pdiff_guess_parent(apiurl, project, package, check_exists_first = False) + (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)) @@ -4181,11 +4156,11 @@ Please submit there instead, or use --nodevelproject to force direct submission. if not noparentok and not self._pdiff_package_exists(apiurl, parent_project, parent_package): self._pdiff_raise_non_existing_package(parent_project, parent_package, - msg = 'Parent for %s/%s (%s/%s) does not exist.' % \ + msg='Parent for %s/%s (%s/%s) does not exist.' % (project, package, parent_project, parent_package)) rdiff = server_diff(apiurl, parent_project, parent_package, None, project, - package, None, unified = unified, missingok = noparentok) + package, None, unified=unified, missingok=noparentok) run_pager(rdiff) @@ -4221,7 +4196,7 @@ Please submit there instead, or use --nodevelproject to force direct submission. sys.stdout.buffer.write(rdiff) except AttributeError as e: print(decode_it(rdiff)) - #run_pager(rdiff) + # run_pager(rdiff) def _prdiff_output_matching_requests(self, opts, requests, srcprj, pkg): @@ -4257,7 +4232,6 @@ Please submit there instead, or use --nodevelproject to force direct submission. help='show full unified diffs of differences') @cmdln.option('-d', '--diffstat', action='store_true', help='show diffstat of differences') - def do_prdiff(self, subcmd, opts, *args): """ Server-side diff of two projects @@ -4323,7 +4297,7 @@ Please submit there instead, or use --nodevelproject to force direct submission. oldprj, pkg, None, newprj, pkg, None, unified=True, missingok=False, meta=False, expand=True - ) + ) if rdiff: print("differs: %s" % pkg) @@ -4343,7 +4317,6 @@ Please submit there instead, or use --nodevelproject to force direct submission. if opts.show_not_in_old: print("new only: %s" % pkg) - def do_repourls(self, subcmd, opts, *args): """ Shows URLs of .repo files @@ -4353,8 +4326,6 @@ Please submit there instead, or use --nodevelproject to force direct submission. usage: osc repourls [PROJECT] """ - import tempfile - def _repo_type(apiurl, project, repo): if not os.path.exists('/usr/lib/build/queryconfig'): return None @@ -4363,7 +4334,7 @@ Please submit there instead, or use --nodevelproject to force direct submission. f.write(build_config) f.flush() repo_type = return_external('/usr/lib/build/queryconfig', '--dist', - f.name, 'repotype').rstrip(b'\n') + f.name, 'repotype').rstrip(b'\n') if not repo_type: return None return decode_it(repo_type) @@ -4396,7 +4367,6 @@ Please submit there instead, or use --nodevelproject to force direct submission. # We assume everything else is rpm-md print(url_tmpl % (project.replace(':', ':/'), repo, project)) - def do_browse(self, subcmd, opts, *args): """ Opens browser @@ -4434,7 +4404,6 @@ Please submit there instead, or use --nodevelproject to force direct submission. run_external('xdg-open', url) - @cmdln.option('-r', '--revision', metavar='rev', help='checkout the specified revision. ' 'NOTE: if you checkout the complete project ' @@ -4445,20 +4414,20 @@ Please submit there instead, or use --nodevelproject to force direct submission. @cmdln.option('-D', '--deleted', action='store_true', help='checkout an already deleted package. No meta information ') @cmdln.option('-u', '--unexpand-link', action='store_true', - help='if a package is a link, check out the _link file ' \ + help='if a package is a link, check out the _link file ' 'instead of the expanded sources') @cmdln.option('-M', '--meta', action='store_true', - help='checkout out meta data instead of sources' ) + help='checkout out meta data instead of sources') @cmdln.option('-c', '--current-dir', action='store_true', - help='place PACKAGE folder in the current directory ' \ + help='place PACKAGE folder in the current directory ' 'instead of a PROJECT/PACKAGE directory') @cmdln.option('-o', '--output-dir', metavar='outdir', - help='place package in the specified directory ' \ + help='place package in the specified directory ' 'instead of a PROJECT/PACKAGE directory') @cmdln.option('-s', '--source-service-files', action='store_true', - help='Run source services.' ) + help='Run source services.') @cmdln.option('-S', '--server-side-source-service-files', action='store_true', - help='Use server side generated sources instead of local generation.' ) + help='Use server side generated sources instead of local generation.') @cmdln.option('-l', '--limit-size', metavar='limit_size', help='Skip all files with a given size') @cmdln.alias('co') @@ -4502,11 +4471,11 @@ Please submit there instead, or use --nodevelproject to force direct submission. # obs://build.opensuse.org/openSUSE:11.3/standard/fc6c25e795a89503e99d59da5dc94a79-screen m = re.match(r"obs://([^/]+)/(\S+)/([^/]+)/([A-Fa-f\d]+)\-([^:]*)(:\S+)?", args[0]) if m and len(args) == 1: - apiurl = "https://" + m.group(1) + apiurl = "https://" + m.group(1) project = project_dir = m.group(2) # platform = m.group(3) - opts.revision = m.group(4) - package = m.group(5) + opts.revision = m.group(4) + package = m.group(5) apiurl = apiurl.replace('/build.', '/api.') filename = None else: @@ -4532,7 +4501,7 @@ Please submit there instead, or use --nodevelproject to force direct submission. raise oscerr.WrongOptions('-D | --deleted can only be used with a package') rev, dummy = parseRevisionOption(opts.revision) - if rev == None: + if rev is None: rev = "latest" if rev and rev != "latest" and not checkRevision(project, package, rev): @@ -4551,10 +4520,10 @@ Please submit there instead, or use --nodevelproject to force direct submission. else: if opts.current_dir: project_dir = None - checkout_package(apiurl, project, package, rev, expand_link=expand_link, \ - prj_dir=project_dir, service_files = opts.source_service_files, \ - server_service_files=opts.server_side_source_service_files, \ - progress_obj=self.download_progress, size_limit=opts.limit_size, \ + checkout_package(apiurl, project, package, rev, expand_link=expand_link, + prj_dir=project_dir, service_files=opts.source_service_files, + server_service_files=opts.server_side_source_service_files, + progress_obj=self.download_progress, size_limit=opts.limit_size, meta=opts.meta, outdir=opts.output_dir) print_request_list(apiurl, project, package) @@ -4571,7 +4540,7 @@ Please submit there instead, or use --nodevelproject to force direct submission. show_project_meta(apiurl, project) scm_url = show_scmsync(apiurl, project) - if scm_url != None: + if scm_url is not None: if not os.path.isfile('/usr/lib/obs/service/obs_scm_bridge'): raise oscerr.OscIOError(None, 'Install the obs-scm-bridge package to work on packages managed in scm (git)!') os.putenv("OSC_VERSION", get_osc_version()) @@ -4580,7 +4549,7 @@ Please submit there instead, or use --nodevelproject to force direct submission. Project.init_project(apiurl, prj_dir, project, conf.config['do_package_tracking'], scm_url=scm_url) print(statfrmt('A', prj_dir)) - if scm_url != None: + if scm_url is not None: return # all packages @@ -4605,28 +4574,27 @@ Please submit there instead, or use --nodevelproject to force direct submission. pass try: - checkout_package(apiurl, project, package, expand_link = expand_link, \ - prj_dir = prj_dir, service_files = opts.source_service_files, \ - server_service_files = opts.server_side_source_service_files, \ - progress_obj=self.download_progress, size_limit=opts.limit_size, \ + checkout_package(apiurl, project, package, expand_link=expand_link, + prj_dir=prj_dir, service_files=opts.source_service_files, + server_service_files=opts.server_side_source_service_files, + progress_obj=self.download_progress, size_limit=opts.limit_size, meta=opts.meta) except oscerr.LinkExpandError as e: print('Link cannot be expanded:\n', e, file=sys.stderr) print('Use "osc repairlink" for fixing merge conflicts:\n', file=sys.stderr) # check out in unexpanded form at least - checkout_package(apiurl, project, package, expand_link = False, \ - prj_dir = prj_dir, service_files = opts.source_service_files, \ - server_service_files = opts.server_side_source_service_files, \ - progress_obj=self.download_progress, size_limit=opts.limit_size, \ + checkout_package(apiurl, project, package, expand_link=False, + prj_dir=prj_dir, service_files=opts.source_service_files, + server_service_files=opts.server_side_source_service_files, + progress_obj=self.download_progress, size_limit=opts.limit_size, meta=opts.meta) print_request_list(apiurl, project) else: self.argparse_error("Incorrect number of arguments.") - @cmdln.option('-e', '--show-excluded', action='store_true', - help='also show files which are excluded by the ' \ + help='also show files which are excluded by the ' '"exclude_glob" config option') @cmdln.alias('st') def do_status(self, subcmd, opts, *args): @@ -4691,7 +4659,6 @@ Please submit there instead, or use --nodevelproject to force direct submission. if lines: print('\n'.join(lines)) - @cmdln.option('-f', '--force', action='store_true', help='add files even if they are excluded by the exclude_glob config option') def do_add(self, subcmd, opts, *args): @@ -4714,7 +4681,7 @@ Please submit there instead, or use --nodevelproject to force direct submission. # Do some magic here, when adding a url. We want that the server to download the tar ball and to verify it for arg in parseargs(args): if arg.endswith('.git') or arg.startswith('git://') or \ - arg.startswith('git@') or (arg.startswith('https://github.com') and not '/releases/' in arg) or \ + arg.startswith('git@') or (arg.startswith('https://github.com') and '/releases/' not in arg) or \ arg.startswith('https://gitlab.com'): addGitSource(arg) elif arg.startswith('http://') or arg.startswith('https://') or arg.startswith('ftp://'): @@ -4722,7 +4689,6 @@ Please submit there instead, or use --nodevelproject to force direct submission. else: addFiles([arg], force=opts.force) - def do_mkpac(self, subcmd, opts, *args): """ Create a new package under version control @@ -4731,8 +4697,8 @@ Please submit there instead, or use --nodevelproject to force direct submission. osc mkpac new_package """ if not conf.config['do_package_tracking']: - print("to use this feature you have to enable \'do_package_tracking\' " \ - "in the [general] section in the configuration file", file=sys.stderr) + print("to use this feature you have to enable \'do_package_tracking\' " + "in the [general] section in the configuration file", file=sys.stderr) sys.exit(1) if len(args) != 1: @@ -4768,14 +4734,14 @@ Please submit there instead, or use --nodevelproject to force direct submission. if opts.recursive: for pac in prj.pacs_have: state = prj.get_state(pac) - if state != None and state != 'D': + if state is not None and state != 'D': pac_dir = getTransActPath(os.path.join(prj.dir, pac)) args.append(pac_dir) args.remove(arg) prj.write_packages() elif is_project_dir(arg): - print('osc: addremove is not supported in a project dir unless ' \ - '\'do_package_tracking\' is enabled in the configuration file', file=sys.stderr) + print('osc: addremove is not supported in a project dir unless ' + '\'do_package_tracking\' is enabled in the configuration file', file=sys.stderr) sys.exit(1) pacs = findpacs(args) @@ -4838,7 +4804,6 @@ Please submit there instead, or use --nodevelproject to force direct submission. print("or use the --noservice option") return 1 - def _commit(self, subcmd, opts, args): args = parseargs(args) @@ -4874,7 +4839,7 @@ Please submit there instead, or use --nodevelproject to force direct submission. for pac in prj.pacs_have if prj.get_state(pac) == ' ') can_branch = False if any(pac.is_link_to_different_project() for pac in pacs): - repl = raw_input('Some of the packages are links to a different project!\n' \ + repl = raw_input('Some of the packages are links to a different project!\n' 'Create a local branch before commit? (y|N) ') if repl in ('y', 'Y'): can_branch = True @@ -4936,7 +4901,7 @@ Please submit there instead, or use --nodevelproject to force direct submission. # check any of the packages is a link, if so, as for branching can_branch = False if any(pac.is_link_to_different_project() for pac in pacs): - repl = raw_input('Some of the packages are links to a different project!\n' \ + repl = raw_input('Some of the packages are links to a different project!\n' 'Create a local branch before commit? (y|N) ') if repl in ('y', 'Y'): can_branch = True @@ -4968,15 +4933,15 @@ Please submit there instead, or use --nodevelproject to force direct submission. 'if you are going to update the complete project or more than ' 'one package)') @cmdln.option('', '--linkrev', metavar='REV', - help='revision of the link target that is used during link expansion') + help='revision of the link target that is used during link expansion') @cmdln.option('-u', '--unexpand-link', action='store_true', help='if a package is an expanded link, update to the raw _link file') @cmdln.option('-e', '--expand-link', action='store_true', help='if a package is a link, update to the expanded sources') @cmdln.option('-s', '--source-service-files', action='store_true', - help='Run local source services after update.' ) + help='Run local source services after update.') @cmdln.option('-S', '--server-side-source-service-files', action='store_true', - help='Use server side generated sources instead of local generation.' ) + help='Use server side generated sources instead of local generation.') @cmdln.option('-l', '--limit-size', metavar='limit_size', help='Skip all files with a given size') @cmdln.alias('up') @@ -5103,7 +5068,6 @@ Please submit there instead, or use --nodevelproject to force direct submission. rev = None print_request_list(p.apiurl, p.prjname, p.name) - @cmdln.option('-f', '--force', action='store_true', help='forces removal of entire package and its files') @cmdln.alias('rm') @@ -5175,7 +5139,6 @@ Please submit there instead, or use --nodevelproject to force direct submission. elif state == 'S': sys.exit('\'%s\' is marked as skipped and no local file with this name exists' % filename) - def do_resolved(self, subcmd, opts, *args): """ Remove 'conflicted' state on working copy files @@ -5206,7 +5169,6 @@ Please submit there instead, or use --nodevelproject to force direct submission. print('Resolved conflicted state of "%s"' % filename) p.clear_from_conflictlist(filename) - @cmdln.alias('dists') def do_distributions(self, subcmd, opts, *args): """ @@ -5237,7 +5199,7 @@ Please submit there instead, or use --nodevelproject to force direct submission. apiurl = self.get_api_url() if len(files) == 0: - if not '/' in project: + if '/' not in project: raise oscerr.WrongArgs("Missing operand, type osc help rremove for help") else: files = (package, ) @@ -5254,7 +5216,7 @@ Please submit there instead, or use --nodevelproject to force direct submission. if opts.force: print(e, file=sys.stderr) body = e.read() - if e.code in [ 400, 403, 404, 500 ]: + if e.code in [400, 403, 404, 500]: if '' in body: msg = body.split('')[1] msg = msg.split('')[0] @@ -5265,14 +5227,14 @@ Please submit there instead, or use --nodevelproject to force direct submission. @cmdln.alias('r') @cmdln.option('-l', '--last-build', action='store_true', help='show last build results (succeeded/failed/unknown)') - @cmdln.option('-r', '--repo', action='append', default = [], + @cmdln.option('-r', '--repo', action='append', default=[], help='Show results only for specified repo(s)') - @cmdln.option('-a', '--arch', action='append', default = [], + @cmdln.option('-a', '--arch', action='append', default=[], help='Show results only for specified architecture(s)') @cmdln.option('-b', '--brief', action='store_true', help='show the result in "pkgname repo arch result". Default for -f') @cmdln.option('--no-multibuild', action='store_true', default=False, - help='Disable results for all direct affect packages inside of the project') + help='Disable results for all direct affect packages inside of the project') @cmdln.option('-M', '--multibuild-package', metavar='FLAVOR', action='append', default=[], help=HELP_MULTIBUILD_MANY) @cmdln.option('-V', '--vertical', action='store_true', @@ -5284,13 +5246,13 @@ Please submit there instead, or use --nodevelproject to force direct submission. @cmdln.option('-f', '--failed', action='store_true', help='show only failed results') @cmdln.option('', '--xml', action='store_true', default=False, - help='generate output in XML (former results_meta)') + help='generate output in XML (former results_meta)') @cmdln.option('', '--csv', action='store_true', default=False, - help='generate output in CSV format') + help='generate output in CSV format') @cmdln.option('', '--format', default='%(repository)s|%(arch)s|%(state)s|%(dirty)s|%(code)s|%(details)s', - help='format string for csv output') + help='format string for csv output') @cmdln.option('--show-excluded', action='store_true', - help='show repos that are excluded for this package') + help='show repos that are excluded for this package') def do_results(self, subcmd, opts, *args): """ Shows the build results of a package or project @@ -5317,7 +5279,7 @@ Please submit there instead, or use --nodevelproject to force direct submission. if len(args) > 1: package = args[1] - if project == None: + if project is None: raise oscerr.WrongOptions("No project given") if opts.failed and opts.status_filter: @@ -5327,7 +5289,7 @@ Please submit there instead, or use --nodevelproject to force direct submission. opts.status_filter = 'failed' opts.brief = True - if package == None: + if package is None: opts.hide_legend = None opts.name_filter = None opts.show_non_building = None @@ -5364,9 +5326,9 @@ Please submit there instead, or use --nodevelproject to force direct submission. kwargs['printJoin'] = '\n' get_results(**kwargs) - # WARNING: this function is also called by do_results. You need to set a default there # as well when adding a new option! + @cmdln.option('-b', '--brief', action='store_true', help='show the result in "pkgname repo arch result"') @cmdln.option('-w', '--watch', action='store_true', @@ -5374,7 +5336,7 @@ Please submit there instead, or use --nodevelproject to force direct submission. @cmdln.option('-c', '--csv', action='store_true', help='csv output') @cmdln.option('', '--xml', action='store_true', default=False, - help='generate output in XML') + help='generate output in XML') @cmdln.option('-s', '--status-filter', metavar='STATUS', help='show only packages with buildstatus STATUS (see legend)') @cmdln.option('-n', '--name-filter', metavar='EXPR', @@ -5386,7 +5348,7 @@ Please submit there instead, or use --nodevelproject to force direct submission. @cmdln.option('-V', '--vertical', action='store_true', help='list packages vertically instead horizontally') @cmdln.option('--show-excluded', action='store_true', - help='show packages that are excluded in all repos, also hide repos that have only excluded packages') + help='show packages that are excluded in all repos, also hide repos that have only excluded packages') @cmdln.alias('pr') def do_prjresults(self, subcmd, opts, *args): """ @@ -5422,10 +5384,10 @@ Please submit there instead, or use --nodevelproject to force direct submission. print('Please implement support for osc prjresults --watch without --xml.') return 2 - print('\n'.join(get_prj_results(apiurl, project, hide_legend=opts.quiet, \ - csv=opts.csv, status_filter=opts.status_filter, \ - name_filter=opts.name_filter, repo=opts.repo, \ - arch=opts.arch, vertical=opts.vertical, \ + print('\n'.join(get_prj_results(apiurl, project, hide_legend=opts.quiet, + csv=opts.csv, status_filter=opts.status_filter, + name_filter=opts.name_filter, repo=opts.repo, + arch=opts.arch, vertical=opts.vertical, show_excluded=opts.show_excluded, brief=opts.brief))) @cmdln.alias('rpmlint') @@ -5456,11 +5418,11 @@ Please submit there instead, or use --nodevelproject to force direct submission. @cmdln.option('-l', '--last', action='store_true', help='Show the last finished log file') @cmdln.option('--lastsucceeded', '--last-succeeded', action='store_true', - help='Show the last succeeded log file') + help='Show the last succeeded log file') @cmdln.option('-M', '--multibuild-package', metavar='FLAVOR', help=HELP_MULTIBUILD_ONE) @cmdln.option('-o', '--offset', metavar='OFFSET', - help='get log start or end from the offset') + help='get log start or end from the offset') @cmdln.option('-s', '--strip-time', action='store_true', help='strip leading build time from the log') def do_buildlog(self, subcmd, opts, *args): @@ -5480,8 +5442,6 @@ Please submit there instead, or use --nodevelproject to force direct submission. buildlog [REPOSITORY ARCH | BUILDLOGURL] """ - import osc.build - project = package = repository = arch = None apiurl = self.get_api_url() @@ -5497,7 +5457,7 @@ Please submit there instead, or use --nodevelproject to force direct submission. # no local build with this repo was done print('failed to guess arch, using hostarch') repository = args[0] - arch = osc.build.hostarch + arch = osc_build.hostarch elif len(args) < 2: self.print_repos() elif len(args) > 2: @@ -5511,7 +5471,7 @@ Please submit there instead, or use --nodevelproject to force direct submission. offset = 0 if subcmd == "blt" or subcmd == "buildlogtail": - query = { 'view': 'entry' } + query = {'view': 'entry'} if opts.last: query['last'] = 1 if opts.lastsucceeded: @@ -5523,7 +5483,7 @@ Please submit there instead, or use --nodevelproject to force direct submission. if opts.offset: offset = offset - int(opts.offset) else: - offset = offset - ( 8 * 1024 ) + offset = offset - (8 * 1024) if offset < 0: offset = 0 elif opts.offset: @@ -5531,7 +5491,6 @@ Please submit there instead, or use --nodevelproject to force direct submission. strip_time = opts.strip_time or conf.config['buildlog_strip_time'] print_buildlog(apiurl, quote_plus(project), quote_plus(package), quote_plus(repository), quote_plus(arch), offset, strip_time, opts.last, opts.lastsucceeded) - def print_repos(self, repos_only=False, exc_class=oscerr.WrongArgs, exc_msg='Missing arguments', project=None): wd = os.curdir doprint = False @@ -5565,11 +5524,11 @@ Please submit there instead, or use --nodevelproject to force direct submission. @cmdln.option('-l', '--last', action='store_true', help='Show the last finished log file') @cmdln.option('--lastsucceeded', '--last-succeeded', action='store_true', - help='Show the last succeeded log file') + help='Show the last succeeded log file') @cmdln.option('-M', '--multibuild-package', metavar='FLAVOR', help=HELP_MULTIBUILD_ONE) @cmdln.option('-o', '--offset', metavar='OFFSET', - help='get log starting or ending from the offset') + help='get log starting or ending from the offset') @cmdln.option('-s', '--strip-time', action='store_true', help='strip leading build time from the log') def do_remotebuildlog(self, subcmd, opts, *args): @@ -5606,7 +5565,7 @@ Please submit there instead, or use --nodevelproject to force direct submission. offset = 0 if subcmd == "rblt" or subcmd == "rbuildlogtail" or subcmd == "remotebuildlogtail": - query = { 'view': 'entry' } + query = {'view': 'entry'} if opts.last: query['last'] = 1 if opts.lastsucceeded: @@ -5618,7 +5577,7 @@ Please submit there instead, or use --nodevelproject to force direct submission. if opts.offset: offset = offset - int(opts.offset) else: - offset = offset - ( 8 * 1024 ) + offset = offset - (8 * 1024) if offset < 0: offset = 0 elif opts.offset: @@ -5627,7 +5586,6 @@ Please submit there instead, or use --nodevelproject to force direct submission. print_buildlog(apiurl, quote_plus(project), quote_plus(package), quote_plus(repository), quote_plus(arch), offset, strip_time, opts.last, opts.lastsucceeded) def _find_last_repo_arch(self, repo=None, fatal=True): - import glob files = glob.glob(os.path.join(os.getcwd(), store, "_buildinfo-*")) if repo is not None: files = [f for f in files @@ -5732,7 +5690,7 @@ Please submit there instead, or use --nodevelproject to force direct submission. apiurl = self.get_api_url() - if len(args) == 2: # 2 + if len(args) == 2: # 2 if is_package_dir('.'): package = store_read_package(wd) else: @@ -5766,9 +5724,9 @@ Please submit there instead, or use --nodevelproject to force direct submission. for package in root.findall('packagechange'): print(" ", package.get('change'), package.get('key')) - # FIXME: the new osc syntax should allow to specify multiple packages # FIXME: the command should optionally use buildinfo data to show all dependencies + def do_dependson(self, subcmd, opts, *args): """ Dependson shows the build dependencies inside of a project, valid for a given repository and architecture @@ -5793,7 +5751,6 @@ Please submit there instead, or use --nodevelproject to force direct submission. """ self._dependson(False, *args) - def do_whatdependson(self, subcmd, opts, *args): """ Show the packages that require the specified package during the build @@ -5814,7 +5771,6 @@ Please submit there instead, or use --nodevelproject to force direct submission. """ self._dependson(True, *args) - def _dependson(self, reverse, *args): wd = os.curdir args = slash_split(args) @@ -5828,7 +5784,7 @@ Please submit there instead, or use --nodevelproject to force direct submission. apiurl = self.get_api_url() - if len(args) < 3: # 2 + if len(args) < 3: # 2 if is_package_dir('.'): packages = [store_read_package(wd)] elif not is_project_dir('.'): @@ -5856,7 +5812,6 @@ Please submit there instead, or use --nodevelproject to force direct submission. for dep in package.findall('pkgdep'): print(" ", dep.text) - @cmdln.option('--alternative-project', metavar='PROJECT', help='specify the build target project') @cmdln.option('-M', '--multibuild-package', metavar='FLAVOR', @@ -5925,18 +5880,16 @@ Please submit there instead, or use --nodevelproject to force direct submission. apiurl = self.get_api_url() build_descr_data = None - if not build_descr is None: + if build_descr is not None: build_descr_data = open(build_descr, 'rb').read() 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: - from .build import get_prefer_pkgs - from .util import cpio print('Scanning the following dirs for local packages: %s' % ', '.join(opts.prefer_pkgs)) cpiodata = cpio.CpioWrite() - prefer_pkgs = get_prefer_pkgs(opts.prefer_pkgs, arch, - os.path.splitext(build_descr)[1], - cpiodata) + prefer_pkgs = osc_build.get_prefer_pkgs(opts.prefer_pkgs, arch, + os.path.splitext(build_descr)[1], + cpiodata) cpiodata.add(os.path.basename(build_descr.encode()), build_descr_data) build_descr_data = cpiodata.get() @@ -5944,11 +5897,10 @@ Please submit there instead, or use --nodevelproject to force direct submission. package = package + ":" + opts.multibuild_package print(decode_it(get_buildinfo(apiurl, - project, package, repository, arch, - specfile=build_descr_data, - debug=opts.debug, - addlist=opts.extra_pkgs))) - + project, package, repository, arch, + specfile=build_descr_data, + debug=opts.debug, + addlist=opts.extra_pkgs))) def do_buildconfig(self, subcmd, opts, *args): """ @@ -5981,7 +5933,7 @@ Please submit there instead, or use --nodevelproject to force direct submission. apiurl = self.get_api_url() if len(args) == 1: - #FIXME: check if args[0] is really a repo and not a project, need a is_project() function for this + # FIXME: check if args[0] is really a repo and not a project, need a is_project() function for this project = store_read_project(wd) repository = args[0] elif len(args) == 2: @@ -5992,7 +5944,6 @@ Please submit there instead, or use --nodevelproject to force direct submission. print(decode_it(get_buildconfig(apiurl, project, repository))) - def do_workerinfo(self, subcmd, opts, worker): """ Gets the information to a worker from the server @@ -6006,7 +5957,6 @@ Please submit there instead, or use --nodevelproject to force direct submission. apiurl = self.get_api_url() print(''.join(get_worker_info(apiurl, worker))) - @cmdln.option('', '--ignore-file', action='store_true', help='ignore _constraints file and only check project constraints') def do_checkconstraints(self, subcmd, opts, *args): @@ -6122,26 +6072,22 @@ Please submit there instead, or use --nodevelproject to force direct submission. if disabled is not None: if ({'repo': repo.name, 'arch': repo.arch} in disabled or repo.name in [d['repo'] for d in disabled if d['arch'] is None] - or repo.arch in [d['arch'] for d in disabled if d['repo'] is None]): - continue + or repo.arch in [d['arch'] for d in disabled if d['repo'] is None]): + continue data += [repo.name, repo.arch] for row in build_table(2, data, width=2): print(row) - - def parse_repoarchdescr(self, args, noinit = False, alternative_project = None, ignore_descr = False, vm_type = None, multibuild_package = None): + def parse_repoarchdescr(self, args, noinit=False, alternative_project=None, ignore_descr=False, vm_type=None, multibuild_package=None): """helper to parse the repo, arch and build description from args""" - import osc.build - import glob - import tempfile arg_arch = arg_repository = arg_descr = None if len(args) < 3: # some magic, works only sometimes, but people seem to like it :/ all_archs = [] - for mainarch in osc.build.can_also_build: + for mainarch in osc_build.can_also_build: all_archs.append(mainarch) - for subarch in osc.build.can_also_build.get(mainarch): + for subarch in osc_build.can_also_build.get(mainarch): all_archs.append(subarch) for arg in args: if (arg.endswith('.spec') or arg.endswith('.dsc') or @@ -6152,10 +6098,10 @@ Please submit there instead, or use --nodevelproject to force direct submission. 'fissile.yml', 'appimage.yml', '_preinstallimage')): arg_descr = arg else: - if (arg == osc.build.hostarch or arg in all_archs) and arg_arch is None: + if (arg == osc_build.hostarch or arg in all_archs) and arg_arch is None: # it seems to be an architecture in general arg_arch = arg - if not (arg == osc.build.hostarch or arg in osc.build.can_also_build.get(osc.build.hostarch, [])): + if not (arg == osc_build.hostarch or arg in osc_build.can_also_build.get(osc_build.hostarch, [])): if not (vm_type == 'qemu' or vm_type == 'emulator'): print("WARNING: native compile is not possible, a emulator via binfmt misc handler must be configured!") elif not arg_repository: @@ -6168,22 +6114,22 @@ Please submit there instead, or use --nodevelproject to force direct submission. else: arg_repository, arg_arch, arg_descr = args - arg_arch = arg_arch or osc.build.hostarch - self._debug("hostarch: ", osc.build.hostarch) + arg_arch = arg_arch or osc_build.hostarch + self._debug("hostarch: ", osc_build.hostarch) self._debug("arg_arch: ", arg_arch) self._debug("arg_repository: ", arg_repository) self._debug("arg_descr: ", arg_descr) repositories = [] # store list of repos for potential offline use - repolistfile = os.path.join(os.getcwd(), osc.core.store, "_build_repositories") + repolistfile = os.path.join(os.getcwd(), store, "_build_repositories") if noinit: repositories = Repo.fromfile(repolistfile) else: project = alternative_project or store_read_project('.') apiurl = self.get_api_url() repositories = list(get_repos_of_project(apiurl, project)) - if not len(repositories): + if not repositories: raise oscerr.WrongArgs('no repositories defined for project \'%s\'' % project) if alternative_project is None: # only persist our own repos @@ -6206,10 +6152,10 @@ Please submit there instead, or use --nodevelproject to force direct submission. if not arg_repository: raise oscerr.WrongArgs('please specify a repository') if not noinit: - if not arg_repository in repo_names: + 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))) arches = [r.arch for r in repositories if r.name == arg_repository and r.arch] - if arches and not arg_arch in arches: + 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))) # can be implemented using @@ -6239,7 +6185,7 @@ Please submit there instead, or use --nodevelproject to force direct submission. if noinit: bc_filename = '_buildconfig-%s-%s' % (arg_repository, arg_arch) if is_package_dir('.'): - bc_filename = os.path.join(os.getcwd(), osc.core.store, bc_filename) + bc_filename = os.path.join(os.getcwd(), store, bc_filename) else: bc_filename = os.path.abspath(bc_filename) if not os.path.isfile(bc_filename): @@ -6289,7 +6235,6 @@ Please submit there instead, or use --nodevelproject to force direct submission. return arg_repository, arg_arch, arg_descr - @cmdln.option('--clean', action='store_true', help='Delete old build root before initializing it') @cmdln.option('-o', '--offline', action='store_true', @@ -6389,7 +6334,7 @@ Please submit there instead, or use --nodevelproject to force direct submission. @cmdln.option('--download-api-only', action='store_true', help='only fetch packages from the api') @cmdln.option('--oldpackages', metavar='DIR', - help='take previous build from DIR (special values: _self, _link)') + help='take previous build from DIR (special values: _self, _link)') @cmdln.option('--wipe', action='store_true', help=SUPPRESS_HELP) @cmdln.option('--shell', action='store_true', @@ -6401,7 +6346,7 @@ Please submit there instead, or use --nodevelproject to force direct submission. @cmdln.option('-f', '--force', action='store_true', help='Do not ask for confirmation to wipe') @cmdln.option('--host', metavar='HOST', - help='perform the build on a remote server - user@server:~/remote/directory') + help='perform the build on a remote server - user@server:~/remote/directory') @cmdln.option('--trust-all-projects', action='store_true', help='trust packages from all projects') @cmdln.option('--nopreinstallimage', '--no-preinstallimage', action='store_true', @@ -6475,9 +6420,6 @@ Please submit there instead, or use --nodevelproject to force direct submission. # OSC_BUILD_ROOT overrides the setting of build-root. # OSC_PACKAGECACHEDIR overrides the setting of packagecachedir. """ - - import osc.build - if which(conf.config['build-cmd']) is None: print('Error: build (\'%s\') command not found' % conf.config['build-cmd'], file=sys.stderr) print('Install the build package from http://download.opensuse.org/repositories/openSUSE:/Tools/', file=sys.stderr) @@ -6519,21 +6461,21 @@ Please submit there instead, or use --nodevelproject to force direct submission. else: args = self.parse_repoarchdescr(args, opts.noinit or opts.offline, opts.alternative_project, False, opts.vm_type, opts.multibuild_package) repo, arch, build_descr = args - prj, pac = osc.build.calculate_prj_pac(opts, build_descr) + prj, pac = osc_build.calculate_prj_pac(opts, build_descr) apihost = urlsplit(self.get_api_url())[1] - build_root = osc.build.calculate_build_root(apihost, prj, pac, repo, - arch) + build_root = osc_build.calculate_build_root(apihost, prj, pac, repo, + arch) if opts.wipe and not opts.force: - # Confirm delete - print("Really wipe '%s'? [y/N]: " % build_root) - choice = raw_input().lower() - if choice != 'y': - print('Aborting') - sys.exit(0) + # Confirm delete + print("Really wipe '%s'? [y/N]: " % build_root) + choice = raw_input().lower() + if choice != 'y': + print('Aborting') + sys.exit(0) build_args = ['--root=' + build_root, '--noinit', '--shell'] if opts.wipe: build_args.append('--wipe') - sys.exit(osc.build.run_build(opts, *build_args)) + 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('The semantics may change at any time!') @@ -6577,7 +6519,7 @@ Please submit there instead, or use --nodevelproject to force direct submission. print('Building %s for %s/%s' % (args[2], args[0], args[1])) if not opts.host: - return osc.build.main(self.get_api_url(), opts, args) + return osc_build.main(self.get_api_url(), opts, args) else: return self._do_rbuild(subcmd, opts, *args) @@ -6589,7 +6531,7 @@ Please submit there instead, or use --nodevelproject to force direct submission. return lst while name in lst: i = lst.index(name) - lst.pop(i+1) + lst.pop(i + 1) lst.pop(i) return lst @@ -6608,16 +6550,16 @@ Please submit there instead, or use --nodevelproject to force direct submission. pdir = pdir[:-1] hostprefer = os.path.join( - hostpath, - basename, - "%s__" % (long_name.replace('-', '_')), - os.path.basename(os.path.abspath(pdir))) + hostpath, + basename, + "%s__" % (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))] + pdir, + "%s:%s" % (hostname, os.path.dirname(hostprefer))] print('Run: %s' % " ".join(rsync_prefer_cmd)) ret = run_external(rsync_prefer_cmd[0], *rsync_prefer_cmd[1:]) if ret != 0: @@ -6625,17 +6567,16 @@ Please submit there instead, or use --nodevelproject to force direct submission. return 0 - cwd = os.getcwd() basename = os.path.basename(cwd) - if not ':' in opts.host: + if ':' not in opts.host: hostname = opts.host hostpath = "~/" else: hostname, hostpath = opts.host.split(':', 1) # arguments for build: use all arguments behind build and drop --host 'HOST' - hostargs = sys.argv[sys.argv.index(subcmd)+1:] + hostargs = sys.argv[sys.argv.index(subcmd) + 1:] drop_arg2(hostargs, '--host') # global arguments: use first '-' up to subcmd @@ -6658,10 +6599,10 @@ Please submit there instead, or use --nodevelproject to force direct submission. drop_arg2(hostargs, '-k') drop_arg2(hostargs, '--keep-pkgs') hostkeep = os.path.join( - hostpath, - basename, - "__keep_pkgs__", - "") # <--- this adds last '/', thus triggers correct rsync behavior + hostpath, + basename, + "__keep_pkgs__", + "") # <--- this adds last '/', thus triggers correct rsync behavior hostargs.append('--keep-pkgs') hostargs.append(hostkeep) @@ -6694,12 +6635,12 @@ Please submit there instead, or use --nodevelproject to force direct submission. ssh_cmd = \ ['ssh', '-t', hostname, - "cd %(remote_dir)s; %(osc_cmd)s %(global_args)s %(local_args)s" % dict( - remote_dir = os.path.join(hostpath, basename), - osc_cmd = osc_cmd, - global_args = " ".join(hostglobalargs), - local_args = " ".join(hostargs)) - ] + "cd %(remote_dir)s; %(osc_cmd)s %(global_args)s %(local_args)s" % dict( + remote_dir=os.path.join(hostpath, basename), + osc_cmd=osc_cmd, + global_args=" ".join(hostglobalargs), + local_args=" ".join(hostargs)) + ] print('Run: %s' % " ".join(ssh_cmd)) build_ret = run_external(ssh_cmd[0], *ssh_cmd[1:]) if build_ret != 0: @@ -6715,9 +6656,8 @@ Please submit there instead, or use --nodevelproject to force direct submission. return build_ret - @cmdln.option('', '--csv', action='store_true', - help='generate output in CSV (separated by |)') + help='generate output in CSV (separated by |)') @cmdln.option('-l', '--limit', metavar='limit', help='for setting the number of results') @cmdln.option('-M', '--multibuild-package', metavar='FLAVOR', @@ -6766,7 +6706,7 @@ Please submit there instead, or use --nodevelproject to force direct submission. print('\n'.join(get_buildhistory(apiurl, project, package, repository, arch, format, opts.limit))) @cmdln.option('', '--csv', action='store_true', - help='generate output in CSV (separated by |)') + help='generate output in CSV (separated by |)') @cmdln.option('-l', '--limit', metavar='limit', help='for setting the number of results') @cmdln.option('-M', '--multibuild-package', metavar='FLAVOR', @@ -6825,13 +6765,13 @@ Please submit there instead, or use --nodevelproject to force direct submission. @cmdln.option('-r', '--revision', metavar='rev', help='show log of the specified revision') @cmdln.option('', '--csv', action='store_true', - help='generate output in CSV (separated by |)') + help='generate output in CSV (separated by |)') @cmdln.option('', '--xml', action='store_true', - help='generate output in XML') + help='generate output in XML') @cmdln.option('-D', '--deleted', action='store_true', help='work on deleted package') @cmdln.option('-M', '--meta', action='store_true', - help='checkout out meta data instead of sources' ) + help='checkout out meta data instead of sources') def do_log(self, subcmd, opts, *args): """ Shows the commit log of a package @@ -6942,7 +6882,7 @@ Please submit there instead, or use --nodevelproject to force direct submission. command = args[0] - if not (command in ( 'runall', 'ra', 'run', 'localrun', 'manualrun', 'disabledrun', 'remoterun', 'lr', 'dr', 'mr', 'rr', 'merge', 'wait' )): + if command not in ('runall', 'ra', 'run', 'localrun', 'manualrun', 'disabledrun', 'remoterun', 'lr', 'dr', 'mr', 'rr', 'merge', 'wait'): raise oscerr.WrongArgs('Wrong command given.') if command == "remoterun" or command == "rr": @@ -6981,7 +6921,7 @@ Please submit there instead, or use --nodevelproject to force direct submission. @cmdln.option('-M', '--multibuild-package', metavar="FLAVOR", action='append', help=HELP_MULTIBUILD_MANY) @cmdln.option('--all', action='store_true', - help='Rebuild all packages of entire project') + help='Rebuild all packages of entire project') @cmdln.alias('rebuildpac') def do_rebuild(self, subcmd, opts, *args): """ @@ -7045,7 +6985,6 @@ Please submit there instead, or use --nodevelproject to force direct submission. for package in packages: print(rebuild(apiurl, project, package, repo, arch, code)) - def do_info(self, subcmd, opts, *args): """ Print information about a working copy @@ -7114,7 +7053,7 @@ Please submit there instead, or use --nodevelproject to force direct submission. @cmdln.option('-r', '--repo', metavar='REPO', help='Restart builds for a specific repository') @cmdln.option('--all', action='store_true', - help='Restart all running builds of entire project') + help='Restart all running builds of entire project') @cmdln.alias('abortbuild') def do_restartbuild(self, subcmd, opts, *args): """ @@ -7166,7 +7105,6 @@ Please submit there instead, or use --nodevelproject to force direct submission. for package in packages: print(cmdbuild(apiurl, subcmd, project, package, arch, repo)) - @cmdln.option('-a', '--arch', metavar='ARCH', help='Delete all binary packages for a specific architecture') @cmdln.option('-M', '--multibuild-package', metavar="FLAVOR", action='append', @@ -7174,15 +7112,15 @@ Please submit there instead, or use --nodevelproject to force direct submission. @cmdln.option('-r', '--repo', metavar='REPO', help='Delete all binary packages for a specific repository') @cmdln.option('--build-disabled', action='store_true', - help='Delete all binaries of packages for which the build is disabled') + help='Delete all binaries of packages for which the build is disabled') @cmdln.option('--build-failed', action='store_true', - help='Delete all binaries of packages for which the build failed') + help='Delete all binaries of packages for which the build failed') @cmdln.option('--broken', action='store_true', - help='Delete all binaries of packages for which the package source is bad') + help='Delete all binaries of packages for which the package source is bad') @cmdln.option('--unresolvable', action='store_true', - help='Delete all binaries of packages which have dependency errors') + help='Delete all binaries of packages which have dependency errors') @cmdln.option('--all', action='store_true', - help='Delete all binaries regardless of the package status (previously default)') + help='Delete all binaries regardless of the package status (previously default)') @cmdln.alias("unpublish") def do_wipebinaries(self, subcmd, opts, *args): """ @@ -7253,7 +7191,6 @@ Please submit there instead, or use --nodevelproject to force direct submission. else: print(wipebinaries(apiurl, project, package, opts.arch, opts.repo, code)) - @cmdln.option('-d', '--destdir', default='./binaries', metavar='DIR', help='destination directory') @cmdln.option('-M', '--multibuild-package', metavar="FLAVOR", action='append', @@ -7311,7 +7248,7 @@ Please submit there instead, or use --nodevelproject to force direct submission. elif is_project_dir(os.getcwd()): project = store_read_project(os.curdir) else: - raise oscerr.WrongArgs('Missing arguments: either specify and ' \ + raise oscerr.WrongArgs('Missing arguments: either specify and ' ' or move to a project or package working copy') repository = args[0] if len(args) == 2: @@ -7356,7 +7293,7 @@ Please submit there instead, or use --nodevelproject to force direct submission. continue for i in binaries: - if binary != None and binary != i.name: + if binary is not None and binary != i.name: continue # skip source rpms if not opts.sources and (i.name.endswith('.src.rpm') or i.name.endswith('.sdeb')): @@ -7384,11 +7321,10 @@ Please submit there instead, or use --nodevelproject to force direct submission. project, repository, arch, i.name, - package = pac, - target_filename = fname, - target_mtime = i.mtime, - progress_meter = not opts.quiet) - + package=pac, + target_filename=fname, + target_mtime=i.mtime, + progress_meter=not opts.quiet) @cmdln.option('-b', '--bugowner', action='store_true', help='restrict listing to items where the user is bugowner') @@ -7399,9 +7335,9 @@ Please submit there instead, or use --nodevelproject to force direct submission. @cmdln.option('-U', '--user', metavar='USER', help='search for USER instead of yourself') @cmdln.option('--exclude-project', action='append', - help='exclude requests for specified project') + help='exclude requests for specified project') @cmdln.option('--maintained', action='store_true', - help='limit search results to packages with maintained attribute set.') + help='limit search results to packages with maintained attribute set.') def do_my(self, subcmd, opts, *args): """ Show waiting work, packages, projects or requests involving yourself @@ -7475,7 +7411,7 @@ Please submit there instead, or use --nodevelproject to force direct submission. for r in sorted(requests, key=lambda x: x.reqid): print(r.list_view(), '\n') return - elif not type in args_pkg: + elif type not in args_pkg: raise oscerr.WrongArgs("invalid type %s" % type) role_filter = '' @@ -7490,8 +7426,8 @@ 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': "([kind='patchinfo' and issue[@state='OPEN' and owner/@login='%s']])" % user + }) f = http_GET(u) root = ET.parse(f).getroot() if root.findall('package'): @@ -7500,17 +7436,17 @@ Please submit there instead, or use --nodevelproject to force direct submission. project = node.get('project') package = node.get('name') print(project, "/", package, '\n') - p = makeurl(apiurl, ['source', project, package], { 'view': 'issues' }) + p = makeurl(apiurl, ['source', project, package], {'view': 'issues'}) fp = http_GET(p) issues = ET.parse(fp).findall('issue') for issue in issues: - if issue.find('state') == None or issue.find('state').text != "OPEN": + if issue.find('state') is None or issue.find('state').text != "OPEN": continue - if issue.find('owner') == None or issue.find('owner').find('login').text != user: + if issue.find('owner') is None or issue.find('owner').find('login').text != user: continue print(" #", issue.find('label').text, ': ', end=' ') desc = issue.find('summary') - if desc != None: + if desc is not None: print(desc.text) else: print("\n") @@ -7527,7 +7463,7 @@ Please submit there instead, or use --nodevelproject to force direct submission. 'reviewstates': 'new', 'roles': 'reviewer', 'user': user, - }) + }) f = http_GET(u) root = ET.parse(f).getroot() if root.findall('request'): @@ -7543,7 +7479,7 @@ Please submit there instead, or use --nodevelproject to force direct submission. 'states': 'new', 'roles': 'maintainer', 'user': user, - }) + }) f = http_GET(u) root = ET.parse(f).getroot() if root.findall('request'): @@ -7559,7 +7495,7 @@ Please submit there instead, or use --nodevelproject to force direct submission. 'states': 'declined', 'roles': 'creator', 'user': user, - }) + }) f = http_GET(u) root = ET.parse(f).getroot() if root.findall('request'): @@ -7592,7 +7528,7 @@ Please submit there instead, or use --nodevelproject to force direct submission. 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] - if not prj in request_todo or request_todo[prj] != []: + if prj not in request_todo or request_todo[prj] != []: request_todo.setdefault(prj, []).append(i.get('name')) else: for i in res.get('project_id', res.get('project', dummy_elm)).findall('project'): @@ -7603,7 +7539,7 @@ Please submit there instead, or use --nodevelproject to force direct submission. requests = get_user_projpkgs_request_list(apiurl, user, projpkgs=request_todo) for r in sorted(requests, key=lambda x: x.reqid): print(r.list_view(), '\n') - if not len(requests): + if not requests: print(" -> try also 'osc my sr' to see more.") else: for i in sorted(roles.keys()): @@ -7617,21 +7553,20 @@ Please submit there instead, or use --nodevelproject to force direct submission. out = ' %s (%s)' % (prjpac[1], ', '.join(sorted(roles[i]))) print(out) - @cmdln.option('--repos-baseurl', action='store_true', - help='show base URLs of download repositories') + help='show base URLs of download repositories') @cmdln.option('-e', '--exact', action='store_true', help='show only exact matches, this is default now') @cmdln.option('-s', '--substring', action='store_true', help='Show also results where the search term is a sub string, slower search') @cmdln.option('--package', action='store_true', - help='search for a package') + help='search for a package') @cmdln.option('--project', action='store_true', - help='search for a project') + help='search for a project') @cmdln.option('--title', action='store_true', - help='search for matches in the \'title\' element') + help='search for matches in the \'title\' element') @cmdln.option('--description', action='store_true', - help='search for matches in the \'description\' element') + help='search for matches in the \'description\' element') @cmdln.option('-a', '--limit-to-attribute', metavar='ATTRIBUTE', help='match only when given attribute exists in meta data') @cmdln.option('-V', '--version', action='store_true', @@ -7645,13 +7580,13 @@ Please submit there instead, or use --nodevelproject to force direct submission. @cmdln.option('-M', '--mine', action='store_true', help='shorthand for --bugowner --package') @cmdln.option('--csv', action='store_true', - help='generate output in CSV (separated by |)') + help='generate output in CSV (separated by |)') @cmdln.option('--binary', action='store_true', - help='search binary packages') + help='search binary packages') @cmdln.option('-B', '--baseproject', metavar='PROJECT', help='search packages built for PROJECT (implies --binary)') @cmdln.option('--binaryversion', metavar='VERSION', - help='search for binary with specified version (implies --binary)') + help='search for binary with specified version (implies --binary)') @cmdln.alias('se') @cmdln.alias('bse') def do_search(self, subcmd, opts, *args): @@ -7667,7 +7602,7 @@ Please submit there instead, or use --nodevelproject to force direct submission. osc bse ... ('osc search --binary') osc se 'perl(Foo::Bar)' ('osc search --package perl-Foo-Bar') """ - def build_xpath(attr, what, substr = False): + def build_xpath(attr, what, substr=False): if substr: return 'contains(%s, \'%s\')' % (attr, what) else: @@ -7695,7 +7630,7 @@ Please submit there instead, or use --nodevelproject to force direct submission. opts.package = True if (opts.title or opts.description) and (opts.involved or opts.bugowner or opts.maintainer): - raise oscerr.WrongOptions('Sorry, the options \'--title\' and/or \'--description\' ' \ + raise oscerr.WrongOptions('Sorry, the options \'--title\' and/or \'--description\' ' 'are mutually exclusive with \'-i\'/\'-b\'/\'-m\'/\'-M\'') if opts.substring and opts.exact: raise oscerr.WrongOptions('Sorry, the options \'--substring\' and \'--exact\' are mutually exclusive') @@ -7707,8 +7642,8 @@ Please submit there instead, or use --nodevelproject to force direct submission. if opts.binary and (opts.title or opts.description or opts.involved or opts.bugowner or opts.maintainer or opts.project or opts.package): - raise oscerr.WrongOptions('Sorry, \'--binary\' and \'--title\' or \'--description\' or \'--involved ' \ - 'or \'--bugowner\' or \'--maintainer\' or \'--limit-to-attribute \\ ' \ + raise oscerr.WrongOptions('Sorry, \'--binary\' and \'--title\' or \'--description\' or \'--involved ' + 'or \'--bugowner\' or \'--maintainer\' or \'--limit-to-attribute \\ ' 'or \'--project\' or \'--package\' are mutually exclusive') apiurl = self.get_api_url() @@ -7728,12 +7663,12 @@ Please submit there instead, or use --nodevelproject to force direct submission. search_type, search_term = [tmp[0], tmp[1]] else: search_type = 'person' - search_dict = { 'person' : 'userid', - 'group' : 'groupid' } + search_dict = {'person': 'userid', + 'group': 'groupid'} try: - search_id = search_dict[ search_type ] + search_id = search_dict[search_type] except KeyError: - search_type, search_id = [ 'person', 'userid' ] + 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) role_filter_xpath = xpath @@ -7797,10 +7732,10 @@ Please submit there instead, or use --nodevelproject to force direct submission. package = node.get('name') result.append(project) - if not package is None: + if package is not None: result.append(package) - if opts.version and package != None: + if opts.version and package is not None: sr = get_source_rev(apiurl, project, package) v = sr.get('version') r = sr.get('rev') @@ -7834,7 +7769,7 @@ Please submit there instead, or use --nodevelproject to force direct submission. result.append(node.get('filepath')) results.append(result) - if not len(results): + if not results: print('No matches found for \'%s\' in %ss' % (role_filter or search_term, kind)) continue # construct a sorted, flat list @@ -7849,9 +7784,9 @@ Please submit there instead, or use --nodevelproject to force direct submission. results = new headline = [] if kind == 'package' or kind == 'published/binary/id': - headline = [ '# Project', '# Package' ] + headline = ['# Project', '# Package'] else: - headline = [ '# Project' ] + headline = ['# Project'] if opts.version and kind == 'package': headline.append('# Ver') headline.append('Rev') @@ -7870,10 +7805,9 @@ Please submit there instead, or use --nodevelproject to force direct submission. if len(what.keys()) > 1: print('#' * 68) print('matches for \'%s\' in %ss:\n' % (role_filter or search_term, kind)) - for row in build_table(len(headline), results, headline, 2, csv = opts.csv): + for row in build_table(len(headline), results, headline, 2, csv=opts.csv): print(row) - @cmdln.option('-p', '--project', metavar='project', help='specify the path to a project') @cmdln.option('-n', '--name', metavar='name', @@ -7882,10 +7816,10 @@ Please submit there instead, or use --nodevelproject to force direct submission. help='set a title') @cmdln.option('-d', '--description', metavar='description', help='set the description of the package') - @cmdln.option('', '--delete-old-files', action='store_true', - help='delete existing files from the server') - @cmdln.option('-c', '--commit', action='store_true', - help='commit the new files') + @cmdln.option('', '--delete-old-files', action='store_true', + help='delete existing files from the server') + @cmdln.option('-c', '--commit', action='store_true', + help='commit the new files') def do_importsrcpkg(self, subcmd, opts, srpm): """ Import a new package from a src.rpm @@ -7902,9 +7836,6 @@ Please submit there instead, or use --nodevelproject to force direct submission. SRPM is the path of the src.rpm in the local filesystem, or an URL. """ - import glob - from .util import rpmquery - if opts.delete_old_files and conf.config['do_package_tracking']: # IMHO the --delete-old-files option doesn't really fit into our # package tracking strategy @@ -7917,7 +7848,6 @@ Please submit there instead, or use --nodevelproject to force direct submission. print('%s is not a valid link. It must not end with /' % srpm) sys.exit(1) print('trying to fetch', srpm) - from .grabber import OscFileGrabber OscFileGrabber().urlgrab(srpm) srpm = os.path.basename(srpm) @@ -7955,8 +7885,8 @@ Please submit there instead, or use --nodevelproject to force direct submission. # title and description can be empty if not pac: - print('please specify a package name with the \'--name\' option. ' \ - 'The automatic detection failed', file=sys.stderr) + print('please specify a package name with the \'--name\' option. ' + 'The automatic detection failed', file=sys.stderr) sys.exit(1) if conf.config['do_package_tracking']: createPackageDir(os.path.join(project.dir, pac), project) @@ -7980,7 +7910,7 @@ Please submit there instead, or use --nodevelproject to force direct submission. sys.exit(1) edit_meta(metatype='pkg', path_args=(quote_plus(project), quote_plus(pac)), - data = data, apiurl=apiurl) + data=data, apiurl=apiurl) Package.init_package(apiurl, project, pac, os.path.join(project_dir, pac)) else: print('error - local package already exists', file=sys.stderr) @@ -8005,14 +7935,13 @@ Please submit there instead, or use --nodevelproject to force direct submission. p.update_datastructs() p.commit() else: - print('No files were committed to the server. Please ' \ + print('No files were committed to the server. Please ' 'commit them manually.') print('Package \'%s\' only imported locally' % pac) sys.exit(1) print('Package \'%s\' imported successfully' % pac) - @cmdln.option('-X', '-m', '--method', default='GET', metavar='HTTP_METHOD', help='specify HTTP method to use (GET|PUT|DELETE|POST)') @cmdln.option('-e', '--edit', default=None, action='store_true', @@ -8043,7 +7972,7 @@ Please submit there instead, or use --nodevelproject to force direct submission. apiurl = self.get_api_url() - if not opts.method in ['GET', 'PUT', 'POST', 'DELETE']: + if opts.method not in ['GET', 'PUT', 'POST', 'DELETE']: sys.exit('unknown method %s' % opts.method) # default is PUT when uploading files @@ -8068,9 +7997,9 @@ Please submit there instead, or use --nodevelproject to force direct submission. if opts.edit: text = edit_text(out) r = http_request("PUT", - url, - data=text, - headers=opts.headers) + url, + data=text, + headers=opts.headers) out = r.read() if isinstance(out, str): @@ -8078,7 +8007,6 @@ Please submit there instead, or use --nodevelproject to force direct submission. else: sys.stdout.buffer.write(out) - @cmdln.option('-b', '--bugowner-only', action='store_true', help='Show only the bugowner') @cmdln.option('-B', '--bugowner', action='store_true', @@ -8086,7 +8014,7 @@ Please submit there instead, or use --nodevelproject to force direct submission. @cmdln.option('-e', '--email', action='store_true', help='show email addresses instead of user names') @cmdln.option('--nodevelproject', action='store_true', - help='do not follow a defined devel project ' \ + help='do not follow a defined devel project ' '(primary project where a package is developed)') @cmdln.option('-D', '--devel-project', metavar='devel_project', help='define the project where this package is primarily developed') @@ -8144,6 +8072,7 @@ Please submit there instead, or use --nodevelproject to force direct submission. if verbose: tags = ('login', 'realname', 'email') return get_user_data(apiurl, maintainer, *tags) + def setBugownerHelper(apiurl, project, package, bugowner): try: setBugowner(apiurl, project, package, bugowner) @@ -8164,11 +8093,11 @@ Please submit there instead, or use --nodevelproject to force direct submission. pac = None metaroot = None searchresult = None - roles = [ 'bugowner', 'maintainer' ] + roles = ['bugowner', 'maintainer'] if len(opts.role): roles = opts.role elif opts.bugowner_only or opts.bugowner or subcmd == 'bugowner': - roles = [ 'bugowner' ] + roles = ['bugowner'] args = slash_split(args) if opts.user or opts.group: @@ -8197,16 +8126,16 @@ Please submit there instead, or use --nodevelproject to force direct submission. if opts.all: limit = 0 filterroles = roles - if filterroles == [ 'bugowner', 'maintainer' ]: + if filterroles == ['bugowner', 'maintainer']: # use server side configured default filterroles = None if search_term: # try the package name first, it is faster and may catch cases where no # binary with that name exists for the given package name searchresult = owner(apiurl, search_term, "package", usefilter=filterroles, devel=None, limit=limit) - if searchresult == None or len(searchresult) == 0: + if searchresult is None or len(searchresult) == 0: searchresult = owner(apiurl, search_term, "binary", usefilter=filterroles, devel=None, limit=limit) - if searchresult != None and len(searchresult) == 0: + if searchresult is not None and len(searchresult) == 0: # We talk to an OBS 2.4 or later understanding the call if opts.set_bugowner or opts.set_bugowner_request: # filtered search did not succeed, but maybe we want to set an owner initially? @@ -8320,7 +8249,7 @@ Please submit there instead, or use --nodevelproject to force direct submission. for person in result.findall('person'): maintainers.setdefault(person.get('role'), []).append(person.get('name')) for group in result.findall('group'): - maintainers.setdefault(group.get('role'), []).append("group:"+group.get('name')) + maintainers.setdefault(group.get('role'), []).append("group:" + group.get('name')) projects = projects + [maintainers] # from meta data if metaroot: @@ -8329,7 +8258,7 @@ Please submit there instead, or use --nodevelproject to force direct submission. for person in metaroot.findall('person'): maintainers.setdefault(person.get('role'), []).append(person.get('userid')) for group in metaroot.findall('group'): - maintainers.setdefault(group.get('role'), []).append("group:"+group.get('groupid')) + maintainers.setdefault(group.get('role'), []).append("group:" + group.get('groupid')) projects = [maintainers] # showing the maintainers @@ -8347,7 +8276,7 @@ Please submit there instead, or use --nodevelproject to force direct submission. if prj: # not for user/group search for role in roles: - if opts.bugowner and not len(maintainers.get(role, [])): + if opts.bugowner and not maintainers.get(role, []): role = 'maintainer' if pac: print("%s%s of %s/%s : " % (indent, role, prj, pac)) @@ -8357,7 +8286,7 @@ Please submit there instead, or use --nodevelproject to force direct submission. emails = [] for maintainer in maintainers.get(role, []): user = get_maintainer_data(apiurl, maintainer, verbose=False) - if len(user): + if user: emails.append(''.join(user)) print(indent, end=' ') print(', '.join(emails) or '-') @@ -8394,7 +8323,6 @@ Please submit there instead, or use --nodevelproject to force direct submission. if len(user) == 3: print("%s: \"%s\" <%s>" % (user[0], user[1], user[2])) - @cmdln.option('-r', '--revision', metavar='rev', help='print out the specified revision') @cmdln.option('-e', '--expand', action='store_true', @@ -8449,7 +8377,7 @@ Please submit there instead, or use --nodevelproject to force direct submission. rev, dummy = parseRevisionOption(opts.revision) apiurl = self.get_api_url() - query = { } + query = {} if subcmd == 'blame': query['view'] = "blame" if opts.meta: @@ -8460,7 +8388,7 @@ Please submit there instead, or use --nodevelproject to force direct submission. query['rev'] = opts.revision if not opts.unexpand: query['rev'] = show_upstream_srcmd5(apiurl, project, package, expand=True, revision=opts.revision, meta=opts.meta, deleted=opts.deleted) - query['expand'] = 1 # important for blame case to follow links in old revisions + query['expand'] = 1 # important for blame case to follow links in old revisions u = makeurl(apiurl, ['source', project, package, filename], query=query) if subcmd == 'less': f = http_GET(u) @@ -8472,8 +8400,8 @@ Please submit there instead, or use --nodevelproject to force direct submission. else: sys.stdout.buffer.write(data) - # helper function to download a file from a specific revision + def download(self, name, md5, dir, destfile): o = open(destfile, 'wb') if md5 != '': @@ -8483,9 +8411,8 @@ Please submit there instead, or use --nodevelproject to force direct submission. o.write(buf) o.close() - @cmdln.option('-d', '--destdir', default='repairlink', metavar='DIR', - help='destination directory') + help='destination directory') def do_repairlink(self, subcmd, opts, *args): """ Repair a broken source link @@ -8524,62 +8451,62 @@ Please submit there instead, or use --nodevelproject to force direct submission. raise oscerr.WrongArgs('Please specify project and package') # first try stored reference, then lastworking - query = { 'rev': 'latest' } + query = {'rev': 'latest'} u = makeurl(apiurl, ['source', prj, package], query=query) f = http_GET(u) root = ET.parse(f).getroot() linkinfo = root.find('linkinfo') - if linkinfo == None: + if linkinfo is None: raise oscerr.APIError('package is not a source link') - if linkinfo.get('error') == None: + if linkinfo.get('error') is None: raise oscerr.APIError('source link is not broken') workingrev = None if linkinfo.get('baserev'): - query = { 'rev': 'latest', 'linkrev': 'base' } + query = {'rev': 'latest', 'linkrev': 'base'} u = makeurl(apiurl, ['source', prj, package], query=query) f = http_GET(u) root = ET.parse(f).getroot() linkinfo = root.find('linkinfo') - if linkinfo.get('error') == None: + if linkinfo.get('error') is None: workingrev = linkinfo.get('xsrcmd5') - if workingrev == None: - query = { 'lastworking': 1 } + if workingrev is None: + query = {'lastworking': 1} u = makeurl(apiurl, ['source', prj, package], query=query) f = http_GET(u) root = ET.parse(f).getroot() linkinfo = root.find('linkinfo') - if linkinfo == None: + if linkinfo is None: raise oscerr.APIError('package is not a source link') - if linkinfo.get('error') == None: + if linkinfo.get('error') is None: raise oscerr.APIError('source link is not broken') workingrev = linkinfo.get('lastworking') - if workingrev == None: + if workingrev is None: raise oscerr.APIError('source link never worked') print("using last working link target") else: print("using link target of last commit") - query = { 'expand': 1, 'emptylink': 1 } + query = {'expand': 1, 'emptylink': 1} u = makeurl(apiurl, ['source', prj, package], query=query) f = http_GET(u) meta = f.readlines() root_new = ET.fromstring(b''.join(meta)) - dir_new = { 'apiurl': apiurl, 'project': prj, 'package': package } + dir_new = {'apiurl': apiurl, 'project': prj, 'package': package} dir_new['srcmd5'] = root_new.get('srcmd5') dir_new['entries'] = [[n.get('name'), n.get('md5')] for n in root_new.findall('entry')] - query = { 'rev': workingrev } + query = {'rev': workingrev} u = makeurl(apiurl, ['source', prj, package], query=query) f = http_GET(u) root_oldpatched = ET.parse(f).getroot() linkinfo_oldpatched = root_oldpatched.find('linkinfo') - if linkinfo_oldpatched == None: + if linkinfo_oldpatched is None: raise oscerr.APIError('working rev is not a source link?') - if linkinfo_oldpatched.get('error') != None: + if linkinfo_oldpatched.get('error') is not None: raise oscerr.APIError('working rev is not working?') - dir_oldpatched = { 'apiurl': apiurl, 'project': prj, 'package': package } + dir_oldpatched = {'apiurl': apiurl, 'project': prj, 'package': package} dir_oldpatched['srcmd5'] = root_oldpatched.get('srcmd5') dir_oldpatched['entries'] = [[n.get('name'), n.get('md5')] for n in root_oldpatched.findall('entry')] @@ -8588,7 +8515,7 @@ Please submit there instead, or use --nodevelproject to force direct submission. u = makeurl(apiurl, ['source', linkinfo_oldpatched.get('project'), linkinfo_oldpatched.get('package')], query=query) f = http_GET(u) root_old = ET.parse(f).getroot() - dir_old = { 'apiurl': apiurl } + dir_old = {'apiurl': apiurl} dir_old['project'] = linkinfo_oldpatched.get('project') dir_old['package'] = linkinfo_oldpatched.get('package') dir_old['srcmd5'] = root_old.get('srcmd5') @@ -8656,14 +8583,14 @@ Please submit there instead, or use --nodevelproject to force direct submission. continue o = open(os.path.join(destdir, name), 'wb') - code = run_external('diff3', '-m', '-E', - '-L', '.mine', - os.path.join(destdir, name + '.mine'), - '-L', '.old', - os.path.join(destdir, name + '.old'), - '-L', '.new', - os.path.join(destdir, name + '.new'), - stdout=o) + code = run_external( + 'diff3', + '-m', '-E', + '-L', '.mine', os.path.join(destdir, name + '.mine'), + '-L', '.old', os.path.join(destdir, name + '.old'), + '-L', '.new', os.path.join(destdir, name + '.new'), + stdout=o + ) if code == 0: print(statfrmt('G', name)) os.unlink(os.path.join(destdir, name + '.mine')) @@ -8683,7 +8610,6 @@ Please submit there instead, or use --nodevelproject to force direct submission. print('fix the conflicts (files marked with \'C\' above),') print('run \'osc resolved ...\', and commit the changes.') - def do_pull(self, subcmd, opts, *args): """ Merge the changes of the link target into your working copy @@ -8709,36 +8635,36 @@ Please submit there instead, or use --nodevelproject to force direct submission. raise oscerr.WrongArgs('osc pull only works on expanded links.') linkinfo = p.linkinfo baserev = linkinfo.baserev - if baserev == None: + if baserev is None: raise oscerr.WrongArgs('osc pull only works on links containing a base revision.') # get revisions we need - query = { 'expand': 1, 'emptylink': 1 } + query = {'expand': 1, 'emptylink': 1} u = makeurl(p.apiurl, ['source', p.prjname, p.name], query=query) f = http_GET(u) meta = f.readlines() root_new = ET.fromstring(b''.join(meta)) linkinfo_new = root_new.find('linkinfo') - if linkinfo_new == None: + if linkinfo_new is None: raise oscerr.APIError('link is not a really a link?') - if linkinfo_new.get('error') != None: + if linkinfo_new.get('error') is not None: raise oscerr.APIError('link target is broken') if linkinfo_new.get('srcmd5') == baserev: print("Already up-to-date.") p.unmark_frozen() return - dir_new = { 'apiurl': p.apiurl, 'project': p.prjname, 'package': p.name } + dir_new = {'apiurl': p.apiurl, 'project': p.prjname, 'package': p.name} dir_new['srcmd5'] = root_new.get('srcmd5') dir_new['entries'] = [[n.get('name'), n.get('md5')] for n in root_new.findall('entry')] - dir_oldpatched = { 'apiurl': p.apiurl, 'project': p.prjname, 'package': p.name, 'srcmd5': p.srcmd5 } + dir_oldpatched = {'apiurl': p.apiurl, 'project': p.prjname, 'package': p.name, 'srcmd5': p.srcmd5} dir_oldpatched['entries'] = [[f.name, f.md5] for f in p.filelist] - query = { 'rev': linkinfo.srcmd5 } + query = {'rev': linkinfo.srcmd5} u = makeurl(p.apiurl, ['source', linkinfo.project, linkinfo.package], query=query) f = http_GET(u) root_old = ET.parse(f).getroot() - dir_old = { 'apiurl': p.apiurl, 'project': linkinfo.project, 'package': linkinfo.package, 'srcmd5': linkinfo.srcmd5 } + dir_old = {'apiurl': p.apiurl, 'project': linkinfo.project, 'package': linkinfo.package, 'srcmd5': linkinfo.srcmd5} dir_old['entries'] = [[n.get('name'), n.get('md5')] for n in root_old.findall('entry')] # now do 3-way merge @@ -8783,11 +8709,13 @@ Please submit there instead, or use --nodevelproject to force direct submission. continue o = open(name, 'wb') - code = run_external('diff3', '-m', '-E', - '-L', '.mine', name + '.mine', - '-L', '.old', name + '.old', - '-L', '.new', name + '.new', - stdout=o) + code = run_external( + 'diff3', '-m', '-E', + '-L', '.mine', name + '.mine', + '-L', '.old', name + '.old', + '-L', '.new', name + '.new', + stdout=o + ) if code == 0: print(statfrmt('G', name)) os.unlink(name + '.mine') @@ -8806,7 +8734,7 @@ Please submit there instead, or use --nodevelproject to force direct submission. store_write_string(p.absdir, '_pulled', linkinfo_new.get('srcmd5') + '\n') p.unmark_frozen() print() - if len(p.in_conflict): + if p.in_conflict: print('Please fix the conflicts (files marked with \'C\' above),') print('run \'osc resolved ...\', and commit the changes') print('to update the link information.') @@ -8922,8 +8850,6 @@ Please submit there instead, or use --nodevelproject to force direct submission. or can be specified via mailaddr environment variable. """ - - from subprocess import Popen if opts.message and opts.file: raise oscerr.WrongOptions('\'--message\' and \'--file\' are mutually exclusive') elif opts.message and opts.just_edit: @@ -8932,7 +8858,6 @@ Please submit there instead, or use --nodevelproject to force direct submission. raise oscerr.WrongOptions('\'--file\' and \'--just-edit\' are mutually exclusive') meego_style = False if not args: - import glob, re try: fn_changelog = glob.glob('*.changes')[0] fp = open(fn_changelog) @@ -8982,7 +8907,7 @@ Please submit there instead, or use --nodevelproject to force direct submission. cmd_list.extend(args) vc_export_env(apiurl) - vc = Popen(cmd_list) + vc = subprocess.Popen(cmd_list) vc.wait() sys.exit(vc.returncode) @@ -9021,15 +8946,15 @@ Please submit there instead, or use --nodevelproject to force direct submission. @cmdln.option('-p', '--prompt', action='store_true', help='prompt for a value') @cmdln.option('--change-password', action='store_true', - help='Change password') + help='Change password') @cmdln.option('--select-password-store', action='store_true', - help='Change the password store') + help='Change the password store') @cmdln.option('--no-echo', action='store_true', - help='prompt for a value but do not echo entered characters') + help='prompt for a value but do not echo entered characters') @cmdln.option('--dump', action='store_true', - help='dump the complete configuration (without \'pass\' and \'passx\' options)') + help='dump the complete configuration (without \'pass\' and \'passx\' options)') @cmdln.option('--dump-full', action='store_true', - help='dump the complete configuration (including \'pass\' and \'passx\' options)') + help='dump the complete configuration (including \'pass\' and \'passx\' options)') def do_config(self, subcmd, opts, *args): """ Get/set a config option @@ -9064,7 +8989,7 @@ Please submit there instead, or use --nodevelproject to force direct submission. print('[%s]' % sect) for opt in sorted(cp.options(sect)): if sect == 'general' and opt in conf.api_host_options or \ - sect != 'general' and not opt in conf.api_host_options: + sect != 'general' and opt not in conf.api_host_options: continue if opt in ('pass', 'passx') and not opts.dump_full: continue @@ -9076,19 +9001,18 @@ Please submit there instead, or use --nodevelproject to force direct submission. return section, opt, val = args[0], args[1], args[2:] - if len(val) and (opts.delete or opts.stdin or opts.prompt or opts.no_echo): - raise oscerr.WrongOptions('Sorry, \'--delete\' or \'--stdin\' or \'--prompt\' or \'--no-echo\' ' \ - 'and the specification of a value argument are mutually exclusive') + if val and (opts.delete or opts.stdin or opts.prompt or opts.no_echo): + raise oscerr.WrongOptions('Sorry, \'--delete\' or \'--stdin\' or \'--prompt\' or \'--no-echo\' ' + 'and the specification of a value argument are mutually exclusive') elif (opts.prompt or opts.no_echo) and opts.stdin: raise oscerr.WrongOptions('Sorry, \'--prompt\' or \'--no-echo\' and \'--stdin\' are mutually exclusive') elif opts.stdin: # strip lines val = [i.strip() for i in sys.stdin.readlines() if i.strip()] - if not len(val): + if not val: raise oscerr.WrongArgs('error: read empty value from stdin') elif opts.no_echo or opts.prompt: if opts.no_echo: - import getpass inp = getpass.getpass(prompt_value).strip() else: inp = raw_input(prompt_value).strip() @@ -9124,7 +9048,7 @@ Please submit there instead, or use --nodevelproject to force direct submission. """ pacs = findpacs(files) for p in pacs: - if not len(p.todo): + if not p.todo: p.todo = p.filenamelist + p.to_be_added for f in p.todo: p.revert(f) @@ -9144,8 +9068,8 @@ Please submit there instead, or use --nodevelproject to force direct submission. (.osc). Please check the state of the wc afterwards (via 'osc status'). """ def get_apiurl(apiurls): - print('No apiurl is defined for this working copy.\n' \ - 'Please choose one from the following list (enter the number):') + print('No apiurl is defined for this working copy.\n' + 'Please choose one from the following list (enter the number):') for i in range(len(apiurls)): print(' %d) %s' % (i, apiurls[i])) num = raw_input('> ') @@ -9180,8 +9104,8 @@ Please submit there instead, or use --nodevelproject to force direct submission. elif is_package_dir(i): pacs.append(i) else: - print('\'%s\' is neither a project working copy ' \ - 'nor a package working copy' % i, file=sys.stderr) + print('\'%s\' is neither a project working copy ' + 'nor a package working copy' % i, file=sys.stderr) for pdir in pacs: try: p = Package(pdir) @@ -9227,9 +9151,9 @@ Please submit there instead, or use --nodevelproject to force direct submission. os.unlink(os.path.join(p.absdir, filename)) @cmdln.option('-c', '--comment', - help='comment text', metavar='COMMENT') + help='comment text', metavar='COMMENT') @cmdln.option('-p', '--parent', - help='reply to comment with parent id', metavar='PARENT') + help='reply to comment with parent id', metavar='PARENT') def do_comment(self, subcmd, opts, *args): """ List / create / delete comments @@ -9261,13 +9185,13 @@ Please submit there instead, or use --nodevelproject to force direct submission. cmds = ['list', 'create', 'delete'] if args[0] not in cmds: - raise oscerr.WrongArgs('Unknown comment action %s. Choose one of %s.' \ - % (args[0], ', '.join(cmds))) + raise oscerr.WrongArgs('Unknown comment action %s. Choose one of %s.' + % (args[0], ', '.join(cmds))) comment_targets = ['package', 'project', 'request'] if args[0] != 'delete' and args[1] not in comment_targets: - raise oscerr.WrongArgs('Unknown comment target %s. Choose one of %s.' \ - % (args[1], ', '.join(comment_targets))) + raise oscerr.WrongArgs('Unknown comment target %s. Choose one of %s.' + % (args[1], ', '.join(comment_targets))) if args[1] == 'package' and len(args) != 4: raise oscerr.WrongArgs('Please use PROJECT PACKAGE') @@ -9324,13 +9248,12 @@ Please submit there instead, or use --nodevelproject to force direct submission. # to refer to the imported module. Instead use # ".". if (inspect.isfunction(data) and inspect.getmodule(data) == mod - or inspect.ismodule(data)): + or inspect.ismodule(data)): setattr(self.__class__, name, data) except (SyntaxError, NameError, ImportError) as e: - if (os.environ.get('OSC_PLUGIN_FAIL_IGNORE')): + if os.environ.get('OSC_PLUGIN_FAIL_IGNORE'): print("%s: %s\n" % (os.path.join(plugin_dir, extfile), e), file=sys.stderr) else: - import traceback traceback.print_exc(file=sys.stderr) print('\n%s: %s' % (os.path.join(plugin_dir, extfile), e), file=sys.stderr) print("\n Try 'env OSC_PLUGIN_FAIL_IGNORE=1 osc ...'", file=sys.stderr) diff --git a/osc/conf.py b/osc/conf.py index 61cf715a..d663d809 100644 --- a/osc/conf.py +++ b/osc/conf.py @@ -36,7 +36,6 @@ The configuration dictionary could look like this: """ -import bz2 import errno import getpass import os @@ -83,6 +82,7 @@ def _identify_osccookiejar(): return os.path.join(osc_state_dir, 'cookiejar') + DEFAULTS = {'apiurl': 'https://api.opensuse.org', 'user': None, 'pass': None, @@ -106,7 +106,7 @@ DEFAULTS = {'apiurl': 'https://api.opensuse.org', 'build-vm-user': '', # optional for VM builds 'build-kernel': '', # optional for VM builds 'build-initrd': '', # optional for VM builds - 'download-assets-cmd': '/usr/lib/build/download_assets', # optional for scm/git based builds + 'download-assets-cmd': '/usr/lib/build/download_assets', # optional for scm/git based builds 'build-jobs': str(_get_processors()), 'builtin_signature_check': '1', # by default use builtin check for verify pkgs @@ -178,7 +178,7 @@ DEFAULTS = {'apiurl': 'https://api.opensuse.org', # heuristic to speedup Package.status 'status_mtime_heuristic': '0' -} + } # some distros like Debian rename and move build to obs-build if not os.path.isfile('/usr/bin/build') and os.path.isfile('/usr/bin/obs-build'): @@ -187,17 +187,17 @@ if not os.path.isfile('/usr/lib/build/vc') and os.path.isfile('/usr/lib/obs-buil DEFAULTS['vc-cmd'] = '/usr/lib/obs-build/vc' boolean_opts = ['debug', 'do_package_tracking', 'http_debug', 'post_mortem', 'traceback', 'check_filelist', - 'checkout_no_colon', 'checkout_rooted', 'check_for_request_on_action', 'linkcontrol', 'show_download_progress', 'request_show_interactive', - 'request_show_source_buildstatus', 'review_inherit_group', 'use_keyring', 'no_verify', 'builtin_signature_check', - 'http_full_debug', 'include_request_from_project', 'local_service_run', 'buildlog_strip_time', 'no_preinstallimage', - 'status_mtime_heuristic', 'print_web_links', 'ccache', 'sccache', 'build-shell-after-fail'] + 'checkout_no_colon', 'checkout_rooted', 'check_for_request_on_action', 'linkcontrol', 'show_download_progress', 'request_show_interactive', + 'request_show_source_buildstatus', 'review_inherit_group', 'use_keyring', 'no_verify', 'builtin_signature_check', + 'http_full_debug', 'include_request_from_project', 'local_service_run', 'buildlog_strip_time', 'no_preinstallimage', + 'status_mtime_heuristic', 'print_web_links', 'ccache', 'sccache', 'build-shell-after-fail'] integer_opts = ['build-jobs'] api_host_options = ['user', 'pass', 'passx', 'aliases', 'http_headers', 'realname', 'email', 'sslcertck', 'cafile', 'capath', 'trusted_prj', - 'downloadurl', 'sshkey'] + 'downloadurl', 'sshkey'] -def apply_option_types(config): +def apply_option_types(config, conffile=""): """ Return a copy of `config` dictionary with values converted to their expected types according to the enumerated option types (boolean_opts, integer_opts). @@ -431,7 +431,7 @@ your credentials for this apiurl. def parse_apisrv_url(scheme, apisrv): if apisrv.startswith('http://') or apisrv.startswith('https://'): url = apisrv - elif scheme != None: + elif scheme is not None: url = scheme + apisrv else: url = "https://" + apisrv @@ -493,8 +493,8 @@ def get_apiurl_usr(apiurl): try: return get_apiurl_api_host_options(apiurl)['user'] except KeyError: - print('no specific section found in config file for host of [\'%s\'] - using default user: \'%s\'' \ - % (apiurl, config['user']), file=sys.stderr) + print('no specific section found in config file for host of [\'%s\'] - using default user: \'%s\'' + % (apiurl, config['user']), file=sys.stderr) return config['user'] @@ -559,7 +559,7 @@ def config_set_option(section, opt, val=None, delete=False, update=True, creds_m """ cp = get_configParser(config['conffile']) # don't allow "internal" options - general_opts = [i for i in DEFAULTS.keys() if not i in ['user', 'pass', 'passx']] + general_opts = [i for i in DEFAULTS.keys() if i not in ['user', 'pass', 'passx']] if section != 'general': section = config['apiurl_aliases'].get(section, section) scheme, host, path = \ @@ -577,10 +577,10 @@ def config_set_option(section, opt, val=None, delete=False, update=True, creds_m sections[apiurl] = url section = sections.get(section.rstrip('/'), section) - if not section in cp.sections(): + if section not in cp.sections(): raise oscerr.ConfigError('unknown section \'%s\'' % section, config['conffile']) - if section == 'general' and not opt in general_opts or \ - section != 'general' and not opt in api_host_options: + 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']) if not val and not delete and opt == 'pass' and creds_mgr_descr is not None: @@ -635,6 +635,7 @@ def config_set_option(section, opt, val=None, delete=False, update=True, creds_m return (opt, cp.get(section, opt, raw=True)) return (opt, None) + def _extract_user_compat(cp, section, creds_mgr): """ This extracts the user either from the ConfigParser or @@ -645,6 +646,7 @@ def _extract_user_compat(cp, section, creds_mgr): user = creds_mgr.get_user(section) return user + def write_initial_config(conffile, entries, custom_template='', creds_mgr_descriptor=None): """ write osc's intial configuration file. entries is a dict which contains values @@ -705,7 +707,7 @@ def _get_credentials_manager(url, cp): class APIHostOptionsEntry(dict): def __getitem__(self, key, *args, **kwargs): - value = super(self.__class__, self).__getitem__(key, *args, **kwargs) + value = super().__getitem__(key, *args, **kwargs) if key == 'pass' and callable(value): print('Warning: use of a deprecated credentials manager API.', file=sys.stderr) @@ -732,7 +734,7 @@ def get_config(override_conffile=None, conffile = os.path.expanduser(conffile) if not os.path.exists(conffile): - raise oscerr.NoConfigfile(conffile, \ + raise oscerr.NoConfigfile(conffile, account_not_configured_text % conffile) # okay, we made sure that oscrc exists @@ -759,7 +761,7 @@ def get_config(override_conffile=None, config = dict(cp.items('general', raw=1)) config['conffile'] = conffile - config = apply_option_types(config) + config = apply_option_types(config, conffile) config['packagecachedir'] = os.path.expanduser(config['packagecachedir']) config['exclude_glob'] = config['exclude_glob'].split() @@ -831,7 +833,7 @@ def get_config(override_conffile=None, if cp.has_option(url, 'build-root', proper=True): api_host_options[apiurl]['build-root'] = cp.get(url, 'build-root', raw=True) - if not 'sslcertck' in api_host_options[apiurl]: + if 'sslcertck' not in api_host_options[apiurl]: api_host_options[apiurl]['sslcertck'] = True if 'allow_http' not in api_host_options[apiurl]: @@ -868,8 +870,8 @@ def get_config(override_conffile=None, scheme = config.get('scheme', 'https') config['apiurl'] = urljoin(scheme, apisrv) if 'apisrc' in config or 'scheme' in config: - print('Warning: Use of the \'scheme\' or \'apisrv\' in oscrc is deprecated!\n' \ - 'Warning: See README for migration details.', file=sys.stderr) + print('Warning: Use of the \'scheme\' or \'apisrv\' in oscrc is deprecated!\n' + 'Warning: See README for migration details.', file=sys.stderr) if 'build_platform' in config: print('Warning: Use of \'build_platform\' config option is deprecated! (use \'build_repository\' instead)', file=sys.stderr) config['build_repository'] = config['build_platform'] @@ -933,6 +935,7 @@ def identify_conf(): return conffile + def interactive_config_setup(conffile, apiurl, initial=True): scheme = urlsplit(apiurl)[0] http = scheme == "http" @@ -959,6 +962,7 @@ def interactive_config_setup(conffile, apiurl, initial=True): else: add_section(conffile, apiurl, user, passwd, creds_mgr_descriptor=creds_mgr_descr, allow_http=http) + def select_credentials_manager_descr(): if not credentials.has_keyring_support(): print('To use keyrings please install python%d-keyring.' % sys.version_info.major) diff --git a/osc/connection.py b/osc/connection.py index 6516c2f8..3e9f9c80 100644 --- a/osc/connection.py +++ b/osc/connection.py @@ -44,7 +44,7 @@ class MockRequest: return self.headers.get(header_name, default) def has_header(self, header_name): - return (header_name in self.headers) + return header_name in self.headers def add_unredirected_header(self, key, val): # modifies the `headers` variable that was passed to object's constructor @@ -97,9 +97,6 @@ def get_proxy_manager(env): else: proxy_url = f"{proxy_purl.scheme}://{proxy_purl.host}" - # import osc.core here to avoid cyclic imports - from . import core - proxy_headers = urllib3.make_headers( proxy_basic_auth=proxy_purl.auth, user_agent=f"osc/{__version__}", @@ -167,9 +164,6 @@ def http_request(method, url, headers=None, data=None, file=None): :param file: Path to a file to send as data in the request body (conflicts with `data`). """ - # import osc.core here to avoid cyclic imports - from . import core - purl = urllib3.util.parse_url(url) apiurl = conf.extract_known_apiurl(url) headers = urllib3.response.HTTPHeaderDict(headers or {}) diff --git a/osc/core.py b/osc/core.py index 2ef74429..82128a3f 100644 --- a/osc/core.py +++ b/osc/core.py @@ -10,7 +10,12 @@ __store_version__ = '1.0' +import codecs +import datetime +import difflib import errno +import fnmatch +import glob import hashlib import locale import os @@ -20,6 +25,8 @@ import shlex import shutil import subprocess import sys +import tempfile +import textwrap import time from functools import cmp_to_key from http.client import IncompleteRead @@ -36,6 +43,7 @@ except ImportError: from . import __version__ from . import conf +from . import meter from . import oscerr from .connection import http_request, http_GET, http_POST, http_PUT, http_DELETE from .util.helper import decode_list, decode_it, raw_input, _html_escape @@ -43,14 +51,17 @@ from .util.helper import decode_list, decode_it, raw_input, _html_escape ET_ENCODING = "unicode" + def compare(a, b): return cmp(a[1:], b[1:]) + def cmp(a, b): return (a > b) - (a < b) + DISTURL_RE = re.compile(r"^(?P.*)://(?P.*?)/(?P.*?)/(?P.*?)/(?P.*)-(?P.*)$") BUILDLOGURL_RE = re.compile(r"^(?Phttps?://.*?)/build/(?P.*?)/(?P.*?)/(?P.*?)/(?P.*?)/_log$") -BUFSIZE = 1024*1024 +BUFSIZE = 1024 * 1024 store = '.osc' new_project_templ = """\ @@ -212,21 +223,21 @@ new_pattern_template = """\ --> """ -buildstatus_symbols = {'succeeded': '.', - 'disabled': ' ', +buildstatus_symbols = {'succeeded': '.', + 'disabled': ' ', 'expansion error': 'U', # obsolete with OBS 2.0 - 'unresolvable': 'U', - 'failed': 'F', - 'broken': 'B', - 'blocked': 'b', - 'building': '%', - 'finished': 'f', - 'scheduled': 's', - 'locked': 'L', - 'excluded': 'x', - 'dispatching': 'd', - 'signing': 'S', -} + 'unresolvable': 'U', + 'failed': 'F', + 'broken': 'B', + 'blocked': 'b', + 'building': '%', + 'finished': 'f', + 'scheduled': 's', + 'locked': 'L', + 'excluded': 'x', + 'dispatching': 'd', + 'signing': 'S', + } # os.path.samefile is available only under Unix @@ -236,16 +247,20 @@ def os_path_samefile(path1, path2): except AttributeError: return os.path.realpath(path1) == os.path.realpath(path2) + class File: """represent a file, including its metadata""" + def __init__(self, name, md5, size, mtime, skipped=False): self.name = name self.md5 = md5 self.size = size self.mtime = mtime self.skipped = skipped + def __repr__(self): return self.name + def __str__(self): return self.name @@ -253,6 +268,7 @@ class File: class Serviceinfo: """Source service content """ + def __init__(self): """creates an empty serviceinfo instance""" self.services = [] @@ -282,7 +298,7 @@ class Serviceinfo: error("invalid service name: %s" % name, service) mode = service.get('mode', '') data = {'name': name, 'mode': mode} - command = [ name ] + command = [name] for param in service.findall('param'): option = param.get('name') if option is None: @@ -315,30 +331,27 @@ class Serviceinfo: raise e def addVerifyFile(self, serviceinfo_node, filename): - import hashlib - f = open(filename, 'rb') digest = hashlib.sha256(f.read()).hexdigest() f.close() r = serviceinfo_node - s = ET.Element( "service", name="verify_file" ) + s = ET.Element("service", name="verify_file") ET.SubElement(s, "param", name="file").text = filename ET.SubElement(s, "param", name="verifier").text = "sha256" ET.SubElement(s, "param", name="checksum").text = digest - r.append( s ) + r.append(s) return r - def addDownloadUrl(self, serviceinfo_node, url_string): - url = urlparse( url_string ) + url = urlparse(url_string) protocol = url.scheme host = url.netloc path = url.path r = serviceinfo_node - s = ET.Element( "service", name="download_url" ) + s = ET.Element("service", name="download_url") ET.SubElement(s, "param", name="protocol").text = protocol ET.SubElement(s, "param", name="host").text = host ET.SubElement(s, "param", name="path").text = path @@ -348,33 +361,33 @@ class Serviceinfo: def addSetVersion(self, serviceinfo_node): r = serviceinfo_node - s = ET.Element( "service", name="set_version", mode="buildtime" ) - r.append( s ) + s = ET.Element("service", name="set_version", mode="buildtime") + r.append(s) return r def addGitUrl(self, serviceinfo_node, url_string): r = serviceinfo_node - s = ET.Element( "service", name="obs_scm" ) + s = ET.Element("service", name="obs_scm") ET.SubElement(s, "param", name="url").text = url_string ET.SubElement(s, "param", name="scm").text = "git" - r.append( s ) + r.append(s) return r def addTarUp(self, serviceinfo_node): r = serviceinfo_node - s = ET.Element( "service", name="tar", mode="buildtime" ) - r.append( s ) + s = ET.Element("service", name="tar", mode="buildtime") + r.append(s) return r def addRecompressTar(self, serviceinfo_node): r = serviceinfo_node - s = ET.Element( "service", name="recompress", mode="buildtime" ) + s = ET.Element("service", name="recompress", mode="buildtime") ET.SubElement(s, "param", name="file").text = "*.tar" ET.SubElement(s, "param", name="compression").text = "xz" - r.append( s ) + r.append(s) return r - def execute(self, dir, callmode = None, singleservice = None, verbose = None): + def execute(self, dir, callmode=None, singleservice=None, verbose=None): old_dir = os.path.join(dir, '.old') # if 2 osc instances are executed at a time one, of them fails on .old file existence @@ -396,8 +409,6 @@ class Serviceinfo: def _execute(self, dir, old_dir, callmode=None, singleservice=None, verbose=None): - import tempfile - # cleanup existing generated files for filename in os.listdir(dir): if filename.startswith('_service:') or filename.startswith('_service_'): @@ -408,7 +419,7 @@ class Serviceinfo: service_names = [s['name'] for s in allservices] if singleservice and singleservice not in service_names: # set array to the manual specified singleservice, if it is not part of _service file - data = { 'name' : singleservice, 'command' : [ singleservice ], 'mode' : callmode } + data = {'name': singleservice, 'command': [singleservice], 'mode': callmode} allservices = [data] elif singleservice: allservices = [s for s in allservices if s['name'] == singleservice] @@ -423,7 +434,7 @@ class Serviceinfo: os.putenv("OSC_VERSION", get_osc_version()) # set environment when using OBS 2.3 or later - if self.project != None: + if self.project is not None: # These need to be kept in sync with bs_service os.putenv("OBS_SERVICE_APIURL", self.apiurl) os.putenv("OBS_SERVICE_PROJECT", self.project) @@ -455,8 +466,8 @@ class Serviceinfo: cmd = service['command'] if not os.path.exists("/usr/lib/obs/service/" + cmd[0]): raise oscerr.PackageNotInstalled("obs-service-%s" % cmd[0]) - cmd[0] = "/usr/lib/obs/service/"+cmd[0] - cmd = cmd + [ "--outdir", temp_dir ] + cmd[0] = "/usr/lib/obs/service/" + cmd[0] + cmd = cmd + ["--outdir", temp_dir] if conf.config['verbose'] or verbose or conf.config['debug']: print("Run source service:", ' '.join(cmd)) r = run_external(*cmd) @@ -473,16 +484,18 @@ class Serviceinfo: else: name = service['name'] for filename in os.listdir(temp_dir): - os.rename(os.path.join(temp_dir, filename), os.path.join(dir, "_service:"+name+":"+filename)) + os.rename(os.path.join(temp_dir, filename), os.path.join(dir, "_service:" + name + ":" + filename)) finally: if temp_dir is not None: shutil.rmtree(temp_dir) return 0 + class Linkinfo: """linkinfo metadata (which is part of the xml representing a directory) """ + def __init__(self): """creates an empty linkinfo instance""" self.project = None @@ -499,7 +512,7 @@ class Linkinfo: elementtree node. If the passed element is ``None``, the method does nothing. """ - if linkinfo_node == None: + if linkinfo_node is None: return self.project = linkinfo_node.get('project') self.package = linkinfo_node.get('package') @@ -532,17 +545,18 @@ class Linkinfo: """return an informatory string representation""" if self.islink() and not self.isexpanded(): return 'project %s, package %s, xsrcmd5 %s, rev %s' \ - % (self.project, self.package, self.xsrcmd5, self.rev) + % (self.project, self.package, self.xsrcmd5, self.rev) elif self.islink() and self.isexpanded(): if self.haserror(): return 'broken link to project %s, package %s, srcmd5 %s, lsrcmd5 %s: %s' \ - % (self.project, self.package, self.srcmd5, self.lsrcmd5, self.error) + % (self.project, self.package, self.srcmd5, self.lsrcmd5, self.error) else: return 'expanded link to project %s, package %s, srcmd5 %s, lsrcmd5 %s' \ - % (self.project, self.package, self.srcmd5, self.lsrcmd5) + % (self.project, self.package, self.srcmd5, self.lsrcmd5) else: return 'None' + class DirectoryServiceinfo: def __init__(self): self.code = None @@ -570,13 +584,15 @@ class DirectoryServiceinfo: return self.error is not None # http://effbot.org/zone/element-lib.htm#prettyprint + + def xmlindent(elem, level=0): - i = "\n" + level*" " + i = "\n" + level * " " if len(elem): if not elem.text or not elem.text.strip(): elem.text = i + " " for e in elem: - xmlindent(e, level+1) + xmlindent(e, level + 1) if not e.tail or not e.tail.strip(): e.tail = i + " " if not e.tail or not e.tail.strip(): @@ -585,6 +601,7 @@ def xmlindent(elem, level=0): if level and (not elem.tail or not elem.tail.strip()): elem.tail = i + class Project: """ Represent a checked out project directory, holding packages. @@ -651,7 +668,6 @@ class Project: `wc_check` : bool """ - import fnmatch self.dir = dir self.absdir = os.path.abspath(dir) self.progress_obj = progress_obj @@ -676,11 +692,11 @@ class Project: if conf.config['do_package_tracking']: self.pac_root = self.read_packages().getroot() - self.pacs_have = [ pac.get('name') for pac in self.pac_root.findall('package') ] - self.pacs_excluded = [ i for i in os.listdir(self.dir) - for j in conf.config['exclude_glob'] - if fnmatch.fnmatch(i, j) ] - self.pacs_unvers = [ i for i in os.listdir(self.dir) if i not in self.pacs_have and i not in self.pacs_excluded ] + self.pacs_have = [pac.get('name') for pac in self.pac_root.findall('package')] + self.pacs_excluded = [i for i in os.listdir(self.dir) + for j in conf.config['exclude_glob'] + if fnmatch.fnmatch(i, j)] + self.pacs_unvers = [i for i in os.listdir(self.dir) if i not in self.pacs_have and i not in self.pacs_excluded] # store all broken packages (e.g. packages which where removed by a non-osc cmd) # in the self.pacs_broken list self.pacs_broken = [] @@ -690,15 +706,15 @@ class Project: # (except it is already marked as deleted ('D'-state)) self.pacs_broken.append(p) else: - self.pacs_have = [ i for i in os.listdir(self.dir) if i in self.pacs_available ] + self.pacs_have = [i for i in os.listdir(self.dir) if i in self.pacs_available] - self.pacs_missing = [ i for i in self.pacs_available if i not in self.pacs_have ] + self.pacs_missing = [i for i in self.pacs_available if i not in self.pacs_have] def wc_check(self): global store dirty_files = [] req_storefiles = Project.REQ_STOREFILES - if conf.config['do_package_tracking'] and self.scm_url == None: + if conf.config['do_package_tracking'] and self.scm_url is None: req_storefiles += ('_packages',) for fname in req_storefiles: if not os.path.exists(os.path.join(self.absdir, store, fname)): @@ -712,7 +728,7 @@ class Project: msg = 'cannot repair wc: the \'_apiurl\' file is missing but ' \ 'no \'apiurl\' was passed to wc_repair' # hmm should we raise oscerr.WrongArgs? - raise oscerr.WorkingCopyInconsistent(self.prjname, self.name, [], msg) + raise oscerr.WorkingCopyInconsistent(self.name, None, [], msg) # sanity check conf.parse_apisrv_url(None, apiurl) store_write_apiurl(self.dir, apiurl) @@ -739,8 +755,8 @@ class Project: continue print('checking out new package %s' % pac) - checkout_package(self.apiurl, self.name, pac, \ - pathname=getTransActPath(os.path.join(self.dir, pac)), \ + checkout_package(self.apiurl, self.name, pac, + pathname=getTransActPath(os.path.join(self.dir, pac)), prj_obj=self, prj_dir=self.dir, expand_link=expand_link or not unexpand_link, progress_obj=self.progress_obj) @@ -762,9 +778,9 @@ class Project: res = [] for pac in self.pacs_have: st = self.status(pac) - if not st in exclude_states: + if st not in exclude_states: res.append((st, pac)) - if not '?' in exclude_states: + if '?' not in exclude_states: res.extend([('?', pac) for pac in self.pacs_unvers]) return res @@ -779,7 +795,7 @@ class Project: def set_state(self, pac, state): node = self.get_package_node(pac) - if node == None: + if node is None: self.new_package_entry(pac, state) else: node.set('state', state) @@ -797,7 +813,7 @@ class Project: def get_state(self, pac): node = self.get_package_node(pac) - if node != None: + if node is not None: return node.get('state') else: return None @@ -839,13 +855,12 @@ class Project: store_write_string(self.absdir, '_packages', ET.tostring(self.pac_root, encoding=ET_ENCODING)) def addPackage(self, pac): - import fnmatch for i in conf.config['exclude_glob']: if fnmatch.fnmatch(pac, i): msg = 'invalid package name: \'%s\' (see \'exclude_glob\' config option)' % pac raise oscerr.OscIOError(None, msg) state = self.get_state(pac) - if state == None or state == 'D': + if state is None or state == 'D': self.new_package_entry(pac, 'A') self.write_packages() # sometimes the new pac doesn't exist in the list because @@ -855,7 +870,7 @@ class Project: else: raise oscerr.PackageExists(self.name, pac, 'package \'%s\' is already under version control' % pac) - def delPackage(self, pac, force = False): + def delPackage(self, pac, force=False): state = self.get_state(pac.name) can_delete = True if state == ' ' or state == 'D': @@ -888,13 +903,13 @@ class Project: print(statfrmt('D', pac.name)) else: print('package \'%s\' has local modifications (see osc st for details)' % pac.name) - elif state == None: + elif state is None: print('package is not under version control') else: print('unsupported state') - def update(self, pacs = (), expand_link=False, unexpand_link=False, service_files=False): - if len(pacs): + def update(self, pacs=(), expand_link=False, unexpand_link=False, service_files=False): + if pacs: for pac in pacs: Package(os.path.join(self.dir, pac), progress_obj=self.progress_obj).update() else: @@ -903,15 +918,15 @@ class Project: try: # update complete project # packages which no longer exists upstream - upstream_del = [ pac for pac in self.pacs_have if not pac in self.pacs_available and self.get_state(pac) != 'A'] - sinfo_pacs = [pac for pac in self.pacs_have if self.get_state(pac) in (' ', 'D') and not pac in self.pacs_broken] + upstream_del = [pac for pac in self.pacs_have if pac not in self.pacs_available and self.get_state(pac) != 'A'] + sinfo_pacs = [pac for pac in self.pacs_have if self.get_state(pac) in (' ', 'D') and pac not in self.pacs_broken] sinfo_pacs.extend(self.pacs_missing) sinfos = get_project_sourceinfo(self.apiurl, self.name, True, *sinfo_pacs) for pac in upstream_del: if self.status(pac) != '!': p = Package(os.path.join(self.dir, pac)) - self.delPackage(p, force = True) + self.delPackage(p, force=True) delete_storedir(p.storedir) try: os.rmdir(pac) @@ -932,7 +947,7 @@ class Project: p = Package(os.path.join(self.dir, pac), progress_obj=self.progress_obj) rev = None needs_update = True - if p.scm_url != None: + if p.scm_url is not None: # git managed. print("Skipping git managed package ", pac) continue @@ -987,8 +1002,9 @@ class Project: finally: self.write_packages() - def commit(self, pacs = (), msg = '', files = {}, verbose = False, skip_local_service_run = False, can_branch=False, force=False): - if len(pacs): + def commit(self, pacs=(), msg='', files=None, verbose=False, skip_local_service_run=False, can_branch=False, force=False): + files = files or {} + if pacs: try: for pac in pacs: todo = [] @@ -1011,7 +1027,7 @@ class Project: print('osc: \'%s\' is not under version control' % pac) elif pac in self.pacs_broken or not os.path.exists(os.path.join(self.dir, pac)): print('osc: \'%s\' package not found' % pac) - elif state == None: + elif state is None: self.commitExtPackage(pac, msg, todo, verbose=verbose, skip_local_service_run=skip_local_service_run) finally: self.write_packages() @@ -1034,8 +1050,9 @@ class Project: finally: self.write_packages() - def commitNewPackage(self, pac, msg = '', files = [], verbose = False, skip_local_service_run = False): + def commitNewPackage(self, pac, msg='', files=None, verbose=False, skip_local_service_run=False): """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) else: @@ -1043,8 +1060,8 @@ class Project: edit_meta(metatype='pkg', path_args=(quote_plus(self.name), quote_plus(pac)), template_args=({ - 'name': pac, - 'user': user}), + 'name': pac, + 'user': user}), apiurl=self.apiurl) # display the correct dir when sending the changes olddir = os.getcwd() @@ -1068,7 +1085,7 @@ class Project: else: pac_dir = os.path.join(self.dir, pac) p = Package(os.path.join(self.dir, pac)) - #print statfrmt('Deleting', os.path.normpath(os.path.join(p.dir, os.pardir, pac))) + # print statfrmt('Deleting', os.path.normpath(os.path.join(p.dir, os.pardir, pac))) delete_storedir(p.storedir) try: os.rmdir(p.dir) @@ -1078,13 +1095,14 @@ class Project: pac_dir = os.path.join(self.dir, pac) except (oscerr.NoWorkingCopy, oscerr.WorkingCopyOutdated, oscerr.PackageError): pass - #print statfrmt('Deleting', getTransActPath(os.path.join(self.dir, pac))) + # print statfrmt('Deleting', getTransActPath(os.path.join(self.dir, pac))) print(statfrmt('Deleting', getTransActPath(pac_dir))) delete_package(self.apiurl, self.name, pac) self.del_package_node(pac) - def commitExtPackage(self, pac, msg, files = [], verbose=False, skip_local_service_run=False): + def commitExtPackage(self, pac, msg, files=None, verbose=False, skip_local_service_run=False): """commits a package from an external project""" + files = files or [] if os_path_samefile(os.path.join(self.dir, pac), os.getcwd()): pac_path = '.' else: @@ -1143,8 +1161,8 @@ class Package: # should _meta be a required file? REQ_STOREFILES = ('_project', '_package', '_apiurl', '_files', '_osclib_version') OPT_STOREFILES = ('_to_be_added', '_to_be_deleted', '_in_conflict', '_in_update', - '_in_commit', '_meta', '_meta_mode', '_frozenlink', '_pulled', '_linkrepair', - '_size_limit', '_commit_msg', '_last_buildroot') + '_in_commit', '_meta', '_meta_mode', '_frozenlink', '_pulled', '_linkrepair', + '_size_limit', '_commit_msg', '_last_buildroot') def __init__(self, workingdir, progress_obj=None, size_limit=None, wc_check=True): global store @@ -1182,24 +1200,24 @@ class Package: if self.scm_url: return dirty_files for fname in self.filenamelist: - if not os.path.exists(os.path.join(self.storedir, fname)) and not fname in self.skipped: + if not os.path.exists(os.path.join(self.storedir, fname)) and fname not in self.skipped: dirty_files.append(fname) for fname in Package.REQ_STOREFILES: if not os.path.isfile(os.path.join(self.storedir, fname)): dirty_files.append(fname) for fname in os.listdir(self.storedir): if fname in Package.REQ_STOREFILES or fname in Package.OPT_STOREFILES or \ - fname.startswith('_build'): + fname.startswith('_build'): continue elif fname in self.filenamelist and fname in self.skipped: dirty_files.append(fname) - elif not fname in self.filenamelist: + elif fname not in self.filenamelist: dirty_files.append(fname) for fname in self.to_be_deleted[:]: - if not fname in self.filenamelist: + if fname not in self.filenamelist: dirty_files.append(fname) for fname in self.in_conflict[:]: - if not fname in self.filenamelist: + if fname not in self.filenamelist: dirty_files.append(fname) return dirty_files @@ -1217,24 +1235,24 @@ class Package: # all files which are present in the filelist have to exist in the storedir for f in self.filelist: # XXX: should we also check the md5? - if not os.path.exists(os.path.join(self.storedir, f.name)) and not f.name in self.skipped: + if not os.path.exists(os.path.join(self.storedir, f.name)) and f.name not in self.skipped: # if get_source_file fails we're screwed up... get_source_file(self.apiurl, self.prjname, self.name, f.name, - targetfilename=os.path.join(self.storedir, f.name), revision=self.rev, - mtime=f.mtime) + targetfilename=os.path.join(self.storedir, f.name), revision=self.rev, + mtime=f.mtime) for fname in os.listdir(self.storedir): if fname in Package.REQ_STOREFILES or fname in Package.OPT_STOREFILES or \ - fname.startswith('_build'): + fname.startswith('_build'): continue - elif not fname in self.filenamelist or fname in self.skipped: + elif fname not in self.filenamelist or fname in self.skipped: # this file does not belong to the storedir so remove it os.unlink(os.path.join(self.storedir, fname)) for fname in self.to_be_deleted[:]: - if not fname in self.filenamelist: + if fname not in self.filenamelist: self.to_be_deleted.remove(fname) self.write_deletelist() for fname in self.in_conflict[:]: - if not fname in self.filenamelist: + if fname not in self.filenamelist: self.in_conflict.remove(fname) self.write_conflictlist() @@ -1287,18 +1305,22 @@ class Package: # that's why we don't use clear_from_conflictlist self.in_conflict.remove(n) self.write_conflictlist() - if not state in ('A', '?') and not (state == '!' and was_added): + if state not in ('A', '?') and not (state == '!' and was_added): self.put_on_deletelist(n) self.write_deletelist() return (True, state) def delete_storefile(self, n): - try: os.unlink(os.path.join(self.storedir, n)) - except: pass + try: + os.unlink(os.path.join(self.storedir, n)) + except: + pass def delete_localfile(self, n): - try: os.unlink(os.path.join(self.dir, n)) - except: pass + try: + os.unlink(os.path.join(self.dir, n)) + except: + pass def put_on_deletelist(self, n): if n not in self.to_be_deleted: @@ -1377,7 +1399,7 @@ class Package: # only a workaround for ruby on rails, which swallows it otherwise if not copy_only: u = makeurl(self.apiurl, ['source', self.prjname, self.name, pathname2url(n)], query=query) - http_PUT(u, file = tfilename) + http_PUT(u, file=tfilename) if n in self.to_be_added: self.to_be_added.remove(n) @@ -1411,13 +1433,13 @@ class Package: return [] elif error != 'missing': raise oscerr.APIError('commit_get_missing_files: ' - 'unexpected \'error\' attr: \'%s\'' % error) + 'unexpected \'error\' attr: \'%s\'' % error) todo = [] for n in filelist.findall('entry'): name = n.get('name') if name is None: raise oscerr.APIError('missing \'name\' attribute:\n%s\n' - % ET.tostring(filelist, encoding=ET_ENCODING)) + % ET.tostring(filelist, encoding=ET_ENCODING)) todo.append(n.get('name')) return todo @@ -1467,7 +1489,7 @@ class Package: return 1 if not self.todo: - self.todo = [i for i in self.to_be_added if not i in self.filenamelist] + self.filenamelist + self.todo = [i for i in self.to_be_added if i not in self.filenamelist] + self.filenamelist pathn = getTransActPath(self.dir) @@ -1475,7 +1497,7 @@ class Package: todo_delete = [] real_send = [] sha256sums = {} - for filename in self.filenamelist + [i for i in self.to_be_added if not i in self.filenamelist]: + for filename in self.filenamelist + [i for i in self.to_be_added if i not in self.filenamelist]: if filename.startswith('_service:') or filename.startswith('_service_'): continue st = self.status(filename) @@ -1495,8 +1517,8 @@ class Package: f = self.findfilebyname(filename) if f is None: raise oscerr.PackageInternalError(self.prjname, self.name, - 'error: file \'%s\' with state \'%s\' is not known by meta' \ - % (filename, st)) + 'error: file \'%s\' with state \'%s\' is not known by meta' + % (filename, st)) todo_send[filename] = f.md5 elif st == 'D': todo_delete.append(filename) @@ -1508,11 +1530,11 @@ class Package: f = self.findfilebyname(filename) if f is None: raise oscerr.PackageInternalError(self.prjname, self.name, - 'error: file \'%s\' with state \'%s\' is not known by meta' \ - % (filename, st)) + 'error: file \'%s\' with state \'%s\' is not known by meta' + % (filename, st)) todo_send[filename] = f.md5 if ((self.ispulled() or self.islinkrepair() or self.isfrozen()) - and st != 'A' and filename not in sha256sums): + and st != 'A' and filename not in sha256sums): # Ignore files with state 'A': if we should consider it, # it would have been in pac.todo, which implies that it is # in sha256sums. @@ -1544,7 +1566,7 @@ class Package: fileelem.set('hash', 'sha256:%s' % sha256sums[filename]) sfilelist = self.__send_commitlog(msg, filelist) send = self.commit_get_missing(sfilelist) - real_send = [i for i in real_send if not i in send] + real_send = [i for i in real_send if i not in send] # abort after 3 tries tries = 3 tdir = None @@ -1553,7 +1575,7 @@ class Package: if os.path.isdir(tdir): shutil.rmtree(tdir) os.mkdir(tdir) - while len(send) and tries: + while send and tries: for filename in send[:]: sys.stdout.write('.') sys.stdout.flush() @@ -1562,10 +1584,10 @@ class Package: tries -= 1 sfilelist = self.__send_commitlog(msg, filelist) send = self.commit_get_missing(sfilelist) - if len(send): + if send: raise oscerr.PackageInternalError(self.prjname, self.name, - 'server does not accept filelist:\n%s\nmissing:\n%s\n' \ - % (ET.tostring(filelist, encoding=ET_ENCODING), ET.tostring(sfilelist, encoding=ET_ENCODING))) + 'server does not accept filelist:\n%s\nmissing:\n%s\n' + % (ET.tostring(filelist, encoding=ET_ENCODING), ET.tostring(sfilelist, encoding=ET_ENCODING))) # these files already exist on the server for filename in real_send: self.put_source_file(filename, tdir, copy_only=True) @@ -1649,12 +1671,12 @@ class Package: origfile = None get_source_file(self.apiurl, self.prjname, self.name, n, targetfilename=storefilename, - revision=revision, progress_obj=self.progress_obj, mtime=mtime, meta=self.meta) + revision=revision, progress_obj=self.progress_obj, mtime=mtime, meta=self.meta) shutil.copyfile(storefilename, filename) if mtime: utime(filename, (-1, mtime)) - if not origfile is None: + if origfile is not None: os.unlink(origfile) def mergefile(self, n, revision, mtime=None): @@ -1723,7 +1745,7 @@ class Package: for e in root.findall('entry'): size = e.get('size') if size and self.size_limit and int(size) > self.size_limit \ - or skip_service and (e.get('name').startswith('_service:') or e.get('name').startswith('_service_')): + or skip_service and (e.get('name').startswith('_service:') or e.get('name').startswith('_service_')): e.set('skipped', 'true') return ET.tostring(root, encoding=ET_ENCODING) @@ -1756,7 +1778,6 @@ class Package: file has changed (e.g. update_local_filesmeta() has been called). """ - import fnmatch if self.scm_url: self.filenamelist = [] self.filelist = [] @@ -1818,9 +1839,9 @@ class Package: if fnmatch.fnmatch(i, j): self.excluded.append(i) break - self.filenamelist_unvers = [ i for i in os.listdir(self.dir) - if i not in self.excluded - if i not in self.filenamelist ] + self.filenamelist_unvers = [i for i in os.listdir(self.dir) + if i not in self.excluded + if i not in self.filenamelist] def islink(self): """tells us if the package is a link (has 'linkinfo'). @@ -1903,7 +1924,7 @@ class Package: res = [] for fname in sorted(todo): st = self.status(fname) - if not st in exclude_states: + if st not in exclude_states: res.append((st, fname)) return res @@ -1958,7 +1979,7 @@ class Package: state = 'M' elif n in self.to_be_added and not exists: state = '!' - elif not exists and exists_in_store and known_by_meta and not n in self.to_be_deleted: + elif not exists and exists_in_store and known_by_meta and n not in self.to_be_deleted: state = '!' elif exists and not exists_in_store and not known_by_meta: state = '?' @@ -1966,10 +1987,10 @@ class Package: # XXX: this codepath shouldn't be reached (we restore the storefile # in update_datastructs) raise oscerr.PackageInternalError(self.prjname, self.name, - 'error: file \'%s\' is known by meta but no storefile exists.\n' - 'This might be caused by an old wc format. Please backup your current\n' - 'wc and checkout the package again. Afterwards copy all files (except the\n' - '.osc/ dir) into the new package wc.' % n) + 'error: file \'%s\' is known by meta but no storefile exists.\n' + 'This might be caused by an old wc format. Please backup your current\n' + 'wc and checkout the package again. Afterwards copy all files (except the\n' + '.osc/ dir) into the new package wc.' % n) elif os.path.islink(localfile): # dangling symlink, whose name is _not_ tracked: treat it # as unversioned @@ -1981,12 +2002,12 @@ class Package: return state def get_diff(self, revision=None, ignoreUnversioned=False): - import tempfile diff_hdr = b'Index: %s\n' diff_hdr += b'===================================================================\n' kept = [] added = [] deleted = [] + def diff_add_delete(fname, add, revision): diff = [] diff.append(diff_hdr % fname.encode()) @@ -1995,7 +2016,7 @@ class Package: if add: diff.append(b'--- %s\t(revision 0)\n' % fname.encode()) rev = 'revision 0' - if revision and not fname in self.to_be_added: + if revision and fname not in self.to_be_added: rev = 'working copy' diff.append(b'+++ %s\t(%s)\n' % (fname.encode(), rev.encode())) fname = os.path.join(self.absdir, fname) @@ -2010,7 +2031,7 @@ class Package: diff.append(b'--- %s\t(revision %s)\n' % (fname.encode(), b_revision)) diff.append(b'+++ %s\t(working copy)\n' % fname.encode()) fname = os.path.join(self.storedir, fname) - + try: if revision is not None and not add: (fd, tmpfile) = tempfile.mkstemp(prefix='osc_diff') @@ -2042,7 +2063,7 @@ class Package: return diff if revision is None: - todo = self.todo or [i for i in self.filenamelist if not i in self.to_be_added]+self.to_be_added + todo = self.todo or [i for i in self.filenamelist if i not in self.to_be_added] + self.to_be_added for fname in todo: if fname in self.to_be_added and self.status(fname) == 'A': added.append(fname) @@ -2051,8 +2072,8 @@ class Package: elif fname in self.filenamelist: kept.append(self.findfilebyname(fname)) elif fname in self.to_be_added and self.status(fname) == '!': - raise oscerr.OscIOError(None, 'file \'%s\' is marked as \'A\' but does not exist\n'\ - '(either add the missing file or revert it)' % fname) + 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) else: @@ -2062,7 +2083,7 @@ class Package: # swap added and deleted kept, deleted, added, services = self.__get_rev_changes(rfiles) added = [f.name for f in added] - added.extend([f for f in self.to_be_added if not f in kept]) + added.extend([f for f in self.to_be_added if f not in kept]) deleted = [f.name for f in deleted] deleted.extend(self.to_be_deleted) for f in added[:]: @@ -2088,7 +2109,7 @@ class Package: (fd, tmpfile) = tempfile.mkstemp(prefix='osc_diff') get_source_file(self.apiurl, self.prjname, self.name, f.name, tmpfile, revision) diff = get_source_file_diff(self.absdir, f.name, revision, - os.path.basename(tmpfile), os.path.dirname(tmpfile), f.name) + os.path.basename(tmpfile), os.path.dirname(tmpfile), f.name) finally: if tmpfile is not None: os.close(fd) @@ -2113,18 +2134,16 @@ linkinfo: %s rev: %s 'todo' files: %s """ % (self.name, - self.prjname, - self.dir, - '\n '.join(self.filenamelist), - self.linkinfo, - self.rev, - self.todo) + self.prjname, + self.dir, + '\n '.join(self.filenamelist), + self.linkinfo, + self.rev, + self.todo) return r - - def read_meta_from_spec(self, spec = None): - import glob + def read_meta_from_spec(self, spec=None): if spec: specfile = spec else: @@ -2139,7 +2158,7 @@ rev: %s print('please specify one with --specfile') sys.exit(1) else: - print('no specfile was found - please specify one ' \ + print('no specfile was found - please specify one ' 'with --specfile') sys.exit(1) @@ -2148,7 +2167,6 @@ rev: %s self.url = data.get('Url', '') self.descr = data.get('%description', '') - def update_package_meta(self, force=False): """ for the updatepacmetafromspec subcommand @@ -2161,13 +2179,13 @@ rev: %s root.find('title').text = self.summary root.find('description').text = ''.join(self.descr) url = root.find('url') - if url == None: + if url is None: url = ET.SubElement(root, 'url') url.text = self.url - delegate = lambda force=False: make_meta_url('pkg', - (self.prjname, self.name), - self.apiurl, force=force) + def delegate(force=False): return make_meta_url('pkg', + (self.prjname, self.name), + self.apiurl, force=force) url_factory = metafile._URLFactory(delegate) mf = metafile(url_factory, ET.tostring(root, encoding=ET_ENCODING)) @@ -2253,12 +2271,12 @@ rev: %s # treat skipped like added files # problem: this overwrites existing files during the update # (because skipped files aren't in self.filenamelist_unvers) - if f.name in self.filenamelist and not f.name in self.skipped: + if f.name in self.filenamelist and f.name not in self.skipped: kept.append(f) else: added.append(f) for f in self.filelist: - if not f.name in revfilenames: + if f.name not in revfilenames: deleted.append(f) return kept, added, deleted, services @@ -2299,12 +2317,11 @@ rev: %s return True return sinfo.get('srcmd5') != self.srcmd5 - def update(self, rev = None, service_files = False, size_limit = None): - import tempfile + def update(self, rev=None, service_files=False, size_limit=None): rfiles = [] # size_limit is only temporary for this update old_size_limit = self.size_limit - if not size_limit is None: + if size_limit is not None: self.size_limit = int(size_limit) if os.path.isfile(os.path.join(self.storedir, '_in_update', '_files')): print('resuming broken update...') @@ -2327,14 +2344,14 @@ rev: %s # should we remove this file from _in_update? if we don't # the user has no chance to continue without removing the file manually raise oscerr.PackageInternalError(self.prjname, self.name, - '\'%s\' is not known by meta but exists in \'_in_update\' dir') + '\'%s\' is not known by meta but exists in \'_in_update\' dir') elif os.path.isfile(wcfile) and dgst(wcfile) != origfile_md5: - (fd, tmpfile) = tempfile.mkstemp(dir=self.absdir, prefix=broken_file[0]+'.') + (fd, tmpfile) = tempfile.mkstemp(dir=self.absdir, prefix=broken_file[0] + '.') os.close(fd) os.rename(wcfile, tmpfile) os.rename(origfile, wcfile) - print('warning: it seems you modified \'%s\' after the broken ' \ - 'update. Restored original file and saved modified version ' \ + print('warning: it seems you modified \'%s\' after the broken ' + 'update. Restored original file and saved modified version ' 'to \'%s\'.' % (wcfile, tmpfile)) elif not os.path.isfile(wcfile): # this is strange... because it existed before the update. restore it @@ -2380,7 +2397,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) + 'failed to add file \'%s\' file/dir with the same name already exists' % f.name) # ok, the update can't fail due to existing files for f in added: self.updatefile(f.name, rev, f.mtime) @@ -2416,8 +2433,8 @@ rev: %s print('Restored \'%s\'' % 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) + 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) elif state == 'D' and self.findfilebyname(f.name).md5 != f.md5: # XXX: in the worst case we might end up with f.name being @@ -2441,8 +2458,8 @@ rev: %s # checkout service files for f in services: get_source_file(self.apiurl, self.prjname, self.name, f.name, - targetfilename=os.path.join(self.absdir, f.name), revision=rev, - progress_obj=self.progress_obj, mtime=f.mtime, meta=self.meta) + targetfilename=os.path.join(self.absdir, f.name), revision=rev, + progress_obj=self.progress_obj, mtime=f.mtime, meta=self.meta) print(statfrmt('A', os.path.join(pathn, f.name))) store_write_string(self.absdir, '_files', fm + '\n') if not self.meta: @@ -2455,7 +2472,7 @@ rev: %s if self.name.startswith("_"): return 0 curdir = os.getcwd() - os.chdir(self.absdir) # e.g. /usr/lib/obs/service/verify_file fails if not inside the project dir. + os.chdir(self.absdir) # e.g. /usr/lib/obs/service/verify_file fails if not inside the project dir. si = Serviceinfo() if os.path.exists('_service'): if self.filenamelist.count('_service') or self.filenamelist_unvers.count('_service'): @@ -2472,7 +2489,7 @@ rev: %s return r def revert(self, filename): - if not filename in self.filenamelist and not filename in self.to_be_added: + 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) elif filename in self.skipped: raise oscerr.OscIOError(None, 'file \'%s\' is marked as skipped and cannot be reverted' % filename) @@ -2521,6 +2538,7 @@ class AbstractState: """ Base class which represents state-like objects (````, ````). """ + def __init__(self, tag): self.__tag = tag @@ -2545,7 +2563,7 @@ class AbstractState: root = ET.Element(self.get_node_name()) for attr in self.get_node_attrs(): val = getattr(self, attr) - if not val is None: + if val is not None: root.set(attr, val) if self.get_description(): ET.SubElement(root, 'description').text = self.get_description() @@ -2562,11 +2580,12 @@ class AbstractState: class ReviewState(AbstractState): """Represents the review state in a request""" + def __init__(self, review_node): if not review_node.get('state'): - raise oscerr.APIError('invalid review node (state attr expected): %s' % \ - ET.tostring(review_node, encoding=ET_ENCODING)) - AbstractState.__init__(self, review_node.tag) + raise oscerr.APIError('invalid review node (state attr expected): %s' % + ET.tostring(review_node, encoding=ET_ENCODING)) + super().__init__(review_node.tag) self.state = review_node.get('state') self.by_user = review_node.get('by_user') self.by_group = review_node.get('by_group') @@ -2576,7 +2595,7 @@ class ReviewState(AbstractState): self.when = review_node.get('when') self.comment = '' if not review_node.find('comment') is None and \ - review_node.find('comment').text: + review_node.find('comment').text: self.comment = review_node.find('comment').text.strip() def get_node_attrs(self): @@ -2594,11 +2613,11 @@ class RequestHistory(AbstractState): re_name = re.compile(r'^Request (?:got )?([^\s]+)$') def __init__(self, history_node): - AbstractState.__init__(self, history_node.tag) + super().__init__(history_node.tag) self.who = history_node.get('who') self.when = history_node.get('when') if not history_node.find('description') is None and \ - history_node.find('description').text: + history_node.find('description').text: # OBS 2.6 self.description = history_node.find('description').text.strip() else: @@ -2606,7 +2625,7 @@ class RequestHistory(AbstractState): self.description = history_node.get('name') self.comment = '' if not history_node.find('comment') is None and \ - history_node.find('comment').text: + history_node.find('comment').text: self.comment = history_node.find('comment').text.strip() self.name = self._parse_name(history_node) @@ -2632,11 +2651,12 @@ class RequestHistory(AbstractState): class RequestState(AbstractState): """Represents the state of a request""" + def __init__(self, state_node): if not state_node.get('name'): - raise oscerr.APIError('invalid request state node (name attr expected): %s' % \ - ET.tostring(state_node, encoding=ET_ENCODING)) - AbstractState.__init__(self, state_node.tag) + raise oscerr.APIError('invalid request state node (name attr expected): %s' % + ET.tostring(state_node, encoding=ET_ENCODING)) + super().__init__(state_node.tag) self.name = state_node.get('name') self.who = state_node.get('who') self.when = state_node.get('when') @@ -2646,7 +2666,7 @@ class RequestState(AbstractState): self.description = state_node.get('description') self.comment = '' if not state_node.find('comment') is None and \ - state_node.find('comment').text: + state_node.find('comment').text: self.comment = state_node.find('comment').text.strip() def get_node_attrs(self): @@ -2671,7 +2691,7 @@ class Action: Examples:: r = Action('set_bugowner', tgt_project='foo', person_name='buguser') - # available attributes: r.type (== 'set_bugowner'), r.tgt_project (== 'foo'), r.tgt_package (== None) + # available attributes: r.type (== 'set_bugowner'), r.tgt_project (== 'foo'), r.tgt_package (is None) r.to_str() -> @@ -2690,29 +2710,29 @@ class Action: type_args = {'submit': ('src_project', 'src_package', 'src_rev', 'tgt_project', 'tgt_package', 'opt_sourceupdate', 'acceptinfo_rev', 'acceptinfo_srcmd5', 'acceptinfo_xsrcmd5', 'acceptinfo_osrcmd5', 'acceptinfo_oxsrcmd5', 'opt_updatelink', 'opt_makeoriginolder'), - 'add_role': ('tgt_project', 'tgt_package', 'person_name', 'person_role', 'group_name', 'group_role'), - 'set_bugowner': ('tgt_project', 'tgt_package', 'person_name', 'group_name'), - 'maintenance_release': ('src_project', 'src_package', 'src_rev', 'tgt_project', 'tgt_package', 'person_name', - 'acceptinfo_rev', 'acceptinfo_srcmd5', 'acceptinfo_xsrcmd5', 'acceptinfo_osrcmd5', - 'acceptinfo_oxsrcmd5', 'acceptinfo_oproject', 'acceptinfo_opackage'), - 'release': ('src_project', 'src_package', 'src_rev', 'tgt_project', 'tgt_package', 'person_name', - 'acceptinfo_rev', 'acceptinfo_srcmd5', 'acceptinfo_xsrcmd5', 'acceptinfo_osrcmd5', - 'acceptinfo_oxsrcmd5', 'acceptinfo_oproject', 'acceptinfo_opackage', 'tgt_repository'), - 'maintenance_incident': ('src_project', 'src_package', 'src_rev', 'tgt_project', 'tgt_package', 'tgt_releaseproject', 'person_name', 'opt_sourceupdate', 'opt_makeoriginolder', - 'acceptinfo_rev', 'acceptinfo_srcmd5', 'acceptinfo_xsrcmd5', 'acceptinfo_osrcmd5', - 'acceptinfo_oxsrcmd5'), - 'delete': ('tgt_project', 'tgt_package', 'tgt_repository'), - 'change_devel': ('src_project', 'src_package', 'tgt_project', 'tgt_package'), - 'group': ('grouped_id', )} + 'add_role': ('tgt_project', 'tgt_package', 'person_name', 'person_role', 'group_name', 'group_role'), + 'set_bugowner': ('tgt_project', 'tgt_package', 'person_name', 'group_name'), + 'maintenance_release': ('src_project', 'src_package', 'src_rev', 'tgt_project', 'tgt_package', 'person_name', + 'acceptinfo_rev', 'acceptinfo_srcmd5', 'acceptinfo_xsrcmd5', 'acceptinfo_osrcmd5', + 'acceptinfo_oxsrcmd5', 'acceptinfo_oproject', 'acceptinfo_opackage'), + 'release': ('src_project', 'src_package', 'src_rev', 'tgt_project', 'tgt_package', 'person_name', + 'acceptinfo_rev', 'acceptinfo_srcmd5', 'acceptinfo_xsrcmd5', 'acceptinfo_osrcmd5', + 'acceptinfo_oxsrcmd5', 'acceptinfo_oproject', 'acceptinfo_opackage', 'tgt_repository'), + 'maintenance_incident': ('src_project', 'src_package', 'src_rev', 'tgt_project', 'tgt_package', 'tgt_releaseproject', 'person_name', 'opt_sourceupdate', 'opt_makeoriginolder', + 'acceptinfo_rev', 'acceptinfo_srcmd5', 'acceptinfo_xsrcmd5', 'acceptinfo_osrcmd5', + 'acceptinfo_oxsrcmd5'), + 'delete': ('tgt_project', 'tgt_package', 'tgt_repository'), + 'change_devel': ('src_project', 'src_package', 'tgt_project', 'tgt_package'), + 'group': ('grouped_id', )} # attribute prefix to element name map (only needed for abbreviated attributes) prefix_to_elm = {'src': 'source', 'tgt': 'target', 'opt': 'options'} def __init__(self, type, **kwargs): - if not type in Action.type_args.keys(): + if type not in Action.type_args.keys(): raise oscerr.WrongArgs('invalid action type: \'%s\'' % type) self.type = type for i in kwargs.keys(): - if not i in Action.type_args[type]: + if i not in Action.type_args[type]: raise oscerr.WrongArgs('invalid argument: \'%s\'' % i) # set all type specific attributes for i in Action.type_args[type]: @@ -2767,8 +2787,8 @@ class Action: def from_xml(action_node): """create action from XML""" if action_node is None or \ - not action_node.get('type') in Action.type_args.keys() or \ - not action_node.tag in ('action', 'submit'): + action_node.get('type') not in Action.type_args.keys() or \ + action_node.tag not in ('action', 'submit'): raise oscerr.WrongArgs('invalid argument') elm_to_prefix = {i[1]: i[0] for i in Action.prefix_to_elm.items()} kwargs = {} @@ -2866,7 +2886,7 @@ class Request: root.set('creator', self.creator) for action in self.actions: root.append(action.to_xml()) - if not self.state is None: + if self.state is not None: root.append(self.state.to_xml()) for review in self.reviews: root.append(review.to_xml()) @@ -2890,8 +2910,6 @@ class Request: def accept_at_in_hours(self, hours): """set auto accept_at time""" - import datetime - now = datetime.datetime.utcnow() now = now + datetime.timedelta(hours=hours) self.accept_at = now.isoformat() + '+00:00' @@ -3002,7 +3020,6 @@ class Request: def list_view(self): """return "list view" format""" - import textwrap status = self.state.name if self.state.name == 'review' and self.state.approver: status += "(approved)" @@ -3018,21 +3035,21 @@ class Request: lines.append(' From: %s' % ' -> '.join(history)) if self.description: lines.append(textwrap.fill(self.description, width=80, initial_indent=' Descr: ', - subsequent_indent=' ')) + subsequent_indent=' ')) lines.append(textwrap.fill(self.state.comment, width=80, initial_indent=' Comment: ', - subsequent_indent=' ')) + subsequent_indent=' ')) return '\n'.join(lines) def __str__(self): """return "detailed" format""" lines = ['Request: #%s\n' % self.reqid] - if self.accept_at and self.state.name in [ 'new', 'review' ]: - lines.append(' *** This request will get automatically accepted after '+self.accept_at+' ! ***\n') - if self.priority in [ 'critical', 'important' ] and self.state.name in [ 'new', 'review' ]: - lines.append(' *** This request has classified as '+self.priority+' ! ***\n') + if self.accept_at and self.state.name in ['new', 'review']: + lines.append(' *** This request will get automatically accepted after ' + self.accept_at + ' ! ***\n') + if self.priority in ['critical', 'important'] and self.state.name in ['new', 'review']: + lines.append(' *** This request has classified as ' + self.priority + ' ! ***\n') if self.state and self.state.approver and self.state.name == 'review': - lines.append(' *** This request got approved by '+self.state.approver+'. It will get automatically accepted after last review got accepted! ***\n') - + lines.append(' *** This request got approved by ' + self.state.approver + '. It will get automatically accepted after last review got accepted! ***\n') + for action in self.actions: tmpl = ' %(type)-13s %(source)s %(target)s' if action.type == 'delete': @@ -3085,7 +3102,7 @@ class Request: def create(self, apiurl, addrevision=False, enforce_branching=False): """create a new request""" - query = {'cmd' : 'create' } + query = {'cmd': 'create'} if addrevision: query['addrevision'] = "1" if enforce_branching: @@ -3095,13 +3112,12 @@ class Request: root = ET.fromstring(f.read()) self.read(root) + def shorttime(t): """format time as Apr 02 18:19 or Apr 02 2005 depending on whether it is in the current year """ - import time - if time.gmtime()[0] == time.gmtime(t)[0]: # same year return time.strftime('%b %d %H:%M', time.gmtime(t)) @@ -3113,14 +3129,15 @@ def is_project_dir(d): global store return os.path.exists(os.path.join(d, store, '_project')) and not \ - os.path.exists(os.path.join(d, store, '_package')) + os.path.exists(os.path.join(d, store, '_package')) def is_package_dir(d): global store return os.path.exists(os.path.join(d, store, '_project')) and \ - os.path.exists(os.path.join(d, store, '_package')) + os.path.exists(os.path.join(d, store, '_package')) + def parse_disturl(disturl): """Parse a disturl, returns tuple (apiurl, project, source, repository, @@ -3138,6 +3155,7 @@ def parse_disturl(disturl): apiurl = 'https://api.' + ".".join(apiurl.split('.')[1:]) return (apiurl, m.group('project'), m.group('source'), m.group('repository'), m.group('revision')) + def parse_buildlogurl(buildlogurl): """Parse a build log url, returns a tuple (apiurl, project, package, repository, arch), else raises oscerr.WrongArgs exception""" @@ -3150,6 +3168,7 @@ def parse_buildlogurl(buildlogurl): return (m.group('apiurl'), m.group('project'), m.group('package'), m.group('repository'), m.group('arch')) + def slash_split(l): """Split command line arguments like 'foo/bar' into 'foo' 'bar'. This is handy to allow copy/paste a project/package combination in this form. @@ -3163,6 +3182,7 @@ def slash_split(l): r += i.split('/') return r + def expand_proj_pack(args, idx=0, howmany=0): """looks for occurance of '.' at the position idx. If howmany is 2, both proj and pack are expanded together @@ -3186,27 +3206,27 @@ def expand_proj_pack(args, idx=0, howmany=0): if len(args) == idx: args += '.' - if args[idx+0] == '.': - if howmany == 0 and len(args) > idx+1: - if args[idx+1] == '.': + if args[idx + 0] == '.': + if howmany == 0 and len(args) > idx + 1: + if args[idx + 1] == '.': # we have two dots. # remove one dot and make sure to expand both proj and pack - args.pop(idx+1) + args.pop(idx + 1) howmany = 2 else: howmany = 1 # print args,idx,howmany - args[idx+0] = store_read_project('.') + args[idx + 0] = store_read_project('.') if howmany == 0: try: package = store_read_package('.') - args.insert(idx+1, package) + args.insert(idx + 1, package) except: pass elif howmany == 2: package = store_read_package('.') - args.insert(idx+1, package) + args.insert(idx + 1, package) return args @@ -3249,7 +3269,7 @@ def filedir_to_pac(f, progress_obj=None): else: wd = os.path.dirname(f) or os.curdir p = Package(wd, progress_obj=progress_obj) - p.todo = [ os.path.basename(f) ] + p.todo = [os.path.basename(f)] return p @@ -3271,6 +3291,7 @@ def read_filemeta(dir): raise oscerr.NoWorkingCopy('%s\nWhen parsing .osc/_files, the following error was encountered:\n%s' % (msg, e)) return r + def store_readlist(dir, name): global store @@ -3280,12 +3301,15 @@ def store_readlist(dir, name): r = [line.rstrip('\n') for line in f] return r + def read_tobeadded(dir): return store_readlist(dir, '_to_be_added') + def read_tobedeleted(dir): return store_readlist(dir, '_to_be_deleted') + def read_sizelimit(dir): global store @@ -3300,9 +3324,11 @@ def read_sizelimit(dir): return None return int(r) + def read_inconflict(dir): return store_readlist(dir, '_in_conflict') + def parseargs(list_of_args): """Convenience method osc's commandline argument parsing. @@ -3326,7 +3352,7 @@ def pathjoin(a, *p): return path -def makeurl(baseurl, l, query=[]): +def makeurl(baseurl, l, query=None): """Given a list of path compoments, construct a complete URL. Optional parameters for a query string can be given as a list, as a @@ -3334,13 +3360,13 @@ def makeurl(baseurl, l, query=[]): In case of a dictionary, the parameters will be urlencoded by this function. In case of a list not -- this is to be backwards compatible. """ - + query = query or [] if conf.config['debug']: print('makeurl:', baseurl, l, query) - if isinstance(query, type(list())): + if isinstance(query, list): query = '&'.join(query) - elif isinstance(query, type(dict())): + elif isinstance(query, dict): query = urlencode(query) scheme, netloc, path = urlsplit(baseurl)[0:3] @@ -3392,7 +3418,7 @@ def meta_get_packagelist(apiurl, prj, deleted=None, expand=False): u = makeurl(apiurl, ['source', prj], query) f = http_GET(u) root = ET.parse(f).getroot() - return [ node.get('name') for node in root.findall('entry') ] + return [node.get('name') for node in root.findall('entry')] def meta_get_filelist(apiurl, prj, package, verbose=False, expand=False, revision=None, meta=False, deleted=False): @@ -3416,7 +3442,7 @@ def meta_get_filelist(apiurl, prj, package, verbose=False, expand=False, revisio root = ET.parse(f).getroot() if not verbose: - return [ node.get('name') for node in root.findall('entry') ] + return [node.get('name') for node in root.findall('entry')] else: l = [] @@ -3440,7 +3466,7 @@ def meta_get_project_list(apiurl, deleted=None): u = makeurl(apiurl, ['source'], query) f = http_GET(u) root = ET.parse(f).getroot() - return sorted( node.get('name') for node in root if node.get('name')) + return sorted(node.get('name') for node in root if node.get('name')) def show_project_meta(apiurl, prj, rev=None, blame=None): @@ -3469,6 +3495,7 @@ def show_project_meta(apiurl, prj, rev=None, blame=None): f = http_GET(url) return f.readlines() + def show_project_conf(apiurl, prj, rev=None, blame=None): query = {} url = None @@ -3538,9 +3565,11 @@ def show_attribute_meta(apiurl, prj, pac, subpac, attribute, with_defaults, with def clean_assets(directory): return run_external(conf.config['download-assets-cmd'], '--clean', directory) + def download_assets(directory): return run_external(conf.config['download-assets-cmd'], '--unpack', '--noassetdir', directory) + def show_scmsync(apiurl, prj, pac=None): if pac: m = show_package_meta(apiurl, prj, pac) @@ -3552,6 +3581,7 @@ def show_scmsync(apiurl, prj, pac=None): else: return node.text + def show_devel_project(apiurl, prj, pac): m = show_package_meta(apiurl, prj, pac) node = ET.fromstring(b''.join(m)).find('devel') @@ -3586,7 +3616,7 @@ def set_devel_project(apiurl, prj, pac, devprj=None, devpac=None): def show_package_disabled_repos(apiurl, prj, pac): m = show_package_meta(apiurl, prj, pac) - #FIXME: don't work if all repos of a project are disabled and only some are enabled since is empty + # FIXME: don't work if all repos of a project are disabled and only some are enabled since is empty try: root = ET.fromstring(''.join(m)) elm = root.find('build') @@ -3609,7 +3639,7 @@ def show_pattern_metalist(apiurl, prj): except HTTPError as e: e.osc_msg = 'show_pattern_metalist: Error getting pattern list for project \'%s\'' % prj raise - r = sorted( node.get('name') for node in tree.getroot() ) + r = sorted(node.get('name') for node in tree.getroot()) return r @@ -3622,6 +3652,7 @@ def show_pattern_meta(apiurl, prj, pattern): e.osc_msg = 'show_pattern_meta: Error getting pattern \'%s\' for project \'%s\'' % (pattern, prj) raise + def show_configuration(apiurl): u = makeurl(apiurl, ['public', 'configuration']) f = http_GET(u) @@ -3644,8 +3675,6 @@ class metafile: return self._delegate(**kwargs) def __init__(self, url, input, change_is_required=False, file_ext='.xml'): - import tempfile - if isinstance(url, self._URLFactory): self._url_factory = url else: @@ -3654,7 +3683,7 @@ class metafile: self._url_factory = self._URLFactory(delegate, False) self.url = self._url_factory() self.change_is_required = change_is_required - (fd, self.filename) = tempfile.mkstemp(prefix = 'osc_metafile.', suffix = file_ext) + (fd, self.filename) = tempfile.mkstemp(prefix='osc_metafile.', suffix=file_ext) open_mode = 'w' input_as_str = None @@ -3727,36 +3756,38 @@ class metafile: print('discarding %s' % self.filename) os.unlink(self.filename) + # different types of metadata -metatypes = { 'prj': { 'path': 'source/%s/_meta', - 'template': new_project_templ, - 'file_ext': '.xml' - }, - 'pkg': { 'path' : 'source/%s/%s/_meta', - 'template': new_package_templ, - 'file_ext': '.xml' - }, - 'attribute': { 'path' : 'source/%s/%s/_meta', +metatypes = {'prj': {'path': 'source/%s/_meta', + 'template': new_project_templ, + 'file_ext': '.xml' + }, + 'pkg': {'path': 'source/%s/%s/_meta', + 'template': new_package_templ, + 'file_ext': '.xml' + }, + 'attribute': {'path': 'source/%s/%s/_meta', 'template': new_attribute_templ, 'file_ext': '.xml' + }, + 'prjconf': {'path': 'source/%s/_config', + 'template': '', + 'file_ext': '.txt' }, - 'prjconf': { 'path': 'source/%s/_config', - 'template': '', - 'file_ext': '.txt' + 'user': {'path': 'person/%s', + 'template': new_user_template, + 'file_ext': '.xml' + }, + 'group': {'path': 'group/%s', + 'template': new_group_template, + 'file_ext': '.xml' + }, + 'pattern': {'path': 'source/%s/_pattern/%s', + 'template': new_pattern_template, + 'file_ext': '.xml' }, - 'user': { 'path': 'person/%s', - 'template': new_user_template, - 'file_ext': '.xml' - }, - 'group': { 'path': 'group/%s', - 'template': new_group_template, - 'file_ext': '.xml' - }, - 'pattern': { 'path': 'source/%s/_pattern/%s', - 'template': new_pattern_template, - 'file_ext': '.xml' - }, - } + } + def meta_exists(metatype, path_args=None, @@ -3781,6 +3812,7 @@ def meta_exists(metatype, return data + def make_meta_url(metatype, path_args=None, apiurl=None, force=False, remove_linking_repositories=False, msg=None): global metatypes @@ -3795,7 +3827,7 @@ def make_meta_url(metatype, path_args=None, apiurl=None, force=False, remove_lin query = {} if force: - query = { 'force': '1' } + query = {'force': '1'} if remove_linking_repositories: query['remove_linking_repositories'] = '1' if msg: @@ -3803,6 +3835,7 @@ def make_meta_url(metatype, path_args=None, apiurl=None, force=False, remove_lin return makeurl(apiurl, [path], query) + def parse_meta_to_string(data): """ Converts the output of meta_exists into a string value @@ -3835,7 +3868,7 @@ def edit_meta(metatype, data = meta_exists(metatype, path_args, template_args, - create_new = metatype != 'prjconf', # prjconf always exists, 404 => unknown prj + create_new=metatype != 'prjconf', # prjconf always exists, 404 => unknown prj apiurl=apiurl) if edit: @@ -3853,10 +3886,9 @@ def edit_meta(metatype, print(' osc meta pkg %s %s -e' % (unquote(project), package)) return - delegate = lambda force=force: make_meta_url(metatype, path_args, apiurl, - force, - remove_linking_repositories, - msg) + def delegate(force=force): + return make_meta_url(metatype, path_args, apiurl, force, remove_linking_repositories, msg) + url_factory = metafile._URLFactory(delegate) f = metafile(url_factory, data, change_is_required, metatypes[metatype]['file_ext']) @@ -3887,13 +3919,14 @@ def show_files_meta(apiurl, prj, pac, revision=None, expand=False, linkrev=None, f = http_GET(makeurl(apiurl, ['source', prj, pac], query=query)) return f.read() + def show_upstream_srcmd5(apiurl, prj, pac, expand=False, revision=None, meta=False, include_service_files=False, deleted=False): m = show_files_meta(apiurl, prj, pac, expand=expand, revision=revision, meta=meta, deleted=deleted) et = ET.fromstring(m) if include_service_files: try: sinfo = et.find('serviceinfo') - if sinfo != None and sinfo.get('xsrcmd5') and not sinfo.get('error'): + if sinfo is not None and sinfo.get('xsrcmd5') and not sinfo.get('error'): return sinfo.get('xsrcmd5') except: pass @@ -3959,13 +3992,14 @@ def show_upstream_rev_vrev(apiurl, prj, pac, revision=None, expand=False, meta=F et = ET.fromstring(m) return et.get('rev'), et.get('vrev') + def show_upstream_rev(apiurl, prj, pac, revision=None, expand=False, linkrev=None, meta=False, include_service_files=False): m = show_files_meta(apiurl, prj, pac, revision=revision, expand=expand, linkrev=linkrev, meta=meta) et = ET.fromstring(m) if include_service_files: try: sinfo = et.find('serviceinfo') - if sinfo != None and sinfo.get('xsrcmd5') and not sinfo.get('error'): + if sinfo is not None and sinfo.get('xsrcmd5') and not sinfo.get('error'): return sinfo.get('xsrcmd5') except: pass @@ -3973,7 +4007,6 @@ def show_upstream_rev(apiurl, prj, pac, revision=None, expand=False, linkrev=Non def read_meta_from_spec(specfile, *args): - import codecs, re """ Read tags and sections from spec file. To read out a tag the passed argument mustn't end with a colon. To @@ -4011,7 +4044,7 @@ def read_meta_from_spec(specfile, *args): for section in sections: m = re.compile(section_pat % section, re.I | re.M).search(''.join(lines)) if m: - start = lines.index(m.group()+'\n') + 1 + start = lines.index(m.group() + '\n') + 1 data = [] for line in lines[start:]: if line.startswith('%'): @@ -4021,6 +4054,7 @@ def read_meta_from_spec(specfile, *args): return spec_data + def _get_linux_distro(): if distro is not None: return distro.id() @@ -4029,6 +4063,7 @@ def _get_linux_distro(): # compatibility for Python 2.6 to 3.7 return platform.linux_distribution()[0] + def get_default_editor(): system = platform.system() if system == 'Linux': @@ -4040,6 +4075,7 @@ def get_default_editor(): return 'vim' return 'vi' + def get_default_pager(): system = platform.system() if system == 'Linux': @@ -4049,9 +4085,8 @@ def get_default_pager(): return 'less' return 'more' -def run_pager(message, tmp_suffix=''): - import tempfile, sys +def run_pager(message, tmp_suffix=''): if not message: return @@ -4074,11 +4109,13 @@ def run_pager(message, tmp_suffix=''): finally: tmpfile.close() + def run_editor(filename): cmd = _editor_command() cmd.append(filename) return run_external(cmd[0], *cmd[1:]) + def _editor_command(): editor = os.getenv('EDITOR', default=get_default_editor()) try: @@ -4087,9 +4124,8 @@ def _editor_command(): cmd = editor.split() return cmd + def _edit_message_open_editor(filename, data, orig_mtime): - # FIXME: import modules globally - import tempfile editor = _editor_command() mtime = os.stat(filename).st_mtime if isinstance(data, str): @@ -4111,11 +4147,12 @@ def _edit_message_open_editor(filename, data, orig_mtime): run_editor(filename) return os.stat(filename).st_mtime != orig_mtime + def edit_message(footer='', template='', templatelen=30): delim = '--This line, and those below, will be ignored--\n' data = '' if template != '': - if not templatelen is None: + if templatelen is not None: lines = template.splitlines() data = '\n'.join(lines[:templatelen]) if lines[templatelen:]: @@ -4123,8 +4160,8 @@ def edit_message(footer='', template='', templatelen=30): data += '\n' + delim + '\n' + footer return edit_text(data, delim, suffix='.diff', template=template) + def edit_text(data='', delim=None, suffix='.txt', template=''): - import tempfile try: (fd, filename) = tempfile.mkstemp(prefix='osc-editor', suffix=suffix) os.close(fd) @@ -4156,6 +4193,7 @@ def edit_text(data='', delim=None, suffix='.txt', template=''): os.unlink(filename) return msg + def clone_request(apiurl, reqid, msg=None): query = {'cmd': 'branch', 'request': reqid} url = makeurl(apiurl, ['source'], query) @@ -4170,6 +4208,8 @@ def clone_request(apiurl, reqid, msg=None): return project # create a maintenance release request + + def create_release_request(apiurl, src_project, message=''): r = Request() # api will complete the request @@ -4179,21 +4219,24 @@ def create_release_request(apiurl, src_project, message=''): return r # create a maintenance incident per request + + def create_maintenance_request(apiurl, src_project, src_packages, tgt_project, tgt_releaseproject, opt_sourceupdate, message='', enforce_branching=False, rev=None): r = Request() if src_packages: for p in src_packages: - r.add_action('maintenance_incident', src_project=src_project, src_package=p, src_rev=rev, tgt_project=tgt_project, tgt_releaseproject=tgt_releaseproject, opt_sourceupdate = opt_sourceupdate) + r.add_action('maintenance_incident', src_project=src_project, src_package=p, src_rev=rev, tgt_project=tgt_project, tgt_releaseproject=tgt_releaseproject, opt_sourceupdate=opt_sourceupdate) else: - r.add_action('maintenance_incident', src_project=src_project, tgt_project=tgt_project, tgt_releaseproject=tgt_releaseproject, opt_sourceupdate = opt_sourceupdate) + r.add_action('maintenance_incident', src_project=src_project, tgt_project=tgt_project, tgt_releaseproject=tgt_releaseproject, opt_sourceupdate=opt_sourceupdate) r.description = message r.create(apiurl, addrevision=True, enforce_branching=enforce_branching) return r + def create_submit_request(apiurl, - src_project, src_package=None, - dst_project=None, dst_package=None, - message="", orev=None, src_update=None, dst_updatelink=None): + src_project, src_package=None, + dst_project=None, dst_package=None, + message="", orev=None, src_update=None, dst_updatelink=None): options_block = "" package = "" if src_package: @@ -4205,14 +4248,13 @@ def create_submit_request(apiurl, options_block += """true""" options_block += "" - # Yes, this kind of xml construction is horrible targetxml = "" if dst_project: packagexml = "" if dst_package: - packagexml = """package="%s" """ % ( dst_package ) - targetxml = """ """ % ( dst_project, packagexml ) + packagexml = """package="%s" """ % (dst_package) + targetxml = """ """ % (dst_project, packagexml) # XXX: keep the old template for now in order to work with old obs instances xml = """\ @@ -4274,7 +4316,7 @@ def get_request(apiurl, reqid): def change_review_state(apiurl, reqid, newstate, by_user='', by_group='', by_project='', by_package='', message='', supersed=None): - query = {'cmd': 'changereviewstate', 'newstate': newstate } + query = {'cmd': 'changereviewstate', 'newstate': newstate} if by_user: query['by_user'] = by_user if by_group: @@ -4290,8 +4332,9 @@ def change_review_state(apiurl, reqid, newstate, by_user='', by_group='', by_pro root = ET.parse(f).getroot() return root.get('code') + def change_request_state(apiurl, reqid, newstate, message='', supersed=None, force=False): - query = {'cmd': 'changestate', 'newstate': newstate } + query = {'cmd': 'changestate', 'newstate': newstate} if supersed: query['superseded_by'] = supersed if force: @@ -4303,8 +4346,9 @@ def change_request_state(apiurl, reqid, newstate, message='', supersed=None, for root = ET.parse(f).getroot() return root.get('code', 'unknown') + def change_request_state_template(req, newstate): - if not len(req.actions): + if not req.actions: return '' action = req.actions[0] tmpl_name = '%srequest_%s_template' % (action.type, newstate) @@ -4313,15 +4357,16 @@ def change_request_state_template(req, newstate): data = {'reqid': req.reqid, 'type': action.type, 'who': req.creator} if req.actions[0].type == 'submit': data.update({'src_project': action.src_project, - 'src_package': action.src_package, 'src_rev': action.src_rev, - 'dst_project': action.tgt_project, 'dst_package': action.tgt_package, - 'tgt_project': action.tgt_project, 'tgt_package': action.tgt_package}) + 'src_package': action.src_package, 'src_rev': action.src_rev, + 'dst_project': action.tgt_project, 'dst_package': action.tgt_package, + 'tgt_project': action.tgt_project, 'tgt_package': action.tgt_package}) try: return tmpl % data except KeyError as e: print('error: cannot interpolate \'%s\' in \'%s\'' % (e.args[0], tmpl_name), file=sys.stderr) return '' + def get_review_list(apiurl, project='', package='', byuser='', bygroup='', byproject='', bypackage='', states=(), req_type=''): # this is so ugly... @@ -4382,6 +4427,8 @@ def get_review_list(apiurl, project='', package='', byuser='', bygroup='', bypro return requests # this function uses the logic in the api which is faster and more exact then the xpath search + + def get_request_collection(apiurl, role=None, req_who=None, req_states=('new', 'review', 'declined')): query = {"view": "collection"} @@ -4403,9 +4450,10 @@ def get_request_collection(apiurl, role=None, req_who=None, req_states=('new', ' requests.append(r) return requests + def get_exact_request_list(apiurl, src_project, dst_project, src_package=None, dst_package=None, req_who=None, req_state=('new', 'review', 'declined'), req_type=None): xpath = '' - if not 'all' in req_state: + 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 @@ -4434,10 +4482,12 @@ def get_exact_request_list(apiurl, src_project, dst_project, src_package=None, d requests.append(r) return requests -def get_request_list(apiurl, project='', package='', req_who='', req_state=('new', 'review', 'declined'), req_type=None, exclude_target_projects=[], + +def get_request_list(apiurl, project='', package='', req_who='', req_state=('new', 'review', 'declined'), req_type=None, exclude_target_projects=None, withfullhistory=False): + exclude_target_projects = exclude_target_projects or [] xpath = '' - if not 'all' in req_state: + if 'all' not in req_state: for state in req_state: xpath = xpath_join(xpath, 'state/@name=\'%s\'' % state, inner=True) if req_who: @@ -4476,9 +4526,13 @@ def get_request_list(apiurl, project='', package='', req_who='', req_state=('new return requests # old style search, this is to be removed -def get_user_projpkgs_request_list(apiurl, user, req_state=('new', 'review', ), req_type=None, exclude_projects=[], projpkgs={}): + + +def get_user_projpkgs_request_list(apiurl, user, req_state=('new', 'review', ), req_type=None, exclude_projects=None, projpkgs=None): """OBSOLETE: user involved request search is supported by OBS 2.2 server side in a better way Return all running requests for all projects/packages where is user is involved""" + exclude_projects = exclude_projects or [] + projpkgs = projpkgs or {} if not projpkgs: res = get_user_projpkgs(apiurl, user, exclude_projects=exclude_projects) projects = [] @@ -4492,7 +4546,7 @@ def get_user_projpkgs_request_list(apiurl, user, req_state=('new', 'review', ), return [] xpath = '' for prj, pacs in projpkgs.items(): - if not len(pacs): + if not pacs: xpath = xpath_join(xpath, 'action/target/@project=\'%s\'' % prj, inner=True) else: xp = '' @@ -4502,7 +4556,7 @@ def get_user_projpkgs_request_list(apiurl, user, req_state=('new', 'review', ), xpath = xpath_join(xpath, xp, inner=True) if req_type: xpath = xpath_join(xpath, 'action/@type=\'%s\'' % req_type, op='and') - if not 'all' in req_state: + if 'all' not in req_state: xp = '' for state in req_state: xp = xpath_join(xp, 'state/@name=\'%s\'' % state, inner=True) @@ -4515,6 +4569,7 @@ def get_user_projpkgs_request_list(apiurl, user, req_state=('new', 'review', ), result.append(r) return result + def get_request_log(apiurl, reqid): r = get_request(apiurl, reqid) data = [] @@ -4526,11 +4581,12 @@ def get_request_log(apiurl, reqid): r.statehistory[-1].comment = r.description else: r.state.comment = r.description - for state in [ r.state ] + r.statehistory: + for state in [r.state] + r.statehistory: s = frmt % (state.name, state.who, state.when, str(state.comment)) data.append(s) return data + def check_existing_requests(apiurl, src_project, src_package, dst_project, dst_package, ask=True): reqs = get_exact_request_list(apiurl, src_project, dst_project, @@ -4546,7 +4602,7 @@ def check_existing_requests(apiurl, src_project, src_package, dst_project, if len(reqs) > 1: open_request_string = "The following submit requests are already open:" supersede_request_string = "Supersede the old requests?" - print('%s %s.' % \ + print('%s %s.' % (open_request_string, ', '.join([i.reqid for i in reqs]))) repl = raw_input('%s (y/n/c) ' % supersede_request_string) while repl.lower() not in ['c', 'y', 'n']: @@ -4557,6 +4613,7 @@ def check_existing_requests(apiurl, src_project, src_package, dst_project, raise oscerr.UserAbort() return repl == 'y', reqs + def check_existing_maintenance_requests(apiurl, src_project, src_packages, dst_project, release_project, ask=True): reqs = [] @@ -4574,7 +4631,7 @@ def check_existing_maintenance_requests(apiurl, src_project, src_packages, dst_p 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.' % \ + print('%s %s.' % (open_request_string, ', '.join([i.reqid for i in reqs]))) repl = raw_input('%s (y/n/c) ' % supersede_request_string) while repl.lower() not in ['c', 'y', 'n']: @@ -4587,9 +4644,12 @@ def check_existing_maintenance_requests(apiurl, src_project, src_packages, dst_p # old function for compat reasons. Some plugins may call this function. # and we do not want to break the plugins. + + def get_group(apiurl, group): return get_group_meta(apiurl, group) + def get_group_meta(apiurl, group): u = makeurl(apiurl, ['group', quote_plus(group)]) try: @@ -4599,6 +4659,7 @@ def get_group_meta(apiurl, group): print('group \'%s\' not found' % group) return None + def get_user_meta(apiurl, user): u = makeurl(apiurl, ['person', quote_plus(user)]) try: @@ -4608,9 +4669,10 @@ def get_user_meta(apiurl, user): print('user \'%s\' not found' % user) return None + def _get_xml_data(meta, *tags): data = [] - if meta != None: + if meta is not None: root = ET.fromstring(meta) for tag in tags: elm = root.find(tag) @@ -4625,22 +4687,21 @@ def get_user_data(apiurl, user, *tags): """get specified tags from the user meta""" meta = get_user_meta(apiurl, user) return _get_xml_data(meta, *tags) - + def get_group_data(apiurl, group, *tags): meta = get_group_meta(apiurl, group) return _get_xml_data(meta, *tags) -def download(url, filename, progress_obj = None, mtime = None): - import tempfile, shutil +def download(url, filename, progress_obj=None, mtime=None): global BUFSIZE o = None try: prefix = os.path.basename(filename) path = os.path.dirname(filename) - (fd, tmpfile) = tempfile.mkstemp(dir=path, prefix = prefix, suffix = '.osctmp') + (fd, tmpfile) = tempfile.mkstemp(dir=path, prefix=prefix, suffix='.osctmp') os.fchmod(fd, 0o644) try: o = os.fdopen(fd, 'wb') @@ -4661,6 +4722,7 @@ def download(url, filename, progress_obj = None, mtime = None): if mtime: utime(filename, (-1, mtime)) + def get_source_file(apiurl, prj, package, filename, targetfilename=None, revision=None, progress_obj=None, mtime=None, meta=False): targetfilename = targetfilename or filename query = {} @@ -4671,16 +4733,16 @@ def get_source_file(apiurl, prj, package, filename, targetfilename=None, revisio u = makeurl(apiurl, ['source', prj, package, pathname2url(filename.encode(locale.getpreferredencoding(), 'replace'))], query=query) download(u, targetfilename, progress_obj, mtime) + def get_binary_file(apiurl, prj, repo, arch, filename, - package = None, - target_filename = None, - target_mtime = None, - progress_meter = False): + package=None, + target_filename=None, + target_mtime=None, + progress_meter=False): progress_obj = None if progress_meter: - from .meter import create_text_meter - progress_obj = create_text_meter() + progress_obj = meter.create_text_meter() target_filename = target_filename or filename @@ -4699,28 +4761,24 @@ def get_binary_file(apiurl, prj, repo, arch, if target_filename.endswith('.AppImage'): os.chmod(target_filename, 0o755) + def dgst(file): - #if not os.path.exists(file): - #return None + # if not os.path.exists(file): + # return None global BUFSIZE - - try: - import hashlib - md5 = hashlib - except ImportError: - import md5 - md5 = md5 - s = md5.md5() + s = hashlib.md5() f = open(file, 'rb') while True: buf = f.read(BUFSIZE) - if not buf: break + if not buf: + break s.update(buf) f.close() return s.hexdigest() + def sha256_dgst(file): global BUFSIZE @@ -4729,11 +4787,13 @@ def sha256_dgst(file): s = hashlib.sha256() while True: buf = f.read(BUFSIZE) - if not buf: break + if not buf: + break s.update(buf) f.close() return s.hexdigest() + def binary(s): """return ``True`` if a string is binary data using diff's heuristic""" if s and bytes('\0', "utf-8") in s[:4096]: @@ -4747,16 +4807,13 @@ def binary_file(fn): return binary(f.read(4096)) -def get_source_file_diff(dir, filename, rev, oldfilename = None, olddir = None, origfilename = None): +def get_source_file_diff(dir, filename, rev, oldfilename=None, olddir=None, origfilename=None): """ This methods diffs oldfilename against filename (so filename will be shown as the new file). The variable origfilename is used if filename and oldfilename differ in their names (for instance if a tempfile is used for filename etc.) """ - - import difflib - global store if not oldfilename: @@ -4787,13 +4844,13 @@ def get_source_file_diff(dir, filename, rev, oldfilename = None, olddir = None, f1.close() if f2: f2.close() - + from_file = b'%s\t(revision %s)' % (origfilename.encode(), str(rev).encode()) to_file = b'%s\t(working copy)' % origfilename.encode() - d = difflib.diff_bytes(difflib.unified_diff, s1, s2, \ - fromfile = from_file, \ - tofile = to_file) + d = difflib.diff_bytes(difflib.unified_diff, s1, s2, + fromfile=from_file, + tofile=to_file) d = list(d) # python2.7's difflib slightly changed the format # adapt old format to the new format @@ -4805,10 +4862,11 @@ def get_source_file_diff(dir, filename, rev, oldfilename = None, olddir = None, for i, line in enumerate(d): if not line.endswith(b'\n'): d[i] += b'\n\\ No newline at end of file' - if i+1 != len(d): + if i + 1 != len(d): d[i] += b'\n' return d + def server_diff(apiurl, old_project, old_package, old_revision, new_project, new_package, new_revision, @@ -4859,21 +4917,22 @@ def server_diff(apiurl, return string return f.read() + def server_diff_noex(apiurl, - old_project, old_package, old_revision, - new_project, new_package, new_revision, - unified=False, missingok=False, meta=False, expand=True, onlyissues=False, xml=False): + old_project, old_package, old_revision, + new_project, new_package, new_revision, + unified=False, missingok=False, meta=False, expand=True, onlyissues=False, xml=False): try: return server_diff(apiurl, - old_project, old_package, old_revision, - new_project, new_package, new_revision, - unified, missingok, meta, expand, onlyissues, True, xml) + old_project, old_package, old_revision, + new_project, new_package, new_revision, + unified, missingok, meta, expand, onlyissues, True, xml) except HTTPError as e: msg = None body = None try: body = e.read() - if not b'bad link' in body: + if b'bad link' not in body: return b'# diff failed: ' + body except: return b'# diff failed with unknown error' @@ -4882,13 +4941,13 @@ def server_diff_noex(apiurl, rdiff = b"## diff on expanded link not possible, showing unexpanded version\n" try: rdiff += server_diff_noex(apiurl, - old_project, old_package, old_revision, - new_project, new_package, new_revision, - unified, missingok, meta, False) + old_project, old_package, old_revision, + new_project, new_package, new_revision, + unified, missingok, meta, False) except: elm = ET.fromstring(body).find('summary') summary = '' - if not elm is None: + if elm is not None: summary = elm.text return b'error: diffing failed: %s' % summary.encode() return rdiff @@ -4903,20 +4962,21 @@ def request_diff(apiurl, reqid, superseded_reqid=None): f = http_POST(u) return f.read() + def get_request_issues(apiurl, reqid): """ gets a request xml with the issues for the request inside and creates a list 'issue_list' with a dict of the relevant information for the issues. This only works with bugtrackers we can access, like buzilla.o.o """ - u = makeurl(apiurl, ['request', reqid], query={'cmd': 'diff', 'view': 'xml', 'withissues': '1'} ) + u = makeurl(apiurl, ['request', reqid], query={'cmd': 'diff', 'view': 'xml', 'withissues': '1'}) f = http_POST(u) request_tree = ET.parse(f).getroot() issue_list = [] for elem in request_tree.iterfind('action/sourcediff/issues/issue'): issue_id = elem.get('name') encode_search = '@name=\'%s\'' % issue_id - u = makeurl(apiurl, ['search/issue'], query={'match': encode_search} ) + u = makeurl(apiurl, ['search/issue'], query={'match': encode_search}) f = http_GET(u) collection = ET.parse(f).getroot() for cissue in collection: @@ -4927,17 +4987,18 @@ def get_request_issues(apiurl, reqid): issue_list.append(issue) return issue_list + def submit_action_diff(apiurl, action): """diff a single submit action""" # backward compatiblity: only a recent api/backend supports the missingok parameter try: return server_diff(apiurl, action.tgt_project, action.tgt_package, None, - action.src_project, action.src_package, action.src_rev, True, True) + action.src_project, action.src_package, action.src_rev, True, True) except HTTPError as e: if e.code == 400: try: return server_diff(apiurl, action.tgt_project, action.tgt_package, None, - action.src_project, action.src_package, action.src_rev, True, False) + action.src_project, action.src_package, action.src_rev, True, False) except HTTPError as e: if e.code != 404: raise e @@ -4948,6 +5009,7 @@ def submit_action_diff(apiurl, action): return b'error: \'%s\' does not exist' % root.find('summary').text.encode() raise e + def make_dir(apiurl, project, package, pathname=None, prj_dir=None, package_tracking=True, pkg_path=None): """ creates the plain directory structure for a package dir. @@ -4997,7 +5059,7 @@ def make_dir(apiurl, project, package, pathname=None, prj_dir=None, package_trac def checkout_package(apiurl, project, package, revision=None, pathname=None, prj_obj=None, - expand_link=False, prj_dir=None, server_service_files = None, service_files=None, progress_obj=None, size_limit=None, meta=False, outdir=None): + expand_link=False, prj_dir=None, server_service_files=None, service_files=None, progress_obj=None, size_limit=None, meta=False, outdir=None): try: # the project we're in might be deleted. # that'll throw an error then. @@ -5057,7 +5119,7 @@ def checkout_package(apiurl, project, package, # exists meta_data = b''.join(show_package_meta(apiurl, quote_plus(project), quote_plus(package))) root = ET.fromstring(meta_data) - if root.find('scmsync') != None and root.find('scmsync').text != None: + if root.find('scmsync') is not None and root.find('scmsync').text is not None: if not os.path.isfile('/usr/lib/obs/service/obs_scm_bridge'): raise oscerr.OscIOError(None, 'Install the obs-scm-bridge package to work on packages managed in scm (git)!') scm_url = root.find('scmsync').text @@ -5103,8 +5165,9 @@ def checkout_package(apiurl, project, package, print('Running all source services local') p.run_source_services() -def replace_pkg_meta(pkgmeta, new_name, new_prj, keep_maintainers = False, - dst_userid = None, keep_develproject = False): + +def replace_pkg_meta(pkgmeta, new_name, new_prj, keep_maintainers=False, + dst_userid=None, keep_develproject=False): """ update pkgmeta with new new_name and new_prj and set calling user as the only maintainer (unless keep_maintainers is set). Additionally remove the @@ -5126,6 +5189,7 @@ def replace_pkg_meta(pkgmeta, new_name, new_prj, keep_maintainers = False, root.remove(dp) return ET.tostring(root, encoding=ET_ENCODING) + def link_to_branch(apiurl, project, package): """ convert a package with a _link + project.diff to a branch @@ -5137,7 +5201,8 @@ def link_to_branch(apiurl, project, package): else: raise oscerr.OscIOError(None, 'no _link file inside project \'%s\' package \'%s\'' % (project, package)) -def link_pac(src_project, src_package, dst_project, dst_package, force, rev='', cicount='', disable_publish = False, missing_target = False, vrev=''): + +def link_pac(src_project, src_package, dst_project, dst_package, force, rev='', cicount='', disable_publish=False, missing_target=False, vrev=''): """ create a linked package - "src" is the original package @@ -5326,7 +5391,7 @@ def aggregate_pac(src_project, src_package, dst_project, dst_package, repo_map=N aggregate_template += """\ %s -""" % ( src_package) +""" % (src_package) if nosources: aggregate_template += """\ @@ -5351,7 +5416,7 @@ def attribute_branch_pkg(apiurl, attribute, maintained_update_project_attribute, """ Branch packages defined via attributes (via API call) """ - query = { 'cmd': 'branch' } + query = {'cmd': 'branch'} query['attribute'] = attribute if targetproject: query['target_project'] = targetproject @@ -5404,7 +5469,7 @@ def branch_pkg(apiurl, src_project, src_package, nodevelproject=False, rev=None, """ Branch a package (via API call) """ - query = { 'cmd': 'branch' } + query = {'cmd': 'branch'} if nodevelproject: query['ignoredevel'] = '1' if force: @@ -5466,14 +5531,14 @@ def branch_pkg(apiurl, src_project, src_package, nodevelproject=False, rev=None, def copy_pac(src_apiurl, src_project, src_package, dst_apiurl, dst_project, dst_package, - client_side_copy = False, - keep_maintainers = False, - keep_develproject = False, - expand = False, - revision = None, - comment = None, - force_meta_update = None, - keep_link = None): + client_side_copy=False, + keep_maintainers=False, + keep_develproject=False, + expand=False, + revision=None, + comment=None, + force_meta_update=None, + keep_link=None): """ Create a copy of a package. @@ -5482,8 +5547,8 @@ def copy_pac(src_apiurl, src_project, src_package, or by the server, in a single api call. """ - if not (src_apiurl == dst_apiurl and src_project == dst_project \ - and src_package == dst_package): + if not (src_apiurl == dst_apiurl and src_project == dst_project + and src_package == dst_package): src_meta = show_package_meta(src_apiurl, src_project, src_package) dst_userid = conf.get_apiurl_usr(dst_apiurl) src_meta = replace_pkg_meta(src_meta, dst_package, dst_project, keep_maintainers, @@ -5502,7 +5567,7 @@ def copy_pac(src_apiurl, src_project, src_package, print('Copying files...') if not client_side_copy: - query = {'cmd': 'copy', 'oproject': src_project, 'opackage': src_package } + query = {'cmd': 'copy', 'oproject': src_project, 'opackage': src_package} if expand or keep_link: query['expand'] = '1' if keep_link: @@ -5517,7 +5582,6 @@ def copy_pac(src_apiurl, src_project, src_package, else: # copy one file after the other - import tempfile query = {'rev': 'upload'} xml = show_files_meta(src_apiurl, src_project, src_package, expand=expand, revision=revision) @@ -5555,6 +5619,7 @@ def unlock_package(apiurl, prj, pac, msg): u = makeurl(apiurl, ['source', prj, pac], query) http_POST(u) + def unlock_project(apiurl, prj, msg=None): query = {'cmd': 'unlock', 'comment': msg} u = makeurl(apiurl, ['source', prj], query) @@ -5570,6 +5635,7 @@ def undelete_package(apiurl, prj, pac, msg=None): u = makeurl(apiurl, ['source', prj, pac], query) http_POST(u) + def undelete_project(apiurl, prj, msg=None): query = {'cmd': 'undelete'} if msg: @@ -5589,6 +5655,7 @@ def delete_package(apiurl, prj, pac, force=False, msg=None): u = makeurl(apiurl, ['source', prj, pac], query) http_DELETE(u) + def delete_project(apiurl, prj, force=False, msg=None): query = {} if force: @@ -5598,6 +5665,7 @@ def delete_project(apiurl, prj, force=False, msg=None): u = makeurl(apiurl, ['source', prj], query) http_DELETE(u) + def delete_files(apiurl, prj, pac, files): for filename in files: u = makeurl(apiurl, ['source', prj, pac, filename], query={'comment': 'removed %s' % (filename, )}) @@ -5608,10 +5676,11 @@ def delete_files(apiurl, prj, pac, files): def get_platforms(apiurl): return get_repositories(apiurl) + def get_repositories(apiurl): f = http_GET(makeurl(apiurl, ['platform'])) tree = ET.parse(f) - r = sorted( node.get('name') for node in tree.getroot() ) + r = sorted(node.get('name') for node in tree.getroot()) return r @@ -5638,11 +5707,12 @@ def get_distributions(apiurl): def get_platforms_of_project(apiurl, prj): return get_repositories_of_project(apiurl, prj) + def get_repositories_of_project(apiurl, prj): f = show_project_meta(apiurl, prj) root = ET.fromstring(b''.join(f)) - r = [ node.get('name') for node in root.findall('repository')] + r = [node.get('name') for node in root.findall('repository')] return r @@ -5680,6 +5750,7 @@ class Repo: for repo in repos: f.write('%s %s\n' % (repo.name, repo.arch)) + def get_repos_of_project(apiurl, prj): f = show_project_meta(apiurl, prj) root = ET.fromstring(b''.join(f)) @@ -5688,6 +5759,7 @@ def get_repos_of_project(apiurl, prj): for node2 in node.findall('arch'): yield Repo(node.get('name'), node2.text) + def get_binarylist(apiurl, prj, repo, arch, package=None, verbose=False, withccache=False): what = package or '_repository' query = {} @@ -5697,7 +5769,7 @@ def get_binarylist(apiurl, prj, repo, arch, package=None, verbose=False, withcca f = http_GET(u) tree = ET.parse(f) if not verbose: - return [ node.get('filename') for node in tree.findall('binary')] + return [node.get('filename') for node in tree.findall('binary')] else: l = [] for node in tree.findall('binary'): @@ -5713,11 +5785,13 @@ def get_binarylist_published(apiurl, prj, repo, arch): u = makeurl(apiurl, ['published', prj, repo, arch]) f = http_GET(u) tree = ET.parse(f) - r = [ node.get('name') for node in tree.findall('entry')] + r = [node.get('name') for node in tree.findall('entry')] return r -def show_results_meta(apiurl, prj, package=None, lastbuild=None, repository=[], arch=[], oldstate=None, multibuild=False, locallink=False, code=None): +def show_results_meta(apiurl, prj, package=None, lastbuild=None, repository=None, arch=None, oldstate=None, multibuild=False, locallink=False, code=None): + repository = repository or [] + arch = arch or [] query = [] if package: query.append('package=%s' % quote_plus(package)) @@ -5893,7 +5967,7 @@ def get_package_results(apiurl, project, package=None, wait=False, *args, **kwar if pkg is not None and pkg.get('code') in waiting_states: waiting = True break - + if not wait or not waiting: break else: @@ -5902,7 +5976,7 @@ def get_package_results(apiurl, project, package=None, wait=False, *args, **kwar def get_prj_results(apiurl, prj, hide_legend=False, csv=False, status_filter=None, name_filter=None, arch=None, repo=None, vertical=None, show_excluded=None, brief=False): - #print '----------------------------------------' + # print '----------------------------------------' global buildstatus_symbols r = [] @@ -5918,7 +5992,7 @@ def get_prj_results(apiurl, prj, hide_legend=False, csv=False, status_filter=Non targets = [] # {package: {(repo,arch): status}} status = {} - if root.find('result') == None: + if root.find('result') is None: return [] for results in root.findall('result'): for node in results: @@ -5951,7 +6025,7 @@ def get_prj_results(apiurl, prj, hide_legend=False, csv=False, status_filter=Non pacs_to_show = [] targets_to_show = [] - #filtering for Package Status + # filtering for Package Status if status_filter: if status_filter in buildstatus_symbols.values(): # a list is needed because if status_filter == "U" @@ -5971,13 +6045,13 @@ def get_prj_results(apiurl, prj, hide_legend=False, csv=False, status_filter=Non targets_to_show.append(repo) elif name_filter.search(pkg) is not None: pacs_to_show.append(pkg) - #filtering for Package Name + # filtering for Package Name elif name_filter: for pkg in pacs: if name_filter.search(pkg) is not None: pacs_to_show.append(pkg) - #filter non building states + # filter non building states elif not show_excluded: enabled = {} for pkg in status.keys(): @@ -5992,9 +6066,9 @@ def get_prj_results(apiurl, prj, hide_legend=False, csv=False, status_filter=Non targets_to_show = enabled.keys() - pacs = [ i for i in pacs if i in pacs_to_show ] - if len(targets_to_show): - targets = [ i for i in targets if i in targets_to_show ] + pacs = [i for i in pacs if i in pacs_to_show] + if targets_to_show: + targets = [i for i in targets if i in targets_to_show] # csv output if csv: @@ -6019,14 +6093,14 @@ def get_prj_results(apiurl, prj, hide_legend=False, csv=False, status_filter=Non max_pacs = 40 for startpac in range(0, len(pacs), max_pacs): offset = 0 - for pac in pacs[startpac:startpac+max_pacs]: + for pac in pacs[startpac:startpac + max_pacs]: r.append(' |' * offset + ' ' + pac) offset += 1 for tg in targets: line = [] line.append(' ') - for pac in pacs[startpac:startpac+max_pacs]: + for pac in pacs[startpac:startpac + max_pacs]: st = '' if pac not in status or tg not in status[pac]: # for newly added packages, status may be missing @@ -6069,7 +6143,7 @@ def get_prj_results(apiurl, prj, hide_legend=False, csv=False, status_filter=Non st = '?' buildstatus_symbols[status[pac][tg]] = '?' line.append(st) - line.append(' '+pac) + line.append(' ' + pac) r.append(' '.join(line)) line = [] @@ -6094,14 +6168,14 @@ def get_prj_results(apiurl, prj, hide_legend=False, csv=False, status_filter=Non if i < len(legend): legend[i] += s else: - legend.append(' '*24 + s) + legend.append(' ' * 24 + s) r += legend return r -def streamfile(url, http_meth = http_GET, bufsize=8192, data=None, progress_obj=None, text=None): +def streamfile(url, http_meth=http_GET, bufsize=8192, data=None, progress_obj=None, text=None): """ performs http_meth on url and read bufsize bytes from the response until EOF is reached. After each read bufsize bytes are yielded to the @@ -6117,7 +6191,7 @@ def streamfile(url, http_meth = http_GET, bufsize=8192, data=None, progress_obj= retries = retries + 1 if retries > 1 and conf.config['http_debug']: print('\n\nRetry %d --' % (retries - 1), url, file=sys.stderr) - f = http_meth.__call__(url, data = data) + f = http_meth.__call__(url, data=data) cl = f.info().get('Content-Length') if cl is not None: @@ -6143,7 +6217,7 @@ def streamfile(url, http_meth = http_GET, bufsize=8192, data=None, progress_obj= read = 0 while True: data = xread(bufsize) - if not len(data): + if not data: break read += len(data) if progress_obj: @@ -6154,7 +6228,7 @@ def streamfile(url, http_meth = http_GET, bufsize=8192, data=None, progress_obj= progress_obj.end() f.close() - if not cl is None and read != cl: + if cl is not None and read != cl: raise oscerr.OscIOError(None, 'Content-Length is not matching file size for %s: %i vs %i file size' % (url, cl, read)) @@ -6179,11 +6253,10 @@ def print_buildlog(apiurl, prj, package, repository, arch, offset=0, strip_time= sys.stdout.write(decode_it(data.translate(all_bytes, remove_bytes))) # to protect us against control characters - import string all_bytes = bytes.maketrans(b'', b'') - remove_bytes = all_bytes[:8] + all_bytes[14:32] # accept tabs and newlines + remove_bytes = all_bytes[:8] + all_bytes[14:32] # accept tabs and newlines - query = {'nostream' : '1', 'start' : '%s' % offset} + query = {'nostream': '1', 'start': '%s' % offset} if last: query['last'] = 1 if lastsucceeded: @@ -6209,6 +6282,7 @@ def print_buildlog(apiurl, prj, package, repository, arch, offset=0, strip_time= if start_offset == offset: break + def get_dependson(apiurl, project, repository, arch, packages=None, reverse=None): query = [] if packages: @@ -6224,6 +6298,7 @@ def get_dependson(apiurl, project, repository, arch, packages=None, reverse=None f = http_GET(u) return f.read() + def get_buildinfo(apiurl, prj, package, repository, arch, specfile=None, addlist=None, debug=None): query = [] if addlist: @@ -6289,7 +6364,7 @@ def get_source_rev(apiurl, project, package, revision=None): elif ent.find('time').text < new.find('time').text: ent = new if not ent: - return { 'version': None, 'error': 'empty revisionlist: no such package?' } + return {'version': None, 'error': 'empty revisionlist: no such package?'} e = {} for k in ent.keys(): e[k] = ent.get(k) @@ -6297,10 +6372,10 @@ def get_source_rev(apiurl, project, package, revision=None): e[k.tag] = k.text return e -def get_buildhistory(apiurl, prj, package, repository, arch, format = 'text', limit = None): - import time + +def get_buildhistory(apiurl, prj, package, repository, arch, format='text', limit=None): query = {} - if limit != None and int(limit) > 0: + if limit is not None and int(limit) > 0: query['limit'] = int(limit) u = makeurl(apiurl, ['build', prj, repository, arch, package, '_history'], query) f = http_GET(u) @@ -6315,7 +6390,7 @@ def get_buildhistory(apiurl, prj, package, repository, arch, format = 'text', li duration = node.get('duration') t = time.gmtime(int(node.get('time'))) t = time.strftime('%Y-%m-%d %H:%M:%S', t) - if duration == None: + if duration is None: duration = "" if format == 'csv': @@ -6329,14 +6404,14 @@ def get_buildhistory(apiurl, prj, package, repository, arch, format = 'text', li return r -def print_jobhistory(apiurl, prj, current_package, repository, arch, format = 'text', limit=20): - import time + +def print_jobhistory(apiurl, prj, current_package, repository, arch, format='text', limit=20): query = {} if current_package: query['package'] = current_package - if limit != None and int(limit) > 0: + if limit is not None and int(limit) > 0: query['limit'] = int(limit) - u = makeurl(apiurl, ['build', prj, repository, arch, '_jobhistory'], query ) + u = makeurl(apiurl, ['build', prj, repository, arch, '_jobhistory'], query) f = http_GET(u) root = ET.parse(f).getroot() @@ -6352,11 +6427,11 @@ def print_jobhistory(apiurl, prj, current_package, repository, arch, format = 't st = int(node.get('starttime')) et = int(node.get('endtime')) endtime = time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime(et)) - waittm = et-st - if waittm > 24*60*60: - waitbuild = "%1dd %2dh %2dm %2ds" % (waittm / (24*60*60), (waittm / (60*60)) % 24, (waittm / 60) % 60, waittm % 60) - elif waittm > 60*60: - waitbuild = " %2dh %2dm %2ds" % (waittm / (60*60), (waittm / 60) % 60, waittm % 60) + waittm = et - st + if waittm > 24 * 60 * 60: + waitbuild = "%1dd %2dh %2dm %2ds" % (waittm / (24 * 60 * 60), (waittm / (60 * 60)) % 24, (waittm / 60) % 60, waittm % 60) + elif waittm > 60 * 60: + waitbuild = " %2dh %2dm %2ds" % (waittm / (60 * 60), (waittm / 60) % 60, waittm % 60) else: waitbuild = " %2dm %2ds" % (waittm / 60, waittm % 60) @@ -6366,9 +6441,7 @@ def print_jobhistory(apiurl, prj, current_package, repository, arch, format = 't print('%s %-50s %-16s %-16s %-16s %-16s' % (endtime, package[0:49], reason[0:15], code[0:15], waitbuild, worker)) -def get_commitlog(apiurl, prj, package, revision, format = 'text', meta = False, deleted = False, revision_upper=None): - import time - +def get_commitlog(apiurl, prj, package, revision, format='text', meta=False, deleted=False, revision_upper=None): query = {} if deleted: query['deleted'] = 1 @@ -6389,7 +6462,7 @@ def get_commitlog(apiurl, prj, package, revision, format = 'text', meta = False, srcmd5 = node.find('srcmd5').text try: rev = int(node.get('rev')) - #vrev = int(node.get('vrev')) # what is the meaning of vrev? + # vrev = int(node.get('vrev')) # what is the meaning of vrev? try: if revision is not None and revision_upper is not None: if rev > int(revision_upper) or rev < int(revision): @@ -6401,7 +6474,7 @@ def get_commitlog(apiurl, prj, package, revision, format = 'text', meta = False, continue except ValueError: # this part should _never_ be reached but... - return [ 'an unexpected error occured - please file a bug' ] + return ['an unexpected error occured - please file a bug'] version = node.find('version').text user = node.find('user').text try: @@ -6417,7 +6490,7 @@ def get_commitlog(apiurl, prj, package, revision, format = 'text', meta = False, if format == 'csv': s = '%s|%s|%s|%s|%s|%s|%s' % (rev, user, t, srcmd5, version, - decode_it(comment).replace('\\', '\\\\').replace('\n', '\\n').replace('|', '\\|'), requestid) + decode_it(comment).replace('\\', '\\\\').replace('\n', '\\n').replace('|', '\\|'), requestid) r.append(s) elif format == 'xml': r.append('%s' % t) r.append('%s' % requestid) r.append('%s' % - decode_it(comment).replace('&', '&').replace('<', '>').replace('>', '<')) + decode_it(comment).replace('&', '&').replace('<', '>').replace('>', '<')) r.append('') else: if requestid: @@ -6455,6 +6528,7 @@ def runservice(apiurl, prj, package): root = ET.parse(f).getroot() return root.get('code') + def waitservice(apiurl, prj, package): u = makeurl(apiurl, ['source', prj, package], query={'cmd': 'waitservice'}) @@ -6467,6 +6541,7 @@ def waitservice(apiurl, prj, package): root = ET.parse(f).getroot() return root.get('code') + def mergeservice(apiurl, prj, package): # first waiting that the service finishes and that it did not fail waitservice(apiurl, prj, package) @@ -6485,7 +6560,7 @@ def mergeservice(apiurl, prj, package): def rebuild(apiurl, prj, package, repo, arch, code=None): - query = { 'cmd': 'rebuild' } + query = {'cmd': 'rebuild'} if package: query['package'] = package if repo: @@ -6533,6 +6608,7 @@ def store_read_package(dir): raise oscerr.NoWorkingCopy(msg) return p + def store_read_scmurl(dir): global store @@ -6548,6 +6624,7 @@ def store_read_scmurl(dir): raise oscerr.NoWorkingCopy(msg) return p + def store_read_apiurl(dir, defaulturl=True): global store @@ -6577,6 +6654,7 @@ def store_read_apiurl(dir, defaulturl=True): apiurl = conf.config['apiurl'] return apiurl + def store_read_last_buildroot(dir): global store @@ -6588,6 +6666,7 @@ def store_read_last_buildroot(dir): return + def store_write_string(dir, file, string, subdir=''): global store @@ -6606,20 +6685,27 @@ def store_write_string(dir, file, string, subdir=''): os.unlink(fname + '.new') raise + def store_write_project(dir, project): store_write_string(dir, '_project', project + '\n') + def store_write_apiurl(dir, apiurl): store_write_string(dir, '_apiurl', apiurl + '\n') + def store_write_last_buildroot(dir, repo, arch, vm_type): store_write_string(dir, '_last_buildroot', repo + '\n' + arch + '\n' + vm_type + '\n') + def store_unlink_file(dir, file): global store - try: os.unlink(os.path.join(dir, store, file)) - except: pass + try: + os.unlink(os.path.join(dir, store, file)) + except: + pass + def store_read_file(dir, file): global store @@ -6630,6 +6716,7 @@ def store_read_file(dir, file): except: return None + def store_write_initial_packages(dir, project, subelements): global store @@ -6639,6 +6726,7 @@ def store_write_initial_packages(dir, project, subelements): root.append(elem) ET.ElementTree(root).write(fname) + def get_osc_version(): return __version__ @@ -6646,18 +6734,21 @@ def get_osc_version(): def abortbuild(apiurl, project, package=None, arch=None, repo=None): return cmdbuild(apiurl, 'abortbuild', project, package, arch, repo) + def restartbuild(apiurl, project, package=None, arch=None, repo=None): return cmdbuild(apiurl, 'restartbuild', project, package, arch, repo) + def unpublish(apiurl, project, package=None, arch=None, repo=None, code=None): return cmdbuild(apiurl, 'unpublish', project, package, arch, repo, code) + def wipebinaries(apiurl, project, package=None, arch=None, repo=None, code=None): return cmdbuild(apiurl, 'wipe', project, package, arch, repo, code) def cmdbuild(apiurl, cmd, project, package=None, arch=None, repo=None, code=None, sysrq=None): - query = { 'cmd': cmd } + query = {'cmd': cmd} if package: query['package'] = package if arch: @@ -6710,6 +6801,7 @@ def parseRevisionOption(string, allow_md5=True): return tuple(revisions) + def checkRevision(prj, pac, revision, apiurl=None, meta=False): """ check if revision is valid revision, i.e. it is not @@ -6729,7 +6821,8 @@ def checkRevision(prj, pac, revision, apiurl=None, meta=False): except (ValueError, TypeError): return False -def build_table(col_num, data = [], headline = [], width=1, csv = False): + +def build_table(col_num, data=None, headline=None, width=1, csv=False): """ This method builds a simple table. @@ -6741,6 +6834,8 @@ def build_table(col_num, data = [], headline = [], width=1, csv = False): foo bar suse osc """ + data = data or [] + headline = headline or [] longest_col = [] for i in range(col_num): @@ -6781,6 +6876,7 @@ def build_table(col_num, data = [], headline = [], width=1, csv = False): separator = '' return [separator.join(row) for row in table] + def xpath_join(expr, new_expr, op='or', inner=False, nexpr_parentheses=False): """ Join two xpath expressions. If inner is False expr will @@ -6819,6 +6915,7 @@ def xpath_join(expr, new_expr, op='or', inner=False, nexpr_parentheses=False): new_expr = '(%s)' % new_expr return '%s %s %s' % (expr, op, new_expr) + def search(apiurl, queries=None, **kwargs): """ Perform a search request. The requests are constructed as follows: @@ -6836,8 +6933,8 @@ def search(apiurl, queries=None, **kwargs): queries = {} res = {} for urlpath, xpath in kwargs.items(): - path = [ 'search' ] - path += urlpath.split('_') # FIXME: take underscores as path seperators. I see no other way atm to fix OBS api calls and not breaking osc api + path = ['search'] + path += urlpath.split('_') # FIXME: take underscores as path seperators. I see no other way atm to fix OBS api calls and not breaking osc api query = queries.get(urlpath, {}) query['match'] = xpath u = makeurl(apiurl, path, query) @@ -6845,6 +6942,7 @@ def search(apiurl, queries=None, **kwargs): res[urlpath] = ET.parse(f).getroot() return res + def owner(apiurl, search_term=None, mode="binary", attribute=None, project=None, usefilter=None, devel=None, limit=None, binary=None): """ @@ -6852,25 +6950,25 @@ def owner(apiurl, search_term=None, mode="binary", attribute=None, """ # binary is just for API backward compatibility - if not ((search_term is None) ^ (binary is None)): + if not (search_term is None) ^ (binary is None): raise ValueError('Either specify search_term or binary') elif binary is not None: search_term = binary - + # find default project, if not specified # mode can be "binary" or "package" atm - query = { mode: search_term } + query = {mode: search_term} if attribute: query['attribute'] = attribute if project: query['project'] = project if devel: query['devel'] = devel - if limit != None: + if limit is not None: query['limit'] = limit - if usefilter != None: + if usefilter is not None: query['filter'] = ",".join(usefilter) - u = makeurl(apiurl, [ 'search', 'owner' ], query) + u = makeurl(apiurl, ['search', 'owner'], query) res = None try: f = http_GET(u) @@ -6880,6 +6978,7 @@ def owner(apiurl, search_term=None, mode="binary", attribute=None, pass return res + def set_link_rev(apiurl, project, package, revision='', expand=False): url = makeurl(apiurl, ['source', project, package, '_link']) try: @@ -6893,6 +6992,7 @@ def set_link_rev(apiurl, project, package, revision='', expand=False): http_PUT(url, data=l) return revision + def _set_link_rev(apiurl, project, package, root, revision='', expand=False): """ Updates the rev attribute of the _link xml. If revision is set to None @@ -6945,6 +7045,7 @@ def delete_storedir(store_dir): if tail == '.osc': delete_dir(store_dir) + def unpack_srcrpm(srpm, dir, *files): """ This method unpacks the passed srpm into the @@ -6978,6 +7079,7 @@ def unpack_srcrpm(srpm, dir, *files): sys.exit(1) os.chdir(curdir) + def is_rpm(f): """check if the named file is an RPM package""" try: @@ -6994,6 +7096,7 @@ def is_rpm(f): else: return False + def is_srcrpm(f): """check if the named file is a source RPM""" @@ -7011,10 +7114,12 @@ def is_srcrpm(f): else: return False + def addMaintainer(apiurl, prj, pac, user): # for backward compatibility only addPerson(apiurl, prj, pac, user) + def addPerson(apiurl, prj, pac, user, role="maintainer"): """ add a new person to a package or project """ path = quote_plus(prj), @@ -7027,7 +7132,7 @@ def addPerson(apiurl, prj, pac, user, role="maintainer"): template_args=None, create_new=False) - if data and get_user_meta(apiurl, user) != None: + if data and get_user_meta(apiurl, user) is not None: root = ET.fromstring(parse_meta_to_string(data)) found = False for person in root.getiterator('person'): @@ -7045,10 +7150,12 @@ def addPerson(apiurl, prj, pac, user, role="maintainer"): else: print("osc: an error occured") + def delMaintainer(apiurl, prj, pac, user): # for backward compatibility only delPerson(apiurl, prj, pac, user) + def delPerson(apiurl, prj, pac, user, role="maintainer"): """ delete a person from a package or project """ path = quote_plus(prj), @@ -7060,7 +7167,7 @@ def delPerson(apiurl, prj, pac, user, role="maintainer"): path_args=path, template_args=None, create_new=False) - if data and get_user_meta(apiurl, user) != None: + if data and get_user_meta(apiurl, user) is not None: root = ET.fromstring(parse_meta_to_string(data)) found = False for person in root.getiterator('person'): @@ -7077,6 +7184,7 @@ def delPerson(apiurl, prj, pac, user, role="maintainer"): else: print("an error occured") + def setBugowner(apiurl, prj, pac, user=None, group=None): """ delete all bugowners (user and group entries) and set one new one in a package or project """ path = quote_plus(prj), @@ -7109,6 +7217,7 @@ def setBugowner(apiurl, prj, pac, user=None, group=None): path_args=path, data=ET.tostring(root, encoding=ET_ENCODING)) + def setDevelProject(apiurl, prj, pac, dprj, dpkg=None): """ set the element to package metadata""" path = (quote_plus(prj),) + (quote_plus(pac),) @@ -7117,9 +7226,9 @@ def setDevelProject(apiurl, prj, pac, dprj, dpkg=None): template_args=None, create_new=False) - if data and show_project_meta(apiurl, dprj) != None: + if data and show_project_meta(apiurl, dprj) is not None: root = ET.fromstring(parse_meta_to_string(data)) - if not root.find('devel') != None: + if not root.find('devel') is not None: ET.SubElement(root, 'devel') elem = root.find('devel') if dprj: @@ -7138,6 +7247,7 @@ def setDevelProject(apiurl, prj, pac, dprj, dpkg=None): else: print("osc: an error occured") + def createPackageDir(pathname, prj_obj=None): """ create and initialize a new package dir in the given project. @@ -7162,20 +7272,21 @@ def createPackageDir(pathname, prj_obj=None): def stripETxml(node): node.tail = None - if node.text != None: + if node.text is not None: node.text = node.text.replace(" ", "").replace("\n", "") for child in node: stripETxml(child) + def addGitSource(url): service_file = os.path.join(os.getcwd(), '_service') addfile = False - if os.path.exists( service_file ): + if os.path.exists(service_file): services = ET.parse(os.path.join(os.getcwd(), '_service')).getroot() else: services = ET.fromstring("") addfile = True - stripETxml( services ) + stripETxml(services) si = Serviceinfo() s = si.addGitUrl(services, url) s = si.addTarUp(services) @@ -7189,17 +7300,18 @@ def addGitSource(url): f.write(ET.tostring(s, encoding=ET_ENCODING)) f.close() if addfile: - addFiles( ['_service'] ) + addFiles(['_service']) + def addDownloadUrlService(url): service_file = os.path.join(os.getcwd(), '_service') addfile = False - if os.path.exists( service_file ): + if os.path.exists(service_file): services = ET.parse(os.path.join(os.getcwd(), '_service')).getroot() else: services = ET.fromstring("") addfile = True - stripETxml( services ) + stripETxml(services) si = Serviceinfo() s = si.addDownloadUrl(services, url) si.read(s) @@ -7210,7 +7322,7 @@ def addDownloadUrlService(url): f.write(ET.tostring(s, encoding=ET_ENCODING)) f.close() if addfile: - addFiles( ['_service'] ) + addFiles(['_service']) # download file path = os.getcwd() @@ -7233,7 +7345,7 @@ def addDownloadUrlService(url): f.close() -def addFiles(filenames, prj_obj = None, force=False): +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) @@ -7252,7 +7364,7 @@ def addFiles(filenames, prj_obj = None, force=False): print('osc: warning: \'%s\' is already under version control' % filename) 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 ' \ + raise oscerr.WrongArgs('osc: cannot add a directory to a project unless ' '\'do_package_tracking\' is enabled in the configuration file') pacs, no_pacs = findpacs(pacs, fatal=False) @@ -7301,6 +7413,7 @@ def addFiles(filenames, prj_obj = None, force=False): fname = os.path.join(getTransActPath(pac.dir), filename) print('osc: warning: \'%s\' is already under version control' % fname) + def getPrjPacPaths(path): """ returns the path for a project and a package @@ -7326,6 +7439,7 @@ def getPrjPacPaths(path): prj_dir = os.getcwd() return (prj_dir, pac_dir) + def getTransActPath(pac_dir): """ returns the path for the commit and update operations/transactions. @@ -7338,6 +7452,7 @@ def getTransActPath(pac_dir): pathn = '' return pathn + def get_commit_message_template(pac): """ Read the difference in .changes file(s) and put them as a template to commit message. @@ -7364,7 +7479,9 @@ def get_commit_message_template(pac): return template -def parse_diff_for_commit_message(diff, template = []): + +def parse_diff_for_commit_message(diff, template=None): + template = template or [] date_re = re.compile(r'\+(Mon|Tue|Wed|Thu|Fri|Sat|Sun) ([A-Z][a-z]{2}) ( ?[0-9]|[0-3][0-9]) .*') diff = diff.split('\n') @@ -7372,8 +7489,8 @@ def parse_diff_for_commit_message(diff, template = []): for line in diff[3:]: # this condition is magical, but it removes all unwanted lines from commit message if not(line) or (line and line[0] != '+') or \ - date_re.match(line) or \ - line == '+' or line[0:3] == '+++': + date_re.match(line) or \ + line == '+' or line[0:3] == '+++': continue if line == '+-------------------------------------------------------------------': @@ -7383,6 +7500,7 @@ def parse_diff_for_commit_message(diff, template = []): return template + def get_commit_msg(wc_dir, pacs): template = store_read_file(wc_dir, '_commit_msg') # open editor for commit message @@ -7411,7 +7529,8 @@ def get_commit_msg(wc_dir, pacs): store_unlink_file(wc_dir, '_commit_msg') return msg -def print_request_list(apiurl, project, package = None, states = ('new', 'review', ), force = False): + +def print_request_list(apiurl, project, package=None, states=('new', 'review', ), force=False): """ prints list of pending requests for the specified project/package if "check_for_request_on_action" is enabled in the config or if "force" is set to True @@ -7422,18 +7541,17 @@ def print_request_list(apiurl, project, package = None, states = ('new', 'review msg = '\nPending requests for %s: %s (%s)' if sys.stdout.isatty(): msg = f'\033[1m{msg}\033[0m' - if package is None and len(requests): + if package is None and requests: print(msg % ('project', project, len(requests))) - elif len(requests): + elif requests: print(msg % ('package', '/'.join([project, package]), len(requests))) for r in requests: print(r.list_view(), '\n') + def request_interactive_review(apiurl, request, initial_cmd='', group=None, ignore_reviews=False, source_buildstatus=False): """review the request interactively""" - import tempfile, re - tmpfile = None def safe_change_request_state(*args, **kwargs): @@ -7460,23 +7578,23 @@ def request_interactive_review(apiurl, request, initial_cmd='', group=None, for repo in get_repos_of_project(apiurl, action.src_project): if (disabled is None) or (repo.name not in [d['repo'] for d in disabled]): lintlog_entry = { - 'proj': action.src_project, - 'pkg': action.src_package, - 'repo': repo.name, - 'arch': repo.arch - } + 'proj': action.src_project, + 'pkg': action.src_package, + 'repo': repo.name, + 'arch': repo.arch + } lintlogs.append(lintlog_entry) - print('(%i) %s/%s/%s/%s' % ((len(lintlogs)-1), action.src_project, action.src_package, repo.name, repo.arch)) + print('(%i) %s/%s/%s/%s' % ((len(lintlogs) - 1), action.src_project, action.src_package, repo.name, repo.arch)) if not lintlogs: print('No possible rpmlintlogs found') return False while True: try: - lint_n = int(raw_input('Number of rpmlint log to examine (0 - %i): ' % (len(lintlogs)-1))) + lint_n = int(raw_input('Number of rpmlint log to examine (0 - %i): ' % (len(lintlogs) - 1))) lintlogs[lint_n] break except (ValueError, IndexError): - print('Invalid rpmlintlog index. Please choose between 0 and %i' % (len(lintlogs)-1)) + print('Invalid rpmlintlog index. Please choose between 0 and %i' % (len(lintlogs) - 1)) try: print(decode_it(get_rpmlint_log(apiurl, **lintlogs[lint_n]))) except HTTPError as e: @@ -7516,8 +7634,8 @@ def request_interactive_review(apiurl, request, initial_cmd='', group=None, continue if 'summary' in issue: issues += ("## BUG# " + issue['label'] + ": " - + issue.get('summary') + " : " - + issue.get('state', 'unknown state') + '\n') + + issue.get('summary') + " : " + + issue.get('state', 'unknown state') + '\n') else: issues_nodetails += issue['label'] + ' ' check_list.append(issue['label']) @@ -7550,7 +7668,7 @@ def request_interactive_review(apiurl, request, initial_cmd='', group=None, if repl == 'i' and src_actions: req_summary = str(request) + '\n' issues = '\n\n' + get_formatted_issues(apiurl, request.reqid) - if not orequest is None and tmpfile: + if orequest is not None and tmpfile: tmpfile.close() tmpfile = None if tmpfile is None: @@ -7566,7 +7684,7 @@ def request_interactive_review(apiurl, request, initial_cmd='', group=None, # backward compatible diff for old apis for action in src_actions: diff = b'old: %s/%s\nnew: %s/%s\n' % (action.src_project.encode(), action.src_package.encode(), - action.tgt_project.encode(), action.tgt_package.encode()) + action.tgt_project.encode(), action.tgt_package.encode()) diff += submit_action_diff(apiurl, action) diff += b'\n\n' tmpfile.write(diff) @@ -7623,13 +7741,13 @@ def request_interactive_review(apiurl, request, initial_cmd='', group=None, footer += '\n\n' + decode_it(tmpfile.read()) if msg is None: try: - msg = edit_message(footer = footer, template=msg_template) + msg = edit_message(footer=footer, template=msg_template) except oscerr.UserAbort: # do not abort (show prompt again) continue else: msg = msg.strip('\'').strip('"') - if not orequest is None: + if orequest is not None: request.create(apiurl) if not safe_change_request_state(apiurl, request.reqid, 'accepted', msg, force=force): # an error occured @@ -7637,7 +7755,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) + 'superseded by %s' % request.reqid, request.reqid, force=force) elif state is None: clone_request(apiurl, request.reqid, msg) else: @@ -7675,9 +7793,9 @@ def request_interactive_review(apiurl, request, initial_cmd='', group=None, if tmpfile is not None: tmpfile.close() + def edit_submitrequest(apiurl, project, orequest, new_request=None): """edit a submit action from orequest/new_request""" - import tempfile, shutil actions = orequest.get_actions('submit') oactions = actions if new_request is not None: @@ -7700,7 +7818,7 @@ def edit_submitrequest(apiurl, project, orequest, new_request=None): # the api replaced ':' with '_' in prj and pkg names (clone request) package = '%s.%s' % (oactions[num].src_package.replace(':', '_'), - oactions[num].src_project.replace(':', '_')) + oactions[num].src_project.replace(':', '_')) tmpdir = None cleanup = True try: @@ -7710,8 +7828,8 @@ def edit_submitrequest(apiurl, project, orequest, new_request=None): shell = os.getenv('SHELL', default='/bin/sh') olddir = os.getcwd() os.chdir(tmpdir) - print('Checked out package \'%s\' to %s. Started a new shell (%s).\n' \ - 'Please fix the package and close the shell afterwards.' % (package, tmpdir, shell)) + print('Checked out package \'%s\' to %s. Started a new shell (%s).\n' + 'Please fix the package and close the shell afterwards.' % (package, tmpdir, shell)) run_external(shell) # the pkg might have uncommitted changes... cleanup = False @@ -7738,14 +7856,16 @@ def edit_submitrequest(apiurl, project, orequest, new_request=None): r.actions.append(new_action) if new_action.type == 'submit': new_action.src_package = '%s.%s' % (action.src_package.replace(':', '_'), - action.src_project.replace(':', '_')) + action.src_project.replace(':', '_')) new_action.src_project = project # do an implicit cleanup new_action.opt_sourceupdate = 'cleanup' return r -def get_user_projpkgs(apiurl, user, role=None, exclude_projects=[], proj=True, pkg=True, maintained=False, metadata=False): + +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 excl_prj = '' excl_pkg = '' @@ -7787,6 +7907,7 @@ def get_user_projpkgs(apiurl, user, role=None, exclude_projects=[], proj=True, p filter_role(res, user, role) return res + def run_external(filename, *args, **kwargs): """Executes the program filename via subprocess.call. @@ -7812,6 +7933,7 @@ def run_external(filename, *args, **kwargs): raise raise oscerr.ExtRuntimeError(e.strerror, filename) + def return_external(filename, *args, **kwargs): """Executes the program filename via subprocess.check_output. @@ -7848,6 +7970,8 @@ def return_external(filename, *args, **kwargs): raise oscerr.ExtRuntimeError(e.strerror, filename) # backward compatibility: local role filtering + + def filter_role(meta, user, role): """ remove all project/package nodes if no person node exists @@ -7866,12 +7990,13 @@ def filter_role(meta, user, role): for node in delete: root.remove(node) + def find_default_project(apiurl=None, package=None): """ look though the list of conf.config['getpac_default_project'] and find the first project where the given package exists in the build service. """ - if not len(conf.config['getpac_default_project']): + if not conf.config['getpac_default_project']: return None candidates = re.split('[, ]+', conf.config['getpac_default_project']) if package is None or len(candidates) == 1: @@ -7887,6 +8012,7 @@ def find_default_project(apiurl=None, package=None): pass return None + def utime(filename, arg, ignore_einval=True): """wrapper around os.utime which ignore errno EINVAL by default""" try: @@ -7898,6 +8024,7 @@ def utime(filename, arg, ignore_einval=True): return raise + def which(name): """Searches "name" in PATH.""" name = os.path.expanduser(name) @@ -7933,6 +8060,7 @@ def print_comments(apiurl, kind, *args): print('\nComments:') print_rec(comments) + def create_comment(apiurl, kind, comment, *args, **kwargs): query = {} if kwargs.get('parent') is not None: @@ -7942,17 +8070,20 @@ def create_comment(apiurl, kind, comment, *args, **kwargs): ret = ET.fromstring(f.read()).find('summary') return ret.text + def delete_comment(apiurl, cid): u = makeurl(apiurl, ['comment', cid]) f = http_DELETE(u) ret = ET.fromstring(f.read()).find('summary') return ret.text + def get_rpmlint_log(apiurl, proj, pkg, repo, arch): u = makeurl(apiurl, ['build', proj, repo, arch, pkg, 'rpmlint.log']) f = http_GET(u) return f.read() + def checkout_deleted_package(apiurl, proj, pkg, dst): pl = meta_get_filelist(apiurl, proj, pkg, deleted=True) query = {} @@ -7973,37 +8104,38 @@ def checkout_deleted_package(apiurl, proj, pkg, dst): f.write(data) print('done.') + def vc_export_env(apiurl, quiet=False): - # try to set the env variables for the user's realname and email - # (the variables are used by the "vc" script or some source service) - tag2envs = {'realname': ['VC_REALNAME'], - 'email': ['VC_MAILADDR', 'mailaddr']} - tag2val = {} - missing_tags = [] + # try to set the env variables for the user's realname and email + # (the variables are used by the "vc" script or some source service) + tag2envs = {'realname': ['VC_REALNAME'], + 'email': ['VC_MAILADDR', 'mailaddr']} + tag2val = {} + missing_tags = [] - for (tag, envs) in tag2envs.items(): - env_present = [env for env in envs if env in os.environ] - config_present = tag in conf.config['api_host_options'][apiurl] - if not env_present and not config_present: - missing_tags.append(tag) - elif config_present: - tag2val[tag] = conf.config['api_host_options'][apiurl][tag] + for (tag, envs) in tag2envs.items(): + env_present = [env for env in envs if env in os.environ] + config_present = tag in conf.config['api_host_options'][apiurl] + if not env_present and not config_present: + missing_tags.append(tag) + elif config_present: + tag2val[tag] = conf.config['api_host_options'][apiurl][tag] - if missing_tags: - user = conf.get_apiurl_usr(apiurl) - data = get_user_data(apiurl, user, *missing_tags) - if data: - for tag in missing_tags: - val = data.pop(0) - if val != '-': - tag2val[tag] = val - elif not quiet: - msg = 'Try env %s=...' % tag2envs[tag][0] - print(msg, file=sys.stderr) + if missing_tags: + user = conf.get_apiurl_usr(apiurl) + data = get_user_data(apiurl, user, *missing_tags) + if data: + for tag in missing_tags: + val = data.pop(0) + if val != '-': + tag2val[tag] = val + elif not quiet: + msg = 'Try env %s=...' % tag2envs[tag][0] + print(msg, file=sys.stderr) - for (tag, val) in tag2val.items(): - for env in tag2envs[tag]: - os.environ[env] = val + for (tag, val) in tag2val.items(): + for env in tag2envs[tag]: + os.environ[env] = val class MultibuildFlavorResolver: @@ -8076,7 +8208,6 @@ class MultibuildFlavorResolver: break if use_globs: - import fnmatch multibuild_xml = self.get_multibuild_data() all_flavors = self.parse_multibuild_data(multibuild_xml) flavors = set() diff --git a/osc/credentials.py b/osc/credentials.py index 61924e67..272105e0 100644 --- a/osc/credentials.py +++ b/osc/credentials.py @@ -137,17 +137,17 @@ class ObfuscatedConfigFileCredentialsManager(PlaintextConfigFileCredentialsManag if self._cp.has_option(url, 'passx', proper=True): passwd = self._cp.get(url, 'passx', raw=True) else: - passwd = super(self.__class__, self).get_password(url, user, apiurl=apiurl) + passwd = super().get_password(url, user, apiurl=apiurl) return self.decode_password(passwd) def set_password(self, url, user, password): compressed_pw = bz2.compress(password.encode('ascii')) password = base64.b64encode(compressed_pw).decode("ascii") - super(self.__class__, self).set_password(url, user, password) + super().set_password(url, user, password) def delete_password(self, url, user): self._cp.remove_option(url, 'passx') - super(self.__class__, self).delete_password(url, user) + super().delete_password(url, user) @classmethod def decode_password(cls, password): @@ -174,7 +174,7 @@ class ObfuscatedConfigFileDescriptor(AbstractCredentialsManagerDescriptor): class TransientCredentialsManager(AbstractCredentialsManager): def __init__(self, *args, **kwargs): - super(self.__class__, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self._password = None def _process_options(self, options): @@ -232,7 +232,7 @@ class KeyringCredentialsManager(AbstractCredentialsManager): def create(cls, cp, options): if not has_keyring_support(): return None - return super(cls, cls).create(cp, options) + return super().create(cp, options) def _get_password(self, url, user, apiurl=None): self._load_backend() diff --git a/osc/fetch.py b/osc/fetch.py index 8a1c4e34..1770508c 100644 --- a/osc/fetch.py +++ b/osc/fetch.py @@ -6,14 +6,17 @@ import os import re +import shutil +import subprocess import sys import tempfile from urllib.parse import quote_plus from urllib.request import HTTPError +from . import checker as osc_checker from . import conf from . import oscerr -from .core import makeurl, streamfile, dgst +from .core import makeurl, dgst from .grabber import OscFileGrabber, OscMirrorGroup from .meter import create_text_meter from .util import packagequery, cpio @@ -21,9 +24,9 @@ from .util.helper import decode_it class Fetcher: - def __init__(self, cachedir='/tmp', api_host_options={}, urllist=[], + def __init__(self, cachedir='/tmp', urllist=None, http_debug=False, cookiejar=None, offline=False, - enable_cpio=True, modules=[], download_api_only=False): + enable_cpio=True, modules=None, download_api_only=False): # set up progress bar callback self.progress_obj = None if sys.stdout.isatty(): @@ -31,8 +34,8 @@ class Fetcher: self.cachedir = cachedir # generic download URL lists - self.urllist = urllist - self.modules = modules + self.urllist = urllist or [] + self.modules = modules or [] self.http_debug = http_debug self.offline = offline self.cpio = {} @@ -135,7 +138,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='%s(%s) %s' % (prefix, pac.project, pac.filename)) if mg_stat: self.move_package(tmpfile.name, pac.localdir, pac) @@ -155,7 +158,6 @@ class Fetcher: os.unlink(tmpfile.name) def move_package(self, tmpfile, destdir, pac_obj=None): - import shutil canonname = None if pac_obj and pac_obj.name.startswith('container:'): canonname = pac_obj.canonname @@ -258,7 +260,7 @@ class Fetcher: hdrmd5 = packagequery.PackageQuery.queryhdrmd5(i.fullfilename) if not hdrmd5 or hdrmd5 != i.hdrmd5: print('%s/%s: attempting download from api, since the hdrmd5 did not match - %s != %s' - % (i.project, i.name, hdrmd5, i.hdrmd5)) + % (i.project, i.name, hdrmd5, i.hdrmd5)) os.unlink(i.fullfilename) self.__add_cpio(i) @@ -324,8 +326,6 @@ def verify_pacs_old(pac_list): Check all packages in one go, since this takes only 6 seconds on my Athlon 700 instead of 20 when calling 'rpm -K' for each of them. """ - import subprocess - if not pac_list: return @@ -374,7 +374,7 @@ def verify_pacs_old(pac_list): - You may use --no-verify to skip the verification (which is a risk for your system). """ % {'name': missing_key, - 'dir': os.path.expanduser('~')}, file=sys.stderr) + 'dir': os.path.expanduser('~')}, file=sys.stderr) else: print(""" @@ -403,9 +403,8 @@ def verify_pacs(bi): print("using keys from", ', '.join(bi.prjkeys)) - from . import checker failed = False - checker = checker.Checker() + checker = osc_checker.Checker() try: checker.readkeys(bi.keys) for pkg in pac_list: diff --git a/osc/grabber.py b/osc/grabber.py index 74aaf2bc..0ce6a843 100644 --- a/osc/grabber.py +++ b/osc/grabber.py @@ -5,7 +5,6 @@ import os -import sys from urllib.request import HTTPError from urllib.parse import urlparse from urllib.parse import unquote diff --git a/osc/meter.py b/osc/meter.py index 6ae42b83..5ba368d0 100644 --- a/osc/meter.py +++ b/osc/meter.py @@ -62,6 +62,7 @@ def create_text_meter(*args, **kwargs): return TextMeter(*args, **kwargs) return None + if have_pb_module: TextMeter = PBTextMeter else: diff --git a/osc/oscerr.py b/osc/oscerr.py index 81a9bb19..7caa7eb5 100644 --- a/osc/oscerr.py +++ b/osc/oscerr.py @@ -4,120 +4,148 @@ # either version 2, or (at your option) any later version. - class OscBaseError(Exception): def __init__(self, args=()): - Exception.__init__(self) + super().__init__() self.args = args + def __str__(self): return ''.join(self.args) + class UserAbort(OscBaseError): """Exception raised when the user requested abortion""" + class ConfigError(OscBaseError): """Exception raised when there is an error in the config file""" + def __init__(self, msg, fname): - OscBaseError.__init__(self) + super().__init__() self.msg = msg self.file = fname def __str__(self): return f"Error in config file {self.file}\n {self.msg}" + class ConfigMissingApiurl(ConfigError): """Exception raised when a apiurl does not exist in the config file""" + def __init__(self, msg, fname, url): - ConfigError.__init__(self, msg, fname) + super().__init__(msg, fname) self.url = url + class ConfigMissingCredentialsError(ConfigError): def __init__(self, msg, fname, url): - ConfigError.__init__(self, msg, fname) + super().__init__(msg, fname) self.url = url + class APIError(OscBaseError): """Exception raised when there is an error in the output from the API""" + def __init__(self, msg): - OscBaseError.__init__(self) + super().__init__() self.msg = msg + class NoConfigfile(OscBaseError): """Exception raised when osc's configfile cannot be found""" + def __init__(self, fname, msg): - OscBaseError.__init__(self) + super().__init__() self.file = fname self.msg = msg def __str__(self): return f"Config file cannot be found: {self.file}\n {self.msg}" + class ExtRuntimeError(OscBaseError): """Exception raised when there is a runtime error of an external tool""" + def __init__(self, msg, fname): - OscBaseError.__init__(self) + super().__init__() self.msg = msg self.file = fname + class ServiceRuntimeError(OscBaseError): """Exception raised when the execution of a source service failed""" + def __init__(self, msg): - OscBaseError.__init__(self) + super().__init__() self.msg = msg + class WrongArgs(OscBaseError): """Exception raised by the cli for wrong arguments usage""" + class WrongOptions(OscBaseError): """Exception raised by the cli for wrong option usage""" - #def __str__(self): + # def __str__(self): # s = 'Sorry, wrong options.' # if self.args: # s += '\n' + self.args # return s + class NoWorkingCopy(OscBaseError): """Exception raised when directory is neither a project dir nor a package dir""" + class NotMissing(OscBaseError): """Exception raised when link target should not exist, but it does""" + class WorkingCopyWrongVersion(OscBaseError): """Exception raised when working copy's .osc/_osclib_version doesn't match""" + class WorkingCopyOutdated(OscBaseError): """Exception raised when the working copy is outdated. It takes a tuple with three arguments: path to wc, revision that it has, revision that it should have. """ + def __str__(self): return ('Working copy \'%s\' is out of date (rev %s vs rev %s).\n' - 'Looks as if you need to update it first.' \ - % (self.args[0], self.args[1], self.args[2])) + 'Looks as if you need to update it first.' + % (self.args[0], self.args[1], self.args[2])) + class PackageError(OscBaseError): """Base class for all Package related exceptions""" + def __init__(self, prj, pac): - OscBaseError.__init__(self) + super().__init__() self.prj = prj self.pac = pac + class WorkingCopyInconsistent(PackageError): """Exception raised when the working copy is in an inconsistent state""" + def __init__(self, prj, pac, dirty_files, msg): - PackageError.__init__(self, prj, pac) + super().__init__(prj, pac) self.dirty_files = dirty_files self.msg = msg + class LinkExpandError(PackageError): """Exception raised when source link expansion fails""" + def __init__(self, prj, pac, msg): - PackageError.__init__(self, prj, pac) + super().__init__(prj, pac) self.msg = msg + class OscIOError(OscBaseError): def __init__(self, e, msg): - OscBaseError.__init__(self) + super().__init__() self.e = e self.msg = msg @@ -133,6 +161,7 @@ class OscInvalidRevision(OscValueError): """ Invalid revision value. """ + def __str__(self): return "Invalid revision value: {}".format("".join(self.args)) @@ -141,43 +170,52 @@ class PackageNotInstalled(OscBaseError): """ Exception raised when a package is not installed on local system """ + def __init__(self, pkg): - OscBaseError.__init__(self, (pkg,)) + super().__init__((pkg,)) def __str__(self): return 'Package %s is required for this operation' % self.args + class SignalInterrupt(Exception): """Exception raised on SIGTERM and SIGHUP.""" + class PackageExists(PackageError): """ Exception raised when a local object already exists """ + def __init__(self, prj, pac, msg): - PackageError.__init__(self, prj, pac) + super().__init__(prj, pac) self.msg = msg + class PackageMissing(PackageError): """ Exception raised when a local object doesn't exist """ + def __init__(self, prj, pac, msg): - PackageError.__init__(self, prj, pac) + super().__init__(prj, pac) self.msg = msg + class PackageFileConflict(PackageError): """ Exception raised when there's a file conflict. Conflict doesn't mean an unsuccessfull merge in this context. """ + def __init__(self, prj, pac, file, msg): - PackageError.__init__(self, prj, pac) + super().__init__(prj, pac) self.file = file self.msg = msg + class PackageInternalError(PackageError): def __init__(self, prj, pac, msg): - PackageError.__init__(self, prj, pac) + super().__init__(prj, pac) self.msg = msg # vim: sw=4 et diff --git a/osc/oscssl.py b/osc/oscssl.py index 2e6b7ea0..73c79d47 100644 --- a/osc/oscssl.py +++ b/osc/oscssl.py @@ -1,14 +1,10 @@ import binascii -import datetime -import errno import os import socket import ssl -import sys import tempfile import typing -import urllib3.connection from cryptography import x509 from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives import serialization diff --git a/osc/util/ar.py b/osc/util/ar.py index 8e93a9c1..8cf2d1be 100644 --- a/osc/util/ar.py +++ b/osc/util/ar.py @@ -28,7 +28,7 @@ if not hasattr(os, 'SEEK_SET'): class ArError(Exception): """Base class for all ar related errors""" def __init__(self, fn, msg): - Exception.__init__(self) + super().__init__() self.file = fn self.msg = msg @@ -57,7 +57,7 @@ class ArHdr: class ArFile(BytesIO): """Represents a file which resides in the archive""" def __init__(self, fn, uid, gid, mode, buf): - BytesIO.__init__(self, buf) + super().__init__(buf) self.name = fn self.uid = uid self.gid = gid @@ -97,9 +97,9 @@ class Ar: re.DOTALL) def __init__(self, fn = None, fh = None): - if fn == None and fh == None: - raise ValueError('either \'fn\' or \'fh\' must be != None') - if fh != None: + if fn is None and fh is None: + raise ValueError('either \'fn\' or \'fh\' must be is not None') + if fh is not None: self.__file = fh self.__closefile = False self.filename = fh.name @@ -169,7 +169,7 @@ class Ar: if data != b'!': raise ArError(self.filename, 'no ar archive') pos = 8 - while (len(data) != 0): + while len(data) != 0: self.__file.seek(pos, os.SEEK_SET) data = self.__file.read(self.hdr_len) if not data: diff --git a/osc/util/archquery.py b/osc/util/archquery.py index f5b48ce6..20e5cd71 100644 --- a/osc/util/archquery.py +++ b/osc/util/archquery.py @@ -1,7 +1,7 @@ import os import re import subprocess -import tarfile +import sys from . import packagequery @@ -51,14 +51,14 @@ class ArchQuery(packagequery.PackageQuery, packagequery.PackageQueryResult): def version(self): pkgver = self.fields['pkgver'][0] if 'pkgver' in self.fields else None - if pkgver != None: + if pkgver is not None: pkgver = re.sub(br'[0-9]+:', b'', pkgver, 1) pkgver = re.sub(br'-[^-]*$', b'', pkgver) return pkgver def release(self): pkgver = self.fields['pkgver'][0] if 'pkgver' in self.fields else None - if pkgver != None: + if pkgver is not None: m = re.search(br'-([^-])*$', pkgver) if m: return m.group(1) @@ -207,7 +207,6 @@ class ArchQuery(packagequery.PackageQuery, packagequery.PackageQueryResult): if __name__ == '__main__': - import sys archq = ArchQuery.query(sys.argv[1]) print(archq.name(), archq.version(), archq.release(), archq.arch()) try: diff --git a/osc/util/cpio.py b/osc/util/cpio.py index 7d41b564..f762d87a 100644 --- a/osc/util/cpio.py +++ b/osc/util/cpio.py @@ -14,7 +14,6 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA -import mmap import os import stat import struct @@ -30,7 +29,7 @@ if not hasattr(os, 'SEEK_SET'): class CpioError(Exception): """base class for all cpio related errors""" def __init__(self, fn, msg): - Exception.__init__(self) + super().__init__() self.file = fn self.msg = msg def __str__(self): @@ -153,7 +152,7 @@ class CpioRead: if not self.format in self.sfmt.values(): raise CpioError(self.filename, '\'%s\' is not a supported cpio format' % self.format) pos = 0 - while (len(data) != 0): + while len(data) != 0: self.__file.seek(pos, os.SEEK_SET) data = self.__file.read(self.hdr_len) if not data: diff --git a/osc/util/debquery.py b/osc/util/debquery.py index 0b61af2f..13c26cd4 100644 --- a/osc/util/debquery.py +++ b/osc/util/debquery.py @@ -1,6 +1,7 @@ import itertools import os import re +import sys import tarfile from io import BytesIO @@ -58,11 +59,11 @@ class DebQuery(packagequery.PackageQuery, packagequery.PackageQueryResult): else: control = arfile.get_file(b'control.tar.xz') if control: - if not HAVE_LZMA: - raise DebError(self.__path, 'can\'t open control.tar.xz without python-lzma') - decompressed = lzma.decompress(control.read()) - tar = tarfile.open(name="control.tar.xz", - fileobj=BytesIO(decompressed)) + if not HAVE_LZMA: + raise DebError(self.__path, 'can\'t open control.tar.xz without python-lzma') + decompressed = lzma.decompress(control.read()) + tar = tarfile.open(name="control.tar.xz", + fileobj=BytesIO(decompressed)) else: control = arfile.get_file(b'control.tar.zst') if control: @@ -249,7 +250,6 @@ class DebQuery(packagequery.PackageQuery, packagequery.PackageQueryResult): return b'%s_%s_%s.deb' % (name, version, arch) if __name__ == '__main__': - import sys try: debq = DebQuery.query(sys.argv[1]) except DebError as e: diff --git a/osc/util/helper.py b/osc/util/helper.py index 77ca8d8e..3d724676 100644 --- a/osc/util/helper.py +++ b/osc/util/helper.py @@ -4,6 +4,7 @@ # either version 2, or (at your option) any later version. +import builtins import html from .. import oscerr @@ -39,7 +40,6 @@ def decode_it(obj): def raw_input(*args): - import builtins func = builtins.input try: diff --git a/osc/util/packagequery.py b/osc/util/packagequery.py index a70a5568..8b565ab8 100644 --- a/osc/util/packagequery.py +++ b/osc/util/packagequery.py @@ -1,10 +1,12 @@ +import sys + from .helper import decode_it class PackageError(Exception): """base class for all package related errors""" def __init__(self, fname, msg): - Exception.__init__(self) + super().__init__() self.fname = fname self.msg = msg @@ -166,7 +168,6 @@ def cmp(a, b): if __name__ == '__main__': - import sys try: pkgq = PackageQuery.query(sys.argv[1]) except PackageError as e: diff --git a/osc/util/rpmquery.py b/osc/util/rpmquery.py index 7a91fa04..6b78c72c 100644 --- a/osc/util/rpmquery.py +++ b/osc/util/rpmquery.py @@ -1,6 +1,7 @@ import os import re import struct +import sys from . import packagequery from .helper import decode_it @@ -385,7 +386,6 @@ def unpack_string(data, encoding=None): return data if __name__ == '__main__': - import sys try: rpmq = RpmQuery.query(sys.argv[1]) except RpmError as e: diff --git a/tests/common.py b/tests/common.py index db0f4ee2..0cc88fe0 100644 --- a/tests/common.py +++ b/tests/common.py @@ -32,8 +32,8 @@ def urlcompare(url, *args): query_args2 = parse_qs(components2.query) components2 = components2._replace(query=None) - if components != components2 or \ - query_args != query_args2: + if components != components2 or \ + query_args != query_args2: return False return True @@ -64,8 +64,9 @@ def xml_equal(actual, exp): class RequestWrongOrder(Exception): """raised if an unexpected request is issued to urllib2""" + def __init__(self, url, exp_url, method, exp_method): - Exception.__init__(self) + super().__init__() self.url = url self.exp_url = exp_url self.method = method @@ -74,8 +75,10 @@ class RequestWrongOrder(Exception): def __str__(self): return '%s, %s, %s, %s' % (self.url, self.exp_url, self.method, self.exp_method) + class RequestDataMismatch(Exception): """raised if POSTed or PUTed data doesn't match with the expected data""" + def __init__(self, url, got, exp): self.url = url self.got = got @@ -91,7 +94,7 @@ EXPECTED_REQUESTS = [] # HACK: Fix "ValueError: I/O operation on closed file." error in tests on openSUSE Leap 15.2. # The problem seems to appear only in the tests, possibly some interaction with MockHTTPConnectionPool. # Porting 753fbc03 to urllib3 in openSUSE Leap 15.2 would fix the problem. -urllib3.response.HTTPResponse.__iter__ = lambda self : iter(self._fp) +urllib3.response.HTTPResponse.__iter__ = lambda self: iter(self._fp) class MockHTTPConnectionPool: @@ -290,7 +293,7 @@ class OscTestCase(unittest.TestCase): self.assertEqual(got, exp) else: start_delim = "\n" + (" 8< ".join(["-----"] * 8)) + "\n" - end_delim = "\n" + (" >8 ".join(["-----"] * 8)) + "\n\n" + end_delim = "\n" + (" >8 ".join(["-----"] * 8)) + "\n\n" self.assertEqual(got, exp, - "got:" + start_delim + got + end_delim + + "got:" + start_delim + got + end_delim + "expected:" + start_delim + exp + end_delim) diff --git a/tests/test_addfiles.py b/tests/test_addfiles.py index bfee7ff4..1bb5c92e 100644 --- a/tests/test_addfiles.py +++ b/tests/test_addfiles.py @@ -1,5 +1,6 @@ import os import sys +import unittest import osc.core import osc.oscerr @@ -9,10 +10,11 @@ from .common import OscTestCase FIXTURES_DIR = os.path.join(os.path.dirname(__file__), 'addfile_fixtures') + def suite(): - import unittest return unittest.defaultTestLoader.loadTestsFromTestCase(TestAddFiles) + class TestAddFiles(OscTestCase): def _get_fixtures_dir(self): return FIXTURES_DIR @@ -83,6 +85,6 @@ class TestAddFiles(OscTestCase): self.assertRaises(osc.oscerr.OscIOError, p.addfile, 'doesnotexist') self.assertFalse(os.path.exists(os.path.join('.osc', '_to_be_added'))) + if __name__ == '__main__': - import unittest unittest.main() diff --git a/tests/test_commit.py b/tests/test_commit.py index 667ab6ea..a3ea595f 100644 --- a/tests/test_commit.py +++ b/tests/test_commit.py @@ -1,5 +1,6 @@ import os import sys +import unittest from urllib.error import HTTPError from xml.etree import ElementTree as ET @@ -11,12 +12,14 @@ from .common import GET, PUT, POST, DELETE, OscTestCase FIXTURES_DIR = os.path.join(os.path.dirname(__file__), 'commit_fixtures') + def suite(): - import unittest return unittest.defaultTestLoader.loadTestsFromTestCase(TestCommit) + rev_dummy = '\n empty\n' + class TestCommit(OscTestCase): def _get_fixtures_dir(self): return FIXTURES_DIR @@ -27,7 +30,7 @@ class TestCommit(OscTestCase): @POST('http://localhost/source/osctest/simple?comment=&cmd=commitfilelist&user=Admin&withvalidate=1', file='testSimple_missingfilelist', expfile='testSimple_lfilelist') @PUT('http://localhost/source/osctest/simple/nochange?rev=repository', - exp='This file didn\'t change but\nis modified.\n', text=rev_dummy) + exp='This file didn\'t change but\nis modified.\n', text=rev_dummy) @POST('http://localhost/source/osctest/simple?comment=&cmd=commitfilelist&user=Admin', file='testSimple_cfilesremote', expfile='testSimple_lfilelist') @GET('http://localhost/search/request?match=%28state%2F%40name%3D%27new%27+or+state%2F%40name%3D%27review%27%29+and+%28action%2Ftarget%2F%40project%3D%27osctest%27+or+action%2Fsource%2F%40project%3D%27osctest%27%29+and+%28action%2Ftarget%2F%40package%3D%27simple%27+or+action%2Fsource%2F%40package%3D%27simple%27%29', file='testOpenRequests') @@ -183,7 +186,7 @@ class TestCommit(OscTestCase): @POST('http://localhost/source/osctest/simple?comment=&cmd=commitfilelist&user=Admin&withvalidate=1', file='testSimple_missingfilelist', expfile='testSimple_lfilelist') @PUT('http://localhost/source/osctest/simple/nochange?rev=repository', exp='This file didn\'t change but\nis modified.\n', - exception=IOError('test exception'), text=rev_dummy) + exception=IOError('test exception'), text=rev_dummy) def test_interrupt(self): """interrupt a commit""" self._change_to_pkg('simple') @@ -307,7 +310,7 @@ class TestCommit(OscTestCase): @POST('http://localhost/source/osctest/simple?comment=&cmd=commitfilelist&user=Admin&withvalidate=1', file='testSimple_missingfilelist', expfile='testSimple_lfilelist') @PUT('http://localhost/source/osctest/simple/nochange?rev=repository', - exp='This file didn\'t change but\nis modified.\n', text=rev_dummy) + exp='This file didn\'t change but\nis modified.\n', text=rev_dummy) @POST('http://localhost/source/osctest/simple?comment=&cmd=commitfilelist&user=Admin', expfile='testSimple_lfilelist', text='an error occured', code=500) def test_commitfilelist_error(self): @@ -328,7 +331,7 @@ class TestCommit(OscTestCase): @POST('http://localhost/source/osctest/simple?comment=&cmd=commitfilelist&user=Admin', file='testSimple_missingfilelistwithSHAsum', expfile='testSimple_lfilelistwithSHA') @PUT('http://localhost/source/osctest/simple/nochange?rev=repository', - exp='This file didn\'t change but\nis modified.\n', text=rev_dummy) + exp='This file didn\'t change but\nis modified.\n', text=rev_dummy) @POST('http://localhost/source/osctest/simple?comment=&cmd=commitfilelist&user=Admin', file='testSimple_cfilesremote', expfile='testSimple_lfilelistwithSHA') @GET('http://localhost/search/request?match=%28state%2F%40name%3D%27new%27+or+state%2F%40name%3D%27review%27%29+and+%28action%2Ftarget%2F%40project%3D%27osctest%27+or+action%2Fsource%2F%40project%3D%27osctest%27%29+and+%28action%2Ftarget%2F%40package%3D%27simple%27+or+action%2Fsource%2F%40package%3D%27simple%27%29', file='testOpenRequests') @@ -368,6 +371,6 @@ class TestCommit(OscTestCase): self._check_status(p, 'add', '!') self._check_status(p, 'bar', ' ') -if __name__ == '__main__': - import unittest + +if __name__ == '__main__': unittest.main() diff --git a/tests/test_core.py b/tests/test_core.py index a574744e..4cd6f6ce 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -48,5 +48,4 @@ class TestParseRevisionOption(unittest.TestCase): if __name__ == "__main__": - import unittest unittest.main() diff --git a/tests/test_deletefiles.py b/tests/test_deletefiles.py index f70675f3..56685063 100644 --- a/tests/test_deletefiles.py +++ b/tests/test_deletefiles.py @@ -1,4 +1,5 @@ import os +import unittest import osc.core import osc.oscerr @@ -8,10 +9,11 @@ from .common import OscTestCase FIXTURES_DIR = os.path.join(os.path.dirname(__file__), 'deletefile_fixtures') + def suite(): - import unittest return unittest.defaultTestLoader.loadTestsFromTestCase(TestDeleteFiles) + class TestDeleteFiles(OscTestCase): def _get_fixtures_dir(self): return FIXTURES_DIR @@ -205,6 +207,6 @@ class TestDeleteFiles(OscTestCase): self.assertTrue(ret[0] == exp1) self.assertTrue(ret[1] == exp2) + if __name__ == '__main__': - import unittest unittest.main() diff --git a/tests/test_difffiles.py b/tests/test_difffiles.py index 5739be14..1b1252c4 100644 --- a/tests/test_difffiles.py +++ b/tests/test_difffiles.py @@ -1,5 +1,6 @@ import os import re +import unittest import osc.core import osc.oscerr @@ -10,12 +11,14 @@ from .common import GET, OscTestCase FIXTURES_DIR = os.path.join(os.path.dirname(__file__), 'difffile_fixtures') + def suite(): - import unittest return unittest.defaultTestLoader.loadTestsFromTestCase(TestDiffFiles) + class TestDiffFiles(OscTestCase): diff_hdr = 'Index: %s\n===================================================================' + def _get_fixtures_dir(self): return FIXTURES_DIR @@ -335,6 +338,6 @@ Binary file 'binary' has changed. exp = __canonise_diff(exp) self.assertEqualMultiline(got, exp) + if __name__ == '__main__': - import unittest unittest.main() diff --git a/tests/test_helpers.py b/tests/test_helpers.py index 52570880..7821ca65 100644 --- a/tests/test_helpers.py +++ b/tests/test_helpers.py @@ -6,6 +6,7 @@ from osc.util.helper import decode_it, decode_list def suite(): return unittest.defaultTestLoader.loadTestsFromTestCase(TestResults) + class TestResults(unittest.TestCase): def testDecodeList(self): strlist = ['Test1', 'Test2', 'Test3'] @@ -21,7 +22,6 @@ class TestResults(unittest.TestCase): out = decode_list(byteslist) self.assertListEqual(out, strlist) - def testDecodeIt(self): bytes_obj = b'Test the decoding' string_obj = 'Test the decoding' @@ -32,6 +32,6 @@ class TestResults(unittest.TestCase): out = decode_it(string_obj) self.assertEqual(out, string_obj) + if __name__ == '__main__': unittest.main() - diff --git a/tests/test_init_package.py b/tests/test_init_package.py index 30519ac4..ec6c5f05 100644 --- a/tests/test_init_package.py +++ b/tests/test_init_package.py @@ -1,4 +1,5 @@ import os +import unittest import osc.core import osc.oscerr @@ -8,10 +9,11 @@ from .common import OscTestCase FIXTURES_DIR = os.path.join(os.path.dirname(__file__), 'init_package_fixtures') + def suite(): - import unittest return unittest.defaultTestLoader.loadTestsFromTestCase(TestInitPackage) + class TestInitPackage(OscTestCase): def _get_fixtures_dir(self): # workaround for git because it doesn't allow empty dirs @@ -22,7 +24,7 @@ class TestInitPackage(OscTestCase): def tearDown(self): if os.path.exists(os.path.join(FIXTURES_DIR, 'osctest')): os.rmdir(os.path.join(FIXTURES_DIR, 'osctest')) - OscTestCase.tearDown(self) + super().tearDown() def test_simple(self): """initialize a package dir""" @@ -88,6 +90,6 @@ class TestInitPackage(OscTestCase): f.write('foo\n') self.assertRaises(osc.oscerr.OscIOError, osc.core.Package.init_package, 'http://localhost', 'osctest', 'testpkg', pac_dir) + if __name__ == '__main__': - import unittest unittest.main() diff --git a/tests/test_init_project.py b/tests/test_init_project.py index ca3d69f5..4c0f24f6 100644 --- a/tests/test_init_project.py +++ b/tests/test_init_project.py @@ -1,5 +1,7 @@ import os +import unittest +import osc.conf import osc.core import osc.oscerr @@ -8,10 +10,11 @@ from .common import GET, OscTestCase FIXTURES_DIR = os.path.join(os.path.dirname(__file__), 'init_project_fixtures') + def suite(): - import unittest return unittest.defaultTestLoader.loadTestsFromTestCase(TestInitProject) + class TestInitProject(OscTestCase): def _get_fixtures_dir(self): # workaround for git because it doesn't allow empty dirs @@ -22,7 +25,7 @@ class TestInitProject(OscTestCase): def tearDown(self): if os.path.exists(os.path.join(FIXTURES_DIR, 'osctest')): os.rmdir(os.path.join(FIXTURES_DIR, 'osctest')) - OscTestCase.tearDown(self) + super().tearDown() def test_simple(self): """initialize a project dir""" @@ -58,7 +61,6 @@ class TestInitProject(OscTestCase): disable wc_check (because we didn't disable the package tracking before the Project class was imported therefore REQ_STOREFILES contains '_packages') """ - import osc.conf # disable package tracking osc.conf.config['do_package_tracking'] = False prj_dir = os.path.join(self.tmpdir, 'testprj') @@ -70,6 +72,6 @@ class TestInitProject(OscTestCase): self._check_list(os.path.join(storedir, '_apiurl'), 'http://localhost\n') self.assertFalse(os.path.exists(os.path.join(storedir, '_packages'))) + if __name__ == '__main__': - import unittest unittest.main() diff --git a/tests/test_package_status.py b/tests/test_package_status.py index 2bf457e3..85619151 100644 --- a/tests/test_package_status.py +++ b/tests/test_package_status.py @@ -1,4 +1,5 @@ import os +import unittest import osc.core import osc.oscerr @@ -8,10 +9,11 @@ from .common import OscTestCase FIXTURES_DIR = os.path.join(os.path.dirname(__file__), 'project_package_status_fixtures') + def suite(): - import unittest return unittest.defaultTestLoader.loadTestsFromTestCase(TestPackageStatus) + class TestPackageStatus(OscTestCase): def _get_fixtures_dir(self): return FIXTURES_DIR @@ -21,7 +23,7 @@ class TestPackageStatus(OscTestCase): self._change_to_pkg('simple') p = osc.core.Package('.') exp_st = [('A', 'add'), ('?', 'exists'), ('D', 'foo'), ('!', 'merge'), ('R', 'missing'), - ('!', 'missing_added'), ('M', 'nochange'), ('S', 'skipped'), (' ', 'test')] + ('!', 'missing_added'), ('M', 'nochange'), ('S', 'skipped'), (' ', 'test')] st = p.get_status() self.assertEqual(exp_st, st) @@ -84,6 +86,6 @@ class TestPackageStatus(OscTestCase): st = p.get_status(True) self.assertEqual(exp_st, st) + if __name__ == '__main__': - import unittest unittest.main() diff --git a/tests/test_prdiff.py b/tests/test_prdiff.py index 585a794c..92c8f1b0 100644 --- a/tests/test_prdiff.py +++ b/tests/test_prdiff.py @@ -1,6 +1,7 @@ import os import re import sys +import unittest import osc.commandline import osc.core @@ -11,12 +12,14 @@ from .common import GET, POST, OscTestCase, EXPECTED_REQUESTS FIXTURES_DIR = os.path.join(os.path.dirname(__file__), 'prdiff_fixtures') UPSTREAM = 'some:project' -BRANCH = 'home:user:branches:' + UPSTREAM +BRANCH = 'home:user:branches:' + UPSTREAM + def rdiff_url(pkg, oldprj, newprj): return 'http://localhost/source/%s/%s?unified=1&opackage=%s&oproject=%s&cmd=diff&expand=1&tarlimit=0&filelimit=0' % \ (newprj, pkg, pkg, oldprj.replace(':', '%3A')) + def request_url(prj): return 'http://localhost/search/request?match=%%28state%%2F%%40name%%3D%%27new%%27+or+state%%2F%%40name%%3D%%27review%%27%%29+and+%%28action%%2Ftarget%%2F%%40project%%3D%%27%s%%27+or+action%%2Fsource%%2F%%40project%%3D%%27%s%%27%%29' % \ tuple([prj.replace(':', '%3A')] * 2) @@ -42,11 +45,12 @@ def POST_RDIFF(oldprj, newprj): def suite(): - import unittest return unittest.defaultTestLoader.loadTestsFromTestCase(TestProjectDiff) + class TestProjectDiff(OscTestCase): diff_hdr = 'Index: %s\n===================================================================' + def _get_fixtures_dir(self): return FIXTURES_DIR @@ -61,13 +65,11 @@ class TestProjectDiff(OscTestCase): cli.main(argv=argv) return sys.stdout.getvalue() - def testPrdiffTooManyArgs(self): def runner(): self._run_prdiff('one', 'two', 'superfluous-arg') self.assertRaises(osc.oscerr.WrongArgs, runner) - @GET_PROJECT_PACKAGES(UPSTREAM, BRANCH) @POST_RDIFF(UPSTREAM, BRANCH) @POST(rdiff_url('only-in-new', UPSTREAM, BRANCH), exp='', text='') @@ -77,6 +79,7 @@ differs: common-two identical: common-three identical: only-in-new """ + def runner(): self._run_prdiff() @@ -90,7 +93,6 @@ identical: only-in-new out = self._run_prdiff() self.assertEqualMultiline(out, exp) - @GET_PROJECT_PACKAGES(UPSTREAM, BRANCH) @POST_RDIFF(UPSTREAM, BRANCH) @POST(rdiff_url('only-in-new', UPSTREAM, BRANCH), exp='', text='') @@ -104,7 +106,6 @@ identical: only-in-new out = self._run_prdiff('home:user:branches:some:project') self.assertEqualMultiline(out, exp) - @GET_PROJECT_PACKAGES('old:prj', 'new:prj') @POST_RDIFF('old:prj', 'new:prj') def testPrdiffTwoArgs(self): @@ -116,7 +117,6 @@ identical: common-three out = self._run_prdiff('old:prj', 'new:prj') self.assertEqualMultiline(out, exp) - @GET_PROJECT_PACKAGES('old:prj', 'new:prj') @POST_RDIFF('old:prj', 'new:prj') def testPrdiffOldOnly(self): @@ -129,7 +129,6 @@ old only: only-in-old out = self._run_prdiff('--show-not-in-new', 'old:prj', 'new:prj') self.assertEqualMultiline(out, exp) - @GET_PROJECT_PACKAGES('old:prj', 'new:prj') @POST_RDIFF('old:prj', 'new:prj') def testPrdiffNewOnly(self): @@ -142,7 +141,6 @@ new only: only-in-new out = self._run_prdiff('--show-not-in-old', 'old:prj', 'new:prj') self.assertEqualMultiline(out, exp) - @GET_PROJECT_PACKAGES('old:prj', 'new:prj') @POST_RDIFF('old:prj', 'new:prj') def testPrdiffDiffstat(self): @@ -158,7 +156,6 @@ identical: common-three out = self._run_prdiff('--diffstat', 'old:prj', 'new:prj') self.assertEqualMultiline(out, exp) - @GET_PROJECT_PACKAGES('old:prj', 'new:prj') @POST_RDIFF('old:prj', 'new:prj') def testPrdiffUnified(self): @@ -182,9 +179,8 @@ identical: common-three out = self._run_prdiff('--unified', 'old:prj', 'new:prj') self.assertEqualMultiline(out, exp) - @GET_PROJECT_PACKAGES('old:prj', 'new:prj') - @POST(rdiff_url('common-two', 'old:prj', 'new:prj'), exp='', file='common-two-diff') + @POST(rdiff_url('common-two', 'old:prj', 'new:prj'), exp='', file='common-two-diff') @POST(rdiff_url('common-three', 'old:prj', 'new:prj'), exp='', text='') def testPrdiffInclude(self): self._change_to_tmpdir() @@ -195,9 +191,8 @@ identical: common-three 'old:prj', 'new:prj') self.assertEqualMultiline(out, exp) - @GET_PROJECT_PACKAGES('old:prj', 'new:prj') - @POST(rdiff_url('common-two', 'old:prj', 'new:prj'), exp='', file='common-two-diff') + @POST(rdiff_url('common-two', 'old:prj', 'new:prj'), exp='', file='common-two-diff') @POST(rdiff_url('common-three', 'old:prj', 'new:prj'), exp='', text='') def testPrdiffExclude(self): self._change_to_tmpdir() @@ -207,9 +202,8 @@ identical: common-three out = self._run_prdiff('--exclude', 'one', 'old:prj', 'new:prj') self.assertEqualMultiline(out, exp) - @GET_PROJECT_PACKAGES('old:prj', 'new:prj') - @POST(rdiff_url('common-two', 'old:prj', 'new:prj'), exp='', file='common-two-diff') + @POST(rdiff_url('common-two', 'old:prj', 'new:prj'), exp='', file='common-two-diff') def testPrdiffIncludeExclude(self): self._change_to_tmpdir() exp = """differs: common-two @@ -219,13 +213,12 @@ identical: common-three 'old:prj', 'new:prj') self.assertEqualMultiline(out, exp) - @GET_PROJECT_PACKAGES(UPSTREAM, BRANCH) @GET(request_url(UPSTREAM), exp='', file='request') - @POST(rdiff_url('common-one', UPSTREAM, BRANCH), exp='', text='') - @POST(rdiff_url('common-two', UPSTREAM, BRANCH), exp='', file='common-two-diff') + @POST(rdiff_url('common-one', UPSTREAM, BRANCH), exp='', text='') + @POST(rdiff_url('common-two', UPSTREAM, BRANCH), exp='', file='common-two-diff') @POST(rdiff_url('common-three', UPSTREAM, BRANCH), exp='', file='common-two-diff') - @POST(rdiff_url('only-in-new', UPSTREAM, BRANCH), exp='', text='') + @POST(rdiff_url('only-in-new', UPSTREAM, BRANCH), exp='', text='') def testPrdiffRequestsMatching(self): self._change_to_tmpdir() exp = """identical: common-one @@ -241,14 +234,14 @@ identical: only-in-new out = self._run_prdiff('--requests', UPSTREAM, BRANCH) self.assertEqualMultiline(out, exp) - # Reverse the direction of the diff. + @GET_PROJECT_PACKAGES(BRANCH, UPSTREAM) @GET(request_url(BRANCH), exp='', file='no-requests') - @POST(rdiff_url('common-one', BRANCH, UPSTREAM), exp='', text='') - @POST(rdiff_url('common-two', BRANCH, UPSTREAM), exp='', file='common-two-diff') + @POST(rdiff_url('common-one', BRANCH, UPSTREAM), exp='', text='') + @POST(rdiff_url('common-two', BRANCH, UPSTREAM), exp='', file='common-two-diff') @POST(rdiff_url('common-three', BRANCH, UPSTREAM), exp='', file='common-two-diff') - @POST(rdiff_url('only-in-new', BRANCH, UPSTREAM), exp='', text='') + @POST(rdiff_url('only-in-new', BRANCH, UPSTREAM), exp='', text='') def testPrdiffRequestsSwitched(self): self._change_to_tmpdir() exp = """identical: common-one @@ -260,7 +253,5 @@ identical: only-in-new self.assertEqualMultiline(out, exp) - if __name__ == '__main__': - import unittest unittest.main() diff --git a/tests/test_project_status.py b/tests/test_project_status.py index 78c6ef93..c5b14296 100644 --- a/tests/test_project_status.py +++ b/tests/test_project_status.py @@ -1,4 +1,5 @@ import os +import unittest import osc.core import osc.oscerr @@ -8,10 +9,11 @@ from .common import OscTestCase FIXTURES_DIR = os.path.join(os.path.dirname(__file__), 'project_package_status_fixtures') + def suite(): - import unittest return unittest.defaultTestLoader.loadTestsFromTestCase(TestProjectStatus) + class TestProjectStatus(OscTestCase): def _get_fixtures_dir(self): return FIXTURES_DIR @@ -93,7 +95,7 @@ class TestProjectStatus(OscTestCase): self._change_to_pkg('.') prj = osc.core.Project('.', getPackageList=False) exp_st = [(' ', 'conflict'), (' ', 'simple'), ('A', 'added'), ('D', 'deleted'), - ('!', 'missing'), ('!', 'added_deleted'), ('D', 'deleted_deleted'), ('?', 'excluded')] + ('!', 'missing'), ('!', 'added_deleted'), ('D', 'deleted_deleted'), ('?', 'excluded')] st = prj.get_status() self.assertEqual(exp_st, st) @@ -159,6 +161,6 @@ class TestProjectStatus(OscTestCase): p = prj.get_pacobj('doesnotexist') self.assertTrue(isinstance(p, type(None))) + if __name__ == '__main__': - import unittest unittest.main() diff --git a/tests/test_repairwc.py b/tests/test_repairwc.py index cb224b02..30f85e44 100644 --- a/tests/test_repairwc.py +++ b/tests/test_repairwc.py @@ -1,5 +1,7 @@ import os +import shutil import sys +import unittest from xml.etree import ElementTree as ET import osc.core @@ -10,10 +12,11 @@ from .common import GET, PUT, POST, DELETE, OscTestCase FIXTURES_DIR = os.path.join(os.path.dirname(__file__), 'repairwc_fixtures') + def suite(): - import unittest return unittest.defaultTestLoader.loadTestsFromTestCase(TestRepairWC) + class TestRepairWC(OscTestCase): def _get_fixtures_dir(self): return FIXTURES_DIR @@ -214,7 +217,6 @@ class TestRepairWC(OscTestCase): def test_project_noapiurl(self): """the project wc has no _apiurl file""" - import shutil prj_dir = os.path.join(self.tmpdir, 'prj_noapiurl') shutil.copytree(os.path.join(self._get_fixtures_dir(), 'prj_noapiurl'), prj_dir) storedir = os.path.join(prj_dir, osc.core.store) @@ -227,5 +229,4 @@ class TestRepairWC(OscTestCase): if __name__ == '__main__': - import unittest unittest.main() diff --git a/tests/test_request.py b/tests/test_request.py index 9bd84b7a..6754abbe 100644 --- a/tests/test_request.py +++ b/tests/test_request.py @@ -1,4 +1,5 @@ import os +import unittest from xml.etree import ElementTree as ET import osc.core @@ -9,22 +10,23 @@ from .common import OscTestCase FIXTURES_DIR = os.path.join(os.path.dirname(__file__), 'request_fixtures') + def suite(): - import unittest return unittest.defaultTestLoader.loadTestsFromTestCase(TestRequest) + class TestRequest(OscTestCase): def _get_fixtures_dir(self): return FIXTURES_DIR def setUp(self): - OscTestCase.setUp(self, copytree=False) + super().setUp(copytree=False) def test_createsr(self): """create a simple submitrequest""" r = osc.core.Request() r.add_action('submit', src_project='foo', src_package='bar', src_rev='42', - tgt_project='foobar', tgt_package='bar') + tgt_project='foobar', tgt_package='bar') self.assertEqual(r.actions[0].type, 'submit') self.assertEqual(r.actions[0].src_project, 'foo') self.assertEqual(r.actions[0].src_package, 'bar') @@ -49,7 +51,7 @@ class TestRequest(OscTestCase): """create a simple submitrequest""" r = osc.core.Request() r.add_action('submit', src_project='foo', src_package='bar', - tgt_project='foobar', tgt_package='bar', opt_sourceupdate='cleanup', opt_updatelink='1') + tgt_project='foobar', tgt_package='bar', opt_sourceupdate='cleanup', opt_updatelink='1') self.assertEqual(r.actions[0].type, 'submit') self.assertEqual(r.actions[0].src_project, 'foo') self.assertEqual(r.actions[0].src_package, 'bar') @@ -77,7 +79,7 @@ class TestRequest(OscTestCase): """create a submitrequest with missing target package""" r = osc.core.Request() r.add_action('submit', src_project='foo', src_package='bar', - tgt_project='foobar') + tgt_project='foobar') self.assertEqual(r.actions[0].type, 'submit') self.assertEqual(r.actions[0].src_project, 'foo') self.assertEqual(r.actions[0].src_package, 'bar') @@ -148,7 +150,7 @@ class TestRequest(OscTestCase): """create an add_role request (person+group element)""" r = osc.core.Request() r.add_action('add_role', tgt_project='foo', tgt_package='bar', person_name='user', person_role='reader', - group_name='group', group_role='reviewer') + group_name='group', group_role='reviewer') self.assertEqual(r.actions[0].type, 'add_role') self.assertEqual(r.actions[0].tgt_project, 'foo') self.assertEqual(r.actions[0].tgt_package, 'bar') @@ -565,6 +567,6 @@ Comment: """ self.assertTrue(len(r.get_actions('submit', 'delete', 'change_devel')) == 5) self.assertTrue(len(r.get_actions()) == 8) + if __name__ == '__main__': - import unittest unittest.main() diff --git a/tests/test_results.py b/tests/test_results.py index 384eae2b..71a74009 100644 --- a/tests/test_results.py +++ b/tests/test_results.py @@ -1,5 +1,6 @@ import os import sys +import unittest import osc.commandline @@ -7,12 +8,12 @@ from .common import GET, OscTestCase def suite(): - import unittest return unittest.defaultTestLoader.loadTestsFromTestCase(TestResults) + class TestResults(OscTestCase): def setUp(self): - OscTestCase.setUp(self, copytree=False) + super().setUp(copytree=False) def _get_fixtures_name(self): return 'results_fixtures' @@ -31,13 +32,13 @@ class TestResults(OscTestCase): @GET('http://localhost/build/testproject/_result', file='result.xml') def testPrjresults(self): out = self._run_osc('prjresults', '--xml', 'testproject') - self.assertEqualMultiline(out, self._get_fixture('result.xml')+'\n') + self.assertEqualMultiline(out, self._get_fixture('result.xml') + '\n') @GET('http://localhost/build/testproject/_result', file='result-dirty.xml') @GET('http://localhost/build/testproject/_result?oldstate=c57e2ee592dbbf26ebf19cc4f1bc1e83', file='result.xml') def testPrjresultsWatch(self): out = self._run_osc('prjresults', '--watch', '--xml', 'testproject') - self.assertEqualMultiline(out, self._get_fixture('result-dirty.xml')+'\n'+self._get_fixture('result.xml')+'\n') + self.assertEqualMultiline(out, self._get_fixture('result-dirty.xml') + '\n' + self._get_fixture('result.xml') + '\n') @GET('http://localhost/build/testproject/_result?package=python-MarkupSafe&multibuild=1&locallink=1', file='result.xml') def testResults(self): @@ -48,9 +49,8 @@ class TestResults(OscTestCase): @GET('http://localhost/build/testproject/_result?package=python-MarkupSafe&oldstate=c57e2ee592dbbf26ebf19cc4f1bc1e83&multibuild=1&locallink=1', file='result.xml') def testResultsWatch(self): out = self._run_osc('results', '--watch', '--xml', 'testproject', 'python-MarkupSafe') - self.assertEqualMultiline(out, self._get_fixture('result-dirty.xml')+self._get_fixture('result.xml')) + self.assertEqualMultiline(out, self._get_fixture('result-dirty.xml') + self._get_fixture('result.xml')) + if __name__ == '__main__': - import unittest unittest.main() - diff --git a/tests/test_revertfiles.py b/tests/test_revertfiles.py index 3248a312..fd0fba13 100644 --- a/tests/test_revertfiles.py +++ b/tests/test_revertfiles.py @@ -1,4 +1,5 @@ import os +import unittest import osc.core import osc.oscerr @@ -8,10 +9,11 @@ from .common import OscTestCase FIXTURES_DIR = os.path.join(os.path.dirname(__file__), 'revertfile_fixtures') + def suite(): - import unittest return unittest.defaultTestLoader.loadTestsFromTestCase(TestRevertFiles) + class TestRevertFiles(OscTestCase): def _get_fixtures_dir(self): return FIXTURES_DIR @@ -95,6 +97,6 @@ class TestRevertFiles(OscTestCase): self.assertTrue(os.path.exists(storefile)) self.assertFilesEqual(fname, storefile) + if __name__ == '__main__': - import unittest unittest.main() diff --git a/tests/test_setlinkrev.py b/tests/test_setlinkrev.py index 8b01b810..fb040ac8 100644 --- a/tests/test_setlinkrev.py +++ b/tests/test_setlinkrev.py @@ -1,4 +1,5 @@ import os +import unittest import osc.core import osc.oscerr @@ -8,13 +9,14 @@ from .common import GET, PUT, OscTestCase FIXTURES_DIR = os.path.join(os.path.dirname(__file__), 'setlinkrev_fixtures') + def suite(): - import unittest return unittest.defaultTestLoader.loadTestsFromTestCase(TestSetLinkRev) + class TestSetLinkRev(OscTestCase): def setUp(self): - OscTestCase.setUp(self, copytree=False) + super().setUp(copytree=False) def _get_fixtures_dir(self): return FIXTURES_DIR @@ -89,6 +91,6 @@ class TestSetLinkRev(OscTestCase): """delete non existent rev attribute from link xml""" osc.core.set_link_rev('http://localhost', 'osctest', 'simple', revision=None) + if __name__ == '__main__': - import unittest unittest.main() diff --git a/tests/test_update.py b/tests/test_update.py index f6c81a4b..846e50ae 100644 --- a/tests/test_update.py +++ b/tests/test_update.py @@ -1,5 +1,6 @@ import os import sys +import unittest import osc.core import osc.oscerr @@ -9,10 +10,11 @@ from .common import GET, OscTestCase FIXTURES_DIR = os.path.join(os.path.dirname(__file__), 'update_fixtures') + def suite(): - import unittest return unittest.defaultTestLoader.loadTestsFromTestCase(TestUpdate) + class TestUpdate(OscTestCase): def _get_fixtures_dir(self): return FIXTURES_DIR @@ -62,7 +64,7 @@ class TestUpdate(OscTestCase): @GET('http://localhost/source/osctest/simple/_meta', file='meta.xml') def testUpdateUpstreamModifiedFile(self): """a file was modified in the remote package (local file isn't modified)""" - + self._change_to_pkg('simple') osc.core.Package('.').update(rev=2) exp = 'U foo\nAt revision 2.\n' @@ -285,6 +287,6 @@ class TestUpdate(OscTestCase): self.assertFalse(os.path.exists(os.path.join('.osc', 'added'))) self._check_digests('testUpdateResumeDeletedFile_files') + if __name__ == '__main__': - import unittest unittest.main()