comparison tincan.py @ 57:935f8013f540 draft

Fix lack of error detection and recovery in template parsing.
author David Barts <n5jrn@me.com>
date Fri, 31 May 2019 19:40:06 -0700
parents f177756200be
children e08e24707da1
comparison
equal deleted inserted replaced
56:f177756200be 57:935f8013f540
6 6
7 import os, sys 7 import os, sys
8 import ast 8 import ast
9 import binascii 9 import binascii
10 from base64 import b16encode, b16decode 10 from base64 import b16encode, b16decode
11 from chameleon import PageTemplate, PageTemplateFile, TemplateError
11 import email.utils 12 import email.utils
12 import functools 13 import functools
13 import importlib 14 import importlib
14 from inspect import isclass 15 from inspect import isclass
15 import io 16 import io
194 # 195 #
195 # Support for Chameleon templates (the kind TinCan uses). 196 # Support for Chameleon templates (the kind TinCan uses).
196 197
197 class ChameleonTemplate(bottle.BaseTemplate): 198 class ChameleonTemplate(bottle.BaseTemplate):
198 def prepare(self, **options): 199 def prepare(self, **options):
199 from chameleon import PageTemplate, PageTemplateFile
200 if self.source: 200 if self.source:
201 self.tpl = PageTemplate(self.source, **options) 201 self.tpl = PageTemplate(self.source, **options)
202 else: 202 else:
203 self.tpl = PageTemplateFile(self.filename, encoding=self.encoding, 203 self.tpl = PageTemplateFile(self.filename, encoding=self.encoding,
204 search_path=self.lookup, **options) 204 search_path=self.lookup, **options)
588 tfile = TemplateFile(tpath) 588 tfile = TemplateFile(tpath)
589 except OSError as e: 589 except OSError as e:
590 raise TinCanError("{0}: invalid #template: {1!s}".format(self._urlpath, e)) from e 590 raise TinCanError("{0}: invalid #template: {1!s}".format(self._urlpath, e)) from e
591 except IndexError as e: 591 except IndexError as e:
592 raise TinCanError("{0}: invalid #template".format(self._urlpath)) from e 592 raise TinCanError("{0}: invalid #template".format(self._urlpath)) from e
593 self._body = ChameleonTemplate(source=tfile.body, encoding=self._encoding) 593 self._body = self._mktemplate(tfile.body, self.urljoin(rtpath))
594 else: 594 else:
595 self._body = ChameleonTemplate(source=self._template.body, encoding=self._encoding) 595 self._body = self._mktemplate(self._template.body, self._urlpath)
596 self._body.prepare() 596 self._body.prepare()
597 # Process loads 597 # Process loads
598 self._loads = {} 598 self._loads = {}
599 for load in self._header.load: 599 for load in self._header.load:
600 try: 600 try:
622 if not methods: 622 if not methods:
623 raise TinCanError("{0}: no #methods specified".format(self._urlpath)) 623 raise TinCanError("{0}: no #methods specified".format(self._urlpath))
624 # Register this thing with Bottle 624 # Register this thing with Bottle
625 self.logger.info("adding route: %s (%s)", self._origin, ','.join(methods)) 625 self.logger.info("adding route: %s (%s)", self._origin, ','.join(methods))
626 self._app.route(self._origin, methods, self) 626 self._app.route(self._origin, methods, self)
627
628 def _mktemplate(self, source, name):
629 try:
630 return ChameleonTemplate(source=source, encoding=self._encoding)
631 except TemplateError as e:
632 raise TinCanError("{0}: {1!s}".format(name, e)) from e
627 633
628 def _splitpath(self, unsplit): 634 def _splitpath(self, unsplit):
629 return _normpath(self._subdir, unsplit) 635 return _normpath(self._subdir, unsplit)
630 636
631 def _mkerror(self, rerrors): 637 def _mkerror(self, rerrors):