def compare_builds(testing_build, stable_build, untag, tag): if stable_build['package_name'] == testing_build['package_name']: if rpm.labelCompare((str(testing_build['epoch']), testing_build['version'], testing_build['release']), (str(stable_build['epoch']), stable_build['version'], stable_build['release'])) < 0: print "%s is older than %s" % (testing_build['nvr'], stable_build['nvr']) try: build = PackageBuild.byNvr(testing_build['nvr']) for update in build.updates: if update.status != 'stable': print "%s not stable in bodhi!" % update.title raise SQLObjectNotFound else: pass # TODO: do the untagging? except SQLObjectNotFound: if untag: print "Untagging via koji" koji = get_session() koji.untagBuild(tag, testing_build['nvr'], force=True) else: print "Need to untag koji build %s" % testing_build['nvr']
def compare_builds(testing_build, stable_build, untag, tag): if stable_build['package_name'] == testing_build['package_name']: if rpm.labelCompare( (str(testing_build['epoch']), testing_build['version'], testing_build['release']), (str(stable_build['epoch']), stable_build['version'], stable_build['release'])) < 0: print "%s is older than %s" % (testing_build['nvr'], stable_build['nvr']) try: build = PackageBuild.byNvr(testing_build['nvr']) for update in build.updates: if update.status != 'testing': print "%s not testing in bodhi!" % update.title raise SQLObjectNotFound else: if untag: print "Obsoleting via bodhi" update.obsolete(newer=stable_build['nvr']) else: print "Need to obsolete via bodhi" except SQLObjectNotFound: if untag: print "Untagging via koji" koji = get_session() koji.untagBuild(tag, testing_build['nvr'], force=True) else: print "Need to untag koji build %s" % testing_build['nvr']
def expire_buildroot_overrides(): """ Iterate over all of the buildroot overrides, expiring appropriately """ log.info('Running expire_buildroot_overrides job') now = datetime.utcnow() for override in BuildRootOverride.select(BuildRootOverride.q.date_expired == None): if override.expiration and now > override.expiration: log.info('Automatically expiring buildroot override: %s' % override.build) # Hack around overrides w/o a release. if not override.release: try: build = PackageBuild.byNvr(override.build) if len(build.updates): override.release = build.updates[0].release print "Fixing release for %s: %s" % (override.build, override.release.name) override.untag() override.date_expired = now else: log.error("Cannot determine release for override: %s" % override) except SQLObjectNotFound: log.error("Cannot find build for override: %s" % override) else: override.untag() override.date_expired = now log.info('expire_buildroot_overrides job complete!')
def expire_buildroot_overrides(): """ Iterate over all of the buildroot overrides, expiring appropriately """ log.info('Running expire_buildroot_overrides job') now = datetime.utcnow() for override in BuildRootOverride.select( BuildRootOverride.q.date_expired == None): if override.expiration and now > override.expiration: log.info('Automatically expiring buildroot override: %s' % override.build) # Hack around overrides w/o a release. if not override.release: try: build = PackageBuild.byNvr(override.build) if len(build.updates): override.release = build.updates[0].release print "Fixing release for %s: %s" % ( override.build, override.release.name) override.untag() override.date_expired = now else: log.error("Cannot determine release for override: %s" % override) except SQLObjectNotFound: log.error("Cannot find build for override: %s" % override) else: override.untag() override.date_expired = now log.info('expire_buildroot_overrides job complete!')
def compare_builds(testing_build, stable_build, untag, tag): if stable_build["package_name"] == testing_build["package_name"]: if ( rpm.labelCompare( (str(testing_build["epoch"]), testing_build["version"], testing_build["release"]), (str(stable_build["epoch"]), stable_build["version"], stable_build["release"]), ) < 0 ): print "%s is older than %s" % (testing_build["nvr"], stable_build["nvr"]) try: build = PackageBuild.byNvr(testing_build["nvr"]) for update in build.updates: if update.status != "testing": print "%s not testing in bodhi!" % update.title raise SQLObjectNotFound else: if untag: print "Obsoleting via bodhi" update.obsolete(newer=stable_build["nvr"]) else: print "Need to obsolete via bodhi" except SQLObjectNotFound: if untag: print "Untagging via koji" koji = get_session() koji.untagBuild(tag, testing_build["nvr"], force=True) else: print "Need to untag koji build %s" % testing_build["nvr"]
def get_build(self, nvr='TurboGears-1.0.2.2-2.fc7'): package = get_pkg('-'.join(nvr.split('-')[:-2])) package.committers = ['bobvila'] try: build = PackageBuild.byNvr(nvr) except SQLObjectNotFound: build = PackageBuild(nvr=nvr, package=package) return build
def get_build(self, nvr='TurboGears-1.0.2.2-2.fc7'): package = get_pkg('-'.join(nvr.split('-')[:-2])) package.committers = ['bobvila',] try: build = PackageBuild.byNvr(nvr) except SQLObjectNotFound: build = PackageBuild(nvr=nvr, package=package) return build
def clean_pending_tags(): """ Clean up any stray pending tags """ koji = get_session() for release in Release.select(): log.info("Finding all stray pending-testing builds...") if release.name.startswith('EL'): continue tag = release.pending_testing_tag tagged = [build['nvr'] for build in koji.listTagged(tag)] for nvr in tagged: try: build = PackageBuild.byNvr(nvr) for update in build.updates: if update.status in ('testing', 'stable', 'obsolete'): log.info("%s %s" % (nvr, update.status)) log.info("Untagging %s" % nvr) koji.untagBuild(tag, nvr, force=True) except SQLObjectNotFound: log.info("Can't find build for %s" % nvr) log.info("Untagging %s" % nvr) koji.untagBuild(tag, nvr, force=True) log.info("Finding all stray pending-stable builds...") tag = release.pending_stable_tag tagged = [build['nvr'] for build in koji.listTagged(tag)] for nvr in tagged: try: build = PackageBuild.byNvr(nvr) for update in build.updates: if update.status in ('pending', 'obsolete', 'stable'): log.info("%s %s" % (nvr, update.status)) log.info("Untagging %s" % nvr) koji.untagBuild(tag, nvr, force=True) except SQLObjectNotFound: log.info("Untagging %s" % nvr) koji.untagBuild(tag, nvr, force=True)
def clean_pending_tags(): """ Clean up any stray pending tags """ koji = get_session() for release in Release.select(): log.info("Finding all stray pending-testing builds...") if release.name.startswith('E'): continue tag = release.pending_testing_tag tagged = [build['nvr'] for build in koji.listTagged(tag)] for nvr in tagged: try: build = PackageBuild.byNvr(nvr) for update in build.updates: if update.status in ('testing', 'stable', 'obsolete'): log.info("%s %s" % (nvr, update.status)) log.info("Untagging %s" % nvr) koji.untagBuild(tag, nvr, force=True) except SQLObjectNotFound: log.info("Can't find build for %s" % nvr) log.info("Untagging %s" % nvr) koji.untagBuild(tag, nvr, force=True) log.info("Finding all stray pending-stable builds...") tag = release.pending_stable_tag tagged = [build['nvr'] for build in koji.listTagged(tag)] for nvr in tagged: try: build = PackageBuild.byNvr(nvr) for update in build.updates: if update.status in ('pending', 'obsolete', 'stable'): log.info("%s %s" % (nvr, update.status)) log.info("Untagging %s" % nvr) koji.untagBuild(tag, nvr, force=True) except SQLObjectNotFound: log.info("Untagging %s" % nvr) koji.untagBuild(tag, nvr, force=True)
def _fetch_updates(self): """ Based on our given koji tag, populate a list of PackageUpdates. """ log.debug("Fetching builds tagged with '%s'" % self.tag) kojiBuilds = self.koji.listTagged(self.tag, latest=True) nonexistent = [] log.debug("%d builds found" % len(kojiBuilds)) for build in kojiBuilds: self.builds[build['nvr']] = build try: b = PackageBuild.byNvr(build['nvr']) for update in b.updates: if update.status in ('testing', 'stable'): self.updates.add(update) except SQLObjectNotFound, e: nonexistent.append(build['nvr'])
def parse_output(out): updates = defaultdict(set) num_critpath = defaultdict(int) debug = file('bodhi.debug', 'a') deltas = [] occurrences = {} accumulative = timedelta() for line in out.split('\n'): line = line.strip() if '}' in line: continue if line: debug.write(line + '\n') title = line.split()[-1] update = None for build in title.split(','): try: update = PackageBuild.byNvr(build).updates[0] break except SQLObjectNotFound: pass #print "Cannot find update for %s" % build if update: if update.title not in updates[update.release.name]: updates[update.release.name].add(update.title) if update.critpath: num_critpath[update.release.name] += 1 for comment in update.comments: if comment.text == 'This update has been pushed to testing': for othercomment in update.comments: if othercomment.text == 'This update has been pushed to stable': delta = othercomment.timestamp - comment.timestamp deltas.append(delta) occurrences[ delta.days] = occurrences.setdefault( delta.days, 0) + 1 accumulative += delta break break debug.close() deltas.sort() return updates, num_critpath, deltas, accumulative, occurrences
def parse_output(out): updates = defaultdict(set) num_critpath = defaultdict(int) debug = file('bodhi.debug', 'a') deltas = [] occurrences = {} accumulative = timedelta() for line in out.split('\n'): line = line.strip() if '}' in line: continue if line: debug.write(line + '\n') title = line.split()[-1] update = None for build in title.split(','): try: update = PackageBuild.byNvr(build).updates[0] break except SQLObjectNotFound: pass #print "Cannot find update for %s" % build if update: if update.title not in updates[update.release.name]: updates[update.release.name].add(update.title) if update.critpath: num_critpath[update.release.name] += 1 for comment in update.comments: if comment.text == 'This update has been pushed to testing': for othercomment in update.comments: if othercomment.text == 'This update has been pushed to stable': delta = othercomment.timestamp - comment.timestamp deltas.append(delta) occurrences[delta.days] = occurrences.setdefault(delta.days, 0) + 1 accumulative += delta break break debug.close() deltas.sort() return updates, num_critpath, deltas, accumulative, occurrences
def main(): load_config() __connection__ = hub = PackageHub("bodhi") koji = get_session() tasks = [] broke = set() # Clean up any stray pending tags for release in Release.select(): print "Finding all pending-testing builds..." if release.name.startswith('EL'): continue tag = release.pending_testing_tag tagged = [build['nvr'] for build in koji.listTagged(tag)] for nvr in tagged: try: build = PackageBuild.byNvr(nvr) for update in build.updates: if update.status in ('testing', 'stable', 'obsolete'): print "%s %s" % (nvr, update.status) if '--fix' in sys.argv: print "Untagging %s" % nvr koji.untagBuild(tag, nvr, force=True) except SQLObjectNotFound: print "Can't find build for %s" % nvr if '--fix' in sys.argv: print "Untagging %s" % nvr koji.untagBuild(tag, nvr, force=True) tag = release.pending_stable_tag tagged = [build['nvr'] for build in koji.listTagged(tag)] for nvr in tagged: try: build = PackageBuild.byNvr(nvr) for update in build.updates: if update.status in ('pending', 'obsolete'): print "%s %s" % (nvr, update.status) if '--fix' in sys.argv: print "Untagging %s" % nvr koji.untagBuild(tag, nvr, force=True) except SQLObjectNotFound: print "Can't find build for %s" % nvr if '--fix' in sys.argv: print "Untagging %s" % nvr koji.untagBuild(tag, nvr, force=True) # Check for testing updates that aren't tagged properly for update in PackageUpdate.select(PackageUpdate.q.status=='testing'): dest_tag = update.release.testing_tag for build in update.builds: tags = [tag['name'] for tag in koji.listTags(build=build.nvr)] if dest_tag not in tags: print "%s marked as testing, but tagged with %s" % (build.nvr, tags) if '--fix' in sys.argv: broke.add((tags[0], dest_tag, build.nvr)) # Check all candidate updates to see if they are in a different bodhi state for release in Release.select(): tag = release.candidate_tag tagged = [build['nvr'] for build in koji.listTagged(tag, latest=True)] for nvr in tagged: try: build = PackageBuild.byNvr(nvr) for update in build.updates: if update.status in ('testing', 'stable'): print "%s %s but tagged as %s" % (nvr, update.status, tag) if '--fix' in sys.argv: dest = release.testing_tag if update.status == 'stable': dest = release.stable_tag elif update.status == 'obsolete': dest = release.candidate_tag broke.add((tag, dest, nvr)) except SQLObjectNotFound: pass # Make sure that all builds in koji tagged as an update exist # in bodhi, and are in the expect state. for release in Release.select(): for tag in (release.testing_tag, release.stable_tag): tagged = [build['nvr'] for build in koji.listTagged(tag, latest=True)] for nvr in tagged: try: build = PackageBuild.byNvr(nvr) except SQLObjectNotFound: print "PackageUpdate(%s) not found!" % nvr continue if not len(build.updates): print "PackageBuild(%s) has no updates" % (build.nvr) status = 'testing' in tag and 'testing' or 'stable' for update in build.updates: if update.status != status: print "%s is %s in bodhi but tagged as %s in koji" % ( update.title, update.status, tag) if '--fix' in sys.argv: dest = release.testing_tag if update.status == 'stable': dest = release.stable_tag elif update.status == 'obsolete': dest = release.candidate_tag for b in update.builds: broke.add((tag, dest, b.nvr)) if broke: print " ** Fixing broken tags! **" koji.multicall = True for tag, dest, build in broke: print "Moving %s from %s to %s" % (build, tag, dest) koji.moveBuild(tag, dest, build, force=True) print "Running koji.multiCall()" results = koji.multiCall() success = False print "Waiting for tasks" bad_tasks = wait_for_tasks([task[0] for task in results]) if bad_tasks == 0: success = True if success: print "Tags successfully moved!" else: print "Error moving tags!" print "bad_tasks = %r" % bad_tasks
def load_db(): print "\nLoading pickled database %s" % sys.argv[2] db = file(sys.argv[2], 'r') data = pickle.load(db) # Load up all of the overrides for override in data.get('overrides', []): try: BuildRootOverride.byBuild(override['build']) except SQLObjectNotFound: BuildRootOverride(**override) # Legacy format was just a list of update dictionaries # Now we'll pull things out into an organized dictionary: # {'updates': [], 'releases': []} if isinstance(data, dict): for release in data['releases']: try: Release.byName(release['name']) except SQLObjectNotFound: Release(**release) data = data['updates'] progress = ProgressBar(maxValue=len(data)) for u in data: try: release = Release.byName(u['release'][0]) except SQLObjectNotFound: release = Release(name=u['release'][0], long_name=u['release'][1], id_prefix=u['release'][2], dist_tag=u['release'][3]) ## Backwards compatbility request = u['request'] if u['request'] == 'move': request = 'stable' elif u['request'] == 'push': request = 'testing' elif u['request'] == 'unpush': request = 'obsolete' if u['approved'] in (True, False): u['approved'] = None if 'update_id' in u: u['updateid'] = u['update_id'] if not 'date_modified' in u: u['date_modified'] = None try: update = PackageUpdate.byTitle(u['title']) except SQLObjectNotFound: update = PackageUpdate(title=u['title'], date_submitted=u['date_submitted'], date_pushed=u['date_pushed'], date_modified=u['date_modified'], release=release, submitter=u['submitter'], updateid=u['updateid'], type=u['type'], status=u['status'], pushed=u['pushed'], notes=u['notes'], karma=u['karma'], request=request, approved=u['approved']) ## Create Package and PackageBuild objects for pkg, nvr in u['builds']: try: package = Package.byName(pkg) except SQLObjectNotFound: package = Package(name=pkg) try: build = PackageBuild.byNvr(nvr) except SQLObjectNotFound: build = PackageBuild(nvr=nvr, package=package) update.addPackageBuild(build) ## Create all Bugzilla objects for this update for bug_num, bug_title, security, parent in u['bugs']: try: bug = Bugzilla.byBz_id(bug_num) except SQLObjectNotFound: bug = Bugzilla(bz_id=bug_num, security=security, parent=parent) bug.title = bug_title update.addBugzilla(bug) ## Create all CVE objects for this update for cve_id in u['cves']: try: cve = CVE.byCve_id(cve_id) except SQLObjectNotFound: cve = CVE(cve_id=cve_id) update.addCVE(cve) for timestamp, author, text, karma, anonymous in u['comments']: comment = Comment(timestamp=timestamp, author=author, text=text, karma=karma, update=update, anonymous=anonymous) progress()
def main(): load_config() __connection__ = hub = PackageHub("bodhi") koji = get_session() tasks = [] broke = set() # Clean up any stray pending tags for release in Release.select(): print "Finding all pending-testing builds..." if release.name.startswith('EL'): continue tag = release.pending_testing_tag tagged = [build['nvr'] for build in koji.listTagged(tag)] for nvr in tagged: try: build = PackageBuild.byNvr(nvr) for update in build.updates: if update.status in ('testing', 'stable', 'obsolete'): print "%s %s" % (nvr, update.status) if '--fix' in sys.argv: print "Untagging %s" % nvr koji.untagBuild(tag, nvr, force=True) except SQLObjectNotFound: print "Can't find build for %s" % nvr if '--fix' in sys.argv: print "Untagging %s" % nvr koji.untagBuild(tag, nvr, force=True) tag = release.pending_stable_tag tagged = [build['nvr'] for build in koji.listTagged(tag)] for nvr in tagged: try: build = PackageBuild.byNvr(nvr) for update in build.updates: if update.status in ('pending', 'obsolete', 'stable'): print "%s %s" % (nvr, update.status) if '--fix' in sys.argv: print "Untagging %s" % nvr koji.untagBuild(tag, nvr, force=True) except SQLObjectNotFound: print "Can't find build for %s" % nvr if '--fix' in sys.argv: print "Untagging %s" % nvr koji.untagBuild(tag, nvr, force=True) # Check for testing updates that aren't tagged properly for update in PackageUpdate.select(PackageUpdate.q.status == 'testing'): dest_tag = update.release.testing_tag for build in update.builds: tags = [tag['name'] for tag in koji.listTags(build=build.nvr)] if dest_tag not in tags: print "%s marked as testing, but tagged with %s" % (build.nvr, tags) if '--fix' in sys.argv: broke.add((tags[0], dest_tag, build.nvr)) # Check all candidate updates to see if they are in a different bodhi state for release in Release.select(): tag = release.candidate_tag tagged = [build['nvr'] for build in koji.listTagged(tag, latest=True)] for nvr in tagged: try: build = PackageBuild.byNvr(nvr) for update in build.updates: if update.status in ('testing', 'stable'): print "%s %s but tagged as %s" % (nvr, update.status, tag) if '--fix' in sys.argv: dest = release.testing_tag if update.status == 'stable': dest = release.stable_tag elif update.status == 'obsolete': dest = release.candidate_tag broke.add((tag, dest, nvr)) except SQLObjectNotFound: pass # Make sure that all builds in koji tagged as an update exist # in bodhi, and are in the expect state. for release in Release.select(): for tag in (release.testing_tag, release.stable_tag): tagged = [ build['nvr'] for build in koji.listTagged(tag, latest=True) ] for nvr in tagged: try: build = PackageBuild.byNvr(nvr) except SQLObjectNotFound: print "PackageUpdate(%s) not found!" % nvr continue if not len(build.updates): print "PackageBuild(%s) has no updates" % (build.nvr) status = 'testing' in tag and 'testing' or 'stable' for update in build.updates: if update.status != status: print "%s is %s in bodhi but tagged as %s in koji" % ( update.title, update.status, tag) if '--fix' in sys.argv: dest = release.testing_tag if update.status == 'stable': dest = release.stable_tag elif update.status == 'obsolete': dest = release.candidate_tag for b in update.builds: broke.add((tag, dest, b.nvr)) if broke: print " ** Fixing broken tags! **" koji.multicall = True for tag, dest, build in broke: print "Moving %s from %s to %s" % (build, tag, dest) koji.moveBuild(tag, dest, build, force=True) print "Running koji.multiCall()" results = koji.multiCall() success = False print "Waiting for tasks" bad_tasks = wait_for_tasks([task[0] for task in results]) if bad_tasks == 0: success = True if success: print "Tags successfully moved!" else: print "Error moving tags!" print "bad_tasks = %r" % bad_tasks
def load_db(): print "\nLoading pickled database %s" % sys.argv[2] db = file(sys.argv[2], 'r') data = pickle.load(db) # Legacy format was just a list of update dictionaries # Now we'll pull things out into an organized dictionary: # {'updates': [], 'releases': []} if isinstance(data, dict): for release in data['releases']: try: Release.byName(release['name']) except SQLObjectNotFound: Release(**release) data = data['updates'] progress = ProgressBar(maxValue=len(data)) for u in data: try: release = Release.byName(u['release'][0]) except SQLObjectNotFound: release = Release(name=u['release'][0], long_name=u['release'][1], id_prefix=u['release'][2], dist_tag=u['release'][3]) ## Backwards compatbility request = u['request'] if u['request'] == 'move': request = 'stable' elif u['request'] == 'push': request = 'testing' elif u['request'] == 'unpush': request = 'obsolete' if u['approved'] in (True, False): u['approved'] = None if u.has_key('update_id'): u['updateid'] = u['update_id'] if not u.has_key('date_modified'): u['date_modified'] = None try: update = PackageUpdate.byTitle(u['title']) except SQLObjectNotFound: update = PackageUpdate(title=u['title'], date_submitted=u['date_submitted'], date_pushed=u['date_pushed'], date_modified=u['date_modified'], release=release, submitter=u['submitter'], updateid=u['updateid'], type=u['type'], status=u['status'], pushed=u['pushed'], notes=u['notes'], karma=u['karma'], request=request, approved=u['approved']) ## Create Package and PackageBuild objects for pkg, nvr in u['builds']: try: package = Package.byName(pkg) except SQLObjectNotFound: package = Package(name=pkg) try: build = PackageBuild.byNvr(nvr) except SQLObjectNotFound: build = PackageBuild(nvr=nvr, package=package) update.addPackageBuild(build) ## Create all Bugzilla objects for this update for bug_num, bug_title, security, parent in u['bugs']: try: bug = Bugzilla.byBz_id(bug_num) except SQLObjectNotFound: bug = Bugzilla(bz_id=bug_num, security=security, parent=parent) bug.title = bug_title update.addBugzilla(bug) ## Create all CVE objects for this update for cve_id in u['cves']: try: cve = CVE.byCve_id(cve_id) except SQLObjectNotFound: cve = CVE(cve_id=cve_id) update.addCVE(cve) for timestamp, author, text, karma, anonymous in u['comments']: comment = Comment(timestamp=timestamp, author=author, text=text, karma=karma, update=update, anonymous=anonymous) progress()
def load_db(): print "\nLoading pickled database %s" % sys.argv[2] db = file(sys.argv[2], "r") data = pickle.load(db) # Legacy format was just a list of update dictionaries # Now we'll pull things out into an organized dictionary: # {'updates': [], 'releases': []} if isinstance(data, dict): for release in data["releases"]: try: Release.byName(release["name"]) except SQLObjectNotFound: Release(**release) data = data["updates"] progress = ProgressBar(maxValue=len(data)) for u in data: try: release = Release.byName(u["release"][0]) except SQLObjectNotFound: release = Release( name=u["release"][0], long_name=u["release"][1], id_prefix=u["release"][2], dist_tag=u["release"][3] ) ## Backwards compatbility request = u["request"] if u["request"] == "move": request = "stable" elif u["request"] == "push": request = "testing" elif u["request"] == "unpush": request = "obsolete" if u["approved"] in (True, False): u["approved"] = None if u.has_key("update_id"): u["updateid"] = u["update_id"] if not u.has_key("date_modified"): u["date_modified"] = None try: update = PackageUpdate.byTitle(u["title"]) except SQLObjectNotFound: update = PackageUpdate( title=u["title"], date_submitted=u["date_submitted"], date_pushed=u["date_pushed"], date_modified=u["date_modified"], release=release, submitter=u["submitter"], updateid=u["updateid"], type=u["type"], status=u["status"], pushed=u["pushed"], notes=u["notes"], karma=u["karma"], request=request, approved=u["approved"], ) ## Create Package and PackageBuild objects for pkg, nvr in u["builds"]: try: package = Package.byName(pkg) except SQLObjectNotFound: package = Package(name=pkg) try: build = PackageBuild.byNvr(nvr) except SQLObjectNotFound: build = PackageBuild(nvr=nvr, package=package) update.addPackageBuild(build) ## Create all Bugzilla objects for this update for bug_num, bug_title, security, parent in u["bugs"]: try: bug = Bugzilla.byBz_id(bug_num) except SQLObjectNotFound: bug = Bugzilla(bz_id=bug_num, security=security, parent=parent) bug.title = bug_title update.addBugzilla(bug) ## Create all CVE objects for this update for cve_id in u["cves"]: try: cve = CVE.byCve_id(cve_id) except SQLObjectNotFound: cve = CVE(cve_id=cve_id) update.addCVE(cve) for timestamp, author, text, karma, anonymous in u["comments"]: comment = Comment( timestamp=timestamp, author=author, text=text, karma=karma, update=update, anonymous=anonymous ) progress()