def test_no_disown_from_changed_component(self): """ Verify that a ticket is not disowned when the component is changed to a non-assigned component. """ component1 = Component(self.env) component1.name = 'test1' component1.owner = 'joe' component1.insert() component2 = Component(self.env) component2.name = 'test2' component2.owner = '' component2.insert() ticket = Ticket(self.env) ticket['reporter'] = 'santa' ticket['summary'] = 'Foo' ticket['component'] = 'test1' ticket['status'] = 'new' tktid = ticket.insert() ticket = Ticket(self.env, tktid) ticket['component'] = 'test2' ticket.save_changes('jane', 'Testing') self.assertEqual('joe', ticket['owner'])
def test_set_status_to_previous(self): self.env.config.set( 'ticket', 'workflow', 'ConfigurableTicketWorkflow,TicketWorkflowOpStatusPrevious') self._config_set('ticket-workflow', [ ('revert-status', '* -> *'), ('revert-status.operations', 'set_status_to_previous'), ]) tktid = self._insert_ticket(when=datetime(2017, 3, 9, tzinfo=utc), summary='set status to previous', reporter='anonymous', owner='joe') ticket = Ticket(self.env, tktid) req = self._post_req('revert-status', ticket) self.assertTrue(self.tktmod.match_request(req)) self.assertRaises(RequestDone, self.tktmod.process_request, req) ticket = Ticket(self.env, tktid) self.assertEqual('new', ticket['status']) ticket = Ticket(self.env, tktid) ticket['status'] = 'assigned' ticket.save_changes(when=datetime(2017, 3, 9, 1, tzinfo=utc)) ticket['status'] = 'closed' ticket.save_changes(when=datetime(2017, 3, 9, 2, tzinfo=utc)) ticket = Ticket(self.env, tktid) req = self._post_req('revert-status', ticket) self.assertTrue(self.tktmod.match_request(req)) self.assertRaises(RequestDone, self.tktmod.process_request, req) ticket = Ticket(self.env, tktid) self.assertEqual('assigned', ticket['status'])
def test_no_disown_from_changed_component(self): """ Verify that a ticket is not disowned when the component is changed to a non-assigned component. """ component1 = Component(self.env) component1.name = "test1" component1.owner = "joe" component1.insert() component2 = Component(self.env) component2.name = "test2" component2.owner = "" component2.insert() ticket = Ticket(self.env) ticket["reporter"] = "santa" ticket["summary"] = "Foo" ticket["component"] = "test1" ticket["status"] = "new" tktid = ticket.insert() ticket = Ticket(self.env, tktid) ticket["component"] = "test2" ticket.save_changes("jane", "Testing") self.assertEqual("joe", ticket["owner"])
def apply_preset(self, req, tickets, preset=None): if preset is None: return tickets presets = preset and [kw.split('=', 1) for kw in preset.split('&')] or [] fields = dict([(field, value) for field, value in presets]) warn = [] modified_tickets = [] if tickets and presets: db = self.env.get_db_cnx() ticket_module = TicketModule(self.env) action = fields.get('action') for ticket_id in tickets: if 'TICKET_CHGPROP' in req.perm('ticket', ticket_id): ticket = Ticket(self.env, ticket_id, db) ticket.populate(fields) if action: field_changes, problems = ticket_module.get_ticket_changes(req, ticket, action) if problems: for problem in problems: warn.append(problem) ticket_module._apply_ticket_changes(ticket, field_changes) # Apply changes made by the workflow ticket.save_changes(req.authname, None, db=db) modified_tickets.append(ticket_id) else: warn.append(_("You have no permission to modify ticket '%(ticket)s'", ticket=ticket_id)) db.commit() return { 'tickets' : modified_tickets, 'warnings': warn}
def test_owner_from_changed_component(self): """ Verify that the owner of a new ticket is updated when the component is changed. """ component1 = Component(self.env) component1.name = "test1" component1.owner = "joe" component1.insert() component2 = Component(self.env) component2.name = "test2" component2.owner = "kate" component2.insert() ticket = Ticket(self.env) ticket["reporter"] = "santa" ticket["summary"] = "Foo" ticket["component"] = "test1" ticket["status"] = "new" tktid = ticket.insert() ticket = Ticket(self.env, tktid) ticket["component"] = "test2" ticket.save_changes("jane", "Testing") self.assertEqual("kate", ticket["owner"])
def _change_ticket_states(self, id, history): ticket = Ticket(self.env, id) keys = history.keys() keys.sort() for key in keys: ticket['status'] = history[key] ticket.save_changes("me", "testing", datetime.combine(key, datetime.now(utc).timetz()))
def _test_render_time_field(self, format, req, value, expected): self.env.config.set('ticket-custom', 'timefield', 'time') self.env.config.set('ticket-custom', 'timefield.format', format) def timefield_text(): self.assertTrue(self.ticket_module.match_request(req)) template, data = self.ticket_module.process_request(req) content = Chrome(self.env).render_fragment(req, template, data) # select('//td[@headers="h_timefield"') replacement class TimefieldExtractor(HTMLTransform): pick_next_text = False value = '' def handle_starttag(self, tag, attrs): if tag == 'td': for name, value in attrs: if name == 'headers' and value == 'h_timefield': self.pick_next_text = True def handle_data(self, data): if self.pick_next_text: self.value += data def handle_endtag(self, tag): if self.pick_next_text: self.pick_next_text = False extractor = TimefieldExtractor(io.BytesIO()) extractor.feed(content.encode('utf-8')) return extractor.value.decode('utf-8').strip() self._insert_ticket(summary='Time fields') self.assertEqual('', timefield_text()) ticket = Ticket(self.env, 1) ticket['timefield'] = value ticket.save_changes('anonymous') self.assertEqual(expected, timefield_text())
def wake_up(self, *args): db = self.env.get_db_cnx() cursor = db.cursor() # find still opened more recent milestone # select ticket whom milestone are due in less than specified delay cursor.execute(""" SELECT m.name FROM milestone m WHERE m.completed is NULL or m.completed = 0 AND m.due not NULL and m.due > 0 ORDER BY m.due ASC LIMIT 1 """) next_milestone = None for name, in cursor: next_milestone = name # select ticket whom milestone are due in less than specified delay cursor.execute(""" SELECT t.id , t.milestone FROM ticket t, milestone m WHERE t.status != 'closed' AND t.milestone = m.name AND m.completed not NULL and m.completed > 0 """) if next_milestone: for id, milestone in cursor: mess = "ticket %s is opened in closed milestone %s. Should postpone this ticket to %s" % ( id, milestone, next_milestone) self.env.log.debug(mess) ticket = Ticket(self.env, id) ticket.populate({'milestone': next_milestone}) ticket.save_changes(self.getId(), mess) else: self.env.log.debug( "No opened milestone found. Cannot postpone tickets")
def _test_updater(disable): if disable: self.env.config.set('notification', 'always_notify_updater', 'false') ticket = Ticket(self.env) ticket['reporter'] = '*****@*****.**' ticket['summary'] = u'This is a súmmäry' ticket['cc'] = '*****@*****.**' ticket.insert() ticket['component'] = 'dummy' now = datetime.now(utc) ticket.save_changes('*****@*****.**', 'This is a change', when=now) tn = TicketNotifyEmail(self.env) tn.notify(ticket, newticket=False, modtime=now) message = notifysuite.smtpd.get_message() (headers, body) = parse_smtp_message(message) # checks for header existence self.failIf(not headers) # checks for updater in the 'To' recipient list self.failIf('To' not in headers) tolist = [addr.strip() for addr in headers['To'].split(',')] if disable: self.failIf('*****@*****.**' in tolist) else: self.failIf('*****@*****.**' not in tolist)
def test_set_status_to_previous(self): self.env.config.set('ticket', 'workflow', 'ConfigurableTicketWorkflow,TicketWorkflowOpStatusPrevious') self._config_set('ticket-workflow', [ ('revert-status', '* -> *'), ('revert-status.operations', 'set_status_to_previous'), ]) tktid = self._insert_ticket(when=datetime(2017, 3, 9, tzinfo=utc), summary='set status to previous', reporter='anonymous', owner='joe') ticket = Ticket(self.env, tktid) req = self._post_req('revert-status', ticket) self.assertTrue(self.tktmod.match_request(req)) self.assertRaises(RequestDone, self.tktmod.process_request, req) ticket = Ticket(self.env, tktid) self.assertEqual('new', ticket['status']) ticket = Ticket(self.env, tktid) ticket['status'] = 'assigned' ticket.save_changes(when=datetime(2017, 3, 9, 1, tzinfo=utc)) ticket['status'] = 'closed' ticket.save_changes(when=datetime(2017, 3, 9, 2, tzinfo=utc)) ticket = Ticket(self.env, tktid) req = self._post_req('revert-status', ticket) self.assertTrue(self.tktmod.match_request(req)) self.assertRaises(RequestDone, self.tktmod.process_request, req) ticket = Ticket(self.env, tktid) self.assertEqual('assigned', ticket['status'])
def _test_updater(disable): if disable: self.env.config.set('notification','always_notify_updater', 'false') ticket = Ticket(self.env) ticket['reporter'] = '*****@*****.**' ticket['summary'] = u'This is a súmmäry' ticket['cc'] = '*****@*****.**' ticket.insert() ticket['component'] = 'dummy' now = time.time() ticket.save_changes('*****@*****.**', 'This is a change', when=now) tn = TicketNotifyEmail(self.env) tn.notify(ticket, newticket=False, modtime=now) message = notifysuite.smtpd.get_message() (headers, body) = parse_smtp_message(message) # checks for header existence self.failIf(not headers) # checks for updater in the 'To' recipient list self.failIf('To' not in headers) tolist = [addr.strip() for addr in headers['To'].split(',')] if disable: self.failIf('*****@*****.**' in tolist) else: self.failIf('*****@*****.**' not in tolist)
def test_reset_milestone(self): self.env.config.set('ticket', 'workflow', 'ConfigurableTicketWorkflow,TicketWorkflowOpResetMilestone') self._config_set('ticket-workflow', [ ('reset-milestone', '* -> *'), ('reset-milestone.operations', 'reset_milestone'), ]) tktid = self._insert_ticket(when=datetime(2017, 3, 9, tzinfo=utc), summary='reset milestone', milestone='milestone1', reporter='anonymous', owner='joe') ticket = Ticket(self.env, tktid) req = self._post_req('reset-milestone', ticket) self.assertTrue(self.tktmod.match_request(req)) self.assertRaises(RequestDone, self.tktmod.process_request, req) ticket = Ticket(self.env, tktid) self.assertEqual('milestone1', ticket['milestone']) milestone = Milestone(self.env, ticket['milestone']) milestone.completed = datetime(2017, 3, 8, tzinfo=utc) milestone.update() req = self._post_req('reset-milestone', ticket) self.assertTrue(self.tktmod.match_request(req)) self.assertRaises(RequestDone, self.tktmod.process_request, req) ticket = Ticket(self.env, tktid) self.assertEqual('', ticket['milestone']) ticket['milestone'] = 'unknown-milestone' ticket.save_changes(when=datetime(2017, 3, 8, 1, tzinfo=utc)) req = self._post_req('reset-milestone', ticket) self.assertTrue(self.tktmod.match_request(req)) self.assertRaises(RequestDone, self.tktmod.process_request, req) ticket = Ticket(self.env, tktid) self.assertEqual('unknown-milestone', ticket['milestone'])
def ticket_changed(self, ticket, comment, author, old_values): """ ticket发生变化后,判断该ticket是否有父节点。 判断父节点下所有子几点是否结束。 """ #closed , accepted, new , parents db = self.env.get_db_cnx() cursor = db.cursor() if ticket.values["status"] == "closed" and "parents" in ticket.values and len(ticket.values["parents"]) > 0: #这里可以做检查。下面是检查的方法 #通过上面这一句sql就能搞定。 cursor.execute("SELECT COUNT(*) AS UNCLOSED FROM TICKET WHERE ID IN (SELECT CHILD FROM SUBTICKETS WHERE PARENT = %s) AND STATUS != 'closed'" % ticket.values["parents"]) row = cursor.fetchone() try: unclosed = int(row[0]) if unclosed == 0 : #do close the parent parentTicket = Ticket(self.env,ticket.values["parents"]) parentTicket._old["status"] = parentTicket.values["status"] parentTicket.values["status"] = "closed" parentTicket.values["resolution"] = "fixed" parentTicket.save_changes(author, comment="all children has been closed") self.log.debug("parent %s has been closed" % ticket.values["parents"]) else: self.log.debug("has %d unclosed children,so it did not close") self.log.debug("the parent %s has %d unclosed child" % (ticket["parents"], unclosed)) except Exception, err : self.log.exception("did not get the count")
def _save_changes(self, changes, author): """Save ticket changes.""" if self.audit in ('log', 'none'): with self.env.db_transaction as db: cursor = db.cursor() for id, (field, new_pos) in changes.items(): cursor.execute( """ SELECT value from ticket_custom WHERE name=%s AND ticket=%s """, (field, id)) result = cursor.fetchone() if result: old_pos = result[0] cursor.execute( """ UPDATE ticket_custom SET value=%s WHERE name=%s AND ticket=%s """, (new_pos, field, id)) else: old_pos = '(none)' cursor.execute( """ INSERT INTO ticket_custom (ticket,name,value) VALUES (%s,%s,%s) """, (id, field, new_pos)) if self.audit == 'log': self.log.info( "%s reordered ticket #%s's %s from %s to %s" % (author, id, field, old_pos, new_pos)) else: for id, (field, new_pos) in changes.items(): ticket = Ticket(self.env, id) ticket[field] = new_pos ticket.save_changes(author=author, comment='')
def test_changelog_with_attachment(self): """Verify ordering of attachments and comments in the changelog.""" tkt_id = self._insert_ticket("Test", reporter="joe", component="foo") ticket = Ticket(self.env, tkt_id) t1 = datetime(2001, 1, 1, 1, 1, 1, 0, utc) ticket.save_changes("jane", "Testing", t1) t2 = datetime(2001, 1, 1, 1, 1, 2, 0, utc) db = self.env.get_db_cnx() cursor = db.cursor() cursor.execute( "INSERT INTO attachment (type,id,filename,size,time," " description,author,ipnr) " "VALUES ('ticket',%s,'file.txt',1234,%s," " 'My file','mark','')", (str(tkt_id), to_utimestamp(t2)), ) db.commit() t3 = datetime(2001, 1, 1, 1, 1, 3, 0, utc) ticket.save_changes("jim", "Other", t3) log = ticket.get_changelog() self.assertEqual(4, len(log)) self.assertEqual((t1, "jane", "comment", "1", "Testing", True), log[0]) self.assertEqual( [(t2, "mark", "attachment", "", "file.txt", False), (t2, "mark", "comment", "", "My file", False)], sorted(log[1:3]), ) self.assertEqual((t3, "jim", "comment", "2", "Other", True), log[3])
def ticket_setup(tc): ticket = Ticket(tc.env) ticket['reporter'] = 'santa' ticket['summary'] = 'This is the summary' ticket.insert() ticket['status'] = 'new' ticket.save_changes('claus', 'set status', 0)
def test_set_tags(self): tags = ['tag3'] ticket = Ticket(self.env, 1) ticket['keywords'] = tags[0] # Tags get updated by TicketChangeListener method. ticket.save_changes(self.req.authname) self.assertEquals(self.tag_sys.get_all_tags(self.req).keys(), tags)
def _change_ticket(self, id, history): ticket = Ticket(self.env, id) keys = history.keys() keys.sort() for key in keys: ticket['hours_remaining'] = history[key] ticket.save_changes("me", "testing", time.mktime(key.timetuple()))
def test_closed_does_not_dup_to_None(self): # tests that dup_of can go from non-existing to None # (when a pre-existing ticket gets changed, and custom fields added) t1 = self._create_a_ticket() self.failIf(t1.values.has_key('dup_of')) # apparently setting status to new didn't get saved; assert it t1 = Ticket(self.env, 1) self.assertEquals(t1['status'], 'new') self.failIf(t1.values.has_key('dup_of')) # close the ticket t1['status'] = 'closed' t1['resolution'] = 'fixed' t1.save_changes('test', 'test', when=1) t1 = Ticket(self.env, 1) self.assertEquals(t1['status'], 'closed') self.failIf(t1.values.has_key('dup_of')) # t1 does not have dup_of set at all, set it to '' # as if the summary was changed through the web ui and try to save t1['dup_of'] = '' t1['summary'] = 'changed summary' t1.save_changes('test', 'test', when=2) t1 = Ticket(self.env, 1) self.failUnless(t1.values.has_key('dup_of')) # make sure the status did not get changed at all self.assertEquals(t1['status'], 'closed') self.assertEquals(t1['resolution'], 'fixed')
def wake_up(self, *args): db = self.env.get_db_cnx() cursor = db.cursor() # find still opened more recent milestone # select ticket whom milestone are due in less than specified delay cursor.execute(""" SELECT m.name FROM milestone m WHERE m.completed is NULL or m.completed = 0 AND m.due not NULL and m.due > 0 ORDER BY m.due ASC LIMIT 1 """ ) next_milestone = None for name, in cursor: next_milestone = name # select ticket whom milestone are due in less than specified delay cursor.execute(""" SELECT t.id , t.milestone FROM ticket t, milestone m WHERE t.status != 'closed' AND t.milestone = m.name AND m.completed not NULL and m.completed > 0 """ ) if next_milestone: for id, milestone in cursor: mess = "ticket %s is opened in closed milestone %s. Should postpone this ticket to %s" % (id, milestone, next_milestone) self.env.log.debug(mess) ticket = Ticket(self.env, id) ticket.populate({'milestone':next_milestone}) ticket.save_changes(self.getId(),mess) else: self.env.log.debug("No opened milestone found. Cannot postpone tickets")
def set_resource_tags(self, req, ticket_or_resource, tags, comment=u'', when=None): try: resource = ticket_or_resource.resource except AttributeError: resource = ticket_or_resource assert resource.realm == self.realm if not self._check_permission(req, resource, 'modify'): raise PermissionError(resource=resource, env=self.env) tag_set = set(tags) # Processing a call from TracTags, try to alter the ticket. tkt = Ticket(self.env, resource.id) all = self._ticket_tags(tkt) # Avoid unnecessary ticket changes, considering comments below. if tag_set != all: # Will only alter tags in 'keywords' ticket field. keywords = split_into_tags(tkt['keywords']) # Assume, that duplication is depreciated and consolitation # wanted to primarily affect 'keywords' ticket field. # Consequently updating ticket tags and reducing (tag) # 'ticket_fields' afterwards may result in undesired tag loss. tag_set.difference_update(all.difference(keywords)) tkt['keywords'] = u' '.join(sorted(map(to_unicode, tag_set))) tkt.save_changes(get_reporter_id(req), comment) else: # Processing a change listener event. tags = self._ticket_tags(ticket_or_resource) super(TicketTagProvider, self).set_resource_tags(req, resource, tags)
def test_owner_from_changed_component(self): """ Verify that the owner of a new ticket is updated when the component is changed. """ component1 = Component(self.env) component1.name = 'test1' component1.owner = 'joe' component1.insert() component2 = Component(self.env) component2.name = 'test2' component2.owner = 'kate' component2.insert() ticket = Ticket(self.env) ticket['reporter'] = 'santa' ticket['summary'] = 'Foo' ticket['component'] = 'test1' ticket['status'] = 'new' tktid = ticket.insert() ticket = Ticket(self.env, tktid) ticket['component'] = 'test2' ticket.save_changes('jane', 'Testing') self.assertEqual('kate', ticket['owner'])
def test_template_data_changes_for_time_field(self): self.env.config.set('ticket-custom', 'timefield', 'time') dt1 = datetime(2015, 7, 8, tzinfo=utc) dt2 = datetime(2015, 12, 11, tzinfo=utc) with self.env.db_transaction: self._insert_ticket(summary='Time fields', timefield=datetime_now(utc)) self.env.db_transaction("UPDATE ticket_custom SET value='invalid' " "WHERE ticket=1 AND name='timefield'") t = Ticket(self.env, 1) t['timefield'] = dt1 t.save_changes('anonymous') t = Ticket(self.env, 1) t['timefield'] = dt2 t.save_changes('anonymous') req = MockRequest(self.env, method='GET', path_info='/ticket/1') self.assertTrue(self.ticket_module.match_request(req)) data = self.ticket_module.process_request(req)[1] changes = data['changes'] dt1_text = user_time(req, format_datetime, dt1) dt2_text = user_time(req, format_datetime, dt2) self.assertEqual(2, len(changes)) self.assertEqual('', changes[0]['fields']['timefield']['old']) self.assertEqual(dt1_text, changes[0]['fields']['timefield']['new']) self.assertEqual(dt1_text, changes[1]['fields']['timefield']['old']) self.assertEqual(dt2_text, changes[1]['fields']['timefield']['new'])
def change_another_ticket(self, env, tkt_id, comment, author, ticket, trac, action='another'): """ Change ticket in another_trac """ self.log.info("Call change_another_ticket(%s)" %(tkt_id)) another_proj_name = env.config.get('project','name') if not re.match(".* \["+ another_proj_name +"\]", author): (db,cursor) = self._get_dbcursor(env) utc = UTC() when = datetime.now(utc) project_name = self.env.config.get('project','name') try: tkt = Ticket(env, tkt_id, db) except util.TracError, detail: return False if action == 'native': if 'closed' in ticket['status']: cursor.execute("SELECT oldvalue,author FROM ticket_change WHERE ticket='"+tkt_id+"' AND field = 'owner' ORDER by time DESC LIMIT 1") old_owner = cursor.fetchone()[0] # tkt['owner'] = old_owner tkt['owner'] = tkt['reporter'] if tkt['taskstatus']: tkt['taskstatus'] = trac['returnstatus'] elif action == 'another': if 'closed' in tkt['status'] and 'closed' not in ticket['status']: self.log.info("TICKET FIXED AND CLOSED! REOPEN IT!") tkt['status'] = 'reopened' tkt['resolution'] = '' author = author + " [" + project_name + "]" tkt.save_changes(author, comment, when) self.notify(env, tkt, False, when) return True
def process_commit(self, commit): """ Update ticket using message from commit """ try: original = commit.get_original_commit() except: original = None if not commit.is_clone() or \ original is None or \ commit.message != original.message: for action, ticket_id in commit.parse_message(): try: ticket = Ticket(self.env, ticket_id) self._update_ticket(ticket, action, commit) msg = "Commit %s:\n\n%s\n\nSource: [%s]" % (commit.id, commit.message, commit.url,) ticket.save_changes( commit.author, msg, when=datetime.fromtimestamp(commit.time, utc)) except Exception, e: self.log.error('Could not update ticket %s with commit %s: %s' % ( ticket_id,commit.id,str(e),))
def _save_changes(self, changes, author): """Save ticket changes.""" if self.audit in ('log','none'): db = self.env.get_db_cnx() cursor = db.cursor() for id,(field,new_pos) in changes.items(): cursor.execute(""" SELECT value from ticket_custom WHERE name=%s AND ticket=%s """, (field,id)) result = cursor.fetchone() if result: old_pos = result[0] cursor.execute(""" UPDATE ticket_custom SET value=%s WHERE name=%s AND ticket=%s """, (new_pos,field,id)) else: old_pos = '(none)' cursor.execute(""" INSERT INTO ticket_custom (ticket,name,value) VALUES (%s,%s,%s) """, (id,field,new_pos)) if self.audit == 'log': self.log.info("%s reordered ticket #%s's %s from %s to %s" \ % (author,id,field,old_pos,new_pos)) db.commit() else: for id,(field,new_pos) in changes.items(): ticket = Ticket(self.env, id) ticket[field] = new_pos ticket.save_changes(author=author, comment='')
def test_changelog_with_reverted_change(self): tkt_id = self._insert_ticket("Test", reporter="joe", component="foo") ticket = Ticket(self.env, tkt_id) ticket["component"] = "bar" ticket["component"] = "foo" now = datetime(2001, 1, 1, 1, 1, 1, 0, utc) ticket.save_changes("jane", "Testing", now) self.assertEqual([(now, "jane", "comment", "1", "Testing", True)], list(ticket.get_changelog()))
def test_prop_whitespace_change_is_not_saved(self): ticket = Ticket(self.env) ticket.populate({'summary': 'ticket summary'}) ticket.insert() ticket['summary'] = ' ticket summary ' ticket.save_changes() self.assertEqual(0, len(ticket.get_changelog()))
def test_ticket_comment_remove_ok(self): """Ticket comment is successfully deleted.""" ticket = Ticket(self.env) ticket.insert() ticket.save_changes('user1', 'the comment') rv, output = self.execute('ticket remove_comment 1 1') self.assertEqual(0, rv, output) self.assertExpectedResult(output)
def test_ticket_comment_remove_error_invalid_comment_id(self): """ResourceNotFound error reported when comment does not exist.""" ticket = Ticket(self.env) ticket.insert() ticket.save_changes('user1', 'the comment') rv, output = self.execute('ticket remove_comment 1 2') self.assertEqual(2, rv, output) self.assertExpectedResult(output)
def _relation_changed(relation, role): relations = relation.get_relations_id(ticket, relation, role) for target_ticket in relations: xticket = Ticket(self.env, target_ticket) if self.remove_relation(xticket, ticket.id, relation.name, self.opposite(role)): xticket.save_changes('', '(#%s %s) %s' % (ticket.id, ticket['summary'], 'Ticket deleted.'))
def handle_reply(self, req, realm, id, body, headers): """ Add a comment to a ticket """ if realm == 'ticket': ticket = Ticket(self.env, id) ticket.save_changes(headers['From'], body) return 1 return 0
def test_changelog_with_reverted_change(self): tkt_id = self._insert_ticket('Test', reporter='joe', component='foo') ticket = Ticket(self.env, tkt_id) ticket['component'] = 'bar' ticket['component'] = 'foo' now = datetime(2001, 1, 1, 1, 1, 1, 0, utc) ticket.save_changes('jane', 'Testing', now) self.assertEqual([(now, 'jane', 'comment', '1', 'Testing', True)], list(ticket.get_changelog()))
def set_resource_tags(self, req, resource, tags): req.perm.require('TICKET_MODIFY', resource) split_into_tags = TagSystem(self.env).split_into_tags ticket = Ticket(self.env, resource.id) all = self._ticket_tags(ticket) keywords = split_into_tags(ticket['keywords']) tags.difference_update(all.difference(keywords)) ticket['keywords'] = u' '.join(sorted(map(to_unicode, tags))) ticket.save_changes(req.username, u'')
def test_can_save_ticket_without_explicit_username(self): ticket = Ticket(self.env) ticket.insert() ticket['summary'] = 'another summary' ticket.save_changes() for change in ticket.get_changelog(): self.assertIsNone(change[1])
def test_can_save_ticket_without_explicit_username(self): ticket = Ticket(self.env) ticket.insert() ticket['summary'] = 'another summary' ticket.save_changes() for change in ticket.get_changelog(): self.assertEqual(None, change[1])
def _create_ticket_with_change(self, old_props, new_props): """Create a ticket with `old_props` and apply properties in `new_props`. """ t = Ticket(self.env) t.populate(old_props) t.insert() t.populate(new_props) t.save_changes('actor') return t
def _ticket_changed(self, ticket, author, comment, cnum, when, old_values, local_id): self.log.debug('TicketSubscribable: In _ticket_changed(%s,local=%s) for %s'%(ticket.id, local_id, self.env.path)) self.log.debug("TicketSubscribable: seen = %s"%ticket.tracforge_seen) my_ticket = Ticket(self.env, local_id) my_ticket.tracforge_seen = ticket.tracforge_seen for f in old_values: if not f.startswith('tracforge'): my_ticket[f] = ticket[f] my_ticket.save_changes(author, comment, when, cnum=cnum)
def process_message(self, req, msgstr): project_list = get_project_list(self.env, req, return_self=True, include_errors=False) msg = email.message_from_string(msgstr) msg_from = parseaddr(msg.get("from"))[1] msg_subject = msg.get("subject") in_reply_to = msg.get("in-reply-to", "") msg_content = "" if not msg.is_multipart(): msg_content = msg.get_payload(decode=True) else: for part in msg.walk(): if part.get_content_type() == 'text/plain': msg_content = part.get_payload(decode=True) msg_content = to_unicode(msg_content) match = INREPLYTO_TICKET_EXPR.match(in_reply_to) if match: for project, project_path, project_url, project_env in project_list: if not project_env: continue if os.path.basename(project_path).lower() != match.group( 'base').lower(): continue ticket = Ticket(project_env, int(match.group('id'))) now = datetime.now(utc) ticket.save_changes(msg_from, msg_content, when=now) #----- Copiado de web_ui.py ----- try: tn = TicketNotifyEmail(project_env) tn.notify(ticket, newticket=False, modtime=now) except Exception, e: self.log.error( "Failure sending notification on change to " "ticket #%s: %s", ticket.id, exception_to_unicode(e)) ## After saving the changes, apply the side-effects. #for controller in controllers: # self.env.log.debug('Side effect for %s' % # controller.__class__.__name__) #----- Fin Copiado de web_ui.py ----- return (True, "Ticket reply match - %s#%s" % (match.group('base'), match.group('id')))
def _save_ticket_changes(self, req, selected_tickets, new_values, comment, action): """Save changes to tickets.""" valid = True for manipulator in self.ticket_manipulators: if hasattr(manipulator, 'validate_comment'): for message in manipulator.validate_comment(req, comment): valid = False add_warning(req, tag_("The ticket %(field)s is invalid: " "%(message)s", field=tag.strong(_('comment')), message=message)) tickets = [] for id_ in selected_tickets: t = Ticket(self.env, id_) values = self._get_updated_ticket_values(req, t, new_values) for ctlr in self._get_action_controllers(req, t, action): values.update(ctlr.get_ticket_changes(req, t, action)) t.populate(values) for manipulator in self.ticket_manipulators: for field, message in manipulator.validate_ticket(req, t): valid = False if field: add_warning(req, tag_("The ticket field %(field)s is " "invalid: %(message)s", field=tag.strong(field), message=message)) else: add_warning(req, message) tickets.append(t) if not valid: return when = datetime_now(utc) with self.env.db_transaction: for t in tickets: t.save_changes(req.authname, comment, when=when) for ctlr in self._get_action_controllers(req, t, action): ctlr.apply_action_side_effects(req, t, action) event = BatchTicketChangeEvent(selected_tickets, when, req.authname, comment, new_values, action) try: NotificationSystem(self.env).notify(event) except Exception as e: self.log.error("Failure sending notification on ticket batch" "change: %s", exception_to_unicode(e)) add_warning(req, tag_("The changes have been saved, but an error " "occurred while sending notifications: " "%(message)s", message=to_unicode(e)))
def _update_relations(self, db=None, author=None): """Extra actions due to update""" # tickets need to be updated old_name = self._old_data['name'] new_name = self._data['name'] now = datetime.now(utc) comment = 'Product %s renamed to %s' % (old_name, new_name) if old_name != new_name: for t in Product.get_tickets(self._env, self._data['prefix']): ticket = Ticket(self._env, t['id'], db) ticket.save_changes(author, comment, now)
def test_can_save_ticket_without_explicit_comment(self): ticket = Ticket(self.env) ticket.insert() ticket['summary'] = 'another summary' ticket.save_changes('foo') changes = ticket.get_changelog() comment_change = [c for c in changes if c[2] == 'comment'][0] self.assertEqual('1', comment_change[3]) self.assertEqual('', comment_change[4])
def update_ticket_on_db(self, ticketId, author, comment, req): db = self.env.get_db_cnx() ticket = Ticket(self.env, ticketId, db=db) ticket.populate(req.args) now = int(time.time()) ticket.save_changes(author, comment, when=now, db=db) db.commit() return True
def _create_ticket_with_change(self, old_props, new_props, author='anonymous'): """Create a ticket with `old_props` and apply properties in `new_props`. """ t = Ticket(self.env) t.populate(old_props) t.insert() comment = new_props.pop('comment', None) t.populate(new_props) t.save_changes(author, comment=comment) return t
def _update_relations(self, db=None, author=None): """Extra actions due to update""" # tickets need to be updated old_name = self._old_data['name'] new_name = self._data['name'] now = datetime.now(utc) comment = 'Product %s renamed to %s' % (old_name, new_name) if old_name != new_name: for t in Product.get_tickets(self._env, old_name): ticket = Ticket(self._env, t['id'], db) ticket['product'] = new_name ticket.save_changes(author, comment, now)
def test_subsecond_change(self): """Perform two ticket changes within a second.""" tkt_id = self._insert_ticket('Test', reporter='joe', component='foo') ticket = Ticket(self.env, tkt_id) t1 = datetime(2001, 1, 1, 1, 1, 1, 123456, utc) ticket.save_changes('jane', 'Testing', t1) t2 = datetime(2001, 1, 1, 1, 1, 1, 123789, utc) ticket.save_changes('jim', 'Other', t2) log = ticket.get_changelog() self.assertEqual(2, len(log)) self.assertEqual((t1, 'jane', 'comment', '1', 'Testing', True), log[0]) self.assertEqual((t2, 'jim', 'comment', '2', 'Other', True), log[1])
def test_changelog_with_reverted_change(self): tkt_id = self._insert_ticket('Test', reporter='joe', component='foo') ticket = Ticket(self.env, tkt_id) ticket['component'] = 'bar' ticket['component'] = 'foo' ticket.save_changes('jane', 'Testing', when=42) for t, author, field, old, new in ticket.get_changelog(): self.assertEqual((42, 'jane'), (t, author)) if field == 'comment': self.assertEqual(('', 'Testing'), (old, new)) else: self.fail('Unexpected change (%s)' % ((t, author, field, old, new), ))
def test_changelog(self): tkt_id = self._insert_ticket('Test', reporter='joe', component='foo', milestone='bar') ticket = Ticket(self.env, tkt_id) ticket['component'] = 'bar' ticket['milestone'] = 'foo' now = datetime(2001, 1, 1, 1, 1, 1, 0, utc) ticket.save_changes('jane', 'Testing', now) changelog = sorted(ticket.get_changelog()) self.assertEqual([(now, 'jane', 'comment', '1', 'Testing', True), (now, 'jane', 'component', 'foo', 'bar', True), (now, 'jane', 'milestone', 'bar', 'foo', True)], changelog)
def _ticket_changed(self, ticket, author, comment, cnum, when, old_values, local_id): self.log.debug( 'TicketSubscribable: In _ticket_changed(%s,local=%s) for %s' % (ticket.id, local_id, self.env.path)) self.log.debug("TicketSubscribable: seen = %s" % ticket.tracforge_seen) my_ticket = Ticket(self.env, local_id) my_ticket.tracforge_seen = ticket.tracforge_seen for f in old_values: if not f.startswith('tracforge'): my_ticket[f] = ticket[f] my_ticket.save_changes(author, comment, when, cnum=cnum)