def transform(self, output, shared_data=None): if not isinstance(output, dict): return output context = dict(request=request) context.update(HELPERS) context.update(URL=URL) if shared_data: context.update(shared_data.get('template_context', {})) context.update(output) context["__vars__"] = output app_folder = os.path.join(os.environ["PY4WEB_APPS_FOLDER"], request.app_name) path = self.path or os.path.join(app_folder, "templates") filename = os.path.join(path, self.filename) if not os.path.exists(filename): generic_filename = os.path.join(path, "generic.html") if os.path.exists(generic_filename): filename = generic_filename output = yatl.render( Template.reader(filename), path=path, context=context, delimiters=self.delimiters, reader=Template.reader, ) return output
def wrapper(*func_args, **func_kwargs): request.app_name = app_name try: for db in self.dbs: db._adapter.reconnect() for session in self.sessions: session.load() output = function(*func_args, **func_kwargs) if isinstance(output, dict): if self.view: path = os.path.join(folder, 'templates') with open(os.path.join(path, self.view)) as stream: context = dict(request=request) context.update(yatl.helpers.__dict__) context.update(output) output = yatl.render(stream.read(), path=path, context=context, delimiters='[[ ]]') else: output = dumps(output) for db in self.dbs: db._adapter.commit() except bottle.HTTPResponse as e: raise e except HTTP as http: for db in self.dbs: db._adapter.commit() output = bottle.HTTPResponse(status=http.status, body=http.body) except: request.session = None for db in self.dbs: db._adapter.rollback() tb = traceback.format_exc() output = '<html><body><pre>%s</pre></body></html>' % yatl.xmlescape(tb) [session.save() for session in self.sessions if session.changed] return output
def testRun(self): self.assertEqual(render(content='{{for i in range(n):}}{{=i}}{{pass}}', context=dict(n=3)), '012') self.assertEqual(render(content='{{if n>2:}}ok{{pass}}', context=dict(n=3)), 'ok') self.assertEqual( render(content='{{try:}}{{n/0}}{{except:}}fail{{pass}}', context=dict(n=3)), 'fail') self.assertEqual(render(content='{{="<&>"}}'), '<&>') self.assertEqual(render(content='"abc"'), '"abc"') self.assertEqual(render(content='"a\'bc"'), '"a\'bc"') self.assertEqual(render(content='"a\"bc"'), '"a\"bc"') self.assertEqual(render(content=r'"a\"bc"'), r'"a\"bc"') self.assertEqual(render(content=r'"""abc\""""'), r'"""abc\""""')
def testRun(self): self.assertEqual( render(content='{{for i in range(n):}}{{=i}}{{pass}}', context=dict(n=3)), '012') self.assertEqual( render(content='{{if n>2:}}ok{{pass}}', context=dict(n=3)), 'ok') self.assertEqual( render(content='{{try:}}{{n/0}}{{except:}}fail{{pass}}', context=dict(n=3)), 'fail') self.assertEqual(render(content='{{="<&>"}}'), '<&>') self.assertEqual(render(content='"abc"'), '"abc"') self.assertEqual(render(content='"a\'bc"'), '"a\'bc"') self.assertEqual(render(content='"a\"bc"'), '"a\"bc"') self.assertEqual(render(content=r'"a\"bc"'), r'"a\"bc"') self.assertEqual(render(content=r'"""abc\""""'), r'"""abc\""""')
def html(self): """ return html page """ with tempdir(Path(__file__).parent.parent / "templates"): html = open(f"../templates/map.html").read() self.legends = self.get_legends() self.toggles = self.get_toggles() return yatl.render( html, delimiters="[[ ]]", context=dict(token=token, map1=self), )
def error_page(code, button_text=None, href="#", color=None, message=None): message = http.client.responses[code].upper() if message is None else message color = ( {"4": "#F44336", "5": "#607D8B"}.get(str(code)[0], "#2196F3") if not color else color ) return yatl.render( '<html><head><style>body{color:white;text-align: center;background-color:{{=color}};font-family:serif} h1{font-size:6em;margin:16vh 0 8vh 0} h2{font-size:2em;margin:8vh 0} a{color:white;text-decoration:none;font-weight:bold;padding:10px 10px;border-radius:10px;border:2px solid #fff;transition: all .5s ease} a:hover{background:rgba(0,0,0,0.1);padding:10px 30px}</style></head><body><h1>{{=code}}</h1><h2>{{=message}}</h2>{{if button_text:}}<a href="{{=href}}">{{=button_text}}</a>{{pass}}</body></html>', context=dict( code=code, message=message, button_text=button_text, href=href, color=color ), )
def transform(self, output): if not isinstance(output, dict): return output context = dict(request=request) context.update(yatl.helpers.__dict__) context.update(URL=URL) context.update(output) context['__vars__'] = output app_folder = os.path.join(os.environ['WEB3PY_APPLICATIONS_FOLDER'], request.app_name) path = os.path.join(app_folder, 'templates') filename = os.path.join(path, self.filename) template = Template.cache.get(filename, lambda: Template.read(filename), expiration=1, monitor=lambda: os.path.getmtime(filename)) output = yatl.render(template, path=path, context=context, delimiters=self.delimiters) return output
def transform(self, output): if not isinstance(output, dict): return output context = dict(request=request) context.update(yatl.helpers.__dict__) context.update(URL=URL) context.update(output) context['__vars__'] = output app_folder = os.path.join( os.environ['PY4WEB_APPS_FOLDER'], request.app_name) path = self.path or os.path.join(app_folder, 'templates') filename = os.path.join(path, self.filename) output = yatl.render( Template.reader(filename), path=path, context=context, delimiters=self.delimiters, reader=Template.reader) return output
def html(self): """ return html page """ with tempdir(Path(__file__).parent.parent / "templates"): html = open(self.template).read() # use legends and toggles from map1 only self.map1.legends = self.map1.get_legends() self.map1.toggles = self.map1.get_toggles() # align maps self.map2.center = self.map1.center self.map2.zoom = self.map1.zoom return yatl.render( html, delimiters="[[ ]]", context=dict(token=token, map1=self.map1, map2=self.map2), )
def transform(self, output): if not isinstance(output, dict): return output context = dict(request=request) context.update(yatl.helpers.__dict__) context.update(URL=URL) context.update(output) context["__vars__"] = output app_folder = os.path.join(os.environ["PY4WEB_APPS_FOLDER"], request.app_name) path = self.path or os.path.join(app_folder, "templates") filename = os.path.join(path, self.filename) if not os.path.exists(filename): generic_filename = os.path.join(path, 'generic.html') if os.path.exists(generic_filename): filename = generic_filename output = yatl.render( Template.reader(filename), path=path, context=context, delimiters=self.delimiters, reader=Template.reader, ) return output
def testWithDummyFileSystem(self): from os.path import join as pjoin import contextlib if sys.version_info[0] == 2: from cStringIO import StringIO else: from io import StringIO @contextlib.contextmanager def monkey_patch(module, fn_name, patch): try: unpatch = getattr(module, fn_name) except AttributeError: unpatch = None setattr(module, fn_name, patch) try: yield finally: if unpatch is None: delattr(module, fn_name) else: setattr(module, fn_name, unpatch) def dummy_open(path): if path == pjoin('views', 'layout.html'): return ("{{block left_sidebar}}left{{end}}" "{{include}}" "{{block right_sidebar}}right{{end}}") elif path == pjoin('views', 'layoutbrackets.html'): return ("[[block left_sidebar]]left[[end]]" "[[include]]" "[[block right_sidebar]]right[[end]]") elif path == pjoin('views', 'default', 'index.html'): return ("{{extend 'layout.html'}}" "{{block left_sidebar}}{{super}} {{end}}" "to" "{{block right_sidebar}} {{super}}{{end}}") elif path == pjoin('views', 'default', 'indexbrackets.html'): return ("[[extend 'layoutbrackets.html']]" "[[block left_sidebar]][[super]] [[end]]" "to" "[[block right_sidebar]] [[super]][[end]]") elif path == pjoin('views', 'default', 'missing.html'): return ("{{extend 'wut'}}" "{{block left_sidebar}}{{super}} {{end}}" "to" "{{block right_sidebar}} {{super}}{{end}}") elif path == pjoin('views', 'default', 'noescape.html'): return "{{=NOESCAPE('<script></script>')}}" raise IOError self.assertEqual( render(filename=pjoin('views', 'default', 'index.html'), path='views', reader=dummy_open), 'left to right') self.assertEqual( render(filename=pjoin('views', 'default', 'indexbrackets.html'), path='views', delimiters='[[ ]]', reader=dummy_open), 'left to right') #self.assertRaises( # RestrictedError, # render, # filename=pjoin('views', 'default', 'missing.html'), # path='views', # reader=dummy_open) response = DummyResponse() response.delimiters = ('[[', ']]') self.assertEqual( render(filename=pjoin('views', 'default', 'indexbrackets.html'), path='views', context={'response': response}, reader=dummy_open), 'left to right') self.assertEqual( render(filename=pjoin('views', 'default', 'noescape.html'), context={'NOESCAPE': NOESCAPE}, reader=dummy_open), '<script></script>')
def testEqualWrite(self): "test generation of response.write" self.assertEqual(render(content='{{=2+2}}'), '4') self.assertEqual(render(content='{{="abc"}}'), 'abc') # whitespace is stripped self.assertEqual(render(content='{{ ="abc"}}'), 'abc') self.assertEqual(render(content='{{ ="abc" }}'), 'abc') self.assertEqual(render(content='{{pass\n="abc" }}'), 'abc') # = recognized only at the beginning of a physical line self.assertEqual( render(content='{{xyz = "xyz"\n="abc"\n="def"\n=xyz }}'), 'abcdefxyz') # = in python blocks self.assertEqual(render(content='{{if True:\n="abc"\npass }}'), 'abc') self.assertEqual(render(content='{{if True:\n="abc"\npass\n="def" }}'), 'abcdef') self.assertEqual( render(content='{{if False:\n="abc"\npass\n="def" }}'), 'def') self.assertEqual( render(content='{{if True:\n="abc"\nelse:\n="def"\npass }}'), 'abc') self.assertEqual( render(content='{{if False:\n="abc"\nelse:\n="def"\npass }}'), 'def') # codeblock-leading = handles internal newlines, escaped or not self.assertEqual(render(content='{{=list((1,2,3))}}'), '[1, 2, 3]') self.assertEqual(render(content='{{=list((1,2,\\\n3))}}'), '[1, 2, 3]') self.assertEqual(render(content='{{=list((1,2,\n3))}}'), '[1, 2, 3]') # ...but that means no more = operators in the codeblock self.assertRaises(SyntaxError, render, content='{{="abc"\n="def" }}') # = embedded in codeblock won't handle newlines in its argument self.assertEqual(render(content='{{pass\n=list((1,2,\\\n3))}}'), '[1, 2, 3]') self.assertRaises(SyntaxError, render, content='{{pass\n=list((1,2,\n3))}}')
def error_page(code, button_text=None, href='#', color=None, message=None): message = http.client.responses[code].upper() if message is None else message color = {'4':'#F44336', '5': '#607D8B'}.get(str(code)[0], '#2196F3') if not color else color return yatl.render('<html><head><style>body{color:white;text-align: center;background-color:{{=color}};font-family:serif} h1{font-size:6em;margin:16vh 0 8vh 0} h2{font-size:2em;margin:8vh 0} a{color:white;text-decoration:none;font-weight:bold;padding:10px 10px;border-radius:10px;border:2px solid #fff;transition: all .5s ease} a:hover{background:rgba(0,0,0,0.1);padding:10px 30px}</style></head><body><h1>{{=code}}</h1><h2>{{=message}}</h2>{{if button_text:}}<a href="{{=href}}">{{=button_text}}</a>{{pass}}</body></html>', context=dict(code=code, message=message, button_text=button_text, href=href, color=color))
def testWithDummyFileSystem(self): from os.path import join as pjoin import contextlib if sys.version_info[0] == 2: from cStringIO import StringIO else: from io import StringIO @contextlib.contextmanager def monkey_patch(module, fn_name, patch): try: unpatch = getattr(module, fn_name) except AttributeError: unpatch = None setattr(module, fn_name, patch) try: yield finally: if unpatch is None: delattr(module, fn_name) else: setattr(module, fn_name, unpatch) def dummy_open(path): if path == pjoin('views', 'layout.html'): return ("{{block left_sidebar}}left{{end}}" "{{include}}" "{{block right_sidebar}}right{{end}}") elif path == pjoin('views', 'layoutbrackets.html'): return ("[[block left_sidebar]]left[[end]]" "[[include]]" "[[block right_sidebar]]right[[end]]") elif path == pjoin('views', 'default', 'index.html'): return ("{{extend 'layout.html'}}" "{{block left_sidebar}}{{super}} {{end}}" "to" "{{block right_sidebar}} {{super}}{{end}}") elif path == pjoin('views', 'default', 'indexbrackets.html'): return ("[[extend 'layoutbrackets.html']]" "[[block left_sidebar]][[super]] [[end]]" "to" "[[block right_sidebar]] [[super]][[end]]") elif path == pjoin('views', 'default', 'missing.html'): return ("{{extend 'wut'}}" "{{block left_sidebar}}{{super}} {{end}}" "to" "{{block right_sidebar}} {{super}}{{end}}") elif path == pjoin('views', 'default', 'noescape.html'): return "{{=NOESCAPE('<script></script>')}}" raise IOError self.assertEqual( render(filename=pjoin('views', 'default', 'index.html'), path='views', reader=dummy_open), 'left to right') self.assertEqual( render(filename=pjoin('views', 'default', 'indexbrackets.html'), path='views', delimiters='[[ ]]', reader=dummy_open), 'left to right') #self.assertRaises( # RestrictedError, # render, # filename=pjoin('views', 'default', 'missing.html'), # path='views', # reader=dummy_open) response = DummyResponse() response.delimiters = ('[[', ']]') self.assertEqual( render(filename=pjoin('views', 'default', 'indexbrackets.html'), path='views', context={'response': response}, reader=dummy_open), 'left to right') self.assertEqual( render(filename=pjoin('views', 'default', 'noescape.html'), context={'NOESCAPE': NOESCAPE}, reader=dummy_open), '<script></script>')
def testEqualWrite(self): "test generation of response.write" self.assertEqual(render(content='{{=2+2}}'), '4') self.assertEqual(render(content='{{="abc"}}'), 'abc') # whitespace is stripped self.assertEqual(render(content='{{ ="abc"}}'), 'abc') self.assertEqual(render(content='{{ ="abc" }}'), 'abc') self.assertEqual(render(content='{{pass\n="abc" }}'), 'abc') # = recognized only at the beginning of a physical line self.assertEqual(render( content='{{xyz = "xyz"\n="abc"\n="def"\n=xyz }}'), 'abcdefxyz') # = in python blocks self.assertEqual(render(content='{{if True:\n="abc"\npass }}'), 'abc') self.assertEqual( render(content='{{if True:\n="abc"\npass\n="def" }}'), 'abcdef') self.assertEqual( render(content='{{if False:\n="abc"\npass\n="def" }}'), 'def') self.assertEqual(render( content='{{if True:\n="abc"\nelse:\n="def"\npass }}'), 'abc') self.assertEqual(render( content='{{if False:\n="abc"\nelse:\n="def"\npass }}'), 'def') # codeblock-leading = handles internal newlines, escaped or not self.assertEqual(render(content='{{=list((1,2,3))}}'), '[1, 2, 3]') self.assertEqual(render(content='{{=list((1,2,\\\n3))}}'), '[1, 2, 3]') self.assertEqual(render(content='{{=list((1,2,\n3))}}'), '[1, 2, 3]') # ...but that means no more = operators in the codeblock self.assertRaises(SyntaxError, render, content='{{="abc"\n="def" }}') # = embedded in codeblock won't handle newlines in its argument self.assertEqual( render(content='{{pass\n=list((1,2,\\\n3))}}'), '[1, 2, 3]') self.assertRaises( SyntaxError, render, content='{{pass\n=list((1,2,\n3))}}')
def render_yatl(): output = render(path='yatl_templates', filename='yatl_templates/page.html', context=dict(name='bar', title='foo'))
def render_yatl_no_file(): output = render('Hello {{=name}}!', context=dict(name='bar', title='foo'))