Package mathbench :: Package basement :: Module librarian
[hide private]

Source Code for Module mathbench.basement.librarian

  1  #!/usr/bin/python 
  2  # -*- coding: utf-8 -*- 
  3   
  4  """ 
  5  Management of the documentation of mathbench and its plugins. 
  6  """ 
  7   
  8  import os  
  9  import logging 
 10  import re 
 11   
 12  import wx.py.dispatcher as dispatcher 
 13   
14 -def DefangHTML(txt):
15 """ 16 Defang html symbols. 17 18 Inspired from : 19 http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/81330 20 """ 21 symbol_dict = { 22 "&" : "&amp;", 23 ">" : "&gt;", 24 "<" : "&lt;", 25 "é" : "&eacute;", 26 "è" : "&egrave;", 27 "à" : "&agrave;", 28 "\n" : " \n<br>", 29 } 30 re_match_pattern = "(%s)" % "|".join( map(re.escape, symbol_dict.keys()) ) 31 return re.sub( re_match_pattern, lambda m:symbol_dict[m.group()], txt )
32 33
34 -class MathBenchSearchEngine(object):
35 """ 36 A simple search engine to index the documentation of MathBench's 37 basic usages. 38 """ 39 40 MATHBENCH_WEBSITE = "http://mathbench.sourceforge.net/" 41
42 - def __init__(self):
43 """ 44 Create the indexing dictionary 45 """ 46 # We will use here the worst posssible way of indexing the 47 # documentation, but it is mainly to be used as a test for the doc 48 # search api. 49 self.search_dict = { 50 "mathbench help shell idea completion python test idea" : 51 ( self.MATHBENCH_WEBSITE + "doc-basic-usage.html", 52 "Basic usage of the shell"), 53 54 "mathbench help editor execute execution python refine work" : 55 ( self.MATHBENCH_WEBSITE + "doc-editor-work.html", 56 "Working with the editor"), 57 58 "mathbench help librarydesk documentation search query" : 59 ( self.MATHBENCH_WEBSITE + "doc-library-use.html", 60 "Search the documentation via the library desk"), 61 62 "mathbench help extend plugin install" : 63 ( self.MATHBENCH_WEBSITE + "doc-plugins.html", 64 "Adapt the application to your needs with plugins"), 65 }
66 67
68 - def search(self,search_query):
69 """ 70 Search the documentation 71 """ 72 # split the query into its various keywords 73 search_query_kw = search_query.split() 74 # print search_query_kw 75 result_dict = {} 76 for key in self.search_dict.keys(): 77 count = 0 78 for item in search_query_kw: 79 if key.find(str(item))!=-1: 80 count += 1 81 if count != 0: 82 if result_dict.has_key(count): 83 result_dict[count].append(self.search_dict[key]) 84 else: 85 result_dict[count] = [self.search_dict[key]] 86 # print result_dict 87 ranks = result_dict.keys() 88 ranks.sort() 89 ranks.reverse() 90 results = [] 91 for r in ranks: 92 results.extend(result_dict[r]) 93 # print results 94 return results
95 96
97 -class LibrarianSingleton(object):
98 """ 99 A singleton class in charge of building, updating the library 100 and also performing the searches. 101 102 The librarian is in charge of creating the library desk display 103 and then must be informed of which DeskFacory to use to create 104 this desk. 105 106 The display widget created must also send a 'LibraryDeskClosed' 107 signal when it is closed. 108 """ 109 110 __instance = None 111
112 - def __init__(self):
113 """ 114 Initialisation: this class should not be initialised 115 explicitly and the ``get`` classmethod must be called instead. 116 """ 117 if self.__instance is not None: 118 raise Exception("Singleton can't be created twice !") 119 mbse = MathBenchSearchEngine() 120 self.__search_methods = {"MathBench": mbse.search} 121 self.__desk_factory = None 122 self.__desk = None
123 124
125 - def show(self,txt):
126 """ 127 Show the results in a frame. 128 """ 129 if self.__desk==None: 130 self.__desk = self.__desk_factory() 131 dispatcher.connect(receiver=self._desk_closed, 132 signal='LibraryDeskClosed', sender=self.__desk) 133 134 self.__desk.showPage(txt)
135
136 - def _desk_closed(self):
137 """ 138 When the desk is closed 139 """ 140 self.__desk = None
141
142 - def compile_results(self,search_query):
143 """ 144 Compile the search results in a unique html page. 145 """ 146 # Init the html file description 147 search_res = ["""\ 148 <html> 149 <title>Search results</title> 150 151 <body> 152 <H1> Search results for "%s" </H1> 153 <br>""" % search_query 154 ] 155 temp_search_res = [] 156 # browse each context and ask for results 157 # print self.__search_methods 158 for context in self.__search_methods.keys(): 159 res_list = self.__search_methods[context](search_query) 160 if len(res_list)==0: 161 continue 162 else: 163 # when results have been found display them as list 164 temp_search_res.append("""\ 165 <br> 166 <H2>From %s</H2> 167 <br> 168 <ul>""" % DefangHTML(context)) 169 for item in res_list: 170 temp_search_res.append("""\ 171 <li><a href='%s'>%s</a></li> 172 <br>""" % item) 173 # finish the list 174 temp_search_res.append("""\ 175 </ul> 176 <br>""") 177 178 if len(temp_search_res)==0: 179 search_res = ["""\ 180 <html> 181 <title>Search results</title> 182 183 <body> 184 <H1> Sorry, no result for "%s" </H1> 185 <br>""" % search_query 186 ] 187 else: 188 search_res.extend(temp_search_res) 189 190 # At the very end close the document 191 search_res.append("""\ 192 </body> 193 </html> 194 """) 195 return os.linesep.join(search_res)
196 197
198 - def show_welcome(self):
199 """ 200 Display the welcome text in a widget 201 """ 202 welcome_txt = """\ 203 <html> 204 205 <title>Welcome</title> 206 207 <body> 208 209 <H1> Library Desk </H1> 210 211 <H2> About this desk</H2> 212 213 If you're looking for a precise answer, you may enter a search query 214 in the text area of the toolbar, press "Enter" (on your keyboard) and 215 the available answers will be shown to you. 216 217 <br> 218 <br> 219 220 Please also note that this viewer is buggy with external websites, 221 hence you should prefer going to online websites with your own 222 webbrowser. 223 224 225 <H2> About Python </H2> 226 227 <H3> References</H3> 228 <ul> 229 <li><a href="http://python.org">Python language</a> 230 <pre>http://python.org</pre></li> 231 <li><a href="http://docs.python.org/modindex.html">Modules index</a> 232 <pre>http://docs.python.org/modindex.html</pre></li> 233 <li><a href="http://starship.python.net/crew/theller/pyhelp.cgi">Online search</a> 234 <pre>http://starship.python.net/crew/theller/pyhelp.cgi</pre></li> 235 </ul> 236 237 <H3>Quick introductions</H3> 238 <ul> 239 <li><a href="http://docs.python.org/tut/tut.html">Python tutorial</a> 240 <pre>http://docs.python.org/tut/tut.html</pre></li> 241 <li><a href="http://wiki.python.org/moin/SimplePrograms">Simple code samples</a> 242 <pre>http://wiki.python.org/moin/SimplePrograms</pre></li> 243 </ul> 244 245 <H2> About Mathbench</H2> 246 247 <ul> 248 <li><a href="http://mathbench.sourceforge.net/">Mathbench Project</a> 249 <pre>http://mathbench.sourceforge.net</pre></li> 250 </ul> 251 252 </body> 253 254 </html> 255 """ 256 self.show(welcome_txt)
257
258 - def setSearchMethod(self,search_method,context_name):
259 """ 260 Set the search method 261 """ 262 self.__search_methods[context_name] = search_method
263
264 - def record_search(self,txt):
265 """ 266 Record the previous search items 267 """ 268 self.__desk.addToHistory(txt)
269 270 #--- CLASS METHODS 271
272 - def get(self):
273 """ 274 Actually create an instance 275 """ 276 if self.__instance is None: 277 self.__instance = LibrarianSingleton() 278 logging.debug("LibrarianSingleton initialised") 279 return self.__instance
280 get = classmethod(get) 281
282 - def register(self,search_method,context_name):
283 """ 284 Register a search method for a specific context (usually the 285 library imported by a precise plugin.) 286 """ 287 librarian = self.get() 288 librarian.setSearchMethod(search_method,context_name) 289 logging.debug("Adding the search method from %s to the LibrarianSingleton" % context_name)
290 register = classmethod(register) 291
292 - def setDeskFactory(self,desk_factory):
293 """ 294 Set the factory that will be in charge of creating the desk 295 (ie the widget displaying the search results) 296 """ 297 librarian = self.get() 298 librarian.__desk_factory = desk_factory
299 setDeskFactory = classmethod(setDeskFactory) 300 301
302 - def search(self,search_query):
303 """ 304 Return a HTML formated text providing links to all the search results. 305 """ 306 if search_query.strip() == "": 307 return 308 librarian = LibrarianSingleton.get() 309 search_res = librarian.compile_results(search_query) 310 librarian.show(search_res) 311 librarian.record_search(search_query)
312 search = classmethod(search) 313
314 - def welcome(self):
315 """ 316 Display a welome page 317 """ 318 librarian = LibrarianSingleton.get() 319 librarian.show_welcome()
320 welcome = classmethod(welcome) 321 322
323 - def popup(self):
324 """ 325 Put the desk on top of the other frames 326 """ 327 librarian = self.get() 328 if librarian.__desk is None: 329 self.welcome() 330 else: 331 librarian.__desk.Show(False) 332 librarian.__desk.Show(True)
333 popup = classmethod(popup)
334