From 6fea8fb54244ab3a247de2e11794d2d3cc55cc9e Mon Sep 17 00:00:00 2001 From: "Ursula Junque (Ursinha)" Date: Sun, 30 Apr 2017 20:02:06 +0200 Subject: [PATCH] Fix behavior of getBinaryPackage in lpapicache It was using the same parameters to get Source and Binary packages build history, but source packages need a distro series, and binary packages need distro arch series, as the results are arch dependent. Signed-off-by: Mattia Rizzolo --- ubuntutools/lp/lpapicache.py | 84 ++++++++++++++++++++++++++++----- ubuntutools/lp/udtexceptions.py | 4 ++ 2 files changed, 77 insertions(+), 11 deletions(-) diff --git a/ubuntutools/lp/lpapicache.py b/ubuntutools/lp/lpapicache.py index 15b63bc..13fb2f4 100644 --- a/ubuntutools/lp/lpapicache.py +++ b/ubuntutools/lp/lpapicache.py @@ -58,6 +58,7 @@ from lazr.restfulclient.resource import Entry from ubuntutools.lp import (service, api_version) from ubuntutools.lp.udtexceptions import (AlreadyLoggedInError, ArchiveNotFoundException, + ArchSeriesNotFoundException, PackageNotFoundException, PocketDoesNotExistError, SeriesNotFoundException) @@ -288,12 +289,40 @@ class Distribution(BaseWrapper): return dev +class DistroArchSeries(BaseWrapper): + ''' + Wrapper class around a LP distro arch series object. + ''' + resource_type = 'distro_arch_series' + + class DistroSeries(BaseWrapper): ''' Wrapper class around a LP distro series object. ''' resource_type = 'distro_series' + def __init__(self, *args): + if "_architectures" not in self.__dict__: + self._architectures = dict() + + def getArchSeries(self, archtag): + ''' + Returns a DistroArchSeries object for an architecture passed by name + (e.g. 'amd64'). + If the architecture is not found: raise ArchSeriesNotFoundException. + ''' + if archtag not in self._architectures: + try: + architecture = DistroArchSeries( + self().getDistroArchSeries(archtag=archtag)) + self._architectures[architecture.architecture_tag] = ( + architecture) + except HTTPError: + message = "Architecture %s is unknown." % archtag + raise ArchSeriesNotFoundException(message) + return self._architectures[archtag] + class Archive(BaseWrapper): ''' @@ -327,11 +356,11 @@ class Archive(BaseWrapper): name_key='source_name', wrapper=SourcePackagePublishingHistory) - def getBinaryPackage(self, name, series=None, pocket=None): + def getBinaryPackage(self, name, archtag=None, series=None, pocket=None): ''' Returns a BinaryPackagePublishingHistory object for the most - recent source package in the distribution 'dist', series and - pocket. + recent source package in the distribution 'dist', architecture + 'archtag', series and pocket. series defaults to the current development series if not specified. @@ -341,13 +370,16 @@ class Archive(BaseWrapper): If the requested binary package doesn't exist a PackageNotFoundException is raised. ''' - return self._getPublishedItem(name, series, pocket, cache=self._binpkgs, + if archtag is None: + archtag = [] + return self._getPublishedItem(name, series, pocket, archtag=archtag, + cache=self._binpkgs, function='getPublishedBinaries', name_key='binary_name', wrapper=BinaryPackagePublishingHistory) - def _getPublishedItem(self, name, series, pocket, cache, function, name_key, - wrapper): + def _getPublishedItem(self, name, series, pocket, cache, + function, name_key, wrapper, archtag=None): '''Common code between getSourcePackage and getBinaryPackage ''' if pocket is None: @@ -363,21 +395,38 @@ class Archive(BaseWrapper): pocket) dist = Distribution(self.distribution_link) - # Check if series is already a DistoSeries object or not + # Check if series is already a DistroSeries object or not if not isinstance(series, DistroSeries): if series: series = dist.getSeries(series) else: series = dist.getDevelopmentSeries() - index = (name, series.name, pockets) + # getPublishedSources requires a distro_series, while + # getPublishedBinaries requires a distro_arch_series. + # If archtag is not None, I'll assume it's getPublishedBinaries. + if archtag is not None and archtag != []: + if not isinstance(archtag, DistroArchSeries): + arch_series = series.getArchSeries(archtag=archtag) + else: + arch_series = archtag + + if archtag is not None and archtag != []: + index = (name, series.name, archtag, pockets) + else: + index = (name, series.name, pockets) + if index not in cache: params = { name_key: name, - 'distro_series': series(), 'status': 'Published', 'exact_match': True, } + if archtag is not None and archtag != []: + params['distro_arch_series'] = arch_series() + else: + params['distro_series'] = series() + if len(pockets) == 1: params['pocket'] = list(pockets)[0] @@ -398,8 +447,10 @@ class Archive(BaseWrapper): package_type = "source package" else: package_type = "package" - msg = "The %s '%s' does not exist in the %s %s archive" % \ - (package_type, name, dist.display_name, self.name) + msg = ("The %s '%s' does not exist in the %s %s archive" % + (package_type, name, dist.display_name, self.name)) + if archtag is not None and archtag != []: + msg += " for architecture %s" % archtag pockets = [series.name if pocket == 'Release' else '%s-%s' % (series.name, pocket.lower()) for pocket in pockets] @@ -640,6 +691,17 @@ class BinaryPackagePublishingHistory(BaseWrapper): ''' return self._lpobject.component_name + def binaryFileUrls(self): + ''' + Return the URL for this binary publication's files. + Only available in the devel API, not 1.0 + ''' + try: + return self._lpobject.binaryFileUrls() + except AttributeError: + raise AttributeError("binaryFileUrls can only be found in lpapi " + "devel, not 1.0. Login using devel to have it.") + class MetaPersonTeam(MetaWrapper): @property diff --git a/ubuntutools/lp/udtexceptions.py b/ubuntutools/lp/udtexceptions.py index 9ad9c2e..2de23cd 100644 --- a/ubuntutools/lp/udtexceptions.py +++ b/ubuntutools/lp/udtexceptions.py @@ -17,3 +17,7 @@ class ArchiveNotFoundException(BaseException): class AlreadyLoggedInError(Exception): '''Raised when a second login is attempted.''' pass + +class ArchSeriesNotFoundException(BaseException): + """Thrown when a distroarchseries is not found.""" + pass