Ejemplo n.º 1
0
class IHasSpecifications(Interface):
    """An object that has specifications attached to it.

    For example, people, products and distributions have specifications
    associated with them, and you can use this interface to query those.
    """

    visible_specifications = exported(doNotSnapshot(
        CollectionField(
            title=_("All specifications"),
            value_type=Reference(schema=Interface),  # ISpecification, really.
            readonly=True,
            description=_(
                'A list of all specifications, regardless of status or '
                'approval or completion, for this object.'))),
        exported_as="all_specifications", as_of="devel")

    api_valid_specifications = exported(doNotSnapshot(
        CollectionField(
            title=_("Valid specifications"),
            value_type=Reference(schema=Interface),  # ISpecification, really.
            readonly=True,
            description=_(
                'All specifications that are not obsolete. When called from '
                'an ISpecificationGoal it will also exclude the ones that '
                'have not been accepted for that goal'))),
        exported_as="valid_specifications", as_of="devel")

    def specifications(user, quantity=None, sort=None, filter=None,
                       need_people=True, need_branches=True,
                       need_workitems=False):
        """Specifications for this target.

        The user specifies which user to use for calculation of visibility.
        The sort is a dbschema which indicates the preferred sort order. The
        filter is an indicator of the kinds of specs to be returned, and
        appropriate filters depend on the kind of object this method is on.
        If there is a quantity, then limit the result to that number.

        In the case where the filter is [] or None, the content class will
        decide what its own appropriate "default" filter is. In some cases,
        it will show all specs, in others, all approved specs, and in
        others, all incomplete specs.

        If need_people is True, then the assignee, drafter and approver will
        be preloaded, if need_branches is True, linked_branches will be
        preloaded, and if need_workitems is True, work_items will be preloaded.
        """

    def valid_specifications(**kwargs):
        """Valid specifications for this target.
Ejemplo n.º 2
0
class IHasRecipes(Interface):
    """An object that has recipes."""

    recipes = exported(doNotSnapshot(
        CollectionField(
            title=_("All recipes associated with the object."),
            value_type=Reference(schema=Interface),
            readonly=True)))
Ejemplo n.º 3
0
class IHasLocation(Interface):
    """An interface supported by objects with a defined location."""

    latitude = exported(
        doNotSnapshot(
            Float(title=_("The latitude of this object."),
                  required=False, readonly=True)),
        ('devel', dict(exported=False)),
        exported=True)
    longitude = exported(
        doNotSnapshot(
            Float(title=_("The longitude of this object."),
                  required=False, readonly=True)),
        ('devel', dict(exported=False)),
        exported=True)
    time_zone = exported(doNotSnapshot(
        Choice(title=_('The time zone of this object.'),
               required=False, readonly=True,
               vocabulary='TimezoneName')))
Ejemplo n.º 4
0
class IHasMilestones(Interface):
    """An interface for classes providing milestones."""
    export_as_webservice_entry()

    has_milestones = Bool(title=_("Whether the object has any milestones."))

    milestones = exported(doNotSnapshot(
        CollectionField(title=_(
            "The visible and active milestones associated with this "
            "object, ordered by date expected."),
                        value_type=Reference(schema=IMilestone))),
                          exported_as='active_milestones')

    all_milestones = exported(
        doNotSnapshot(
            CollectionField(title=_(
                "All milestones associated with this object, ordered by "
                "date expected."),
                            value_type=Reference(schema=IMilestone))))
Ejemplo n.º 5
0
class IBugSubscription(Interface):
    """The relationship between a person and a bug."""

    export_as_webservice_entry(publish_web_link=False, as_of="beta")

    id = Int(title=_('ID'), readonly=True, required=True)
    person = exported(PersonChoice(title=_('Person'),
                                   required=True,
                                   vocabulary='ValidPersonOrTeam',
                                   readonly=True,
                                   description=_(
                                       "The person's Launchpad ID or "
                                       "e-mail address.")),
                      as_of="beta")
    bug = exported(Reference(Interface,
                             title=_("Bug"),
                             required=True,
                             readonly=True),
                   as_of="beta")
    # We mark this as doNotSnapshot() because it's a magically-generated
    # Storm attribute and it causes Snapshot to break.
    bugID = doNotSnapshot(Int(title=u"The bug id.", readonly=True))
    bug_notification_level = exported(Choice(
        title=_("Bug notification level"),
        required=True,
        vocabulary=BugNotificationLevel,
        default=BugNotificationLevel.COMMENTS,
        description=_("The volume and type of bug notifications "
                      "this subscription will generate."),
    ),
                                      as_of="devel")
    date_created = exported(Datetime(title=_('Date subscribed'),
                                     required=True,
                                     readonly=True),
                            as_of="beta")
    subscribed_by = exported(PersonChoice(
        title=_('Subscribed by'),
        required=True,
        vocabulary='ValidPersonOrTeam',
        readonly=True,
        description=_("The person who created this subscription.")),
                             as_of="beta")

    display_subscribed_by = Attribute("`subscribed_by` formatted for display.")

    display_duplicate_subscribed_by = Attribute(
        "duplicate bug `subscribed_by` formatted for display.")

    @call_with(user=REQUEST_USER)
    @export_read_operation()
    @operation_for_version("beta")
    def canBeUnsubscribedByUser(user):
        """Can the user unsubscribe the subscriber from the bug?"""
Ejemplo n.º 6
0
class IMilestoneData(IHasBugs, IStructuralSubscriptionTarget,
                     IHasOfficialBugTags):
    """Interface containing the data for milestones.

    To be registered for views but not instantiated.
    """
    id = Int(title=_("Id"))

    name = exported(
        MilestoneNameField(
            title=_("Name"),
            description=_(
                "Only letters, numbers, and simple punctuation are allowed."),
            constraint=name_validator))
    target = exported(
        Reference(
            schema=Interface,  # IHasMilestones
            title=_("The product, distribution, or project group for this "
                    "milestone."),
            required=False))
    dateexpected = exported(FormattableDate(
        title=_("Date Targeted"),
        required=False,
        description=_("Example: 2005-11-24")),
                            exported_as='date_targeted')
    active = exported(Bool(title=_("Active"),
                           description=_(
                               "Whether or not this object should be shown "
                               "in web forms for targeting.")),
                      exported_as='is_active')
    displayname = Attribute("A displayname constructed from the name.")
    title = exported(
        TextLine(title=_("A context title for pages."), readonly=True))
    all_specifications = doNotSnapshot(
        Attribute('All specifications linked to this milestone.'))

    def bugtasks(user):
        """Get a list of non-conjoined bugtasks visible to this user."""

    def getSpecifications(user):
        """Return the specifications visible to this user."""
Ejemplo n.º 7
0
class IWebhookTarget(Interface):

    export_as_webservice_entry(as_of='beta')

    webhooks = exported(
        doNotSnapshot(
            CollectionField(title=_("Webhooks for this target."),
                            value_type=Reference(schema=IWebhook),
                            readonly=True)))

    valid_webhook_event_types = List(
        Choice(vocabulary='AnyWebhookEventType'),
        title=_("Valid event types"),
        description=_("Valid event types for this object type."),
        required=True,
        readonly=True)

    default_webhook_event_types = List(
        Choice(vocabulary='ValidWebhookEventType'),
        title=_("Default event types"),
        description=_(
            "Default event types for new webhooks attached to this object "
            "type."),
        required=True,
        readonly=True)

    @call_with(registrant=REQUEST_USER)
    @export_factory_operation(
        IWebhook, ['delivery_url', 'active', 'event_types', 'secret'])
    @operation_for_version("devel")
    def newWebhook(registrant,
                   delivery_url,
                   event_types,
                   active=True,
                   secret=None):
        """Create a new webhook."""
Ejemplo n.º 8
0
class ILanguage(Interface):
    """A Language."""
    export_as_webservice_entry()

    id = Attribute("This Language ID.")

    code = exported(TextLine(title=u'The ISO 639 code', required=True))

    englishname = exported(TextLine(title=u'The English name', required=True),
                           exported_as='english_name')

    nativename = TextLine(
        title=u'Native name',
        description=u'The name of this language in the language itself.',
        required=False)

    pluralforms = exported(Int(
        title=u'Number of plural forms',
        description=u'The number of plural forms this language has.',
        required=False),
                           exported_as='plural_forms')

    guessed_pluralforms = Int(
        title=u"Number of plural forms, or a reasonable guess",
        required=False,
        readonly=True)

    pluralexpression = exported(TextLine(
        title=u'Plural form expression',
        description=(u'The expression that relates a number of items'
                     u' to the appropriate plural form.'),
        required=False),
                                exported_as='plural_expression')

    translators = doNotSnapshot(
        Field(title=u'List of Person/Team that translate into this language.',
              required=True))

    translators_count = exported(
        Int(title=u"Total number of translators for this language.",
            readonly=True))

    translation_teams = Field(
        title=u'List of Teams that translate into this language.',
        required=True)

    countries = Set(
        title=u'Spoken in',
        description=u'List of countries this language is spoken in.',
        required=True,
        value_type=Choice(vocabulary="CountryName"))

    def addCountry(country):
        """Add a country to a list of countries this language is spoken in.

        Provided by SQLObject.
        """

    def removeCountry(country):
        """Remove country from list of countries this language is spoken in.

        Provided by SQLObject.
        """

    visible = exported(
        Bool(title=u'Visible',
             description=(u'Whether this language is visible by default.'),
             required=True))

    direction = exported(Choice(
        title=u'Text direction',
        description=u'The direction of text in this language.',
        required=True,
        vocabulary=TextDirection),
                         exported_as='text_direction')

    displayname = TextLine(title=u'The displayname of the language',
                           required=True,
                           readonly=True)

    alt_suggestion_language = Attribute(
        "A language which can reasonably "
        "be expected to have good suggestions for translations in this "
        "language.")

    dashedcode = TextLine(
        title=(u'The language code in a form suitable for use in HTML and'
               u' XML files.'),
        required=True,
        readonly=True)

    abbreviated_text_dir = TextLine(
        title=(u'The abbreviated form of the text direction, suitable'
               u' for use in HTML files.'),
        required=True,
        readonly=True)

    @invariant
    def validatePluralData(form_language):
        pair = (form_language.pluralforms, form_language.pluralexpression)
        if None in pair and pair != (None, None):
            raise Invalid(
                'The number of plural forms and the plural form expression '
                'must be set together, or not at all.')
Ejemplo n.º 9
0
class IProductSeriesView(ISeriesMixin, IHasAppointedDriver, IHasOwner,
                         ISpecificationGoal, IHasMilestones,
                         IHasOfficialBugTags, IHasExpirableBugs,
                         IHasTranslationImports, IHasTranslationTemplates,
                         IServiceUsage):
    status = exported(
        Choice(title=_('Status'),
               required=True,
               vocabulary=SeriesStatus,
               default=SeriesStatus.DEVELOPMENT))

    parent = Attribute('The structural parent of this series - the product')

    datecreated = exported(Datetime(title=_('Date Registered'),
                                    required=True,
                                    readonly=True),
                           exported_as='date_created')

    owner = exported(
        PersonChoice(
            title=_('Owner'),
            required=True,
            vocabulary='ValidOwner',
            description=_('Project owner, either a valid Person or Team')))

    driver = exported(
        PersonChoice(
            title=_("Release manager"),
            description=_(
                "The person or team responsible for decisions about features "
                "and bugs that will be targeted to this series. If you don't "
                "nominate someone here, then the owner of this series will "
                "automatically have those permissions, as will the project "
                "and project group drivers."),
            required=False,
            vocabulary='ValidPersonOrTeam'))

    title = exported(
        Title(title=_('Title'),
              description=_("The product series title.  "
                            "Should be just a few words.")))

    displayname = exported(TextLine(
        title=_('Display Name'),
        description=_(
            "Display name.  In this case we have removed the underlying "
            "database field, and this attribute just returns the name.")),
                           exported_as='display_name')

    releases = exported(
        CollectionField(title=_("An iterator over the releases in this "
                                "Series, sorted with latest release first."),
                        readonly=True,
                        value_type=Reference(schema=IProductRelease)))

    release_files = Attribute("An iterator over the release files in this "
                              "Series, sorted with latest release first.")

    packagings = Attribute("An iterator over the Packaging entries "
                           "for this product series.")

    specifications = Attribute("The specifications targeted to this "
                               "product series.")

    sourcepackages = Attribute(
        _("List of distribution packages for this "
          "product series"))

    milestones = exported(doNotSnapshot(
        CollectionField(title=_("The visible milestones associated with this "
                                "project series, ordered by date expected."),
                        readonly=True,
                        value_type=Reference(schema=IMilestone))),
                          exported_as='active_milestones')

    all_milestones = exported(
        doNotSnapshot(
            CollectionField(title=_(
                "All milestones associated with this project series, "
                "ordered by date expected."),
                            readonly=True,
                            value_type=Reference(schema=IMilestone))))

    branch = exported(
        ReferenceChoice(title=_('Branch'),
                        vocabulary='BranchRestrictedOnProduct',
                        schema=IBranch,
                        required=False,
                        description=_(
                            "The Bazaar branch for this series.  Leave blank "
                            "if this series is not maintained in Bazaar.")))

    translations_autoimport_mode = exported(Choice(
        title=_('Import settings'),
        vocabulary=TranslationsBranchImportMode,
        required=True,
        description=_("Specify which files will be imported from the "
                      "source code branch.")),
                                            as_of="devel")

    potemplate_count = Int(
        title=_("The total number of POTemplates in this series."),
        readonly=True,
        required=True)

    productserieslanguages = Attribute(
        "The set of ProductSeriesLanguages for this series.")

    translations_branch = ReferenceChoice(
        title=_("Translations export branch"),
        vocabulary='HostedBranchRestrictedOnOwner',
        schema=IBranch,
        required=False,
        description=_("A Bazaar branch to commit translation snapshots to.  "
                      "Leave blank to disable."))

    all_specifications = doNotSnapshot(
        Attribute('All specifications linked to this series.'))

    def getCachedReleases():
        """Gets a cached copy of this series' releases.

        Returns None if there is no release."""

    def getLatestRelease():
        """Gets the most recent release in the series.

        Returns None if there is no release."""

    def getRelease(version):
        """Get the release in this series that has the specified version.
        Return None is there is no such release.
        """

    def getPackage(distroseries):
        """Return the SourcePackage for this project series in the supplied
        distroseries. This will use a Packaging record if one exists, but
        it will also work through the ancestry of the distroseries to try
        to find a Packaging entry that may be relevant."""

    def getUbuntuTranslationFocusPackage():
        """Return the SourcePackage that packages this project in Ubuntu's
        translation focus or current series or any series, in that order."""

    def setPackaging(distroseries, sourcepackagename, owner):
        """Create or update a Packaging record for this product series,
        connecting it to the given distroseries and source package name.
        """

    def getPackagingInDistribution(distribution):
        """Return all the Packaging entries for this product series for the
        given distribution. Note that this only returns EXPLICT packaging
        entries, it does not look at distro series ancestry in the same way
        that IProductSeries.getPackage() does.
        """

    def getPOTemplate(name):
        """Return the POTemplate with this name for the series."""

    # where are the tarballs released from this branch placed?
    releasefileglob = exported(TextLine(
        title=_("Release URL pattern"),
        required=False,
        constraint=validate_release_glob,
        description=_('A URL pattern that matches releases that are part '
                      'of this series.  Launchpad automatically scans this '
                      'site to import new releases.  Example: '
                      'http://ftp.gnu.org/gnu/emacs/emacs-21.*.tar.gz')),
                               exported_as='release_finder_url_pattern')

    releaseverstyle = Attribute("The version numbering style for this "
                                "series of releases.")

    is_development_focus = Attribute(
        _("Is this series the development focus for the product?"))

    @operation_parameters(include_inactive=Bool(title=_("Include inactive"),
                                                required=False,
                                                default=False))
    @export_read_operation()
    @export_operation_as('get_timeline')
    def getTimeline(include_inactive):
        """Return basic timeline data useful for creating a diagram.
Ejemplo n.º 10
0
class IWebhook(Interface):

    export_as_webservice_entry(as_of='beta')

    id = Int(title=_("ID"), readonly=True, required=True)

    target = exported(
        Reference(
            title=_("Target"),
            schema=Interface,  # Actually IWebhookTarget.
            required=True,
            readonly=True,
            description=_(
                "The object for which this webhook receives events.")))
    event_types = exported(
        List(Choice(vocabulary='ValidWebhookEventType'),
             title=_("Event types"),
             required=True,
             readonly=False))
    registrant = exported(
        Reference(title=_("Registrant"),
                  schema=IPerson,
                  required=True,
                  readonly=True,
                  description=_("The person who created this webhook.")))
    registrant_id = Int(title=_("Registrant ID"))
    date_created = exported(
        Datetime(title=_("Date created"), required=True, readonly=True))
    date_last_modified = exported(
        Datetime(title=_("Date last modified"), required=True, readonly=True))

    delivery_url = exported(
        URIField(title=_("Delivery URL"),
                 allowed_schemes=['http', 'https'],
                 required=True,
                 readonly=False))
    active = exported(
        Bool(title=_("Active"),
             description=_("Deliver details of subscribed events."),
             required=True,
             readonly=False))

    # Do not export this.
    secret = TextLine(
        title=_("Secret"),
        required=False,
        description=_(
            "An optional string used to sign delivery bodies with HMAC-SHA1 "
            "in the X-Hub-Signature header. This must be less than 200 bytes "
            "long."),
        max_length=200)

    deliveries = exported(
        doNotSnapshot(
            CollectionField(title=_("Recent deliveries for this webhook."),
                            value_type=Reference(schema=Interface),
                            readonly=True)))

    def getDelivery(id):
        """Retrieve a delivery by ID, or None if it doesn't exist."""

    @export_factory_operation(Interface, [])  # Actually IWebhookDelivery.
    @operation_for_version('devel')
    def ping():
        """Send a test event."""

    @export_destructor_operation()
    @operation_for_version('devel')
    def destroySelf():
        """Delete this webhook."""

    @export_write_operation()
    @operation_parameters(secret=copy_field(secret))
    @operation_for_version('devel')
    def setSecret(secret):
        """Set the secret used to sign deliveries."""
Ejemplo n.º 11
0
class IDistributionPublic(
    IBugTarget, ICanGetMilestonesDirectly, IHasAppointedDriver,
    IHasBuildRecords, IHasDrivers, IHasMilestones, IHasSharingPolicies,
    IHasOOPSReferences, IHasOwner, IHasSprints, IHasTranslationImports,
    ITranslationPolicy, IKarmaContext, ILaunchpadUsage, IMakesAnnouncements,
    IOfficialBugTagTargetPublic, IPillar, IServiceUsage,
    ISpecificationTarget, IHasExpirableBugs):
    """Public IDistribution properties."""

    id = Attribute("The distro's unique number.")
    name = exported(
        DistributionNameField(
            title=_("Name"),
            constraint=name_validator,
            description=_("The distro's name."), required=True))
    displayname = exported(
        TextLine(
            title=_("Display Name"),
            description=_("The displayable name of the distribution."),
            required=True),
        exported_as='display_name')
    title = exported(
        Title(
            title=_("Title"),
            description=_("The distro's title."), required=True))
    summary = exported(
        Summary(
            title=_("Summary"),
            description=_(
                "A short paragraph to introduce the goals and highlights "
                "of the distribution."),
            required=True))
    homepage_content = exported(
        Text(
            title=_("Homepage Content"), required=False,
            description=_(
                "The content of this distribution's home page. Edit this and "
                "it will be displayed for all the world to see. It is NOT a "
                "wiki so you cannot undo changes.")))
    icon = exported(
        IconImageUpload(
            title=_("Icon"), required=False,
            default_image_resource='/@@/distribution',
            description=_(
                "A small image of exactly 14x14 pixels and at most 5kb in "
                "size, that can be used to identify this distribution. The "
                "icon will be displayed everywhere we list the distribution "
                "and link to it.")))
    logo = exported(
        LogoImageUpload(
            title=_("Logo"), required=False,
            default_image_resource='/@@/distribution-logo',
            description=_(
                "An image of exactly 64x64 pixels that will be displayed in "
                "the heading of all pages related to this distribution. It "
                "should be no bigger than 50kb in size.")))
    mugshot = exported(
        MugshotImageUpload(
            title=_("Brand"), required=False,
            default_image_resource='/@@/distribution-mugshot',
            description=_(
                "A large image of exactly 192x192 pixels, that will be "
                "displayed on this distribution's home page in Launchpad. "
                "It should be no bigger than 100kb in size. ")))
    description = exported(
        Description(
            title=_("Description"),
            description=_(
                "Details about the distributions's work, highlights, goals, "
                "and how to contribute. Use plain text, paragraphs are "
                "preserved and URLs are linked in pages. Don't repeat the "
                "Summary."),
            required=True))
    domainname = exported(
        TextLine(
            title=_("Web site URL"),
            description=_("The distro's web site URL."), required=True),
        exported_as='domain_name')
    owner = exported(
        PublicPersonChoice(
            title=_("Owner"),
            required=True,
            vocabulary='ValidPillarOwner',
            description=_("The restricted team, moderated team, or person "
                          "who maintains the distribution information in "
                          "Launchpad.")))
    registrant = exported(
        PublicPersonChoice(
            title=_("Registrant"), vocabulary='ValidPersonOrTeam',
            description=_("The distro's registrant."), required=True,
            readonly=True))
    date_created = exported(
        Datetime(title=_('Date created'),
                 description=_("The date this distribution was registered.")))
    driver = exported(
        PublicPersonChoice(
            title=_("Driver"),
            description=_(
                "The person or team responsible for decisions about features "
                "and bugs that will be targeted for any series in this "
                "distribution. Note that you can also specify a driver "
                "on each series whose permissions will be limited to that "
                "specific series."),
            required=False, vocabulary='ValidPersonOrTeam'))
    drivers = Attribute(
        "Presents the distro driver as a list for consistency with "
        "IProduct.drivers where the list might include a project driver.")
    members = exported(PublicPersonChoice(
        title=_("Members"),
        description=_("The distro's members team."), required=True,
        vocabulary='ValidPersonOrTeam'))
    mirror_admin = exported(PublicPersonChoice(
        title=_("Mirror Administrator"),
        description=_("The person or team that has the rights to review and "
                      "mark this distribution's mirrors as official."),
        required=True, vocabulary='ValidPersonOrTeam'))
    archive_mirrors = exported(doNotSnapshot(
        CollectionField(
            description=_("All enabled and official ARCHIVE mirrors "
                          "of this Distribution."),
            readonly=True, value_type=Object(schema=IDistributionMirror))))
    archive_mirrors_by_country = doNotSnapshot(CollectionField(
            description=_("All enabled and official ARCHIVE mirrors "
                          "of this Distribution."),
            readonly=True, value_type=Object(schema=IDistributionMirror)))
    cdimage_mirrors = exported(doNotSnapshot(
        CollectionField(
            description=_("All enabled and official RELEASE mirrors "
                          "of this Distribution."),
            readonly=True, value_type=Object(schema=IDistributionMirror))))
    cdimage_mirrors_by_country = doNotSnapshot(CollectionField(
            description=_("All enabled and official ARCHIVE mirrors "
                          "of this Distribution."),
            readonly=True, value_type=Object(schema=IDistributionMirror)))
    disabled_mirrors = Attribute(
        "All disabled and official mirrors of this Distribution.")
    unofficial_mirrors = Attribute(
        "All unofficial mirrors of this Distribution.")
    pending_review_mirrors = Attribute(
        "All mirrors of this Distribution that haven't been reviewed yet.")
    series = exported(doNotSnapshot(
        CollectionField(
            title=_("DistroSeries inside this Distribution"),
            # Really IDistroSeries, see _schema_circular_imports.py.
            value_type=Reference(schema=Interface))))
    derivatives = exported(doNotSnapshot(
        CollectionField(
            title=_("This Distribution's derivatives"),
            # Really IDistroSeries, see _schema_circular_imports.py.
            value_type=Reference(schema=Interface))))
    architectures = List(
        title=_("DistroArchSeries inside this Distribution"))
    uploaders = Attribute(_(
        "ArchivePermission records for uploaders with rights to upload to "
        "this distribution."))
    package_derivatives_email = TextLine(
        title=_("Package Derivatives Email Address"),
        description=_(
            "The email address to send information about updates to packages "
            "that are derived from another distribution. The sequence "
            "{package_name} is replaced with the actual package name."),
        required=False)

    # properties
    currentseries = exported(
        Reference(
            # Really IDistroSeries, see _schema_circular_imports.py.
            Interface,
            title=_("Current series"),
            description=_(
                "The current development series of this distribution. "
                "Note that all maintainerships refer to the current "
                "series. When people ask about the state of packages "
                "in the distribution, we should interpret that query "
                "in the context of the currentseries.")),
        exported_as="current_series")

    full_functionality = Attribute(
        "Whether or not we enable the full functionality of Launchpad for "
        "this distribution. Currently only Ubuntu and some derivatives "
        "get the full functionality of LP")

    translation_focus = Choice(
        title=_("Translation focus"),
        description=_(
            "The release series that translators should focus on."),
        required=False,
        vocabulary='FilteredDistroSeries')

    language_pack_admin = Choice(
        title=_("Language Pack Administrator"),
        description=_("The distribution language pack administrator."),
        required=False, vocabulary='ValidPersonOrTeam')

    main_archive = exported(
        Reference(
            title=_('Distribution Main Archive.'), readonly=True,
            # Really IArchive, see _schema_circular_imports.py.
            schema=Interface))

    all_distro_archives = exported(doNotSnapshot(
        CollectionField(
            title=_(
                "A sequence of the distribution's primary, "
                "partner and debug archives."),
            readonly=True, required=False,
            value_type=Reference(schema=Interface))),
                # Really IArchive, see _schema_circular_imports.py.
        exported_as='archives')

    all_distro_archive_ids = Attribute(
        "A list containing the IDs of all the non-PPA archives.")

    has_published_binaries = Bool(
        title=_("Has Published Binaries"),
        description=_("True if this distribution has binaries published "
                      "on disk."),
        readonly=True, required=False)

    has_published_sources = Bool(
        title=_("Has Published Sources"),
        description=_("True if this distribution has sources published."),
        readonly=True, required=False)

    redirect_release_uploads = exported(Bool(
        title=_("Redirect release pocket uploads"),
        description=_("Redirect release pocket uploads to proposed pocket"),
        readonly=False, required=True))

    development_series_alias = exported(DistroSeriesNameField(
        title=_("Alias for development series"),
        description=_(
            "If set, an alias for the current development series in this "
            "distribution."),
        constraint=name_validator, readonly=False, required=False))

    def getArchiveIDList(archive=None):
        """Return a list of archive IDs suitable for sqlvalues() or quote().

        If the archive param is supplied, just its ID will be returned in
        a list of one item.  If it is not supplied, return a list of
        all the IDs for all the archives for the distribution.
        """

    def __getitem__(name):
        """Returns a DistroSeries that matches name, or raises and
        exception if none exists."""

    def __iter__():
        """Iterate over the series for this distribution."""

    @operation_parameters(
        name=TextLine(title=_("Archive name"), required=True))
    @operation_returns_entry(Interface)
    @export_read_operation()
    def getArchive(name):
        """Return the distribution archive with the given name.

        Only distribution archives are considered -- PPAs will not be found.

        :param name: The name of the archive, e.g. 'partner'
        """

    # Really IDistroSeries, see _schema_circular_imports.py.
    @operation_returns_collection_of(Interface)
    @export_operation_as(name="getDevelopmentSeries")
    @export_read_operation()
    def getDevelopmentSeries():
        """Return the DistroSeries which are marked as in development."""

    def resolveSeriesAlias(name):
        """Resolve a series alias.

        :param name: The name to resolve.
        :raises NoSuchDistroSeries: If there is no match.
        """

    @operation_parameters(
        name_or_version=TextLine(title=_("Name or version"), required=True))
    # Really IDistroSeries, see _schema_circular_imports.py.
    @operation_returns_entry(Interface)
    @call_with(follow_aliases=True)
    @export_read_operation()
    def getSeries(name_or_version, follow_aliases=False):
        """Return the series with the name or version given.

        :param name_or_version: The `IDistroSeries.name` or
            `IDistroSeries.version`.
        """

    # This API is specifically for Ensemble's Principia.  It does not scale
    # well to distributions of Ubuntu's scale, and is not intended for it.
    # Therefore, this should probably never be exposed for a webservice
    # version other than "devel".
    @operation_parameters(
        since=Datetime(
            title=_("Time of last change"),
            description=_(
                "Return branches that have new tips since this timestamp."),
            required=False))
    @call_with(user=REQUEST_USER)
    @export_operation_as(name="getBranchTips")
    @export_read_operation()
    @operation_for_version('devel')
    def getBranchTips(user=None, since=None):
        """Return a list of branches which have new tips since a date.

        Each branch information is a tuple of (branch_unique_name,
        tip_revision, (official_series*)).

        So for each branch in the distribution, you'll get the branch unique
        name, the revision id of tip, and if the branch is official for some
        series, the list of series name.

        :param: user: If specified, shows the branches visible to that user.
            if not specified, only branches visible to the anonymous user are
            shown.

        :param since: If specified, limits results to branches modified since
            that date and time.
        """

    @operation_parameters(
        name=TextLine(title=_("Name"), required=True))
    @operation_returns_entry(IDistributionMirror)
    @export_read_operation()
    def getMirrorByName(name):
        """Return the mirror with the given name for this distribution or None
        if it's not found.
        """

    @operation_parameters(
        country=copy_field(IDistributionMirror['country'], required=True),
        mirror_type=copy_field(IDistributionMirror['content'], required=True))
    @operation_returns_entry(IDistributionMirror)
    @export_read_operation()
    def getCountryMirror(country, mirror_type):
        """Return the country DNS mirror for a country and content type."""

    def newMirror(owner, speed, country, content, displayname=None,
                  description=None, http_base_url=None,
                  ftp_base_url=None, rsync_base_url=None, enabled=False,
                  official_candidate=False, whiteboard=None):
        """Create a new DistributionMirror for this distribution.

        At least one of http_base_url or ftp_base_url must be provided in
        order to create a mirror.
        """

    @operation_parameters(
        name=TextLine(title=_("Package name"), required=True))
    # Really returns IDistributionSourcePackage, see
    # _schema_circular_imports.py.
    @operation_returns_entry(Interface)
    @export_read_operation()
    def getSourcePackage(name):
        """Return a DistributionSourcePackage with the given name for this
        distribution, or None.
        """

    def getSourcePackageRelease(sourcepackagerelease):
        """Returns an IDistributionSourcePackageRelease

        Receives a sourcepackagerelease.
        """

    def getCurrentSourceReleases(source_package_names):
        """Get the current release of a list of source packages.

        :param source_package_names: a list of `ISourcePackageName`
            instances.

        :return: a dict where the key is a `IDistributionSourcePackage`
            and the value is a `IDistributionSourcePackageRelease`.
        """

    def getDistroSeriesAndPocket(distroseriesname, follow_aliases=False):
        """Return a (distroseries,pocket) tuple which is the given textual
        distroseriesname in this distribution."""

    def getSeriesByStatus(status):
        """Query context distribution for distroseries with a given status.

        :param status: Series status to look for
        :return: list of `IDistroSeries`
        """

    @rename_parameters_as(text="source_match")
    @operation_parameters(
        text=TextLine(title=_("Source package name substring match"),
                      required=True))
    # Really returns IDistributionSourcePackage, see
    # _schema_circular_imports.py.
    @operation_returns_collection_of(Interface)
    @export_read_operation()
    def searchSourcePackages(
        text, has_packaging=None, publishing_distroseries=None):
        """Search for source packages that correspond to the given text.

        This method just decorates the result of searchSourcePackageCaches()
        to return DistributionSourcePackages.
        """

    def searchSourcePackageCaches(
        text, has_packaging=None, publishing_distroseries=None):
        """Search for source packages that correspond to the given text.

        :param text: The text that will be matched.
        :param has_packaging: If True, it will filter out
            packages with no packaging (i.e. no link to the upstream
            project). False will do the reverse filtering, and None
            will do no filtering on this field.
        :param publishing_distroseries: If it is not None, then
            it will filter out source packages that do not have a
            publishing history for the given distroseries.
        :return: A result set containing
            (DistributionSourcePackageCache, SourcePackageName, rank) tuples
            ordered by rank.
        """

    def searchBinaryPackages(package_name, exact_match=False):
        """Search for binary packages in this distribution.

        :param package_name: The binary package name to match.
        :param exact_match: If False, substring matches are done on the
            binary package names; if True only a full string match is
            returned.
        :return: A result set containing appropriate DistributionSourcePackage
            objects for the matching source.

        The returned results will consist of source packages that match
        (a substring of) their binary package names.
        """

    def guessPublishedSourcePackageName(pkgname):
        """Return the "published" SourcePackageName related to pkgname.

        If pkgname corresponds to a source package that was published in
        any of the distribution series, that's the SourcePackageName that is
        returned.

        If there is any official source package branch linked, then that
        source package name is returned.

        Otherwise, try to find a published binary package name and then return
        the source package name from which it comes from.

        :raises NotFoundError: when pkgname doesn't correspond to either a
            published source or binary package name in this distribution.
        """

    def getAllPPAs():
        """Return all PPAs for this distribution."""

    def searchPPAs(text=None, show_inactive=False):
        """Return all PPAs matching the given text in this distribution.

        'text', when passed, will restrict results to Archives with matching
        description (using substring) or matching Archive.owner (using
        available person fti/ftq).

        'show_inactive', when False, will restrict results to Archive with
        at least one source publication in PENDING or PUBLISHED status.
        """

    def getPendingAcceptancePPAs():
        """Return only pending acceptance PPAs in this distribution."""

    def getPendingPublicationPPAs():
        """Return all PPAs in this distribution that are pending publication.

        A PPA is said to be pending publication if it has publishing records
        in the pending state or if it had packages deleted from it.
        """

    def getArchiveByComponent(component_name):
        """Return the archive most appropriate for the component name.

        Where different components may imply a different archive (e.g.
        partner), this method will return the archive for that component.

        If the component_name supplied is unknown, None is returned.
        """

    def getAllowedBugInformationTypes():
        """Get the information types that a bug in this distribution can have.

        :return: A sequence of `InformationType`s.
        """

    def getDefaultBugInformationType():
        """Get the default information type of a new bug in this distro.

        :return: The `InformationType`.
        """

    def userCanEdit(user):
        """Can the user edit this distribution?"""
Ejemplo n.º 12
0
class IProductView(
    ICanGetMilestonesDirectly, IHasAppointedDriver, IHasBranches,
    IHasExternalBugTracker,
    IHasMergeProposals, IHasMilestones, IHasExpirableBugs,
    IHasMugshot, IHasSprints, IHasTranslationImports,
    ITranslationPolicy, IKarmaContext, IMakesAnnouncements,
    IOfficialBugTagTargetPublic, IHasOOPSReferences,
    IHasRecipes, IHasCodeImports, IServiceUsage, IHasGitRepositories):
    """Public IProduct properties."""

    registrant = exported(
        PublicPersonChoice(
            title=_('Registrant'),
            required=True,
            readonly=True,
            vocabulary='ValidPersonOrTeam',
            description=_("This person registered the project in "
                          "Launchpad.")))

    driver = exported(
        PersonChoice(
            title=_("Driver"),
            description=_(
                "This person or team will be able to set feature goals for "
                "and approve bug targeting or backporting for ANY major "
                "series in this project. You might want to leave this blank "
                "and just appoint a team for each specific series, rather "
                "than having one project team that does it all."),
            required=False, vocabulary='ValidPersonOrTeam'))

    summary = exported(
        Summary(
            title=_('Summary'),
            description=_(
                "A short paragraph to introduce the project's work.")))

    description = exported(
        Description(
            title=_('Description'),
            required=False,
            description=_(
                "Details about the project's work, highlights, goals, and "
                "how to contribute. Use plain text, paragraphs are preserved "
                "and URLs are linked in pages. Don't repeat the Summary.")))

    datecreated = exported(
        Datetime(
            title=_('Date Created'),
            required=True, readonly=True,
            description=_("The date this project was created in Launchpad.")),
        exported_as='date_created')

    homepageurl = exported(
        URIField(
            title=_('Homepage URL'),
            required=False,
            allowed_schemes=['http', 'https', 'ftp'], allow_userinfo=False,
            description=_("""The project home page. Please include
                the http://""")),
        exported_as="homepage_url")

    wikiurl = exported(
        URIField(
            title=_('Wiki URL'),
            required=False,
            allowed_schemes=['http', 'https', 'ftp'], allow_userinfo=False,
            description=_("""The full URL of this project's wiki, if it has
                one. Please include the http://""")),
        exported_as='wiki_url')

    screenshotsurl = exported(
        URIField(
            title=_('Screenshots URL'),
            required=False,
            allowed_schemes=['http', 'https', 'ftp'], allow_userinfo=False,
            description=_("""The full URL for screenshots of this project,
                if available. Please include the http://""")),
        exported_as='screenshots_url')

    downloadurl = exported(
        URIField(
            title=_('Download URL'),
            required=False,
            allowed_schemes=['http', 'https', 'ftp'], allow_userinfo=False,
            description=_("""The full URL where downloads for this project
                are located, if available. Please include the http://""")),
        exported_as='download_url')

    programminglang = exported(
        TextLine(
            title=_('Programming Languages'),
            required=False,
            description=_("""A comma delimited list of programming
                languages used for this project.""")),
        exported_as='programming_language')

    sourceforgeproject = exported(
        TextLine(
            title=_('Sourceforge Project'),
            required=False,
            constraint=sourceforge_project_name_validator,
            description=_("""The SourceForge project name for
                this project, if it is in sourceforge.""")),
        exported_as='sourceforge_project')

    freshmeatproject = exported(
        TextLine(
            title=_('Freshmeat Project'),
            required=False, description=_("""The Freshmeat project name for
                this project, if it is in freshmeat. [DEPRECATED]""")),
        exported_as='freshmeat_project')

    homepage_content = Text(
        title=_("Homepage Content"), required=False,
        description=_(
            "The content of this project's home page. Edit this and it will "
            "be displayed for all the world to see. It is NOT a wiki "
            "so you cannot undo changes."))

    mugshot = exported(
        MugshotImageUpload(
            title=_("Brand"), required=False,
            default_image_resource='/@@/product-mugshot',
            description=_(
                "A large image of exactly 192x192 pixels, that will be "
                "displayed on this project's home page in Launchpad. It "
                "should be no bigger than 100kb in size.")),
        exported_as='brand')

    autoupdate = Bool(
        title=_('Automatic update'),
        description=_("Whether or not this project's attributes are "
                      "updated automatically."))

    private_bugs = exported(
        Bool(
            title=_('Private bugs (obsolete; always False)'), readonly=True,
            description=_("Replaced by bug_sharing_policy.")),
        ('devel', dict(exported=False)))

    branch_sharing_policy = exported(Choice(
        title=_('Branch sharing policy'),
        description=_("Sharing policy for this project's branches."),
        required=True, readonly=True, vocabulary=BranchSharingPolicy),
        as_of='devel')
    bug_sharing_policy = exported(Choice(
        title=_('Bug sharing policy'),
        description=_("Sharing policy for this project's bugs."),
        required=True, readonly=True, vocabulary=BugSharingPolicy),
        as_of='devel')
    specification_sharing_policy = exported(Choice(
        title=_('Blueprint sharing policy'),
        description=_("Sharing policy for this project's specifications."),
        required=True, readonly=True, vocabulary=SpecificationSharingPolicy),
        as_of='devel')

    licenses = exported(
        Set(title=_('Licences'),
            value_type=Choice(vocabulary=License)))

    license_info = exported(
        Description(
            title=_('Description of additional licences'),
            required=False,
            description=_(
                "Description of licences that do not appear in the list "
                "above.")))

    bugtracker = exported(
        ProductBugTracker(
            title=_('Bugs are tracked'),
            vocabulary="BugTracker"),
        exported_as='bug_tracker')

    sourcepackages = Attribute(_("List of packages for this product"))

    date_next_suggest_packaging = exported(
        Datetime(
            title=_('Next suggest packaging date'),
            description=_(
                "Obsolete. The date to resume Ubuntu package suggestions."),
            required=False),
        ('devel', dict(exported=False)))

    distrosourcepackages = Attribute(_("List of distribution packages for "
        "this product"))

    ubuntu_packages = Attribute(
        _("List of distribution packages for this product in Ubuntu"))

    series = exported(
        doNotSnapshot(
            CollectionField(value_type=Object(schema=IProductSeries))))

    development_focus = exported(
        ReferenceChoice(
            title=_('Development focus'), required=True,
            vocabulary='FilteredProductSeries',
            schema=IProductSeries,
            description=_(
                'The series that represents the master or trunk branch. '
                'The Bazaar URL lp:<project> points to the development focus '
                'series branch.')))
    development_focusID = Attribute("The development focus ID.")

    releases = exported(
        doNotSnapshot(
            CollectionField(
                title=_("An iterator over the ProductReleases for "
                        "this product."),
                readonly=True,
                value_type=Reference(schema=IProductRelease))))

    translation_focus = exported(
        ReferenceChoice(
            title=_("Translation focus"), required=False,
            vocabulary='FilteredProductSeries',
            schema=IProductSeries,
            description=_(
                'Project series that translators should focus on.')))

    translatable_packages = Attribute(
        "A list of the source packages for this product that can be "
        "translated sorted by distroseries.name and sourcepackage.name.")

    translatable_series = Attribute(
        "A list of the series of this product for which we have translation "
        "templates.")

    obsolete_translatable_series = Attribute("""
        A list of the series of this product with obsolete translation
        templates.""")

    primary_translatable = Attribute(
        "The best guess we have for what new translators will want to "
        "translate for a given product: the latest series for which we have "
        "templates, and failing that, an Ubuntu package.")

    translationgroups = Attribute("The list of applicable translation "
        "groups for a product. There can be several: one from the product, "
        "and potentially one from the project, too.")

    commercial_subscription = exported(
        Reference(
            ICommercialSubscription,
            title=_("Commercial subscriptions"),
            description=_(
                "An object which contains the timeframe and the voucher "
                "code of a subscription.")))

    commercial_subscription_is_due = exported(
            Bool(
                title=_("Commercial subscription is due"),
                readonly=True,
                description=_(
                    "Whether the project's licensing requires a new "
                    "commercial subscription to use launchpad.")))

    has_current_commercial_subscription = Attribute("""
        Whether the project has a current commercial subscription.""")

    license_status = Attribute("""
        Whether the licence is OPENSOURCE, UNREVIEWED, or PROPRIETARY.""")

    remote_product = exported(
        TextLine(
            title=_('Remote bug tracker project id'), required=False,
            description=_(
                "Some bug trackers host multiple projects at the same URL "
                "and require an identifier for the specific project.")))

    active_or_packaged_series = Attribute(
        _("Series that are active and/or have been packaged."))

    packagings = Attribute(_("All the packagings for the project."))

    security_contact = exported(
        TextLine(
            title=_('Security contact'), required=False, readonly=True,
            description=_('Security contact (obsolete; always None)')),
            ('devel', dict(exported=False)), as_of='1.0')

    vcs = exported(
        Choice(
            title=_("VCS"),
            required=False,
            vocabulary=VCSType,
            description=_(
                "Version control system for this project's code.")))

    inferred_vcs = Choice(
        title=_("Inferred VCS"),
        readonly=True,
        vocabulary=VCSType,
        description=_(
            "Inferred version control system for this project's code."))

    def getAllowedBugInformationTypes():
        """Get the information types that a bug in this project can have.

        :return: A sequence of `InformationType`s.
        """

    def getDefaultBugInformationType():
        """Get the default information type of a new bug in this project.

        :return: The `InformationType`.
        """

    def getVersionSortedSeries(statuses=None, filter_statuses=None):
        """Return all the series sorted by the name field as a version.

        The development focus field is an exception. It will always
        be sorted first.

        :param statuses: If statuses is not None, only include series
                         which are in the given statuses.
        :param filter_statuses: Filter out any series with statuses listed in
                                filter_statuses.
        """

    def redeemSubscriptionVoucher(voucher, registrant, purchaser,
                                  subscription_months, whiteboard=None,
                                  current_datetime=None):
        """Redeem a voucher and extend the subscription expiration date.

        The voucher must have already been verified to be redeemable.
        :param voucher: The voucher id as tracked in the external system.
        :param registrant: Who is redeeming the voucher.
        :param purchaser: Who purchased the voucher.  May not be known.
        :param subscription_months: integer indicating the number of months
            the voucher is for.
        :param whiteboard: Notes for this activity.
        :param current_datetime: Current time.  Will be datetime.now() if not
            specified.
        :return: None
        """

    def getPackage(distroseries):
        """Return a package in that distroseries for this product."""

    @operation_parameters(
        name=TextLine(title=_("Name"), required=True))
    @operation_returns_entry(IProductSeries)
    @export_read_operation()
    def getSeries(name):
        """Return the series for this product for the given name, or None."""

    @operation_parameters(
        version=TextLine(title=_("Version"), required=True))
    @operation_returns_entry(IProductRelease)
    @export_read_operation()
    def getRelease(version):
        """Return the release for this product that has the version given."""

    def getMilestonesAndReleases():
        """Return all the milestones and releases for this product."""

    def packagedInDistros():
        """Returns the distributions this product has been packaged in."""

    def userCanEdit(user):
        """Can the user edit this product?"""

    def getLinkedBugWatches():
        """Return all the bug watches that are linked to this Product.

        Being linked, means that a bug watch having the same bug tracker
        as this Product is using, is linked to a bug task targeted to
        this Product.
        """

    @operation_parameters(
        include_inactive=Bool(title=_("Include inactive"),
                              required=False, default=False))
    @export_read_operation()
    @export_operation_as('get_timeline')
    def getTimeline(include_inactive):
        """Return basic timeline data useful for creating a diagram.
Ejemplo n.º 13
0
class IBugTracker(Interface):
    """A remote bug system.

    Launchpadlib example: What bug tracker is used for a distro source
    package?

    ::

        product = source_package.upstream_product
        if product:
            tracker = product.bug_tracker
            if not tracker:
                project = product.project_group
                if project:
                    tracker = project.bug_tracker
        if tracker:
            print "%s at %s" %(tracker.bug_tracker_type, tracker.base_url)

    """
    export_as_webservice_entry()

    id = Int(title=_('ID'))
    bugtrackertype = exported(
        Choice(title=_('Bug Tracker Type'),
               vocabulary=BugTrackerType,
               default=BugTrackerType.BUGZILLA),
        exported_as='bug_tracker_type')
    name = exported(
        BugTrackerNameField(
            title=_('Name'),
            constraint=name_validator,
            description=_('A URL-friendly name for the bug tracker, '
                          'such as "mozilla-bugs".')))
    title = exported(
        TextLine(
            title=_('Title'),
            description=_('A descriptive label for this tracker to show '
                          'in listings.')))
    summary = exported(
        Text(
            title=_('Summary'),
            description=_(
                'A brief introduction or overview of this bug '
                'tracker instance.'),
            required=False))
    baseurl = exported(
        BugTrackerURL(
            title=_('Location'),
            allowed_schemes=LOCATION_SCHEMES_ALLOWED,
            description=_(
                'The top-level URL for the bug tracker, or an upstream email '
                'address. This must be accurate so that Launchpad can link '
                'to external bug reports.')),
        exported_as='base_url')
    aliases = exported(
        List(
            title=_('Location aliases'),
            description=_(
                'A list of URLs or email addresses that all lead to the '
                'same bug tracker, or commonly seen typos, separated by '
                'whitespace.'),
            value_type=BugTrackerURL(
                allowed_schemes=LOCATION_SCHEMES_ALLOWED),
            required=False),
        exported_as='base_url_aliases')
    owner = exported(
        Reference(title=_('Owner'), schema=Interface),
        exported_as='registrant')
    contactdetails = exported(
        Text(
            title=_('Contact details'),
            description=_(
                'The contact details for the external bug tracker (so that, '
                'for example, its administrators can be contacted about a '
                'security breach).'),
            required=False),
        exported_as='contact_details')
    watches = doNotSnapshot(
        exported(
            CollectionField(
                title=_('The remote watches on this bug tracker.'),
                value_type=Reference(schema=IObject))))
    has_lp_plugin = exported(
        Bool(
            title=_('This bug tracker has a Launchpad plugin installed.'),
            required=False, default=False))
    products = Attribute('The products that use this bug tracker.')
    latestwatches = Attribute('The last 10 watches created.')
    imported_bug_messages = Attribute(
        'Bug messages that have been imported from this bug tracker.')
    multi_product = Attribute(
        "This bug tracker tracks multiple remote products.")
    active = exported(
        Bool(
            title=_('Updates for this bug tracker are enabled'),
            required=True, default=True))

    watches_ready_to_check = Attribute(
        "The set of bug watches that are scheduled to be checked.")
    watches_with_unpushed_comments = Attribute(
        "The set of bug watches that have unpushed comments.")
    watches_needing_update = Attribute(
        "The set of bug watches that need updating.")

    def getBugFilingAndSearchLinks(remote_product, summary=None,
                                   description=None, remote_component=None):
        """Return the bug filing and search links for the tracker.

        :param remote_product: The name of the product on which the bug
            is to be filed or searched for.
        :param summary: The string with which to pre-filly the summary
            field of the upstream bug tracker's search and bug filing forms.
        :param description: The string with which to pre-filly the description
            field of the upstream bug tracker's bug filing form.
        :param remote_component: The name of the component on which the bug
            is to be filed or search for.
        :return: A dict of the absolute URL of the bug filing form and
            the search form for `remote_product` on the remote tracker,
            in the form {'bug_filing_url': foo, 'search_url': bar}. If
            either or both of the URLs is unavailable for the current
            BugTrackerType the relevant values in the dict will be set
            to None. If the bug tracker requires a `remote_product` but
            None is passed, None will be returned for both values in the
            dict.
        """

    def getBugsWatching(remotebug):
        """Get the bugs watching the given remote bug in this bug tracker."""

    def getLinkedPersonByName(name):
        """Return the `IBugTrackerPerson` for a given name on a bugtracker.

        :param name: The name of the person on the bugtracker in
            `bugtracker`.
        :return: an `IBugTrackerPerson`.
        """

    def linkPersonToSelf(name, person):
        """Link a Person to the BugTracker using a given name.

        :param name: The name used for person on bugtracker.
        :param person: The `IPerson` to link to bugtracker.
        :raise BugTrackerPersonAlreadyExists: If `name` has already been
            used to link a person to `bugtracker`.
        :return: An `IBugTrackerPerson`.
        """

    def ensurePersonForSelf(
        display_name, email, rationale, creation_comment):
        """Return the correct `IPerson` for a given name on a bugtracker.

        :param bugtracker: The `IBugTracker` for which we should have a
            given Person.
        :param display_name: The name of the Person on `bugtracker`.
        :param email: The Person's email address if available. If `email`
            is supplied a Person will be created or retrieved using that
            email address and no `IBugTrackerPerson` records will be created.
        :param rationale: The `PersonCreationRationale` used to create a
            new `IPerson` for this `name` and `bugtracker`, if necessary.
        :param creation_comment: The creation comment for the `IPerson`
            if one is created.
         """

    def destroySelf():
        """Delete this bug tracker."""

    def resetWatches(new_next_check=None):
        """Reset the next_check times of this BugTracker's `BugWatch`es.

        :param new_next_check: If specified, contains the datetime to
            which to set the BugWatches' next_check times.  If not
            specified, the watches' next_check times will be set to a
            point between now and 24 hours hence.
        """

    @operation_parameters(
        component_group_name=TextLine(
            title=u"The name of the remote component group", required=True))
    @operation_returns_entry(Interface)
    @export_write_operation()
    def addRemoteComponentGroup(component_group_name):
        """Adds a new component group to the bug tracker"""

    @export_read_operation()
    @operation_returns_collection_of(Interface)
    def getAllRemoteComponentGroups():
        """Return collection of all component groups for this bug tracker"""

    @operation_parameters(
        component_group_name=TextLine(
            title=u"The name of the remote component group",
            required=True))
    @operation_returns_entry(Interface)
    @export_read_operation()
    def getRemoteComponentGroup(component_group_name):
        """Retrieve a given component group registered with the bug tracker.

        :param component_group_name: Name of the component group to retrieve.
        """

    @operation_parameters(
        distribution=TextLine(
            title=u"The distribution for the source package",
            required=True),
        sourcepackagename=TextLine(
            title=u"The source package name",
            required=True))
    @operation_returns_entry(Interface)
    @export_read_operation()
    @operation_for_version('devel')
    def getRemoteComponentForDistroSourcePackageName(
        distribution, sourcepackagename):
        """Returns the component linked to this source package, if any.

        If no components have been linked, returns value of None.
        """

    def getRelatedPillars(user=None):
        """Returns the `IProduct`s and `IProjectGroup`s that use this tracker.
Ejemplo n.º 14
0
class IDistroSeriesPublic(ISeriesMixin, IHasAppointedDriver, IHasOwner,
                          IBugTarget, ISpecificationGoal, IHasMilestones,
                          IHasOfficialBugTags, IHasBuildRecords,
                          IHasTranslationImports, IHasTranslationTemplates,
                          IServiceUsage, IHasExpirableBugs):
    """Public IDistroSeries properties."""

    id = Attribute("The distroseries's unique number.")
    name = exported(
        DistroSeriesNameField(title=_("Name"),
                              required=True,
                              description=_("The name of this series."),
                              constraint=name_validator))
    display_name = exported(TextLine(title=_("Display name"),
                                     required=True,
                                     description=_("The series displayname.")),
                            exported_as="displayname")
    displayname = Attribute("Display name (deprecated)")
    fullseriesname = exported(
        TextLine(title=_("Series full name"),
                 required=False,
                 description=_("The series full name, e.g. Ubuntu Warty")))
    title = exported(
        Title(title=_("Title"),
              required=True,
              description=_(
                  "The title of this series. It should be distinctive "
                  "and designed to look good at the top of a page.")))
    description = exported(
        Description(title=_("Description"),
                    required=True,
                    description=_(
                        "A detailed description of this series, with "
                        "information on the architectures covered, the "
                        "availability of security updates and any other "
                        "relevant information.")))
    version = exported(
        DistroSeriesVersionField(
            title=_("Version"),
            required=True,
            description=_("The version string for this series.")))
    distribution = exported(
        Reference(
            Interface,  # Really IDistribution, see circular import fix below.
            title=_("Distribution"),
            required=True,
            description=_("The distribution for which this is a series.")))
    distributionID = Attribute('The distribution ID.')
    named_version = Attribute('The combined display name and version.')
    parent = Attribute('The structural parent of this series - the distro')
    components = Attribute("The series components.")
    # IComponent is not exported on the api.
    component_names = exported(
        List(value_type=TextLine(),
             title=_(u'The series component names'),
             readonly=True))
    upload_components = Attribute("The series components that can be "
                                  "uploaded to.")
    suite_names = exported(
        List(value_type=TextLine(),
             title=_(u'The series pocket names'),
             readonly=True))
    sections = Attribute("The series sections.")
    status = exported(
        Choice(title=_("Status"), required=True, vocabulary=SeriesStatus))
    datereleased = exported(Datetime(title=_("Date released")))
    previous_series = exported(
        ReferenceChoice(
            title=_("Parent series"),
            description=_("The series from which this one was branched."),
            required=True,
            schema=Interface,  # Really IDistroSeries
            vocabulary='DistroSeries'),
        ("devel", dict(exported_as="previous_series")),
        ("1.0", dict(exported_as="parent_series")),
        ("beta", dict(exported_as="parent_series")),
        readonly=True)
    registrant = exported(
        PublicPersonChoice(title=_("Registrant"),
                           vocabulary='ValidPersonOrTeam'))
    owner = exported(
        Reference(
            IPerson,
            title=_("Owning team of the derived series"),
            readonly=True,
            description=_(
                "This attribute mirrors the owner of the distribution.")))
    date_created = exported(
        Datetime(title=_("The date this series was registered.")))
    driver = exported(
        ReferenceChoice(
            title=_("Driver"),
            description=_(
                "The person or team responsible for decisions about features "
                "and bugs that will be targeted to this series of the "
                "distribution."),
            required=False,
            vocabulary='ValidPersonOrTeam',
            schema=IPerson))
    changeslist = exported(
        TextLine(title=_("Email changes to"),
                 required=True,
                 description=_("The mailing list or other email address that "
                               "Launchpad should notify about new uploads."),
                 constraint=email_validator))
    sourcecount = Attribute("Source Packages Counter")
    defer_translation_imports = Bool(
        title=_("Defer translation imports"),
        description=_("Suspends any translation imports for this series"),
        default=True,
        required=True,
    )
    binarycount = Attribute("Binary Packages Counter")

    architecturecount = Attribute("The number of architectures in this "
                                  "series.")
    nominatedarchindep = exported(
        Reference(
            Interface,  # IDistroArchSeries.
            title=_("DistroArchSeries designed to build "
                    "architecture-independent packages whithin this "
                    "distroseries context."),
            default=None,
            required=False))
    messagecount = Attribute("The total number of translatable items in "
                             "this series.")
    distroserieslanguages = Attribute("The set of dr-languages in this "
                                      "series.")

    hide_all_translations = Bool(
        title=u'Hide translations for this release',
        required=True,
        description=(
            u"You may hide all translation for this distribution series so"
            " that only Launchpad administrators will be able to see them."
            " For example, you should hide these translations while they are"
            " being imported from a previous series so that translators"
            " will not be confused by imports that are in progress."),
        default=True)

    language_pack_base = Choice(title=_('Language pack base'),
                                required=False,
                                description=_('''
            Language pack with the export of all translations
            available for this distribution series when it was generated. The
            subsequent update exports will be generated based on this one.
            '''),
                                vocabulary='FilteredFullLanguagePack')

    language_pack_delta = Choice(title=_('Language pack update'),
                                 required=False,
                                 description=_('''
            Language pack with the export of all translation updates
            available for this distribution series since the language pack
            base was generated.
            '''),
                                 vocabulary='FilteredDeltaLanguagePack')

    language_pack_proposed = Choice(title=_('Proposed language pack update'),
                                    required=False,
                                    description=_('''
            Base or update language pack export that is being tested and
            proposed to be used as the new language pack base or
            language pack update for this distribution series.
            '''),
                                    vocabulary='FilteredLanguagePack')

    language_pack_full_export_requested = exported(
        Bool(title=_('Request a full language pack export'),
             required=True,
             description=_('''
            Whether next language pack generation will be a full export. This
            information is useful when update packs are too big and want to
            merge all those changes in the base pack.
            ''')))

    last_full_language_pack_exported = Object(
        title=_('Latest exported language pack with all translation files.'),
        required=False,
        readonly=True,
        schema=ILanguagePack)

    last_delta_language_pack_exported = Object(title=_(
        'Lastest exported language pack with updated translation files.'),
                                               required=False,
                                               readonly=True,
                                               schema=ILanguagePack)

    # related joins
    packagings = Attribute("All of the Packaging entries for this "
                           "distroseries.")
    specifications = Attribute("The specifications targeted to this "
                               "series.")

    language_packs = Attribute(
        "All language packs associated with this distribution series.")

    backports_not_automatic = Bool(
        title=_("Don't upgrade to backports automatically"),
        required=True,
        description=_("""
            Set NotAutomatic: yes and ButAutomaticUpgrades: yes in Release
            files generated for the backports pocket. This tells apt to
            automatically upgrade within backports, but not into it.
            """))

    include_long_descriptions = exported(
        Bool(title=_("Include long descriptions in Packages rather than in "
                     "Translation-en"),
             default=True,
             required=True,
             description=_("""
                If True, write long descriptions to the per-architecture
                Packages files; if False, write them to a Translation-en
                file common across architectures instead. Using a common
                file reduces the bandwidth footprint of enabling multiarch
                on clients, which requires downloading Packages files for
                multiple architectures.""")))

    index_compressors = exported(
        List(value_type=Choice(vocabulary=IndexCompressionType),
             title=_("Compression types to use for published index files"),
             required=True,
             description=_("""
            A list of compression types to use for published index files
            (Packages, Sources, etc.).""")))

    publish_by_hash = exported(
        Bool(title=_("Publish by-hash directories"),
             required=True,
             description=_("""
            Publish archive index files in by-hash directories so that apt
            can retrieve them based on their hash, avoiding race conditions
            between InRelease and other files during mirror updates.""")))

    advertise_by_hash = exported(
        Bool(title=_("Advertise by-hash directories"),
             required=True,
             description=_("""
            Advertise by-hash directories with a flag in the Release file so
            that apt uses them by default.  Only effective if
            publish_by_hash is also set.""")))

    strict_supported_component_dependencies = exported(Bool(
        title=_("Strict dependencies of supported components"),
        required=True,
        description=_("""
            If True, packages in supported components (main and restricted)
            may not build-depend on packages in unsupported components.  Do
            not rely on the name of this attribute, even for reading; it is
            currently subject to change.""")),
                                                       as_of="devel")

    inherit_overrides_from_parents = Bool(
        title=_("Inherit overrides from parents"),
        readonly=False,
        required=True)

    main_archive = exported(
        Reference(
            Interface,  # Really IArchive, see below for circular import fix.
            title=_('Distribution Main Archive')))

    supported = exported(
        Bool(title=_("Supported"),
             description=_(
                 "Whether or not this series is currently supported.")))

    def isUnstable():
        """Whether or not a distroseries is unstable.

        The distribution is "unstable" until it is released; after that
        point, all development on the Release pocket is stopped and
        development moves on to the other pockets.
        """

    def getLatestUploads():
        """Return the latest five source uploads for this DistroSeries.

        It returns a list containing up to five elements as
        IDistributionSourcePackageRelease instances
        """

    # DistroArchSeries lookup properties/methods.
    architectures = Attribute("All architectures in this series.")

    enabled_architectures = exported(
        doNotSnapshot(
            CollectionField(
                title=_("Enabled architectures"),
                description=_("All architectures in this series with the "
                              "'enabled' flag set."),
                value_type=Reference(schema=Interface),  # IDistroArchSeries
                readonly=True)),
        exported_as="architectures")

    virtualized_architectures = Attribute(
        "All architectures in this series where PPA is supported.")

    buildable_architectures = Attribute(
        "All architectures in this series with available chroot tarball.")

    def __getitem__(archtag):
        """Return the distroarchseries for this distroseries with the
        given architecturetag.
        """

    def __str__():
        """Return the name of the distroseries."""

    def getDistroArchSeriesByProcessor(processor):
        """Return the distroarchseries for this distroseries with the
        given architecturetag from a `IProcessor`.

        :param processor: An `IProcessor`
        :return: An `IDistroArchSeries` or None when none was found.
        """

    @operation_parameters(archtag=TextLine(title=_("The architecture tag"),
                                           required=True))
    @operation_returns_entry(Interface)
    @export_read_operation()
    def getDistroArchSeries(archtag):
        """Return the distroarchseries for this distroseries with the
        given architecturetag.
        """

    # End of DistroArchSeries lookup methods.

    def updateStatistics(ztm):
        """Update all the Rosetta stats for this distro series."""

    def updatePackageCount():
        """Update the binary and source package counts for this distro
        series."""

    @operation_parameters(name=TextLine(
        title=_("The name of the source package"), required=True))
    @operation_returns_entry(ISourcePackage)
    @export_read_operation()
    def getSourcePackage(name):
        """Return a source package in this distro series by name.

        The name given may be a string or an ISourcePackageName-providing
        object. The source package may not be published in the distro series.
        """

    def getTranslatableSourcePackages():
        """Return a list of Source packages in this distribution series
        that can be translated.
        """

    def getPrioritizedUnlinkedSourcePackages():
        """Return a list of package summaries that need packaging links.

        A summary is a dict of package (`ISourcePackage`), total_bugs,
        and total_messages (translatable messages).
        """

    def getPrioritizedPackagings():
        """Return a list of packagings that need more upstream information."""

    def getMostRecentlyLinkedPackagings():
        """Return a list of packagings that are the most recently linked.

        At most five packages are returned of those most recently linked to an
        upstream.
        """

    @operation_parameters(
        created_since_date=Datetime(
            title=_("Created Since Timestamp"),
            description=_(
                "Return items that are more recent than this timestamp."),
            required=False),
        status=Choice(
            vocabulary=PackageUploadStatus,
            title=_("Package Upload Status"),
            description=_("Return only items that have this status."),
            required=False),
        archive=Reference(
            # Really IArchive, patched in _schema_circular_imports.py
            schema=Interface,
            title=_("Archive"),
            description=_("Return only items for this archive."),
            required=False),
        pocket=Choice(
            vocabulary=PackagePublishingPocket,
            title=_("Pocket"),
            description=_("Return only items targeted to this pocket"),
            required=False),
        custom_type=Choice(vocabulary=PackageUploadCustomFormat,
                           title=_("Custom Type"),
                           description=_(
                               "Return only items with custom files of this "
                               "type."),
                           required=False),
        name=TextLine(title=_("Package or file name"), required=False),
        version=TextLine(title=_("Package version"), required=False),
        exact_match=Bool(title=_("Exact match"),
                         description=_(
                             "Whether to filter name and version by exact "
                             "matching."),
                         required=False),
    )
    # Really IPackageUpload, patched in _schema_circular_imports.py
    @operation_returns_collection_of(Interface)
    @export_read_operation()
    def getPackageUploads(status=None,
                          created_since_date=None,
                          archive=None,
                          pocket=None,
                          custom_type=None,
                          name=None,
                          version=None,
                          exact_match=False):
        """Get package upload records for this distribution series.

        :param status: Filter results by this `PackageUploadStatus`, or list
            of statuses.
        :param created_since_date: If specified, only returns items uploaded
            since the timestamp supplied.
        :param archive: Filter results for this `IArchive`.
        :param pocket: Filter results by this `PackagePublishingPocket` or a
            list of `PackagePublishingPocket`.
        :param custom_type: Filter results by this
            `PackageUploadCustomFormat`.
        :param name: Filter results by this file name or package name.
        :param version: Filter results by this version number string.
        :param exact_match: If True, look for exact string matches on the
            `name` and `version` filters.  If False, look for a substring
            match so that e.g. a package "kspreadsheetplusplus" would match
            the search string "spreadsheet".  Defaults to False.
        :return: A result set containing `IPackageUpload`.
        """

    def getUnlinkedTranslatableSourcePackages():
        """Return a list of source packages that can be translated in
        this distribution series but which lack Packaging links.
        """

    def getBinaryPackage(name):
        """Return a DistroSeriesBinaryPackage for this name.

        The name given may be an IBinaryPackageName or a string.  The
        binary package may not be published in the distro series.
        """

    def getCurrentSourceReleases(source_package_names):
        """Get the current release of a list of source packages.

        :param source_package_names: a list of `ISourcePackageName`
            instances.

        :return: a dict where the key is a `ISourcePackage`
            and the value is a `IDistributionSourcePackageRelease`.
        """

    def getPublishedSources(sourcepackage_or_name,
                            pocket=None,
                            version=None,
                            include_pending=False,
                            archive=None):
        """Return the SourcePackagePublishingHistory(s)

        Deprecated.  Use IArchive.getPublishedSources instead.

        Given a ISourcePackageName or name.

        If pocket is not specified, we look in all pockets.

        If version is not specified, return packages with any version.

        If 'include_pending' is True, we return also the pending publication
        records, those packages that will get published in the next publisher
        run (it's only useful when we need to know if a given package is
        known during a publisher run, mostly in pre-upload checks)

        If 'archive' is not specified consider publication in the
        main_archive, otherwise respect the given value.
        """

    def getAllPublishedSources():
        """Return all currently published sources for the distroseries.

        Return publications in the main archives only.
        """

    def getAllUncondemnedSources():
        """Return all uncondemned sources for the distroseries.

        An uncondemned publication is one without scheduleddeletiondate set.

        Return publications in the main archives only.
        """

    def getAllPublishedBinaries():
        """Return all currently published binaries for the distroseries.

        Return publications in the main archives only.
        """

    def getAllUncondemnedBinaries():
        """Return all uncondemned binaries for the distroseries.

        An uncondemned publication is one without scheduleddeletiondate set.

        Return publications in the main archives only.
        """

    def getDistroSeriesLanguage(language):
        """Return the DistroSeriesLanguage for this distroseries and the
        given language, or None if there's no DistroSeriesLanguage for this
        distribution and the given language.
        """

    def getDistroSeriesLanguageOrDummy(language):
        """Return the DistroSeriesLanguage for this distroseries and the
        given language, or a DummyDistroSeriesLanguage.
        """

    def createUploadedSourcePackageRelease(sourcepackagename,
                                           version,
                                           maintainer,
                                           builddepends,
                                           builddependsindep,
                                           architecturehintlist,
                                           component,
                                           creator,
                                           urgency,
                                           changelog,
                                           changelog_entry,
                                           dsc,
                                           dscsigningkey,
                                           section,
                                           dsc_maintainer_rfc822,
                                           dsc_standards_version,
                                           dsc_format,
                                           dsc_binaries,
                                           archive,
                                           copyright,
                                           build_conflicts,
                                           build_conflicts_indep,
                                           dateuploaded=None,
                                           source_package_recipe_build=None,
                                           user_defined_fields=None,
                                           homepage=None,
                                           buildinfo=None):
        """Create an uploads `SourcePackageRelease`.

        Set this distroseries set to be the uploadeddistroseries.

        All arguments are mandatory, they are extracted/built when
        processing and uploaded source package:

         :param dateuploaded: timestamp, if not provided will be UTC_NOW
         :param sourcepackagename: `ISourcePackageName`
         :param version: string, a debian valid version
         :param maintainer: IPerson designed as package maintainer
         :param creator: IPerson, package uploader
         :param component: IComponent
         :param section: ISection
         :param urgency: dbschema.SourcePackageUrgency
         :param dscsigningkey: IGPGKey used to sign the DSC file
         :param dsc: string, original content of the dsc file
         :param copyright: string, the original debian/copyright content
         :param changelog: LFA ID of the debian/changelog file in librarian
         :param changelog_entry: string, changelog extracted from the
                                 changesfile
         :param architecturehintlist: string, DSC architectures
         :param builddepends: string, DSC build dependencies
         :param builddependsindep: string, DSC architecture independent build
                                   dependencies.
         :param build_conflicts: string, DSC Build-Conflicts content
         :param build_conflicts_indep: string, DSC Build-Conflicts-Indep
                                       content
         :param dsc_maintainer_rfc822: string, DSC maintainer field
         :param dsc_standards_version: string, DSC standards version field
         :param dsc_format: string, DSC format version field
         :param dsc_binaries:  string, DSC binaries field
         :param archive: IArchive to where the upload was targeted
         :param dateuploaded: optional datetime, if omitted assumed nowUTC
         :param source_package_recipe_build: optional SourcePackageRecipeBuild
         :param user_defined_fields: optional sequence of key-value pairs with
                                     user defined fields.
         :param homepage: optional string with (unchecked) upstream homepage
                          URL
         :param buildinfo: optional LFA with build information file
         :return: the just creates `SourcePackageRelease`
        """

    def getComponentByName(name):
        """Get the named component.

        Raise NotFoundError if the component is not in the permitted component
        list for this distroseries.
        """

    def getSectionByName(name):
        """Get the named section.

        Raise NotFoundError if the section is not in the permitted section
        list for this distroseries.
        """

    def addSection(section):
        """SQLObject provided method to fill a related join key section."""

    def getBinaryPackagePublishing(archtag, pocket, component, archive):
        """Get BinaryPackagePublishings in a DistroSeries.

        Can optionally restrict the results by architecturetag, pocket and/or
        component.

        If archive is passed, restricted the results to the given archive,
        if it is suppressed the results will be restricted to the
        distribution 'main_archive'.
        """

    def getSourcePackagePublishing(pocket, component, archive):
        """Return a selectResult of ISourcePackagePublishingHistory.

        According status and pocket.
        If archive is passed, restricted the results to the given archive,
        if it is suppressed the results will be restricted to the
        distribution 'main_archive'.
        """

    def searchPackages(text):
        """Search through the packge cache for this distroseries and return
        DistroSeriesBinaryPackage objects that match the given text.
        """

    def createQueueEntry(pocket,
                         archive,
                         changesfilename=None,
                         changesfilecontent=None,
                         changes_file_alias=None,
                         signingkey=None,
                         package_copy_job=None):
        """Create a queue item attached to this distroseries.

        Create a new `PackageUpload` to the given pocket and archive.

        The default state is NEW.  Any further state changes go through
        the Queue state-machine.

        :param pocket: The `PackagePublishingPocket` to upload to.
        :param archive: The `Archive` to upload to.  Must be for the same
            `Distribution` as this series.
        :param changesfilename: Name for the upload's .changes file.  You may
            specify a changes file by passing both `changesfilename` and
            `changesfilecontent`, or by passing `changes_file_alias`.
        :param changesfilecontent: Text for the changes file.  It will be
            signed and stored in the Librarian.  Must be passed together with
            `changesfilename`; alternatively, you may provide a
            `changes_file_alias` to replace both of these.
        :param changes_file_alias: A `LibraryFileAlias` containing the
            .changes file.  Security warning: unless the file has already
            been checked, this may open us up to replay attacks as per bugs
            159304 and 451396.  Use `changes_file_alias` only if you know
            this can't happen.
        :param signingkey: `IGPGKey` used to sign the changes file, or None if
            it is unsigned.
        :return: A new `PackageUpload`.
        """

    def newArch(architecturetag, processor, official, owner, enabled=True):
        """Create a new port or DistroArchSeries for this DistroSeries."""

    def getPOFileContributorsByLanguage(language):
        """People who translated strings to the given language.

        The people that translated only IPOTemplate objects that are not
        current will not appear in the returned list.
        """

    def getSuite(pocket):
        """Return the suite for this distro series and the given pocket.

        :param pocket: A `DBItem` of `PackagePublishingPocket`.
        :return: A string.
        """

    def isSourcePackageFormatPermitted(format):
        """Check if the specified source format is allowed in this series.

        :param format: The SourcePackageFormat to check.
        """

    @operation_returns_collection_of(Interface)
    @export_read_operation()
    def getDerivedSeries():
        """Get all `DistroSeries` derived from this one."""

    @operation_returns_collection_of(Interface)
    @export_read_operation()
    def getParentSeries():
        """Get all parent `DistroSeries`."""

    @operation_parameters(
        parent_series=Reference(
            schema=Interface,  # IDistroSeries
            title=_("The parent series to consider."),
            required=False),
        difference_type=Choice(
            vocabulary=DistroSeriesDifferenceType,
            title=_("Only return differences of this type."),
            required=False),
        source_package_name_filter=TextLine(title=_(
            "Only return differences for packages matching this "
            "name."),
                                            required=False),
        status=Choice(vocabulary=DistroSeriesDifferenceStatus,
                      title=_("Only return differences of this status."),
                      required=False),
        child_version_higher=Bool(title=_(
            "Only return differences for which the child's version "
            "is higher than the parent's."),
                                  required=False),
    )
    @operation_returns_collection_of(Interface)
    @export_read_operation()
    @operation_for_version('devel')
    def getDifferencesTo(parent_series, difference_type,
                         source_package_name_filter, status,
                         child_version_higher):
        """Return the differences between this series and the specified
        parent_series (or all the parent series if parent_series is None).

        :param parent_series: The parent series for which the differences
            should be returned. All parents are considered if this is None.
        :param difference_type: The type of the differences to return.
        :param source_package_name_filter: A package name to use as a filter
            for the differences.
        :param status: The status of the differences to return.
        :param child_version_higher: Only return differences for which the
            child's version is higher than the parent's version.
        """

    def isDerivedSeries():
        """Is this series a derived series?

        A derived series has one or more parent series.
        """

    def isInitializing():
        """Is this series initializing?"""

    def isInitialized():
        """Has this series been initialized?"""

    def getInitializationJob():
        """Get the last `IInitializeDistroSeriesJob` for this series.

        :return: `None` if no job is found or an `IInitializeDistroSeriesJob`.
        """

    @operation_parameters(
        since=Datetime(
            title=_("Minimum creation timestamp"),
            description=_("Ignore comments that are older than this."),
            required=False),
        source_package_name=TextLine(
            title=_("Name of source package"),
            description=_("Only return comments for this source package."),
            required=False))
    @operation_returns_collection_of(Interface)
    @export_read_operation()
    @operation_for_version('devel')
    def getDifferenceComments(since=None, source_package_name=None):
        """Get `IDistroSeriesDifferenceComment` items.
Ejemplo n.º 15
0
class ISourcePackageRecipeView(Interface):
    """IBranch attributes that require launchpad.View permission."""

    id = Int()

    date_created = Datetime(required=True, readonly=True)

    registrant = exported(
        PublicPersonChoice(title=_("The person who created this recipe."),
                           required=True,
                           readonly=True,
                           vocabulary='ValidPersonOrTeam'))

    def getRecipeText(validate=False):
        """Return the text of this recipe.

        :param validate: If True, check that the recipe text can be parsed.
        """

    recipe_text = exported(Text(readonly=True))

    pending_builds = exported(
        doNotSnapshot(
            CollectionField(title=_("The pending builds of this recipe."),
                            description=_(
                                'Pending builds of this recipe, sorted in '
                                'descending order of creation.'),
                            value_type=Reference(schema=Interface),
                            readonly=True)))

    completed_builds = exported(
        doNotSnapshot(
            CollectionField(
                title=_("The completed builds of this recipe."),
                description=_(
                    'Completed builds of this recipe, sorted in '
                    'descending order of finishing (or starting if not'
                    'completed successfully).'),
                value_type=Reference(schema=Interface),
                readonly=True)))

    builds = exported(
        doNotSnapshot(
            CollectionField(
                title=_("All builds of this recipe."),
                description=_(
                    'All builds of this recipe, sorted in '
                    'descending order of finishing (or starting if not'
                    'completed successfully).'),
                value_type=Reference(schema=Interface),
                readonly=True)))

    last_build = exported(
        Reference(Interface,
                  title=_("The the most recent build of this recipe."),
                  readonly=True))

    @call_with(requester=REQUEST_USER)
    @operation_parameters(archive=Reference(schema=IArchive),
                          distroseries=Reference(schema=IDistroSeries),
                          pocket=Choice(vocabulary=PackagePublishingPocket, ))
    @operation_returns_entry(Interface)
    @export_write_operation()
    def requestBuild(archive, distroseries, requester, pocket):
        """Request that the recipe be built in to the specified archive.

        :param archive: The IArchive which you want the build to end up in.
        :param requester: the person requesting the build.
        :param pocket: the pocket that should be targeted.
        :raises: various specific upload errors if the requestor is not
            able to upload to the archive.
        """

    def containsUnbuildableSeries(archive):
        """Does the recipe contain series that can not be built into.
        """

    @export_write_operation()
    def performDailyBuild():
        """Perform a build into the daily build archive."""

    @export_read_operation()
    @operation_for_version("devel")
    def getPendingBuildInfo():
        """Find distroseries and archive data for pending builds.
Ejemplo n.º 16
0
class ISnapView(Interface):
    """`ISnap` attributes that require launchpad.View permission."""

    id = Int(title=_("ID"), required=True, readonly=True)

    date_created = exported(Datetime(
        title=_("Date created"), required=True, readonly=True))

    registrant = exported(PublicPersonChoice(
        title=_("Registrant"), required=True, readonly=True,
        vocabulary="ValidPersonOrTeam",
        description=_("The person who registered this snap package.")))

    source = Attribute(
        "The source branch for this snap package (VCS-agnostic).")

    available_processors = Attribute(
        "The architectures that are available to be enabled or disabled for "
        "this snap package.")

    @call_with(check_permissions=True, user=REQUEST_USER)
    @operation_parameters(
        processors=List(
            value_type=Reference(schema=IProcessor), required=True))
    @export_write_operation()
    @operation_for_version("devel")
    def setProcessors(processors, check_permissions=False, user=None):
        """Set the architectures for which the snap package should be built."""

    def getAllowedArchitectures():
        """Return all distroarchseries that this package can build for.

        :return: Sequence of `IDistroArchSeries` instances.
        """

    can_upload_to_store = exported(Bool(
        title=_("Can upload to store"), required=True, readonly=True,
        description=_(
            "Whether everything is set up to allow uploading builds of this "
            "snap package to the store.")))

    @call_with(requester=REQUEST_USER)
    @operation_parameters(
        archive=Reference(schema=IArchive),
        distro_arch_series=Reference(schema=IDistroArchSeries),
        pocket=Choice(vocabulary=PackagePublishingPocket),
        channels=Dict(
            title=_("Source snap channels to use for this build."),
            description=_(
                "A dictionary mapping snap names to channels to use for this "
                "build.  Currently only 'core' and 'snapcraft' keys are "
                "supported."),
            key_type=TextLine(), required=False))
    # Really ISnapBuild, patched in lp.snappy.interfaces.webservice.
    @export_factory_operation(Interface, [])
    @operation_for_version("devel")
    def requestBuild(requester, archive, distro_arch_series, pocket,
                     channels=None, build_request=None):
        """Request that the snap package be built.

        :param requester: The person requesting the build.
        :param archive: The IArchive to associate the build with.
        :param distro_arch_series: The architecture to build for.
        :param pocket: The pocket that should be targeted.
        :param channels: A dictionary mapping snap names to channels to use
            for this build.
        :param build_request: The `ISnapBuildRequest` job being processed,
            if any.
        :return: `ISnapBuild`.
        """

    @call_with(requester=REQUEST_USER)
    @operation_parameters(
        archive=Reference(schema=IArchive),
        pocket=Choice(vocabulary=PackagePublishingPocket),
        channels=Dict(
            title=_("Source snap channels to use for this build."),
            description=_(
                "A dictionary mapping snap names to channels to use for this "
                "build.  Currently only 'core' and 'snapcraft' keys are "
                "supported."),
            key_type=TextLine(), required=False))
    @export_factory_operation(ISnapBuildRequest, [])
    @operation_for_version("devel")
    def requestBuilds(requester, archive, pocket, channels=None):
        """Request that the snap package be built for relevant architectures.

        This is an asynchronous operation; once the operation has finished,
        the resulting build request's C{status} will be "Completed" and its
        C{builds} collection will return the resulting builds.

        :param requester: The person requesting the builds.
        :param archive: The IArchive to associate the builds with.
        :param pocket: The pocket that should be targeted.
        :param channels: A dictionary mapping snap names to channels to use
            for these builds.
        :return: An `ISnapBuildRequest`.
        """

    def requestBuildsFromJob(requester, archive, pocket, channels=None,
                             allow_failures=False, fetch_snapcraft_yaml=True,
                             build_request=None, logger=None):
        """Synchronous part of `Snap.requestBuilds`.

        Request that the snap package be built for relevant architectures.

        :param requester: The person requesting the builds.
        :param archive: The IArchive to associate the builds with.
        :param pocket: The pocket that should be targeted.
        :param channels: A dictionary mapping snap names to channels to use
            for these builds.
        :param allow_failures: If True, log exceptions other than "already
            pending" from individual build requests; if False, raise them to
            the caller.
        :param fetch_snapcraft_yaml: If True, fetch snapcraft.yaml from the
            appropriate branch or repository and use it to decide which
            builds to request; if False, fall back to building for all
            supported architectures.
        :param build_request: The `ISnapBuildRequest` job being processed,
            if any.
        :param logger: An optional logger.
        :raises CannotRequestAutoBuilds: if fetch_snapcraft_yaml is False
            and self.distro_series is not set.
        :return: A sequence of `ISnapBuild` instances.
        """

    def getBuildRequest(job_id):
        """Get an asynchronous build request by ID.

        :param job_id: The ID of the build request.
        :return: `ISnapBuildRequest`.
        """

    pending_build_requests = exported(doNotSnapshot(CollectionField(
        title=_("Pending build requests for this snap package."),
        value_type=Reference(ISnapBuildRequest),
        required=True, readonly=True)))

    failed_build_requests = exported(doNotSnapshot(CollectionField(
        title=_("Failed build requests for this snap package."),
        value_type=Reference(ISnapBuildRequest),
        required=True, readonly=True)))

    # XXX cjwatson 2018-06-20: Deprecated as an exported method; can become
    # an internal helper method once production JavaScript no longer uses
    # it.
    @operation_parameters(
        snap_build_ids=List(
            title=_("A list of snap build IDs."), value_type=Int()))
    @export_read_operation()
    @operation_for_version("devel")
    def getBuildSummariesForSnapBuildIds(snap_build_ids):
        """Return a dictionary containing a summary of the build statuses.

        :param snap_build_ids: A list of snap build IDs.
        :type source_ids: ``list``
        :return: A dict consisting of the overall status summaries for the
            given snap builds.
        """

    @call_with(user=REQUEST_USER)
    @operation_parameters(
        request_ids=List(
            title=_("A list of snap build request IDs."), value_type=Int(),
            required=False),
        build_ids=List(
            title=_("A list of snap build IDs."), value_type=Int(),
            required=False))
    @export_read_operation()
    @operation_for_version("devel")
    def getBuildSummaries(request_ids=None, build_ids=None, user=None):
        """Return a dictionary containing a summary of build information.

        :param request_ids: A list of snap build request IDs.
        :param build_ids: A list of snap build IDs.
        :param user: The `IPerson` requesting this information.
        :return: A dict of {"requests", "builds"}, consisting of the overall
            status summaries for the given snap build requests and snap
            builds respectively.
        """

    builds = exported(doNotSnapshot(CollectionField(
        title=_("All builds of this snap package."),
        description=_(
            "All builds of this snap package, sorted in descending order "
            "of finishing (or starting if not completed successfully)."),
        # Really ISnapBuild, patched in lp.snappy.interfaces.webservice.
        value_type=Reference(schema=Interface), readonly=True)))

    completed_builds = exported(doNotSnapshot(CollectionField(
        title=_("Completed builds of this snap package."),
        description=_(
            "Completed builds of this snap package, sorted in descending "
            "order of finishing."),
        # Really ISnapBuild, patched in lp.snappy.interfaces.webservice.
        value_type=Reference(schema=Interface), readonly=True)))

    pending_builds = exported(doNotSnapshot(CollectionField(
        title=_("Pending builds of this snap package."),
        description=_(
            "Pending builds of this snap package, sorted in descending "
            "order of creation."),
        # Really ISnapBuild, patched in lp.snappy.interfaces.webservice.
        value_type=Reference(schema=Interface), readonly=True)))
Ejemplo n.º 17
0
class IGitRepositoryView(IHasRecipes):
    """IGitRepository attributes that require launchpad.View permission."""

    id = Int(title=_("ID"), readonly=True, required=True)

    date_created = exported(
        Datetime(title=_("Date created"), required=True, readonly=True))

    repository_type = exported(
        Choice(
            title=_("Repository type"),
            required=True,
            readonly=True,
            vocabulary=GitRepositoryType,
            description=_(
                "The way this repository is hosted: directly on Launchpad, or "
                "imported from somewhere else.")))

    registrant = exported(
        PublicPersonChoice(
            title=_("Registrant"),
            required=True,
            readonly=True,
            vocabulary="ValidPersonOrTeam",
            description=_("The person who registered this Git repository.")))

    owner = exported(
        PersonChoice(
            title=_("Owner"),
            required=True,
            readonly=True,
            vocabulary="AllUserTeamsParticipationPlusSelf",
            description=_(
                "The owner of this Git repository. This controls who can modify "
                "the repository.")))

    target = exported(Reference(
        title=_("Target"),
        required=True,
        readonly=True,
        schema=IHasGitRepositories,
        description=_("The target of the repository.")),
                      as_of="devel")

    namespace = Attribute(
        "The namespace of this repository, as an `IGitNamespace`.")

    # XXX cjwatson 2015-01-29: Add some advice about default repository
    # naming.
    name = exported(
        TextLine(
            title=_("Name"),
            required=True,
            readonly=True,
            constraint=git_repository_name_validator,
            description=_(
                "The repository name. Keep very short, unique, and descriptive, "
                "because it will be used in URLs.")))

    information_type = exported(
        Choice(title=_("Information type"),
               vocabulary=InformationType,
               required=True,
               readonly=True,
               default=InformationType.PUBLIC,
               description=_(
                   "The type of information contained in this repository.")))

    owner_default = exported(
        Bool(title=_("Owner default"),
             required=True,
             readonly=True,
             description=_(
                 "Whether this repository is the default for its owner and "
                 "target.")))

    target_default = exported(
        Bool(title=_("Target default"),
             required=True,
             readonly=True,
             description=_(
                 "Whether this repository is the default for its target.")))

    unique_name = exported(
        Text(
            title=_("Unique name"),
            readonly=True,
            description=_(
                "Unique name of the repository, including the owner and project "
                "names.")))

    display_name = exported(
        Text(title=_("Display name"),
             readonly=True,
             description=_("Display name of the repository.")))

    code_reviewer = Attribute(
        "The reviewer if set, otherwise the owner of the repository.")

    shortened_path = Attribute(
        "The shortest reasonable version of the path to this repository.")

    @operation_parameters(reviewer=Reference(
        title=_("A person for which the reviewer status is in question."),
        schema=IPerson))
    @export_read_operation()
    @operation_for_version('devel')
    def isPersonTrustedReviewer(reviewer):
        """Return true if the `reviewer` is a trusted reviewer.

        The reviewer is trusted if they either own the repository, or are in
        the team that owns the repository, or they are in the review team
        for the repository.
        """

    git_identity = exported(
        Text(
            title=_("Git identity"),
            readonly=True,
            description=_(
                "If this is the default repository for some target, then this is "
                "'lp:' plus a shortcut version of the path via that target.  "
                "Otherwise it is simply 'lp:' plus the unique name.")))

    identity = Attribute(
        "The identity of this repository: a VCS-independent synonym for "
        "git_identity.")

    git_https_url = exported(
        TextLine(
            title=_("HTTPS URL"),
            readonly=True,
            description=_(
                "An HTTPS URL for this repository, or None in the case of private "
                "repositories.")))

    git_ssh_url = exported(
        TextLine(title=_("SSH URL"),
                 readonly=True,
                 description=_("A git+ssh:// URL for this repository.")))

    refs = exported(
        doNotSnapshot(
            CollectionField(
                title=_("The references present in this repository."),
                readonly=True,
                # Really IGitRef, patched in _schema_circular_imports.py.
                value_type=Reference(Interface))))

    branches = exported(
        doNotSnapshot(
            CollectionField(
                title=_("The branch references present in this repository."),
                readonly=True,
                # Really IGitRef, patched in _schema_circular_imports.py.
                value_type=Reference(Interface))))

    branches_by_date = Attribute(
        "The branch references present in this repository, ordered by last "
        "commit date.")

    subscriptions = exported(
        CollectionField(
            title=_("GitSubscriptions associated with this repository."),
            readonly=True,
            # Really IGitSubscription, patched in _schema_circular_imports.py.
            value_type=Reference(Interface)))

    subscribers = exported(
        CollectionField(title=_("Persons subscribed to this repository."),
                        readonly=True,
                        value_type=Reference(IPerson)))

    code_import = exported(
        Reference(
            title=_("The associated CodeImport, if any."),
            # Really ICodeImport, patched in _schema_circular_imports.py.
            schema=Interface))

    rules = Attribute("The access rules for this repository.")

    grants = Attribute("The access grants for this repository.")

    @operation_parameters(
        path=TextLine(title=_("A string to look up as a path.")))
    # Really IGitRef, patched in _schema_circular_imports.py.
    @operation_returns_entry(Interface)
    @export_read_operation()
    @operation_for_version("devel")
    def getRefByPath(path):
        """Look up a single reference in this repository by path.

        :param path: A string to look up as a path.

        :return: An `IGitRef`, or None.
        """

    def createOrUpdateRefs(refs_info, get_objects=False, logger=None):
        """Create or update a set of references in this repository.

        :param refs_info: A dict mapping ref paths to
            {"sha1": sha1, "type": `GitObjectType`}.
        :param get_objects: Return the created/updated references.
        :param logger: An optional logger.

        :return: A list of the created/updated references if get_objects,
            otherwise None.
        """

    def removeRefs(paths):
        """Remove a set of references in this repository.

        :params paths: An iterable of paths.
        """

    def planRefChanges(hosting_path, logger=None):
        """Plan ref changes based on information from the hosting service.

        :param hosting_path: A path on the hosting service.
        :param logger: An optional logger.

        :return: A dict of refs to create or update as appropriate, mapping
            ref paths to dictionaries of their fields; and a set of ref
            paths to remove.
        """

    def fetchRefCommits(hosting_path, refs, logger=None):
        """Fetch commit information from the hosting service for a set of refs.

        :param hosting_path: A path on the hosting service.
        :param refs: A dict mapping ref paths to dictionaries of their
            fields; the field dictionaries will be updated with any detailed
            commit information that is available.
        :param logger: An optional logger.
        """

    def synchroniseRefs(refs_to_upsert, refs_to_remove, logger=None):
        """Synchronise references with those from the hosting service.

        :param refs_to_upsert: A dictionary mapping ref paths to
            dictionaries of their fields; these refs will be created or
            updated as appropriate.
        :param refs_to_remove: A set of ref paths to remove.
        :param logger: An optional logger.
        """

    def setOwnerDefault(value):
        """Set whether this repository is the default for its owner-target.

        This is for internal use; the caller should ensure permission to
        edit the owner, should arrange to remove any existing owner-target
        default, and should check that this repository is attached to the
        desired target.

        :param value: True if this repository should be the owner-target
            default, otherwise False.
        """

    def setTargetDefault(value):
        """Set whether this repository is the default for its target.

        This is for internal use; the caller should ensure permission to
        edit the target, should arrange to remove any existing target
        default, and should check that this repository is attached to the
        desired target.

        :param value: True if this repository should be the target default,
            otherwise False.
        """

    def getCodebrowseUrl():
        """Construct a browsing URL for this Git repository."""

    def getCodebrowseUrlForRevision(commit):
        """The URL to the commit of the merge to the target branch"""

    def getLatestScanJob():
        """Return the last IGitRefScanJobSource for this repository"""

    def visibleByUser(user):
        """Can the specified user see this repository?"""

    def getAllowedInformationTypes(user):
        """Get a list of acceptable `InformationType`s for this repository.

        If the user is a Launchpad admin, any type is acceptable.
        """

    def getInternalPath():
        """Get the internal path to this repository.

        This is used on the storage backend.
        """

    def getRepositoryDefaults():
        """Return a sorted list of `ICanHasDefaultGitRepository` objects.

        There is one result for each related object for which this
        repository is the default.  For example, in the case where a
        repository is the default for a project and is also its owner's
        default repository for that project, the objects for both the
        project and the person-project are returned.

        More important related objects are sorted first.
        """

    # Marker for references to Git URL layouts: ##GITNAMESPACE##
    def getRepositoryIdentities():
        """A list of aliases for a repository.

        Returns a list of tuples of path and context object.  There is at
        least one alias for any repository, and that is the repository
        itself.  For default repositories, the context object is the
        appropriate default object.

        Where a repository is the default for a product or a distribution
        source package, the repository is available through a number of
        different URLs.  These URLs are the aliases for the repository.

        For example, a repository which is the default for the 'fooix'
        project and which is also its owner's default repository for that
        project is accessible using:
          fooix - the context object is the project fooix
          ~fooix-owner/fooix - the context object is the person-project
              ~fooix-owner and fooix
          ~fooix-owner/fooix/+git/fooix - the unique name of the repository
              where the context object is the repository itself.
        """

    def userCanBeSubscribed(person):
        """Return True if the `IPerson` can be subscribed to the repository."""

    @operation_parameters(
        person=Reference(title=_("The person to subscribe."), schema=IPerson),
        notification_level=Choice(
            title=_("The level of notification to subscribe to."),
            vocabulary=BranchSubscriptionNotificationLevel),
        max_diff_lines=Choice(
            title=_("The max number of lines for diff email."),
            vocabulary=BranchSubscriptionDiffSize),
        code_review_level=Choice(
            title=_("The level of code review notification emails."),
            vocabulary=CodeReviewNotificationLevel))
    # Really IGitSubscription, patched in _schema_circular_imports.py.
    @operation_returns_entry(Interface)
    @call_with(subscribed_by=REQUEST_USER)
    @export_write_operation()
    @operation_for_version("devel")
    def subscribe(person, notification_level, max_diff_lines,
                  code_review_level, subscribed_by):
        """Subscribe this person to the repository.

        :param person: The `Person` to subscribe.
        :param notification_level: The kinds of repository changes that
            cause notification.
        :param max_diff_lines: The maximum number of lines of diff that may
            appear in a notification.
        :param code_review_level: The kinds of code review activity that
            cause notification.
        :param subscribed_by: The person who is subscribing the subscriber.
            Most often the subscriber themselves.
        :return: A new or existing `GitSubscription`.
        """

    @operation_parameters(person=Reference(title=_("The person to search for"),
                                           schema=IPerson))
    # Really IGitSubscription, patched in _schema_circular_imports.py.
    @operation_returns_entry(Interface)
    @export_read_operation()
    @operation_for_version("devel")
    def getSubscription(person):
        """Return the `GitSubscription` for this person."""

    def hasSubscription(person):
        """Is this person subscribed to the repository?"""

    @operation_parameters(person=Reference(
        title=_("The person to unsubscribe"), schema=IPerson))
    @call_with(unsubscribed_by=REQUEST_USER)
    @export_write_operation()
    @operation_for_version("devel")
    def unsubscribe(person, unsubscribed_by):
        """Remove the person's subscription to this repository.

        :param person: The person or team to unsubscribe from the repository.
        :param unsubscribed_by: The person doing the unsubscribing.
        """

    def getSubscriptionsByLevel(notification_levels):
        """Return the subscriptions that are at the given notification levels.

        :param notification_levels: An iterable of
            `BranchSubscriptionNotificationLevel`s.
        :return: A `ResultSet`.
        """

    def getNotificationRecipients():
        """Return a complete INotificationRecipientSet instance.

        The INotificationRecipientSet instance contains the subscribers
        and their subscriptions.
        """

    landing_targets = Attribute(
        "A collection of the merge proposals where this repository is "
        "the source.")
    _api_landing_targets = exported(
        CollectionField(
            title=_("Landing targets"),
            description=_(
                "A collection of the merge proposals where this repository is "
                "the source."),
            readonly=True,
            # Really IBranchMergeProposal, patched in
            # _schema_circular_imports.py.
            value_type=Reference(Interface)),
        exported_as="landing_targets")
    landing_candidates = Attribute(
        "A collection of the merge proposals where this repository is "
        "the target.")
    _api_landing_candidates = exported(
        CollectionField(
            title=_("Landing candidates"),
            description=_(
                "A collection of the merge proposals where this repository is "
                "the target."),
            readonly=True,
            # Really IBranchMergeProposal, patched in
            # _schema_circular_imports.py.
            value_type=Reference(Interface)),
        exported_as="landing_candidates")
    dependent_landings = exported(
        CollectionField(
            title=_("Dependent landings"),
            description=_(
                "A collection of the merge proposals that are dependent on this "
                "repository."),
            readonly=True,
            # Really IBranchMergeProposal, patched in _schema_circular_imports.py.
            value_type=Reference(Interface)))

    def getPrecachedLandingTargets(user):
        """Return precached landing targets.

        Target and prerequisite repositories are preloaded.
        """

    def getPrecachedLandingCandidates(user):
        """Return precached landing candidates.

        Source and prerequisite repositories are preloaded.
        """

    @operation_parameters(
        status=List(title=_("A list of merge proposal statuses to filter by."),
                    value_type=Choice(vocabulary=BranchMergeProposalStatus)),
        merged_revision_ids=List(
            TextLine(title=_('The target revision ID of the merge.'))))
    @call_with(visible_by_user=REQUEST_USER)
    # Really IBranchMergeProposal, patched in _schema_circular_imports.py.
    @operation_returns_collection_of(Interface)
    @export_read_operation()
    @operation_for_version("devel")
    def getMergeProposals(status=None,
                          visible_by_user=None,
                          merged_revision_ids=None,
                          eager_load=False):
        """Return matching BranchMergeProposals."""

    def getMergeProposalByID(id):
        """Return this repository's merge proposal with this id, or None."""

    def isRepositoryMergeable(other):
        """Is the other repository mergeable into this one (or vice versa)?"""

    pending_updates = Attribute(
        "Whether there are recent changes in this repository that have not "
        "yet been scanned.")

    def updateMergeCommitIDs(paths):
        """Update commit SHA1s of merge proposals for this repository.

        The *_git_commit_sha1 columns of merge proposals are stored
        explicitly in order that merge proposals are still meaningful after
        associated refs have been deleted.  However, active merge proposals
        where the refs in question still exist should have these columns
        kept up to date.
        """

    def updateLandingTargets(paths):
        """Update landing targets (MPs where this repository is the source).

        For each merge proposal, create `UpdatePreviewDiffJob`s.

        :param paths: A list of reference paths.  Any merge proposals whose
            source is this repository and one of these paths will have their
            diffs updated.
        """

    def markRecipesStale(paths):
        """Mark recipes associated with this repository as stale.

        :param paths: A list of reference paths.  Any recipes that include
            an entry that points to this repository and that have a
            `revspec` that is one of these paths will be marked as stale.
        """

    def markSnapsStale(paths):
        """Mark snap packages associated with this repository as stale.

        :param paths: A list of reference paths.  Any snap packages that
            include an entry that points to this repository and that are
            based on one of these paths will be marked as stale.
        """

    def detectMerges(paths, logger=None):
        """Detect merges of landing candidates.

        :param paths: A list of reference paths.  Any merge proposals whose
            target is this repository and one of these paths will be
            checked.
        :param logger: An optional logger.
        """

    def getBlob(filename, rev=None):
        """Get a blob by file name from this repository.

        :param filename: Relative path of a file in the repository.
        :param rev: An optional revision. Defaults to 'HEAD'.
        :return: A binary string with the blob content.
        """

    def getDiff(old, new):
        """Get the diff between two commits in this repository.

        :param old: The OID of the old commit.
        :param new: The OID of the new commit.
        :return: The diff as a binary string.
        """

    def getRule(ref_pattern):
        """Get the access rule for this repository with a given pattern.

        :param ref_pattern: The reference pattern that the rule should have.
        :return: An `IGitRule`, or None.
        """

    def getActivity(changed_after=None):
        """Get activity log entries for this repository.

        :param changed_after: If supplied, only return entries for changes
            made after this date.
        :return: A `ResultSet` of `IGitActivity`.
        """

    def getPrecachedActivity(**kwargs):
        """Activity log entries are preloaded.
Ejemplo n.º 18
0
class IBugView(Interface):
    """IBug attributes that require launchpad.View permission."""

    name = exported(
        BugNameField(title=_('Nickname'),
                     required=False,
                     description=_("""A short and unique name.
                Add one only if you often need to retype the URL
                but have trouble remembering the bug number."""),
                     constraint=bug_name_validator))
    title = exported(
        Title(title=_('Summary'),
              required=True,
              description=_("""A one-line summary of the problem.""")))
    description = exported(
        Description(title=_('Description'),
                    required=True,
                    description=_("""A detailed description of the problem,
                 including the steps required to reproduce it."""),
                    strip_text=True,
                    trailing_only=True,
                    min_length=1,
                    max_length=50000))
    ownerID = Int(title=_('Owner'), required=True, readonly=True)
    owner = exported(
        Reference(IPerson, title=_("The owner's IPerson"), readonly=True))
    bugtasks = exported(CollectionField(title=_(
        'BugTasks on this bug, sorted upstream, then '
        'by ubuntu, then by other distroseries.'),
                                        value_type=Reference(schema=IBugTask),
                                        readonly=True),
                        exported_as='bug_tasks')
    default_bugtask = Reference(
        title=_("The first bug task to have been filed."), schema=IBugTask)
    duplicateof = exported(DuplicateBug(title=_('Duplicate Of'),
                                        required=False,
                                        readonly=True),
                           exported_as='duplicate_of')
    datecreated = exported(Datetime(title=_('Date Created'),
                                    required=True,
                                    readonly=True),
                           exported_as='date_created')
    displayname = TextLine(title=_("Text of the form 'Bug #X"), readonly=True)
    activity = exported(
        doNotSnapshot(
            CollectionField(
                title=_('Log of activity that has occurred on this bug.'),
                value_type=Reference(schema=IBugActivity),
                readonly=True)))
    affected_pillars = Attribute(
        'The "pillars", products or distributions, affected by this bug.')
    permits_expiration = Bool(
        title=_("Does the bug's state permit expiration?"),
        description=_(
            "Expiration is permitted when the bug is not valid anywhere, "
            "a message was sent to the bug reporter, and the bug is "
            "associated with pillars that have enabled bug expiration."),
        readonly=True)
    can_expire = exported(Bool(title=_(
        "Can the Incomplete bug expire? "
        "Expiration may happen when the bug permits expiration, "
        "and a bugtask cannot be confirmed."),
                               readonly=True), ('devel', dict(exported=False)),
                          exported=True)
    subscriptions = exported(
        doNotSnapshot(
            CollectionField(title=_('Subscriptions'),
                            value_type=Reference(schema=Interface),
                            readonly=True)))
    date_last_updated = exported(
        Datetime(title=_('Date Last Updated'), required=True, readonly=True))
    is_complete = Bool(
        title=_("Is Complete?"),
        description=_(
            "True or False depending on whether this bug is considered "
            "completely addressed. A bug in Launchpad is completely "
            "addressed when there are no tasks that are still open for "
            "the bug."),
        readonly=True)
    official_tags = Attribute("The official bug tags relevant to this bug.")
    who_made_private = exported(
        PublicPersonChoice(
            title=_('Who Made Private'),
            required=False,
            vocabulary='ValidPersonOrTeam',
            description=_("The person who set this bug private."),
            readonly=True))
    date_made_private = exported(
        Datetime(title=_('Date Made Private'), required=False, readonly=True))
    heat = exported(
        Int(title=_("The 'heat' of the bug"), required=False, readonly=True))
    watches = exported(CollectionField(
        title=_("All bug watches associated with this bug."),
        value_type=Object(schema=IBugWatch),
        readonly=True),
                       exported_as='bug_watches')
    cves = exported(
        CollectionField(title=_('CVE entries related to this bug.'),
                        value_type=Reference(schema=ICve),
                        readonly=True))
    has_cves = Bool(title=u"True if the bug has cve entries.")
    cve_links = Attribute('Links between this bug and CVE entries.')
    duplicates = exported(
        CollectionField(
            title=_("MultiJoin of bugs which are dupes of this one."),
            value_type=BugField(),
            readonly=True))
    # See lp.bugs.model.bug.Bug.attachments for why there are two similar
    # properties here.
    # attachments_unpopulated would more naturally be attachments, and
    # attachments be attachments_prepopulated, but lazr.resful cannot
    # export over a non-exported attribute in an interface.
    # https://bugs.launchpad.net/lazr.restful/+bug/625102
    attachments_unpopulated = CollectionField(
        title=_("List of bug attachments."),
        value_type=Reference(schema=IBugAttachment),
        readonly=True)
    attachments = doNotSnapshot(
        exported(
            CollectionField(title=_("List of bug attachments."),
                            value_type=Reference(schema=IBugAttachment),
                            readonly=True)))
    security_related = exported(
        Bool(title=_("This bug is a security vulnerability."),
             required=False,
             readonly=True))
    has_patches = Attribute("Does this bug have any patches?")
    latest_patch_uploaded = exported(
        Datetime(title=_('Date when the most recent patch was uploaded.'),
                 required=False,
                 readonly=True))
    latest_patch = Attribute("The most recent patch of this bug.")
    initial_message = Attribute(
        "The message that was specified when creating the bug")
    questions = Attribute("List of questions related to this bug.")
    specifications = Attribute("List of related specifications.")
    tags = exported(
        List(title=_("Tags"),
             description=_("Space-separated keywords for classifying "
                           "this bug report."),
             value_type=Tag(),
             required=False))
    messages = doNotSnapshot(
        CollectionField(title=_(
            "The messages related to this object, in reverse "
            "order of creation (so newest first)."),
                        readonly=True,
                        value_type=Reference(schema=IMessage)))
    followup_subject = Attribute("The likely subject of the next message.")
    date_last_message = exported(
        Datetime(title=_("Date of last bug message"),
                 required=False,
                 readonly=True))
    number_of_duplicates = exported(
        Int(title=_('The number of bugs marked as duplicates of this bug'),
            required=True,
            readonly=True))
    message_count = exported(
        Int(title=_('The number of comments on this bug'),
            required=True,
            readonly=True))
    users_affected_count = exported(
        Int(title=_('The number of users affected by this bug '
                    '(not including duplicates)'),
            required=True,
            readonly=True))
    users_unaffected_count = exported(
        # We don't say "(not including duplicates)" here because
        # affected and unaffected are asymmetrical that way.  If a dup
        # affects you, then the master bug affects you; but if a dup
        # *doesn't* affect you, the master bug may or may not affect
        # you, since a dup is often a specific symptom of a more
        # general master bug.
        Int(title=_('The number of users unaffected by this bug'),
            required=True,
            readonly=True))
    users_affected = exported(
        doNotSnapshot(
            CollectionField(title=_('The number of users affected by this bug '
                                    '(not including duplicates)'),
                            value_type=Reference(schema=IPerson),
                            readonly=True)))
    users_unaffected = exported(
        doNotSnapshot(
            CollectionField(title=_('Users explicitly marked as unaffected '
                                    '(not including duplicates)'),
                            value_type=Reference(schema=IPerson),
                            readonly=True)))
    users_affected_count_with_dupes = exported(
        Int(title=_('The number of users affected by this bug '
                    '(including duplicates)'),
            required=True,
            readonly=True))
    other_users_affected_count_with_dupes = exported(
        Int(title=_('The number of users affected by this bug '
                    '(including duplicates), excluding the current user'),
            required=True,
            readonly=True))
    users_affected_with_dupes = exported(
        doNotSnapshot(
            CollectionField(title=_('Users affected (including duplicates)'),
                            value_type=Reference(schema=IPerson),
                            readonly=True)))
    # Adding related BugMessages provides a hook for getting at
    # BugMessage.message.visible when building bug comments.
    bug_messages = Attribute('The bug messages related to this object.')
    comment_count = Attribute(
        "The number of comments on this bug, not including the initial "
        "comment.")
    indexed_messages = doNotSnapshot(
        exported(CollectionField(title=_(
            "The messages related to this object, in reverse "
            "order of creation (so newest first)."),
                                 readonly=True,
                                 value_type=Reference(schema=IMessage)),
                 exported_as='messages'))

    def getSpecifications(user):
        """List of related specifications that the user can view."""

    def _indexed_messages(include_content=False, include_parents=False):
        """Low level query for getting bug messages.

        :param include_content: If True retrieve the content for the messages
            too.
        :param include_parents: If True retrieve the object for parent
            messages too. If False the parent attribute will be *forced* to
            None to prevent lazy evaluation triggering database lookups.
        """

    def hasBranch(branch):
        """Is this branch linked to this bug?"""

    def isSubscribed(person):
        """Is person subscribed to this bug?

        Returns True if the user is explicitly subscribed to this bug
        (no matter what the type of subscription), otherwise False.

        If person is None, the return value is always False.
        """

    def isSubscribedToDupes(person):
        """Is person directly subscribed to dupes of this bug?

        Returns True if the user is directly subscribed to at least one
        duplicate of this bug, otherwise False.
        """

    def isMuted(person):
        """Does person have a muted subscription on this bug?

        :returns: True if the user has muted all email from this bug.
        """

    def getDirectSubscriptions():
        """A sequence of IBugSubscriptions directly linked to this bug."""

    def getDirectSubscribers(recipients=None, level=None):
        """A list of IPersons that are directly subscribed to this bug.

        Direct subscribers have an entry in the BugSubscription table.
        """

    def getDirectSubscribersWithDetails():
        """Get direct subscribers and their subscriptions for the bug.

        Those with muted bug subscriptions are excluded from results.

        :returns: A ResultSet of tuples (Person, BugSubscription)
            representing a subscriber and their bug subscription.
        """

    def getIndirectSubscribers(recipients=None, level=None):
        """Return IPersons that are indirectly subscribed to this bug.

        Indirect subscribers get bugmail, but don't have an entry in the
        BugSubscription table. This subscribers from dupes, etc.
        """

    def getAlsoNotifiedSubscribers(recipients=None, level=None):
        """Return IPersons in the "Also notified" subscriber list.

        This includes assignees, but not subscribers from duplicates.
        """

    def getSubscriptionsFromDuplicates():
        """Return IBugSubscriptions subscribed from dupes of this bug."""

    def getSubscribersFromDuplicates():
        """Return IPersons subscribed from dupes of this bug."""

    def getSubscribersForPerson(person):
        """Find the persons or teams by which person is subscribed.

        This call should be quite cheap to make and performs a single query.

        :return: An IResultSet.
        """

    def getSubscriptionForPerson(person):
        """Return the `BugSubscription` for a `Person` to this `Bug`.

        If no such `BugSubscription` exists, return None.
        """

    def getSubscriptionInfo(level=None):
        """Return a `BugSubscriptionInfo` at the given `level`.

        :param level: A member of `BugNotificationLevel`. Defaults to
            `BugSubscriptionLevel.LIFECYCLE` if unspecified.
        """

    def getBugNotificationRecipients(level=BugNotificationLevel.LIFECYCLE):
        """Return a complete INotificationRecipientSet instance.

        The INotificationRecipientSet instance will contain details of
        all recipients for bug notifications sent by this bug; this
        includes email addresses and textual and header-ready
        rationales. See `BugNotificationRecipients` for
        details of this implementation.
        """

    def clearBugNotificationRecipientsCache():
        """Clear the bug notification recipient BugNotificationLevel cache.

        Call this when a change to a bug or bugtask would change the
        notification recipients. Changing a a bugtask's milestone or
        target is such a case.
        """

    def canBeAQuestion():
        """Return True of False if a question can be created from this bug.

        A Question can be created from a bug if:
        1. There is only one bugtask with a status of New, Incomplete,
           Confirmed, or Wont Fix. Any other bugtasks must be Invalid.
        2. The bugtask's target uses Launchpad to track bugs.
        3. The bug was not made into a question previously.
        """

    def getQuestionCreatedFromBug():
        """Return the question created from this Bug, or None."""

    def getMessagesForView(slice_info):
        """Return BugMessage,Message,MessageChunks for renderinger.

        This eager loads message.owner validity associated with the
        bugmessages.

        :param slice_info: Either None or a list of slices to constraint the
            returned rows. The step parameter in each slice is ignored.
        """

    @operation_parameters(target=Reference(schema=Interface,
                                           title=_('Target')))
    @export_read_operation()
    def canBeNominatedFor(target):
        """Can this bug nominated for this target?

        :nomination_target: An IDistroSeries or IProductSeries.

        Returns True or False.
        """

    @operation_parameters(target=Reference(schema=Interface,
                                           title=_('Target')))
    @operation_returns_entry(Interface)
    @export_read_operation()
    def getNominationFor(target):
        """Return the IBugNomination for the target.

        If no nomination is found, a NotFoundError is raised.

        :param nomination_target: An IDistroSeries or IProductSeries.
        """

    @operation_parameters(
        target=Reference(schema=Interface, title=_('Target'), required=False),
        nominations=List(
            title=_("Nominations to search through."),
            value_type=Reference(schema=Interface),  # IBugNomination
            required=False))
    @operation_returns_collection_of(Interface)  # IBugNomination
    @export_read_operation()
    def getNominations(target=None, nominations=None):
        """Return a list of all IBugNominations for this bug.

        The list is ordered by IBugNominations.target.bugtargetdisplayname.

        :param target: An IProduct or IDistribution. Only nominations
            for this target are returned.
        :param nominations: The list of nominations to search through.
            If none is given, the bug's nominations are looked through.
            This can be useful when having to call this method multiple
            times, to avoid getting the list of nominations each time.
        """

    def getBugWatch(bugtracker, remote_bug):
        """Return the BugWatch that has the given bugtracker and remote bug.

        Return None if this bug doesn't have such a bug watch.
        """

    def getBugTask(target):
        """Return the bugtask with the specified target.

        Return None if no such bugtask is found.
        """

    def getBugTasksByPackageName(bugtasks):
        """Return a mapping from `ISourcePackageName` to its bug tasks.

        This mapping is suitable to pass as the bugtasks_by_package
        cache to getConjoinedMaster().

        The mapping is from a `ISourcePackageName` to all the bug tasks
        that are targeted to such a package name, no matter which
        distribution or distro series it is.

        All the tasks that don't have a package will be available under
        None.
        """

    @call_with(user=REQUEST_USER)
    @export_write_operation()
    def isUserAffected(user):
        """Is :user: marked as affected by this bug?"""

    def userCanSetCommentVisibility(user):
        """Return True if `user` can set bug comment visibility.

        This method is called by security adapters for authenticated users.

        Users who can set bug comment visibility are:
        - Admins and registry admins
        - users in project roles on any bugtask:
          - maintainer
          - driver
          - bug supervisor

        Additionally, the comment owners can hide their own comments but that
        is not checked here - this method is to see if arbitrary users can
        hide comments they did not make themselves.

        """

    @call_with(user=REQUEST_USER)
    @operation_returns_collection_of(Interface)
    @export_read_operation()
    def getHWSubmissions(user=None):
        """Return HWDB submissions linked to this bug.

        :return: A sequence of HWDB submissions linked to this bug.
        :param user: The user making the request.

        Only those submissions are returned which the user can access.
        Public submissions are always included; private submisisons only
        if the user is the owner or an admin.
        """

    @operation_parameters(days_old=Int(
        title=_('Number of days of inactivity for which to check.'),
        required=False))
    @export_read_operation()
    def isExpirable(days_old=None):
        """Is this bug eligible for expiration and was it last updated
        more than X days ago?

        If days_old is None the default number of days without activity
        is used.

        Returns True or False.
        """

    def getActivityForDateRange(start_date, end_date):
        """Return all the `IBugActivity` for this bug in a date range.

        :param start_date: The earliest date for which activity can be
            returned.
        :param end_date: The latest date for which activity can be
            returned.
        """

    def shouldConfirmBugtasks():
        """Should we try to confirm this bug's bugtasks?

        Return True if more than one user is affected."""

    def maybeConfirmBugtasks():
        """Maybe try to confirm our new bugtasks."""

    def personIsDirectSubscriber(person):
        """Return True if the person is a direct subscriber to this `IBug`.

        Otherwise, return False.
        """

    def personIsAlsoNotifiedSubscriber(person):
        """Return True if the person is an indirect subscriber to this `IBug`.

        Otherwise, return False.
        """

    def personIsSubscribedToDuplicate(person):
        """Return True if the person subscribed to a duplicate of this `IBug`.

        Otherwise, return False.
        """

    def getAllowedInformationTypes(user):
        """Get a list of acceptable `InformationType`s for this bug.
Ejemplo n.º 19
0
class ILiveFSView(Interface):
    """`ILiveFS` attributes that require launchpad.View permission."""

    id = exported(Int(title=_("ID"), required=True, readonly=True))

    date_created = exported(Datetime(
        title=_("Date created"), required=True, readonly=True))

    registrant = exported(PublicPersonChoice(
        title=_("Registrant"), required=True, readonly=True,
        vocabulary="ValidPersonOrTeam",
        description=_(
            "The person who registered this live filesystem image.")))

    @call_with(requester=REQUEST_USER)
    @operation_parameters(
        archive=Reference(schema=IArchive),
        distro_arch_series=Reference(schema=IDistroArchSeries),
        pocket=Choice(vocabulary=PackagePublishingPocket),
        unique_key=TextLine(
            title=_("A unique key for this build, if required."),
            required=False),
        metadata_override=Dict(
            title=_("A dict of data about the image."),
            key_type=TextLine(), required=False),
        version=TextLine(title=_("A version string for this build.")))
    # Really ILiveFSBuild, patched in _schema_circular_imports.py.
    @export_factory_operation(Interface, [])
    @operation_for_version("devel")
    def requestBuild(requester, archive, distro_arch_series, pocket,
                     unique_key=None, metadata_override=None, version=None):
        """Request that the live filesystem be built.

        :param requester: The person requesting the build.
        :param archive: The IArchive to associate the build with.
        :param distro_arch_series: The architecture to build for.
        :param pocket: The pocket that should be targeted.
        :param unique_key: An optional unique key for this build; if set,
            this identifies a class of builds for this live filesystem.
        :param metadata_override: An optional JSON string with a dict of
            data about the image; this will be merged into the metadata dict
            for the live filesystem.
        :param version: A version string for this build; if not set, a
            version string will be generated from the date and time when the
            build was requested.
        :return: `ILiveFSBuild`.
        """

    builds = exported(doNotSnapshot(CollectionField(
        title=_("All builds of this live filesystem."),
        description=_(
            "All builds of this live filesystem, sorted in descending order "
            "of finishing (or starting if not completed successfully)."),
        # Really ILiveFSBuild, patched in _schema_circular_imports.py.
        value_type=Reference(schema=Interface), readonly=True)))

    completed_builds = exported(doNotSnapshot(CollectionField(
        title=_("Completed builds of this live filesystem."),
        description=_(
            "Completed builds of this live filesystem, sorted in descending "
            "order of finishing."),
        # Really ILiveFSBuild, patched in _schema_circular_imports.py.
        value_type=Reference(schema=Interface), readonly=True)))

    pending_builds = exported(doNotSnapshot(CollectionField(
        title=_("Pending builds of this live filesystem."),
        description=_(
            "Pending builds of this live filesystem, sorted in descending "
            "order of creation."),
        # Really ILiveFSBuild, patched in _schema_circular_imports.py.
        value_type=Reference(schema=Interface), readonly=True)))