Ejemplo n.º 1
0
    def _delete_change(self, req, id, ts, field):
        """Delete the change to a field on the specified ticket at the
          specified timestamp."""
        ticket = Ticket(self.env, id)
        db = self.env.get_db_cnx()
        cursor = db.cursor()
        dt = to_datetime(int(ts))
        changelog = ticket.get_changelog(dt)
        if changelog:
            if field == 'change':
                # Iterate over all the fields that have changed 
                for change in changelog:
                    self._delete_change(req, id, ts, change[2])
            elif field == 'attachment':
                # Delete the attachment
                cursor.execute("""
                    DELETE FROM attachment WHERE type = 'ticket'
                    AND id = %s AND time = %s""", (id, ts))
            else:
                # Revert the field to its old value if it's the newest change to that field
                exists_newer = [True for change in ticket.get_changelog()
                                if to_timestamp(change[0]) > int(ts) and field == change[2]]
                if field != 'comment' and not exists_newer:
                    oldval = [change[3] for change in changelog if change[2] == field]
                    if oldval:
                        custom_fields = [f['name'] for f in ticket.fields if f.get('custom')]
                        if field in custom_fields:
                            cursor.execute("""
                                UPDATE ticket_custom SET value=%s
                                WHERE ticket=%s AND name=%s""", (oldval[0], id, field))
                        else:
                            cursor.execute("""
                                UPDATE ticket SET %s=%%s
                                WHERE id=%%s""" % field, (oldval[0], id))
                # Delete the ticket change
                cursor.execute("""
                    DELETE FROM ticket_change
                    WHERE ticket=%s AND time=%s AND field=%s
                    """, (id, ts, field))
        else:
            raise TracError("""
                      Ticket change with timestamp %s (datetime: %s) not found
                      in ticket #%s changelog.
                      """ % (ts, dt, id))

        db.commit()
        msg = "Change to field \"%s\" of ticket #%s at %s has been deleted." \
              % (field, id, dt)
        add_notice(req, msg)
        self.log.debug("TicketDelete: " + msg)
Ejemplo n.º 2
0
 def get_changelog( self , ticketid):
   t = Ticket(self.macroenv.tracenv, ticketid)
   try: 
     return( t.get_changelog() )
   except:
     self.macroenv.tracenv.log.warning("get_changelog failed on ticket %s", ticketid)
     return [] # no changelogs
Ejemplo n.º 3
0
 def get_changelog( self , ticketid):
   t = Ticket(self.macroenv.tracenv, ticketid)
   try: 
     return( t.get_changelog() )
   except:
     self.macroenv.tracenv.log.warn("get_changelog failed on ticket %s", ticketid)
     return [] # no changelogs
Ejemplo n.º 4
0
 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])
Ejemplo n.º 5
0
Archivo: model.py Proyecto: t2y/trac
    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()))
Ejemplo n.º 6
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()))
Ejemplo n.º 7
0
    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()))
Ejemplo n.º 8
0
Archivo: model.py Proyecto: t2y/trac
    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])
Ejemplo n.º 9
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()))
Ejemplo n.º 10
0
Archivo: model.py Proyecto: t2y/trac
 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()))
Ejemplo n.º 11
0
 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])
Ejemplo n.º 12
0
Archivo: model.py Proyecto: t2y/trac
    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])
Ejemplo n.º 13
0
    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])
Ejemplo n.º 14
0
 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])
Ejemplo n.º 15
0
    def testComplexNotification(self):
        env = Environment(ENV)

        ticket1 = Ticket(env)
        ticket1['summary'] = 'Fix please.'
        ticket1['status'] = 'new'
        ticket1_id = ticket1.insert()
        ticket2 = Ticket(env)
        ticket2['summary'] = 'This one too, thanks.'
        ticket2['status'] = 'new'
        ticket2_id = ticket2.insert()

        ticket1 = Ticket(env, ticket1_id)
        self.assertEqual(ticket1['status'], 'new')
        self.assertEqual(ticket1['resolution'], '')
        ticket2 = Ticket(env, ticket2_id)
        self.assertEqual(ticket2['status'], 'new')
        self.assertEqual(ticket2['resolution'], '')

        message1 = "Fix #%d: you're welcome." % ticket1_id
        self.makeGitCommit(ALTGIT, 'newfile', 'with some new content',
                           message1)
        message2 = "See #%d: you bet." % ticket2_id
        self.makeGitCommit(ALTGIT, 'newfile', 'with improved content',
                           message2)
        self.openGitHubHook(2, 'alt')

        ticket1 = Ticket(env, ticket1_id)
        self.assertEqual(ticket1['status'], 'closed')
        self.assertEqual(ticket1['resolution'], 'fixed')
        changelog1 = ticket1.get_changelog()
        self.assertEqual(len(changelog1), 4)
        self.assertEqual(changelog1[0][2], 'comment')
        self.assertIn("you're welcome", changelog1[0][4])
        ticket2 = Ticket(env, ticket2_id)
        self.assertEqual(ticket2['status'], 'new')
        self.assertEqual(ticket2['resolution'], '')
        changelog2 = ticket2.get_changelog()
        self.assertEqual(len(changelog2), 1)
        self.assertEqual(changelog2[0][2], 'comment')
        self.assertIn("you bet", changelog2[0][4])
Ejemplo n.º 16
0
 def test_process_commit(self):
     commits = []
     time = self.now
     for data in COMMITS:
         c = GitHubCommit(self.env, git_url=GIT_URL, **data)
         c.time = time
         c.save()
         commits.append(c)
         time = time + 60
     
     # parse commit for the first time (with a clone)
     self.ticker_updater.process_commit(commits[0])
     tkt1 = Ticket(self.env, 1)
     change_log = tkt1.get_changelog()
     eq_(1, len(change_log))
     eq_('Damien Lebrun <*****@*****.**>', change_log[0][1])
     eq_(
         'Commit %(id)s:\n\n%(message)s\n\nSource: [%(url)s]' % COMMITS[0],
         change_log[0][4])
     
     # parse same commit (still clone),
     # should not update the ticket
     self.ticker_updater.process_commit(commits[1])
     tkt1 = Ticket(self.env, 1)
     change_log = tkt1.get_changelog()
     eq_(1, len(change_log))
     
     # parse the commit from the main git repository
     # Should update the repository
     self.ticker_updater.process_commit(commits[2])
     tkt1 = Ticket(self.env, 1)
     change_log = tkt1.get_changelog()
     eq_(3, len(change_log))
     eq_('Damien Lebrun <*****@*****.**>', change_log[1][1])
     eq_(
         'Commit %(id)s:\n\n%(message)s\n\nSource: [%(url)s]' % COMMITS[2],
         change_log[1][4])
     eq_('Damien Lebrun <*****@*****.**>', change_log[2][1])
     eq_('resolution',change_log[2][2])
     eq_('fixed',change_log[2][4])
         
Ejemplo n.º 17
0
Archivo: model.py Proyecto: t2y/trac
 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])
Ejemplo n.º 18
0
 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])
Ejemplo n.º 19
0
 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])
Ejemplo n.º 20
0
 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)
Ejemplo n.º 21
0
 def _delete_change(self, id, ts, field=None):
     """Delete the change on the given ticket at the given timestamp."""
     db = self.env.get_db_cnx()
     cursor = db.cursor()
     ticket = Ticket(self.env,id)
     if field:
         if field == 'attachment':
             pass # Better handling still pending
         else:
             custom_fields = [f['name'] for f in ticket.fields if f.get('custom')]
             if field != "comment" and not [1 for time, author, field2, oldval, newval, _ in ticket.get_changelog() if time > ts and field == field2]:
                 oldval = [old for _, _, field2, old, _, _ in ticket.get_changelog(ts) if field2 == field][0]
                 if field in custom_fields:
                     cursor.execute("UPDATE ticket_custom SET value=%s WHERE ticket=%s AND name=%s", (oldval, id, field))
                 else:
                     cursor.execute("UPDATE ticket SET %s=%%s WHERE id=%%s" % field, (oldval, id))
             cursor.execute("DELETE FROM ticket_change WHERE ticket = %s AND time = %s AND field = %s", (id, ts, field))
     else:
         for _, _, field, _, _, _ in ticket.get_changelog(ts):
             self._delete_change(id, ts, field)
         
     db.commit()
Ejemplo n.º 22
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'
     ticket.save_changes('jane', 'Testing', when=42)
     for t, author, field, old, new, permanent in ticket.get_changelog():
         self.assertEqual((42, 'jane', True), (t, author, permanent))
         if field == 'comment':
             self.assertEqual(('', 'Testing'), (old, new))
         else:
             self.fail('Unexpected change (%s)'
                       % ((t, author, field, old, new),))
Ejemplo n.º 23
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'
     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), ))
Ejemplo n.º 24
0
    def testComplexNotification(self):
        env = Environment(ENV)

        ticket1 = Ticket(env)
        ticket1['summary'] = 'Fix please.'
        ticket1['status'] = 'new'
        ticket1_id = ticket1.insert()
        ticket2 = Ticket(env)
        ticket2['summary'] = 'This one too, thanks.'
        ticket2['status'] = 'new'
        ticket2_id = ticket2.insert()

        ticket1 = Ticket(env, ticket1_id)
        self.assertEqual(ticket1['status'], 'new')
        self.assertEqual(ticket1['resolution'], '')
        ticket2 = Ticket(env, ticket2_id)
        self.assertEqual(ticket2['status'], 'new')
        self.assertEqual(ticket2['resolution'], '')

        message1 = "Fix #%d: you're welcome." % ticket1_id
        self.makeGitCommit(ALTGIT, 'newfile', 'with some new content', message1)
        message2 = "See #%d: you bet." % ticket2_id
        self.makeGitCommit(ALTGIT, 'newfile', 'with improved content', message2)
        self.openGitHubHook(2, 'alt')

        ticket1 = Ticket(env, ticket1_id)
        self.assertEqual(ticket1['status'], 'closed')
        self.assertEqual(ticket1['resolution'], 'fixed')
        changelog1 = ticket1.get_changelog()
        self.assertEqual(len(changelog1), 4)
        self.assertEqual(changelog1[0][2], 'comment')
        self.assertIn("you're welcome", changelog1[0][4])
        ticket2 = Ticket(env, ticket2_id)
        self.assertEqual(ticket2['status'], 'new')
        self.assertEqual(ticket2['resolution'], '')
        changelog2 = ticket2.get_changelog()
        self.assertEqual(len(changelog2), 1)
        self.assertEqual(changelog2[0][2], 'comment')
        self.assertIn("you bet", changelog2[0][4])
Ejemplo n.º 25
0
Archivo: model.py Proyecto: t2y/trac
 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)
Ejemplo n.º 26
0
    def _delete_change(self, id, ts, field=None):
        """Delete the change on the given ticket at the given timestamp."""
        db = self.env.get_db_cnx()
        cursor = db.cursor()
        ticket = Ticket(self.env, id)
        if field:
            if field == 'attachment':
                pass  # Better handling still pending
            else:
                custom_fields = [
                    f['name'] for f in ticket.fields if f.get('custom')
                ]
                if field != "comment" and not [
                        1 for time, author, field2, oldval, newval, _ in
                        ticket.get_changelog() if time > ts and field == field2
                ]:
                    oldval = [
                        old
                        for _, _, field2, old, _, _ in ticket.get_changelog(ts)
                        if field2 == field
                    ][0]
                    if field in custom_fields:
                        cursor.execute(
                            "UPDATE ticket_custom SET value=%s WHERE ticket=%s AND name=%s",
                            (oldval, id, field))
                    else:
                        cursor.execute(
                            "UPDATE ticket SET %s=%%s WHERE id=%%s" % field,
                            (oldval, id))
                cursor.execute(
                    "DELETE FROM ticket_change WHERE ticket = %s AND time = %s AND field = %s",
                    (id, ts, field))
        else:
            for _, _, field, _, _, _ in ticket.get_changelog(ts):
                self._delete_change(id, ts, field)

        db.commit()
Ejemplo n.º 27
0
 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,
     )
Ejemplo n.º 28
0
    def test_action_with_state_change(self):
        """Actions can have change status."""
        self.env.config.set('ticket-workflow', 'embiggen', '* -> big')

        first_ticket_id = self._insert_ticket('Test 1', reporter='joe',
                                              status='small')
        second_ticket_id = self._insert_ticket('Test 2', reporter='joe')
        selected_tickets = [first_ticket_id, second_ticket_id]

        batch = BatchModifyModule(self.env)
        batch._save_ticket_changes(self.req, selected_tickets, {}, '',
                                   'embiggen')

        ticket = Ticket(self.env, int(first_ticket_id))
        changes = ticket.get_changelog()
        self.assertFieldChanged(first_ticket_id, 'status', 'big')
        self.assertFieldChanged(second_ticket_id, 'status', 'big')
Ejemplo n.º 29
0
 def _populate_action_comments(self):
     t = Ticket(self.env, self.testrun)
     history = t.get_changelog()
     pat = re.compile(r"(\b(ta_id)=([0-9]+))")
     for change in history:
         # we get a list of change attributes [...,...,"user","comment",...]
         # (datetime.datetime(2012, 6, 25, 7, 19, 7, 742580, tzinfo=<FixedOffset "UTC" 0:00:00>),
         #  u'testadmin',
         #  u'comment',
         #  u'2',
         #  u'\npassed with comment "Check menu and toolbar" in
         #  [http://localhorst:8000/trac/TestManager/general/testcase/23 TestCase #23]
         #  for [wiki:Testcases/UC012?revision=None]\n\ntoo slow\n', 1)
         match = pat.search(change[4])
         # if the ta_id is found, we have an association
         if match and int(match.group(3)) == self.id:
             self._comments.append({"user": change[1], "text": change[4]})
Ejemplo n.º 30
0
    def test_action_with_state_change(self):
        """Actions can have change status."""
        self.env.config.set('ticket-workflow', 'embiggen', '* -> big')

        first_ticket_id = self._insert_ticket('Test 1', reporter='joe',
                                              status='small')
        second_ticket_id = self._insert_ticket('Test 2', reporter='joe')
        selected_tickets = [first_ticket_id, second_ticket_id]

        batch = BatchModifyModule(self.env)
        batch._save_ticket_changes(self.req, selected_tickets, {}, '',
                                   'embiggen')

        ticket = Ticket(self.env, int(first_ticket_id))
        changes = ticket.get_changelog()
        self.assertFieldChanged(first_ticket_id, 'status', 'big')
        self.assertFieldChanged(second_ticket_id, 'status', 'big')
Ejemplo n.º 31
0
 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)
     for t, author, field, old, new, permanent in ticket.get_changelog():
         self.assertEqual((now, 'jane', True), (t, author, permanent))
         if field == 'component':
             self.assertEqual(('foo', 'bar'), (old, new))
         elif field == 'milestone':
             self.assertEqual(('bar', 'foo'), (old, new))
         elif field == 'comment':
             self.assertEqual(('', 'Testing'), (old, new))
         else:
             self.fail('Unexpected change (%s)'
                       % ((t, author, field, old, new),))
Ejemplo n.º 32
0
 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)
     self.env.db_transaction("""
         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)))
     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])
Ejemplo n.º 33
0
    def test_action_with_side_effects(self):
        """Actions can have operations with side effects."""
        self.env.config.set('ticket-workflow', 'buckify', '* -> *')
        self.env.config.set('ticket-workflow', 'buckify.operations',
                                               'set_owner')
        self.req.args = {}
        self.req.args['action_buckify_reassign_owner'] = 'buck'

        first_ticket_id = self._insert_ticket('Test 1', reporter='joe',
                                              owner='foo')
        second_ticket_id = self._insert_ticket('Test 2', reporter='joe')
        selected_tickets = [first_ticket_id, second_ticket_id]

        batch = BatchModifyModule(self.env)
        batch._save_ticket_changes(self.req, selected_tickets, {}, '',
                                   'buckify')

        ticket = Ticket(self.env, int(first_ticket_id))
        changes = ticket.get_changelog()
        self.assertFieldChanged(first_ticket_id, 'owner', 'buck')
        self.assertFieldChanged(second_ticket_id, 'owner', 'buck')
Ejemplo n.º 34
0
    def testNotification(self):
        ticket = Ticket(self.env)
        ticket['summary'] = 'I need a commit!'
        ticket['status'] = 'new'
        ticket_id = ticket.insert()

        ticket = Ticket(self.env, ticket_id)
        self.assertEqual(ticket['status'], 'new')
        self.assertEqual(ticket['resolution'], '')

        message = "Fix #%d: here you go." % ticket_id
        self.makeGitCommit(GIT, 'newfile', 'with some new content', message)
        self.openGitHubHook()

        ticket = Ticket(self.env, ticket_id)
        self.assertEqual(ticket['status'], 'closed')
        self.assertEqual(ticket['resolution'], 'fixed')
        changelog = ticket.get_changelog()
        self.assertEqual(len(changelog), 4)
        self.assertEqual(changelog[0][2], 'comment')
        self.assertIn("here you go", changelog[0][4])
Ejemplo n.º 35
0
    def test_action_with_side_effects(self):
        """Actions can have operations with side effects."""
        self.env.config.set('ticket-workflow', 'buckify', '* -> *')
        self.env.config.set('ticket-workflow', 'buckify.operations',
                                               'set_owner')
        self.req.args = {}
        self.req.args['action_buckify_reassign_owner'] = 'buck'

        first_ticket_id = self._insert_ticket('Test 1', reporter='joe',
                                              owner='foo')
        second_ticket_id = self._insert_ticket('Test 2', reporter='joe')
        selected_tickets = [first_ticket_id, second_ticket_id]

        batch = BatchModifyModule(self.env)
        batch._save_ticket_changes(self.req, selected_tickets, {}, '',
                                   'buckify')

        ticket = Ticket(self.env, int(first_ticket_id))
        changes = ticket.get_changelog()
        self.assertFieldChanged(first_ticket_id, 'owner', 'buck')
        self.assertFieldChanged(second_ticket_id, 'owner', 'buck')
Ejemplo n.º 36
0
Archivo: model.py Proyecto: t2y/trac
 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)
     self.env.db_transaction("""
         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)))
     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])
Ejemplo n.º 37
0
    def testNotification(self):
        ticket = Ticket(self.env)
        ticket['summary'] = 'I need a commit!'
        ticket['status'] = 'new'
        ticket_id = ticket.insert()

        ticket = Ticket(self.env, ticket_id)
        self.assertEqual(ticket['status'], 'new')
        self.assertEqual(ticket['resolution'], '')

        message = "Fix #%d: here you go." % ticket_id
        self.makeGitCommit(GIT, 'newfile', 'with some new content', message)
        self.openGitHubHook()

        ticket = Ticket(self.env, ticket_id)
        self.assertEqual(ticket['status'], 'closed')
        self.assertEqual(ticket['resolution'], 'fixed')
        changelog = ticket.get_changelog()
        self.assertEqual(len(changelog), 4)
        self.assertEqual(changelog[0][2], 'comment')
        self.assertIn("here you go", changelog[0][4])
Ejemplo n.º 38
0
    def background_cron(self):
        self.env.log.info('TracTaskCare _cron()')

        t = Timer(self.cron_period, self.background_cron)
        t.start()

        headers = {
            'Content-Type': 'application/json',
            self.auth_x_httpheader_key: self.auth_x_httpheader_value,
            self.auth_httpheader_key: self.auth_httpheader_value,
        }
        url = self.resource_getalltickets
        res = requests.get(url, headers=headers)
        payload = res.json()['payload']
        for taskcare_ticket in payload:
            if taskcare_ticket['status'] == 'Solved':
                continue
            if taskcare_ticket[
                    self.filter_column_key] != self.filter_column_value:
                continue

            # taskTitle = 'TKT-xxxxx'
            with self.env.db_query as db:
                sql = 'SELECT ticket FROM ticket_custom WHERE name = %s AND value = %s;'
                rows = db(sql,
                          (self.taskcare_column, taskcare_ticket['taskTitle']))

                if 0 == len(rows):
                    # Create a new ticket and sync
                    ticket = Ticket(self.env)
                    ticket['description'] = taskcare_ticket['Description']
                    ticket['summary'] = taskcare_ticket['subject']
                    ticket[self.taskcare_column] = taskcare_ticket['taskTitle']
                    ticket.insert()
                else:
                    ticket = Ticket(self.env, tkt_id=int(rows[0]))

                trac_comments = ticket.get_changelog()
                taskcare_comments = taskcare_ticket['taskComments']
Ejemplo n.º 39
0
    def test_create_ticket(self):
        # Multiple test in one method, this sucks
        # 1. Creating ticket
        ticket = Ticket(self.env)
        ticket['reporter'] = 'santa'
        ticket['summary'] = 'Foo'
        ticket['foo'] = 'This is a custom field'
        self.assertEqual('santa', ticket['reporter'])
        self.assertEqual('Foo', ticket['summary'])
        self.assertEqual('This is a custom field', ticket['foo'])
        ticket.insert()

        # Retrieving ticket
        ticket2 = Ticket(self.env, 1)
        self.assertEqual(1, ticket2.id)
        self.assertEqual('santa', ticket2['reporter'])
        self.assertEqual('Foo', ticket2['summary'])
        self.assertEqual('This is a custom field', ticket2['foo'])

        # Modifying ticket
        ticket2['summary'] = 'Bar'
        ticket2['foo'] = 'New value'
        ticket2.save_changes('santa', 'this is my comment')

        # Retrieving ticket
        ticket3 = Ticket(self.env, 1)
        self.assertEqual(1, ticket3.id)
        self.assertEqual(ticket3['reporter'], 'santa')
        self.assertEqual(ticket3['summary'], 'Bar')
        self.assertEqual(ticket3['foo'], 'New value')

        # Testing get_changelog()
        log = ticket3.get_changelog()
        self.assertEqual(len(log), 3)
        ok_vals = ['foo', 'summary', 'comment']
        self.failUnless(log[0][2] in ok_vals)
        self.failUnless(log[1][2] in ok_vals)
        self.failUnless(log[2][2] in ok_vals)
Ejemplo n.º 40
0
 def assertCommentAdded(self, ticket_id, comment):
     ticket = Ticket(self.env, int(ticket_id))
     changes = ticket.get_changelog()
     comment_change = [c for c in changes if c[2] == 'comment'][0]
     self.assertEqual(comment_change[2], comment)
Ejemplo n.º 41
0
    def _draw_ticket(self, req, params):
        # Draw image and generate data for image map for ticket view
        start, end, days = self._get_dates(params)
        members = self._settings.members
        resources = self._settings.resources
        cursor = self.db.cursor()
        
        # ids are required for mapping members to their colours
        midx = {}
        for i, m in enumerate(members):
            midx[m] = i

        # group tickets according to the owner
        mem_tickets, owned_tickets = {}, 0
        for mem in members:
            statement = '''select id from ticket where owner = "%s" and not 
                (status = "closed" and changetime <= %s) and not time > %s'''\
                % (mem, self._to_time(start), self._to_time(end))
            cursor.execute(statement)
            mem_tickets[mem] = [t[0] for t in cursor]
            owned_tickets += len(mem_tickets[mem])

        if owned_tickets == 0:
            params['msg'] = 'There are no tickets to visualise in the selected time period'
            return

        # ticket size is relative to number of tickets and "screen size"
        ticket_width = self._bounded(_TICKET_MIN, _SCREEN_SPACE / owned_tickets, _TICKET_MAX)

        date_offset, bar_gap, name_offset = 80, 20, 30
        # determine width of graph
        page_width = date_offset + (owned_tickets * ticket_width) + (len(members) * bar_gap)
        # determine height of graph
        page_height = name_offset + (days * _SQUARE_SIZE)

        img = Image.new("RGBA", (page_width, page_height), (255, 255, 255, 255))
        draw = ImageDraw.Draw(img)

        draw = self._write_dates((0, page_height), start, days, draw)
        
        # draw individual tickets
        map = []
        memx = date_offset
        colh = days * _SQUARE_SIZE
        for i, mem in enumerate(members):
            x, y = memx, page_height
            colw = len(mem_tickets[mem]) * ticket_width
            draw.rectangle([x, y, x + colw - 1, y - colh + 1], fill=(229, 229, 229, 255))
            for j, tid in enumerate(mem_tickets[mem]):
                ticket = Ticket(self.env, tid)
                tcreated = ticket.time_created.date()

                starty = page_height - self._date_y(start, tcreated)
                x = memx + (j * ticket_width)

                # determine the colour index for the reported circle
                reporter = ticket['reporter']
                if reporter not in midx:
                    continue #reporter not configured in Narcissus settings, so don't show ticket
                cidx = midx[reporter]

                dots = [(starty, cidx)]

                # create the ticket lines: last change starts as ticket open,
                # line starts as thin, colour starts as black
                draw_from = draw_to = tcreated
                width = change_width = ticket_width / 4
                status = ticket['status']
                for dtime, _, field, _, newvalue, _ in ticket.get_changelog():
                    dtime = dtime.date()
                    if dtime <= end:
                        dot = None
                        ttype = field
                        if ttype == 'status':
                            ttype = newvalue
                        if ttype == 'assigned':
                            draw_to = dtime
                            change_width = ticket_width / 2
                            status = 'assigned'
                        elif ttype == 'resolution':
                            draw_to = dtime
                            dot = midx[ticket['reporter']] + 1
                            status = 'closed'
                        elif ttype == 'reopened':
                            draw_to = dtime
                            change_width = ticket_width / 4
                            dot = midx[ticket['reporter']] + 1
                            status = 'new'
                        if draw_to > draw_from:
                            draw_days = (draw_to - draw_from).days
                            y = page_height - self._date_y(start, draw_from) - (_SQUARE_SIZE / 2)
                            draw.line([x + (ticket_width / 2), y,
                                x + (ticket_width / 2), y - draw_days * _SQUARE_SIZE],
                                fill=(128, 128, 128, 255), width=width)
                        if dot:
                            y = page_height - self._date_y(start, draw_to)
                            dots.append((y, dot - 1))
                        draw_from = draw_to
                        width = change_width
                if status != 'closed' or draw_to > end:
                    draw_days = (end - draw_from).days
                    y = page_height - self._date_y(start, draw_from) - (_SQUARE_SIZE / 2)
                    draw.line([x + (ticket_width / 2), y, x + (ticket_width / 2),
                        y - (draw_days * _SQUARE_SIZE + (_SQUARE_SIZE / 2))], 
                        fill=(128, 128, 128, 255), width=width)
                for dot in dots:
                    y, i = dot[0] - (_SQUARE_SIZE / 2), dot[1]
                    draw.ellipse([x, y - ticket_width, x + ticket_width, y],
                        fill=(_RED[i%len(_RED)], _GREEN[i%len(_GREEN)], _BLUE[i%len(_BLUE)], 255))
    
                # default length if there haven't been any changes to the ticket yet
                last_change = end
                if ticket['status'] == 'closed':
                    for dtime, _, _, _, _, _ in ticket.get_changelog():
                        dtime = dtime.date()
                        if dtime <= end:
                            last_change = dtime
                ticket_length = (last_change - tcreated).days + 1

                # add info for the template to render an image map
                idx = 'ticket_%s' % (tid)
                href = '%s/details?tid=%s' % (req.base_url, tid)
                item = {}
                item['href'] = href
                item['x1'] = x
                item['y1'] = starty - (ticket_length * _SQUARE_SIZE)
                item['x2'] = x + ticket_width
                item['y2'] = starty
                map.append(item)

            # print member name
            x, y = memx + 10, name_offset * 0.4
            draw.text((x, y), mem, fill=(0, 0, 0, 255), font=self._ttf)
            
            # increment the horizontal point for the next member
            memx += colw + bar_gap

        params['mapItems'] = map
        params['vis'] = self._cache_image(req, params, img, 'vis')
Ejemplo n.º 42
0
    def _update_data(self, req):
        # Update narcissus_data table with info to be visualised
        db = self.env.get_db_cnx()
        cursor = db.cursor()

        cursor.execute('select max(dtime) from narcissus_data')
        start_rev = 1
        last_update = cursor.fetchone()[0]
        if not last_update:
            # no data yet, update data from the beginning
            cursor.execute('select min(time) from wiki')
            last_update = cursor.fetchone()[0]
        else:
            # update data from this change
            cursor.execute('select eid from narcissus_data where resource = "svn"')
            for row in cursor:
                if int(row[0]) > start_rev:
                    start_rev = int(row[0])
            start_rev += 1
        last_update = datetime.date.fromtimestamp(last_update)
        members = self._settings.members
        
        # populate table with wiki activity
        cursor.execute('''select name, min(version), count(version), min(time) from wiki
            where time > %f group by name order by min(time)''' % self._to_time(last_update))
        for page, start_version, versions, _ in cursor:
            versions += start_version
            # page has been added
            if start_version == 1:
                new_page = WikiPage(self.env, page, 1)
                add = len(new_page.text.splitlines())
                if (new_page.author in members) and (new_page.time.date() > last_update):
                    self._insert_data(new_page.author, new_page.time, 
                        new_page.name, 'wiki', 'add', add)
                start_version += 1
            for i in xrange(start_version, versions):
                # page has been edited
                old_page, edit_page = WikiPage(self.env, page, i - 1), WikiPage(self.env, page, i)
                if (edit_page.author in members) and (edit_page.time.date() > last_update):
                    changes = self._my_diff(old_page.text, edit_page.text)
                    edit = self._edit_newlines(changes)
                    if edit:
                        self._insert_data(edit_page.author, edit_page.time, 
                            edit_page.name, 'wiki', 'edit', edit)

        # populate table with ticket activity
        credits = self._settings.credits
        cursor.execute('select id from ticket')
        for row in cursor:
            ticket = Ticket(self.env, row[0])
            # ticket has been opened
            if ticket['reporter'] in members and ticket.time_created.date() > last_update:
                self._insert_data(ticket['reporter'], ticket.time_created, 
                    ticket.id, 'ticket', 'open', 1) # FIXME
            for dtime, author, field, _, newvalue, _ in ticket.get_changelog():
                if author in members and dtime.date() > last_update:
                    if field == 'comment':
                        # ticket has received comment
                        self._insert_data(author, dtime, ticket.id, 
                            'ticket', 'comment', credits['comment'])
                    elif newvalue == 'assigned':
                        # ticket has been accepted
                        self._insert_data(author, dtime, ticket.id, 
                            'ticket', 'accept', credits['accept'])
                    elif field == 'resolution':
                        # ticket has been closed, reopened closures only count as a change
                        reopened = False
                        for inner_time, _, _, _, _, _ in ticket.get_changelog():
                            if inner_time > dtime and field == 'resolution':
                                reopened = True
                        if reopened:
                            self._insert_data(author, dtime, ticket.id, 
                                'ticket', 'update', credits['update'])
                        else:
                            if ticket['owner'] in members:
                                self._insert_data(ticket['owner'], dtime, 
                                    ticket.id, 'ticket', 'close', credits['close'])
                            if author != ticket['owner']:
                                self._insert_data(author, dtime, ticket.id, 
                                    'ticket', 'proxy close', credits['update'])
                    else:
                        # ticket has been changed
                        self._insert_data(author, dtime, ticket.id, 
                            'ticket', 'update', 1) # FIXME

        # populate table with svn activity
        repos = self.env.get_repository()
        youngest_rev = str(repos.youngest_rev or 0).split(':')[0]

        try:
            youngest_rev = int(youngest_rev) + 1
        except:
            youngest_rev = 0

        for rev in xrange(start_rev, int(youngest_rev) + 1):
            cs = repos.get_changeset(rev)
            add, edit = 0, 0
            for path, _, change, base_path, base_rev in cs.get_changes():
                if change == 'add':
                    add += self._svn_add_newlines(repos, path, rev)
                elif change == 'edit':
                    diff_args = {'old_path': base_path,
                                 'old_rev': base_rev, 
                                 'new_path': path or '/', 
                                 'new_rev': rev
                                }
                    changes = self._my_svn_diff(repos, diff_args)
                    if changes:
                        edit += self._edit_newlines(changes)

            valid_user = cs.author in members
            if not valid_user:
                for u, n, e in self.env.get_known_users():
                    if e != None and e in cs.author:
                        valid_user = True

            if add and valid_user:
                self._insert_data(cs.author, cs.date, rev, 'svn', 'add', add)
            if edit and valid_user:
                self._insert_data(cs.author, cs.date, rev, 'svn', 'edit', edit)
        db.commit()
Ejemplo n.º 43
0
    def _draw_ticket(self, req, params):
        # Draw image and generate data for image map for ticket view
        start, end, days = self._get_dates(params)
        members = self._settings.members
        resources = self._settings.resources
        cursor = self.db.cursor()

        # ids are required for mapping members to their colours
        midx = {}
        for i, m in enumerate(members):
            midx[m] = i

        # group tickets according to the owner
        mem_tickets, owned_tickets = {}, 0
        for mem in members:
            statement = '''select id from ticket where owner = "%s" and not 
                (status = "closed" and changetime <= %s) and not time > %s'''\
                % (mem, start, end)
            cursor.execute(statement)
            mem_tickets[mem] = [t[0] for t in cursor]
            owned_tickets += len(mem_tickets[mem])

        if owned_tickets == 0:
            params[
                'msg'] = 'There are no tickets to visualise in the selected time period'
            return

        # ticket size is relative to number of tickets and "screen size"
        ticket_width = self._bounded(_TICKET_MIN,
                                     _SCREEN_SPACE / owned_tickets,
                                     _TICKET_MAX)

        date_offset, bar_gap, name_offset = 80, 20, 30
        # determine width of graph
        page_width = date_offset + (owned_tickets *
                                    ticket_width) + (len(members) * bar_gap)
        # determine height of graph
        page_height = name_offset + (days * _SQUARE_SIZE)

        img = Image.new("RGBA", (page_width, page_height),
                        (255, 255, 255, 255))
        draw = ImageDraw.Draw(img)

        draw = self._write_dates((0, page_height), start, days, draw)

        # draw individual tickets
        map = []
        memx = date_offset
        colh = days * _SQUARE_SIZE
        for i, mem in enumerate(members):
            x, y = memx, page_height
            colw = len(mem_tickets[mem]) * ticket_width
            draw.rectangle([x, y, x + colw - 1, y - colh + 1],
                           fill=(229, 229, 229, 255))
            for j, tid in enumerate(mem_tickets[mem]):
                ticket = Ticket(self.env, tid)
                tcreated = self._to_microseconds(ticket.time_created.date())

                starty = page_height - self._date_y(start, tcreated)
                x = memx + (j * ticket_width)

                # determine the colour index for the reported circle
                reporter = ticket['reporter']
                if reporter not in midx:
                    continue  #reporter not configured in Narcissus settings, so don't show ticket
                cidx = midx[reporter]

                dots = [(starty, cidx)]

                # create the ticket lines: last change starts as ticket open,
                # line starts as thin, colour starts as black
                draw_from = draw_to = tcreated
                width = change_width = ticket_width / 4
                status = ticket['status']
                for dtime, _, field, _, newvalue, _ in ticket.get_changelog():
                    dtime = self._to_microseconds(dtime)
                    if dtime <= end:
                        dot = None
                        ttype = field
                        if ttype == 'status':
                            ttype = newvalue
                        if ttype == 'assigned':
                            draw_to = dtime
                            change_width = ticket_width / 2
                            status = 'assigned'
                        elif ttype == 'resolution':
                            draw_to = dtime
                            dot = midx[ticket['reporter']] + 1
                            status = 'closed'
                        elif ttype == 'reopened':
                            draw_to = dtime
                            change_width = ticket_width / 4
                            dot = midx[ticket['reporter']] + 1
                            status = 'new'
                        if draw_to > draw_from:
                            draw_days = self._date_days(draw_to - draw_from)
                            y = page_height - self._date_y(
                                start, draw_from) - (_SQUARE_SIZE / 2)
                            draw.line([
                                x + (ticket_width / 2), y, x +
                                (ticket_width / 2),
                                y - draw_days * _SQUARE_SIZE
                            ],
                                      fill=(128, 128, 128, 255),
                                      width=width)
                        if dot:
                            y = page_height - self._date_y(start, draw_to)
                            dots.append((y, dot - 1))
                        draw_from = draw_to
                        width = change_width
                if status != 'closed' or draw_to > end:
                    draw_days = self._date_days(end - draw_from)
                    y = page_height - self._date_y(
                        start, draw_from) - (_SQUARE_SIZE / 2)
                    draw.line([
                        x + (ticket_width / 2), y, x + (ticket_width / 2), y -
                        (draw_days * _SQUARE_SIZE + (_SQUARE_SIZE / 2))
                    ],
                              fill=(128, 128, 128, 255),
                              width=width)
                for dot in dots:
                    y, i = dot[0] - (_SQUARE_SIZE / 2), dot[1]
                    draw.ellipse([x, y - ticket_width, x + ticket_width, y],
                                 fill=(_RED[i % len(_RED)],
                                       _GREEN[i % len(_GREEN)],
                                       _BLUE[i % len(_BLUE)], 255))

                # default length if there haven't been any changes to the ticket yet
                last_change = end
                if ticket['status'] == 'closed':
                    for dtime, _, _, _, _, _ in ticket.get_changelog():
                        dtime = self._to_microseconds(dtime)
                        if dtime <= end:
                            last_change = dtime
                ticket_length = self._date_days(last_change - tcreated) + 1

                # add info for the template to render an image map
                idx = 'ticket_%s' % (tid)
                href = '%s/details?tid=%s' % (req.base_url, tid)
                item = {}
                item['href'] = href
                item['x1'] = x
                item['y1'] = starty - (ticket_length * _SQUARE_SIZE)
                item['x2'] = x + ticket_width
                item['y2'] = starty
                map.append(item)

            # print member name
            x, y = memx + 10, name_offset * 0.4
            draw.text((x, y), mem, fill=(0, 0, 0, 255), font=self._ttf)

            # increment the horizontal point for the next member
            memx += colw + bar_gap

        params['mapItems'] = map
        params['vis'] = self._cache_image(req, params, img, 'vis')
Ejemplo n.º 44
0
    def _update_data(self, req):
        # Update narcissus_data table with info to be visualised
        db = self.env.get_db_cnx()
        cursor = db.cursor()

        cursor.execute('select max(dtime) from narcissus_data')
        start_rev = 1
        last_update = cursor.fetchone()[0]
        if not last_update:
            # no data yet, update data from the beginning
            cursor.execute('select min(time) from wiki')
            last_update = cursor.fetchone()[0]
        else:
            # update data from this change
            cursor.execute(
                'select eid from narcissus_data where resource = "svn"')
            for row in cursor:
                if int(row[0]) > start_rev:
                    start_rev = int(row[0])
            start_rev += 1
        members = self._settings.members

        # populate table with wiki activity
        cursor.execute(
            '''select name, min(version), count(version), min(time) from wiki
            where time > %f group by name order by min(time)''' % last_update)
        for page, start_version, versions, _ in cursor:
            versions += start_version
            # page has been added
            if start_version == 1:
                new_page = WikiPage(self.env, page, 1)
                add = len(new_page.text.splitlines())
                if (new_page.author in members) and (self._to_microseconds(
                        new_page.time) > last_update):
                    self._insert_data(new_page.author, new_page.time,
                                      new_page.name, 'wiki', 'add', add)
                start_version += 1
            for i in xrange(start_version, versions):
                # page has been edited
                old_page, edit_page = WikiPage(self.env, page,
                                               i - 1), WikiPage(
                                                   self.env, page, i)
                if (edit_page.author in members) and (self._to_microseconds(
                        edit_page.time) > last_update):
                    changes = self._my_diff(old_page.text, edit_page.text)
                    edit = self._edit_newlines(changes)
                    if edit:
                        self._insert_data(edit_page.author, edit_page.time,
                                          edit_page.name, 'wiki', 'edit', edit)

        # populate table with ticket activity
        credits = self._settings.credits
        cursor.execute('select id from ticket')
        for row in cursor:
            ticket = Ticket(self.env, row[0])
            # ticket has been opened
            if ticket['reporter'] in members and self._to_microseconds(
                    ticket.time_created) > last_update:
                self._insert_data(ticket['reporter'], ticket.time_created,
                                  ticket.id, 'ticket', 'open', 1)  # FIXME
            for dtime, author, field, _, newvalue, _ in ticket.get_changelog():
                if author in members and self._to_microseconds(
                        dtime) > last_update:
                    if field == 'comment':
                        # ticket has received comment
                        self._insert_data(author, dtime, ticket.id, 'ticket',
                                          'comment', credits['comment'])
                    elif newvalue == 'assigned':
                        # ticket has been accepted
                        self._insert_data(author, dtime, ticket.id, 'ticket',
                                          'accept', credits['accept'])
                    elif field == 'resolution':
                        # ticket has been closed, reopened closures only count as a change
                        reopened = False
                        for inner_time, _, _, _, _, _ in ticket.get_changelog(
                        ):
                            if inner_time > dtime and field == 'resolution':
                                reopened = True
                        if reopened:
                            self._insert_data(author, dtime, ticket.id,
                                              'ticket', 'update',
                                              credits['update'])
                        else:
                            if ticket['owner'] in members:
                                self._insert_data(ticket['owner'], dtime,
                                                  ticket.id, 'ticket', 'close',
                                                  credits['close'])
                            if author != ticket['owner']:
                                self._insert_data(author, dtime, ticket.id,
                                                  'ticket', 'proxy close',
                                                  credits['update'])
                    else:
                        # ticket has been changed
                        self._insert_data(author, dtime, ticket.id, 'ticket',
                                          'update', 1)  # FIXME

        # populate table with svn activity
        repos = self.env.get_repository()
        youngest_rev = str(repos.youngest_rev or 0).split(':')[0]

        try:
            youngest_rev = int(youngest_rev) + 1
        except:
            youngest_rev = 0

        for rev in xrange(start_rev, youngest_rev):
            cs = repos.get_changeset(rev)
            add, edit = 0, 0
            for path, _, change, base_path, base_rev in cs.get_changes():
                if change == 'add':
                    add += self._svn_add_newlines(repos, path, rev)
                elif change == 'edit':
                    diff_args = {
                        'old_path': base_path,
                        'old_rev': base_rev,
                        'new_path': path or '/',
                        'new_rev': rev
                    }
                    changes = self._my_svn_diff(repos, diff_args)
                    if changes:
                        edit += self._edit_newlines(changes)

            valid_user = cs.author in members
            if not valid_user:
                for u, n, e in self.env.get_known_users():
                    if e != None and e in cs.author:
                        valid_user = True

            if add and valid_user:
                self._insert_data(cs.author, cs.date, rev, 'svn', 'add', add)
            if edit and valid_user:
                self._insert_data(cs.author, cs.date, rev, 'svn', 'edit', edit)
        db.commit()
Ejemplo n.º 45
0
 def assertFieldChanged(self, ticket_id, field, new_value):
     ticket = Ticket(self.env, int(ticket_id))
     changes = ticket.get_changelog()
     field_change = [c for c in changes if c[2] == field][0]
     self.assertEqual(field_change[4], new_value)
Ejemplo n.º 46
0
 def get_changelog(self):
     t = Ticket(self.env, id)
     return (t.get_changelog())
Ejemplo n.º 47
0
 def get_changelog( self ):
   t = Ticket(self.env, id)
   return( t.get_changelog() )
Ejemplo n.º 48
0
def get_ticket_notification_recipients(env,
                                       config,
                                       tktid,
                                       prev_cc=None,
                                       modtime=None):
    """Returns notifications recipients.

    :since 1.0.2: the `config` parameter is no longer used.
    :since 1.0.2: the `prev_cc` parameter is deprecated.
    :since 1.1.3: deprecated and will be removed in 1.3.1.
    """
    section = env.config['notification']
    always_notify_reporter = section.getbool('always_notify_reporter')
    always_notify_owner = section.getbool('always_notify_owner')
    always_notify_updater = section.getbool('always_notify_updater')

    cc_recipients = set(prev_cc or [])
    to_recipients = set()
    tkt = Ticket(env, tktid)

    # CC field is stored as comma-separated string. Parse to list.
    to_list = lambda cc: cc.replace(',', ' ').split()

    # Backward compatibility
    if not modtime:
        modtime = tkt['changetime']

    # Harvest email addresses from the author field of ticket_change(s)
    if always_notify_updater:
        for author, ticket in env.db_query(
                """
                SELECT DISTINCT author, ticket FROM ticket_change
                WHERE ticket=%s
                """, (tktid, )):
            to_recipients.add(author)

    # Harvest previous owner and cc list
    author = None
    for changelog in tkt.get_changelog(modtime):
        author, field, old = changelog[1:4]
        if field == 'owner' and always_notify_owner:
            to_recipients.add(old)
        elif field == 'cc':
            cc_recipients.update(to_list(old))

    # Harvest email addresses from the cc, reporter, and owner fields
    updater = author or tkt['reporter']
    if tkt['cc']:
        cc_recipients.update(to_list(tkt['cc']))
    if always_notify_reporter:
        to_recipients.add(tkt['reporter'])
    if always_notify_owner:
        to_recipients.add(tkt['owner'])
    if always_notify_updater and updater:
        to_recipients.add(updater)

    # Suppress the updater from the recipients if necessary
    if not always_notify_updater:
        filter_out = True
        if always_notify_reporter and updater == tkt['reporter']:
            filter_out = False
        if always_notify_owner and updater == tkt['owner']:
            filter_out = False
        if filter_out:
            to_recipients.discard(updater)

    return list(to_recipients), list(cc_recipients), \
           tkt['reporter'], tkt['owner']
Ejemplo n.º 49
0
Archivo: model.py Proyecto: t2y/trac
    def test_comment_with_whitespace_only_is_not_saved(self):
        ticket = Ticket(self.env)
        ticket.insert()

        ticket.save_changes(comment='\n \n ')
        self.assertEqual(0, len(ticket.get_changelog()))
Ejemplo n.º 50
0
    def test_comment_with_whitespace_only_is_not_saved(self):
        ticket = Ticket(self.env)
        ticket.insert()

        ticket.save_changes(comment='\n \n ')
        self.assertEqual(0, len(ticket.get_changelog()))
Ejemplo n.º 51
0
    def get_list(self, realm, wl, req, fields=None):
        db = self.env.get_db_cnx()
        cursor = db.cursor()
        context = Context.from_request(req)
        locale = getattr(req, 'locale', LC_TIME)

        ticketlist = []
        extradict = {}
        if not fields:
            fields = set(self.default_fields['ticket'])
        else:
            fields = set(fields)

        if 'changetime' in fields:
            max_changetime = datetime(1970, 1, 1, tzinfo=utc)
            min_changetime = datetime.now(utc)
        if 'time' in fields:
            max_time = datetime(1970, 1, 1, tzinfo=utc)
            min_time = datetime.now(utc)

        for sid, last_visit in wl.get_watched_resources(
                'ticket', req.authname):
            ticketdict = {}
            try:
                ticket = Ticket(self.env, sid, db)
                exists = ticket.exists
            except:
                exists = False

            if not exists:
                ticketdict['deleted'] = True
                if 'id' in fields:
                    ticketdict['id'] = sid
                    ticketdict['ID'] = '#' + sid
                if 'author' in fields:
                    ticketdict['author'] = '?'
                if 'changetime' in fields:
                    ticketdict['changedsincelastvisit'] = 1
                    ticketdict['changetime'] = '?'
                    ticketdict['ichangetime'] = 0
                if 'time' in fields:
                    ticketdict['time'] = '?'
                    ticketdict['itime'] = 0
                if 'comment' in fields:
                    ticketdict['comment'] = tag.strong(t_("deleted"),
                                                       class_='deleted')
                if 'notify' in fields:
                    ticketdict['notify'] = wl.is_notify(req, 'ticket', sid)
                if 'description' in fields:
                    ticketdict['description'] = ''
                if 'owner' in fields:
                    ticketdict['owner'] = ''
                if 'reporter' in fields:
                    ticketdict['reporter'] = ''
                ticketlist.append(ticketdict)
                continue

            render_elt = lambda x: x
            if not (Chrome(self.env).show_email_addresses or \
                    'EMAIL_VIEW' in req.perm(ticket.resource)):
                render_elt = obfuscate_email_address

            # Copy all requested fields from ticket
            if fields:
                for f in fields:
                    ticketdict[f] = ticket.values.get(f, u'')
            else:
                ticketdict = ticket.values.copy()

            changetime = ticket.time_changed
            if wl.options['attachment_changes']:
                for attachment in Attachment.select(self.env, 'ticket', sid,
                                                    db):
                    if attachment.date > changetime:
                        changetime = attachment.date
            if 'attachment' in fields:
                attachments = []
                for attachment in Attachment.select(self.env, 'ticket', sid,
                                                    db):
                    wikitext = u'[attachment:"' + u':'.join([
                        attachment.filename, 'ticket', sid
                    ]) + u'" ' + attachment.filename + u']'
                    attachments.extend([
                        tag(', '),
                        format_to_oneliner(self.env,
                                           context,
                                           wikitext,
                                           shorten=False)
                    ])
                if attachments:
                    attachments.reverse()
                    attachments.pop()
                ticketdict['attachment'] = moreless(attachments, 5)

            # Changes are special. Comment, commentnum and last author are included in them.
            if 'changes' in fields or 'author' in fields or 'comment' in fields or 'commentnum' in fields:
                changes = []
                # If there are now changes the reporter is the last author
                author = ticket.values['reporter']
                commentnum = u"0"
                comment = u""
                want_changes = 'changes' in fields
                for date, cauthor, field, oldvalue, newvalue, permanent in ticket.get_changelog(
                        changetime, db):
                    author = cauthor
                    if field == 'comment':
                        if 'commentnum' in fields:
                            ticketdict['commentnum'] = to_unicode(oldvalue)
                        if 'comment' in fields:
                            comment = to_unicode(newvalue)
                            comment = moreless(comment, 200)
                            ticketdict['comment'] = comment
                        if not want_changes:
                            break
                    else:
                        if want_changes:
                            label = self.fields['ticket'].get(field, u'')
                            if label:
                                changes.extend([
                                    tag(
                                        tag.strong(label), ' ',
                                        render_property_diff(
                                            self.env, req, ticket, field,
                                            oldvalue, newvalue)),
                                    tag('; ')
                                ])
                if want_changes:
                    # Remove the last tag('; '):
                    if changes:
                        changes.pop()
                    changes = moreless(changes, 5)
                    ticketdict['changes'] = tag(changes)

            if 'id' in fields:
                ticketdict['id'] = sid
                ticketdict['ID'] = format_to_oneliner(self.env,
                                                      context,
                                                      '#' + sid,
                                                      shorten=True)
            if 'cc' in fields:
                if render_elt == obfuscate_email_address:
                    ticketdict['cc'] = ', '.join(
                        [render_elt(c) for c in ticketdict['cc'].split(', ')])
            if 'author' in fields:
                ticketdict['author'] = render_elt(author)
            if 'changetime' in fields:
                ichangetime = to_timestamp(changetime)
                ticketdict.update(
                    changetime=format_datetime(changetime,
                                               locale=locale,
                                               tzinfo=req.tz),
                    ichangetime=ichangetime,
                    changedsincelastvisit=(last_visit < ichangetime and 1
                                           or 0),
                    changetime_delta=pretty_timedelta(changetime),
                    changetime_link=req.href.timeline(
                        precision='seconds',
                        from_=trac_format_datetime(changetime,
                                                   'iso8601',
                                                   tzinfo=req.tz)))
                if changetime > max_changetime:
                    max_changetime = changetime
                if changetime < min_changetime:
                    min_changetime = changetime
            if 'time' in fields:
                time = ticket.time_created
                ticketdict.update(time=format_datetime(time,
                                                       locale=locale,
                                                       tzinfo=req.tz),
                                  itime=to_timestamp(time),
                                  time_delta=pretty_timedelta(time),
                                  time_link=req.href.timeline(
                                      precision='seconds',
                                      from_=trac_format_datetime(
                                          time, 'iso8601', tzinfo=req.tz)))
                if time > max_time:
                    max_time = time
                if time < min_time:
                    min_time = time
            if 'description' in fields:
                description = ticket.values['description']
                description = moreless(description, 200)
                ticketdict['description'] = description
            if 'notify' in fields:
                ticketdict['notify'] = wl.is_notify(req, 'ticket', sid)
            if 'owner' in fields:
                ticketdict['owner'] = render_elt(ticket.values['owner'])
            if 'reporter' in fields:
                ticketdict['reporter'] = render_elt(ticket.values['reporter'])
            if 'tags' in fields and self.tagsystem:
                tags = []
                for t in self.tagsystem.get_tags(req, Resource('ticket', sid)):
                    tags.extend(
                        [tag.a(t, href=req.href('tags', q=t)),
                         tag(', ')])
                if tags:
                    tags.pop()
                ticketdict['tags'] = moreless(tags, 10)

            ticketlist.append(ticketdict)

        if 'changetime' in fields:
            extradict['max_changetime'] = format_datetime(max_changetime,
                                                          locale=locale,
                                                          tzinfo=req.tz)
            extradict['min_changetime'] = format_datetime(min_changetime,
                                                          locale=locale,
                                                          tzinfo=req.tz)
        if 'time' in fields:
            extradict['max_time'] = format_datetime(max_time,
                                                    locale=locale,
                                                    tzinfo=req.tz)
            extradict['min_time'] = format_datetime(min_time,
                                                    locale=locale,
                                                    tzinfo=req.tz)

        return ticketlist, extradict
Ejemplo n.º 52
0
 def assertFieldChanged(self, ticket_id, field, new_value):
     ticket = Ticket(self.env, int(ticket_id))
     changes = ticket.get_changelog()
     field_change = [c for c in changes if c[2] == field][0]
     self.assertEqual(field_change[4], new_value)
Ejemplo n.º 53
0
 if ':' in source_obj:
     ticket_num, source_obj = source_obj.split(':', 1)
     if not Ticket.id_is_valid(ticket_num):
         return system_message("%s is not a valid ticket id" %
                               ticket_num)
     try:
         ticket = Ticket(self.env, ticket_num)
         if 'TICKET_VIEW' not in formatter.perm(ticket.resource):
             return ''
     except ResourceNotFound:
         return system_message("Ticket %s does not exist" %
                               ticket_num)
     if ':' in source_obj:
         source_format, comment_num = source_obj.split(':', 1)
         if source_format == 'comment':
             changelog = ticket.get_changelog()
             out = []
             if changelog:
                 for (ts, author, field, oldval, newval,
                      permanent) in changelog:
                     if field == 'comment' and \
                             oldval == comment_num:
                         dest_format = 'text/x-trac-wiki'
                         ctxt = Context.from_request(
                             formatter.req, 'ticket', ticket_num)
                         out = newval
                         break
             if not out:
                 return system_message(
                     "Comment %s does not exist for Ticket %s" %
                     (comment_num, ticket_num))
Ejemplo n.º 54
0
def get_ticket_notification_recipients(env, config, tktid, prev_cc=None,
                                       modtime=None):
    """Returns notifications recipients.

    :since 1.0.2: the `config` parameter is no longer used.
    :since 1.0.2: the `prev_cc` parameter is deprecated.
    :since 1.1.3: deprecated and will be removed in 1.3.1.
    """
    section = env.config['notification']
    always_notify_reporter = section.getbool('always_notify_reporter')
    always_notify_owner = section.getbool('always_notify_owner')
    always_notify_updater = section.getbool('always_notify_updater')

    cc_recipients = set(prev_cc or [])
    to_recipients = set()
    tkt = Ticket(env, tktid)

    # CC field is stored as comma-separated string. Parse to list.
    to_list = lambda cc: cc.replace(',', ' ').split()

    # Backward compatibility
    if not modtime:
        modtime = tkt['changetime']

    # Harvest email addresses from the author field of ticket_change(s)
    if always_notify_updater:
        for author, ticket in env.db_query("""
                SELECT DISTINCT author, ticket FROM ticket_change
                WHERE ticket=%s
                """, (tktid, )):
            to_recipients.add(author)

    # Harvest previous owner and cc list
    author = None
    for changelog in tkt.get_changelog(modtime):
        author, field, old = changelog[1:4]
        if field == 'owner' and always_notify_owner:
            to_recipients.add(old)
        elif field == 'cc':
            cc_recipients.update(to_list(old))

    # Harvest email addresses from the cc, reporter, and owner fields
    updater = author or tkt['reporter']
    if tkt['cc']:
        cc_recipients.update(to_list(tkt['cc']))
    if always_notify_reporter:
        to_recipients.add(tkt['reporter'])
    if always_notify_owner:
        to_recipients.add(tkt['owner'])
    if always_notify_updater and updater:
        to_recipients.add(updater)

    # Suppress the updater from the recipients if necessary
    if not always_notify_updater:
        filter_out = True
        if always_notify_reporter and updater == tkt['reporter']:
            filter_out = False
        if always_notify_owner and updater == tkt['owner']:
            filter_out = False
        if filter_out:
            to_recipients.discard(updater)

    return list(to_recipients), list(cc_recipients), \
           tkt['reporter'], tkt['owner']
Ejemplo n.º 55
0
     out, ctxt, dest_format = self._get_source(formatter, source_obj, dest_format)
 elif source_format == "ticket":
     if ":" in source_obj:
         ticket_num, source_obj = source_obj.split(":", 1)
         if not Ticket.id_is_valid(ticket_num):
             return system_message("%s is not a valid ticket id" % ticket_num)
         try:
             ticket = Ticket(self.env, ticket_num)
             if not "TICKET_VIEW" in formatter.perm(ticket.resource):
                 return ""
         except ResourceNotFound, e:
             return system_message("Ticket %s does not exist" % ticket_num)
         if ":" in source_obj:
             source_format, comment_num = source_obj.split(":", 1)
             if source_format == "comment":
                 changelog = ticket.get_changelog()
                 out = []
                 if changelog:
                     for (ts, author, field, oldval, newval, permanent) in changelog:
                         if field == "comment" and oldval == comment_num:
                             dest_format = "text/x-trac-wiki"
                             ctxt = Context.from_request(formatter.req, "ticket", ticket_num)
                             out = newval
                             break
                 if not out:
                     return system_message("Comment %s does not exist for Ticket %s" % (comment_num, ticket_num))
             else:
                 system_message("Unsupported ticket field %s" % source_format)
     else:
         return system_message("Ticket field must be specified")
 else:
Ejemplo n.º 56
0
 def assertCommentAdded(self, ticket_id, comment):
     ticket = Ticket(self.env, int(ticket_id))
     changes = ticket.get_changelog()
     comment_change = [c for c in changes if c[2] == 'comment'][0]
     self.assertEqual(comment_change[2], comment)