class ISeriesMixin(IHasDrivers): """Methods & properties shared between distro & product series.""" active = exported(Bool( title=_("Active"), description=_( "Whether or not this series is stable and supported, or " "under current development. This excludes series which " "are experimental or obsolete."))) summary = exported( Summary(title=_("Summary"), description=_('A single paragraph that explains the goals of ' 'of this series and the intended users. ' 'For example: "The 2.0 series of Apache ' 'represents the current stable series, ' 'and is recommended for all new deployments".'), required=True)) drivers = exported( CollectionField( title=_( 'A list of the people or teams who are drivers for this ' 'series. This list is made up of any drivers or owners ' 'from this series and the parent drivers.'), readonly=True, value_type=Reference(schema=IPerson))) bug_supervisor = CollectionField( title=_('Currently just a reference to the parent bug ' 'supervisor.'), readonly=True, value_type=Reference(schema=IPerson))
class IBug(IBugPublic, IBugView, IBugAppend, IHasLinkedBranches): """The core bug entry.""" export_as_webservice_entry() linked_bugbranches = exported(CollectionField( title=_("Bazaar branches associated with this bug, usually " "branches on which this bug is being fixed."), value_type=Reference(schema=IBugBranch), readonly=True), exported_as='linked_branches') @accessor_for(linked_bugbranches) @call_with(user=REQUEST_USER) @export_read_operation() @operation_for_version('beta') def getVisibleLinkedBranches(user): """Return all the branches linked to the bug that `user` can see.""" linked_merge_proposals = exported( CollectionField( title=_("Merge proposals associated with this bug (currently only " "Git-based merge proposals)."), # Really IBranchMergeProposal, patched in # _schema_circular_imports.py. value_type=Reference(schema=Interface), readonly=True), as_of='devel') @accessor_for(linked_merge_proposals) @call_with(user=REQUEST_USER) @export_read_operation() @operation_for_version('devel') def getVisibleLinkedMergeProposals(user): """Return all the MPs linked to the bug that `user` can see."""
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.
class IBranchMergeQueue(Interface): """An interface for managing branch merges.""" export_as_webservice_entry() id = Int(title=_('ID'), readonly=True, required=True) registrant = exported( PublicPersonChoice( title=_("The user that registered the branch."), required=True, readonly=True, vocabulary='ValidPersonOrTeam')) owner = exported( PersonChoice( title=_('Owner'), required=True, readonly=True, vocabulary='UserTeamsParticipationPlusSelf', description=_("The owner of the merge queue."))) name = exported( TextLine( title=_('Name'), required=True, description=_( "Keep very short, unique, and descriptive, because it will " "be used in URLs. " "Examples: main, devel, release-1.0, gnome-vfs."))) description = exported( Text( title=_('Description'), required=False, description=_( 'A short description of the purpose of this merge queue.'))) configuration = exported( TextLine( title=_('Configuration'), required=False, readonly=True, description=_( "A JSON string of configuration values."))) date_created = exported( Datetime( title=_('Date Created'), required=True, readonly=True)) branches = exported( CollectionField( title=_('Dependent Branches'), description=_( 'A collection of branches that this queue manages.'), readonly=True, value_type=Reference(Interface))) @mutator_for(configuration) @operation_parameters( config=TextLine(title=_("A JSON string of configuration values."))) @export_write_operation() def setMergeQueueConfig(config): """Set the JSON string configuration of the merge queue.
class ICve(Interface): """A single CVE database entry.""" export_as_webservice_entry() id = Int(title=_('ID'), required=True, readonly=True) sequence = exported( TextLine(title=_('CVE Sequence Number'), description=_('Should take the form XXXX-XXXX, all digits.'), required=True, readonly=False, constraint=valid_cve_sequence)) status = exported( Choice(title=_('Current CVE State'), default=CveStatus.CANDIDATE, description=_("Whether or not the " "vulnerability has been reviewed and assigned a " "full CVE number, or is still considered a " "Candidate, or is deprecated."), required=True, vocabulary=CveStatus)) description = exported( TextLine(title=_('Title'), description=_('A description of the CVE issue. This will be ' 'updated regularly from the CVE database.'), required=True, readonly=False)) datecreated = exported(Datetime(title=_('Date Created'), required=True, readonly=True), exported_as='date_created') datemodified = exported(Datetime(title=_('Date Modified'), required=True, readonly=False), exported_as='date_modified') bugs = exported( CollectionField( title=_('Bugs related to this CVE entry.'), readonly=True, value_type=Reference(schema=Interface))) # Redefined in bug.py. # Other attributes. url = exported( TextLine(title=_('URL'), description=_("Return a URL to the site that has the CVE " "data for this CVE reference."))) displayname = exported(TextLine(title=_("Display Name"), description=_( "A very brief name describing " "the ref and state.")), exported_as='display_name') title = exported( TextLine(title=_("Title"), description=_("A title for the CVE"))) references = Attribute("The set of CVE References for this CVE.") def createReference(source, content, url=None): """Create a new CveReference for this CVE.""" def removeReference(ref): """Remove a CveReference."""
class IHasLinkedBranches(Interface): """A interface for handling branch linkages.""" linked_branches = exported( CollectionField( title=_('MultiJoin of the bugs which are dups of this one'), value_type=Reference(schema=IBranch), readonly=True)) @call_with(registrant=REQUEST_USER) @operation_parameters(branch=Reference(schema=IBranch)) @export_write_operation() @operation_for_version('beta') def linkBranch(branch, registrant): """Associate a branch with this bug. :param branch: The branch being linked to. :param registrant: The user linking the branch. """ @call_with(user=REQUEST_USER) @operation_parameters(branch=Reference(schema=IBranch)) @export_write_operation() @operation_for_version('beta') def unlinkBranch(branch, user): """Unlink a branch from this bug.
class IBugTrackerComponentGroup(Interface): """A collection of components in a remote bug tracker. Some bug trackers organize sets of components into higher level groups, such as Bugzilla's 'product'. """ export_as_webservice_entry() id = Int(title=_('ID')) name = exported( Text( title=_('Name'), description=_('The name of the bug tracker product.'))) components = exported( CollectionField( title=_('Components.'), value_type=Reference(schema=IBugTrackerComponent))) bug_tracker = exported( Reference(title=_('BugTracker'), schema=IBugTracker)) @operation_parameters( component_name=TextLine( title=u"The name of the remote software component to be added", required=True)) @export_write_operation() def addComponent(component_name): """Adds a component to be tracked as part of this component group"""
class ISnapAdminAttributes(Interface): """`ISnap` attributes that can be edited by admins. These attributes need launchpad.View to see, and launchpad.Admin to change. """ private = exported(Bool( title=_("Private"), required=False, readonly=False, description=_("Whether or not this snap is private."))) require_virtualized = exported(Bool( title=_("Require virtualized builders"), required=True, readonly=False, description=_("Only build this snap package on virtual builders."))) processors = exported(CollectionField( title=_("Processors"), description=_( "The architectures for which the snap package should be built."), value_type=Reference(schema=IProcessor), readonly=False)) allow_internet = exported(Bool( title=_("Allow external network access"), required=True, readonly=False, description=_( "Allow access to external network resources via a proxy. " "Resources hosted on Launchpad itself are always allowed.")))
class IPillarNameSet(Interface): """An object for searching across projects, project groups, and distros. Projects, project groups, and distributions are collectively known as "pillars". This object lets you do a combined search across all types of pillars. It also gives you access to pillars that have been flagged by administrators as "featured" pillars. """ export_as_webservice_entry('pillars') def __contains__(name): """True if the given name is an active Pillar or an alias to one.""" def __getitem__(name): """Get an active pillar by its name or any of its aliases. If there's no pillar with the given name or there is one but it's inactive, raise NotFoundError. """ def getByName(name, ignore_inactive=False): """Return the pillar whose name or alias matches the given name. If ignore_inactive is True, then only active pillars are considered. If no pillar is found, return None. """ def count_search_matches(user, text): """Return the total number of Pillars matching :text:""" @call_with(user=REQUEST_USER) @operation_parameters(text=TextLine(title=u"Search text"), limit=Int(title=u"Maximum number of items to " "return. This is a hard limit: any " "pagination you request will happen " "within this limit.", required=False)) @operation_returns_collection_of(IPillar) @export_read_operation() def search(user, text, limit): """Return Projects/Project groups/Distros matching :text:. If :limit: is None, the default batch size will be used. The results are ordered descending by rank. """ def add_featured_project(project): """Add a project to the featured project list.""" def remove_featured_project(project): """Remove a project from the featured project list.""" featured_projects = exported(CollectionField( title=_('Projects, project groups, and distributions that are ' 'featured on the site.'), value_type=Reference(schema=IPillar)), exported_as="featured_pillars")
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)))
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))))
class IStructuralSubscriptionPublic(Interface): """The public parts of a subscription to a Launchpad structure.""" id = Int(title=_('ID'), readonly=True, required=True) product = Int(title=_('Product'), required=False, readonly=True) productseries = Int(title=_('Product series'), required=False, readonly=True) projectgroup = Int(title=_('Project group'), required=False, readonly=True) milestone = Int(title=_('Milestone'), required=False, readonly=True) distribution = Int(title=_('Distribution'), required=False, readonly=True) distroseries = Int(title=_('Distribution series'), required=False, readonly=True) sourcepackagename = Int(title=_('Source package name'), required=False, readonly=True) subscriber = exported( PersonChoice(title=_('Subscriber'), required=True, vocabulary='ValidPersonOrTeam', readonly=True, description=_("The person subscribed."))) subscribed_by = exported( PublicPersonChoice( title=_('Subscribed by'), required=True, vocabulary='ValidPersonOrTeam', readonly=True, description=_("The person creating the subscription."))) date_created = exported( Datetime(title=_("The date on which this subscription was created."), required=False, readonly=True)) date_last_updated = exported( Datetime( title=_("The date on which this subscription was last updated."), required=False, readonly=True)) target = exported( Reference( schema=Interface, # IStructuralSubscriptionTarget required=True, readonly=True, title=_("The structure to which this subscription belongs."))) bug_filters = exported( CollectionField( title=_('List of bug filters that narrow this subscription.'), readonly=True, required=False, value_type=Reference(schema=Interface))) # IBugSubscriptionFilter
class IBug(IBugPublic, IBugView, IBugEdit, IHasLinkedBranches): """The core bug entry.""" export_as_webservice_entry() linked_branches = exported( CollectionField(title=_("Branches associated with this bug, usually " "branches on which this bug is being fixed."), value_type=Reference(schema=IBugBranch), readonly=True)) @accessor_for(linked_branches) @call_with(user=REQUEST_USER) @export_read_operation() @operation_for_version('beta') def getVisibleLinkedBranches(user): """Return the branches linked to this bug that are visible by
class ISnapBuildRequest(Interface): """A request to build a snap package.""" # XXX cjwatson 2018-06-14 bug=760849: "beta" is a lie to get WADL # generation working. Individual attributes must set their version to # "devel". export_as_webservice_entry(as_of="beta") id = Int(title=_("ID"), required=True, readonly=True) date_requested = exported(Datetime( title=_("The time when this request was made"), required=True, readonly=True)) date_finished = exported(Datetime( title=_("The time when this request finished"), required=False, readonly=True)) snap = exported(Reference( # Really ISnap, patched in lp.snappy.interfaces.webservice. Interface, title=_("Snap package"), required=True, readonly=True)) status = exported(Choice( title=_("Status"), vocabulary=SnapBuildRequestStatus, required=True, readonly=True)) error_message = exported(TextLine( title=_("Error message"), required=True, readonly=True)) builds = exported(CollectionField( title=_("Builds produced by this request"), # Really ISnapBuild, patched in lp.snappy.interfaces.webservice. value_type=Reference(schema=Interface), required=True, readonly=True)) archive = Reference( IArchive, title=u"The source archive for builds produced by this request", required=True, readonly=True) channels = Dict( title=_("Source snap channels for builds produced by this request"), key_type=TextLine(), required=False, readonly=True)
class ISourcePackageRecipeBuild(IPackageBuild): """A build of a source package.""" export_as_webservice_entry() id = Int(title=_("Identifier for this build.")) binary_builds = CollectionField( Reference(IBinaryPackageBuild), title=_("The binary builds that resulted from this."), readonly=True) distroseries = Reference(IDistroSeries, title=_("The distroseries being built for"), readonly=True) requester = Object(schema=IPerson, required=False, title=_("The person who wants this to be done.")) recipe = Object(schema=ISourcePackageRecipe, title=_("The recipe being built.")) manifest = Object(schema=ISourcePackageRecipeData, title=_('A snapshot of the recipe for this build.')) def getManifestText(): """The text of the manifest for this build.""" source_package_release = Reference( ISourcePackageRelease, title=_("The produced source package release"), readonly=True) is_virtualized = Bool(title=_('If True, this build is virtualized.')) def getFileByName(filename): """Return the file under +files with specified name.""" def cancelBuild(): """Cancel the build.""" def destroySelf(): """Delete the build itself."""
class ISourcePackageRecipeBuildView(IPackageBuild): id = Int(title=_("Identifier for this build.")) binary_builds = CollectionField( Reference(IBinaryPackageBuild), title=_("The binary builds that resulted from this."), readonly=True) distroseries = Reference( IDistroSeries, title=_("The distroseries being built for"), readonly=True) requester = Object( schema=IPerson, required=False, title=_("The person who wants this to be done.")) recipe = Object( schema=ISourcePackageRecipe, title=_("The recipe being built.")) can_be_rescored = exported(Bool( title=_("Can be rescored"), required=True, readonly=True, description=_("Whether this build record can be rescored manually."))) can_be_cancelled = exported(Bool( title=_("Can be cancelled"), required=True, readonly=True, description=_("Whether this build record can be cancelled."))) manifest = Object( schema=ISourcePackageRecipeData, title=_( 'A snapshot of the recipe for this build.')) def getManifestText(): """The text of the manifest for this build.""" source_package_release = Reference( ISourcePackageRelease, title=_("The produced source package release"), readonly=True) def getFileByName(filename): """Return the file under +files with specified name."""
class IBugLinkTarget(Interface): """An entity which can be linked to bugs. Examples include an ISpecification. """ export_as_webservice_entry(as_of="beta") bugs = exported( CollectionField(title=_("Bugs related to this object."), value_type=Reference(schema=IBug), readonly=True), as_of="devel") def linkBug(bug, user=None, check_permissions=True, props=None): """Link the object with this bug. If a new link is created by this method, an ObjectLinkedEvent is sent for each end. :return: True if a new link was created, False if it already existed. """ def unlinkBug(bug, user=None, check_permissions=True): """Remove any link between this object and the bug.
class IBugLinkTarget(Interface): """An entity which can be linked to bugs. Examples include an ISpecification. """ export_as_webservice_entry(as_of="beta") bugs = exported( CollectionField(title=_("Bugs related to this object."), value_type=Reference(schema=IBug), readonly=True), as_of="devel") bug_links = List(title=_("The links between bugs and this object."), value_type=Object(schema=IBugLink), readonly=True) def linkBug(bug): """Link the object with this bug. If the object is already linked, return the old linker, otherwise return a new IBugLink object. If a new IBugLink is created by this method, a ObjectCreatedEvent should be sent. """ def unlinkBug(bug): """Remove any link between this object and the bug. If the bug wasn't
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."""
class ISnapBuildView(IPackageBuild): """`ISnapBuild` attributes that require launchpad.View permission.""" build_request = Reference( ISnapBuildRequest, title=_("The build request that caused this build to be created."), required=False, readonly=True) requester = exported( Reference(IPerson, title=_("The person who requested this build."), required=True, readonly=True)) snap = exported( Reference(ISnap, title=_("The snap package to build."), required=True, readonly=True)) archive = exported( Reference(IArchive, title=_("The archive from which to build the snap package."), required=True, readonly=True)) distro_arch_series = exported( Reference(IDistroArchSeries, title=_("The series and architecture for which to build."), required=True, readonly=True)) arch_tag = exported( TextLine(title=_("Architecture tag"), required=True, readonly=True)) pocket = exported( Choice(title=_("The pocket for which to build."), vocabulary=PackagePublishingPocket, required=True, readonly=True)) channels = exported( 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())) virtualized = Bool(title=_("If True, this build is virtualized."), readonly=True) score = exported( Int(title=_("Score of the related build farm job (if any)."), required=False, readonly=True)) can_be_rescored = exported( Bool(title=_("Can be rescored"), required=True, readonly=True, description=_( "Whether this build record can be rescored manually."))) can_be_cancelled = exported( Bool(title=_("Can be cancelled"), required=True, readonly=True, description=_("Whether this build record can be cancelled."))) eta = Datetime( title=_("The datetime when the build job is estimated to complete."), readonly=True) estimate = Bool(title=_("If true, the date value is an estimate."), readonly=True) date = Datetime(title=_( "The date when the build completed or is estimated to " "complete."), readonly=True) revision_id = exported( TextLine(title=_("Revision ID"), required=False, readonly=True, description=_( "The revision ID of the branch used for this build, if " "available."))) store_upload_jobs = CollectionField( title=_("Store upload jobs for this build."), # Really ISnapStoreUploadJob. value_type=Reference(schema=Interface), readonly=True) # Really ISnapStoreUploadJob. last_store_upload_job = Reference( title=_("Last store upload job for this build."), schema=Interface) store_upload_status = exported( Choice(title=_("Store upload status"), vocabulary=SnapBuildStoreUploadStatus, required=True, readonly=False)) store_upload_url = exported( TextLine(title=_("Store URL"), description=_( "The URL to use for managing this package in the store."), required=False, readonly=True)) store_upload_revision = exported( Int(title=_("Store revision"), description=_( "The revision assigned to this package by the store."), required=False, readonly=True)) store_upload_error_message = exported( TextLine( title=_("Store upload error message"), description=_( "The error message, if any, from the last attempt to upload " "this snap build to the store. (Deprecated; use " "store_upload_error_messages instead.)"), required=False, readonly=True)) store_upload_error_messages = exported( List(title=_("Store upload error messages"), description=_( "A list of dict(message, link) where message is an error " "description and link, if any, is an external link to extra " "details, from the last attempt to upload this snap build " "to the store."), value_type=Dict(key_type=TextLine()), required=False, readonly=True)) store_upload_metadata = Attribute( _("A dict of data about store upload progress.")) def getFiles(): """Retrieve the build's `ISnapFile` records. :return: A result set of (`ISnapFile`, `ILibraryFileAlias`, `ILibraryFileContent`). """ def getFileByName(filename): """Return the corresponding `ILibraryFileAlias` in this context. The following file types (and extension) can be looked up: * Build log: '.txt.gz' * Upload log: '_log.txt' Any filename not matching one of these extensions is looked up as a snap package output file. :param filename: The filename to look up. :raises NotFoundError: if no file exists with the given name. :return: The corresponding `ILibraryFileAlias`. """ @export_read_operation() @operation_for_version("devel") def getFileUrls(): """URLs for all the files produced by this build.
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.
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.
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.
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.
class IPOTemplate(IRosettaStats): """A translation template.""" export_as_webservice_entry(singular_name='translation_template', plural_name='translation_templates') id = exported( Int(title=u"The translation template id.", required=True, readonly=True)) name = exported( TextLine(title=_("Template name"), description=_( "The name of this PO template, for example " "'evolution-2.2'. Each translation template has a " "unique name in its package. It's important to get this " "correct, because Launchpad will recommend alternative " "translations based on the name."), constraint=valid_name, required=True)) translation_domain = exported( TextLine( title=_("Translation domain"), description=_( "The translation domain for a translation template. " "Used with PO file format when generating MO files for inclusion " "in language pack or MO tarball exports."), required=True)) description = exported( Text( title=_("Description"), description=_( "Please provide a brief description of the content " "of this translation template, for example, telling translators " "if this template contains strings for end-users or other " "developers."), required=False)) header = Text( title=_('Header'), description=_("The standard template header in its native format."), required=True) iscurrent = exported(Bool( title=_("Template is active"), description=_( "If unchecked, people can no longer change the template's " "translations."), required=True, default=True), exported_as='active') owner = exported( PersonChoice( title=_("Owner"), required=True, description=_( "The owner of the template in Launchpad can edit the template " "and change it's status, and can also upload new versions " "of the template when a new release is made or when the " "translation strings have been changed during development."), vocabulary="ValidOwner")) productseries = Choice(title=_("Series"), required=False, vocabulary="ProductSeries") distroseries = Choice(title=_("Series"), required=False, vocabulary="DistroSeries") sourcepackagename = Choice( title=_("Source Package Name"), description=_("The source package that uses this template."), required=False, vocabulary="SourcePackageName") sourcepackagenameID = Int( title=_("Source Package Name ID"), description=_("The ID of the source package that uses this template."), required=False, readonly=True) sourcepackage = Reference( ISourcePackage, title=u"Source package this template is for, if any.", required=False, readonly=True) from_sourcepackagename = Choice( title=_("From Source Package Name"), description=_( "The source package this template comes from (set it only if it's" " different from the previous 'Source Package Name'."), required=False, vocabulary="SourcePackageName") sourcepackageversion = TextLine(title=_("Source Package Version"), required=False) binarypackagename = Choice( title=_("Binary Package"), description=_("The package in which this template's translations are " "installed."), required=False, vocabulary="BinaryPackageName") languagepack = exported(Bool( title=_("Include translations for this template in language packs?"), description=_( "Check this box if this template is part of a language pack so " "its translations should be exported that way."), required=True, default=False), exported_as='exported_in_languagepacks') path = exported( TextLine(title=_( "Path of the template in the source tree, including filename."), required=True)) source_file = Object(title=_('Source file for this translation template'), readonly=True, schema=ILibraryFileAlias) source_file_format = exported(Choice( title=_("File format for the source file"), required=False, vocabulary=TranslationFileFormat), exported_as='format') priority = exported( Int(title=_('Priority'), required=True, default=0, description=_( 'A number that describes how important this template is. Often ' 'there are multiple templates, and you can use this as a way ' 'of indicating which are more important and should be ' 'translated first. Pick any number - higher priority ' 'templates will generally be listed first.'))) datecreated = Datetime( title=_('When this translation template was created.'), required=True, readonly=True) translationgroups = Attribute( _(''' The `ITranslationGroup` objects that handle translations for this template. There can be several because they can be inherited from project to product, for example. ''')) translationpermission = Choice(title=_('Translation permission'), required=True, readonly=True, description=_(''' The permission system which is used for this translation template. This is inherited from the product, project and/or distro in which the translation template is found. '''), vocabulary='TranslationPermission') pofiles = exported( CollectionField( title=_("All translation files that exist for this template."), # Really IPOFile, see _schema_circular_imports.py. value_type=Reference(schema=Interface)), exported_as='translation_files') relatives_by_source = Attribute( _('''All `IPOTemplate` objects that have the same source. For example those that came from the same productseries or the same source package. ''')) displayname = TextLine(title=_('The translation template brief name.'), required=True, readonly=True) title = TextLine(title=_('The translation template title.'), required=True, readonly=True) product = Object( title=_('The `IProduct` to which this translation template belongs.'), required=False, readonly=True, # Really IProduct, see _schema_circular_imports.py. schema=Interface) distribution = Object(title=_( 'The `IDistribution` to which this translation template ' 'belongs.'), readonly=True, schema=IDistribution) messagecount = exported(Int( title=_('The number of translation messages for this template.'), required=True, readonly=True), exported_as='message_count') language_count = exported( Int(title=_('The number of languages for which we have translations.'), required=True, readonly=True)) translationtarget = Attribute( _(''' The direct object in which this template is attached. This will either be an `ISourcePackage` or an `IProductSeries`. ''')) date_last_updated = exported( Datetime(title=_('Date for last update'), required=True)) uses_english_msgids = Bool(title=_("Uses English strings as msgids"), readonly=True, description=_(""" Some formats, such as Mozilla's XPI, use symbolic msgids where gettext uses the original English strings to identify messages. """)) translation_side = Int(title=_("Translation side"), required=True, readonly=True) def __iter__(): """Return an iterator over current `IPOTMsgSet` in this template.""" def clearPOFileCache(): """Clear `POFile`-related cached data. As you work with a `POTemplate`, some data about its `POFile`s gets cached. But if you're iterating over the template's translations one `POFile` at a time, you can drop any cached data about a `POFile` as soon as you're done with it. Use this method to do that. """ def setActive(active): """Toggle the iscurrent flag. Takes care of updating the suggestive potempalte cache when the template is disabled. """ def getHeader(): """Return an `ITranslationHeaderData` representing its header.""" def getPOTMsgSetByMsgIDText(singular_text, plural_text=None, only_current=False, context=None): """Return `IPOTMsgSet` indexed by `singular_text` from this template. If the key is a string or a unicode object, returns the `IPOTMsgSet` in this template that has a primary message ID with the given text. If `only_current` is True, then get only current message sets. If `context` is not None, look for a message set with that context value. If `plural_text` is not None, also filter by that plural text. If no `IPOTMsgSet` is found, return None. """ def getPOTMsgSetBySequence(sequence): """Return the `IPOTMsgSet` with the given sequence or None. :arg sequence: The sequence number when the `IPOTMsgSet` appears. The sequence number must be > 0. """ def getPOTMsgSets(current=True, prefetch=True): """Return an iterator over `IPOTMsgSet` objects in this template. :param current: Whether to limit the search to current POTMsgSets. :param prefetch: Whether to prefetch the `POMsgID`s attached to the POTMsgSets. This is for optimization only. :return: All current POTMsgSets for the template if `current` is True, or all POTMsgSets for the template otherwise. """ def getTranslationCredits(): """Return an iterator over translation credits. Return all `IPOTMsgSet` objects in this template that are translation credits. """ def getPOTMsgSetsCount(current=True): """Return the number of POTMsgSet objects related to this object. The current argument is used to select only current POTMsgSets or all of them. """ def __getitem__(key): """Same as getPOTMsgSetByMsgIDText(), with only_current=True """ def sharingKey(): """A key for determining the sharing precedence of a template. Active templates have precedence over inactive ones. Development foci have precendence over non-development foci. Product development foci have precedence over Package development foci. """ def getPOTMsgSetByID(id): """Return the POTMsgSet object related to this POTemplate with the id. If there is no POTMsgSet with that id and for that POTemplate, return None. """ def languages(): """This Return the set of languages for which we have POFiles for this POTemplate. """ def getPOFileByPath(path): """Get the PO file of the given path. Return None if there is no such `IPOFile`. """ def getPOFileByLang(language_code): """Get the PO file of the given language. Return None if there is no such POFile. """ def getOtherSidePOTemplate(): """Get the POTemplate with the same name on the other side of a packaging link. """ def hasPluralMessage(): """Test whether this template has any message sets which are plural message sets.""" def export(): """Return a serialized version as a string using its native format.""" def exportWithTranslations(): """Return an ExportedTranslationFile using its native format. It include all translations available. """ def expireAllMessages(): """Mark all of our message sets as not current (sequence=0)""" def newPOFile(language_code, create_sharing=True): """Return a new `IPOFile` for the given language. Raise LanguageNotFound if the language does not exist in the database. We should not have already an `IPOFile` for the given language_code. :param language_code: The code of the language for which to create the IPOFile. :param requester: The requester person. If given and will have edit permissions on the IPOFile, it becomes the owner. Otherwise rosetta_experts own the file. :param create_sharing: Whether the IPOFile should be created in all sharing templates, too. Should only be set to False to avoid loops when creating a new IPOTemplate. """ def getDummyPOFile(language, requester=None, check_for_existing=True): """Return a DummyPOFile if there isn't already a persistent `IPOFile` Raise `LanguageNotFound` if the language does not exist in the database. This method is designed to be used by read only actions. This way you only create a POFile when you actually need to store data. We should not have already a POFile for the given language: if check_for_existing is set to False, no check will be done for this. """ def createPOTMsgSetFromMsgIDs(msgid_singular, msgid_plural=None, context=None, sequence=0): """Creates a new template message in the database. :param msgid_singular: A reference to a singular msgid. :param msgid_plural: A reference to a plural msgid. Can be None if the message is not a plural message. :param context: A context for the template message differentiating it from other template messages with exactly the same `msgid`. :param sequence: The sequence number of this POTMsgSet within this POTemplate. If 0, it is considered obsolete. :return: The newly created message set. """ def createMessageSetFromText(singular_text, plural_text, context=None, sequence=0): """Creates a new template message in the database using strings. Similar to createMessageSetFromMessageID, but takes text objects (unicode or string) along with textual context, rather than a message IDs. :param singular_text: The string for the singular msgid. :param msgid_plural: The string for the plural msgid. Must be None if the message is not a plural message. :param context: A context for the template message differentiating it from other template messages with exactly the same `msgid`. :param sequence: The sequence number of this POTMsgSet within this POTemplate. If 0, it is considered obsolete. :return: The newly created message set. """ def getOrCreateSharedPOTMsgSet(singular_text, plural_text, context=None, initial_file_references=None, initial_source_comment=None): """Finds an existing shared POTMsgSet to use or creates a new one. :param singular_text: string containing singular form. :param plural_text: string containing plural form. :param context: context to differentiate between two messages with same singular_text and plural_text. :param initial_file_references: Initializer for file_references if a new POTMsgSet needs to be created. Will not be set on an existing POTMsgSet. :param initial_source_comment: Initializer for source_comment if a new POTMsgSet needs to be created. Will not be set on an existing POTMsgSet. :return: existing or new shared POTMsgSet with a sequence of 0 in this POTemplate. """ def importFromQueue(entry_to_import, logger=None, txn=None): """Import given queue entry. :param entry_to_import: `TranslationImportQueueEntry` specifying an approved import for this `POTemplate` :param logger: optional logger to report problems to. :param txn: optional transaction manager for intermediate commits. Used to prevent long-running transactions that can lead to deadlocks. :return: a tuple of the subject line and body for a notification email to be sent to the uploader. """ def getTranslationRows(): """Return the `IVPOTexport` objects for this template.""" def awardKarma(person, action_name): """Award karma for a translation action on this template.""" def getTranslationPolicy(): """Return the applicable `ITranslationPolicy` object.
class IGitRefView(IHasMergeProposals, IHasRecipes, IPrivacy, IInformationType): """IGitRef attributes that require launchpad.View permission.""" repository = exported( ReferenceChoice( title=_("Repository"), required=True, readonly=True, vocabulary="GitRepository", # Really IGitRepository, patched in _schema_circular_imports.py. schema=Interface, description=_("The Git repository containing this reference."))) repository_url = Attribute( "The repository URL, if this is a reference in a remote repository.") path = exported( TextLine( title=_("Path"), required=True, readonly=True, description=_( "The full path of this reference, e.g. refs/heads/master."))) name = Attribute( "A shortened version of the full path to this reference, with any " "leading refs/heads/ removed.") url_quoted_name = Attribute("The reference name, quoted for use in URLs.") commit_sha1 = exported( TextLine( title=_("Commit SHA-1"), required=True, readonly=True, description=_( "The full SHA-1 object name of the commit object referenced by " "this reference."))) object_type = Choice(title=_("Object type"), required=True, readonly=True, vocabulary=GitObjectType) author = Attribute( "The author of the commit pointed to by this reference.") author_date = Datetime( title=_("The author date of the commit pointed to by this reference."), required=False, readonly=True) committer = Attribute( "The committer of the commit pointed to by this reference.") committer_date = Datetime(title=_( "The committer date of the commit pointed to by this reference."), required=False, readonly=True) commit_message = Text(title=_( "The commit message of the commit pointed to by this reference."), required=False, readonly=True) display_name = TextLine(title=_("Display name"), required=True, readonly=True, description=_("Display name of the reference.")) displayname = Attribute( "Copy of display_name for IHasMergeProposals views.") commit_message_first_line = TextLine( title=_("The first line of the commit message."), required=False, readonly=True) identity = Attribute( "The identity of this reference. This will be the shortened path to " "the containing repository, plus a colon, plus the reference path " "with any leading refs/heads/ removed; for example, launchpad:master.") unique_name = Attribute( "The unique name of this reference. This will be the unique name of " "the containing repository, plus a colon, plus the reference path " "with any leading refs/heads/ removed; for example, " "~launchpad-pqm/launchpad:master.") repository_type = Attribute( "The type of the repository containing this reference.") owner = Attribute("The owner of the repository containing this reference.") target = Attribute( "The target of the repository containing this reference.") namespace = Attribute( "The namespace of the repository containing this reference, as an " "`IGitNamespace`.") def getCodebrowseUrl(): """Construct a browsing URL for this Git reference.""" def getCodebrowseUrlForRevision(commit): """Construct a browsing URL for this Git at the given commit""" information_type = Attribute( "The type of information contained in the repository containing this " "reference.") private = Bool( title=_("Private"), required=False, readonly=True, description=_( "The repository containing this reference is visible only to its " "subscribers.")) def visibleByUser(user): """Can the specified user see the repository containing this reference?""" def transitionToInformationType(information_type, user, verify_policy=True): """Set the information type for this reference's repository. :param information_type: The `InformationType` to transition to. :param user: The `IPerson` who is making the change. :param verify_policy: Check if the new information type complies with the `IGitNamespacePolicy`. """ reviewer = Attribute( "The person or exclusive team that is responsible for reviewing " "proposals and merging into this reference.") code_reviewer = Attribute( "The reviewer if set, otherwise the owner of the repository " "containing this reference.") def isPersonTrustedReviewer(reviewer): """Return true if the `reviewer` is a trusted reviewer. The reviewer is trusted if they either own the repository containing this reference, or are in the team that owns the repository, or they are in the review team for the repository. """ subscriptions = Attribute( "GitSubscriptions associated with the repository containing this " "reference.") subscribers = Attribute( "Persons subscribed to the repository containing this reference.") def subscribe(person, notification_level, max_diff_lines, code_review_level, subscribed_by): """Subscribe this person to the repository containing this reference. :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`. """ def getSubscription(person): """Return the `GitSubscription` for this person.""" def unsubscribe(person, unsubscribed_by): """Remove the person's subscription to this reference's repository. :param person: The person or team to unsubscribe from the repository. :param unsubscribed_by: The person doing the unsubscribing. """ 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 reference is " "the source.") _api_landing_targets = exported( CollectionField( title=_("Landing targets"), description=_( "A collection of the merge proposals where this reference 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 reference is " "the target.") _api_landing_candidates = exported( CollectionField( title=_("Landing candidates"), description=_( "A collection of the merge proposals where this reference 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 " "reference."), 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. """ # XXX cjwatson 2015-04-16: Rename in line with landing_targets above # once we have a better name. def addLandingTarget(registrant, merge_target, merge_prerequisite=None, date_created=None, needs_review=None, description=None, review_requests=None, commit_message=None): """Create a new BranchMergeProposal with this reference as the source. Both the target and the prerequisite, if it is there, must be references whose repositories have the same target as the source. References in personal repositories cannot specify merge proposals. :param registrant: The person who is adding the landing target. :param merge_target: Must be another reference, and different to self. :param merge_prerequisite: Optional, but if it is not None it must be another reference. :param date_created: Used to specify the date_created value of the merge request. :param needs_review: Used to specify the proposal is ready for review right now. :param description: A description of the bugs fixed, features added, or refactorings. :param review_requests: An optional list of (`Person`, review_type). """ @operation_parameters( # merge_target and merge_prerequisite are actually IGitRef, patched # in _schema_circular_imports. merge_target=Reference(schema=Interface), merge_prerequisite=Reference(schema=Interface), needs_review=Bool( title=_("Needs review"), description=_( "If True, the proposal needs review. Otherwise, it will be " "work in progress.")), initial_comment=Text( title=_("Initial comment"), description=_("Registrant's initial description of proposal.")), commit_message=Text( title=_("Commit message"), description=_("Message to use when committing this merge.")), reviewers=List(value_type=Reference(schema=IPerson)), review_types=List(value_type=TextLine())) @call_with(registrant=REQUEST_USER) # Really IBranchMergeProposal, patched in _schema_circular_imports.py. @export_factory_operation(Interface, []) @operation_for_version("devel") def createMergeProposal(registrant, merge_target, merge_prerequisite=None, needs_review=None, initial_comment=None, commit_message=None, reviewers=None, review_types=None): """Create a new BranchMergeProposal with this reference as the source. Both the merge_target and the merge_prerequisite, if it is there, must be references whose repositories have the same target as the source. References in personal repositories cannot specify merge proposals. """ @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 getDependentMergeProposals(status=None, visible_by_user=None, eager_load=False): """Return BranchMergeProposals dependent on merging this reference.""" pending_updates = Attribute( "Whether there are recent changes in this repository that have not " "yet been scanned.") def getCommits(start, limit=None, stop=None, union_repository=None, start_date=None, end_date=None, handle_timeout=False, logger=None): """Get commit information from this reference. :param start: The commit to start listing from. :param limit: If not None, return no more than this many commits. :param stop: If not None, ignore this commit and its ancestors. :param union_repository: If not None, resolve commit identifiers in this repository as well (particularly useful with `stop`). :param start_date: If not None, ignore commits before this date. :param end_date: If not None, ignore commits after this date. :param handle_timeout: If True and the backend request times out, synthesise commit information from what we have in the database. :param logger: An optional logger. :return: An iterable of commit information dicts. """ def getLatestCommits(quantity=10, extended_details=False, user=None, handle_timeout=False, logger=None): """Return a specific number of the latest commits in this ref.""" has_commits = Attribute("Whether this reference has any commits.") def getBlob(filename): """Get a blob by file name from this reference. :param filename: Relative path of a file in the repository. :return: A binary string with the blob content. """ def getLatestScanJob(): """Return the last IGitRefScanJobSource for the repository""" def rescan(): """Force a rescan of the repository"""
class IQuestion(IHasOwner): """A single question, often a support request.""" export_as_webservice_entry(as_of='beta') id = exported(Int(title=_('Question Number'), required=True, readonly=True, description=_("The tracking number for this question.")), as_of="devel") title = exported(TextLine( title=_('Summary'), required=True, description=_("A one-line summary of the issue or problem.")), as_of="devel") description = exported(Text( title=_('Description'), required=True, description=_( "Include as much detail as possible: what " u"you\N{right single quotation mark}re trying to achieve, what steps " "you take, what happens, and what you think should happen instead." )), as_of="devel") status = exported(Choice(title=_('Status'), vocabulary=QuestionStatus, default=QuestionStatus.OPEN, readonly=True), as_of="devel") priority = Choice(title=_('Priority'), vocabulary=QuestionPriority, default=QuestionPriority.NORMAL) # XXX flacoste 2006-10-28: It should be more precise to define a new # vocabulary that excludes the English variants. language = exported(ReferenceChoice( title=_('Language'), vocabulary='Language', schema=ILanguage, description=_('The language in which this question is written.')), as_of="devel") owner = exported(PublicPersonChoice(title=_('Owner'), required=True, readonly=True, vocabulary='ValidPersonOrTeam'), as_of="devel") assignee = exported(PublicPersonChoice( title=_('Assignee'), required=False, description=_("The person responsible for helping to resolve the " "question."), vocabulary='ValidPersonOrTeam'), as_of="devel") answerer = exported(PublicPersonChoice( title=_('Answered By'), required=False, description=_("The person who last provided a response intended to " "resolve the question."), vocabulary='ValidPersonOrTeam'), as_of="devel", readonly=True) answer = exported(Reference( title=_('Answer'), required=False, description=_( "The IQuestionMessage that contains the answer " "confirmed by the owner as providing a solution to their " "problem."), schema=IQuestionMessage), readonly=True, as_of="devel") datecreated = exported(Datetime(title=_('Date Created'), required=True, readonly=True), exported_as='date_created', readonly=True, as_of="devel") datedue = exported(Datetime( title=_('Date Due'), required=False, default=None, description=_( "The date by which we should have resolved this question.")), exported_as='date_due', readonly=True, as_of="devel") datelastquery = exported(Datetime( title=_("Date Last Queried"), required=True, description=_("The date on which we last heard from the " "customer (owner).")), exported_as='date_last_query', readonly=True, as_of="devel") datelastresponse = exported(Datetime( title=_("Date last Responded"), required=False, description=_( "The date on which we last communicated " "with the customer. The combination of datelastquery and " "datelastresponse tells us in whose court the ball is.")), exported_as='date_last_response', readonly=True, as_of="devel") date_solved = exported(Datetime( title=_("Date Answered"), required=False, description=_( "The date on which the question owner confirmed that the " "question is Solved.")), exported_as='date_solved', readonly=True, as_of="devel") product = Choice(title=_('Upstream Project'), required=False, vocabulary='Product', description=_( 'Select the upstream project with which you need ' 'support.')) distribution = Choice(title=_('Distribution'), required=False, vocabulary='Distribution', description=_( 'Select ' 'the distribution for which you need support.')) sourcepackagename = Choice( title=_('Source Package'), required=False, vocabulary='SourcePackageName', description=_( 'The source package ' 'in the distribution which contains the software with which you ' 'are experiencing difficulties.')) whiteboard = Text( title=_('Status Whiteboard'), required=False, description=_('Up-to-date notes on the status of the question.')) # other attributes target = exported(Reference( title=_('This question is about'), required=True, schema=IQuestionTarget, description=_('The distribution, source package, or project the ' 'question pertains to.')), as_of="devel") faq = Object(title=_('Linked FAQ'), description=_( 'The FAQ document containing the long answer to this ' 'question.'), readonly=True, required=False, schema=IFAQ) # joins subscriptions = Attribute('The set of subscriptions to this question.') reopenings = Attribute("Records of times when this question was reopened.") messages = exported(CollectionField( title=_("Messages"), description=_( "The list of messages that were exchanged as part of this " "question , sorted from first to last."), value_type=Reference(schema=IQuestionMessage), required=True, default=[], readonly=True), as_of='devel') # Workflow methods def setStatus(user, new_status, comment, datecreated=None): """Change the status of this question. Set the question's status to new_status and add an IQuestionMessage with action SETSTATUS. Only the question target owner or admin can change the status using this method. An InvalidQuestiontateError is raised when this method is called with new_status equals to the current question status. Return the created IQuestionMessage. This method should fire an IObjectCreatedEvent for the created IQuestionMessage and an IObjectModifiedEvent for the question. :user: The IPerson making the change. :new_status: The new QuestionStatus :comment: A string or IMessage containing an explanation for the change. :datecreated: Date for the message. Defaults to the current time. """ can_request_info = Attribute( 'Whether the question is in a state where a user can request more ' 'information from the question owner.') def requestInfo(user, question, datecreated=None): """Request more information from the question owner. Add an IQuestionMessage with action REQUESTINFO containing the question. The question's status is changed to NEEDSINFO, and the datelastresponse attribute is updated to the message creation date. The user requesting more information cannot be the question's owner. This workflow method should only be called when the question status is OPEN or NEEDSINFO. An InvalidQuestionStateError is raised otherwise. It can also be called when the question is in the ANSWERED state, but in that case, the status will stay unchanged. Return the created IQuestionMessage. This method should fire an IObjectCreatedEvent for the created IQuestionMessage and an IObjectModifiedEvent for the question. :user: IPerson requesting for the information. :question: A string or IMessage containing the question. :datecreated: Date for the answer. Defaults to the current time. """ can_give_info = Attribute( 'Whether the question is in a state where the question owner can ' 'give more information on the question.') def giveInfo(reply, datecreated=None): """Reply to the information request. Add an IQuestionMessage with action GIVEINFO. The question status is changed to OPEN, the datelastquery attribute is updated to the message creation time. This method should only be called on behalf of the question owner when the question is in the OPEN or NEEDSINFO state. An InvalidQuestionStateError is raised otherwise. Return the created IQuestionMessage. This method should fire an IObjectCreatedEvent for the created IQuestionMessage and an IObjectModifiedEvent for the question. :reply: A string or IMessage containing the new information. :datecreated: Date for the message. Defaults to the current time. """ can_give_answer = Attribute( 'Whether the question is in a state a user can provide an answer on ' 'the question.') def giveAnswer(user, answer, datecreated=None): """Give an answer to this question. If the user is not the question's owner, add an IQuestionMessage with action ANSWER containing an answer for the question. This changes the question's status to ANSWERED and updates the datelastresponse attribute to the message's creation date. When the question owner answers the question, add an IQuestionMessage with action CONFIRM. The question status is changed to SOLVED, the answerer attribute is updated to contain the question owner, the answer attribute will be updated to point at the new message, the datelastresponse and date_solved attributes are updated to the message creation date. This workflow method should only be called when the question status is one of OPEN, ANSWERED or NEEDSINFO. An InvalidQuestionStateError is raised otherwise. Return the created IQuestionMessage. This method should fire an IObjectCreatedEvent for the created IQuestionMessage and an IObjectModifiedEvent for the question. :user: IPerson giving the answer. :answer: A string or IMessage containing the answer. :datecreated: Date for the message. Defaults to the current time. """ def linkFAQ(user, faq, comment, datecreated=None): """Link a FAQ as an answer to this question. Exactly like giveAnswer() but also link the IFAQ faq object to this question. Return the created IQuestionMessage. This method should fire an IObjectCreatedEvent for the created IQuestionMessage and an IObjectModifiedEvent for the question. :param user: IPerson linking the faq. :param faq: The IFAQ containing the answer. :param comment: A string or IMessage explaining how the FAQ is relevant. :param datecreated: Date for the message. Defaults to the current time. """ can_confirm_answer = Attribute( 'Whether the question is in a state for the question owner to ' 'confirm that an answer solved their problem.') def confirmAnswer(comment, answer=None, datecreated=None): """Confirm that a solution to the question was found. Add an IQuestionMessage with action CONFIRM. The question status is changed to SOLVED. If the answer parameter is not None, it is recorded in the answer attribute and the answerer attribute is set to that message's owner. The datelastresponse and date_solved attributes are updated to the message creation date. This workflow method should only be called on behalf of the question owner, when the question status is ANSWERED, or when the status is OPEN or NEEDSINFO but an answer was already provided. An InvalidQuestionStateError is raised otherwise. Return the created IQuestionMessage. This method should fire an IObjectCreatedEvent for the created IQuestionMessage and an IObjectModifiedEvent for the question. :comment: A string or IMessage containing a comment. :answer: The IQuestionMessage that contain the answer to the question. It must be one of the IQuestionMessage of this question. :datecreated: Date for the message. Defaults to the current time. """ def canReject(user): """Test if a user can reject the question. Return true only if user is an answer contact for the question target, the question target owner or part of the administration team. """ @operation_parameters( comment=Text(title=_("An explanation of the rejection"))) @call_with(user=REQUEST_USER) @export_factory_operation(IQuestionMessage, []) @operation_for_version("devel") def reject(user, comment, datecreated=None): """Mark this question as INVALID. Add an IQuestionMessage with action REJECT. The question status is changed to INVALID. The created message is set as the question answer and its owner as the question answerer. The datelastresponse and date_solved are updated to the message creation. Only answer contacts for the question target, the target owner or a member of the admin team can reject a request. All questions can be rejected. Return the created IQuestionMessage. This method should fire an IObjectCreatedEvent for the created IQuestionMessage and an IObjectModifiedEvent for the question. :user: The user rejecting the request. :comment: A string or IMessage containing an explanation of the rejection. :datecreated: Date for the message. Defaults to the current time. """ def expireQuestion(user, comment, datecreated=None): """Mark a question as EXPIRED. Add an IQuestionMessage with action EXPIRE. This changes the question status to EXPIRED and update the datelastresponse attribute to the new message creation date. This workflow method should only be called when the question status is one of OPEN or NEEDSINFO. An InvalidQuestionStateError is raised otherwise. Return the created IQuestionMessage. (Note this method is named expireQuestion and not expire because of conflicts with SQLObject.) This method should fire an IObjectCreatedEvent for the created IQuestionMessage and an IObjectModifiedEvent for the question. :user: IPerson expiring the request. :comment: A string or IMessage containing an explanation for the expiration. :datecreated: Date for the message. Defaults to the current time. """ can_reopen = Attribute( 'Whether the question state is a state where the question owner ' 'could reopen it.') def reopen(comment, datecreated=None): """Reopen a question that was ANSWERED, EXPIRED or SOLVED. Add an IQuestionMessage with action REOPEN. This changes the question status to OPEN and update the datelastquery attribute to the new message creation date. When the question was in the SOLVED state, this method should reset the date_solved, answerer and answer attributes. This workflow method should only be called on behalf of the question owner, when the question status is in one of ANSWERED, EXPIRED or SOLVED. An InvalidQuestionStateError is raised otherwise. Return the created IQuestionMessage. This method should fire an IObjectCreatedEvent for the created IQuestionMessage and an IObjectModifiedEvent for the question. :comment: A string or IMessage containing more information about the request. :datecreated: Date for the message. Defaults to the current time. """ def addComment(user, comment, datecreated=None): """Add a comment on the question. Create an IQuestionMessage with action COMMENT. It leaves the question status unchanged. This method should fire an IObjectCreatedEvent for the created IQuestionMessage and an IObjectModifiedEvent for the question. :user: The IPerson making the comment. :comment: A string or IMessage containing the comment. :datecreated: Date for the message. Defaults to the current time. """ # subscription-related methods @operation_parameters(person=Reference(IPerson, title=_('Person'), required=True)) @call_with(subscribed_by=REQUEST_USER) @export_write_operation() @operation_for_version("devel") def subscribe(person, subscribed_by=None): """Subscribe `person` to the question. :param person: the subscriber. :param subscribed_by: the person who created the subscription. :return: an `IQuestionSubscription`. """ def isSubscribed(person): """Return a boolean indicating whether the person is subscribed.""" @operation_parameters(person=Reference(IPerson, title=_('Person'), required=False)) @call_with(unsubscribed_by=REQUEST_USER) @export_write_operation() @operation_for_version("devel") def unsubscribe(person, unsubscribed_by): """Unsubscribe `person` from the question. :param person: the subscriber. :param unsubscribed_by: the person who removed the subscription. """ def getDirectSubscribers(): """Return the persons who are subscribed to this question. :return: A list of persons sorted by displayname. """ def getDirectSubscribersWithDetails(): """Get direct subscribers and their subscriptions for the question. :returns: A ResultSet of tuples (Person, QuestionSubscription) representing a subscriber and their question subscription. """ def getIndirectSubscribers(): """Return the persons who are implicitly subscribed to this question. :return: A list of persons sorted by displayname. """ def getRecipients(): """Return the set of person to notify about changes in this question. That is the union of getDirectSubscribers() and getIndirectSubscribers(). :return: An `INotificationRecipientSet` containing the persons to notify along the rationale for doing so. """ direct_recipients = Attribute( "Return An `INotificationRecipientSet` containing the persons to " "notify along the rationale for doing so.") indirect_recipients = Attribute( "Return the INotificationRecipientSet of answer contacts for the " "question's target as well as the question's assignee.") @operation_parameters(comment_number=Int( title=_('The number of the comment in the list of messages.'), required=True), visible=Bool(title=_('Show this comment?'), required=True)) @call_with(user=REQUEST_USER) @export_write_operation() @operation_for_version('devel') def setCommentVisibility(user, comment_number, visible): """Set the visible attribute on a question message.
class IConversation(Interface): """A conversation has a number of comments.""" comments = CollectionField(value_type=Reference(schema=IComment), title=_('The comments in the conversation'))
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.
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."""