trac-ticketlinks / trac / ticket /

Diff from to


         Must return a list of `(field, message)` tuples, one for each problem
         detected. `field` can be `None` to indicate an overall problem with the
         ticket. Therefore, a return value of `[]` means everything is OK."""
 class ITicketLinkController(Interface):
     def get_ends():
         """Return an iterable of field names populated in a new ticket created
         as a linked ticket."""
 class IMilestoneChangeListener(Interface):
     """Extension point interface for components that require notification
     when milestones are created, modified, or deleted."""
     default_copy_fields = ListOption('ticket', 'default_copy_fields', [],
         doc="""Default fields populated for newly created linked tickets
         (''since 0.13dev'').""")
-    # regular expression to match links
-    NUMBERS_RE = re.compile(r'\d+', re.U)
+    # Regular expression to match links, a link is any number preceeded by
+    # the beginning of the string, whitespace, a comma or a hash/pound
+    # e.g. '1, #2, linked:#3 4 other:5,6' -> ['1', '2', '4', '6']
+    NUMBERS_RE = re.compile(r'(?:^|[\s,])#?(\d+)', re.U)
     def __init__(self):
         self.log.debug('action controllers for ticket workflow: %r' % 
             field['custom'] = True
         # fields for links
         for controller in self.link_controllers:
             for end1, end2 in controller.get_ends():
                     self._add_link_field(end2, controller, fields)
         return fields
     reserved_field_names = ['report', 'order', 'desc', 'group', 'groupdesc',
                             'col', 'row', 'format', 'max', 'page', 'verbose',
                             'comment', 'or']
     def _add_link_field(self, end, controller, fields):
         label = controller.render_end(end)
         copy_fields = controller.get_copy_fields(end)
         if end in [f['name'] for f in fields]:
-            self.log.warning('Duplicate field name "%s" (ignoring)', end)
+            self.log.warning('Duplicate field name "%s" (ignoring)',
+                             end)
-        field = {'name': end, 'type': 'link', 'label': label, 
+        field = {'name': end, 'type': 'link', 'label': label,
+                 'creator': controller.is_creator(end),
                  'link': True, 'format': 'wiki', 'copy_fields': copy_fields}
            return []
        return list(unique(int(id) for id in self.NUMBERS_RE.findall(value)))
+    def other_end(self, end):
+        """Return the other end of a bidirectional link, end if the link is
+        unidirectional.
+        """
+        other_end = self.link_ends_map[end]
+        if other_end is None:
+            return end
+        else:
+            return other_end
     # IResourceManager methods
     def get_resource_realms(self):