Attachment 'tables-1.3.py'

Download

   1 #-*- coding: utf-8 -*-
   2 '''
   3 MoinMoin - tables parser, Version 1.3, 15.10.2012
   4 
   5 A simple parser that reads key:value pairs from a listing of tables (moin table markup from page or attachment) and captions then formats these for display within an enclosing borderless table. Defaults to single column layout with captions above centred tables. If more key:value pairs are provided additional rows are added to the layout. The user can set options to (1) force double or triple column layout, (2) place captions to the left or right of the tables, (3) set tables left or right justified, (4) give tables a width other than the default of 66% (a value from 25 to 100% is permitted), and (5) show only the markup for re-use with modifications, if desired, or for debugging purposes.
   6 
   7 The key:value list must be in the form " table_page/file:: caption" with a leading space (as moin dictionary entries). All non-conforming lines are ignored without warning.
   8 
   9 The key is a page or attachment name. The parser checks for a page first. Processing instructions are permitted at the head of a page but not in an attachment. Comment lines beginning with `##` are permitted within the table. Otherwise, both the page and file must contain a markup for a single table only.
  10 
  11 The parser is intended for page section use only. The parser name is followed by a list of keywords separated by spaces to specify any options required.
  12 
  13 Keywords
  14 
  15 anchors : Create anchors from the captions, if they contain 'Table nnn', where n is any digit. Any bold or italic emphasis markup is removed from the caption first. The anchors are placed before tables in a horizontal group.
  16 
  17 c-2 : forces double column layout, if the requested with is 50% or less. Overides c-3, if both options given, as double column takes precedence.
  18 
  19 c-3 : forces triple column layout, if the requested width is 33% or less. Default is one columns, so no c-1 is not needed.
  20 
  21 c-left : caption to left of image. Overides c-none or c-right, if more than one option given, as left takes precedence.
  22 
  23 c-none : ignore captions.
  24 
  25 c-right : caption to right of image. Overides c-none, if both options given, as right takes precedence over none.
  26 
  27 t-left : tables set left. Overides f-right, if both options given, as left takes precedence.
  28 
  29 t-right : tables set right.
  30 
  31 nnn% : requested width of table (including caption if set to left or right), where n is digits from 25 to 100. If outside this range, the default 50% is applied and no warning is given. If two or more width options are given, the first takes precedence and others are ignored (even if the first is invalid and the default widith applied).
  32 
  33 markup : shows the markup if you wish to re-use this with modification (assuming the default tabulation does not suit a specific purpose) or for debugging purposes.
  34 
  35 # : inserted at the beginning of the caption overrides caption inclusion and any associated padding. Inclusion of caption text is option and effectively acts as a comment. Overidding captions can result in uneven multiple row layout where rows have different number of images and/or overidden captions. Therefore, this feature in recommended only for single row layouts. Also, caption and padding cells are not generated, so the sum of the cell widths is less than the table width and the tables and remaining captions will increase in size proportionally. Values set by the nnn% argument therefore become nominal only.
  36 
  37 Defaults are caption and table centred, width 66%, one column (so no options for these are needed).
  38 
  39 Keywords can appear in any order, other than as indicated above for conflicting choices.
  40 
  41 Dependency
  42 
  43 The parser requires a macro RenderText.py to be installed in plugin/macros. This macro un-glues the inserted table's lines, renders the markup text and inserts it in the enclosing table cell.
  44 
  45 {{{
  46 from MoinMoin import wikiutil
  47 from MoinMoin.parser.text_moin_wiki import Parser as wiki
  48 def execute(macro, text):
  49      text = (text.replace('&&', '\n')).replace(')+>>', ')>>')
  50      return wikiutil.renderText(macro.request, wiki, text)
  51 }}}
  52 
  53 Usage
  54 
  55 {{{#!tables [anchors ][c-2|c-3 ][c-left|c-none|c-right ][t-left|t-right ][nnn% ][markup ]
  56  table_page/file:: [#]caption
  57  table_page/file:: [#]caption
  58  ...
  59 }}}
  60 
  61 History
  62 
  63 Version 1.3 - 15.10.2012: included automatic anchor insertion
  64 Version 1.2 - 14.10.2012: included time dependency to properly handle Ref macro in captions
  65 Version 1.1 - 23.01.2011: escaped macro syntax; revised RenderText macro accordingly
  66 Version 1.0 - 22.01.2011: initial version
  67 
  68 Developed with inspiration and code from:
  69 
  70 figures.py parser - @copyright: 2011 Ian Riley
  71 keyval.py parser - @copyright: 2006 by Matt Cooper <macooper@vt.edu>
  72 sort.py parser - @copyright: 2005 ReimarBauer
  73 
  74 Copyright
  75 
  76 @copyright: 2012 Ian Riley <ian.riley@internode.on.net>
  77 
  78 License
  79 
  80 GNU GPL, see COPYING for details.
  81 '''
  82 
  83 import re
  84 from MoinMoin.action import AttachFile
  85 from MoinMoin.Page import Page
  86 from MoinMoin.parser import text_moin_wiki as wiki
  87 from MoinMoin import wikiutil
  88 
  89 Dependencies = ["time"] # for captions with <<Ref()>>, which uses <<FootNote()>>, so no caching
  90 
  91 class Parser:
  92     parsername = 'tables'
  93 
  94     def __init__(self, raw, request, **kw):
  95         self.raw = raw
  96         self.request = request
  97         self.form = request.form
  98         self._ = request.getText
  99         self.args = kw.get('format_args', '')
 100 
 101     def format(self, formatter):
 102         empty = u''
 103         eol = u'\n'
 104         rtn = u'\r'
 105         glue = u'&&'
 106         sep = u':: '
 107         sep_dir = u'/'
 108         space = u' '
 109         monospace = u'` `'
 110         macro_end = u')>>'
 111         macro_esc = u')+>>'
 112         ignore = u'#'
 113         comment = u'##'
 114         percent = u'%'
 115         brk = u'<<BR>>'
 116         parsing = (u"{{{", u"}}}", )
 117         anchor = u'<<Anchor(%(anchorname)s)>>'
 118         anchor_pattern = u'^(Table? \d+)'
 119         tab = u'||<tablestyle="width:100%; " '
 120         cell  = u'||<style="border:none; width:%(width)s%%; ">'
 121         cella  = u'||<%(align)s style="border:none; width:%(width)s%%; ">'
 122         padcell  = u'||<style="border:none; width:%(pad)s%%; ">'
 123         celli = u'||'
 124         cellf = u'||\n'
 125         tbl = u'<<RenderText(%(tbl)s)>>'
 126         cap = u'%(cap)s'
 127         capc = u'<<RenderText(||<tablestyle="width:100%%; " style="border:none; ">%(cap)s ||)>>'
 128         tfile = u'.txt'
 129         warning_msg =  u'||<style="color: #ff0000; font-weight: bold;">%s: %s||'
 130         options, tables, anchornames, rows, results = ([], [], [], [], [], )
 131         tbls, ignored, layout, padding = (0, 0, 0, 0, )
 132         left, centre, right, void = (0, 1, 2, 3, )
 133         top, mid, bot, ljust, cjust, rjust = (u'^', u'', u'v', u'(', u':', u')', )
 134         max_cols = 1
 135         std_width = 66
 136         min_widths = (0, 25, 25, 25, )
 137         max_widths = (0, 100, 50, 33, )
 138         aligns = (mid, top, mid, mid, ) # TODO consider making this a selectable option
 139         justs = (rjust, ljust, ljust, ljust, ) # leave centred (ie above) caption left justified
 140         # for captions (left, centre, right, none,)
 141         layouts = (cella+cap+cell+tbl, cell+capc+tbl, cell+tbl+cella+cap, cell+tbl, ) 
 142 
 143         #set defaults which might get changed
 144         cap_pos = centre
 145         tbl_pos = centre
 146         req_width = std_width
 147 
 148         # set options
 149         options = self.args.split(space)
 150         anchors = "anchors" in options
 151         if "c-none" in options:
 152             cap_pos = void
 153         if "c-right" in options:  # do second as right takes precedence
 154             cap_pos = right
 155         if "c-left" in options: # do last as left takes precedence
 156             cap_pos = left
 157         if "c-3" in options:
 158             max_cols = 3
 159         if "c-2" in options: # do second as single column takes precedence
 160             max_cols = 2
 161         if "t-right" in options:
 162             tbl_pos = right
 163         if "t-left" in options: # do second as left takes precedence
 164             tbl_pos = left
 165         markup = "markup" in options
 166         for option in options:
 167             if option.endswith(percent):
 168                 try:
 169                     req_width = int(option.rstrip(percent)) # will check this value later
 170                 except:
 171                     pass
 172                 break # do not look for any more width options
 173         del options
 174         # check requested width in range or set default
 175         if (req_width > max_widths[1]) or (req_width < min_widths[3]):
 176             req_width = std_width
 177         # dynamically set maximum columns depending on requested width
 178         while (max_cols > 1) and (req_width > max_widths[max_cols]):
 179             max_cols = max_cols - 1
 180         # calculate widths for captions (left, centre, right)
 181         widths = (int(req_width / 2), req_width, int(req_width / 2), req_width, )
 182 
 183         def get_attachment(request, page_name, source):
 184             if AttachFile.exists(request, page_name, source):
 185                 file_name = Page(request, page_name).getPagePath("attachments")
 186                 file_name = file_name+sep_dir+source
 187                 f = open(file_name,'r')
 188                 text = f.read()
 189                 f.close()
 190                 text = text.replace(rtn,empty)
 191                 if text == empty:
 192                     text = warning_msg % (source, 'attachment empty', )
 193             else:
 194                 text = warning_msg % (source, 'not found', )
 195             return text
 196 
 197         def get_content(source):
 198             content = []
 199             page_name = self.request.page.page_name
 200             abs_source = wikiutil.AbsPageName(page_name, source)
 201             # is there a page?
 202             if not Page(self.request, abs_source).isStandardPage(abs_source):
 203                 #try for an attachment instead
 204                 text = get_attachment(self.request, page_name, (source + tfile))
 205             else:
 206                 if self.request.user.may.read(abs_source):
 207                     content = Page(self.request, abs_source)
 208                     text = content.getPageText()
 209                     if (content is None) or (text == empty):
 210                         text = warning_msg % (source, 'page empty', )
 211                 else:
 212                     text = warning_msg % (source, 'access denied', )
 213             # crudely check that text conforms to table markup
 214             text = text.strip()
 215             lines = text.split(eol)
 216             text = empty
 217             for line in lines:
 218                 if line.startswith(comment):
 219                     continue
 220                 if (not line.startswith(celli)) or (not line.endswith(celli)):
 221                      text = warning_msg % (source, 'invalid table markup', )
 222                      break
 223                 text = text + line.strip() + glue
 224             text = text.rstrip(glue)
 225             text = text.replace(macro_end, macro_esc)
 226             return text
 227 
 228         def get_anchorname(val):
 229             match = None
 230             if anchors:
 231                 match = re.match(anchor_pattern, val.replace("'","")).group()
 232             return match
 233              
 234         # process the lines of text provided
 235         lines = self.raw.split(eol)
 236         for line in lines:
 237             if line:
 238                 # handle table lines
 239                 if (line[0] == space) and (sep in line):
 240                     key, val = (line.lstrip(space)).split(sep)
 241                     val = val.replace(macro_end, macro_esc)
 242                     tables.append((key, val, get_content(key)))
 243                     anchornames.append(get_anchorname(val))
 244                     #if val.startswith(ignore): #TODO check if really not needed
 245                     #    ignored = ignored + 1
 246         del lines
 247 
 248         # construct a list of row column numbers
 249         tbls = len(tables)
 250         while tbls >= max_cols:
 251            rows.append(max_cols)
 252            tbls = tbls - max_cols
 253         if tbls > 0:
 254            rows.append(tbls)
 255 
 256         # construct output for columns in rows
 257         def calc_padding():
 258             table_width = int(100 / max_cols) * max_cols
 259             item_width = widths[cap_pos]
 260             if (cap_pos in (left, right, )): # offset caption so double for image + caption
 261                 item_width = item_width * 2
 262             if tbl_pos == centre: # centred so needs smaller interspersed padding
 263                 padding = int((table_width - (item_width * cols)) / (cols + 1))
 264             else: # not centred so wider padding
 265                 padding = int(table_width - (item_width * cols))
 266             return padding
 267 
 268         def add_padding(seq):
 269             yes_pad = False
 270             if padding == 0:
 271                 return ''
 272             if seq == 0:
 273                 yes_pad = (tbl_pos == right)
 274             elif seq == 1:
 275                 yes_pad = (tbl_pos == centre) and \
 276                           ((cap_pos in (centre, void, )) or \
 277                            (first_col) or \
 278                            ((cap_pos == left) and (layout != void)))
 279             elif seq == 2:
 280                 yes_pad = (tbl_pos == centre) and \
 281                           ((cols == 1) or \
 282                            ((cap_pos == right) and (layout != void)))
 283             elif seq == 3:
 284                 yes_pad = (tbl_pos == left)
 285 
 286             if yes_pad:
 287                 return (padcell % {'pad': padding})
 288             else:
 289                 return ''
 290 
 291         for cols in rows:
 292             first_col = True
 293             pending = ''
 294             anchors_pending = ''
 295             padding = calc_padding()
 296             pending = pending + add_padding(0)
 297             while cols > 0:
 298                 table = tables.pop(0)
 299                 if anchors:
 300                     anchorname = anchornames.pop(0)
 301                     if anchorname:
 302                         anchors_pending += (anchor % {'anchorname': anchorname, })
 303                 if table[1].startswith(ignore):
 304                     layout = void
 305                 else:
 306                     layout = cap_pos
 307                 pending = pending + add_padding(1)
 308                 pending = pending + \
 309                          (layouts[layout] % {'align': aligns[cap_pos]+justs[cap_pos], \
 310                                              'width': widths[cap_pos], \
 311                                              'tbl': table[2], \
 312                                              'cap': table[1]})
 313                 pending = pending + add_padding(2)
 314                 cols = cols - 1
 315                 first_col = False
 316             pending = pending + add_padding(3)
 317             pending = tab + pending[3:] + cellf # insert tablestyle and close table
 318             if anchors:
 319                 results.append(anchors_pending)
 320             results.append(pending)
 321 
 322         del rows, tables
 323 
 324         # escape markup if requested
 325         if markup:
 326             results.insert(0, parsing[0])
 327             results.append(parsing[1])
 328 
 329         wikiizer = wiki.Parser(eol.join(results), self.request)
 330         wikiizer.format(formatter, inhibit_p=True)#-*- coding: utf-8 -*-
 331 '''
 332 MoinMoin - tables parser, Version 1.3, 14.10.2012
 333 
 334 A simple parser that reads key:value pairs from a listing of tables (moin table markup from page or attachment) and captions then formats these for display within an enclosing borderless table. Defaults to single column layout with captions above centred tables. If more key:value pairs are provided additional rows are added to the layout. The user can set options to (1) force double or triple column layout, (2) place captions to the left or right of the tables, (3) set tables left or right justified, (4) give tables a width other than the default of 66% (a value from 25 to 100% is permitted), and (5) show only the markup for re-use with modifications, if desired, or for debugging purposes.
 335 
 336 The key:value list must be in the form " table_page/file:: caption" with a leading space (as moin dictionary entries). All non-conforming lines are ignored without warning.
 337 
 338 The key is a page or attachment name. The parser checks for a page first. Processing instructions are permitted at the head of a page but not in an attachment. Comment lines beginning with `##` are permitted within the table. Otherwise, both the page and file must contain a markup for a single table only.
 339 
 340 The parser is intended for page section use only. The parser name is followed by a list of keywords separated by spaces to specify any options required.
 341 
 342 Keywords
 343 
 344 anchors : Create anchors from the captions, if they contain 'Table nnn', where n is any digit. Any bold or italic emphasis markup is removed from the caption first. The anchors are placed before all figures in the tables.
 345 
 346 c-2 : forces double column layout, if the requested with is 50% or less. Overides c-3, if both options given, as double column takes precedence.
 347 
 348 c-3 : forces triple column layout, if the requested width is 33% or less. Default is one columns, so no c-1 is not needed.
 349 
 350 c-left : caption to left of image. Overides c-none or c-right, if more than one option given, as left takes precedence.
 351 
 352 c-none : ignore captions.
 353 
 354 c-right : caption to right of image. Overides c-none, if both options given, as right takes precedence over none.
 355 
 356 t-left : tables set left. Overides f-right, if both options given, as left takes precedence.
 357 
 358 t-right : tables set right.
 359 
 360 nnn% : requested width of table (including caption if set to left or right), where n is digits from 25 to 100. If outside this range, the default 50% is applied and no warning is given. If two or more width options are given, the first takes precedence and others are ignored (even if the first is invalid and the default widith applied).
 361 
 362 markup : shows the markup if you wish to re-use this with modification (assuming the default tabulation does not suit a specific purpose) or for debugging purposes.
 363 
 364 # : inserted at the beginning of the caption overrides caption inclusion and any associated padding. Inclusion of caption text is option and effectively acts as a comment. Overidding captions can result in uneven multiple row layout where rows have different number of images and/or overidden captions. Therefore, this feature in recommended only for single row layouts. Also, caption and padding cells are not generated, so the sum of the cell widths is less than the table width and the tables and remaining captions will increase in size proportionally. Values set by the nnn% argument therefore become nominal only.
 365 
 366 Defaults are caption and table centred, width 66%, one column (so no options for these are needed).
 367 
 368 Keywords can appear in any order, other than as indicated above for conflicting choices.
 369 
 370 Dependency
 371 
 372 The parser requires a macro RenderText.py to be installed in plugin/macros. This macro un-glues the inserted table's lines, renders the markup text and inserts it in the enclosing table cell.
 373 
 374 {{{
 375 from MoinMoin import wikiutil
 376 from MoinMoin.parser.text_moin_wiki import Parser as wiki
 377 def execute(macro, text):
 378      text = (text.replace('&&', '\n')).replace(')+>>', ')>>')
 379      return wikiutil.renderText(macro.request, wiki, text)
 380 }}}
 381 
 382 Usage
 383 
 384 {{{#!tables [c-2|c-3 ][c-left|c-none|c-right ][t-left|t-right ][nnn% ][markup ]
 385  table_page/file:: [#]caption
 386  table_page/file:: [#]caption
 387  ...
 388 }}}
 389 
 390 History
 391 
 392 Version 1.3 - 14.10.2012: included automatic anchor insertion
 393 Version 1.2 - 14.10.2012: included time dependency to properly handle Ref macro in captions
 394 Version 1.1 - 23.01.2011: escaped macro syntax; revised RenderText macro accordingly
 395 Version 1.0 - 22.01.2011: initial version
 396 
 397 Developed with inspiration and code from:
 398 
 399 figures.py parser - @copyright: 2011 Ian Riley
 400 keyval.py parser - @copyright: 2006 by Matt Cooper <macooper@vt.edu>
 401 sort.py parser - @copyright: 2005 ReimarBauer
 402 
 403 Copyright
 404 
 405 @copyright: 2012 Ian Riley <ian.riley@internode.on.net>
 406 
 407 License
 408 
 409 GNU GPL, see COPYING for details.
 410 '''
 411 
 412 import re
 413 from MoinMoin.action import AttachFile
 414 from MoinMoin.Page import Page
 415 from MoinMoin.parser import text_moin_wiki as wiki
 416 from MoinMoin import wikiutil
 417 
 418 Dependencies = ["time"] # for captions with <<Ref()>>, which uses <<FootNote()>>, so no caching
 419 
 420 class Parser:
 421     parsername = 'tables'
 422 
 423     def __init__(self, raw, request, **kw):
 424         self.raw = raw
 425         self.request = request
 426         self.form = request.form
 427         self._ = request.getText
 428         self.args = kw.get('format_args', '')
 429 
 430     def format(self, formatter):
 431         empty = u''
 432         eol = u'\n'
 433         rtn = u'\r'
 434         glue = u'&&'
 435         sep = u':: '
 436         sep_dir = u'/'
 437         space = u' '
 438         monospace = u'` `'
 439         macro_end = u')>>'
 440         macro_esc = u')+>>'
 441         ignore = u'#'
 442         comment = u'##'
 443         percent = u'%'
 444         brk = u'<<BR>>'
 445         parsing = (u"{{{", u"}}}", )
 446         anchor = u'<<Anchor(%(anchorname)s)>>'
 447         anchor_pattern = u'^(Table? \d+)'
 448         tab = u'||<tablestyle="width:100%; " '
 449         cell  = u'||<style="border:none; width:%(width)s%%; ">'
 450         cella  = u'||<%(align)s style="border:none; width:%(width)s%%; ">'
 451         padcell  = u'||<style="border:none; width:%(pad)s%%; ">'
 452         celli = u'||'
 453         cellf = u'||\n'
 454         tbl = u'<<RenderText(%(tbl)s)>>'
 455         cap = u'%(cap)s'
 456         capc = u'<<RenderText(||<tablestyle="width:100%%; " style="border:none; ">%(cap)s ||)>>'
 457         tfile = u'.txt'
 458         warning_msg =  u'||<style="color: #ff0000; font-weight: bold;">%s: %s||'
 459         options, tables, anchornames, rows, results = ([], [], [], [], [], )
 460         tbls, ignored, layout, padding = (0, 0, 0, 0, )
 461         left, centre, right, void = (0, 1, 2, 3, )
 462         top, mid, bot, ljust, cjust, rjust = (u'^', u'', u'v', u'(', u':', u')', )
 463         max_cols = 1
 464         std_width = 66
 465         min_widths = (0, 25, 25, 25, )
 466         max_widths = (0, 100, 50, 33, )
 467         aligns = (mid, top, mid, mid, ) # TODO consider making this a selectable option
 468         justs = (rjust, ljust, ljust, ljust, ) # leave centred (ie above) caption left justified
 469         # for captions (left, centre, right, none,)
 470         layouts = (cella+cap+cell+tbl, cell+capc+tbl, cell+tbl+cella+cap, cell+tbl, ) 
 471 
 472         #set defaults which might get changed
 473         cap_pos = centre
 474         tbl_pos = centre
 475         req_width = std_width
 476 
 477         # set options
 478         options = self.args.split(space)
 479         anchors = "anchors" in options
 480         if "c-none" in options:
 481             cap_pos = void
 482         if "c-right" in options:  # do second as right takes precedence
 483             cap_pos = right
 484         if "c-left" in options: # do last as left takes precedence
 485             cap_pos = left
 486         if "c-3" in options:
 487             max_cols = 3
 488         if "c-2" in options: # do second as single column takes precedence
 489             max_cols = 2
 490         if "t-right" in options:
 491             tbl_pos = right
 492         if "t-left" in options: # do second as left takes precedence
 493             tbl_pos = left
 494         markup = "markup" in options
 495         for option in options:
 496             if option.endswith(percent):
 497                 try:
 498                     req_width = int(option.rstrip(percent)) # will check this value later
 499                 except:
 500                     pass
 501                 break # do not look for any more width options
 502         del options
 503         # check requested width in range or set default
 504         if (req_width > max_widths[1]) or (req_width < min_widths[3]):
 505             req_width = std_width
 506         # dynamically set maximum columns depending on requested width
 507         while (max_cols > 1) and (req_width > max_widths[max_cols]):
 508             max_cols = max_cols - 1
 509         # calculate widths for captions (left, centre, right)
 510         widths = (int(req_width / 2), req_width, int(req_width / 2), req_width, )
 511 
 512         def get_attachment(request, page_name, source):
 513             if AttachFile.exists(request, page_name, source):
 514                 file_name = Page(request, page_name).getPagePath("attachments")
 515                 file_name = file_name+sep_dir+source
 516                 f = open(file_name,'r')
 517                 text = f.read()
 518                 f.close()
 519                 text = text.replace(rtn,empty)
 520                 if text == empty:
 521                     text = warning_msg % (source, 'attachment empty', )
 522             else:
 523                 text = warning_msg % (source, 'not found', )
 524             return text
 525 
 526         def get_content(source):
 527             content = []
 528             page_name = self.request.page.page_name
 529             abs_source = wikiutil.AbsPageName(page_name, source)
 530             # is there a page?
 531             if not Page(self.request, abs_source).isStandardPage(abs_source):
 532                 #try for an attachment instead
 533                 text = get_attachment(self.request, page_name, (source + tfile))
 534             else:
 535                 if self.request.user.may.read(abs_source):
 536                     content = Page(self.request, abs_source)
 537                     text = content.getPageText()
 538                     if (content is None) or (text == empty):
 539                         text = warning_msg % (source, 'page empty', )
 540                 else:
 541                     text = warning_msg % (source, 'access denied', )
 542             # crudely check that text conforms to table markup
 543             text = text.strip()
 544             lines = text.split(eol)
 545             text = empty
 546             for line in lines:
 547                 if line.startswith(comment):
 548                     continue
 549                 if (not line.startswith(celli)) or (not line.endswith(celli)):
 550                      text = warning_msg % (source, 'invalid table markup', )
 551                      break
 552                 text = text + line.strip() + glue
 553             text = text.rstrip(glue)
 554             text = text.replace(macro_end, macro_esc)
 555             return text
 556 
 557         def get_anchorname(val):
 558             match = None
 559             if anchors:
 560                 match = re.match(anchor_pattern, val.replace("'","")).group()
 561             return match
 562              
 563         # process the lines of text provided
 564         lines = self.raw.split(eol)
 565         for line in lines:
 566             if line:
 567                 # handle table lines
 568                 if (line[0] == space) and (sep in line):
 569                     key, val = (line.lstrip(space)).split(sep)
 570                     val = val.replace(macro_end, macro_esc)
 571                     tables.append((key, val, get_content(key)))
 572                     anchornames.insert(0, get_anchorname(val))
 573                     #if val.startswith(ignore): #TODO check if really not needed
 574                     #    ignored = ignored + 1
 575         del lines
 576 
 577         # construct a list of row column numbers
 578         tbls = len(tables)
 579         while tbls >= max_cols:
 580            rows.append(max_cols)
 581            tbls = tbls - max_cols
 582         if tbls > 0:
 583            rows.append(tbls)
 584 
 585         # construct output for columns in rows
 586         def calc_padding():
 587             table_width = int(100 / max_cols) * max_cols
 588             item_width = widths[cap_pos]
 589             if (cap_pos in (left, right, )): # offset caption so double for image + caption
 590                 item_width = item_width * 2
 591             if tbl_pos == centre: # centred so needs smaller interspersed padding
 592                 padding = int((table_width - (item_width * cols)) / (cols + 1))
 593             else: # not centred so wider padding
 594                 padding = int(table_width - (item_width * cols))
 595             return padding
 596 
 597         def add_padding(seq):
 598             yes_pad = False
 599             if padding == 0:
 600                 return ''
 601             if seq == 0:
 602                 yes_pad = (tbl_pos == right)
 603             elif seq == 1:
 604                 yes_pad = (tbl_pos == centre) and \
 605                           ((cap_pos in (centre, void, )) or \
 606                            (first_col) or \
 607                            ((cap_pos == left) and (layout != void)))
 608             elif seq == 2:
 609                 yes_pad = (tbl_pos == centre) and \
 610                           ((cols == 1) or \
 611                            ((cap_pos == right) and (layout != void)))
 612             elif seq == 3:
 613                 yes_pad = (tbl_pos == left)
 614 
 615             if yes_pad:
 616                 return (padcell % {'pad': padding})
 617             else:
 618                 return ''
 619 
 620         for cols in rows:
 621             first_col = True
 622             pending = ''
 623             padding = calc_padding()
 624             pending = pending + add_padding(0)
 625             while cols > 0:
 626                 table = tables.pop(0)
 627                 if table[1].startswith(ignore):
 628                     layout = void
 629                 else:
 630                     layout = cap_pos
 631                 pending = pending + add_padding(1)
 632                 pending = pending + \
 633                          (layouts[layout] % {'align': aligns[cap_pos]+justs[cap_pos], \
 634                                              'width': widths[cap_pos], \
 635                                              'tbl': table[2], \
 636                                              'cap': table[1]})
 637                 pending = pending + add_padding(2)
 638                 cols = cols - 1
 639                 first_col = False
 640             pending = pending + add_padding(3)
 641             pending = tab + pending[3:] + cellf # insert tablestyle and close table
 642             results.append(pending)
 643 
 644         #insert anchors if requested
 645         if anchors:
 646             names = [a for a in anchornames if a != None]
 647             if names:
 648                 pending = ''
 649                 for name in names:
 650                     pending += (anchor % {'anchorname': name, })
 651                 results.insert(0, pending)
 652 
 653         del rows, tables
 654 
 655         # escape markup if requested
 656         if markup:
 657             results.insert(0, parsing[0])
 658             results.append(parsing[1])
 659 
 660         wikiizer = wiki.Parser(eol.join(results), self.request)
 661         wikiizer.format(formatter, inhibit_p=True)

You are not allowed to attach a file to this page.