1""" 2Parser for PythonPoint using the xmllib.py in the standard Python 3distribution. Slow, but always present. We intend to add new parsers 4as Python 2.x and the XML package spread in popularity and stabilise. 5 6The parser has a getPresentation method; it is called from 7pythonpoint.py. 8""" 9 10import string, imp, sys, os, copy 11from reportlab.lib.utils import isSeq, uniChr, isPy3 12from reportlab.lib import colors 13from reportlab.lib.enums import TA_LEFT, TA_RIGHT, TA_CENTER, TA_JUSTIFY 14from reportlab.lib.utils import recursiveImport 15from reportlab.platypus.paraparser import HTMLParser, known_entities 16from tools.pythonpoint import pythonpoint 17from reportlab.platypus import figures 18from reportlab.lib.utils import asNative 19 20 21def getModule(modulename,fromPath='tools.pythonpoint.styles'): 22 """Get a module containing style declarations. 23 24 Search order is: 25 tools/pythonpoint/ 26 tools/pythonpoint/styles/ 27 ./ 28 """ 29 30 try: 31 exec('from tools.pythonpoint import '+modulename) 32 return eval(modulename) 33 except ImportError: 34 try: 35 exec('from tools.pythonpoint.styles import '+modulename) 36 return eval(modulename) 37 except ImportError: 38 exec('import '+modulename) 39 return eval(modulename) 40 41 42class PPMLParser(HTMLParser): 43 attributes = { 44 #this defines the available attributes for all objects, 45 #and their default values. Although these don't have to 46 #be strings, the ones parsed from the XML do, so 47 #everything is a quoted string and the parser has to 48 #convert these to numbers where appropriate. 49 'stylesheet': { 50 'path':'None', 51 'module':'None', 52 'function':'getParagraphStyles' 53 }, 54 'frame': { 55 'x':'0', 56 'y':'0', 57 'width':'0', 58 'height':'0', 59 'border':'false', 60 'leftmargin':'0', #this is ignored 61 'topmargin':'0', #this is ignored 62 'rightmargin':'0', #this is ignored 63 'bottommargin':'0', #this is ignored 64 }, 65 'slide': { 66 'id':'None', 67 'title':'None', 68 'effectname':'None', # Split, Blinds, Box, Wipe, Dissolve, Glitter 69 'effectdirection':'0', # 0,90,180,270 70 'effectdimension':'H', # H or V - horizontal or vertical 71 'effectmotion':'I', # Inwards or Outwards 72 'effectduration':'1', #seconds, 73 'outlineentry':'None', 74 'outlinelevel':'0' # 1 is a child, 2 is a grandchild etc. 75 }, 76 'para': { 77 'style':'Normal', 78 'bullettext':'', 79 'effectname':'None', 80 'effectdirection':'0', 81 'effectdimension':'H', 82 'effectmotion':'I', 83 'effectduration':'1' 84 }, 85 'image': { 86 'filename':'', 87 'width':'None', 88 'height':'None', 89 'effectname':'None', 90 'effectdirection':'0', 91 'effectdimension':'H', 92 'effectmotion':'I', 93 'effectduration':'1' 94 }, 95 'table': { 96 'widths':'None', 97 'heights':'None', 98 'fieldDelim':',', 99 'rowDelim':'\n', 100 'style':'None', 101 'effectname':'None', 102 'effectdirection':'0', 103 'effectdimension':'H', 104 'effectmotion':'I', 105 'effectduration':'1' 106 }, 107 'rectangle': { 108 'x':'0', 109 'y':'0', 110 'width':'100', 111 'height':'100', 112 'fill':'None', 113 'stroke':'(0,0,0)', 114 'linewidth':'0', 115 'effectname':'None', 116 'effectdirection':'0', 117 'effectdimension':'H', 118 'effectmotion':'I', 119 'effectduration':'1' 120 }, 121 'roundrect': { 122 'x':'0', 123 'y':'0', 124 'width':'100', 125 'height':'100', 126 'radius':'6', 127 'fill':'None', 128 'stroke':'(0,0,0)', 129 'linewidth':'0', 130 'effectname':'None', 131 'effectdirection':'0', 132 'effectdimension':'H', 133 'effectmotion':'I', 134 'effectduration':'1' 135 }, 136 'line': { 137 'x1':'0', 138 'y1':'0', 139 'x2':'100', 140 'y2':'100', 141 'stroke':'(0,0,0)', 142 'width':'0', 143 'effectname':'None', 144 'effectdirection':'0', 145 'effectdimension':'H', 146 'effectmotion':'I', 147 'effectduration':'1' 148 }, 149 'ellipse': { 150 'x1':'0', 151 'y1':'0', 152 'x2':'100', 153 'y2':'100', 154 'stroke':'(0,0,0)', 155 'fill':'None', 156 'linewidth':'0', 157 'effectname':'None', 158 'effectdirection':'0', 159 'effectdimension':'H', 160 'effectmotion':'I', 161 'effectduration':'1' 162 }, 163 'polygon': { 164 'points':'(0,0),(50,0),(25,25)', 165 'stroke':'(0,0,0)', 166 'linewidth':'0', 167 'stroke':'(0,0,0)', 168 'fill':'None', 169 'effectname':'None', 170 'effectdirection':'0', 171 'effectdimension':'H', 172 'effectmotion':'I', 173 'effectduration':'1' 174 }, 175 'string':{ 176 'x':'0', 177 'y':'0', 178 'color':'(0,0,0)', 179 'font':'Times-Roman', 180 'size':'12', 181 'align':'left', 182 'effectname':'None', 183 'effectdirection':'0', 184 'effectdimension':'H', 185 'effectmotion':'I', 186 'effectduration':'1' 187 }, 188 'customshape':{ 189 'path':'None', 190 'module':'None', 191 'class':'None', 192 'initargs':'None' 193 } 194 } 195 196 def __init__(self,verbose=0, caseSensitive=0, ignoreUnknownTags=1): 197 self.caseSensitive = caseSensitive 198 self.ignoreUnknownTags = ignoreUnknownTags 199 self.presentations = [] 200 #yes, I know a generic stack would be easier... 201 #still, testing if we are 'in' something gives 202 #a degree of validation. 203 self._curPres = None 204 self._curSection = None 205 self._curSlide = None 206 self._curFrame = None 207 self._curPara = None #the only places we are interested in 208 self._curPrefmt = None 209 self._curPyCode = None 210 self._curString = None 211 self._curTable = None 212 self._curTitle = None 213 self._curAuthor = None 214 self._curSubject = None 215 self.fx = 1 216 HTMLParser.__init__(self) 217 if not isPy3: 218 try: 219 self.parser.returnUnicode = False 220 except: 221 pass 222 223 def _arg(self,tag,args,name): 224 "What's this for???" 225 if name in args: 226 v = args[name] 227 else: 228 if tag in self.attributes: 229 v = self.attributes[tag][name] 230 else: 231 v = None 232 return v 233 234 def ceval(self,tag,args,name): 235 if name in args: 236 v = args[name] 237 else: 238 if tag in self.attributes: 239 v = self.attributes[tag][name] 240 else: 241 return None 242 243 # handle named colors (names from reportlab.lib.colors) 244 if name in ('color', 'stroke', 'fill'): 245 v = str(pythonpoint.checkColor(v)) 246 247 return eval(v) 248 249 def getPresentation(self): 250 return self._curPres 251 252 253 def handle_data(self, data): 254 #the only data should be paragraph text, preformatted para 255 #text, 'string text' for a fixed string on the page, 256 #or table data 257 data = asNative(data) 258 if self._curPara: 259 self._curPara.rawtext = self._curPara.rawtext + data 260 elif self._curPrefmt: 261 self._curPrefmt.rawtext = self._curPrefmt.rawtext + data 262 elif self._curPyCode: 263 self._curPyCode.rawtext = self._curPyCode.rawtext + data 264 elif self._curString: 265 self._curString.text = self._curString.text + data 266 elif self._curTable: 267 self._curTable.rawBlocks.append(data) 268 elif self._curTitle != None: # need to allow empty strings, 269 # hence explicitly testing for None 270 self._curTitle = self._curTitle + data 271 elif self._curAuthor != None: 272 self._curAuthor = self._curAuthor + data 273 elif self._curSubject != None: 274 self._curSubject = self._curSubject + data 275 276 def handle_cdata(self, data): 277 #just append to current paragraph text, so we can quote XML 278 if self._curPara: 279 self._curPara.rawtext = self._curPara.rawtext + data 280 elif self._curPrefmt: 281 self._curPrefmt.rawtext = self._curPrefmt.rawtext + data 282 elif self._curPyCode: 283 self._curPyCode.rawtext = self._curPyCode.rawtext + data 284 elif self._curString: 285 self._curString.text = self._curString.text + data 286 elif self._curTable: 287 self._curTable.rawBlocks.append(data) 288 elif self._curAuthor != None: 289 self._curAuthor = self._curAuthor + data 290 elif self._curSubject != None: 291 self._curSubject = self._curSubject + data 292 293 def start_presentation(self, args): 294 self._curPres = pythonpoint.PPPresentation() 295 self._curPres.filename = self._arg('presentation',args,'filename') 296 self._curPres.effectName = self._arg('presentation',args,'effect') 297 self._curPres.pageDuration = self._arg('presentation',args,'pageDuration') 298 299 h = self._arg('presentation',args,'pageHeight') 300 if h: 301 self._curPres.pageHeight = h 302 w = self._arg('presentation',args,'pageWidth') 303 if w: 304 self._curPres.pageWidth = w 305 #print 'page size =', self._curPres.pageSize 306 307 def end_presentation(self): 308 pass 309## print 'Fully parsed presentation',self._curPres.filename 310 311 def start_title(self, args): 312 self._curTitle = '' 313 314 def end_title(self): 315 self._curPres.title = self._curTitle 316 self._curTitle = None 317 318 def start_author(self, args): 319 self._curAuthor = '' 320 321 def end_author(self): 322 self._curPres.author = self._curAuthor 323 self._curAuthor = None 324 325 def start_subject(self, args): 326 self._curSubject = '' 327 328 def end_subject(self): 329 self._curPres.subject = self._curSubject 330 self._curSubject = None 331 332 def start_stylesheet(self, args): 333 #makes it the current style sheet. 334 path = self._arg('stylesheet',args,'path') 335 if path=='None': path = [] 336 if not isSeq(path): path = [path] 337 path.append('styles') 338 path.append(os.getcwd()) 339 modulename = self._arg('stylesheet', args, 'module') 340 funcname = self._arg('stylesheet', args, 'function') 341 try: 342 found = imp.find_module(modulename, path) 343 (file, pathname, description) = found 344 mod = imp.load_module(modulename, file, pathname, description) 345 except ImportError: 346 #last gasp 347 mod = getModule(modulename) 348 349 #now get the function 350 func = getattr(mod, funcname) 351 pythonpoint.setStyles(func()) 352## print 'set global stylesheet to %s.%s()' % (modulename, funcname) 353 354 def end_stylesheet(self): 355 pass 356 357 def start_section(self, args): 358 name = self._arg('section',args,'name') 359 self._curSection = pythonpoint.PPSection(name) 360 361 def end_section(self): 362 self._curSection = None 363 364 def start_slide(self, args): 365 s = pythonpoint.PPSlide() 366 s.id = self._arg('slide',args,'id') 367 s.title = self._arg('slide',args,'title') 368 a = self._arg('slide',args,'effectname') 369 if a != 'None': 370 s.effectName = a 371 s.effectDirection = self.ceval('slide',args,'effectdirection') 372 s.effectDimension = self._arg('slide',args,'effectdimension') 373 s.effectDuration = self.ceval('slide',args,'effectduration') 374 s.effectMotion = self._arg('slide',args,'effectmotion') 375 376 #HACK - may not belong here in the long run... 377 #by default, use the slide title for the outline entry, 378 #unless it is specified as an arg. 379 a = self._arg('slide',args,'outlineentry') 380 if a == "Hide": 381 s.outlineEntry = None 382 elif a != 'None': 383 s.outlineEntry = a 384 else: 385 s.outlineEntry = s.title 386 387 s.outlineLevel = self.ceval('slide',args,'outlinelevel') 388 389 #let it know its section, which may be none 390 s.section = self._curSection 391 self._curSlide = s 392 393 def end_slide(self): 394 self._curPres.slides.append(self._curSlide) 395 self._curSlide = None 396 397 def start_frame(self, args): 398 self._curFrame = pythonpoint.PPFrame( 399 self.ceval('frame',args,'x'), 400 self.ceval('frame',args,'y'), 401 self.ceval('frame',args,'width'), 402 self.ceval('frame',args,'height') 403 ) 404 if self._arg('frame',args,'border')=='true': 405 self._curFrame.showBoundary = 1 406 407 def end_frame(self): 408 self._curSlide.frames.append(self._curFrame) 409 self._curFrame = None 410 411 def start_notes(self, args): 412 name = self._arg('notes',args,'name') 413 self._curNotes = pythonpoint.PPNotes() 414 415 def end_notes(self): 416 self._curSlide.notes.append(self._curNotes) 417 self._curNotes = None 418 419 def start_registerFont(self, args): 420 name = self._arg('font',args,'name') 421 path = self._arg('font',args,'path') 422 pythonpoint.registerFont0(self.sourceFilename, name, path) 423 424 425 def end_registerFont(self): 426 pass 427 428 429 def pack_slide(self, element, args): 430 if self.fx: 431 effectName = self._arg(element,args,'effectname') 432 if effectName != 'None': 433 curSlide = copy.deepcopy(self._curSlide) 434 if self._curFrame: 435 curFrame = copy.deepcopy(self._curFrame) 436 curSlide.frames.append(curFrame) 437 self._curPres.slides.append(curSlide) 438 self._curSlide.effectName = effectName 439 self._curSlide.effectDirection = self.ceval(element,args,'effectdirection') 440 self._curSlide.effectDimension = self._arg(element,args,'effectdimension') 441 self._curSlide.effectDuration = self.ceval(element,args,'effectduration') 442 self._curSlide.effectMotion = self._arg(element,args,'effectmotion') 443 self._curSlide.outlineEntry = None 444 445 def start_para(self, args): 446 self.pack_slide('para', args) 447 self._curPara = pythonpoint.PPPara() 448 self._curPara.style = self._arg('para',args,'style') 449 450 # hack - bullet character if bullet style 451 bt = self._arg('para',args,'bullettext') 452 if bt == '': 453 if self._curPara.style == 'Bullet': 454 bt = u'\u2022' # Symbol Font bullet character, reasonable default 455 elif self._curPara.style == 'Bullet2': 456 bt = u'\u2022' # second-level bullet 457 else: 458 bt = None 459 460 self._curPara.bulletText = bt 461 462 def end_para(self): 463 if self._curFrame: 464 self._curFrame.content.append(self._curPara) 465 self._curPara = None 466 elif self._curNotes: 467 self._curNotes.content.append(self._curPara) 468 self._curPara = None 469 470 471 def start_prefmt(self, args): 472 self._curPrefmt = pythonpoint.PPPreformattedText() 473 self._curPrefmt.style = self._arg('prefmt',args,'style') 474 475 476 def end_prefmt(self): 477 self._curFrame.content.append(self._curPrefmt) 478 self._curPrefmt = None 479 480 481 def start_pycode(self, args): 482 self._curPyCode = pythonpoint.PPPythonCode() 483 self._curPyCode.style = self._arg('pycode',args,'style') 484 485 486 def end_pycode(self): 487 self._curFrame.content.append(self._curPyCode) 488 self._curPyCode = None 489 490 491 def start_image(self, args): 492 self.pack_slide('image',args) 493 sourceFilename = self.sourceFilename # XXX 494 filename = self._arg('image',args,'filename') 495 filename = os.path.join(os.path.dirname(sourceFilename), filename) 496 self._curImage = pythonpoint.PPImage() 497 self._curImage.filename = filename 498 self._curImage.width = self.ceval('image',args,'width') 499 self._curImage.height = self.ceval('image',args,'height') 500 501 502 def end_image(self): 503 self._curFrame.content.append(self._curImage) 504 self._curImage = None 505 506 507 def start_table(self, args): 508 self.pack_slide('table',args) 509 self._curTable = pythonpoint.PPTable() 510 self._curTable.widths = self.ceval('table',args,'widths') 511 self._curTable.heights = self.ceval('table',args,'heights') 512 #these may contain escapes like tabs - handle with 513 #a bit more care. 514 if 'fieldDelim' in args: 515 self._curTable.fieldDelim = eval('"' + args['fieldDelim'] + '"') 516 if 'rowDelim' in args: 517 self._curTable.rowDelim = eval('"' + args['rowDelim'] + '"') 518 if 'style' in args: 519 self._curTable.style = args['style'] 520 521 522 def end_table(self): 523 self._curFrame.content.append(self._curTable) 524 self._curTable = None 525 526 527 def start_spacer(self, args): 528 """No contents so deal with it here.""" 529 sp = pythonpoint.PPSpacer() 530 sp.height = eval(args['height']) 531 self._curFrame.content.append(sp) 532 533 534 def end_spacer(self): 535 pass 536 537 538 ## the graphics objects - go into either the current section 539 ## or the current slide. 540 def start_fixedimage(self, args): 541 sourceFilename = self.sourceFilename 542 filename = self._arg('image',args,'filename') 543 filename = os.path.join(os.path.dirname(sourceFilename), filename) 544 img = pythonpoint.PPFixedImage() 545 img.filename = filename 546 img.x = self.ceval('fixedimage',args,'x') 547 img.y = self.ceval('fixedimage',args,'y') 548 img.width = self.ceval('fixedimage',args,'width') 549 img.height = self.ceval('fixedimage',args,'height') 550 self._curFixedImage = img 551 552 553 def end_fixedimage(self): 554 if self._curSlide: 555 self._curSlide.graphics.append(self._curFixedImage) 556 elif self._curSection: 557 self._curSection.graphics.append(self._curFixedImage) 558 self._curFixedImage = None 559 560 561 def start_rectangle(self, args): 562 self.pack_slide('rectangle', args) 563 rect = pythonpoint.PPRectangle( 564 self.ceval('rectangle',args,'x'), 565 self.ceval('rectangle',args,'y'), 566 self.ceval('rectangle',args,'width'), 567 self.ceval('rectangle',args,'height') 568 ) 569 rect.fillColor = self.ceval('rectangle',args,'fill') 570 rect.strokeColor = self.ceval('rectangle',args,'stroke') 571 self._curRectangle = rect 572 573 574 def end_rectangle(self): 575 if self._curSlide: 576 self._curSlide.graphics.append(self._curRectangle) 577 elif self._curSection: 578 self._curSection.graphics.append(self._curRectangle) 579 self._curRectangle = None 580 581 582 def start_roundrect(self, args): 583 self.pack_slide('roundrect', args) 584 rrect = pythonpoint.PPRoundRect( 585 self.ceval('roundrect',args,'x'), 586 self.ceval('roundrect',args,'y'), 587 self.ceval('roundrect',args,'width'), 588 self.ceval('roundrect',args,'height'), 589 self.ceval('roundrect',args,'radius') 590 ) 591 rrect.fillColor = self.ceval('roundrect',args,'fill') 592 rrect.strokeColor = self.ceval('roundrect',args,'stroke') 593 self._curRoundRect = rrect 594 595 596 def end_roundrect(self): 597 if self._curSlide: 598 self._curSlide.graphics.append(self._curRoundRect) 599 elif self._curSection: 600 self._curSection.graphics.append(self._curRoundRect) 601 self._curRoundRect = None 602 603 604 def start_line(self, args): 605 self.pack_slide('line', args) 606 self._curLine = pythonpoint.PPLine( 607 self.ceval('line',args,'x1'), 608 self.ceval('line',args,'y1'), 609 self.ceval('line',args,'x2'), 610 self.ceval('line',args,'y2') 611 ) 612 self._curLine.strokeColor = self.ceval('line',args,'stroke') 613 614 615 def end_line(self): 616 if self._curSlide: 617 self._curSlide.graphics.append(self._curLine) 618 elif self._curSection: 619 self._curSection.graphics.append(self._curLine) 620 self._curLine = None 621 622 623 def start_ellipse(self, args): 624 self.pack_slide('ellipse', args) 625 self._curEllipse = pythonpoint.PPEllipse( 626 self.ceval('ellipse',args,'x1'), 627 self.ceval('ellipse',args,'y1'), 628 self.ceval('ellipse',args,'x2'), 629 self.ceval('ellipse',args,'y2') 630 ) 631 self._curEllipse.strokeColor = self.ceval('ellipse',args,'stroke') 632 self._curEllipse.fillColor = self.ceval('ellipse',args,'fill') 633 634 635 def end_ellipse(self): 636 if self._curSlide: 637 self._curSlide.graphics.append(self._curEllipse) 638 elif self._curSection: 639 self._curSection.graphics.append(self._curEllipse) 640 self._curEllipse = None 641 642 643 def start_polygon(self, args): 644 self.pack_slide('polygon', args) 645 self._curPolygon = pythonpoint.PPPolygon(self.ceval('polygon',args,'points')) 646 self._curPolygon.strokeColor = self.ceval('polygon',args,'stroke') 647 self._curPolygon.fillColor = self.ceval('polygon',args,'fill') 648 649 650 def end_polygon(self): 651 if self._curSlide: 652 self._curSlide.graphics.append(self._curPolygon) 653 elif self._curSection: 654 self._curSection.graphics.append(self._curPolygon) 655 self._curEllipse = None 656 657 658 def start_string(self, args): 659 self.pack_slide('string', args) 660 self._curString = pythonpoint.PPString( 661 self.ceval('string',args,'x'), 662 self.ceval('string',args,'y') 663 ) 664 self._curString.color = self.ceval('string',args,'color') 665 self._curString.font = self._arg('string',args,'font') 666 self._curString.size = self.ceval('string',args,'size') 667 if args['align'] == 'left': 668 self._curString.align = TA_LEFT 669 elif args['align'] == 'center': 670 self._curString.align = TA_CENTER 671 elif args['align'] == 'right': 672 self._curString.align = TA_RIGHT 673 elif args['align'] == 'justify': 674 self._curString.align = TA_JUSTIFY 675 #text comes later within the tag 676 677 678 def end_string(self): 679 #controller should have set the text 680 if self._curSlide: 681 self._curSlide.graphics.append(self._curString) 682 elif self._curSection: 683 self._curSection.graphics.append(self._curString) 684 self._curString = None 685 686 687 def start_infostring(self, args): 688 # like a string, but lets them embed page no, author etc. 689 self.start_string(args) 690 self._curString.hasInfo = 1 691 692 693 def end_infostring(self): 694 self.end_string() 695 696 697 def start_customshape(self, args): 698 #loads one 699 path = self._arg('customshape',args,'path') 700 if path=='None': 701 path = [] 702 else: 703 path=[path] 704 705 # add package root folder and input file's folder to path 706 path.append(os.path.dirname(self.sourceFilename)) 707 path.append(os.path.dirname(pythonpoint.__file__)) 708 709 modulename = self._arg('customshape',args,'module') 710 funcname = self._arg('customshape',args,'class') 711 try: 712 found = imp.find_module(modulename, path) 713 (file, pathname, description) = found 714 mod = imp.load_module(modulename, file, pathname, description) 715 except ImportError: 716 mod = getModule(modulename) 717 718 #now get the function 719 720 func = getattr(mod, funcname) 721 initargs = self.ceval('customshape',args,'initargs') 722 self._curCustomShape = func(*initargs) 723 724 def end_customshape(self): 725 if self._curSlide: 726 self._curSlide.graphics.append(self._curCustomShape) 727 elif self._curSection: 728 self._curSection.graphics.append(self._curCustomShape) 729 self._curCustomShape = None 730 731 def start_drawing(self, args): 732 #loads one 733 moduleName = args["module"] 734 funcName = args["constructor"] 735 showBoundary = int(args.get("showBoundary", "0")) 736 hAlign = args.get("hAlign", "CENTER") 737 738 739 # the path for the imports should include: 740 # 1. document directory 741 # 2. python path if baseDir not given, or 742 # 3. baseDir if given 743 try: 744 dirName = sdict["baseDir"] 745 except: 746 dirName = None 747 importPath = [os.getcwd()] 748 if dirName is None: 749 importPath.extend(sys.path) 750 else: 751 importPath.insert(0, dirName) 752 753 modul = recursiveImport(moduleName, baseDir=importPath) 754 func = getattr(modul, funcName) 755 drawing = func() 756 757 drawing.hAlign = hAlign 758 if showBoundary: 759 drawing._showBoundary = 1 760 761 self._curDrawing = pythonpoint.PPDrawing() 762 self._curDrawing.drawing = drawing 763 764 def end_drawing(self): 765 self._curFrame.content.append(self._curDrawing) 766 self._curDrawing = None 767 768 def start_pageCatcherFigure(self, args): 769 filename = args["filename"] 770 pageNo = int(args["pageNo"]) 771 width = float(args.get("width", "595")) 772 height = float(args.get("height", "842")) 773 774 775 fig = figures.PageCatcherFigureNonA4(filename, pageNo, args.get("caption", ""), width, height) 776 sf = args.get('scaleFactor', None) 777 if sf: sf = float(sf) 778 border = not (args.get('border', None) in ['0','no']) 779 780 fig.scaleFactor = sf 781 fig.border = border 782 783 #self.ceval('pageCatcherFigure',args,'scaleFactor'), 784 #initargs = self.ceval('customshape',args,'initargs') 785 self._curFigure = pythonpoint.PPFigure() 786 self._curFigure.figure = fig 787 788 def end_pageCatcherFigure(self): 789 self._curFrame.content.append(self._curFigure) 790 self._curFigure = None 791 792 ## intra-paragraph XML should be allowed through into PLATYPUS 793 def unknown_starttag(self, tag, attrs): 794 if self._curPara: 795 echo = '<%s' % tag 796 for key, value in attrs.items(): 797 echo = echo + ' %s="%s"' % (key, value) 798 echo = echo + '>' 799 self._curPara.rawtext = self._curPara.rawtext + echo 800 else: 801 print('Unknown start tag %s' % tag) 802 803 804 def unknown_endtag(self, tag): 805 if self._curPara: 806 self._curPara.rawtext = self._curPara.rawtext + '</%s>'% tag 807 else: 808 print('Unknown end tag %s' % tag) 809 810 def handle_charref(self, name): 811 try: 812 if name[0]=='x': 813 n = int(name[1:],16) 814 else: 815 n = int(name) 816 except ValueError: 817 self.unknown_charref(name) 818 return 819 self.handle_data(uniChr(n).encode('utf8')) 820 821 #HTMLParser interface 822 def handle_starttag(self, tag, attrs): 823 "Called by HTMLParser when a tag starts" 824 825 #tuple tree parser used to expect a dict. HTML parser 826 #gives list of two-element tuples 827 if isinstance(attrs, list): 828 d = {} 829 for (k, v) in attrs: 830 d[k] = v 831 attrs = d 832 if not self.caseSensitive: tag = tag.lower() 833 try: 834 start = getattr(self,'start_'+tag) 835 except AttributeError: 836 if not self.ignoreUnknownTags: 837 raise ValueError('Invalid tag "%s"' % tag) 838 start = self.start_unknown 839 #call it 840 start(attrs or {}) 841 842 def handle_endtag(self, tag): 843 "Called by HTMLParser when a tag ends" 844 #find the existing end_tagname method 845 if not self.caseSensitive: tag = tag.lower() 846 try: 847 end = getattr(self,'end_'+tag) 848 except AttributeError: 849 if not self.ignoreUnknownTags: 850 raise ValueError('Invalid tag "%s"' % tag) 851 end = self.end_unknown 852 #call it 853 end() 854 855 def handle_entityref(self, name): 856 "Handles a named entity. " 857 try: 858 v = uniChr(known_entities[name]) 859 except: 860 v = u'&%s;' % name 861 self.handle_data(v) 862 863 def start_unknown(self,attr): 864 pass 865 def end_unknown(self): 866 pass 867