DistroSeries ============ From the DerivationOverview spec : A distribution of GNU/Linux comprises a set of packages, an installer, possibly a live-CD, some amount of metadata associated with the arrangement of those elements and also a lot of information on managing it. A distro series is a given version of a distribution. So, for Ubuntu, there are releases (or planned releases) like "warty", "hoary" and "bendy". Distro releases are retrieved with the IDistroSeriesSet utility, much like people are retrieved with the IPersonSet utility, or bug tasks are retrieved with the IBugTaskSet utility. The IDistroSeriesSet utility is accessed in the usual fashion: >>> from zope.component import getUtility >>> from canonical.database.sqlbase import flush_database_updates >>> from canonical.launchpad.webapp.testing import verifyObject >>> from lp.registry.interfaces.distribution import IDistributionSet >>> from lp.registry.interfaces.distroseries import ( ... IDistroSeries, ... IDistroSeriesSet, ... ) >>> from lp.translations.interfaces.hastranslationimports import ( ... IHasTranslationImports) >>> distroseriesset = getUtility(IDistroSeriesSet) To retrieve a specific release of a distribution, use IDistroSeriesSet.get: >>> warty = distroseriesset.get(1) >>> print warty.name warty >>> print warty.fullseriesname Ubuntu Warty Or IDistroSeriesSet.findByName: >>> for distroseries in distroseriesset.findByName("warty"): ... print distroseries.name warty To get one specific release by name, use queryByName: >>> ubuntu = getUtility(IDistributionSet).getByName("ubuntu") >>> warty = distroseriesset.queryByName(ubuntu, "warty") >>> warty.name u'warty' If the release by that name doesn't exist, None will be returned: >>> foobar = distroseriesset.queryByName(ubuntu, "foobar") >>> print foobar None Or IDistroSeriesSet.findByVersion: >>> for distroseries in distroseriesset.findByVersion("5.04"): ... print distroseries.name hoary We verify that a distroseries does in fact fully provide IDistroSeries: >>> verifyObject(IDistroSeries, warty) True >>> IDistroSeries.providedBy(warty) True And IHasTranslationImports: >>> verifyObject(IHasTranslationImports, warty) True >>> IHasTranslationImports.providedBy(warty) True To search the set of IDistroSeriess, use IDistroSeriesSet.search: >>> ubuntu_releases = distroseriesset.search( ... distribution=ubuntu, isreleased=True, orderBy="-datereleased") >>> [release.name for release in ubuntu_releases] [u'warty'] >>> all_ubuntu_releases = distroseriesset.search(distribution=ubuntu) >>> all_ubuntu_releases.count() 4 Distroseries identifying attributes ----------------------------------- A distroseries has a set of attributes that identify it. The launchpad id is the name attribute. >>> print warty.name warty It has a title for heading and titles... >>> print warty.title The Warty Warthog Release And a displayname for referring to it in a sentence. >>> print warty.displayname Warty The fullseriesname attribute is used when the context of the series name can be confused. Note that the value is created from the launchpad id names of the distribution and the series, though it may look like the displayname attributes were used. >>> print warty.fullseriesname Ubuntu Warty The version attribute holds the debversion of the series. >>> print warty.version 4.10 The named_version attribute is used is used to present the series displayname and version values consistently. >>> print warty.named_version Warty (4.10) Published sources ----------------- DistroSeries.getPublishedSources: >>> from lp.registry.model.distroseries import DistroSeries >>> from lp.registry.model.sourcepackagename import SourcePackageName >>> warty2 = DistroSeries.get(1) Passing a ISourcePackageName as argument: >>> prs = warty2.getPublishedSources( ... SourcePackageName.byName('mozilla-firefox')) >>> print prs.count() 1 >>> print prs[0].sourcepackagerelease.sourcepackagename.name mozilla-firefox Passing a string name: >>> print warty2.getPublishedSources('mozilla-firefox').count() 1 Including pending publication records in the result: >>> print warty2.getPublishedSources('mozilla-firefox', ... include_pending=True).count() 2 Not found as empty list: >>> print warty2.getPublishedSources('nosuchpackage').count() 0 See distroseries-publishing-lookups.txt for more information. canUploadToPocket method helps us to decide if an upload is allowed or not, according the distroseries status and the upload target pocket. >>> from lp.registry.interfaces.distribution import IDistributionSet >>> ubuntu = getUtility(IDistributionSet)['ubuntu'] >>> breezy_autotest = ubuntu['breezy-autotest'] >>> hoary = ubuntu['hoary'] >>> from lp.registry.interfaces.pocket import PackagePublishingPocket >>> from lp.registry.interfaces.series import SeriesStatus >>> warty.status.name 'CURRENT' >>> warty.canUploadToPocket(PackagePublishingPocket.RELEASE) False >>> warty.canUploadToPocket(PackagePublishingPocket.SECURITY) True >>> breezy_autotest.status.name 'EXPERIMENTAL' >>> breezy_autotest.canUploadToPocket(PackagePublishingPocket.RELEASE) True >>> breezy_autotest.canUploadToPocket(PackagePublishingPocket.SECURITY) False The FROZEN status is special. Uploads are allowed for all pockets as the upload will have to wait for manual approval anyway: >>> from zope.security.proxy import removeSecurityProxy >>> removeSecurityProxy(hoary).status = SeriesStatus.FROZEN >>> hoary.status.name 'FROZEN' >>> hoary.canUploadToPocket(PackagePublishingPocket.RELEASE) True >>> hoary.canUploadToPocket(PackagePublishingPocket.SECURITY) True Package searching ----------------- You can search through binary packages publishing in a distribution release by using the searchPackages method, which uses magical fti: >>> warty.searchPackages("pmount").count() 1 This also works for small or weirdly named packages that don't work through fti, and even for substrings: >>> warty.searchPackages("linux-2.6.12").count() 1 >>> warty.searchPackages("at").count() 1 >>> pkgs = warty.searchPackages('a') >>> for dsbp in pkgs: ... print "%s: %s" % (dsbp.__class__.__name__, dsbp.name) DistroSeriesBinaryPackage: foobar DistroSeriesBinaryPackage: mozilla-firefox DistroSeriesBinaryPackage: at DistroSeriess have components and sections ------------------------------------------ A distroseries has some number of components and/or sections which are valid for that distroseries. These selections are used by (among other things) the uploader for validating incoming uploads. >>> hoary = distroseriesset.get(3) >>> for c in hoary.components: ... print c.name main restricted >>> for s in hoary.sections: ... print s.name base web editors admin devel translations >>> from lp.soyuz.interfaces.component import IComponentSet >>> from lp.soyuz.interfaces.section import ISectionSet >>> python = getUtility(ISectionSet).ensure('python') >>> hoary.addSection(python) >>> for c in hoary.components: ... print c.name main restricted >>> for s in hoary.sections: ... print s.name base web editors admin devel python translations Breezy-autotest has got a partner component, which is not reported: >>> breezyautotest = distroseriesset.queryByName( ... ubuntu, "breezy-autotest") >>> for c in breezyautotest.components: ... print c.name main restricted universe multiverse The upload_components property, however, reports all the available components since partner is allowed for upload: >>> for c in breezyautotest.upload_components: ... print c.name main restricted universe multiverse partner DistroSeries can be initialized from their parents -------------------------------------------------- When a distroseries is derived from another distroseries (be it a derivative distribution, or simply the next release in a sequence from Ubuntu) we need to initialize the new release with quite a lot of information. Not least of which is the section and component selections and the publishing information for the distroseries. DistroSeries provides us with a method for doing this which carefully goes behind the back of sqlobject to copy potentially tens of thousands of rows around in order to set up a distroseries. IDistroSeries lists a series of preconditions for performing an initialization. In particular the initializer won't overwrite publishing records etc. Essentially this is a "Do not push this button again" type set of assertions. >>> from lp.soyuz.scripts.initialize_distroseries import ( ... InitializeDistroSeries) >>> login("foo.bar@canonical.com") >>> humpy = ubuntu.newSeries('humpy', 'Humpy Hippo', ... 'The Humpy Hippo', 'Fat', 'Yo Momma', ... '99.2', None, hoary.owner) >>> humpy.previous_series = hoary >>> ids = InitializeDistroSeries(humpy, [hoary.id]) >>> ids.initialize() >>> hoary.getPublishedSources('pmount').count() 1 >>> humpy.getPublishedSources('pmount').count() 1 >>> len(hoary['i386'].getReleasedPackages('pmount')) 1 >>> len(humpy['i386'].getReleasedPackages('pmount')) 1 Check if the attributes of an DRSPR instance for the just initialized distroseries are sane. A DRSPR instance should filter attributes of a SPR according the distroseries in question (practically according what is published in this distrorelelase) Since the initialize-from-parent procedure copies the latest publications from the parent IDRSPR.builds should be empty, reflecting that there are no builds for this SPR in this DistroSeries. IDRSPR.builds will be non-empty after a developer submits a new SPR for the DistroSeries. In other hand IDRSPR.binaries should return the binaries resulted of the SPRs inheritance by joining BPP->BPR->BUILD->SPR, i.e, binaries published in this distroseries (in fact, in one of its architectures) resulted of the sourcepackagerelease in question, but built anywhere. (fix bug #52938) Initialize a new distroseries based on warty (since it has, at least one coherent published source + binary, mozilla-firefox) >>> bumpy = ubuntu.newSeries('bumpy', 'Bumpy', ... 'The Bumpy', 'Fat', 'Boom', ... '99.3', None, warty.owner) >>> bumpy.previous_series = warty >>> ids = InitializeDistroSeries(bumpy, [warty.id]) >>> ids.initialize() Build a new ISourcePackage based in the new distroseries: >>> bumpy_firefox_sp = bumpy.getSourcePackage('mozilla-firefox') Check the content IDRSPR binaries & builds attributes: 'binaries' should be inherited from parent release. >>> bumpy_firefox_sp.currentrelease.binaries.count() 3 >>> for bin in bumpy_firefox_sp.currentrelease.binaries: ... print bin.id, bin.title, bin.build.distro_arch_series.title 27 mozilla-firefox-data-0.9 The Warty Warthog Release for i386 (x86) 26 mozilla-firefox-0.9 The Warty Warthog Release for hppa (hppa) 12 mozilla-firefox-0.9 The Warty Warthog Release for i386 (x86) 'builds' should be empty since it was built in parent (warty), not in this distroseries (bumby. >>> len(bumpy_firefox_sp.currentrelease.builds) 0 the SPR returns all build records for it. >>> bumpy_firefox_sp.currentrelease.sourcepackagerelease.builds.count() 4 The new series also has the same packaging links as its parent series. >>> for packaging in warty.packagings: ... print packaging.sourcepackagename.name a52dec alsa-utils evolution mozilla-firefox netapplet >>> for packaging in bumpy.packagings: ... print packaging.sourcepackagename.name a52dec alsa-utils evolution mozilla-firefox netapplet Translatable Packages and Packaging ----------------------------------- You can easily find out what packages are translatable in a distribution release: >>> translatables = hoary.getTranslatableSourcePackages() >>> for translatable in translatables: ... print translatable.name evolution mozilla pmount Packages can be linked to upstream productseries in specific distribution releases. IDistroSeries offers a way to query translatable packages that are linked to upstream productseries. >>> unlinked_translatables = hoary.getUnlinkedTranslatableSourcePackages() >>> for translatable in unlinked_translatables: ... print translatable.name pmount mozilla The links to upstream product series can be verified using the packagings property: >>> packagings = hoary.packagings >>> for packaging in packagings: ... print packaging.sourcepackagename.name, \ ... packaging.productseries.product.displayname evolution Evolution mozilla-firefox Mozilla Firefox netapplet NetApplet From the results above you can notice that neither mozilla-firefox nor netapplet are translatable in Hoary. Packages that need linking and packagings that need upstream information ----------------------------------------------------------------------- The distroseries getPrioritizedUnlinkedSourcePackages() method returns a prioritized list of `ISourcePackage` objects that need a packaging link to an `IProductSeries` to provide the the upstream information to share bugs, translations, and code. Each item in the list is a dict with the 'package', total_bugs, and total_messages (translatable messages). >>> for summary in hoary.getPrioritizedUnlinkedSourcePackages(): ... print summary['package'].name ... print '%(bug_count)s %(total_messages)s' % summary pmount 0 64 alsa-utils 0 0 cnews 0 0 libstdc++ 0 0 linux-source-2.6.15 0 0 The distroseries getPrioritizedPackagings() method that returns a prioritized list of `IPackaging` that need more information about the upstream project to share bugs, translations, and code. >>> for packaging in hoary.getPrioritizedPackagings(): ... print packaging.sourcepackagename.name netapplet evolution Most recently linked packagings ------------------------------- The distroseries getMostRecentlyLinkedPackagings() method returns a list of up to five packages that are the most recently linked to an upstream. >>> distribution = factory.makeDistribution() >>> distroseries = factory.makeDistroSeries(distribution=distribution) >>> pkgs = distroseries.getMostRecentlyLinkedPackagings() >>> print pkgs.count() 0 >>> for name in ['aaron', 'bjorn', 'chex', 'deryck', 'edwin', 'francis']: ... product = factory.makeProduct(name=name) ... productseries = factory.makeProductSeries(product=product) ... spn = factory.makeSourcePackageName(name=name) ... package = factory.makeSourcePackage(sourcepackagename=spn, ... distroseries=distroseries) ... package.setPackaging(productseries, product.owner) ... transaction.commit() >>> pkgs = distroseries.getMostRecentlyLinkedPackagings() >>> for packaging in pkgs: ... print packaging.sourcepackagename.name francis edwin deryck chex bjorn DistroSeries can build meta objects for packages ------------------------------------------------ >>> from lp.registry.interfaces.sourcepackage import ISourcePackage >>> from lp.soyuz.interfaces.distroseriesbinarypackage import IDistroSeriesBinaryPackage >>> from lp.soyuz.interfaces.distroseriessourcepackagerelease import IDistroSeriesSourcePackageRelease >>> pmount_src_name = SourcePackageName.byName('pmount') >>> pmount_source = hoary.getSourcePackage(pmount_src_name) >>> ISourcePackage.providedBy(pmount_source) True >>> from lp.soyuz.model.binarypackagename import ( ... BinaryPackageName) >>> pmount_bin_name = BinaryPackageName.byName('pmount') >>> pmount_drbp = hoary.getBinaryPackage(pmount_bin_name) >>> IDistroSeriesBinaryPackage.providedBy(pmount_drbp) True >>> len(pmount_drbp.current_publishings) 3 >>> from lp.soyuz.model.sourcepackagerelease import ( ... SourcePackageRelease) >>> pmount_rel = SourcePackageRelease.selectOneBy( ... sourcepackagenameID=pmount_src_name.id, version='0.1-1') >>> pmount_rel.sourcepackagename.name u'pmount' >>> pmount_srcrel = hoary.getSourcePackageRelease(pmount_rel) >>> IDistroSeriesSourcePackageRelease.providedBy(pmount_srcrel) True Check some properties of DRSPR meta class Entire publishing history: >>> pmount_srcrel.publishing_history.count() 1 Most recent published history row: >>> pmount_srcrel.current_published is None True >>> netapplet_srcrel = hoary.getSourcePackage('netapplet').currentrelease >>> spph = netapplet_srcrel.current_published >>> spph.section.name u'web' The changesfile attribute contains the package changelog. It is provided as an ILibraryFileAlias: >>> firefox_srcrel = warty.getSourcePackage( ... 'mozilla-firefox').currentrelease >>> print firefox_srcrel.title "mozilla-firefox" 0.9 source package in The Warty Warthog Release >>> firefox_srcrel.changesfile If the package changelog is not available, that attribute is None: >>> netapplet_srcrel.changesfile is None True Perform `post publication` override: >>> new_section = getUtility(ISectionSet)['base'] >>> override = netapplet_srcrel.current_published.changeOverride( ... new_section=new_section) >>> override.section == new_section True >>> print override.status.name PENDING >>> netapplet_srcrel.publishing_history.count() 2 Override information about 'pmount' is pending publication: >>> print netapplet_srcrel.current_published.status.name PENDING >>> print netapplet_srcrel.current_published.section.name base Supersede previous netapplet publication: >>> last_published = netapplet_srcrel.publishing_history[1] >>> last_published.supersede() >>> flush_database_updates() >>> netapplet_srcrel.publishing_history.count() 2 >>> print last_published.status.name SUPERSEDED >>> from canonical.database.sqlbase import get_transaction_timestamp >>> last_published.datesuperseded == get_transaction_timestamp() True SourcePackagePublishingHistory ------------------------------ IDistroSeries.getSourcePackagePublishing returns all the ISPPH records for a given status in a given pocket. It makes easy to generate a list of currently published sources for override-check, for instance. it can also be used to generate the archive packages list in the future. >>> ubuntu = getUtility(IDistributionSet)['ubuntu'] >>> hoary = ubuntu['hoary'] >>> from lp.soyuz.enums import PackagePublishingStatus >>> hoary_pub_sources = hoary.getSourcePackagePublishing( ... PackagePublishingStatus.PUBLISHED, ... PackagePublishingPocket.RELEASE) >>> hoary_pub_sources.count() 6 >>> for pub in hoary_pub_sources: ... print pub.displayname alsa-utils 1.0.9a-4ubuntu1 in hoary cnews cr.g7-37 in hoary evolution 1.0 in hoary libstdc++ b8p in hoary linux-source-2.6.15 2.6.15.3 in hoary pmount 0.1-2 in hoary >>> hoary_pub_source = hoary_pub_sources[0] >>> hoary_pub_source.sourcepackagerelease.name u'alsa-utils' >>> hoary_pub_source.sourcepackagerelease.version u'1.0.9a-4ubuntu1' >>> hoary_pub_source.component.name u'main' >>> hoary_pub_source.section.name u'base' >>> hoary.getSourcePackagePublishing( ... PackagePublishingStatus.PUBLISHED, ... PackagePublishingPocket.UPDATES).count() 0 This method also allow us to restrict the results to a given component: >>> component_main = getUtility(IComponentSet)['main'] >>> hoary.getSourcePackagePublishing( ... PackagePublishingStatus.PUBLISHED, ... PackagePublishingPocket.RELEASE, ... component=component_main).count() 5 >>> component_multiverse = getUtility(IComponentSet)['multiverse'] >>> hoary.getSourcePackagePublishing( ... PackagePublishingStatus.PUBLISHED, ... PackagePublishingPocket.RELEASE, ... component=component_multiverse).count() 0 By default the IDistribution 'main_archive' is considered, but It also allows the callsite to specify one and then the result will be restricted to it. >>> debian_archive = getUtility(IDistributionSet)['debian'].main_archive >>> print debian_archive.purpose.title Primary Archive >>> hoary.getSourcePackagePublishing( ... PackagePublishingStatus.PUBLISHED, ... PackagePublishingPocket.RELEASE, ... component=component_main, archive=debian_archive).count() 0 ISPP.getPublishedBinaries returns all the binaries generated by the publication in question: >>> warty = ubuntu['warty'] >>> warty_pub_sources = warty.getSourcePackagePublishing( ... PackagePublishingStatus.PUBLISHED, ... PackagePublishingPocket.RELEASE) >>> warty_pub_source = warty_pub_sources[4] >>> warty_pub_source.sourcepackagerelease.name u'mozilla-firefox' >>> warty_pub_source.sourcepackagerelease.version u'0.9' >>> warty_pub_source.component.name u'main' >>> warty_pub_source.section.name u'web' >>> warty_mozilla_pub_binaries = warty_pub_source.getPublishedBinaries() >>> len(warty_mozilla_pub_binaries) 4 >>> warty_mozilla_pub_bin = warty_mozilla_pub_binaries[0] >>> from lp.soyuz.interfaces.publishing import IBinaryPackagePublishingHistory >>> verifyObject(IBinaryPackagePublishingHistory, warty_mozilla_pub_bin) True >>> warty_mozilla_pub_bin.binarypackagerelease.name u'mozilla-firefox' >>> warty_mozilla_pub_bin.binarypackagerelease.version u'0.9' >>> warty_mozilla_pub_bin.component.name u'main' >>> warty_mozilla_pub_bin.section.name u'base' DistroSeries.getBinaryPackagePublishing will return BinaryPackagePublishingHistory objects for the DistroSeries: >>> warty = ubuntu['warty'] >>> bpphs = warty.getBinaryPackagePublishing() >>> bpphs.count() 10 >>> 'mozilla-firefox' in set( ... pkgpub.binarypackagerelease.binarypackagename.name ... for pkgpub in bpphs) True It also allows us to pass wanted strings like: name, version, archtag and sourcename. >>> warty.getBinaryPackagePublishing( ... name="nosuchpackage").count() 0 >>> warty.getBinaryPackagePublishing( ... version="nosuchversion").count() 0 >>> warty.getBinaryPackagePublishing( ... archtag="nosucharch").count() 0 >>> warty.getBinaryPackagePublishing( ... sourcename="nosuchsource").count() 0 We can restrict the results by component: >>> warty.getBinaryPackagePublishing( ... component=component_main).count() 10 >>> warty.getBinaryPackagePublishing( ... component=component_multiverse).count() 0 By pocket: >>> warty.getBinaryPackagePublishing( ... pocket=PackagePublishingPocket.RELEASE).count() 10 >>> warty.getBinaryPackagePublishing( ... pocket=PackagePublishingPocket.BACKPORTS).count() 0 Or any combination of them: >>> warty.getBinaryPackagePublishing( ... sourcename="alsa", pocket=PackagePublishingPocket.RELEASE, ... component=component_main).count() 0 >>> warty.getBinaryPackagePublishing( ... name="mozilla-firefox", archtag='i386', ... component=component_main).count() 2 As getSourcePackagePublishing, getBinaryPublishing accepts 'archive' parameter for result restriction: >>> warty.getBinaryPackagePublishing( ... name="mozilla-firefox", archtag='i386', ... component=component_main, archive=debian_archive).count() 0 getAllPublishedSources will return all publications with status PUBLISHED and in the main archives for this distroseries: >>> sources = warty.getAllPublishedSources() >>> for source in sources: ... print( ... source.sourcepackagerelease.sourcepackagename.name, ... source.sourcepackagerelease.version) (u'netapplet', u'0.99.6-1') (u'alsa-utils', u'1.0.8-1ubuntu1') (u'alsa-utils', u'1.0.9a-4') (u'mozilla-firefox', u'0.9') (u'cdrkit', u'1.0') (u'iceweasel', u'1.0') Similarly for binary publications: >>> binaries = warty.getAllPublishedBinaries() >>> for binary in binaries: ... print( ... binary.binarypackagerelease.binarypackagename.name, ... binary.binarypackagerelease.version) (u'mozilla-firefox', u'0.9') (u'pmount', u'0.1-1') (u'linux-2.6.12', u'2.6.12.20') (u'pmount', u'2:1.9-1') (u'at', u'3.14156') (u'cdrkit', u'1.0') (u'mozilla-firefox', u'1.0') (u'mozilla-firefox', u'0.9') (u'mozilla-firefox-data', u'0.9') (u'mozilla-firefox-data', u'0.9') Creating DistroSeries --------------------- Users with launchpad.Driver permission may create DistroSeries. In the case of an `IDerivativeDistribution` A user who is a driver can create the series and he is automatically assigned to the series' driver role so that he can edit it. >>> youbuntu = factory.makeDistribution(name='youbuntu') >>> yo_driver = factory.makePerson(name='yo-driver') >>> youbuntu.driver = yo_driver >>> login_person(yo_driver) >>> youbuntu.full_functionality False >>> yo_series = youbuntu.newSeries( ... name='island', displayname='Island', title='YouBuntu Island', ... summary='summary', description='description', version='09.07', ... previous_series=warty, registrant=yo_driver) >>> print yo_series.name island >>> print yo_series.registrant.name yo-driver >>> print yo_series.driver.name yo-driver Owners of derivative distributions, and admins can create series too, but they are not automatically set as the series driver because they always have permission to edit the series. >>> login_person(youbuntu.owner) >>> yo_series = youbuntu.newSeries( ... name='forest', displayname='Forest', title='YouBuntu Forest', ... summary='summary', description='description', version='09.07', ... previous_series=warty, registrant=youbuntu.owner) >>> print yo_series.name forest >>> print yo_series.driver None Ubuntu is an `IBaseDistribution` which requires special preparation for Soyuz and Translations before a series can be created. Ubuntu driver can not create series. >>> login_person(ubuntu.owner.activemembers[0]) >>> ubuntu.driver = yo_driver >>> login_person(yo_driver) >>> ubuntu.newSeries( ... name='finch', displayname='Finch', title='Ubuntu Finch', ... summary='summary', description='description', version='9.06', ... previous_series=warty, owner=ubuntu.driver) Traceback (most recent call last): ... Unauthorized: ... Owners and admins of base distributions are the only users who can create a series. >>> login_person(ubuntu.owner.activemembers[0]) >>> u_series = ubuntu.newSeries( ... name='finch', displayname='Finch', title='Ubuntu Finch', ... summary='summary', description='description', version='9.06', ... previous_series=warty, registrant=ubuntu.owner) >>> print u_series.name finch >>> print u_series.registrant.name ubuntu-team >>> print u_series.driver None Specification Listings ---------------------- We should be able to get lists of specifications in different states related to a distroseries. Basically, we can filter by completeness, and by whether or not the spec is informational. >>> distroset = getUtility(IDistributionSet) >>> kubuntu = distroset.getByName("kubuntu") >>> krunch = kubuntu.getSeries("krunch") >>> from lp.blueprints.enums import SpecificationFilter First, there should be one informational specs for krunch: >>> filter = [SpecificationFilter.INFORMATIONAL] >>> krunch.specifications(filter=filter).count() 1 There are 2 completed specs for Krunch: >>> filter = [SpecificationFilter.COMPLETE] >>> for spec in kubuntu.specifications(filter=filter): ... print spec.name, spec.is_complete thinclient-local-devices True usplash-on-hibernation True And there are 2 incomplete specs: >>> filter = [SpecificationFilter.INCOMPLETE] >>> for spec in krunch.specifications(filter=filter): ... print spec.name, spec.is_complete cluster-installation False revu False If we ask for all specs, we get them in the order of priority. >>> filter = [SpecificationFilter.ALL] >>> for spec in krunch.specifications(filter=filter): ... print spec.priority.title, spec.name Essential cluster-installation High revu Medium thinclient-local-devices Low usplash-on-hibernation Undefined kde-desktopfile-langpacks Not krunch-desktop-plan With a distroseries, we can ask for ACCEPTED, PROPOSED and DECLINED specs: >>> filter=[SpecificationFilter.ACCEPTED] >>> for spec in krunch.specifications(filter=filter): ... print spec.name, spec.goalstatus.title cluster-installation Accepted revu Accepted thinclient-local-devices Accepted usplash-on-hibernation Accepted >>> filter=[SpecificationFilter.PROPOSED] >>> for spec in krunch.specifications(filter=filter): ... print spec.name, spec.goalstatus.title kde-desktopfile-langpacks Proposed >>> filter=[SpecificationFilter.DECLINED] >>> for spec in krunch.specifications(filter=filter): ... print spec.name, spec.goalstatus.title krunch-desktop-plan Declined And if we ask just for specs, we get BOTH the incomplete and the complete ones that have been accepted. >>> for spec in krunch.specifications(): ... print spec.name, spec.is_complete, spec.goalstatus.title cluster-installation False Accepted revu False Accepted thinclient-local-devices True Accepted usplash-on-hibernation True Accepted We can filter for specifications that contain specific text: >>> for spec in krunch.specifications(filter=['usb']): ... print spec.name thinclient-local-devices Drivers ======= Distributions have drivers, who are people that have permission to approve bugs and features for specific releases. The rules are that: 1. a "driver" can be set on either Distribution or DistroSeries 2. drivers are only actually relevant on a DistroSeries, because thats the granularity at which we track spec/bug targeting 3. the important attribute is ".drivers" on a distroseries, it is calculated based on the combination of owners and drivers in the distribution and the distroseries. It is a LIST of drivers, which might be empty, or have one or two people/teams in it. 4. If the release has a driver, then that driver is in the list. 5. If the distribution has a driver then that is in the list too, otherwise 6. If neither the release nor the distribution has a driver, then the distribution registrant is the driver. We test these rules below. First, we look at a release where both the distribution and release have drivers. Kubuntu should be a good example. >>> kubuntu.driver.name u'jblack' >>> krunch.driver.name u'edgar' >>> for d in krunch.drivers: ... print d.name edgar jblack Now, we look at a release where there is a driver on the release but not on the distribution. >>> debian = distroset.getByName('debian') >>> print debian.driver None >>> print debian.owner.name mark >>> sarge = debian.getSeries('sarge') >>> print sarge.driver.name jdub >>> for d in sarge.drivers: ... print d.name jdub mark Now, a release where there is no driver on the release but there is a driver on the distribution. >>> redhat = distroset.getByName('redhat') >>> print redhat.driver.name jblack >>> six = redhat.getSeries('six') >>> print six.driver None >>> for d in six.drivers: ... print d.name jblack Finally, on a release where neither the distribution nor the release have a driver. Here, we expect the driver to be the owner of the distribution (because this is the "commonest fallback"). >>> sid = debian.getSeries('sid') >>> print debian.driver None >>> print debian.owner.name mark >>> print sid.driver None >>> print sid.registrant.name jdub >>> for d in sid.drivers: ... print d.name mark Lastest Uploads --------------- IDistroSeries provides the 'getLatestUpload' method which returns a list of the last 5 (five) IDistroSeriesSourcePackageRelease (IDRSPR) uploaded and published in its context. >>> warty = ubuntu['warty'] >>> latest_uploads = warty.getLatestUploads() Each element is an IDistroSeriesSourcePackageRelease instance: >>> for upload in latest_uploads: ... print upload.title "mozilla-firefox" 0.9 source package in The Warty Warthog Release Also, empty results (caused obviously by lack of sample data or very earlier development state of a distroseries) are possible: >>> ubuntutest = getUtility(IDistributionSet)['ubuntutest'] >>> breezy_autotest = ubuntutest['breezy-autotest'] >>> latest_uploads = breezy_autotest.getLatestUploads() >>> len(latest_uploads) 0 Getting build records for a distro series ----------------------------------------- IDistroSeries inherits the IHasBuildRecords interfaces and therefore provides a getBuildRecords() method. >>> builds = ubuntu['warty'].getBuildRecords(name='firefox') >>> for build in builds: ... print build.title hppa build of mozilla-firefox 0.9 in ubuntu warty RELEASE i386 build of mozilla-firefox 0.9 in ubuntu warty RELEASE For further options that can be used with getBuildRecords(), please see hasbuildrecords.txt