def confirm_at_start(page, info_container): ''' Asks for confirmation from the user for any pre-existing settings regarding security level for known sites. This is meant to be called only at the start of a given Crunchy session (hence the name of the function). ''' page.add_css_code(security_css % ('block', 'block')) h2 = SubElement(info_container, 'h2') h2.text = _('Confirm the security levels') h2.attrib['class'] = "crunchy" directions = SubElement(info_container, "h4") directions.text = _("Before browsing any further ...\n\n") directions.text += _( "Do you wish to retain the existing settings for these sites?\n\n") directions.text += _( "You can change any of them before clicking on the approve button.\n\n" ) # in case list gets too long, we include buttons at top and bottom of list nb_sites = len(config[page.username]['site_security']) add_button(info_container, nb_sites) for site_num, site in enumerate(config[page.username]['site_security']): format_site_security_options(info_container, site, site_num, page) add_button(info_container, nb_sites) return
def expected_output_process(dummy, elem, uid): """Displays and saves a copy of the expected output""" vlam = elem.attrib["title"] name = extract_name(vlam) expected_output = elem.text # We assume that the author has written the expected output as # <pre ...> # starts on this line... # </pre> # When doing so, the newline at the end of the opening <pre...> needs # to be discarded so that it can be compared with the real output. if expected_output.startswith("\r\n"): expected_output = expected_output[2:] elif expected_output.startswith("\n\r"): expected_output = expected_output[2:] elif expected_output.startswith("\n"): expected_output = expected_output[1:] # which we store expected_outputs[name] = expected_output # reset the original element to use it as a container. For those # familiar with dealing with ElementTree Elements, in other context, # note that the style_pycode() method extracted all of the existing # text, removing any original markup (and other elements), so that we # do not need to save either the "text" attribute or the "tail" one # before resetting the element. elem.clear() elem.tag = "div" elem.attrib["id"] = "div_" + uid elem.attrib['class'] = "test_output" # Create a title h4 = SubElement(elem, 'h4') h4.text = "Expected output; name= %s" % name # a container with the expected output pre = SubElement(elem, "pre") pre.text = expected_output
def analyzer_widget_callback(page, elem, uid): """Handles embedding suitable code into the page in order to display and run the analyzer""" vlam = elem.attrib["title"] log_id = extract_log_id(vlam) if log_id: t = 'analyzer' config[page.username]['logging_uids'][uid] = (log_id, t) elem.attrib['title'] = "python" analyzercode, show_vlam = plugin['services'].style(page, elem, None, vlam) elem.attrib['title'] = vlam if log_id: config['log'][log_id] = [tostring(markup)] wrap_in_div(elem, uid, vlam, "analyzer", show_vlam) #insert_markup(elem, uid, vlam, markup, "analyzer") # call the insert_editor_subwidget service to insert an editor: plugin['services'].insert_editor_subwidget(page, elem, uid, analyzercode) #some spacing: SubElement(elem, "br") # use the insert_analyzer_button service as any plugin can do insert_analyzer_button(page, elem, uid) SubElement(elem, "br") # finally, an output subwidget: plugin['services'].insert_io_subwidget(page, elem, uid)
def hidden_code_widget_callback(page, elem, uid): """Handles embedding suitable code into the page in order to display and run code samples""" vlam = elem.attrib["title"] config["extracted_lines"][uid] = [] # When a security mode is set to "display ...", we only parse the # page, but no Python execution from is allowed from that page. # If that is the case, we won't include javascript either, to make # thus making the source easier to read. if 'display' not in config[page.username]['page_security_level'](page.url): if not page.includes("hidden_code_included"): page.add_include("hidden_code_included") page.add_js_code(hidden_code_jscode) elem.attrib['title'] = "py" complete_code, show_vlam = plugin['services'].style(page, elem, None, vlam) # _lines = complete_code.split('\n') displayed_lines = [] hidden_lines = [] hide = False for _line in _lines: if hide: if _line.strip() == HIDDEN_CODE_END: hide = False config["extracted_lines"][uid].append('\n'.join(hidden_lines)) else: hidden_lines.append(_line) else: if _line.strip() == HIDDEN_CODE_BEGIN: hide = True hidden_lines = [] displayed_lines.append(HIDDEN_CODE_MARKER) else: displayed_lines.append(_line) complete_code = '\n'.join(displayed_lines) elem.attrib['title'] = vlam elem.attrib["class"] += " hidden" elem.attrib["id"] = "hidden_pre_" + uid wrap_in_div(elem, uid, vlam, "hidden_code", show_vlam) btn = SubElement(elem, "button") btn.text = _("Show/hide complete code") btn.attrib["onclick"] = "$('#%s').toggle()" % ("hidden_pre_" + uid) plugin['services'].insert_editor_subwidget(page, elem, uid, complete_code) SubElement(elem, "br") btn = SubElement(elem, "button") btn.attrib["id"] = "run_code_btn_" + uid btn.text = _("Run Code") btn.attrib["onclick"] = "exec_hidden_code('%s')" % uid SubElement(elem, "br") plugin['services'].insert_io_subwidget(page, elem, uid)
def create_empty_menu(): # tested '''creates the basic menu structure including only the title''' menu = Element('div') menu.attrib['class'] = "crunchy_menu" _ul = SubElement(menu, "ul") _li = SubElement(_ul, "li") _li.text = _("Crunchy Menu") menu_items = SubElement(_li, "ul") return menu, menu_items
def unittest_widget_callback(page, elem, uid): """Handles embedding suitable code into the page in order to display and run unittests""" vlam = elem.attrib["title"] log_id = extract_log_id(vlam) if log_id: t = 'unittest' config[page.username]['logging_uids'][uid] = (log_id, t) # When a security mode is set to "display ...", we only parse the # page, but no Python execution from is allowed from that page. # If that is the case, we won't include javascript either, to make # thus making the source easier to read. if 'display' not in config[page.username]['page_security_level'](page.url): if not page.includes("unittest_included"): page.add_include("unittest_included") page.add_js_code(unittest_jscode) elem.attrib['title'] = "python" unittestcode, show_vlam = plugin['services'].style(page, elem, None, vlam) elem.attrib['title'] = vlam if log_id: config['log'][log_id] = [tostring(markup)] # which we store unittests[uid] = unittestcode wrap_in_div(elem, uid, vlam, "doctest", show_vlam) if config[page.username]['popups']: # insert popup helper img = Element("img", src="/images/help.png", style="height:32px;", title="cluetip Hello %s! " % page.username + "This is a unittest.; click for more.", rel="/docs/popups/unittest.html") elem.append(img) plugin['services'].insert_cluetip(page, img, uid) #insert_markup(elem, uid, vlam, markup, "unittest") # call the insert_editor_subwidget service to insert an editor: plugin['services'].insert_editor_subwidget(page, elem, uid) #some spacing: SubElement(elem, "br") # the actual button used for code execution: btn = SubElement(elem, "button") btn.text = "Run Unittest" btn.attrib["onclick"] = "exec_unittest('%s')" % uid if "analyzer_score" in vlam: plugin['services'].add_scoring(page, btn, uid) if "analyzer_report" in vlam: plugin['services'].insert_analyzer_button(page, elem, uid) SubElement(elem, "br") # finally, an output subwidget: plugin['services'].insert_io_subwidget(page, elem, uid)
def add_button(info_container, nb_sites): '''adds button for site approval or removal''' approve_btn = SubElement(info_container, "button", onclick="app_approve(%d)" % nb_sites) approve_btn.text = _("Approve") SubElement(info_container, "span").text = " " deny_btn = SubElement(info_container, "button", onclick="app_remove_all()") deny_btn.text = _("Remove all") return
def code_sample_process(page, elem, uid): """Style and saves a copy of the sample code. This code currently does not work because it depends on the obsoleted style_pycode service in the colourize plugin.""" raise NotImplementedError() vlam = elem.attrib["title"] name = extract_name(vlam) names[uid] = name # When a security mode is set to "display ...", we only parse the # page, but no Python execution from is allowed from that page. # If that is the case, we won't include javascript either, to make # thus making the source easier to read. if 'display' not in config[page.username]['page_security_level'](page.url): if not page.includes("code_test_included"): page.add_include("code_test_included") page.add_js_code(code_test_jscode) page.add_js_code(complete_test_jscode) page.add_css_code(css) insert_comprehensive_test_button(page) # next, we style the code, also extracting it in a useful form sample_code, markup, error = plugin['services'].style_pycode(page, elem) if error is not None: markup = copy.deepcopy(elem) # which we store code_samples[name] = sample_code # reset the original element to use it as a container. For those # familiar with dealing with ElementTree Elements, in other context, # note that the style_pycode() method extracted all of the existing # text, removing any original markup (and other elements), so that we # do not need to save either the "text" attribute or the "tail" one # before resetting the element. elem.clear() elem.tag = "div" elem.attrib["id"] = "div_" + uid elem.attrib['class'] = "crunchy" # We insert the styled sample code inside this container element: elem.append(markup) # Create a title h4 = Element('h4') h4.text = "Sample code; name= %s" % name elem.insert(0, h4) #some spacing: SubElement(elem, "br") # the actual button used for code execution: btn = SubElement(elem, "button") btn.text = "Run code check" btn.attrib["onclick"] = "exec_code_check('%s')" % uid SubElement(elem, "br") # finally, an output subwidget: plugin['services'].insert_io_subwidget(page, elem, uid) return
def add_hidden_load_and_save(page, elem, textarea_id): # tested ''' adds hidden load and save javascript objects on a page ''' hidden_load_id = 'hidden_load' + textarea_id hidden_load = SubElement(elem, 'div', id=hidden_load_id) hidden_load.attrib['class'] = 'load_file' add_load_file(page, hidden_load, hidden_load_id, textarea_id) hidden_save_id = 'hidden_save' + textarea_id hidden_save = SubElement(elem, 'div', id=hidden_save_id) hidden_save.attrib['class'] = 'save_file' add_save_file(page, hidden_save, hidden_save_id, textarea_id) return
def insert_file_browser(page, elem, uid, action, title, js_script, klass): '''inserts a file tree object in a page.''' if 'display' not in config[page.username]['page_security_level'](page.url): if not page.includes("jquery_file_tree"): page.add_include("jquery_file_tree") page.insert_js_file("/javascript/jquery.filetree.js") page.insert_css_file("/css/jquery.filetree.css") else: return tree_id = "tree_" + uid root = local_browser_root # use value specified in config.py by default if not os.path.exists(root): root = os.path.splitdrive(__file__)[0] + "/" # use base directory js_code = """$(document).ready( function() { $('#%s').fileTree({ root: '%s', script: '%s', expandSpeed: -1, collapseSpeed: -1, multiFolder: false }, function(file) { %s }); }); """ % (tree_id, root, action, js_script) page.add_js_code(js_code) elem.text = title elem.attrib['class'] = klass file_div = SubElement(elem, 'div') file_div.attrib['id'] = tree_id file_div.attrib['class'] = "filetree_window" return
def add_configuration_to_menu(page): '''adds a menu item allowing the user to choose the preferences''' menu_item = Element("li") link = SubElement(menu_item, 'a', href="/docs/basic_tutorial/preferences.html") link.text = _("Preferences") additional_menu_items['preferences'] = menu_item
def add_browsing_to_menu(dummy): '''adds a menu item allowing the user to go the the browsers page''' menu_item = Element("li") link = SubElement(menu_item, 'a', href="/docs/basic_tutorial/browsing.html") link.text = _("Browsing") additional_menu_items['browsing'] = menu_item
def insert_analyzer_button(page, elem, uid): """inserts an Elementtree that is an button to make a report on the code quality. Return the inserted button """ # Form to select the analyzer SubElement(elem, "br") form1 = SubElement(elem, 'form', name='form1_' + uid) span = SubElement(form1, 'span') span.text = _('Analyzer: ') span.attrib['class'] = 'analyzer' select = SubElement(form1, 'select', id='analyzer_' + uid) analyzer_names = configuration.options['analyzer'] for name in analyzer_names: if name is None: analyzer = str(None) else: analyzer = name.replace('analyzer_', '') option = SubElement(select, 'option', value=analyzer) option.text = analyzer if analyzer == str(config[page.username]['analyzer']): option.attrib['selected'] = 'selected' SubElement(elem, "br") if 'display' not in config[page.username]['page_security_level'](page.url): if not page.includes("analyzer_included"): page.add_include("analyzer_included") page.add_js_code(analyzer_jscode) btn = SubElement(elem, "button") btn.text = _("Analyze the code") btn.attrib["onclick"] = "exec_analyzer('%s')" % uid # add the display of the score add_scoring(page, btn, uid)
def rst_edit_setup(page, elem, uid): elem.tag = "div" # editor textarea = SubElement(elem, "textarea", name="rst_enter") textarea.attrib["id"] = uid + "_rst_edit" textarea.attrib["class"] = "rst_enter" textarea.text = elem.text elem.text = '' plugin['services'].enable_editarea(page, elem, textarea.attrib["id"], syntax="robotstxt") if not page.includes("editarea_included"): page.add_include("editarea_included") page.add_js_code(editArea_load_and_save) page.insert_js_file("/edit_area/edit_area_crunchy.js") # save html button = SubElement(elem, "button") button.text = _("Save html") # preview area div = SubElement(elem, "div") div.attrib["id"] = "html_preview" page.add_js_code(js_code) # hidden save file hidden_div = SubElement(elem, "div") h_uid = "hidden_div_" + uid hidden_div.attrib["id"] = h_uid button.attrib["onclick"] = show_save_file_js % h_uid add_save_file(page, hidden_div, h_uid, div.attrib["id"]) page.add_js_code(save_html_file_js % (h_uid, h_uid)) if page.is_local: src.interface.path_info['source_base_dir'] = page.url else: src.interface.path_info['source_base_dir'] = os.path.normpath( os.path.join(plugin['crunchy_base_dir'](), "server_root", page.url[1:])) base_dir = os.path.dirname(src.interface.path_info['source_base_dir']) if base_dir not in sys.path: sys.path.insert(0, base_dir)
def insert_traceback(page, elem, tb): '''inserts a traceback, nicely styled.''' pre = SubElement(elem, "pre") vlam = "pytb" pre.attrib['title'] = vlam pre.text = tb dummy, dummy = plugin['services'].style(page, pre, None, vlam) # prevent any further processing pre.attrib["title"] = "no_vlam" return
def add_save_file(page, parent, hidden_save_id, textarea_id): '''Inserts the widget required to browse for and save a local Python file. This is intended to be used to save a file from the editor. ''' input_id = "input_" + hidden_save_id js_saved_script = """save_file(document.getElementById('%s').value, '%s');""" % (input_id, textarea_id) SubElement(parent, "br") SubElement(parent, 'input', name='url', size='60', id=input_id) SubElement(parent, "br") btn = SubElement(parent, 'button', onclick=js_saved_script) btn.text = _("Save file") js_script = """document.getElementById('%s').value=file;""" % input_id insert_file_browser(page, parent, hidden_save_id, '/jquery_file_tree_all', _('Select a file to save'), js_script, "save_file") btn = SubElement(parent, 'button', onclick="c=getElementById('%s');c.style.visibility='hidden';c.style.zIndex=-1;"%hidden_save_id) btn.text = _("Cancel") return
def insert_load_remote(dummy_page, parent, dummy_uid): # tested '''inserts a form to load a remote page''' # in general, page and uid are used by similar plugins, but they are # redundant here. div = SubElement(parent, "div") p = SubElement(div, "p") p.text = _("Type url of remote tutorial.") form = SubElement(div, 'form', name='url', size='80', method='get', action='/remote') SubElement(form, 'input', name='url', size='80', value=parent.text) input2 = SubElement(form, 'input', type='submit', value=_('Load remote tutorial')) input2.attrib['class'] = 'crunchy' parent.text = ' '
def add_load_file(page, parent, hidden_load_id, textarea_id): '''Inserts the widget required to browse for and load a local Python file. This is intended to be used to load a file in the editor. ''' js_script = """path = file; load_file('%s')""" % textarea_id insert_file_browser(page, parent, hidden_load_id, '/jquery_file_tree_all', _('Select a file to open'), js_script, "load_file") btn = SubElement(parent, 'button', onclick="c=getElementById('%s');c.style.visibility='hidden';c.style.zIndex=-1;"%hidden_load_id) btn.text = _("Cancel") return
def create_security_menu_item(page): '''creates the security report menu item''' if 'display' in page.security_info['level']: security_result_image = '/images/display.png' elif page.security_info['number removed'] == 0: security_result_image = '/images/ok.png' else: security_result_image = '/images/warning.png' security_item = Element("li") a = SubElement(security_item, "a", id="security_info_link", href="#", onclick="show_security_info();", title="security_link") a.text = "Security: " SubElement(a, "img", src=security_result_image) additional_menu_items['security_report'] = security_item return
def insert_alternate_python(page, elem, uid): """inserts the required widget to launch a Python script using an alternate Python version. """ vlam = insert_bare_editor(page, elem, uid) form1 = SubElement(elem, 'form', name='form1_') span = SubElement(form1, 'span') span.text = _('Alternate Python path: ') span.attrib['class'] = 'alt_python' input1 = SubElement( form1, 'input', id='input1_' + uid, size='50', value=config[page.username]['alternate_python_version']) input1.attrib['class'] = 'alt_python' SubElement(elem, "br") btn = SubElement(elem, "button") btn.attrib[ "onclick"] = "exec_code_externally_python_interpreter('%s')" % uid btn.text = _("Execute as external program") if "analyzer_score" in vlam: plugin['services'].add_scoring(page, btn, uid) if "analyzer_report" in vlam: plugin['services'].insert_analyzer_button(page, elem, uid) path_label = SubElement(elem, "span", id='path_' + uid) path_label.text = config[ page.username]['temp_dir'] + os.path.sep + "temp.py" path_label.attrib['class'] = 'path_info'
def format_site_security_options(parent, site, site_num, page): '''adds the various security options for a given site''' options = [ 'trusted', 'normal', 'strict', 'display trusted', 'display normal', 'display strict' ] if 'localhost' not in site: options.append('remove') fieldset = SubElement(parent, "fieldset") site_label = SubElement(fieldset, "legend") site_label.text = site form = SubElement(fieldset, "form") form.attrib['id'] = "site_" + str(site_num + 1) form.attrib['name'] = site for option in options: label = SubElement(form, 'label') if option == 'remove': label.text = _('remove from list') else: label.text = option label.attrib['for'] = site + option inp = SubElement(label, 'input', value=option, type='radio', name='rad', id=site + option) SubElement(form, 'br') if site in config[page.username]['site_security']: if option == config[page.username]['site_security'][site]: inp.attrib['checked'] = 'checked' elif 'localhost' in site: if option == config[page.username]['local_security']: inp.attrib['checked'] = 'checked' return
def insert_editor_subwidget(page, elem, uid, code="\n"): # tested """inserts an Elementtree that is an editor, used to provide a basic insert_editor_subwidget service """ inp = SubElement(elem, "textarea") inp.attrib["rows"] = "10" inp.attrib["cols"] = "80" editor_id = "code_" + uid inp.attrib["id"] = editor_id if code == "": code = "\n" inp.text = code plugin['services'].enable_editarea(page, elem, editor_id)
def render(self, elem): """render the widget to a particular file object""" row = SubElement(elem, 'tr') option = SubElement(row, 'td') label = SubElement(option, 'label') label.attrib['for'] = self.key label.text = "%s: " % self.key # we use a unique id, rather than simply the key, in case two # identical preference widgets are on the same page... _id = str(self.uid) + "__KEY__" + str(self.key) input = SubElement( option, 'input', type='text', id=_id, name=self.key, value=self.get(), onchange="growl_show('%s');set_config('%s', '%s');" % (self.key, _id, self.key)) input.attrib['class'] = 'config_gui' desc = SubElement(row, 'td') desc.text = str( getattr(get_prefs(self.username).__class__, self.key).__doc__)
def insert_interactive_objects(page): '''inserts the interactive objects required in a slideshow''' if not page.includes("slideshow_included"): return for div in page.tree.getiterator("div"): if 'class' in div.attrib: if div.attrib['class'] == "presentation": # add slide with interpreter new_div = Element("div") new_div.attrib['class'] = "slide" # new_div is not processed by set_overflow above which is why # we must set this property explictly. new_div.attrib['style'] = "height: 70%; overflow: auto;" new_div.attrib['id'] = "crunchy_interpreter" pre = SubElement(new_div, "pre", title="interpreter") # the following text is at least 50 characters # with a non-space character at the end. This is to allow # the creation of a list with "short" titles to select # a given slide. # see slides.js line 100 pre.text = "# Crunchy Interpreter #" uid = page.pageid + "_" + uidgen(page.username) plugin['services'].insert_interpreter(page, pre, uid) div.append(new_div) # add slide with editor new_div2 = Element("div") new_div2.attrib['class'] = "slide" # new_div2 is not processed by set_overflow above ... new_div2.attrib['style'] = "height: 70%; overflow: auto;" new_div2.attrib['id'] = "crunchy_editor" pre2 = SubElement(new_div2, "pre", title="editor") # same as above. pre2.text = "# Crunchy editor #" uid = page.pageid + "_" + uidgen(page.username) plugin['services'].insert_editor(page, pre2, uid) div.append(new_div2) return
def insert_editor(page, elem, uid, lines, lineno): '''insert the an editor as usual''' # Note: in developping this plugin, we observed that the code was styled # automatically - that is the "div/getsource" handler was called before the # "pre" handler was. This could just be a coincidence on which we can not # rely. pre = SubElement(elem, "pre") if python_version < 3: vlam = "python" else: vlam = "python3" if "linenumber" in elem.attrib['title']: vlam += " linenumber=%s"%lineno pre.attrib['title'] = vlam pre.text ="".join(lines) plugin['services'].insert_editor(page, pre, uid) # prevent any further processing pre.attrib["title"] = "no_vlam" return
def insert_preferences(page, elem, uid): '''insert the requested preference choosers on a page''' if not page.includes("set_config"): page.add_include("set_config") page.add_js_code(set_config_jscode) page.add_js_code(gritter_jscode) page.add_include("jquery.gritter.js") page.insert_js_file("/javascript/jquery.gritter.js") page.insert_css_file("/css/gritter.css") # The original div in the raw html page may contain some text # as a visual reminder that we need to remove here. elem.text = '' elem.attrib['class'] = 'config_gui' parent = SubElement(elem, 'table') username = page.username to_show = elem.attrib['title'].split(' ') if len(to_show) == 1: # choices = "preferences"; all values are shown to_show = ['boolean', 'multiple_choice', 'user_defined'] show(parent, username, uid, to_show) return
def insert_editor(page, elem, uid): """handles the editor widget""" vlam = insert_bare_editor(page, elem, uid) #log_id = util.extract_log_id(vlam) SubElement(elem, "br") if not ("no_internal" in vlam and "external" in vlam): btn1 = SubElement(elem, "button") btn1.attrib["onclick"] = "exec_code('%s')" % uid SubElement(elem, "br") btn2 = SubElement(elem, "button", id="run_from_file_" + uid) btn2.attrib["onclick"] = "exec_code_externally('%s')" % uid btn2.text = _("Save and Run from file") path_label = SubElement(elem, "span") path_label.attrib['id'] = 'path_' + uid path_label.attrib['class'] = 'path_info' if "external" in vlam: path_label.text = config[ page.username]['temp_dir'] + os.path.sep + "temp.py" if "analyzer_score" in vlam: plugin['services'].add_scoring(page, btn2, uid) if not "no_internal" in vlam: btn1.text = _("Execute as separate thread") else: path_label.text = "" # effectively hides it. btn1.text = _("Execute") # Note that btn2 will be revealed by execution code when a file is saved; # see editarea.py for this. btn2.attrib['style'] = "display:none;" if "analyzer_score" in vlam: plugin['services'].add_scoring(page, btn1, uid) if "analyzer_report" in vlam: SubElement(elem, "br") plugin['services'].insert_analyzer_button(page, elem, uid) SubElement(elem, "br") plugin['services'].insert_io_subwidget(page, elem, uid)
def format_table(parent, title, headings, content): '''formats a report in a standard table form''' h2 = SubElement(parent, 'h2') h2.text = title h2.attrib['class'] = "crunchy" table = SubElement(parent, 'table') table.attrib['class'] = 'summary' tr = SubElement(table, 'tr') for item in headings: th = SubElement(tr, 'th') th.text = item for item in content: tr = SubElement(table, 'tr') for cell in item: td = SubElement(tr, 'td') td.text = str(cell) return
def create_quit(): # tested '''creates the quit element for the menu''' Quit = Element("li") a = SubElement(Quit, "a", href=server['exit']) a.text = _("Quit Crunchy") return Quit
def create_home(): # tested '''creates the home element for the menu''' home = Element("li") a = SubElement(home, "a", href="/index.html") a.text = _("Crunchy Home") return home