Attachment 'Gallery2-1.3.3-5.py'

Download

   1 # -*- coding: iso-8859-1 -*-
   2 """
   3     MoinMoin - Gallery2 parser
   4 
   5     PURPOSE:
   6         This parser is used to visualize a couple of images as a thumbnail gallery.
   7 	Optional a description of an image could be added including WikiName.
   8 	On default the image name and it's creation date is shown.
   9 
  10     CALLING SEQUENCE:
  11       {{{
  12       #!Gallery2 [columns=columns],[filter=filter],[mode=mode],[show_text=show_text],
  13                  [show_date=show_date], [show_tools=show_tools],
  14                  [sort_by_name=sort_by_name],[sort_by_date=sort_by_date]
  15                  [only_items=only_items],[template_itemlist=template_itemlist],
  16                  [border_thick=border_thick],[renew=renew]
  17       * [image1.jpg alias]
  18       * [image2.jpg alias]
  19       }}}
  20 
  21     KEYWORD PARAMETERS:
  22         columns:           number of columns for thumbnails
  23 	filter:            regex to select images
  24         show_text:         default is 1 description is shown
  25 	                   any other means no description
  26 	show_date:         default is 1 date info from exif header if available is shown
  27 	sort_by_name:      default is 1, the images are sorted by name, but not if only_items is 1
  28 	sort_by_date:      default is 0, the images are sorted to the modification time
  29 	reverse_sort:      default is 0, if set to 1 the file list is reversed
  30                            any other means no description
  31 	show_tools:        default is 1 icon toolbar is show any other disables this
  32 	mode:              default is 1 this means description below the image
  33 	                   any other number means description right of image
  34 	only_items:        default is 0 if it is set to 1 only images which are described in listitem are shown
  35 	                   dependend on the order of the items
  36 	template_itemlist: default is 0, if set to 1 an item list is shown which could be copied into the script. 
  37 	border_thick:      default is 1 this is the thickness in pixeln of the outer frame
  38 	renew:             default is 0 if set to 1 then all selected thumbnails_* and webnails_* removed.
  39 	                   Afterwards they are new created.
  40         help:              default is 0 if set a copy of the CALLING SEQUENCE is shown, 
  41 	                   (there are some new ideas around to show help to an user so this will be later replaced)
  42 
  43     OPTIONAL INPUTS:
  44 	itemlist : if it is used and only_items is 1 then only the images in this list are ahown.
  45 	           The alias text is used as description of the image instead of the file name
  46 
  47 
  48     EXAMPLE:
  49 = GalleryTest =
  50 
  51 == all images shown, one is decribed ==
  52 {{{
  53 { { {
  54 #!Gallery2
  55 * [100_1185.JPG Bremen, SpaceCenter]
  56 } } }
  57 }}}
  58 
  59 Result: [[BR]]
  60  {{{
  61 #!Gallery2
  62 * [100_1185.JPG Bremen, SpaceCenter]
  63 }}}
  64 
  65 == only thumbnails and only_items ==
  66 {{{
  67 { { {
  68 #!Gallery2 show_text=0,show_tools=0,show_date=0,columns=2,only_items=1
  69  * [100_1185.JPG Bremen, SpaceCenter]
  70  * [100_1194.JPG Bremen]
  71 } } }
  72 }}}
  73 
  74 Result: [[BR]]
  75  {{{
  76 #!Gallery2 show_text=0,show_tools=0,show_date=0,columns=2,only_items=1
  77  * [100_1185.JPG Bremen, SpaceCenter]
  78  * [100_1194.JPG Bremen]
  79 }}}
  80 
  81 == only_items by two columns and text right ==
  82 
  83 {{{
  84 { { {
  85 #!Gallery2 mode=2,columns=2,only_items=1
  86  * [100_1185.JPG Bremen, SpaceCenter]
  87  * [100_1194.JPG Bremen]
  88 } } }
  89 }}}
  90 
  91 Result: [[BR]]
  92  {{{
  93 #!Gallery2 mode=2,columns=2,only_items=1
  94  * [100_1185.JPG Bremen, SpaceCenter]
  95  * [100_1194.JPG Bremen, behind SpaceCenter]
  96 }}}
  97 
  98 ----
  99 
 100 == only_items by two columns, date supressed ==
 101 
 102 {{{
 103 { { {
 104 #!Gallery2 columns=2,only_items=1,show_date=0
 105  * [100_1185.JPG Bremen, SpaceCenter]
 106  * [100_1194.JPG Bremen, behind SpaceCenter]
 107 } } }
 108 }}}
 109 
 110 Result: [[BR]]
 111  {{{
 112 #!Gallery2 columns=2,only_items=1,show_date=0
 113  * [100_1185.JPG Bremen, SpaceCenter]
 114  * [100_1194.JPG Bremen, behind SpaceCenter]
 115 }}}
 116 
 117 
 118 == filter regex used, mode 2, icons and date supressed, one column and border_thick=5 ==
 119 {{{
 120 { { {
 121 #!Gallery2 columns=1,filter=100_118[0-5],mode=2,show_date=0,show_tools=0,border_thick=5
 122 } } }
 123 }}}
 124 
 125 Result: [[BR]]
 126  {{{
 127 #!Gallery2 columns=1,filter=100_118[0-7],mode=2,show_date=0,show_tools=0,border_thick=5
 128 }}}
 129 
 130 == other macro calls ==
 131 {{{
 132 { { {
 133 #!Gallery2 only_items=1,show_date=0
 134  * [100_1189.JPG [[MiniPage(||Bremen||SpaceCenter||\n|| ||SpaceJump||)]]]
 135 } } }
 136 }}}
 137 
 138 Result: [[BR]]
 139  {{{
 140 #!Gallery2 only_items=1,show_date=0
 141  * [100_1189.JPG [[MiniPage(||Bremen||SpaceCenter||\n|| ||SpaceJump||)]]]
 142 }}}
 143 
 144 == renew means always new thumbnails and webnails of selection ==
 145 {{{
 146 { { {
 147 #!Gallery2 only_items=1,show_date=0,show_tools=0,renew=1
 148  * [100_1189.JPG [[MiniPage(||["Bremen"]||SpaceCenter||\n|| ||SpaceJump||)]]]
 149 } } }
 150 }}}
 151 
 152 Result: [[BR]]
 153  {{{
 154 #!Gallery2 only_items=1,show_date=0,renew=1
 155  * [100_1189.JPG [[MiniPage(||["Bremen"]||SpaceCenter||\n|| ||SpaceJump||)]]]
 156 }}}
 157 
 158 
 159 
 160     PROCEDURE:
 161       Download some images to a page and start with the examples.
 162       Aliasing of the filenames are done by adding an itemlist, see example.
 163 
 164       This routine requires the PIL (Python Imaging Library).
 165       And the EXIF routine from http://home.cfl.rr.com/genecash/digital_camera.html
 166 
 167 
 168       At the moment I have added the EXIF routine to the parsers dir.
 169       It's not the best place but during developing it is nice to have it there
 170       If you put it to another place you have to change the line
 171       from MoinMoin.parser import EXIF too.
 172 
 173       This routine requires the Action macro gallery2Image which is used to rotate or delete a selected image.
 174       Only users which have the rights to delete are able to execute this action macro.
 175       The icons of these are only shown if you have enough rights.
 176 
 177       The gallery2image macro does not take care on the EXIF header. This is lost by rotating.
 178       If a file is deleted by this macro it is moved to a bak file.
 179 
 180       Please remove the Version number from the code!
 181 
 182     RESTRICTIONS:
 183       The slideshow is not implemented at the moment. The implementation will be done in the acrion macro.
 184       This is not a quite big problem normally files with an EXIF header are right rotated.
 185 
 186     Required Images:
 187       I have put them to wiki/modern/img/ dir. The icons were created by me. License: GPL
 188 
 189     attachment:to_bak.png
 190     attachment:to_left.png
 191     attachment:to_right.png
 192     attachment:to_slide.png
 193     attachment:to_full.png
 194 
 195     HISTORY:
 196     While recognizing how to write MiniPage I got the idea to write a Gallery Parser.
 197     We have used in our wikis in the past the Gallery macro of SimonRyan.
 198     I have tried to modify it a bit to change it for 1.3 but my python skills weren't enough
 199     or it was easier to write it completly new.
 200     So this one shows now a way how a Gallery could be used by the parser and an action Macro.
 201     Probably it is a good example for others who like to know how to do this
 202 
 203     MODIFICATION HISTORY:
 204         Version 1.3.3.-1
 205         @copyright: 2005 by Reimar Bauer (R.Bauer@fz-juelich.de)
 206         @license: GNU GPL, see COPYING for details.
 207 	2005-03-26: Version 1.3.3-2 keyword renew added
 208 	            creation of thumnails and webnails in two calls splitted
 209                     Version 1.3.3-3 bug fixed if itemlist is given to describe only some of the images
 210 		                    but only_items is not set to 1
 211 				    Example code changed
 212         2005-03-27: Version 1.3.3-4 Action macro added and the form to call it. User which have rights to delete
 213                                     could use the functions of gallery2Image.
 214         2005-08-03: Version 1.3.3-5 theme path for icons corrected and a platform independent path joining
 215 	                            os.unlink removed as suggested by CraigJohnson
 216 	                            sort_by_name is default if not only_items is 1
 217                                     optional sort_by_date could be used
 218                                     keyword template_itemlist added 
 219                                     keyword help added
 220                                     extra frame by mode=2 removed 
 221 				    
 222     
 223 
 224 """
 225 Dependencies = []
 226 from MoinMoin.action import AttachFile
 227 from MoinMoin import wikiutil, config
 228 from MoinMoin.Page import Page
 229 import os,string,re,Image,StringIO
 230 from MoinMoin.parser import EXIF
 231 
 232 from MoinMoin.parser import wiki
 233 
 234 #def ImageProcess(var):
 235 #    f=open('/tmp/workfile.txt', 'w')
 236 #    f.write(var)
 237 #    f.close()
 238 
 239 def get_quotes(self,formatter):
 240     quotes = self.raw.split('\n')
 241     quotes = [quote.strip() for quote in quotes]
 242     quotes = [quote[2:] for quote in quotes if quote.startswith('* ')]
 243 
 244     image=[]
 245     alias=[]
 246     for line in quotes:
 247         im,na=line[1:-1].split(' ',1)
 248 
 249         ##taken from MiniPage
 250 
 251         out=StringIO.StringIO()
 252         self.request.redirect(out)
 253         wikiizer = wiki.Parser(na.strip(),self.request)
 254         wikiizer.format(formatter)
 255         na=out.getvalue()
 256         self.request.redirect()
 257         del out
 258 
 259         alias.append(na)
 260         image.append(im.strip())
 261 
 262     result={}
 263     result['alias']=alias
 264     result['image']=image
 265 
 266     return(result)
 267 
 268 
 269 
 270 class Parser:
 271     def __init__(self, raw, request, **kw):
 272         self.raw = raw
 273         self.request = request
 274         self.form = request.form
 275         self._ = request.getText
 276         self.kw = {}
 277         self.kw['sort_by_date']='0' # nor implemented at the moment
 278         self.kw['sort_by_name']='1' 
 279         self.kw['template_itemlist']='0' 
 280         self.kw['reverse_sort']='0'
 281         self.kw['border_thick']='1'
 282         self.kw['columns']='4'
 283         self.kw['filter']='.'
 284         self.kw['mode']='1'
 285 	self.kw['help']='0'
 286         self.kw['show_text']='1'
 287         self.kw['show_date']='1'
 288         self.kw['show_tools']='1'
 289         self.kw['only_items']='0'
 290         self.kw['renew']='0'
 291         self.kw['thumbnail_width']='128'
 292         self.kw['webnail_width']='640'
 293         self.kw['text_width']='140'
 294 
 295 
 296         for arg in kw.get('format_args','').split(','):
 297 
 298             if (arg.find('=') > -1):
 299                key=arg.split('=')
 300                self.kw[str(key[0])]=wikiutil.escape(string.join(key[1],''), quote=1)
 301 
 302         self.kw['width']=str((int(self.kw['thumbnail_width'])+int(self.kw['text_width'])))
 303 
 304 
 305     def format(self, formatter):
 306         
 307         kw=self.kw
 308         Dict = {}
 309         quotes=get_quotes(self,formatter)
 310 
 311         current_pagename=formatter.page.page_name
 312         attachment_path = AttachFile.getAttachDir(self.request,current_pagename,create=1)
 313 
 314         if (kw['help'] == '1'):
 315 
 316 	    self.request.write('<BR>')
 317 	    self.request.write('{{{<BR>')
 318             self.request.write('#!Gallery2 [columns=columns],[filter=filter],[mode=mode],[show_text=show_text],<BR>')
 319             self.request.write('           [show_date=show_date], [show_tools=show_tools],<BR>')
 320             self.request.write('           [sort_by_name=sort_by_name],[sort_by_date=sort_by_date],<BR>')
 321             self.request.write('           [only_items=only_items],[template_itemlist=template_itemlist],<BR>')
 322             self.request.write('           [border_thick=border_thick],[renew=renew],[help=help]<BR>')
 323             self.request.write(' * [image1.jpg alias]<BR>')
 324             self.request.write(' * [image2.jpg alias]<BR>')
 325             self.request.write('}}}<BR>')
 326 	    return    
 327 	
 328         if (kw['only_items'] == '1'):
 329             all_files=quotes['image']
 330         else:
 331             all_files=os.listdir(attachment_path)
 332 
 333         result=[]
 334 
 335         for test in all_files:
 336            if re.match(kw['filter'], test):
 337               result.append(test)
 338 
 339         all_files=result
 340 	
 341         if (len(all_files) == 0):
 342             self.request.write("<BR><BR><H1>No matching image file found!</H1>")
 343             return
 344 	
 345         if ((kw['sort_by_name']=='1') and (kw['only_items'] == '0')): 
 346             all_files.sort()
 347           
 348         if (kw['sort_by_date']=='1'): 
 349            
 350            for attfile in all_files:
 351                infile=os.path.join(attachment_path,attfile)
 352                ft_file=str(os.path.getmtime(infile))+os.tmpnam()
 353                Dict[ft_file]=attfile
 354        
 355            file_mdate=[]
 356            keys = Dict.keys()
 357            keys.sort()
 358            for txt in keys:
 359                file_mdate.append(Dict[txt])
 360 
 361            all_files=file_mdate
 362          
 363         if (kw['reverse_sort']=='1'): 
 364              all_files.reverse()   
 365 
 366  
 367         cells=[]
 368         big={}
 369         medium={}
 370         small={}
 371         cell_name=[]
 372         exif_date=[]
 373 	
 374         big_image_url=[]
 375 
 376 	img=[]
 377 
 378         valid_img=0
 379         if (kw['template_itemlist'] == '1'):
 380            self.request.write('Copy the following listitems into the script. Replace alias with the label you want. Afterwards disable template_itemlist by setting it to 0:<BR>')
 381         for attfile in all_files:
 382              # only files not thumb or webnails
 383             if ((string.find(string.join(attfile,''),'thumbnail_') == -1) and (string.find(string.join(attfile,''),'webnail_') == -1)) :
 384                 # only images
 385                 if wikiutil.isPicture(attfile):
 386 
 387                     file, ext = os.path.splitext(attfile)
 388 
 389                     if (ext == '.gif') or (ext == '.png'):
 390                         img_type='PNG'
 391                         thumbfile='thumbnail_'+file+".png"
 392                         webnail='webnail_'+file+".png"
 393                     else:
 394                         img_type="JPEG"
 395                         thumbfile='thumbnail_'+file+".jpg"
 396                         webnail='webnail_'+file+".jpg"
 397 
 398 
 399                     infile=os.path.join(attachment_path,attfile)
 400                     # wikiutil.isPicture checks only the filename if it could be a picture
 401                     # it does not require to exist
 402                     if os.path.exists(infile):
 403                         img.append(attfile)
 404 			
 405                         f=open(infile, 'rb')
 406 			
 407                         tags=EXIF.process_file(f)
 408 
 409                         if tags.has_key('EXIF DateTimeOriginal'):
 410                              date=str(tags['EXIF DateTimeOriginal'])
 411                              date=string.replace(date,':','-',2)
 412                              exif_date.append(date)
 413                         else:
 414                              date='--'
 415                              exif_date.append(date)
 416 			    
 417 
 418                         f.close()
 419                         if (kw['template_itemlist'] == '1'):
 420                             self.request.write(' * [%(attfile)s %(date)s]<BR>' % {
 421                                'attfile' : attfile,
 422                                'date'    : 'alias'
 423 			    })
 424 
 425                         thumb=os.path.join(attachment_path,thumbfile)
 426                         webf=os.path.join(attachment_path,webnail)
 427 
 428                         if (kw['renew'] == '1'):
 429                            if os.path.exists(thumb):
 430                               os.unlink(thumb)
 431                            if os.path.exists(webf):
 432                               os.unlink(webf)
 433 
 434                         valid_img=valid_img+1
 435 
 436                         im = Image.open(infile)
 437                         if not os.path.exists(webf):
 438                             im.thumbnail(((int(kw['webnail_width'])),((int(kw['webnail_width'])))), Image.ANTIALIAS)
 439                             im.save(webf, img_type)
 440 
 441                         if not os.path.exists(thumb):
 442                             im.thumbnail(((int(kw['thumbnail_width'])),((int(kw['thumbnail_width'])))),
 443                                          Image.ANTIALIAS)
 444                             im.save(thumb, img_type)
 445 
 446 
 447 
 448                         big_image_url.append(AttachFile.getAttachUrl(current_pagename,
 449                                     attfile,self.request))
 450                         medium['src']=AttachFile.getAttachUrl(current_pagename,webnail,self.request)
 451 
 452                         small['title']=attfile
 453                         small['alt']=attfile
 454                         small['src']=AttachFile.getAttachUrl(current_pagename,thumbfile,self.request)
 455 
 456 
 457                         image_link=formatter.image(**small)
 458                     # collect images
 459                         cells.append(formatter.url(1,medium['src'] )+image_link+formatter.url(0))
 460                         cell_name.append(attfile)
 461 
 462 
 463         ##over all images
 464         n=len(cells)
 465         cols=int(kw['columns'])
 466 
 467         rows=n/cols
 468         first=0
 469         result=[]
 470         if (valid_img == 0):
 471            result.append('Image not found')
 472 
 473         #if (valid_img > 1):
 474         result.append('<table border="'+kw['border_thick']+'" valign="bottom">')
 475 
 476         z=1
 477         i=0
 478 
 479         ############################################
 480         ##TODO: syntax change to formatter - later #
 481         ############################################
 482 
 483         # fixed width because of better visualisation on different browsers
 484         for line in cells:
 485             if (z == 1):
 486                if (cols > 1) and (n > 1):
 487                   if (kw['mode']=='1'):
 488                      result.append('<td width="'+kw['thumbnail_width']+'" >')
 489                      #result.append(formatter.table_cell(1))
 490                   else:
 491                       result.append('<td width="'+kw['width']+'" >')
 492             if n > 1 and cols > 1:
 493                result.append('<table border="1" valign="center">')
 494 
 495             result.append('<TR valign="center">')
 496             # image align center
 497             result.append('<td align="center" valign="center" width="'+kw['thumbnail_width']+'">')
 498             result.append(line)
 499             result.append(formatter.table_cell(0))
 500 
 501             if (kw['show_text']=='1'):
 502                 if (kw['mode']=='1'):
 503                   result.append(formatter.table_row(0))
 504                   result.append(formatter.table_row(1))
 505                   # text aligned left in mode 1
 506                   result.append('<td align="left" width="'+kw['thumbnail_width']+'" >')
 507                 else:
 508                      # text aligned on top in mode 2
 509                     result.append('<td valign="top" width="'+kw['text_width']+'" >')
 510 
 511                 i_quote=0
 512                 found=0
 513                 for text in quotes['image'] :
 514                     if (text == cell_name[i]):
 515                         result.append(quotes['alias'][i_quote])
 516                         found=1
 517                     i_quote=i_quote+1
 518 
 519                 if (found == 0):
 520                     result.append(cell_name[i])
 521 
 522                 result.append(formatter.table_cell(0))
 523                 if (kw['mode']=='1'):
 524                     result.append(formatter.table_row(0))
 525 
 526 
 527             if (kw['show_date']=='1'):
 528                 if (kw['mode']=='1'):
 529                     result.append(formatter.table_row(1))
 530                     result.append(formatter.table_cell(1))
 531                     result.append(exif_date[i])
 532                     result.append(formatter.table_cell(0))
 533                     result.append(formatter.table_row(0))
 534 
 535             if (kw['show_tools'] == '1'):
 536                result.append(formatter.table_row(1))
 537                # tool bar centriert
 538                result.append('<td align="center">')
 539                result.append('<TABLE align="center">')
 540                result.append('<TR><td>')
 541                result.append('<FORM><TT>')
 542 
 543                result.append('<input type="hidden" name="action" value="AttachFile">')
 544                result.append('<input type="hidden" name="do" value=get>')
 545                result.append('<input type="hidden" name="target" value='+img[i]+'>')
 546                result.append('<input type="image" value="submit" src="/wiki/modern/img/to_full.png" title="load image">')
 547                result.append('</TT></FONT></FORM>')
 548                result.append('</td><td>')
 549                result.append('<form action="%(baseurl)s/%(pagename)s" method="POST" enctype="multipart/form-data"><TT>' % {
 550                              'baseurl': self.request.getScriptname(),
 551                              'pagename': wikiutil.quoteWikinameURL(current_pagename)})
 552 
 553                result.append('<input type="hidden" name="action" value="gallery2image">')
 554                result.append('<input type="hidden" name="do" value=PS>')
 555                result.append('<input type="hidden" name="target" value='+string.join(img,',')+'>')
 556                result.append('<input type="image" value="submit" src="/wiki/modern/img/to_slide.png" title="slide_show">')
 557                result.append('</TT></FONT></FORM>')
 558                result.append('</td>')
 559 
 560                if self.request.user.may.delete(current_pagename):
 561                    result.append('<td>')
 562 
 563                    result.append('<form action="%(baseurl)s/%(pagename)s" method="POST" enctype="multipart/form-data"><TT>' % {
 564                                  'baseurl': self.request.getScriptname(),
 565                                  'pagename': wikiutil.quoteWikinameURL(current_pagename)})
 566 
 567                    result.append('<input type="hidden" name="action" value="gallery2image">')
 568                    result.append('<input type="hidden" name="do" value=RL>')
 569                    result.append('<input type="hidden" name="target" value='+img[i]+'>')
 570                    result.append('<input type="image" value="submit" src="/wiki/modern/img/to_left.png" title="rotate to left">')
 571                    result.append('</TT></FONT></FORM>')
 572                    result.append('</td><td>')
 573                    result.append('<form action="%(baseurl)s/%(pagename)s" method="POST" enctype="multipart/form-data"><TT>' % {
 574                                 'baseurl': self.request.getScriptname(),
 575                                 'pagename': wikiutil.quoteWikinameURL(current_pagename)})
 576 
 577                    result.append('<input type="hidden" name="action" value="gallery2image">')
 578                    result.append('<input type="hidden" name="do" value=RR>')
 579                    result.append('<input type="hidden" name="target" value='+img[i]+'>')
 580                    result.append('<input type="image"  value="submit" src="/wiki/modern/img/to_right.png" title="rotate to right">')
 581 
 582                    result.append('</TT></FONT></FORM>')
 583                    result.append('</td><td>')
 584                    result.append('<form action="%(baseurl)s/%(pagename)s" method="POST" enctype="multipart/form-data"><TT>' % {
 585                                 'baseurl': self.request.getScriptname(),
 586                                 'pagename': wikiutil.quoteWikinameURL(current_pagename)})
 587 
 588                    result.append('<input type="hidden" name="action" value="gallery2image">')
 589                    result.append('<input type="hidden" name="do" value=RM>')
 590                    result.append('<input type="hidden" name="target" value='+img[i]+'>')
 591                    result.append('<input type="image" value="submit" src="/wiki/modern/img/to_bak.png" title="move to bak">')
 592                    result.append('</TT></FONT></FORM>')
 593                    result.append('</TD>')
 594                result.append('</TR>')
 595                result.append('</TABLE>')
 596 
 597             result.append(formatter.table_cell(0))
 598             if (kw['show_date']=='1'):
 599                 if not (kw['mode']=='1'):
 600                     result.append(formatter.table_cell(1))
 601                     result.append(exif_date[i])
 602                     result.append(formatter.table_cell(0))
 603             if (kw['show_tools'] == '1'):
 604                result.append(formatter.table_row(0))
 605             if n > 1 and cols > 1:
 606                result.append(formatter.table(0))
 607             if ((z != cols) and (i < n-1)):
 608                 result.append(formatter.table_cell(1))
 609             if (z == cols):
 610                 result.append(formatter.table_cell(0))
 611                 result.append(formatter.table_row(0))
 612             z=z+1
 613             i=i+1
 614             if (z > cols):
 615                z=1
 616 
 617         result.append(formatter.table(0))
 618         ##Output
 619         self.request.write(string.join(result,''))
 620         
 621         return()

Attached Files

To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.
  • [get | view] (2006-08-06 08:57:54, 41.8 KB) [[attachment:EXIF.py]]
  • [get | view] (2005-03-24 20:14:37, 10.6 KB) [[attachment:Gallery2-1.3.3-1.py]]
  • [get | view] (2005-03-26 08:39:13, 11.6 KB) [[attachment:Gallery2-1.3.3-2.py]]
  • [get | view] (2005-03-26 12:41:49, 13.1 KB) [[attachment:Gallery2-1.3.3-3.py]]
  • [get | view] (2005-03-27 20:23:01, 19.0 KB) [[attachment:Gallery2-1.3.3-4.py]]
  • [get | view] (2005-08-03 19:30:10, 23.2 KB) [[attachment:Gallery2-1.3.3-5.py]]
  • [get | view] (2005-08-18 07:58:38, 31.9 KB) [[attachment:Gallery2-1.3.5-10.py]]
  • [get | view] (2005-09-02 19:55:13, 34.1 KB) [[attachment:Gallery2-1.3.5-11.py]]
  • [get | view] (2005-11-13 18:09:11, 35.4 KB) [[attachment:Gallery2-1.3.5-12.py]]
  • [get | view] (2005-11-18 20:13:04, 46.2 KB) [[attachment:Gallery2-1.3.5-13.py]]
  • [get | view] (2005-12-03 15:33:06, 46.6 KB) [[attachment:Gallery2-1.3.5-14.py]]
  • [get | view] (2006-01-01 09:20:19, 43.3 KB) [[attachment:Gallery2-1.3.5-15.py]]
  • [get | view] (2005-08-07 15:46:28, 26.9 KB) [[attachment:Gallery2-1.3.5-6.py]]
  • [get | view] (2005-08-13 15:13:59, 28.7 KB) [[attachment:Gallery2-1.3.5-7.py]]
  • [get | view] (2005-08-14 13:02:00, 27.5 KB) [[attachment:Gallery2-1.3.5-8.py]]
  • [get | view] (2005-08-14 14:38:32, 28.7 KB) [[attachment:Gallery2-1.3.5-9.py]]
  • [get | view] (2006-08-06 08:45:47, 41.8 KB) [[attachment:Gallery2-1.5.4-16.py]]
  • [get | view] (2006-08-22 20:29:39, 42.0 KB) [[attachment:Gallery2-1.5.4-18.py]]
  • [get | view] (2006-08-06 08:57:36, 514.8 KB) [[attachment:example.swf]]
  • [get | view] (2005-08-17 18:10:27, 11.3 KB) [[attachment:gallery2image_test.py]]
  • [get | view] (2005-08-10 16:49:16, 1.3 KB) [[attachment:patchpullfromdir.diff]]
  • [get | view] (2006-08-17 16:32:50, 41.9 KB) [[attachment:text_x_gallery2-1.6.0-17.py]]
  • [get | view] (2006-08-22 20:23:06, 42.1 KB) [[attachment:text_x_gallery2-1.6.0-18.py]]
  • [get | view] (2008-02-06 10:08:05, 42.2 KB) [[attachment:text_x_gallery2-1.6.0-19.py]]
 All files | Selected Files: delete move to page copy to page

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