def announce(self, user, title, summary=None, url=None, publication_date=None): """See IHasAnnouncements.""" # We establish the appropriate target property. project = product = distribution = None if IProduct.providedBy(self): product = self elif IProjectGroup.providedBy(self): project = self elif IDistribution.providedBy(self): distribution = self else: raise AssertionError, 'Unsupported announcement target' # Create the announcement in the database. announcement = Announcement( registrant = user, title = title, summary = summary, url = url, product = product, project = project, distribution = distribution ) announcement.setPublicationDate(publication_date) return announcement
def _getByName(self, name): """Finds a specification by name from the current context. Returns a specification if (and only if) the current context defines a unique specification namespace and then if a matching specification can be found within that namespace. Returns None otherwise. """ if ISpecificationSet.providedBy(self.context): # The context is the set of all specifications. Since this # set corresponds to multiple specification namespaces, we # return None. return None elif IProjectGroup.providedBy(self.context): # The context is a project group. Since a project group # corresponds to multiple specification namespaces, we # return None. return None elif ISpecification.providedBy(self.context): # The context is a specification. Since a specification's # target defines a single specification namespace, we ask # the target to perform the lookup. return self.context.target.getSpecification(name) elif ISprint.providedBy(self.context): # The context is a sprint. Since a sprint corresponds # to multiple specification namespaces, we return None. return None else: # The context is a entity such as a product or distribution. # Since this type of context is associated with exactly one # specification namespace, we ask the context to perform the # lookup. return self.context.getSpecification(name)
def getAnnouncements(self, limit=5, published_only=True): """See IHasAnnouncements.""" # Create the SQL query. query = '1=1 ' # Filter for published news items if necessary. if published_only: query += """ AND Announcement.date_announced <= timezone('UTC'::text, now()) AND Announcement.active IS TRUE """ if IProduct.providedBy(self): if self.project is None: query += """ AND Announcement.product = %s""" % sqlvalues(self.id) else: query += """ AND (Announcement.product = %s OR Announcement.project = %s) """ % sqlvalues(self.id, self.project) elif IProjectGroup.providedBy(self): query += """ AND (Announcement.project = %s OR Announcement.product IN (SELECT id FROM Product WHERE project = %s)) """ % sqlvalues (self.id, self.id) elif IDistribution.providedBy(self): query += (' AND Announcement.distribution = %s' % sqlvalues(self.id)) elif IAnnouncementSet.providedBy(self): # There is no need to filter for pillar if we are looking for # all announcements. pass else: raise AssertionError, 'Unsupported announcement target' return Announcement.select(query, limit=limit)
def template(self): # Check for the magical "index" added by the browser:page template # machinery. If it exists this is actually the # zope.browserpage.simpleviewclass.simple class that is magically # mixed in by the browser:page zcml directive the template defined in # the directive should be used. if safe_hasattr(self, 'index'): return super(HasSpecificationsView, self).template # Sprints and Persons don't have a usage enum for blueprints, so we # have to fallback to the default. if (ISprint.providedBy(self.context) or IPerson.providedBy(self.context)): return self.default_template # ProjectGroups are a special case, as their products may be a # combination of usage settings. To deal with this, check all # products via the involvment menu. if (IProjectGroup.providedBy(self.context) or IProjectGroupSeries.providedBy(self.context)): involvement = getMultiAdapter((self.context, self.request), name='+get-involved') if service_uses_launchpad(involvement.blueprints_usage): return self.default_template else: return self.not_launchpad_template # Otherwise, determine usage and provide the correct template. service_usage = IServiceUsage(self.context) if service_uses_launchpad(service_usage.blueprints_usage): return self.default_template else: return self.not_launchpad_template
def __init__(self, context, request): super(PillarInvolvementView, self).__init__(context, request) self.official_malone = False self.answers_usage = ServiceUsage.UNKNOWN self.blueprints_usage = ServiceUsage.UNKNOWN self.translations_usage = ServiceUsage.UNKNOWN self.codehosting_usage = ServiceUsage.UNKNOWN pillar = nearest(self.context, IPillar) self._set_official_launchpad(pillar) if IDistroSeries.providedBy(self.context): distribution = self.context.distribution self.codehosting_usage = distribution.codehosting_usage self.answers_usage = ServiceUsage.NOT_APPLICABLE elif IDistributionSourcePackage.providedBy(self.context): self.blueprints_usage = ServiceUsage.UNKNOWN self.translations_usage = ServiceUsage.UNKNOWN elif IProjectGroup.providedBy(pillar): # XXX: 2010-10-07 EdwinGrubbs bug=656292 # Fix _set_official_launchpad(). # Project groups do not support submit code, override the # default. self.codehosting_usage = ServiceUsage.NOT_APPLICABLE else: # The context is used by all apps. pass
def _validate(self, input): """Make sure all the aliases are valid for the field's pillar. An alias is valid if it can be used as the name of a pillar and is not identical to the pillar's existing name. """ context = self.context from lp.registry.interfaces.product import IProduct from lp.registry.interfaces.projectgroup import IProjectGroup from lp.registry.interfaces.distribution import IDistribution if IProduct.providedBy(context): name_field = IProduct['name'] elif IProjectGroup.providedBy(context): name_field = IProjectGroup['name'] elif IDistribution.providedBy(context): name_field = IDistribution['name'] else: raise AssertionError("Unexpected context type.") name_field.bind(context) existing_aliases = context.aliases for name in self._split_input(input): if name == context.name: raise LaunchpadValidationError('This is your name: %s' % name) elif name in existing_aliases: # This is already an alias to this pillar, so there's no need # to validate it. pass else: name_field._validate(name)
def template(self): # Check for the magical "index" added by the browser:page template # machinery. If it exists this is actually the # zope.browserpage.simpleviewclass.simple class that is magically # mixed in by the browser:page zcml directive the template defined in # the directive should be used. if safe_hasattr(self, 'index'): return super(HasSpecificationsView, self).template # Sprints and Persons don't have a usage enum for blueprints, so we # have to fallback to the default. if (ISprint.providedBy(self.context) or IPerson.providedBy(self.context)): return self.default_template # ProjectGroups are a special case, as their products may be a # combination of usage settings. To deal with this, check all # products via the involvment menu. if (IProjectGroup.providedBy(self.context) or IProjectGroupSeries.providedBy(self.context)): involvement = getMultiAdapter( (self.context, self.request), name='+get-involved') if service_uses_launchpad(involvement.blueprints_usage): return self.default_template else: return self.not_launchpad_template # Otherwise, determine usage and provide the correct template. service_usage = IServiceUsage(self.context) if service_uses_launchpad(service_usage.blueprints_usage): return self.default_template else: return self.not_launchpad_template
def project_products_using_malone_vocabulary_factory(context): """Return a vocabulary containing a project's products using Malone.""" project = IProjectGroup(context) return SimpleVocabulary([ SimpleTerm(product, product.name, title=product.displayname) for product in project.products if product.bug_tracking_usage == ServiceUsage.LAUNCHPAD])
def getAnnouncements(self, limit=5, published_only=True): """See IHasAnnouncements.""" # Create the SQL query. query = '1=1 ' # Filter for published news items if necessary. if published_only: query += """ AND Announcement.date_announced <= timezone('UTC'::text, now()) AND Announcement.active IS TRUE """ if IProduct.providedBy(self): if self.projectgroup is None: query += """ AND Announcement.product = %s""" % sqlvalues(self.id) else: query += """ AND (Announcement.product = %s OR Announcement.project = %s) """ % sqlvalues(self.id, self.projectgroup) elif IProjectGroup.providedBy(self): query += """ AND (Announcement.project = %s OR Announcement.product IN (SELECT id FROM Product WHERE project = %s)) """ % sqlvalues(self.id, self.id) elif IDistribution.providedBy(self): query += (' AND Announcement.distribution = %s' % sqlvalues(self.id)) elif IAnnouncementSet.providedBy(self): # There is no need to filter for pillar if we are looking for # all announcements. pass else: raise AssertionError('Unsupported announcement target') return Announcement.select(query, limit=limit)
def announce(self, user, title, summary=None, url=None, publication_date=None): """See IHasAnnouncements.""" # We establish the appropriate target property. projectgroup = product = distribution = None if IProduct.providedBy(self): product = self elif IProjectGroup.providedBy(self): projectgroup = self elif IDistribution.providedBy(self): distribution = self else: raise AssertionError('Unsupported announcement target') # Create the announcement in the database. announcement = Announcement( registrant=user, title=title, summary=summary, url=url, product=product, projectgroup=projectgroup, distribution=distribution, ) announcement.setPublicationDate(publication_date) return announcement
def _getPublicRevisionsHelper(obj, day_limit): """Helper method for Products and ProjectGroups.""" # Here to stop circular imports. from lp.code.model.branch import Branch from lp.registry.model.product import Product from lp.code.model.branchrevision import BranchRevision origin = [ Revision, Join(BranchRevision, BranchRevision.revision == Revision.id), Join(Branch, BranchRevision.branch == Branch.id), ] conditions = And( revision_time_limit(day_limit), Branch.information_type.is_in(PUBLIC_INFORMATION_TYPES)) if IProduct.providedBy(obj): conditions = And(conditions, Branch.product == obj) elif IProjectGroup.providedBy(obj): origin.append(Join(Product, Branch.product == Product.id)) conditions = And(conditions, Product.projectgroup == obj) else: raise AssertionError("Not an IProduct or IProjectGroup: %r" % obj) result_set = Store.of(obj).using(*origin).find(Revision, conditions) result_set.config(distinct=True) return result_set.order_by(Desc(Revision.revision_date))
def _getPublicRevisionsHelper(obj, day_limit): """Helper method for Products and ProjectGroups.""" # Here to stop circular imports. from lp.code.model.branch import Branch from lp.registry.model.product import Product from lp.code.model.branchrevision import BranchRevision origin = [ Revision, Join(BranchRevision, BranchRevision.revision == Revision.id), Join(Branch, BranchRevision.branch == Branch.id), ] conditions = And( revision_time_limit(day_limit), Branch.information_type.is_in(PUBLIC_INFORMATION_TYPES)) if IProduct.providedBy(obj): conditions = And(conditions, Branch.product == obj) elif IProjectGroup.providedBy(obj): origin.append(Join(Product, Branch.product == Product.id)) conditions = And(conditions, Product.project == obj) else: raise AssertionError( "Not an IProduct or IProjectGroup: %r" % obj) result_set = Store.of(obj).using(*origin).find( Revision, conditions) result_set.config(distinct=True) return result_set.order_by(Desc(Revision.revision_date))
def __init__(self, component): if IProjectGroup.providedBy(component): component_type = 'project group' else: component_type = component.__class__.__name__.lower() LaunchpadFault.__init__( self, component_name=component.displayname, component_type=component_type)
def initialize(self): context = self.context if IProduct.providedBy(context): self.context_name = "Project" elif IDistribution.providedBy(context): self.context_name = "Distribution" elif IProjectGroup.providedBy(context): self.context_name = "Project Group" else: raise AssertionError("Context is not a Product, Project group or Distribution: %r" % context)
def _assert_cache_values(self, view, duplicate_search): cache = IJSONRequestCache(view.request).objects self.assertEqual( duplicate_search, cache['enable_bugfiling_duplicate_search']) excluded_statuses = [ BugTaskStatus.UNKNOWN, BugTaskStatus.EXPIRED, BugTaskStatus.INVALID, BugTaskStatus.OPINION, BugTaskStatus.WONTFIX, BugTaskStatus.INCOMPLETE] bugtask_status_data = [] for item in BugTaskStatus: item = item.value if item in excluded_statuses: continue name = item.title value = item.title description = item.description new_item = {'name': name, 'value': value, 'description': description, 'description_css_class': 'choice-description', 'style': '', 'help': '', 'disabled': False, 'css_class': 'status' + item.name} bugtask_status_data.append(new_item) self.assertEqual(bugtask_status_data, cache['bugtask_status_data']) excluded_importances = [BugTaskImportance.UNKNOWN] bugtask_importance_data = [] for item in BugTaskImportance: item = item.value if item in excluded_importances: continue name = item.title value = item.title description = item.description new_item = {'name': name, 'value': value, 'description': description, 'description_css_class': 'choice-description', 'style': '', 'help': '', 'disabled': False, 'css_class': 'importance' + item.name} bugtask_importance_data.append(new_item) self.assertEqual( bugtask_importance_data, cache['bugtask_importance_data']) bugtask_info_type_data = {} if not IProjectGroup.providedBy(view.context): for item in view.context.getAllowedBugInformationTypes(): new_item = {'name': item.title, 'value': item.name, 'description': item.description, 'is_private': item not in PUBLIC_INFORMATION_TYPES, 'description_css_class': 'choice-description'} bugtask_info_type_data[item.name] = new_item self.assertContentEqual( bugtask_info_type_data, cache['information_type_data'])
def create_faq(self): """Return a Link to create a new FAQ.""" collection = IFAQCollection(self.context) if IProjectGroup.providedBy(self.context): url = '' enabled = False else: url = canonical_url( collection, view_name='+createfaq', rootsite='answers') enabled = True return Link(url, 'Create a new FAQ', icon='add', enabled=enabled)
def create_faq(self): """Return a Link to create a new FAQ.""" collection = IFAQCollection(self.context) if IProjectGroup.providedBy(self.context): url = '' enabled = False else: url = canonical_url(collection, view_name='+createfaq', rootsite='answers') enabled = True return Link(url, 'Create a new FAQ', icon='add', enabled=enabled)
def initialize(self): context = self.context if IProduct.providedBy(context): self.context_name = 'Project' elif IDistribution.providedBy(context): self.context_name = 'Distribution' elif IProjectGroup.providedBy(context): self.context_name = 'Project Group' else: raise AssertionError( "Context is not a Product, Project group or Distribution: %r" % context)
def _findPillar(self, pillar_name): """Find and return the pillar with the given name. If the given name is '+junk' or None, return None. :raise NoSuchProduct if there's no pillar with the given name or it is a project. """ if pillar_name == "+junk": return None pillar = self._findOrRaise(NoSuchProduct, pillar_name, getUtility(IPillarNameSet).getByName) if IProjectGroup.providedBy(pillar): raise NoSuchProduct(pillar_name) return pillar
def _findPillar(self, pillar_name): """Find and return the pillar with the given name. If the given name is '+junk' or None, return None. :raise NoSuchProduct if there's no pillar with the given name or it is a project. """ if pillar_name == '+junk': return None pillar = self._findOrRaise(NoSuchProduct, pillar_name, getUtility(IPillarNameSet).getByName) if IProjectGroup.providedBy(pillar): raise NoSuchProduct(pillar_name) return pillar
def logo(self): """See `IFeed`.""" # The logo is different depending upon the context we are displaying. if self.context.logo is not None: return self.context.logo.getURL() elif IProjectGroup.providedBy(self.context): url = '/@@/project-logo' elif IProduct.providedBy(self.context): url = '/@@/product-logo' elif IDistribution.providedBy(self.context): url = '/@@/distribution-logo' else: raise AssertionError( "Context for TargetsAnnouncementsFeed does not provide an " "expected interface.") return self.site_url + url
def icon(self): """See `IFeed`.""" # The icon is customized based upon the context. if self.context.icon is not None: return self.context.icon.getURL() elif IProjectGroup.providedBy(self.context): url = '/@@/project' elif IProduct.providedBy(self.context): url = '/@@/product' elif IDistribution.providedBy(self.context): url = '/@@/distribution' else: raise AssertionError( "Context for TargetsAnnouncementsFeed does not provide an " "expected interface.") return self.site_url + url
def __init__(self, search_text=None, owner=None, sort=None, product=None, distribution=None, projectgroup=None): """Initialize a new FAQ search. See `IFAQCollection`.searchFAQs for the basic parameters description. Additional parameters: :param product: The product in which to search for FAQs. :param distribution: The distribution in which to search for FAQs. :param projectgroup: The project group in which to search for FAQs. """ if search_text is not None: assert isinstance(search_text, basestring), ( 'search_text should be a string, not %s' % type(search_text)) self.search_text = search_text if owner is not None: assert IPerson.providedBy(owner), ( 'owner should be an IPerson, not %s' % type(owner)) self.owner = owner if sort is not None: assert sort in FAQSort.items, ( 'sort should be an item from FAQSort, not %s' % type(sort)) self.sort = sort if product is not None: assert IProduct.providedBy(product), ( 'product should be an IProduct, not %s' % type(product)) assert distribution is None and projectgroup is None, ( 'can only use one of product, distribution, or projectgroup') self.product = product if distribution is not None: assert IDistribution.providedBy(distribution), ( 'distribution should be an IDistribution, %s' % type(distribution)) assert product is None and projectgroup is None, ( 'can only use one of product, distribution, or projectgroup') self.distribution = distribution if projectgroup is not None: assert IProjectGroup.providedBy(projectgroup), ( 'projectgroup should be an IProjectGroup, not %s' % type(projectgroup)) assert product is None and distribution is None, ( 'can only use one of product, distribution, or projectgroup') self.projectgroup = projectgroup
def __init__(self, search_text=None, owner=None, sort=None, product=None, distribution=None, project=None): """Initialize a new FAQ search. See `IFAQCollection`.searchFAQs for the basic parameters description. Additional parameters: :param product: The product in which to search for FAQs. :param distribution: The distribution in which to search for FAQs. :param project: The project in which to search for FAQs. """ if search_text is not None: assert isinstance(search_text, basestring), ( 'search_text should be a string, not %s' % type(search_text)) self.search_text = search_text if owner is not None: assert IPerson.providedBy(owner), ( 'owner should be an IPerson, not %s' % type(owner)) self.owner = owner if sort is not None: assert sort in FAQSort.items, ( 'sort should be an item from FAQSort, not %s' % type(sort)) self.sort = sort if product is not None: assert IProduct.providedBy(product), ( 'product should be an IProduct, not %s' % type(product)) assert distribution is None and project is None, ( 'can only use one of product, distribution, or project') self.product = product if distribution is not None: assert IDistribution.providedBy(distribution), ( 'distribution should be an IDistribution, %s' % type(distribution)) assert product is None and project is None, ( 'can only use one of product, distribution, or project') self.distribution = distribution if project is not None: assert IProjectGroup.providedBy(project), ( 'project should be an IProjectGroup, not %s' % type(project)) assert product is None and distribution is None, ( 'can only use one of product, distribution, or project') self.project = project
def retarget(self, target): """See `IAnnouncement`.""" if IProduct.providedBy(target): self.product = target self.distribution = None self.project = None elif IDistribution.providedBy(target): self.distribution = target self.project = None self.product = None elif IProjectGroup.providedBy(target): self.project = target self.distribution = None self.product = None else: raise AssertionError, 'Unknown target' self.date_last_modified = UTC_NOW
def retarget(self, target): """See `IAnnouncement`.""" if IProduct.providedBy(target): self.product = target self.distribution = None self.projectgroup = None elif IDistribution.providedBy(target): self.distribution = target self.projectgroup = None self.product = None elif IProjectGroup.providedBy(target): self.projectgroup = target self.distribution = None self.product = None else: raise AssertionError('Unknown target') self.date_last_modified = UTC_NOW
def setTarget(self, target): """Constrain the search to only return items in target. This is equivalent to calling setProduct etc but the type of target does not need to be known to the caller. :param target: A `IHasBug`, or some search term like all/any/none on `IHasBug`. If using all/any all the targets must be of the same type due to implementation limitations. Currently only distroseries and productseries `IHasBug` implementations are supported. """ # Yay circular deps. from lp.registry.interfaces.distribution import IDistribution from lp.registry.interfaces.distroseries import IDistroSeries from lp.registry.interfaces.product import IProduct from lp.registry.interfaces.productseries import IProductSeries from lp.registry.interfaces.milestone import IMilestone from lp.registry.interfaces.projectgroup import IProjectGroup from lp.registry.interfaces.sourcepackage import ISourcePackage from lp.registry.interfaces.distributionsourcepackage import \ IDistributionSourcePackage if isinstance(target, (any, all)): assert len(target.query_values), \ 'cannot determine target with no targets' instance = target.query_values[0] else: instance = target if IDistribution.providedBy(instance): self.setDistribution(target) elif IDistroSeries.providedBy(instance): self.setDistroSeries(target) elif IProduct.providedBy(instance): self.setProduct(target) elif IProductSeries.providedBy(instance): self.setProductSeries(target) elif IMilestone.providedBy(instance): self.milestone = target elif ISourcePackage.providedBy(instance): self.setSourcePackage(target) elif IDistributionSourcePackage.providedBy(instance): self.setSourcePackage(target) elif IProjectGroup.providedBy(instance): self.setProject(target) else: raise AssertionError("unknown target type %r" % target)
def setTarget(self, target): """Constrain the search to only return items in target. This is equivalent to calling setProduct etc but the type of target does not need to be known to the caller. :param target: A `IHasBug`, or some search term like all/any/none on `IHasBug`. If using all/any all the targets must be of the same type due to implementation limitations. Currently only distroseries and productseries `IHasBug` implementations are supported. """ # Yay circular deps. from lp.registry.interfaces.distribution import IDistribution from lp.registry.interfaces.distroseries import IDistroSeries from lp.registry.interfaces.product import IProduct from lp.registry.interfaces.productseries import IProductSeries from lp.registry.interfaces.milestone import IMilestone from lp.registry.interfaces.projectgroup import IProjectGroup from lp.registry.interfaces.sourcepackage import ISourcePackage from lp.registry.interfaces.distributionsourcepackage import \ IDistributionSourcePackage if isinstance(target, (any, all)): assert len(target.query_values), \ 'cannot determine target with no targets' instance = target.query_values[0] else: instance = target if IDistribution.providedBy(instance): self.setDistribution(target) elif IDistroSeries.providedBy(instance): self.setDistroSeries(target) elif IProduct.providedBy(instance): self.setProduct(target) elif IProductSeries.providedBy(instance): self.setProductSeries(target) elif IMilestone.providedBy(instance): self.milestone = target elif ISourcePackage.providedBy(instance): self.setSourcePackage(target) elif IDistributionSourcePackage.providedBy(instance): self.setSourcePackage(target) elif IProjectGroup.providedBy(instance): self.setProjectGroup(target) else: raise AssertionError("unknown target type %r" % target)
def getTopContributors(self, category=None, limit=None): """See IKarmaContext.""" from lp.registry.model.person import Person store = IStore(Person) if IProduct.providedBy(self): condition = KarmaCache.productID == self.id elif IDistribution.providedBy(self): condition = KarmaCache.distributionID == self.id elif IProjectGroup.providedBy(self): condition = KarmaCache.projectID == self.id else: raise AssertionError("Not a product, project or distribution: %r" % self) if category is not None: category = category.id contributors = store.find( (Person, KarmaCache.karmavalue), KarmaCache.personID == Person.id, KarmaCache.categoryID == category, condition).order_by( Desc(KarmaCache.karmavalue)).config(limit=limit) return list(contributors)
def getTopContributors(self, category=None, limit=None): """See IKarmaContext.""" from lp.registry.model.person import Person store = IStore(Person) if IProduct.providedBy(self): condition = KarmaCache.productID == self.id elif IDistribution.providedBy(self): condition = KarmaCache.distributionID == self.id elif IProjectGroup.providedBy(self): condition = KarmaCache.projectID == self.id else: raise AssertionError( "Not a product, project or distribution: %r" % self) if category is not None: category = category.id contributors = store.find( (Person, KarmaCache.karmavalue), KarmaCache.personID == Person.id, KarmaCache.categoryID == category, condition).order_by( Desc(KarmaCache.karmavalue)).config(limit=limit) return list(contributors)
def initialize(self): if IPerson.providedBy(self.context): self.is_person = True elif IDistribution.providedBy(self.context): self.is_target = True self.is_pillar = True self.show_series = True elif IProduct.providedBy(self.context): self.is_target = True self.is_pillar = True self.has_wiki = True self.show_series = True elif IProjectGroup.providedBy(self.context): self.is_project = True self.is_pillar = True self.has_wiki = True self.show_target = True self.show_series = True elif IProjectGroupSeries.providedBy(self.context): self.show_milestone = True self.show_target = True self.show_series = True elif (IProductSeries.providedBy(self.context) or IDistroSeries.providedBy(self.context)): self.is_series = True self.show_milestone = True elif ISprint.providedBy(self.context): self.is_sprint = True self.show_target = True else: raise AssertionError('Unknown blueprint listing site.') if IHasDrivers.providedBy(self.context): self.has_drivers = True self.batchnav = BatchNavigator( self.specs, self.request, size=config.launchpad.default_batch_size)
def review(self, user, permission, context=None, date_expires=None): """See `IOAuthRequestToken`.""" if self.is_reviewed: raise OAuthValidationError( "Request tokens can be reviewed only once.") if self.is_expired: raise OAuthValidationError( 'This request token has expired and can no longer be ' 'reviewed.') self.date_reviewed = datetime.now(pytz.timezone('UTC')) self.date_expires = date_expires self.person = user self.permission = permission if IProduct.providedBy(context): self.product = context elif IProjectGroup.providedBy(context): self.project = context elif IDistribution.providedBy(context): self.distribution = context elif IDistributionSourcePackage.providedBy(context): self.sourcepackagename = context.sourcepackagename self.distribution = context.distribution else: assert context is None, ("Unknown context type: %r." % context)
def display_target_column(self): """Return True when the context has question targets to display.""" return IProjectGroup.providedBy(self.context)
def _assert_cache_values(self, view, duplicate_search): cache = IJSONRequestCache(view.request).objects self.assertEqual(duplicate_search, cache['enable_bugfiling_duplicate_search']) excluded_statuses = [ BugTaskStatus.UNKNOWN, BugTaskStatus.EXPIRED, BugTaskStatus.INVALID, BugTaskStatus.OPINION, BugTaskStatus.WONTFIX, BugTaskStatus.INCOMPLETE ] bugtask_status_data = [] for item in BugTaskStatus: item = item.value if item in excluded_statuses: continue name = item.title value = item.title description = item.description new_item = { 'name': name, 'value': value, 'description': description, 'description_css_class': 'choice-description', 'style': '', 'help': '', 'disabled': False, 'css_class': 'status' + item.name } bugtask_status_data.append(new_item) self.assertEqual(bugtask_status_data, cache['bugtask_status_data']) excluded_importances = [BugTaskImportance.UNKNOWN] bugtask_importance_data = [] for item in BugTaskImportance: item = item.value if item in excluded_importances: continue name = item.title value = item.title description = item.description new_item = { 'name': name, 'value': value, 'description': description, 'description_css_class': 'choice-description', 'style': '', 'help': '', 'disabled': False, 'css_class': 'importance' + item.name } bugtask_importance_data.append(new_item) self.assertEqual(bugtask_importance_data, cache['bugtask_importance_data']) bugtask_info_type_data = {} if not IProjectGroup.providedBy(view.context): for item in view.context.getAllowedBugInformationTypes(): new_item = { 'name': item.title, 'value': item.name, 'description': item.description, 'is_private': item not in PUBLIC_INFORMATION_TYPES, 'description_css_class': 'choice-description' } bugtask_info_type_data[item.name] = new_item self.assertContentEqual(bugtask_info_type_data, cache['information_type_data'])
def sharePillarInformation(self, pillar, grantee, user, permissions): """See `ISharingService`.""" # We do not support adding grantees to project groups. assert not IProjectGroup.providedBy(pillar) # Separate out the info types according to permission. information_types = permissions.keys() info_types_for_all = [ info_type for info_type in information_types if permissions[info_type] == SharingPermission.ALL] info_types_for_some = [ info_type for info_type in information_types if permissions[info_type] == SharingPermission.SOME] info_types_for_nothing = [ info_type for info_type in information_types if permissions[info_type] == SharingPermission.NOTHING] # The wanted policies are for the information_types in all. required_pillar_info_types = [ (pillar, information_type) for information_type in information_types if information_type in info_types_for_all] policy_source = getUtility(IAccessPolicySource) policy_grant_source = getUtility(IAccessPolicyGrantSource) if len(required_pillar_info_types) > 0: wanted_pillar_policies = policy_source.find( required_pillar_info_types) # We need to figure out which policy grants to create or delete. wanted_policy_grants = [(policy, grantee) for policy in wanted_pillar_policies] existing_policy_grants = [ (grant.policy, grant.grantee) for grant in policy_grant_source.find(wanted_policy_grants)] # Create any newly required policy grants. policy_grants_to_create = ( set(wanted_policy_grants).difference(existing_policy_grants)) if len(policy_grants_to_create) > 0: policy_grant_source.grant( [(policy, grantee, user) for policy, grantee in policy_grants_to_create]) # Now revoke any existing policy grants for types with # permission 'some'. all_pillar_policies = policy_source.findByPillar([pillar]) policy_grants_to_revoke = [ (policy, grantee) for policy in all_pillar_policies if policy.type in info_types_for_some] if len(policy_grants_to_revoke) > 0: policy_grant_source.revoke(policy_grants_to_revoke) # For information types with permission 'nothing', we can simply # call the deletePillarGrantee method directly. if len(info_types_for_nothing) > 0: self.deletePillarGrantee( pillar, grantee, user, info_types_for_nothing) # Return grantee data to the caller. ap_grant_flat = getUtility(IAccessPolicyGrantFlatSource) grant_permissions = list(ap_grant_flat.findGranteePermissionsByPolicy( all_pillar_policies, [grantee])) grant_counts = list(self.getAccessPolicyGrantCounts(pillar)) invisible_types = [ count_info[0].title for count_info in grant_counts if count_info[1] == 0] grantee = None if grant_permissions: [grantee] = self.jsonGranteeData(grant_permissions) result = { 'grantee_entry': grantee, 'invisible_information_types': invisible_types} return result
def getByName(self, name, ignore_inactive=False): """See `IProjectGroupSet`.""" pillar = getUtility(IPillarNameSet).getByName(name, ignore_inactive) if not IProjectGroup.providedBy(pillar): return None return pillar
def context_is_project(self): """Return True when the context is a project.""" return IProjectGroup.providedBy(self.context)
def getBugTarget(cls, path): """Return the IBugTarget with the given path. Path should be in any of the following forms: $product $product/$product_series $distribution $distribution/$source_package $distribution/$distro_series $distribution/$distro_series/$source_package """ path = cls._normalizePath(path) name, rest = cls._splitPath(path) pillar = getUtility(IPillarNameSet).getByName(name, ignore_inactive=True) if pillar is None: raise BugTargetNotFound( "There is no project named '%s' registered in Launchpad." % name) # We can't check for IBugTarget, since ProjectGroup is an IBugTarget # we don't allow bugs to be filed against. if IProjectGroup.providedBy(pillar): products = ", ".join(product.name for product in pillar.products) raise BugTargetNotFound( "%s is a group of projects. To report a bug, you need to" " specify which of these projects the bug applies to: %s" % (pillar.name, products)) assert IDistribution.providedBy(pillar) or IProduct.providedBy(pillar) if not rest: return pillar # Resolve the path that is after the pillar name. if IProduct.providedBy(pillar): series_name, rest = cls._splitPath(rest) product_series = pillar.getSeries(series_name) if product_series is None: raise BugTargetNotFound( "%s doesn't have a series named '%s'." % (pillar.displayname, series_name)) elif not rest: return product_series else: assert IDistribution.providedBy(pillar) # The next step can be either a distro series or a source # package. series_name, rest = cls._splitPath(rest) try: series = pillar.getSeries(series_name) except NotFoundError: package_name = series_name else: if not rest: return series else: pillar = series package_name, rest = cls._splitPath(rest) package = pillar.getSourcePackage(package_name) if package is None: raise BugTargetNotFound( "%s doesn't have a series or source package named '%s'." % (pillar.displayname, package_name)) elif not rest: return package assert rest, "This is the fallback for unexpected path components." raise BugTargetNotFound("Unexpected path components: %s" % rest)
def getBugTarget(cls, path): """Return the IBugTarget with the given path. Path should be in any of the following forms: $product $product/$product_series $distribution $distribution/$source_package $distribution/$distro_series $distribution/$distro_series/$source_package """ path = cls._normalizePath(path) name, rest = cls._splitPath(path) pillar = getUtility(IPillarNameSet).getByName( name, ignore_inactive=True) if pillar is None: raise BugTargetNotFound( "There is no project named '%s' registered in Launchpad." % name) # We can't check for IBugTarget, since ProjectGroup is an IBugTarget # we don't allow bugs to be filed against. if IProjectGroup.providedBy(pillar): products = ", ".join(product.name for product in pillar.products) raise BugTargetNotFound( "%s is a group of projects. To report a bug, you need to" " specify which of these projects the bug applies to: %s" % ( pillar.name, products)) assert IDistribution.providedBy(pillar) or IProduct.providedBy(pillar) if not rest: return pillar # Resolve the path that is after the pillar name. if IProduct.providedBy(pillar): series_name, rest = cls._splitPath(rest) product_series = pillar.getSeries(series_name) if product_series is None: raise BugTargetNotFound( "%s doesn't have a series named '%s'." % ( pillar.displayname, series_name)) elif not rest: return product_series else: assert IDistribution.providedBy(pillar) # The next step can be either a distro series or a source # package. series_name, rest = cls._splitPath(rest) try: series = pillar.getSeries(series_name) except NotFoundError: package_name = series_name else: if not rest: return series else: pillar = series package_name, rest = cls._splitPath(rest) package = pillar.getSourcePackage(package_name) if package is None: raise BugTargetNotFound( "%s doesn't have a series or source package named '%s'." % (pillar.displayname, package_name)) elif not rest: return package assert rest, "This is the fallback for unexpected path components." raise BugTargetNotFound("Unexpected path components: %s" % rest)