Changeset 3506

Show
Ignore:
Timestamp:
04/12/08 18:04:02 (5 months ago)
Author:
tcoulter
Message:

1) Changed look/feel of tracbacks, where instead of just linking, it shows an excerpt of the comment that was made.
2) Allowed for multiple references of a ticket within a comment, where each reference produces another excerpt within the tracback.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • tracbacksplugin/0.11/tracbacks/tracbacks.py

    r3498 r3506  
    3838    implements(ITicketChangeListener) 
    3939 
     40    TRACBACK_MAGIC_NUMBER = "{{{\n#!html\n<div class=\"tracback\"></div>\n}}}\n" 
     41    TRACBACK_PREFACE = "This ticket has been referenced in ticket #" 
     42     
     43    TICKET_REGEX = r""" 
     44        (?=                    # Don't return '#' character: 
     45           (?<=^\#)            # Look for a TracLink Ticket at the beginning of the string 
     46          |(?<=[\s,.;:!]\#)    # or on a whitespace boundary or some punctuation 
     47        ) 
     48        (\d+)                  # Any length ticket number (return the digits) 
     49        (?= 
     50           (?=\b)              # Don't return word boundary at the end 
     51          |$                   # Don't return end of string 
     52        ) 
     53        """ 
     54 
     55    EXCERPT_CHARACTERS = 80 
     56    WEED_BUFFER = 2 
     57 
    4058    # ITicketChangeListener methods 
    4159 
     
    4866 
    4967    def ticket_changed(self, ticket, comment, author, old_values): 
    50         pattern = re.compile(r""" 
    51         (?=                    # Don't return '#' character: 
    52            (?<=^\#)            # Look for a TracLink Ticket at the beginning of the string 
    53           |(?<=[\s,.;:!]\#)    # or on a whitespace boundary or some punctuation 
    54         ) 
    55         (\d+)                  # Any length ticket number (return the digits) 
    56         (?= 
    57            (?=\b)              # Don't return word boundary at the end 
    58           |$                   # Don't return end of string 
    59         ) 
    60         """, re.VERBOSE) 
     68         
     69        pattern = re.compile(self.TICKET_REGEX, re.VERBOSE) 
     70         
    6171        tickets_referenced = pattern.findall(comment) 
    6272        # convert from strings to ints and discard duplicates 
     
    6676 
    6777        # put trackbacks on the tickets that we found 
    68         trackback_preface = "Trackback: #" 
    69         if trackback_preface not in comment: # prevent infinite recursion 
    70             for ticket_to_trackback in tickets_referenced: 
     78        if not self.is_tracback(comment): # prevent infinite recursion 
     79            for ticket_to_tracback in tickets_referenced: 
    7180                try: 
    72                     t = Ticket(self.env, ticket_to_trackback) 
     81                    t = Ticket(self.env, ticket_to_tracback) 
    7382                except ResourceNotFound: # referenced ticket does not exist 
    7483                    continue 
    75                 trackback_string = trackback_preface + str(ticket.id) 
    76                 t.save_changes(author, trackback_string) 
     84                     
     85                tracback = self.create_tracbacks(ticket, t, comment) 
     86                print tracback 
     87                t.save_changes(author, tracback) 
    7788 
    7889    def ticket_deleted(self, ticket): 
    7990        pass 
     91         
     92    def is_tracback(self, comment): 
     93        return comment.startswith(self.TRACBACK_MAGIC_NUMBER) 
     94         
     95    def create_tracbacks(self, ticket, ticket_to_tracback, comment): 
     96        tracback = self.TRACBACK_MAGIC_NUMBER + self.TRACBACK_PREFACE + str(ticket.id) + ":" 
     97         
     98        # find all occurrences of ticket_to_tracback. This is error prone. 
     99        # we'll weed the errors out later. 
     100        string_representation = "#" + str(ticket_to_tracback.id) 
     101         
     102        excerpts = [] 
     103         
     104        index = -1 
     105        while comment.find(string_representation, index + 1) > -1: 
     106            # Get two characters in context so we can make sure this is really 
     107            # a reference to a ticket, and not anything else. 
     108            index = comment.find(string_representation, index + 1) 
     109             
     110            print str(index) + " ::: " 
     111             
     112            if not self.is_weed(comment, index, index + len(string_representation)): 
     113                start = index - self.EXCERPT_CHARACTERS 
     114                end = index + len(string_representation) + self.EXCERPT_CHARACTERS   
     115                     
     116                # Make sure we don't go into the negative. 
     117                if start < 0: 
     118                    start = 0 
     119                 
     120                excerpt = comment[start:end] 
     121                excerpt = excerpt.replace("\n", "") 
     122                 
     123                # There's probably a better way to say this in python, but Tim doesn't know 
     124                # how to do it. (He's tried """ but something's foobar'ed.) 
     125                excerpts.append("\n> ''...%s...''\n" % excerpt) 
     126             
     127        tracback += ''.join(excerpts) 
     128        return tracback 
     129         
     130    def is_weed(self, comment, start, end): 
     131        start -= self.WEED_BUFFER 
     132        end += self.WEED_BUFFER 
     133         
     134        # Make sure we don't have a negative starting value. 
     135        if start < 0: 
     136            start = 0 
     137             
     138        try: 
     139            match = re.search(self.TICKET_REGEX, comment[start:end]) 
     140            return False 
     141        except: # Not a match. This must be a weed. 
     142            return True 
     143         
     144         
     145         
     146         
     147#        Doug, with some very very cool regular expression prowess, produced 
     148#        the following regular expression that returns sentences with ticket 
     149#        links in them. We could use this -- and almost should -- but I'm  
     150#        going to use the easy method for now as it takes less expertise. 
     151#         
     152#        sentence_pattern = r""" 
     153#        (?:                       # This initial group isn't a matching group 
     154#            (?<=\.)               # End of previous sentence is a period 
     155#           |(?<=\.\s)             #     or period with one space 
     156#           |(?<=\.\s\s)           #     or period with two space 
     157#           |(?<=\.\s\s\s)         #     or period with three spaces 
     158#           |(?<=\.\s\s\s\s)       #     or period with four spaces 
     159#           |^                     # Or we match the beginning of the line 
     160#        ) 
     161#        (                         # We match everything else and return it 
     162#                                  # Because of this, we don't return any other 
     163#                                  # matches 
     164#                [^\s]             # A sentence does not begin with a space 
     165#                (?:               # Match the beginning of the sentence 
     166#                    [^.]          # A sentence does not contain a period 
     167#                   |\.[^\s]       # unless it's part of a word, like a URL 
     168#                )*                # Match any length 
     169#     
     170#            (?=                   # Starting here is a duplicate of the ticketlink 
     171#                                  # above, but without returning any text 
     172#               (?<=^\#)           # Look for a TracLink Ticket at the beginning of the string 
     173#              |(?<=[\s,.;:!]\#)   # or on a whitespace boundary or some punctuation 
     174#            ) 
     175#            (?=\d+)               # Any length ticket number (return the digits) 
     176#            (?=                   # Don't return the end of the ticke tink 
     177#               (?=\b)             # Whether it's a word boundary 
     178#              |$                  # Or an end of string 
     179#            ) 
     180#            (?:                   # Here we match the end of the sentence 
     181#                                  # It follows the same rules as the beginning 
     182#                [^.]              # Don't match a period 
     183#               |\.[^\s]           # unless it's inside a word 
     184#            )*                    # Any length to the end of the sentence 
     185#            (?:                   # Here we will match the end of the sentence 
     186#                (?:\.             # Which is a period (returned as part of the 
     187#                                  # above expression 
     188#                    (?=\s+|$)     # then followed by unmatched whitespace or the 
     189#                                  # end of the line 
     190#                ) 
     191#               |$                 # if there's no period, jus tthe end of the line 
     192#                                  # We'll accept that too 
     193#            ) 
     194#        ) 
     195#        """ 
     196#        excerpt = re.compile(sentence_pattern, re.VERBOSE | re.MULTILINE)