comparison tincan.py @ 17:8186de188daf draft

Improve the run-time error handling in code-behinds.
author David Barts <n5jrn@me.com>
date Mon, 20 May 2019 07:34:46 -0700
parents 448fc3d534f8
children e88ab99914cf
comparison
equal deleted inserted replaced
16:448fc3d534f8 17:8186de188daf
13 from inspect import isclass 13 from inspect import isclass
14 import io 14 import io
15 import py_compile 15 import py_compile
16 from stat import S_ISDIR, S_ISREG 16 from stat import S_ISDIR, S_ISREG
17 from string import whitespace 17 from string import whitespace
18 import traceback
19 import urllib
18 20
19 import bottle 21 import bottle
20 22
21 # E x c e p t i o n s 23 # E x c e p t i o n s
22 24
328 self._template.prepare() 330 self._template.prepare()
329 self._class = klass 331 self._class = klass
330 332
331 def __call__(self, e): 333 def __call__(self, e):
332 bottle.request.environ[_FTYPE] = True 334 bottle.request.environ[_FTYPE] = True
333 obj = self._class(bottle.request, e) 335 try:
334 obj.handle() 336 obj = self._class(bottle.request, e)
335 return self._template.render(obj.export()).lstrip('\n') 337 obj.handle()
338 return self._template.render(obj.export()).lstrip('\n')
339 except bottle.HTTPResponse as e:
340 return e
341 except Exception as e:
342 traceback.print_exc()
343 raise bottle.HTTPError(status=500, exception=e)
336 344
337 class _TinCanRoute(object): 345 class _TinCanRoute(object):
338 """ 346 """
339 A route created by the TinCan launcher. 347 A route created by the TinCan launcher.
340 """ 348 """
514 def __call__(self): 522 def __call__(self):
515 """ 523 """
516 This gets called by the framework AFTER the page is launched. 524 This gets called by the framework AFTER the page is launched.
517 """ 525 """
518 target = None 526 target = None
519 obj = self._class(bottle.request, bottle.response) 527 try:
520 try: 528 obj = self._class(bottle.request, bottle.response)
521 obj.handle() 529 obj.handle()
522 return self._body.render(obj.export()).lstrip('\n') 530 return self._body.render(obj.export()).lstrip('\n')
523 except ForwardException as fwd: 531 except ForwardException as fwd:
524 target = fwd.target 532 target = fwd.target
533 except bottle.HTTPResponse as e:
534 return e
535 except Exception as e:
536 traceback.print_exc()
537 raise bottle.HTTPError(status=500, exception=e)
525 if target is None: 538 if target is None:
526 raise TinCanError("{0}: unexpected null target".format(self._urlpath)) 539 message = "{0}: unexpected null target".format(self._urlpath)
540 sys.stderr.write(message + '\n')
541 raise bottle.HTTPError(status=500, exception=TinCanError(message))
527 # We get here if we are doing a server-side programmatic 542 # We get here if we are doing a server-side programmatic
528 # forward. 543 # forward.
529 environ = bottle.request.environ 544 environ = bottle.request.environ
530 if _FORIG not in environ: 545 if _FORIG not in environ:
531 environ[_FORIG] = self._urlpath 546 environ[_FORIG] = self._urlpath
532 if _FLOOP not in environ: 547 if _FLOOP not in environ:
533 environ[_FLOOP] = set([self._urlpath]) 548 environ[_FLOOP] = set([self._urlpath])
534 elif target in environ[_FLOOP]: 549 elif target in environ[_FLOOP]:
535 raise TinCanError("{0}: forward loop detected".format(environ[_FORIG])) 550 message = "{0}: forward loop detected".format(environ[_FORIG])
551 sys.stderr.write(message + '\n')
552 raise bottle.HTTPError(status=500, exception=TinCanError(message))
536 environ[_FLOOP].add(target) 553 environ[_FLOOP].add(target)
537 environ['bottle.raw_path'] = target 554 environ['bottle.raw_path'] = target
538 environ['PATH_INFO'] = urllib.parse.quote(target) 555 environ['PATH_INFO'] = urllib.parse.quote(target)
539 route, args = self._app.router.match(environ) 556 route, args = self._app.router.match(environ)
540 environ['route.handle'] = environ['bottle.route'] = route 557 environ['route.handle'] = environ['bottle.route'] = route