Source code for libka.ironhand.ka_iron_hand

#!/usr/bin/python3
# -*- coding: utf-8 -*-
# pylint: disable=line-too-long
# kate: space-indent on; indent-width 4; replace-tabs on; indent-mode python; remove-trailing-space modified;
# vim: expandtab ts=4
# pylint: enable=line-too-long

############################################################################
#   Copyright © 2017-2024 José Manuel Santamaría Lema <panfaust@gmail.com> #
#                                                                          #
#   This program is free software; you can redistribute it and/or modify   #
#   it under the terms of the GNU General Public License as published by   #
#   the Free Software Foundation; either version 2 of the License, or      #
#   (at your option) any later version.                                    #
############################################################################

"""
This module just provides the KAIronHand class.
"""

from launchpadlib.launchpad import Launchpad

from libka.kagraph.ka_graph import KAGraph
from libka.kagraph.ka_graph_archive_build_status import KAGraphArchiveBuildStatus
from libka.kagraph.ka_graph_ppa_build_status import KAGraphPPABuildStatus
from libka.kagraph.ka_graph_proposed_migration_status import KAGraphProposedMigrationStatus

from libka.ka_data_utils import read_json_data_file
from libka.ka_data_utils import read_bd_relations_file
from libka.kubuntu_ppa import KubuntuPPA

from libka.ka_print import ka_print_good_stuff
from libka.ka_print import ka_print_info

[docs] class KAIronHand(): # pylint: disable=too-many-instance-attributes """ This class is meant to provide one or several graph types for the given release type. :param release_type: must be `"qt"`, `"frameworks"`, `"plasma"` or `"applications"` :param version: the version in `ka-metadata/versions.json` :param archive_name: it can be either `None`, `"staging"` or `"ubuntu"` - `None` will not retrieve any info from Launchpad (only use it if you just need a `build_depends` graph), - `"staging"` will retrieve information from the default staging PPA for `release_type`, - `"archive"` will retrieve information from the Ubuntu archive. :param dist: is the distribution name: focal, bionic, groovy ... """ #FIXME: ↑ and retry builds, but that's not implemented yet def __init__(self, release_type, version, archive_name, dist): #Init members self._archive_name = archive_name self._release_type = release_type self._release_type_version = version self._dist = dist self._graphs_map = {} self._graph_types_list = [] self._retry_builds = False self._retry_builds_force = False self._arch_list_str = 'any' self._pm_graph_check_excuses = False #Init these LP related members to avoid pylint warnings self._lp = None self._lpubuntu = None self._lpseries = None self._excuses_url = None self._bd_relation_map = None self._archive = None self._all_sources = None self._all_builds = None
[docs] def login(self): """ Mehod to log in into Launchpad anonymously. This is probably the first method you should call before doing anything else. """ #Print info message ka_print_info("Log in to Launchpad anonymously...") #Login into launchpad to check the status of packages self._lp = Launchpad.login_anonymously('ka-iron-hand (Kubuntu Automation)', 'production', version='devel') self._lpubuntu = self._lp.distributions["ubuntu"] self._lpseries = self._lpubuntu.getSeries(name_or_version=self._dist)
[docs] def login_auth(self): """ Method to log into Launchpad, authenticated. """ self.login() #FIXME: do the actual thing
[docs] def set_arch_list(self, arch_list_str): """ Sets the architecture list to consider. """ self._arch_list_str = arch_list_str
[docs] def set_pm_graph_check_excuses(self, enabled): """ Wether to parse the update excuses to set some package states or not. """ self._pm_graph_check_excuses = enabled
[docs] def set_excuses_url(self, url): """ URL for th update excuses web page (if it's parsing is enabled). """ self._excuses_url = url
[docs] def set_graph_types(self, graph_types_list): """ Sets the graph types to render, takes as an argument a string list with the kind of graphs to render, current supported types: * "build_depends" * "build_status" * "proposed_migration" * "retry_builds" """ self._graph_types_list = graph_types_list
[docs] def set_retry_builds(self, retry_builds, force=False): """ Determines if we should retry dep-wait/failed builds or not. """ self._retry_builds = retry_builds self._retry_builds_force = force
def _get_package_info(self): """ Gets package information to be used by execute() """ #Read the build dependencies relations map package_bd_relations_file = ("package-bd-relations/%s-%s.json" % (self._release_type, self._dist)) self._bd_relation_map = read_bd_relations_file(package_bd_relations_file, nodoc=False) #Find out the archive to work with if self._archive_name is None: return if self._archive_name == "staging": #Find out the proper ppa from release_type kppa = KubuntuPPA(self._release_type) self._archive = self._lp.people[kppa.get_user_name()].getPPAByName( name=kppa.get_ppa_name()) elif self._archive_name == "ubuntu": self._archive = self._lpubuntu.main_archive else: pass #FIXME: support for custom ppas not implemented yet #Get the source and builds info ka_print_info("Getting package information...") self._all_sources = {} self._all_builds = {} number_of_sources = len(self._bd_relation_map) i = 0 padding = len(str(number_of_sources)) for package in self._bd_relation_map: i += 1 ka_print_info("(%s of %s) Getting information for package %s" % (str(i).rjust(padding), number_of_sources, package)) status_to_check = ['Pending', 'Published'] for status in status_to_check: sources = self._archive.getPublishedSources(distro_series=self._lpseries, exact_match=True, status=status, source_name=package) self._all_sources[package] = sources if len(sources) > 0: break try: builds = sources[0].getBuilds() except IndexError: continue self._all_builds[package] = builds
[docs] def execute(self): """ Retrieves all the needed package information from Launchpad and performs all the operations to get the graphs and/or retry builds. You can access the resulting graphs with the `get_graphs` method from this class. """ #Get the package information self._get_package_info() #Retry builds if self._retry_builds: pass #TODO #Reset the graphs map self._graphs_map = {} #Render and store the graphs requested for graph_type in self._graph_types_list: ka_print_good_stuff("Rendering %s graph..." % graph_type) #Create the graph if graph_type == "build_depends": graph_title = ("%s %s - %s (build depends graph)" % (self._release_type, self._release_type_version, self._dist)) kag = KAGraph(graph_title) elif graph_type == "proposed_migration": graph_title = ("%s %s - %s (proposed migration status)" % (self._release_type, self._release_type_version, self._dist)) kag = KAGraphProposedMigrationStatus(title=graph_title, dist=self._dist) kag.set_check_excuses(self._pm_graph_check_excuses) kag.set_excuses_url(self._excuses_url) elif (graph_type == "build_status") or (graph_type == "retry_builds"): #FIXME: retry-builds if self._archive_name == "ubuntu": graph_title = "%s %s - %s (%s build status)" % ( self._release_type, self._release_type_version, self._dist, self._archive_name) kag = KAGraphArchiveBuildStatus(title=graph_title, dist=self._dist) else: graph_title = ("%s %s - %s (%s build status)" % (self._release_type, self._release_type_version, self._dist, self._archive_name)) kag = KAGraphPPABuildStatus(title=graph_title, dist=self._dist) else: raise Exception("Graph type %s not supported" % graph_type) #Set expected version and list for different versions kag.set_expected_version(self._release_type_version) diff_versions_map = read_json_data_file('different-versions.json') try: diff_versions_list = diff_versions_map[self._release_type] except KeyError: diff_versions_list = [] kag.set_different_versions(diff_versions_list) #Populate graph with nodes and edges kag.populate_from_bd_relations_map(self._bd_relation_map) #Set the arch list kag.set_arch_list(self._arch_list_str) #Set the status of the nodes with the info from LP if graph_type != "build_depends": if kag.__class__.__name__ == "KAGraphPPABuildStatus": kag.set_package_status_from_lp_sources_and_builds( self._all_sources, self._all_builds) else: kag.set_package_status_from_lp_sources_and_builds( self._all_sources, self._all_builds, self._lpseries) #Add legend kag.add_legend() #Final graph settings... kag.update_timestamp() kag.transitive_reduction() #Store the graph for retrieving it later self._graphs_map[graph_type] = kag
[docs] def get_graphs(self): """ Returns a hashmap of KAGraph's indexed by type of graph. """ return self._graphs_map