1. Odd Simon Simonsen
  2. trac-rpc-mq

Source

trac-rpc-mq / t1055 / t1055-list_links-r7194.diff

diff -r 4663bf114c66 trunk/tracrpc/util.py
--- a/trunk/tracrpc/util.py	Thu Nov 26 15:30:46 2009 +0100
+++ b/trunk/tracrpc/util.py	Sun Dec 20 02:15:14 2009 -0500
@@ -10,7 +10,10 @@
 import time
 import xmlrpclib
 
+from genshi.builder import Element
+
 from trac.util.datefmt import utc
+from trac.wiki.formatter import Formatter
 
 ### PUBLIC
 
@@ -44,3 +47,75 @@
     from trac.util.text import empty
 except ImportError:
     empty = None
+
+class TracLinksFormatter(Formatter):
+    r"""A wiki formatter that pays attention to nothing but trac 
+    links.
+    
+    Verbatim copy of tracgviz.ig.wiki.TracLinksFormatter
+    """
+    for fmt_name in (x for x in Formatter.__dict__ \
+            if x.endswith('_formatter') and \
+            x not in ['_lhref_formatter', '_shref_formatter']):
+        locals()[fmt_name] = lambda *args, **kwds: ''
+    del fmt_name
+
+class WikiCrawler(TracLinksFormatter):
+    r"""Gather the all links found in a piece of text.
+    """
+    def __init__(self, env, context):
+        super(WikiCrawler, self).__init__(env, context)
+        self._links = []
+    
+    def handle_match(self, fullmatch):
+        r"""Modified version of `trac.wiki.formatter.Formatter.handle_match` 
+        needed to gather links generated by external wiki syntax 
+        providers (e.g. CamelCase).
+        """
+        def ext_wrapper(ext_handler):
+            def _ext_wrapper(fmt, match, fullmatch):
+                result = ext_handler(fmt, match, fullmatch)
+                if isinstance(result, Element) and str(result.tag) == 'a':
+                    self._links.append(result)
+                return result
+            return _ext_wrapper
+
+        for itype, match in fullmatch.groupdict().items():
+            if match and not itype in self.wikiparser.helper_patterns:
+                # Check for preceding escape character '!'
+                if match[0] == '!':
+                    return escape(match[1:])
+                if itype in self.wikiparser.external_handlers:
+                    external_handler = self.wikiparser.external_handlers[itype]
+                    return ext_wrapper(external_handler)(self, match, fullmatch)
+                else:
+                    internal_handler = getattr(self, '_%s_formatter' % itype)
+                    return internal_handler(match, fullmatch)
+
+    def _lhref_formatter(self, match, fullmatch):
+        link = super(WikiCrawler, self)._lhref_formatter(match, fullmatch)
+        self.env.log.debug("RPC(util) LinkFormatter LHREF rule triggered. "
+                        "Match= '%s' Full match= '%s' Link= '%s'", 
+                        match, fullmatch, link)
+        self._links.append(link)
+        return link
+        
+    def _shref_formatter(self, match, fullmatch):
+        link = super(WikiCrawler, self)._shref_formatter(match, fullmatch)
+        self.env.log.debug("RPC(util) LinkFormatter SHREF rule triggered. "
+                        "Match= '%s' Full match= '%s' Link= '%s'", 
+                        match, fullmatch, link)
+        self._links.append(link)
+        return link
+    
+    def extract_link(self, lnk_obj):
+        raise TracError('Unable to extract TracLink from DOM object.')
+    
+    def iter_urls(self):
+        for link in self._links :
+          if not link:
+              pass
+          elif isinstance(link, Element):
+              yield link.attrib.get('href')
+          else:
+              yield self.extract_link(link)
diff -r 4663bf114c66 trunk/tracrpc/wiki.py
--- a/trunk/tracrpc/wiki.py	Thu Nov 26 15:30:46 2009 +0100
+++ b/trunk/tracrpc/wiki.py	Sun Dec 20 02:15:14 2009 -0500
@@ -10,10 +10,12 @@
     from cStringIO import StringIO
 except ImportError:
     from StringIO import StringIO
+from itertools import chain
 import xmlrpclib
 import os
 
 from trac.core import *
+from trac.mimeview.api import Context
 from trac.resource import Resource
 from trac.util.datefmt import to_timestamp, to_datetime, utc
 from trac.wiki.api import WikiSystem
@@ -22,6 +24,7 @@
 from trac.attachment import Attachment
 
 from tracrpc.api import IXMLRPCHandler, expose_rpc
+from tracrpc.util import WikiCrawler
 
 class WikiRPC(Component):
     """Superset of the
@@ -199,8 +202,17 @@
         return True
 
     def listLinks(self, req, pagename):
-        """ ''Not implemented'' """
-        return []
+        """ List all URLs in links found in a wiki page. Supports both 
+        TracLinks and CamelCase"""
+        text = self.getPage(req, pagename)
+        env = self.env
+        ctx = Context.from_request(req, absurls=True)
+        abs_ref, href = req.abs_href, req.href
+        lf = WikiCrawler(env, ctx)
+        lf.format(text)
+        files = self.listAttachments(req, pagename)
+        href = self.env.abs_href.attachment
+        return chain(lf.iter_urls(), (href('wiki', f) for f in files))
 
     def wikiToHtml(self, req, text):
         """ Render arbitrary Wiki text as HTML. """