def test_assets_render_from_style(): register_style( 'my_style', Style( test, assets__an_asset=Asset.css(attrs__href='http://foo.bar/baz'), )) class MyPage(Page): class Meta: iommi_style = 'my_style' expected = prettify(''' <!DOCTYPE html> <html> <head> <title/> <link href='http://foo.bar/baz' rel="stylesheet"/> </head> <body/> </html> ''') actual = prettify( MyPage().bind(request=req('get')).render_to_response().content) assert actual == expected unregister_style('my_style')
def test_deprecated_assets_style(settings, capsys): settings.DEBUG = True with register_style( 'my_style', Style( test, assets__an_asset=Asset.css(attrs__href='http://foo.bar/baz'), ), ): captured = capsys.readouterr() assert 'Warning: The preferred way to add top level assets config' in captured.out settings.DEBUG = False expected = prettify( ''' <!DOCTYPE html> <html> <head> <title/> <link href='http://foo.bar/baz' rel="stylesheet"/> </head> <body/> </html> ''' ) actual = prettify(Page(iommi_style='my_style').bind(request=req('get')).render_to_response().content) assert actual == expected
def test_assets_render_once(): an_asset = Asset.css(attrs__href='http://foo.bar/baz') class MyPage(Page): foo = html.div('foo', assets__my_asset=an_asset) bar = html.div('bar', assets__my_asset=an_asset) expected = prettify(''' <!DOCTYPE html> <html> <head> <title/> <link href='http://foo.bar/baz' rel="stylesheet"/> </head> <body> <div> foo </div> <div> bar </div> </body> </html> ''') actual = prettify( MyPage().bind(request=req('get')).render_to_response().content) assert actual == expected
def live_edit_view(request, view, args, kwargs): view = get_wrapped_view(view) # Read the old code try: # view is a function based view filename = view.__globals__['__file__'] except AttributeError: # view is an iommi class from iommi.debug import filename_and_line_num_from_part filename, _ = filename_and_line_num_from_part(view) with open(filename) as f: entire_file = f.read() ast_of_entire_file = parso.parse(entire_file) is_unix_line_endings = '\r\n' not in entire_file ast_of_old_code = find_view(view, ast_of_entire_file) assert ast_of_old_code is not None flow_direction = request.GET.get('_iommi_live_edit') or 'column' assert flow_direction in ('column', 'row') if request.method == 'POST': try: code = request.POST['data'].replace('\t', ' ') if is_unix_line_endings: code = code.replace('\r\n', '\n') final_result = dangerous_execute_code(code, request, view, args, kwargs) if orig_reload is not None: # A little monkey patch dance to avoid one reload of the runserver when it's just us writing the code to disk # This only works in django 2.2+ def restore_auto_reload(filename): from django.utils import autoreload print('Skipped reload') autoreload.trigger_reload = orig_reload autoreload.trigger_reload = restore_auto_reload if isinstance(view, Part): ast_of_new_code = find_node(name=view.__class__.__name__, node=parso.parse(code), node_type='classdef') else: ast_of_new_code = find_node(name=view.__name__, node=parso.parse(code), node_type='funcdef') ast_of_old_code.children[:] = ast_of_new_code.children new_code = ast_of_entire_file.get_code() with open(filename, 'w') as f: f.write(new_code) return final_result except Exception as e: import traceback traceback.print_exc() error = str(e) if not error: error = str(e.__class__) return HttpResponse(json.dumps(dict(error=error))) return LiveEditPage( title='iommi live edit', h_tag__include=False, assets__code_editor=Asset.js( attrs=dict( src='https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.12/ace.js', integrity= 'sha512-GZ1RIgZaSc8rnco/8CXfRdCpDxRCphenIiZ2ztLy3XQfCbQUSCuk8IudvNHxkRA3oUg6q0qejgN/qqyG1duv5Q==', crossorigin='anonymous', ), after=-1, ), assets__live_edit_page_custom=Asset( tag='style', text=''' .container { padding: 0 !important; margin: 0 !important; max-width: 100%; } html, body { height: 100%; margin: 0; } .container { display: flex; flex-flow: <<flow_direction>>; height: 100%; } .container iframe { flex: 1 1 auto; } .container #editor { flex: 2 1 auto; } '''.replace('<<flow_direction>>', flow_direction), ), parts__result=html.iframe(attrs__id='result'), parts__editor=html.div( ast_of_old_code.get_code(), attrs__id='editor', ), parts__script=html.script( mark_safe(''' function iommi_debounce(func, wait) { let timeout; return (...args) => { const fn = () => func.apply(this, args); clearTimeout(timeout); timeout = setTimeout(() => fn(), wait); }; } var editor = ace.edit("editor"); editor.setTheme("ace/theme/cobalt"); editor.session.setMode("ace/mode/python"); editor.setShowPrintMargin(false); async function update() { let form_data = new FormData(); form_data.append('data', editor.getValue()); let response = await fetch('', { method: 'POST', body: form_data }); let foo = await response.json(); if (foo.page) { // TODO: get scroll position and restore it document.getElementById('result').srcdoc = foo.page; } } function foo() { iommi_debounce(update, 200)(); } editor.session.on('change', foo); editor.setFontSize(14); editor.session.setUseWrapMode(true); foo(); ''')), )
class Meta: assets__css_asset = Asset.css(attrs__href='http://foo.bar/baz.css') assets__js_asset = Asset.js(attrs__href='http://foo.bar/baz.j')
class MyPage(Page): foo = html.div( 'foo', assets__my_asset=Asset.css(attrs__href='http://foo.bar/baz'))
'NAME': 'mammon', **dokku_db_conf } } DATE_FORMAT = 'Y-m-d' DATETIME_FORMAT = 'Y-m-d' IOMMI_DEFAULT_STYLE = Style( bootstrap, base_template='iommi_base.html', root__assets=dict( jquery_ui=Asset.js( attrs=dict( src='https://code.jquery.com/ui/1.13.0/jquery-ui.min.js', crossorigin='anonymous', integrity='sha256-hlKLmzaRlE8SCJC1Kw8zoUbU8BxA+8kR3gseuKfMjxA', ), after=-1, ), i18n=Asset.js(attrs=dict(src="/jsi18n/", crossorigin='anonymous')), lodash=Asset.js(attrs=dict( src= "https://cdnjs.cloudflare.com/ajax/libs/lodash.js/2.4.1/lodash.min.js", crossorigin='anonymous')), inline_edit=Asset.js( attrs=dict(src="/inline_edit.js", crossorigin='anonymous')), input_overlay=Asset.js( attrs=dict(src="/input_overlay.js", crossorigin='anonymous')), # inlinecomplete=Asset.js(attrs=dict(src="/site-media2/jquery.inlinecomplete.js", crossorigin='anonymous')), intoViewport=Asset.js( attrs=dict(src="/site-media2/jquery.intoViewport.min.js",