00001
00002 """
00003 ROS - TutorialChain
00004
00005 <<TutorialChain(path/to/FirstTutorial)>>
00006 Given a wiki link to a Tutorial, it will traverse the next links
00007 until a terminal Tutorial with no next link is found. Then the
00008 Tutorials are displayed in order with links and descriptions.
00009
00010 @copyright: 2012 Willow Garage,
00011 William Woodall <wwoodall@willowgarage.com>
00012 @license: BSD
00013 """
00014
00015 from __future__ import print_function
00016
00017 import re
00018 from Queue import Queue
00019
00020 from MoinMoin import wikiutil
00021 from MoinMoin.Page import Page
00022 from MoinMoin.parser.text_moin_wiki import Parser as WikiParser
00023
00024 Dependencies = ["pages"]
00025
00026
00027 def formatContext(page, macro):
00028 """ Format search context for each matched page
00029
00030 Try to show first maxlines interesting matches context.
00031 """
00032 body = page.get_raw_body()
00033
00034 pagedict = {}
00035 for line in body.split("\n"):
00036 if line.startswith("##"):
00037 line = line[2:].strip()
00038 parts = line.split("=", 1)
00039 if len(parts) == 2:
00040 pagedict[parts[0].strip()] = parts[1].strip()
00041
00042 title = pagedict.get("title", "No Title")
00043 description = pagedict.get("description", "No Description")
00044
00045 next_pages = []
00046 linkpat = re.compile("\[\[([^|]*)(\|([^]]*))?\]\]")
00047 for key, val in pagedict.items():
00048 if key.startswith("next.") and key.find(".link") != -1:
00049 m = linkpat.search(val)
00050 if m:
00051 next_pages.append(m.group(1))
00052
00053 return title, description, next_pages
00054
00055
00056 def get_wiki_page(wiki_link, macro):
00057 if not wiki_link:
00058 return {}
00059 page_name = macro.formatter.page.page_name
00060 tutorial_page_name = wikiutil.AbsPageName(page_name, wiki_link)
00061 tutorial_page = Page(macro.request, tutorial_page_name)
00062 result = formatContext(tutorial_page, macro)
00063 if not result:
00064 return {}
00065 tutorial = {
00066 'link': tutorial_page_name,
00067 'title': result[0],
00068 'desc': result[1],
00069 'next': result[2]
00070 }
00071 return tutorial
00072
00073
00074 def crawl_tutorials_breadth_first(tutorial_root, macro):
00075 queue = Queue()
00076 queue.put((tutorial_root, None))
00077 tutorials = []
00078 while not queue.empty():
00079 link, parent = queue.get()
00080 tut = get_wiki_page(link, macro)
00081 tup = (tut['link'], tut['title'], tut['desc'])
00082 if tut['link'] not in [t[0] for t in tutorials]:
00083 tutorials.append(tup)
00084 else:
00085 tutorials.append(tutorials.pop(tutorials.index(tup)))
00086 for next in tut['next']:
00087 queue.put((next, tut['link']))
00088 return tutorials
00089
00090
00091 def execute(macro, first_tutorial):
00092 try:
00093 request = macro.request
00094 _ = request.getText
00095
00096 if type(first_tutorial) == str:
00097 first_tutorial = first_tutorial.strip()
00098 if not first_tutorial:
00099 err = _('Invalid first Tutorial given: '
00100 '{{{"%s"}}}', wiki=True) % first_tutorial
00101 return '<span class="error">%s</span>' % err
00102
00103 tutorial_list = crawl_tutorials_breadth_first(first_tutorial, macro)
00104
00105 f = macro.formatter
00106 content = ''
00107 content += f.number_list(1)
00108 for link, title, desc in tutorial_list:
00109 desc = str(desc or 'No Description')
00110 content += ''.join([
00111 f.listitem(1),
00112 f.pagelink(1, str(link or '#BadLink')),
00113 str(title or 'No Title'),
00114 f.pagelink(0),
00115 "<p>",
00116 wikiutil.renderText(request, WikiParser, desc),
00117 "</p>",
00118 f.listitem(0)
00119 ])
00120 content += f.number_list(0)
00121 return content
00122 except Exception as e:
00123 import traceback
00124 tb = traceback.format_exc()
00125 return '<span class="error"><pre>%s\nError: %s</pre></span>' % (tb, e)