Roundup Tracker

It's a common use case to have your tracker system somehow integrated within your Source Control Manager. A simple way I found to do this is to have keywords in the item messages that expand to hyperlinks.

Hence, if you type in the item's note textbox something like 'This problem is solved in Version:35' the recipe I present here lets roundup expands such message with an hyperlink in 'Version:35' that points to a custom Versioning system.

This solution is very customizable and you may find many others useful cases.

Procedures

  1. In issue.item.html replace the line where it says:
       "structure msg.content.hyperlinked"
    by:
       "structure python:utils.localReplace(msg.content.hyperlinked())"
  2. In your 'extensions' directory, create a file 'local_replace.py' with::
       1      from custom_tags import CustomTags
       2      def localReplace(aMessage):
       3          return CustomTags().replace(aMessage)
       4 
       5      def init(instance):
       6          instance.registerUtil('localReplace', localReplace)
    
  3. Add the custom_tags.py to a directory where Roundup can find it (I'd use python's

    site-packages see footnote, or you can create a subdirectory named lib in your tracker home directory and put the file there.) customizing the 'substitute' attribute for your own needs. All the specific work you need to do is in this variable. Read the CustomTags class doc for details.

Ask any question at the roundup users mailing list or by email to hfoffani@gmail.com.

Regards,

-Hernan.

custom_tags.py:

   1     import re
   2     class CustomTags:
   3         """Replace custom tags
   4     
   5         Use this class if you want to do parametrized string substitution
   6         in a given text.  It's useful to expand some keywords with a full
   7         html tag.  Customize this class by changing the 'substitute'
   8         attribute.  This attribute is a list of tuples.  Each tuple
   9         represents a substitution task.  The first item of the tuple is
  10         the lookup regular expression, the second item is the replace
  11         string template.  Just be careful to match the names in the
  12         regular expression, eg. '(?P<a_name>...)', with the corresponding
  13         ones in the template, eg. '... %(a_name)s ...'
  14     
  15         A simple case:
  16         >>> ct = CustomTags()
  17         >>> ct.substitute = [('mom','papa')]
  18         >>> ct.replace("hey! look mom! no hands!")
  19         'hey! look papa! no hands!'
  20     
  21         A more complex one:
  22         >>> ct.substitute = [ (
  23         ...      r'(?P<kw>rev):(?P<int>\d*)',
  24         ...      r'<a href="http://%(kw)s?%(int)s">%(kw)s:%(int)s</a>'
  25         ...  ) ] 
  26         >>> ct.replace("this is rev:33. but not rev:44")
  27         'this is <a href="http://rev?33">rev:33</a>. but not <a href="http://rev?44">rev:44</a>'
  28         >>> ct.replace("this remains untouched")
  29         'this remains untouched'
  30     
  31         More than one substitution task:
  32         >>> ct = CustomTags()
  33         >>> ct.substitute = [
  34         ...    ( r'mom', r'papa' ),
  35         ...    ( # a more complex one
  36         ...      r'(?P<kw>rev):(?P<int>\d*)',
  37         ...      r'<a href="http://%(kw)s?%(int)s">%(kw)s:%(int)s</a>')
  38         ... ]
  39         >>> ct.replace("mom, look for rev:1")
  40         'papa, look for <a href="http://rev?1">rev:1</a>'
  41     
  42         Do nothing:
  43         >>> ct = CustomTags()
  44         >>> ct.substitute = [ ]
  45         >>> ct.replace("this should be untouched.")
  46         'this should be untouched.'
  47 
  48         For better performance you may precompile the regexp adding a
  49         call to 're.compile(..)' to the first member of each tuple in
  50         the 'substitute' list.
  51         """
  52     
  53         substitute = [ 
  54           # ( r'mom', r'papa' ),
  55           # ( r'(?P<kw>rev):(?P<int>\d*)',
  56           #   r'<a href="http://%(kw)s?%(int)s">%(kw)s:%(int)s</a>' )
  57         ]
  58     
  59         def replace(self, text):
  60             """Returns a copy of text with its contents replaced."""
  61     
  62             ntext = text
  63             for regex, template in self.substitute:
  64                 for match in re.finditer(regex, text):
  65                     ntag = template % match.groupdict()
  66                     ntext = ntext.replace(match.group(0), ntag, 1)
  67             return ntext
  68     
  69     if __name__ == "__main__":
  70         import doctest
  71         doctest.testmod()

How to use site-packages for custom scripts.

Back to top

Back to roundup wiki's FrontPage