def _reindex_endpoints(self, relation): trs = TicketRelationsSpecifics(self.env) ticket_indexer = TicketIndexer(self.env) for resource in map(ResourceIdSerializer.get_resource_by_id, (relation.source, relation.destination)): if resource.realm == 'ticket': ticket = trs._create_ticket_by_full_id(resource) ticket_indexer._index_ticket(ticket)
def get_ticket_relations(self, ticket): grouped_relations = {} relsys = RelationsSystem(self.env) reltypes = relsys.get_relation_types() trs = TicketRelationsSpecifics(self.env) for r in relsys.get_relations(ticket): r['desthref'] = get_resource_url(self.env, r['destination'], self.env.href) r['destticket'] = trs._create_ticket_by_full_id(r['destination']) grouped_relations.setdefault(reltypes[r['type']], []).append(r) return grouped_relations
def test_can_find_ticket_by_product_and_id(self): """ Can find ticket given #prefix-id""" product2 = "tp2" self._load_product_from_data(self.global_env, product2) p2_env = ProductEnvironment(self.global_env, product2) t1 = self._insert_and_load_ticket_with_env(p2_env, "T1") trs = TicketRelationsSpecifics(self.env) ticket = trs.find_ticket("#%s-%d" % (product2, t1.id)) self.assertEqual(ticket.id, 1)
def test_can_find_ticket_by_id_from_different_env(self): """ Can find ticket from different env given #id""" product2 = "tp2" self._load_product_from_data(self.global_env, product2) p2_env = ProductEnvironment(self.global_env, product2) t1 = self._insert_and_load_ticket_with_env(p2_env, "T1") trs = TicketRelationsSpecifics(self.env) ticket = trs.find_ticket("#%d" % t1.id) self.assertEqual(ticket.id, 1)
def test_can_resolve_ticket_when_blocker_is_resolved(self): #arrange ticket1 = self._insert_and_load_ticket("A1") ticket2 = self._insert_and_load_ticket("A2", status="closed") self.add_relation(ticket1, DEPENDS_ON, ticket2) #act self.req.args["action"] = 'resolve' warnings = TicketRelationsSpecifics(self.env).validate_ticket( self.req, ticket1) #assert self.assertEqual(0, len(list(warnings)))
def test_ticket_can_be_resolved(self): #arrange parent = self._insert_and_load_ticket("A1") child = self._insert_and_load_ticket("A2") #act self.add_relation(parent, PARENT, child) self.req.args['action'] = 'resolve' warnings = \ TicketRelationsSpecifics(self.env).validate_ticket(self.req, child) self.assertEqual(0, len(list(warnings)))
def validate(self, relation): source, destination = map(ResourceIdSerializer.get_resource_by_id, [relation.source, relation.destination]) if source.realm == 'ticket' and destination.realm == 'ticket': source, destination = map( TicketRelationsSpecifics(self.env)._create_ticket_by_full_id, [source, destination]) if destination['time'] > source['time']: raise ValidationError( "Relation %s must reference an older resource." % self.render_relation_type(relation.type))
def test_cannot_resolve_ticket_when_blocker_is_unresolved(self): #arrange ticket1 = self._insert_and_load_ticket("A1") ticket2 = self._insert_and_load_ticket("A2") self.relations_system.add(ticket1, ticket2, "dependson") #act self.req.args["action"] = 'resolve' warnings = TicketRelationsSpecifics(self.env).validate_ticket( self.req, ticket1) #asset self.assertEqual(1, len(list(warnings)))
def test_cannot_close_ticket_with_open_children(self): t1 = self._insert_and_load_ticket("1", status='closed') t2 = self._insert_and_load_ticket("2", status='closed') t3 = self._insert_and_load_ticket("3") self.relations_system.add(t2, t1, "parent") self.relations_system.add(t3, t1, "parent") self.req.args["action"] = 'resolve' warnings = TicketRelationsSpecifics(self.env).validate_ticket( self.req, t1) #assert self.assertEqual(1, len(list(warnings)))
def test_cannot_close_ticket_with_open_children(self): t1 = self._insert_and_load_ticket("1") # t1 t2 = self._insert_and_load_ticket("2", status='closed') # / | \ t3 = self._insert_and_load_ticket("3") # t2 t3 t4 t4 = self._insert_and_load_ticket("4") self.add_relation(t1, PARENT, t2) self.add_relation(t1, PARENT, t3) self.add_relation(t1, PARENT, t4) # A warning is be returned for each open ticket self.req.args["action"] = 'resolve' warnings = \ TicketRelationsSpecifics(self.env).validate_ticket(self.req, t1) self.assertEqual(2, len(list(warnings)))
def notify(self, relation, deleted=False): self.relation = relation source = ResourceIdSerializer.get_resource_by_id(relation.source) if source.realm == 'ticket': self.imitate_ticket_notification = True helper = TicketRelationsSpecifics(self.env) t = helper._create_ticket_by_full_id(source) self.template = Chrome(self.env).load_template( TicketNotifyEmail.template_name, method='text') if deleted: modtime = deleted else: modtime = from_utimestamp(relation.time) TicketNotifyEmail.notify(self, t, newticket=False, modtime=modtime) else: self._generic_notify(relation, deleted)
def process_request(self, req): tid = req.args.get('id') if not tid: raise TracError(_('No ticket id provided.')) try: ticket = Ticket(self.env, tid) except ValueError: raise TracError(_('Invalid ticket id.')) req.perm.require('TICKET_VIEW') relsys = RelationsSystem(self.env) data = { 'relation': {}, } if req.method == 'POST': # for modifying the relations TICKET_MODIFY is required for # both the source and the destination tickets req.perm.require('TICKET_MODIFY') if 'remove' in req.args: rellist = req.args.get('sel') if rellist: if isinstance(rellist, basestring): rellist = [ rellist, ] self.remove_relations(req, rellist) elif 'add' in req.args: relation = dict( destination=req.args.get('dest_tid', ''), type=req.args.get('reltype', ''), comment=req.args.get('comment', ''), ) try: trs = TicketRelationsSpecifics(self.env) dest_ticket = trs.find_ticket(relation['destination']) except NoSuchTicketError: data['error'] = _('Invalid ticket ID.') else: req.perm.require('TICKET_MODIFY', Resource(dest_ticket.id)) try: relsys.add(ticket, dest_ticket, relation['type'], relation['comment'], req.authname) except NoSuchTicketError: data['error'] = _('Invalid ticket ID.') except UnknownRelationType: data['error'] = _('Unknown relation type.') except ValidationError as ex: data['error'] = ex.message if 'error' in data: data['relation'] = relation else: raise TracError(_('Invalid operation.')) data.update({ 'ticket': ticket, 'reltypes': sorted(relsys.get_relation_types().iteritems(), key=lambda x: x[0]), 'relations': self.get_ticket_relations(ticket), }) return 'relations_manage.html', data, None
def process_request(self, req): tid = req.args.get('id') if not tid: raise TracError(_('No ticket id provided.')) try: ticket = Ticket(self.env, tid) except ValueError: raise TracError(_('Invalid ticket id.')) # For access to the relation management, TICKET_MODIFY is required. req.perm.require('TICKET_MODIFY') relsys = RelationsSystem(self.env) data = { 'relation': {}, } if req.method == 'POST': # for modifying the relations TICKET_MODIFY is required for # both the source and the destination tickets if 'remove' in req.args: rellist = req.args.get('sel') if rellist: if isinstance(rellist, basestring): rellist = [ rellist, ] self.remove_relations(req, rellist) elif 'add' in req.args: relation = dict( destination=req.args.get('dest_tid', ''), type=req.args.get('reltype', ''), comment=req.args.get('comment', ''), ) try: trs = TicketRelationsSpecifics(self.env) dest_ticket = trs.find_ticket(relation['destination']) except NoSuchTicketError: data['error'] = _('Invalid ticket ID.') else: req.perm.require('TICKET_MODIFY', Resource(dest_ticket.id)) try: dbrel = relsys.add(ticket, dest_ticket, relation['type'], relation['comment'], req.authname) except NoSuchTicketError: data['error'] = _('Invalid ticket ID.') except UnknownRelationType: data['error'] = _('Unknown relation type.') except ValidationError as ex: data['error'] = ex.message else: # Notify try: self.notify_relation_changed(dbrel) except Exception, e: self.log.error( "Failure sending notification on" "creation of relation: %s", exception_to_unicode(e)) add_warning( req, _( "The relation has been added, " "but an error occurred while " "sending notifications: " "%(message)s", message=to_unicode(e))) if 'error' in data: data['relation'] = relation else: raise TracError(_('Invalid operation.'))