def __setstate__(self, state): super(NotebookBlockCode, self).__setstate__(state) self.__code = state.get('code') if self.__code is None: self.__code = source_code.PythonCode() self.__result = None self.__incr = IncrementalValueMonitor()
class LiveValue (AbstractLive): def __init__(self, value=None): self.__incr = IncrementalValueMonitor(self) self.__value = value @property def incremental_monitor(self): return self.__incr @property def value(self): self.__incr.on_access() return self.__value @value.setter def value(self, v): self.__value = v self.__incr.on_changed() @property def static_value(self): return self.__value
def __init__(self, blocks=None): if blocks is None: blocks = [NotebookBlockCode(self)] self.__blocks = blocks self.__incr = IncrementalValueMonitor() self._module = None self.__execution_state = LiveValue() self.__exec_state_init()
def __setstate__(self, state): self.__blocks = state.get('blocks') if self.__blocks is None: self.__blocks = [] self.__incr = IncrementalValueMonitor() self._module = None self.__execution_state = LiveValue() self.__exec_state_init()
def __init__(self, notebook, language, var_name='src'): super(NotebookBlockSource, self).__init__(notebook) try: code_type = self.__language_to_type_map[language] except KeyError: raise ValueError, 'Invalid language {0}'.format(language) self.__code = code_type() self.__var_name = LiveValue(var_name) self.__incr = IncrementalValueMonitor()
def __init__(self, xs=None): self._items = [] if xs is not None: self._items[:] = xs[:] self.__change_history__ = None self._incr = IncrementalValueMonitor() self.__change_listener = None
def __init__(self, app, category, path, loc_prefix, app_context, on_docs_loaded): self.__incr = IncrementalValueMonitor() self.category = category self.__app_context = app_context self.__imported_module_registry = ImportedModuleRegistry() self._app = app self.__path = path self.__loc_prefix = loc_prefix self.__documents = [] self.__docs_by_location = {} self.__docs_by_filename = {} self.__load_documents(on_docs_loaded)
class AbstractConsole(object): def __init__(self, code=''): self.__blocks = [] self.__current_block = CurrentBlock( self._source_text_to_code_object(code), self) self.__incr = IncrementalValueMonitor() def _execute_current_block(self, block): result = self._get_result_of_executing_code(block.code) block.code.editable = False self.__blocks.append(ConsoleBlock(block.code, result)) self.__current_block = CurrentBlock( self._source_text_to_code_object(''), self) self.__incr.on_changed() def __present__(self, fragment): self.__incr.on_access() preamble = self._get_console_preamble_text( ) + '\n' + 'Press Control+Enter to execute.' contents = [ '<div class="python_console_header">{0}</div>'.format( preamble.replace('\n', '<br>')) ] notifications = self._get_console_notifications() if notifications is not None: contents.append('<div class="console_notifications">') contents.append(notifications) contents.append('</div>') for block in self.__blocks + [self.__current_block]: contents.extend(['<div>', block, '</div>']) return Html(*contents).use_css('/static/larch/console.css') def _source_text_to_code_object(self, source_text): raise NotImplementedError, 'abstract' def _get_result_of_executing_code(self, code): raise NotImplementedError, 'abstract' def _get_console_preamble_text(self): raise NotImplementedError, 'abstract' def _get_console_notifications(self): return None
class NotebookBlockCode (NotebookBlock): def __init__(self, notebook, code=None): super(NotebookBlockCode, self).__init__(notebook) self.__code = source_code.PythonCode(code=code) self.__result = None self.__incr = IncrementalValueMonitor() def __getstate__(self): state = super(NotebookBlockCode, self).__getstate__() state['code'] = self.__code return state def __setstate__(self, state): super(NotebookBlockCode, self).__setstate__(state) self.__code = state.get('code') if self.__code is None: self.__code = source_code.PythonCode() self.__result = None self.__incr = IncrementalValueMonitor() def execute(self, module): self.__result = self.__code.execute_in_module(module) self.__incr.on_changed() def __present__(self, fragment): self.__incr.on_access() header = Html('<div class="notebook_python_code_header">Python code (executable)</div>') code = Html('<div class="notebook_python_code_container notebook_code_container">', self.__code, '</div>') res = ['<div class="notebook_result_container">', self.__result, '</div>'] if self.__result is not None else [] p = Html(*(['<div class="notebook_code_block">', header, '<div class="notebook_code_block_body">', code] + res + ['</div></div>'])) p = focusable.focusable(p) return p
class ToolList (object): def __init__(self): self.contents = [] self.__incr = IncrementalValueMonitor() def add(self, box): box._tool_list = self self.contents.append(box) self.__incr.on_changed() def close(self, box): self.contents.remove(box) self.__incr.on_changed() def __present__(self, fragment): self.__incr.on_access() return Html(*self.contents)
def __init__(self, value=None): self.__incr = IncrementalValueMonitor(self) self.__value = value
def __init__(self, notebook, code=None): super(NotebookBlockCode, self).__init__(notebook) self.__code = source_code.PythonCode(code=code) self.__result = None self.__incr = IncrementalValueMonitor()
class DocumentList (object): def __init__(self, app, category, path, loc_prefix, app_context, on_docs_loaded): self.__incr = IncrementalValueMonitor() self.category = category self.__app_context = app_context self.__imported_module_registry = ImportedModuleRegistry() self._app = app self.__path = path self.__loc_prefix = loc_prefix self.__documents = [] self.__docs_by_location = {} self.__docs_by_filename = {} self.__load_documents(on_docs_loaded) @property def path(self): return self.__path @property def loc_prefix(self): return self.__loc_prefix def __iter__(self): return iter(self.__documents) def doc_for_location(self, location): return self.__docs_by_location.get(location) def doc_for_filename(self, filename): return self.__docs_by_filename.get(filename) def unused_filename(self, filename): if filename not in self.__docs_by_filename: return filename index = 0 while True: name = filename + '_' + str(index) if name not in self.__docs_by_filename: return name index += 1 def __add_document(self, doc): self.__documents.append(doc) self.__docs_by_location[doc.location] = doc self.__docs_by_filename[doc.filename] = doc self.__incr.on_changed() def new_document_for_content(self, name, content_factory): if name in self.__docs_by_filename: raise DocumentNameInUseError, name # Document file names do NOT include the extension filename = _sanitise_filename(name) file_path = os.path.join(self.__path, filename + '.ularch') def on_doc_created(doc): doc.save() self.__add_document(doc) Document.for_content(on_doc_created, self, name, filename, file_path, content_factory, self.__app_context, self.__imported_module_registry) def reload(self): self.__documents = [] self.__docs_by_location = {} self.__docs_by_filename = {} self.__load_documents(None) self.__incr.on_changed() def __load_documents(self, on_all_docs_loaded): file_paths = glob.glob(os.path.join(self.__path, '*' + _EXTENSION)) num_docs_to_load = len(file_paths) docs_loaded = [0] def on_doc_loaded(doc): self.__add_document(doc) docs_loaded[0] += 1 if docs_loaded[0] == num_docs_to_load and on_all_docs_loaded is not None: on_all_docs_loaded() for p in sorted(file_paths): Document.load(on_doc_loaded, self._app, self, p, self.__app_context, self.__imported_module_registry) def __doc_table_row(self, doc, page): def on_save(event): doc.save_and_display_notification(page) save_button = button.button('Save', on_save) doc_title = '<a href="/pages/{0}/{1}" class="larch_app_doc_title">{2}</a>'.format(self.loc_prefix, doc.location, doc.name) doc_filename = '<span class="larch_app_doc_filename">{0}</span><span class="larch_app_doc_extension">.ularch</span>'.format(doc.filename) controls = Html('<div class="larch_app_doc_controls">', save_button, '</div>') return Html('<tr class="larch_app_doc"> <td>', doc_title, '</td><td>', doc_filename, '</td><td>', controls, '</td></tr>') def __present__(self, fragment): self.__incr.on_access() contents = ['<table class="larch_app_doc_list">'] contents.append('<thead class="larch_app_doc_list_header"><td>Title</td><td>Filename</td><td>Save</td></thead>') contents.append('<tbody>') contents.extend([self.__doc_table_row(doc, fragment.page) for doc in self.__documents]) contents.append('</tbody></table>') return Html(*contents)
def __setstate__(self, state): super(NotebookBlockSource, self).__setstate__(state) self.__code = state.get('code') self.__var_name = LiveValue(state.get('var_name')) self.__incr = IncrementalValueMonitor()
class Notebook (object): def __init__(self, blocks=None): if blocks is None: blocks = [NotebookBlockCode(self)] self.__blocks = blocks self.__incr = IncrementalValueMonitor() self._module = None self.__execution_state = LiveValue() self.__exec_state_init() def __exec_state_init(self): self.__execution_state.value = Html('<span class="notebook_exec_state_init">CODE NOT EXECUTED</span>') def __exec_state_executed(self): self.__execution_state.value = Html('') def __getstate__(self): return {'blocks': self.__blocks} def __setstate__(self, state): self.__blocks = state.get('blocks') if self.__blocks is None: self.__blocks = [] self.__incr = IncrementalValueMonitor() self._module = None self.__execution_state = LiveValue() self.__exec_state_init() def append(self, block): self.__blocks.append(block) self.__incr.on_changed() def execute(self): self._module = imp.new_module('<Notebook>') larch_builtins.init_module(self._module) self.__execute_in_module(self._module) self.__exec_state_executed() def __execute_in_module(self, module): for block in self.__blocks: block.execute(module) def _insert_block(self, block_to_insert, below, focus_block): index = len(self.__blocks) if focus_block is not None and focus_block in self.__blocks: index = self.__blocks.index(focus_block) if below: index += 1 self.__blocks.insert(index, block_to_insert) self.__incr.on_changed() def _delete_block(self, focus_block): if focus_block is not None and focus_block in self.__blocks: self.__blocks.remove(focus_block) self.__incr.on_changed() def __load_module__(self, document, fullname): try: return sys.modules[fullname] except KeyError: pass mod = document.new_module(fullname, self) self.__execute_in_module(mod) return mod def _save_containing_document_and_display_notification(self, fragment): subject = fragment.subject try: save_and_display_notification = subject.document.save_and_display_notification except AttributeError: print 'WARNING: Could not save; method unavailable' raise else: save_and_display_notification(fragment) def _unload_from_containing_document_and_display_notification(self, fragment): subject = fragment.subject try: unload_modules_and_display_notification = subject.document.unload_modules_and_display_notification except AttributeError: print 'WARNING: Could not unload_modules_and_display_notification; method unavailable' raise else: unload_modules_and_display_notification(fragment) def __focused_block(self, page): seg = page.focused_segment if seg is not None: frag = seg.fragment return frag.find_enclosing_model(NotebookBlock) else: return None def __commands__(self, page): return [ command.Command([command.Key(ord('R'))], 'Insert rich text below', lambda page: self._insert_block(NotebookBlockText(self), True, self.__focused_block(page))), command.Command([command.Key(ord('P'))], 'Insert Python code below', lambda page: self._insert_block(NotebookBlockCode(self), True, self.__focused_block(page))), command.Command([command.Key(ord('J'))], 'Insert Javascript source below', lambda page: self._insert_block(NotebookBlockSource(self, 'js', 'js'), True, self.__focused_block(page))), command.Command([command.Key(ord('C'))], 'Insert CSS source below', lambda page: self._insert_block(NotebookBlockSource(self, 'css', 'css'), True, self.__focused_block(page))), command.Command([command.Key(ord('T'))], 'Insert HTML source below', lambda page: self._insert_block(NotebookBlockSource(self, 'html', 'html'), True, self.__focused_block(page))), command.Command([command.Key(ord('G'))], 'Insert GLSL source below', lambda page: self._insert_block(NotebookBlockSource(self, 'glsl', 'glsl'), True, self.__focused_block(page))), command.Command([command.Key(ord('A')), command.Key(ord('R'))], 'Insert rich text below', lambda page: self._insert_block(NotebookBlockText(self), False, self.__focused_block(page))), command.Command([command.Key(ord('A')), command.Key(ord('P'))], 'Insert Python code below', lambda page: self._insert_block(NotebookBlockCode(self), False, self.__focused_block(page))), command.Command([command.Key(ord('A')), command.Key(ord('J'))], 'Insert Javascript source below', lambda page: self._insert_block(NotebookBlockSource(self, 'js', 'js'), False, self.__focused_block(page))), command.Command([command.Key(ord('A')), command.Key(ord('C'))], 'Insert CSS source below', lambda page: self._insert_block(NotebookBlockSource(self, 'css', 'css'), False, self.__focused_block(page))), command.Command([command.Key(ord('A')), command.Key(ord('T'))], 'Insert HTML source below', lambda page: self._insert_block(NotebookBlockSource(self, 'html', 'html'), False, self.__focused_block(page))), command.Command([command.Key(ord('A')), command.Key(ord('G'))], 'Insert GLSL source below', lambda page: self._insert_block(NotebookBlockSource(self, 'glsl', 'glsl'), False, self.__focused_block(page))), command.Command([command.Key(ord('X'))], 'Remove block', lambda page: self._delete_block(self.__focused_block(page))), ] def __menu_bar_contents__(self, page, fragment): # # File menu # def on_save(): self._save_containing_document_and_display_notification(fragment) def on_unload(): self._unload_from_containing_document_and_display_notification(fragment) save_item = menu.item('Save (Ctrl+S)', lambda event: on_save()) unload_modules_item = menu.item('Unload modules', lambda event: on_unload()) file_menu_contents = menu.sub_menu('File', [save_item, menu.separator(), unload_modules_item]) file_menu = menu.menu([file_menu_contents], drop_down=True) # # Edit menu # def _insert_rich_text(below): self._insert_block(NotebookBlockText(self), below, self.__focused_block(fragment.page)) def _insert_code(below): self._insert_block(NotebookBlockCode(self), below, self.__focused_block(fragment.page)) def _insert_js(below): self._insert_block(NotebookBlockSource(self, 'js', 'js'), below, self.__focused_block(fragment.page)) def _insert_css(below): self._insert_block(NotebookBlockSource(self, 'css', 'css'), below, self.__focused_block(fragment.page)) def _insert_glsl(below): self._insert_block(NotebookBlockSource(self, 'glsl', 'glsl'), below, self.__focused_block(fragment.page)) def _insert_html(below): self._insert_block(NotebookBlockSource(self, 'html', 'html'), below, self.__focused_block(fragment.page)) insert_rich_text_above = menu.item('Insert rich text above', lambda event: _insert_rich_text(False)) insert_code_above = menu.item('Insert executable Python code above', lambda event: _insert_code(False)) insert_js_above = menu.item('Insert JS source above', lambda event: _insert_js(False)) insert_css_above = menu.item('Insert CSS source above', lambda event: _insert_css(False)) insert_html_above = menu.item('Insert HTML source above', lambda event: _insert_html(False)) insert_glsl_above = menu.item('Insert GLSL source above', lambda event: _insert_glsl(False)) insert_rich_text_below = menu.item('Insert rich text below', lambda event: _insert_rich_text(True)) insert_code_below = menu.item('Insert executable Python code below', lambda event: _insert_code(True)) insert_js_below = menu.item('Insert JS source below', lambda event: _insert_js(True)) insert_css_below = menu.item('Insert CSS source below', lambda event: _insert_css(True)) insert_html_below = menu.item('Insert HTML source below', lambda event: _insert_html(True)) insert_glsl_below = menu.item('Insert GLSL source below', lambda event: _insert_glsl(True)) remove_block = menu.item('Remove block', lambda event: self._delete_block(self.__focused_block(fragment.page))) edit_menu_contents = menu.sub_menu('Edit', [ insert_rich_text_above, insert_code_above, insert_js_above, insert_css_above, insert_html_above, insert_glsl_above, menu.separator(), insert_rich_text_below, insert_code_below, insert_js_below, insert_css_below, insert_html_below, insert_glsl_below, menu.separator(), remove_block]) edit_menu = menu.menu([edit_menu_contents], drop_down=True) exec_button = button.button('Execute (Ctrl-Enter)', lambda event: self.execute()) return [file_menu, edit_menu, exec_button, self.__execution_state] def __present__(self, fragment): def on_execute_key(event, key): self.execute() return True def on_save_key(event, key): self._save_containing_document_and_display_notification(fragment) self.__incr.on_access() contents = [] for block in self.__blocks: contents.extend(['<div>', block, '</div>']) p = Html(*contents) p = p.with_key_handler([KeyAction(KeyAction.KEY_DOWN, 13, ctrl=True)], on_execute_key) p = p.with_key_handler([KeyAction(KeyAction.KEY_DOWN, ord('S'), ctrl=True, prevent_default=True)], on_save_key) return p.use_css('/static/larch/notebook.css')
def __init__(self): self.contents = [] self.__incr = IncrementalValueMonitor()
def __init__(self, code=''): self.__blocks = [] self.__current_block = CurrentBlock( self._source_text_to_code_object(code), self) self.__incr = IncrementalValueMonitor()
def __init__(self): self._incr = IncrementalValueMonitor() self.__change_history__ = None self._parent = None
class TrackedLiveList (object): __slots__ = [ '__change_history__', '_items', '_incr', '__change_listener'] def __init__(self, xs=None): self._items = [] if xs is not None: self._items[:] = xs[:] self.__change_history__ = None self._incr = IncrementalValueMonitor() self.__change_listener = None @property def change_listener(self): return self.__change_listener @change_listener.setter def change_listener(self, x): self.__change_listener = x def __getstate__(self): self._incr.on_access() return { 'items' : self._items } def __setstate__(self, state): self._items = state['items'] self.__change_history__ = None self._incr = IncrementalValueMonitor() self.__change_listener = None def __copy__(self): self._incr.on_access() t = type( self ) return t( self._items ) def __deepcopy__(self, memo): self._incr.on_access() t = type( self ) return t( deepcopy( self._items, memo ) ) def __eq__(self, other): if isinstance( other, TrackedLiveList ): other = other._items return self._items == other def __ne__(self, other): if isinstance( other, TrackedLiveList ): other = other._items return self._items != other def __str__(self): return str( self._items ) def __repr__(self): return 'LiveList( {0} )'.format( repr( self._items ) ) def __trackable_contents__(self): return self._items def __clipboard_copy__(self, memo): self._incr.on_access() t = type( self ) return t( [ memo.copy( x ) for x in self ] ) def __iter__(self): self._incr.on_access() return _LiveListIter( iter( self._items ), self._incr ) def __contains__(self, x): self._incr.on_access() return x in self._items def __add__(self, xs): self._incr.on_access() return self._items + xs def __mul__(self, x): self._incr.on_access() return self._items * x def __rmul__(self, x): self._incr.on_access() return x * self._items def __getitem__(self, index): self._incr.on_access() return self._items[index] def __len__(self): self._incr.on_access() return len( self._items ) def index(self, x, i=None, j=None): self._incr.on_access() if i is None: return self._items.index( x ) elif j is None: return self._items.index( x, i ) else: return self._items.index( x, i, j ) def count(self, x): self._incr.on_access() return self._items.count( x ) def __setitem__(self, index, x): if isinstance( index, int ) or isinstance( index, long ): oldX = self._items[index] if self.__change_listener is not None: old_contents = self._items[:] self._items[index] = x _on_tracked_list_set_item( self.__change_history__, self, index, oldX, x, 'Live list set item' ) if self.__change_listener is not None: self.__change_listener( old_contents, self._items[:] ) else: old_contents = self._items[:] self._items[index] = x newContents = self._items[:] _on_tracked_list_set_contents( self.__change_history__, self, old_contents, newContents, 'Live list set item' ) if self.__change_listener is not None: self.__change_listener( old_contents, newContents ) self._incr.on_changed() def __delitem__(self, index): oldContents = self._items[:] del self._items[index] newContents = self._items[:] _on_tracked_list_set_contents( self.__change_history__, self, oldContents, newContents, 'Live list del item' ) if self.__change_listener is not None: self.__change_listener( oldContents, newContents ) self._incr.on_changed() def append(self, x): if self.__change_listener is not None: old_contents = self._items[:] self._items.append( x ) _on_tracked_list_append( self.__change_history__, self, x, 'Live list append' ) if self.__change_listener is not None: self.__change_listener( old_contents, self._items[:] ) self._incr.on_changed() def extend(self, xs): if self.__change_listener is not None: old_contents = self._items[:] self._items.extend( xs ) _on_tracked_list_extend( self.__change_history__, self, xs, 'Live list extend' ) if self.__change_listener is not None: self.__change_listener( old_contents, self._items[:] ) self._incr.on_changed() def insert(self, i, x): if self.__change_listener is not None: old_contents = self._items[:] self._items.insert( i, x ) _on_tracked_list_insert( self.__change_history__, self, i, x, 'Live list insert' ) if self.__change_listener is not None: self.__change_listener( old_contents, self._items[:] ) self._incr.on_changed() def pop(self): if self.__change_listener is not None: old_contents = self._items[:] x = self._items.pop() _on_tracked_list_pop( self.__change_history__, self, x, 'Live list pop' ) if self.__change_listener is not None: self.__change_listener( old_contents, self._items[:] ) self._incr.on_changed() return x def remove(self, x): if self.__change_listener is not None: old_contents = self._items[:] i = self._items.index( x ) xFromList = self._items[i] del self._items[i] _on_tracked_list_remove( self.__change_history__, self, i, xFromList, 'Live list remove' ) if self.__change_listener is not None: self.__change_listener( old_contents, self._items[:] ) self._incr.on_changed() def reverse(self): if self.__change_listener is not None: old_contents = self._items[:] self._items.reverse() _on_tracked_list_reverse( self.__change_history__, self, 'Live list reverse' ) if self.__change_listener is not None: self.__change_listener( old_contents, self._items[:] ) self._incr.on_changed() def sort(self, cmp_fn=None, key=None, reverse=False): old_contents = self._items[:] self._items.sort( cmp=cmp_fn, key=key, reverse=reverse ) newContents = self._items[:] _on_tracked_list_set_contents( self.__change_history__, self, old_contents, newContents, 'Live list sort' ) if self.__change_listener is not None: self.__change_listener( old_contents, newContents ) self._incr.on_changed() def _set_contents(self, xs): old_contents = self._items[:] self._items[:] = xs _on_tracked_list_set_contents( self.__change_history__, self, old_contents, xs, 'Live list set contents' ) if self.__change_listener is not None: self.__change_listener( old_contents, self._items[:] ) self._incr.on_changed()
def __setstate__(self, state): self._items = state['items'] self.__change_history__ = None self._incr = IncrementalValueMonitor() self.__change_listener = None
def __setstate__(self, state): self._incr = IncrementalValueMonitor() self.__change_history__ = None self._parent = None
class NotebookBlockSource (NotebookBlock): __language_to_type_map = { 'html': source_code.HtmlCode, 'css': source_code.CSSCode, 'js': source_code.JSCode, 'glsl': source_code.GLSLCode, } __type_to_language_map = { source_code.HtmlCode: 'html', source_code.CSSCode: 'css', source_code.JSCode: 'js', source_code.GLSLCode: 'glsl', } __language_to_human_name = { 'html': 'HTML', 'css': 'CSS', 'js': 'Javascript', 'glsl': 'GLSL', } def __init__(self, notebook, language, var_name='src'): super(NotebookBlockSource, self).__init__(notebook) try: code_type = self.__language_to_type_map[language] except KeyError: raise ValueError, 'Invalid language {0}'.format(language) self.__code = code_type() self.__var_name = LiveValue(var_name) self.__incr = IncrementalValueMonitor() def __getstate__(self): state = super(NotebookBlockSource, self).__getstate__() state['code'] = self.__code state['var_name'] = self.__var_name.static_value return state def __setstate__(self, state): super(NotebookBlockSource, self).__setstate__(state) self.__code = state.get('code') self.__var_name = LiveValue(state.get('var_name')) self.__incr = IncrementalValueMonitor() @property def language(self): return self.__type_to_language_map[type(self.__code)] @language.setter def language(self, lang): try: code_type = self.__language_to_type_map[lang] except KeyError: raise ValueError, 'Invalid language {0}'.format(lang) src_text = self.__code.source_text self.__code = code_type(code=src_text) self.__incr.on_changed() def execute(self, module): module.__dict__[self.__var_name.static_value] = self.__code.source_text def __present__(self, fragment): self.__incr.on_access() def _on_change_language(lang): self.language = lang language = self.language var_name = text_entry.live_text_entry(self.__var_name) js_item = menu.item('Javascript', lambda event: _on_change_language('js')) css_item = menu.item('CSS', lambda event: _on_change_language('css')) glsl_item = menu.item('GLSL', lambda event: _on_change_language('glsl')) html_item = menu.item('HTML', lambda event: _on_change_language('html')) lang_menu = menu.sub_menu('Change language', [ js_item, css_item, glsl_item, html_item ]) lang_menu_button = menu.menu([lang_menu], drop_down=True) human_lang_name = self.__language_to_human_name[language] header = Html('<div class="notebook_{0}_code_header">'.format(language), '<table class="notebook_src_language_select_table"><tr>', '<td>{0}</td>'.format(human_lang_name), '<td>', lang_menu_button, '</td>', '</tr></table>', '<table><tr>', '<td>Variable name:</td>', '<td>', var_name, '</td>', '</tr></table>', '</div>') code = Html('<div class="notebook_{0}_code_container notebook_code_container">'.format(language), self.__code, '</div>') p = Html('<div class="notebook_code_block">', header, '<div class="notebook_code_block_body">', code, '</div></div>') p = focusable.focusable(p) return p