def __init__(self, notebook, config=None, template='Default'): '''Constructor @param notebook: a L{Notebook} object @param config: optional C{ConfigManager} object @param template: html template for zim pages ''' assert isinstance(notebook, Notebook) self.notebook = notebook self.config = config or ConfigManager(profile=notebook.profile) self.output = None if isinstance(template, basestring): from zim.templates import get_template self.template = get_template('html', template) if not self.template: raise AssertionError, 'Could not find html template: %s' % template else: self.template = template self.linker = WWWLinker(self.notebook) self.template.set_linker(self.linker) self.plugins = PluginManager(self.config) self.plugins.extend(notebook.index) self.plugins.extend(notebook) self.plugins.extend(self)
def __init__(self, notebook, config=None, template='Default'): '''Constructor @param notebook: a L{Notebook} object @param config: optional C{ConfigManager} object @param template: html template for zim pages ''' assert isinstance(notebook, Notebook) self.notebook = notebook self.config = config or ConfigManager(profile=notebook.profile) self.output = None if template is None: template = 'Default' if isinstance(template, basestring): from zim.templates import get_template self.template = get_template('html', template) if not self.template: raise AssertionError('Could not find html template: %s' % template) else: self.template = template self.linker_factory = partial(WWWLinker, self.notebook, self.template.resources_dir) self.dumper_factory = get_format('html').Dumper # XXX self.plugins = PluginManager(self.config) self.plugins.extend(notebook) self.plugins.extend(self)
def __init__(self, uimanager, pageview): self.uimanager = uimanager self.pageview = pageview self.insertedobjects = PluginManager().insertedobjects self._ui_id = None self._actiongroup = None self.add_ui() self.insertedobjects.connect('changed', self.on_changed)
def _find_plugin(name): plugins = PluginManager() for plugin_name in plugins.list_installed_plugins(): try: klass = plugins.get_plugin_class(plugin_name) for objtype in klass.discover_classes(InsertedObjectTypeExtension): if objtype.name == name: activatable = klass.check_dependencies_ok() return (plugin_name, klass.plugin_info['name'], activatable, klass) except: continue return None
def testTaskListTreeView(self): plugin = PluginManager.load_plugin('tasklist') notebook = self.setUpNotebook(content=tests.FULL_NOTEBOOK) notebook.index.check_and_update() from zim.plugins.tasklist.gui import TaskListTreeView view = TasksView.new_from_index(notebook.index) opener = tests.MockObject() treeview = TaskListTreeView(view, opener, task_labels=['TODO', 'FIXME']) menu = treeview.get_popup() # Check these do not cause errors - how to verify state ? tests.gtk_activate_menu_item(menu, _("Expand _All")) tests.gtk_activate_menu_item(menu, _("_Collapse All")) # Copy tasklist -> csv from zim.gui.clipboard import Clipboard tests.gtk_activate_menu_item(menu, _('_Copy')) text = Clipboard.get_text() lines = text.splitlines() self.assertTrue(len(lines) > 10) self.assertTrue(len(lines[0].split(',')) > 3) self.assertFalse(any('<span' in l for l in lines)) # make sure encoding is removed # Test tags tags = treeview.get_tags() for tag in ('home', 'FIXME', '__no_tags__', 'tags'): self.assertIn(tag, tags) self.assertGreater(tags[tag], 0)
def testTemplate(self): pluginklass = PluginManager.get_plugin_class('calendar') plugin = pluginklass() plugin.preferences['namespace'] = Path('Calendar') notebook = tests.new_notebook() plugin.extend(notebook) dumper = get_dumper('wiki') zim.datetimetz.FIRST_DAY_OF_WEEK = \ zim.datetimetz.MONDAY for path in ( Path('Calendar:2012'), Path('Calendar:2012:04:27'), Path('Calendar:2012:Week 17'), Path('Calendar:2012:04'), ): tree = notebook.get_template(path) lines = dumper.dump(tree) #~ print lines self.assertTrue(not 'Created' in ''.join(lines)) # No fall back if 'Week' in path.name: days = [l for l in lines if l.startswith('=== ')] self.assertEqual(len(days), 7)
def testPageViewExtensions(self): plugin = PluginManager.load_plugin('tableofcontents') notebook = self.setUpNotebook() mainwindow = setUpMainWindow(notebook) plugin.preferences['floating'] = True ## floating ext = list(plugin.extensions) self.assertEqual(len(ext), 1) self.assertIsInstance(ext[0], ToCPageViewExtension) self.assertIsInstance(ext[0].tocwidget, FloatingToC) plugin.preferences.changed() # make sure no errors are triggered plugin.preferences['show_h1'] = True plugin.preferences['show_h1'] = False plugin.preferences['pane'] = RIGHT_PANE plugin.preferences['pane'] = LEFT_PANE ### embedded plugin.preferences['floating'] = False self.assertIsInstance(ext[0].tocwidget, SidePaneToC) plugin.preferences.changed() # make sure no errors are triggered plugin.preferences['show_h1'] = True plugin.preferences['show_h1'] = False plugin.preferences['pane'] = RIGHT_PANE plugin.preferences['pane'] = LEFT_PANE plugin.preferences['floating'] = True # switch back
def runTest(self): plugin = PluginManager.load_plugin('inlinecalculator') notebook = self.setUpNotebook() pageview = setUpPageView(notebook) extension = find_extension(pageview, InlineCalculatorPageViewExtension) buffer = pageview.textview.get_buffer() def get_text(): start, end = buffer.get_bounds() return start.get_text(end) # Simple case buffer.set_text('1 + 1 =\n') buffer.place_cursor(buffer.get_iter_at_offset(7)) extension.eval_math() self.assertEqual(get_text(), '1 + 1 = 2\n') # Looks back to previous line buffer.set_text('1 + 1 =\n\n') buffer.place_cursor(buffer.get_iter_at_offset(8)) extension.eval_math() self.assertEqual(get_text(), '1 + 1 = 2\n\n') # Multi-line example buffer.set_text('1\n2\n3\n--- +\n') buffer.place_cursor(buffer.get_iter_at_offset(6)) extension.eval_math() self.assertEqual(get_text(), '1\n2\n3\n--- +\n6\n')
def setUp(self): self.plugin = PluginManager.load_plugin('pageindex') self.window = setUpMainWindow( self.setUpNotebook(content=tests.FULL_NOTEBOOK)) self.extension = find_extension(self.window.pageview, PageIndexNotebookViewExtension) assert self.extension is not None
def testTaskListTreeView(self): klass = PluginManager.get_plugin_class('tasklist') plugin = klass() notebook = tests.new_notebook() plugin.extend(notebook.index) index_ext = plugin.get_extension(IndexExtension) self.assertIsNotNone(index_ext) notebook.index.flush() notebook.index.update() from zim.plugins.tasklist import TaskListTreeView opener = tests.MockObject() treeview = TaskListTreeView(index_ext, opener) menu = treeview.get_popup() # Check these do not cause errors - how to verify state ? tests.gtk_activate_menu_item(menu, _("Expand _All")) tests.gtk_activate_menu_item(menu, _("_Collapse All")) # Copy tasklist -> csv from zim.gui.clipboard import Clipboard tests.gtk_activate_menu_item(menu, 'gtk-copy') text = Clipboard.get_text() lines = text.splitlines() self.assertTrue(len(lines) > 10) self.assertTrue(len(lines[0].split(',')) > 3) self.assertFalse(any('<span' in l for l in lines)) # make sure encoding is removed
def testNamespace(self): pluginklass = PluginManager.get_plugin_class('journal') plugin = pluginklass() notebook = self.setUpNotebook() properties = plugin.notebook_properties(notebook) today = dateclass.today() for namespace in (Path('Calendar'), Path(':')): properties['namespace'] = namespace path = plugin.path_from_date(notebook, today) self.assertTrue(isinstance(path, Path)) self.assertTrue(path.ischild(namespace)) date = plugin.date_from_path(path) self.assertTrue(isinstance(date, dateclass)) self.assertEqual(date, today) from zim.plugins.journal import DAY, WEEK, MONTH, YEAR zim.datetimetz.FIRST_DAY_OF_WEEK = \ zim.datetimetz.MONDAY properties['namespace'] = Path('Calendar') date = dateclass(2012, 4, 27) for setting, wanted, start in ( (DAY, 'Calendar:2012:04:27', dateclass(2012, 4, 27)), (WEEK, 'Calendar:2012:Week 17', dateclass(2012, 4, 23)), (MONTH, 'Calendar:2012:04', dateclass(2012, 4, 1)), (YEAR, 'Calendar:2012', dateclass(2012, 1, 1)), ): properties['granularity'] = setting path = plugin.path_from_date(notebook, date) self.assertEqual(path.name, wanted) self.assertEqual(plugin.date_from_path(path), start) path = plugin.path_for_month_from_date(notebook, date) self.assertEqual(path.name, 'Calendar:2012:04')
def testNamespace(self): pluginklass = PluginManager.get_plugin_class('calendar') plugin = pluginklass() today = dateclass.today() for namespace in (Path('Calendar'), Path(':')): plugin.preferences['namespace'] = namespace path = plugin.path_from_date(today) self.assertTrue(isinstance(path, Path)) self.assertTrue(path.ischild(namespace)) date = plugin.date_from_path(path) self.assertTrue(isinstance(date, dateclass)) self.assertEqual(date, today) from zim.plugins.calendar import DAY, WEEK, MONTH, YEAR zim.datetimetz.FIRST_DAY_OF_WEEK = \ zim.datetimetz.MONDAY plugin.preferences['namespace'] = Path('Calendar') date = dateclass(2012, 4, 27) for setting, wanted, start in ( (DAY, 'Calendar:2012:04:27', dateclass(2012, 4, 27)), (WEEK, 'Calendar:2012:Week 17', dateclass(2012, 4, 23)), (MONTH, 'Calendar:2012:04', dateclass(2012, 4, 1)), (YEAR, 'Calendar:2012', dateclass(2012, 1, 1)), ): plugin.preferences['granularity'] = setting path = plugin.path_from_date(date) self.assertEqual(path.name, wanted) self.assertEqual(plugin.date_from_path(path), start) path = plugin.path_for_month_from_date(date) self.assertEqual(path.name, 'Calendar:2012:04')
def setUpMainWindow(notebook, path='Test', plugins=None): if isinstance(path, str): path = Path(path) mainwindow = MainWindow(notebook, page=path) mainwindow.__pluginmanager__ = plugins or PluginManager() mainwindow.init_uistate() # XXX return mainwindow
def testShowPreferencesDialog(self): from zim.gui.preferencesdialog import PreferencesDialog from zim.plugins import PluginManager self.uiactions.widget = Gtk.Window() self.uiactions.widget.__pluginmanager__ = PluginManager() with tests.DialogContext(PreferencesDialog): self.uiactions.show_preferences()
def testObjectTypes(self): PluginManager.load_plugin(self.plugin) notebook = self.setUpNotebook() page = notebook.get_page(Path('Test')) for name in self.object_types: otype = PluginManager.insertedobjects[name] attrib, data = otype.new_object() model = otype.model_from_data(notebook, page, attrib, data) self.assertIsNotNone(model) widget = otype.create_widget(model) self.assertIsNotNone(widget) attrib, data = otype.data_from_model(model) self.assertIsNotNone(otype.label) if isinstance(model, BackwardImageGeneratorObjectType): self.assertIsNotNone(otype.scriptname) self.assertIsNotNone(otype.imagefile_extension)
def setUpMainWindow(notebook, path='Test'): if isinstance(path, str): path = Path(path) config = VirtualConfigManager() mainwindow = MainWindow(notebook, config, page=path) mainwindow.__pluginmanager__ = PluginManager(config) mainwindow.init_uistate() # XXX return mainwindow
def _run_new_window(self, notebook, page): from gi.repository import GObject from zim.gui.mainwindow import MainWindow from zim.config import ConfigManager from zim.plugins import PluginManager config = ConfigManager() preferences = config.preferences['General'] preferences.setdefault('plugins', [ 'pageindex', 'pathbar', 'journal', 'insertsymbol', 'printtobrowser', 'versioncontrol', ]) # Upgrade plugin list preferences.setdefault('plugins_list_version', 'none') if preferences['plugins_list_version'] != '0.68': preferences['plugins'].extend(['pageindex', 'pathbar']) if 'calendar' in preferences['plugins']: preferences['plugins'].remove('calendar') preferences['plugins'].append('journal') config.preferences['JournalPlugin'] = config.preferences[ 'CalendarPlugin'] preferences['plugins_list_version'] = '0.68' pluginmanager = PluginManager(config) pluginmanager.extend(notebook) window = MainWindow(notebook, config, page=page, **self.get_options('geometry', 'fullscreen')) pluginmanager.extend(window) pluginmanager.extend(window.pageview) window.__pluginmanager__ = pluginmanager # HACK to allow dialogs to find it window.present() if not window.notebook.index.is_uptodate: window._uiactions.reload_index(update_only=True) # XXX else: # Start a lightweight background check of the index # put a small delay to ensure window is shown before we start def start_background_check(): notebook.index.start_background_check(notebook) return False # only run once GObject.timeout_add(500, start_background_check) return window
def run(self, *args, **kwargs): '''Run a commandline command, either in this process, an existing process, or a new process. @param args: commandline arguments @param kwargs: optional arguments for L{build_command} ''' PluginManager().load_plugins_from_preferences( ConfigManager.preferences['General']['plugins']) cmd = build_command(args, **kwargs) self._run_cmd(cmd, args) # test seam
def testMainWindowExtensions(self): plugin = PluginManager.load_plugin('journal') notebook = self.setUpNotebook() mainwindow = setUpMainWindow(notebook) plugin.preferences.changed() # make sure no errors are triggered ext = find_extension(mainwindow.pageview, JournalPageViewExtension) ext.go_page_today() self.assertTrue(mainwindow.page.name.startswith('Journal:'))
def runTest(self): 'Test PrintToBrowser plugin' pluginklass = PluginManager.get_plugin_class('printtobrowser') plugin = pluginklass() notebook = self.setUpNotebook(content=tests.FULL_NOTEBOOK) page = notebook.get_page(Path('Test:foo')) file = plugin.print_to_file(notebook, page) self.assertTrue(file.exists()) content = file.read() self.assertTrue('<h1>Foo</h1>' in content)
def runTest(self): 'Test PrintToBrowser plugin' pluginklass = PluginManager.get_plugin_class('printtobrowser') plugin = pluginklass() notebook = tests.new_notebook() page = notebook.get_page(Path('Test:foo')) file = plugin.print_to_file(notebook, page) self.assertTrue(file.exists()) content = file.read() self.assertTrue('<h1>Foo</h1>' in content)
def runTest(self): plugin = PluginManager.load_plugin('pathbar') window = setUpMainWindow(self.setUpNotebook()) extension = find_extension(window, PathBarMainWindowExtension) for ptype in PATHBAR_TYPES: extension.set_pathbar(ptype) pathbar = window._zim_window_central_vbox.get_children()[0] if ptype == PATHBAR_NONE: self.assertNotIsInstance(pathbar, PathBar) else: self.assertIsInstance(pathbar, extension._klasses[ptype])
def testMainWindowExtensions(self): pluginklass = PluginManager.get_plugin_class('journal') plugin = pluginklass() notebook = self.setUpNotebook() mainwindow = setUpMainWindow(notebook) plugin.extend(mainwindow.pageview) plugin.preferences.changed() # make sure no errors are triggered list(plugin.extensions)[0].go_page_today() self.assertTrue(mainwindow.page.name.startswith('Journal:'))
def _run_new_window(self, notebook, page): from gi.repository import GObject from zim.gui.mainwindow import MainWindow pluginmanager = PluginManager() preferences = ConfigManager.preferences['General'] preferences.setdefault('plugins_list_version', 'none') if preferences['plugins_list_version'] != '0.70': if not preferences['plugins']: pluginmanager.load_plugins_from_preferences( [ # Default plugins 'pageindex', 'pathbar', 'insertsymbol', 'printtobrowser', 'versioncontrol', ]) else: # Upgrade version <0.70 where these were core functions pluginmanager.load_plugins_from_preferences( ['pageindex', 'pathbar']) if 'calendar' in pluginmanager.failed: ConfigManager.preferences['JournalPlugin'] = \ ConfigManager.preferences['CalendarPlugin'] pluginmanager.load_plugins_from_preferences(['journal']) preferences['plugins_list_version'] = '0.70' window = MainWindow(notebook, page=page, **self.get_options('geometry', 'fullscreen')) window.present() if not window.notebook.index.is_uptodate: window._uiactions.reload_index(update_only=True) # XXX else: # Start a lightweight background check of the index # put a small delay to ensure window is shown before we start def start_background_check(): notebook.index.start_background_check(notebook) return False # only run once GObject.timeout_add(500, start_background_check) return window
def run(self): from zim.export.selections import AllPages, SinglePage, SubPages from zim.config import ConfigManager from zim.plugins import PluginManager notebook, page = self.build_notebook() # load plugins, needed so the the proper export functions would work from CLI config = ConfigManager(profile=notebook.profile) plugins = PluginManager(config) plugins.extend(notebook) notebook.index.check_and_update() if page and self.opts.get('recursive'): selection = SubPages(notebook, page) elif page: selection = SinglePage(notebook, page) else: selection = AllPages(notebook) exporter = self.get_exporter(page) exporter.export(selection)
def testNotebookExtension(self): plugin = PluginManager.load_plugin('journal') notebook = self.setUpNotebook() ext = find_extension(notebook, JournalNotebookExtension) self.assertIsNotNone(ext) page = Path('Foo') link = notebook.suggest_link(page, '2014-01-06') self.assertEqual(link.name, 'Journal:2014:01:06') link = notebook.suggest_link(page, 'foo') self.assertIsNone(link)
def testEditProperties(self): from zim.gui.preferencesdialog import PreferencesDialog from zim.plugins import PluginManager self.uiactions.widget = Gtk.Window() self.uiactions.widget.__pluginmanager__ = PluginManager() def edit_properties(dialog): dialog.set_input(home='NewHome') dialog.assert_response_ok() with tests.DialogContext(edit_properties): self.uiactions.show_properties() self.assertEqual(self.notebook.config['Notebook']['home'], Path('NewHome'))
def __init__(self, pageview): self.pageview = pageview self.edit_format_actions = ( pageview.toggle_format_strong, pageview.toggle_format_emphasis, pageview.toggle_format_mark, pageview.toggle_format_strike, pageview.toggle_format_code, pageview.toggle_format_sub, pageview.toggle_format_sup, ) self.edit_menus = ( ('_List', 'view-list-symbolic', self._create_list_menu()), ('_Heading', 'format-text-heading-symbolic', self._create_head_menu()), ('_Insert', 'insert-image-symbolic', self._create_insert_menu()), ) self.edit_clear_action = pageview.clear_formatting def on_extensions_changed(o, obj): if obj in (pageview, PluginManager.insertedobjects): self._update_insert_menu() PluginManager.connect('extensions-changed', on_extensions_changed)
def testEditPropertiesReadOnly(self): from zim.gui.preferencesdialog import PreferencesDialog from zim.plugins import PluginManager self.uiactions.widget = Gtk.Window() self.uiactions.widget.__pluginmanager__ = PluginManager() self.assertFalse(self.notebook.readonly) # implies attribute exists .. self.notebook.readonly = True def edit_properties(dialog): self.assertFalse(dialog.get_input_enabled('home')) dialog.assert_response_ok() with tests.DialogContext(edit_properties): self.uiactions.show_properties()
def testNotebookExtension(self): pluginklass = PluginManager.get_plugin_class('calendar') plugin = pluginklass() notebook = tests.new_notebook(self.get_tmp_name()) plugin.extend(notebook) ext = list(plugin.extensions) self.assertEqual(len(ext), 1) self.assertIsInstance(ext[0], NotebookExtension) page = Path('Foo') link = notebook.suggest_link(page, '2014-01-06') self.assertEqual(link.name, 'Journal:2014:01:06') link = notebook.suggest_link(page, 'foo') self.assertIsNone(link)
def testNotebookExtension(self): pluginklass = PluginManager.get_plugin_class('journal') plugin = pluginklass() notebook = self.setUpNotebook() plugin.extend(notebook) ext = list(plugin.extensions) self.assertEqual(len(ext), 1) self.assertIsInstance(ext[0], NotebookExtension) page = Path('Foo') link = notebook.suggest_link(page, '2014-01-06') self.assertEqual(link.name, 'Journal:2014:01:06') link = notebook.suggest_link(page, 'foo') self.assertIsNone(link)
def testPropertiesNotChangedOnCancel(self): from zim.gui.preferencesdialog import PreferencesDialog from zim.plugins import PluginManager self.uiactions.widget = Gtk.Window() self.uiactions.widget.__pluginmanager__ = PluginManager() # In fact this is testig the "cancel" button for all dialogs # which have one .. def edit_properties(dialog): dialog.set_input(home='NewHome') dialog.do_response_cancel() with tests.DialogContext(edit_properties): self.uiactions.show_properties() self.assertNotEqual(self.notebook.config['Notebook']['home'], Path('NewHome'))
def testIndexing(self): '''Check indexing of tasklist plugin''' plugin = PluginManager.load_plugin('tasklist') notebook = self.setUpNotebook(content=tests.FULL_NOTEBOOK) # Test indexing based on index signals notebook.index.check_and_update() view = TasksView.new_from_index(notebook.index) for tasks in ( list(view.list_open_tasks()), list(view.list_open_tasks_flatlist()), ): self.assertTrue(len(tasks) > 5) for task in tasks: path = view.get_path(task) self.assertTrue(not path is None)
def testIndexing(self): '''Check indexing of tasklist plugin''' klass = PluginManager.get_plugin_class('tasklist') plugin = klass() notebook = tests.new_notebook() plugin.extend(notebook.index) index_ext = plugin.get_extension(IndexExtension) self.assertIsNotNone(index_ext) # Test indexing based on index signals notebook.index.flush() notebook.index.update() self.assertTrue(index_ext.db_initialized) tasks = list(index_ext.list_tasks()) self.assertTrue(len(tasks) > 5) for task in tasks: path = index_ext.get_path(task) self.assertTrue(not path is None)
def testMainWindowExtensions(self): pluginklass = PluginManager.get_plugin_class('calendar') plugin = pluginklass() notebook = tests.new_notebook(self.get_tmp_name()) ui = setupGtkInterface(self, notebook=notebook) plugin.preferences['embedded'] = True self.assertEqual(plugin.extension_classes['MainWindow'], MainWindowExtensionEmbedded) plugin.extend(ui.mainwindow) ext = list(plugin.extensions) self.assertEqual(len(ext), 1) self.assertIsInstance(ext[0], MainWindowExtensionEmbedded) plugin.preferences.changed() # make sure no errors are triggered ext[0].go_page_today() self.assertTrue(ui.page.name.startswith('Journal:')) plugin.preferences['embedded'] = False self.assertEqual(plugin.extension_classes['MainWindow'], MainWindowExtensionDialog) plugin.extend(ui.mainwindow) # plugin does not remember objects, manager does that ext = list(plugin.extensions) self.assertEqual(len(ext), 1) self.assertIsInstance(ext[0], MainWindowExtensionDialog) plugin.preferences.changed() # make sure no errors are triggered def test_dialog(dialog): self.assertIsInstance(dialog, CalendarDialog) dialog.do_today('xxx') ui.open_page(Path('foo')) with tests.DialogContext(test_dialog): ext[0].show_calendar() plugin.preferences['embedded'] = True # switch back
def testParsing(self): klass = PluginManager.get_plugin_class('tasklist') plugin = klass() notebook = tests.new_notebook() plugin.extend(notebook.index) index_ext = plugin.get_extension(IndexExtension) self.assertIsNotNone(index_ext) # Test correctnest of parsing NO_DATE = '9999' def extract_tasks(text): # Returns a nested list of tuples, where each node is # like "(TASK, [CHILD, ...]) where each task (and child) # is a tuple like (open, actionable, prio, due, description) parser = zim.formats.get_format('wiki').Parser() tree = parser.parse(text) origtree = tree.tostring() #~ print 'TREE', origtree tasks = index_ext._extract_tasks(tree) self.assertEqual(tree.tostring(), origtree) # extract should not modify the tree return tasks def t(label, open=True, due=NO_DATE, prio=0, tags='', actionable=True): # Generate a task tuple # (open, actionable, prio, due, tags, description) if tags: tags = set(unicode(tags).split(',')) else: tags = set() return [open, actionable, prio, due, tags, unicode(label)] # Note that this same text is in the test notebook # so it gets run through the index as well - keep in sync text = '''\ Try all kind of combos - see if the parser trips TODO: [ ] A [ ] B [ ] C [ ] D [ ] E FIXME: dus ~~FIXME:~~ foo [ ] Simple [ ] List [ ] List with [ ] Nested items [*] Some are done [*] Done but with open child [x] Others not [ ] FOOOOO [ ] Bar [ ] And then there are @tags [ ] Next: And due dates [ ] Date [d: 11/12] [ ] Date [d: 11/12/2012] [ ] TODO: BAR !!! TODO @home: [ ] Some more tasks !!! [ ] Foo ! * some sub item * some other item [ ] Bar TODO: dus FIXME: jaja - TODO !! @FIXME ~~TODO~~: Ignore this one - it is strike out * TODO: dus - list item * FIXME: jaja - TODO !! @FIXME - list item * ~~TODO~~: Ignore this one - it is strike out - list item * Bullet list * With tasks as sub items [ ] Sub item bullets * dus 1. Numbered list 2. With tasks as sub items [ ] Sub item numbered 3. dus Test task inheritance: [ ] Main @tag1 @tag2 ! [*] Sub1 [ ] Sub2 @tag3 !!!! [*] Sub2-1 [*] Sub2-2 @tag4 [ ] Sub2-3 [ ] Sub3 TODO: @someday [ ] A [ ] B [ ] B-1 [ ] C TODO @home [ ] main task [x] do this [ ] Next: do that [ ] Next: do something else ''' mydate = '%04i-%02i-%02i' % parse_date('11/12') wanted = [ (t('A'), []), (t('B'), []), (t('C'), []), (t('D'), []), (t('E'), []), (t('FIXME: dus'), []), (t('Simple'), []), (t('List'), []), (t('List with'), [ (t('Nested items'), []), (t('Some are done', open=False), []), (t('Done but with open child', open=True), [ (t('Others not', open=False), []), (t('FOOOOO'), []), ]), ]), (t('Bar'), []), (t('And then there are @tags', tags='tags'), []), (t('Next: And due dates', actionable=False), []), (t('Date [d: 11/12]', due=mydate), []), (t('Date [d: 11/12/2012]', due='2012-12-11'), [ (t('TODO: BAR !!!', prio=3, due='2012-12-11'), []), # due date is inherited ]), # this list inherits the @home tag - and inherits prio (t('Some more tasks !!!', prio=3, tags='home'), [ (t('Foo !', prio=1, tags='home'), []), (t('Bar', prio=3, tags='home'), []), ]), (t('TODO: dus'), []), (t('FIXME: jaja - TODO !! @FIXME', prio=2, tags='FIXME'), []), (t('TODO: dus - list item'), []), (t('FIXME: jaja - TODO !! @FIXME - list item', prio=2, tags='FIXME'), []), (t('Sub item bullets'), []), (t('Sub item numbered'), []), (t('Main @tag1 @tag2 !', prio=1, tags='tag1,tag2'), [ (t('Sub1', prio=1, open=False, tags='tag1,tag2'), []), (t('Sub2 @tag3 !!!!', prio=4, tags='tag1,tag2,tag3'), [ (t('Sub2-1', prio=4, open=False, tags='tag1,tag2,tag3'), []), (t('Sub2-2 @tag4', prio=4, open=False, tags='tag1,tag2,tag3,tag4'), []), (t('Sub2-3', prio=4, tags='tag1,tag2,tag3'), []), ]), (t('Sub3', prio=1, tags='tag1,tag2'), []), ]), (t('A', tags='someday', actionable=False), []), (t('B', tags='someday', actionable=False), [ (t('B-1', tags='someday', actionable=False), []), ]), (t('C', tags='someday', actionable=False), []), (t('main task', tags='home'), [ (t('do this', open=False, tags='home'), []), (t('Next: do that', tags='home'), []), (t('Next: do something else', tags='home', actionable=False), []), ]) ] plugin.preferences['nonactionable_tags'] = '@someday, @maybe' index_ext._set_preferences() tasks = extract_tasks(text) self.assertEqual(tasks, wanted) plugin.preferences['all_checkboxes'] = False wanted = [ (t('A'), []), (t('B'), []), (t('C'), []), (t('FIXME: dus'), []), (t('Next: And due dates', actionable=False), []), (t('TODO: BAR !!!', prio=3), []), # this list inherits the @home tag - and inherits prio (t('Some more tasks !!!', prio=3, tags='home'), [ (t('Foo !', prio=1, tags='home'), []), (t('Bar', prio=3, tags='home'), []), ]), (t('TODO: dus'), []), (t('FIXME: jaja - TODO !! @FIXME', prio=2, tags='FIXME'), []), (t('TODO: dus - list item'), []), (t('FIXME: jaja - TODO !! @FIXME - list item', prio=2, tags='FIXME'), []), (t('A', tags='someday', actionable=False), []), (t('B', tags='someday', actionable=False), [ (t('B-1', tags='someday', actionable=False), []), ]), (t('C', tags='someday', actionable=False), []), (t('main task', tags='home'), [ (t('do this', open=False, tags='home'), []), (t('Next: do that', tags='home'), []), (t('Next: do something else', tags='home', actionable=False), []), ]) ] tasks = extract_tasks(text) self.assertEqual(tasks, wanted)
def runTest(self): 'Test InlineCalculator plugin' pluginklass = PluginManager.get_plugin_class('inlinecalculator') plugin = pluginklass() for text, wanted in ( ('3 + 4 =', '3 + 4 = 7'), ('3 + 4 = 1', '3 + 4 = 7'), ('3 + 4 = 1 ', '3 + 4 = 7 '), ('10 / 3 =', '10 / 3 = 3.33333333333'), # divide integers to float ! ('milage: 3 + 4 =', 'milage: 3 + 4 = 7'), ('3 + 4 = 7 + 0.5 = ', '3 + 4 = 7 + 0.5 = 7.5'), ('''\ 5.5 4.3 3.1 --- + ''', '''\ 5.5 4.3 3.1 --- + 12.9 ''' ), ): result = plugin.process_text(text) self.assertEqual(result, wanted) # Tests from clac.py self test for test in '''\ 1+2 == 3 sqrt(-1) == j -2*asin(-1) == pi abs(sin(pi)) < 1e-9 abs(1-cos(0)) < 1e-9 round( 3.1 + -4.8j) == (3-5j) ceil( 3.1 + -4.8j) == (4-4j) abs( 3-4j) == 5 degrees(pi) == 180 radians(180) == pi abs( exp(j*pi) + 1 ) < 1e-9 # pow(1.2,3.4) == 1.2**3.4 ldexp(1.2,3) == 1.2 * 2 ** 3 modf(1.2)[1] == 1 log(81,3) == 4 gcd(6,8) == 2 lcm(6,8) == 24 angle( exp( j*pi ) ) == pi # log(-1)**2 == -1*pow(pi,2) round( degrees(phase( e**(2j)))) == 115 # sum( [ round(42 * exp(j*2*x*pi/4)) for x in range(4)] ) == 0 oct(8) == '010' 0x42-042-42 == -10 # 1k == 1024 # 1m == 2**20 # 1g == 2**30 2**10-1 == 1023 # 2**1k == 2**1024 '''.splitlines(): if test.startswith('#'): continue #~ print 'TESTING:', test self.assertTrue(plugin.safe_eval(test)) self.assertRaises(Exception, plugin.process_text, 'open("/etc/passwd")') # global self.assertRaises(Exception, plugin.process_text, 'self') # local
class WWWInterface(object): '''Class to handle the WWW interface for zim notebooks. Objects of this class are callable, so they can be used as application objects within a WSGI compatible framework. See PEP 333 for details (U{http://www.python.org/dev/peps/pep-0333/}). For basic handlers to run this interface see the "wsgiref" package in the standard library for python. ''' def __init__(self, notebook, config=None, template='Default'): '''Constructor @param notebook: a L{Notebook} object @param config: optional C{ConfigManager} object @param template: html template for zim pages ''' assert isinstance(notebook, Notebook) self.notebook = notebook self.config = config or ConfigManager(profile=notebook.profile) self.output = None if isinstance(template, basestring): from zim.templates import get_template self.template = get_template('html', template) if not self.template: raise AssertionError, 'Could not find html template: %s' % template else: self.template = template self.linker = WWWLinker(self.notebook) self.template.set_linker(self.linker) self.plugins = PluginManager(self.config) self.plugins.extend(notebook.index) self.plugins.extend(notebook) self.plugins.extend(self) #~ self.notebook.index.update() def __call__(self, environ, start_response): '''Main function for handling a single request. Follows the WSGI API. @param environ: dictionary with environment variables for the request and some special variables. See the PEP for expected variables. @param start_response: a function that can be called to set the http response and headers. For example:: start_response(200, [('Content-Type', 'text/plain')]) @returns: the html page content as a list of lines ''' headerlist = [] headers = Headers(headerlist) path = environ.get('PATH_INFO', '/') try: methods = ('GET', 'HEAD') if not environ['REQUEST_METHOD'] in methods: raise WWWError('405', headers=[('Allow', ', '.join(methods))]) # cleanup path #~ print 'INPUT', path path = path.replace('\\', '/') # make it windows save isdir = path.endswith('/') parts = [p for p in path.split('/') if p and not p == '.'] if [p for p in parts if p.startswith('.')]: # exclude .. and all hidden files from possible paths raise PathNotValidError() path = '/' + '/'.join(parts) if isdir and not path == '/': path += '/' #~ print 'PATH', path if not path: path = '/' elif path == '/favicon.ico': path = '/+resources/favicon.ico' else: path = urllib.unquote(path) if path == '/': headers.add_header('Content-Type', 'text/html', charset='utf-8') content = self.render_index() elif path.startswith('/+docs/'): dir = self.notebook.document_root if not dir: raise PageNotFoundError(path) file = dir.file(path[7:]) content = [file.raw()] # Will raise FileNotFound when file does not exist headers['Content-Type'] = file.get_mimetype() elif path.startswith('/+file/'): file = self.notebook.dir.file(path[7:]) # TODO: need abstraction for getting file from top level dir ? content = [file.raw()] # Will raise FileNotFound when file does not exist headers['Content-Type'] = file.get_mimetype() elif path.startswith('/+resources/'): if self.template.resources_dir: file = self.template.resources_dir.file(path[12:]) if not file.exists(): file = data_file('pixmaps/%s' % path[12:]) else: file = data_file('pixmaps/%s' % path[12:]) if file: content = [file.raw()] # Will raise FileNotFound when file does not exist headers['Content-Type'] = file.get_mimetype() else: raise PageNotFoundError(path) else: # Must be a page or a namespace (html file or directory path) headers.add_header('Content-Type', 'text/html', charset='utf-8') if path.endswith('.html'): pagename = path[:-5].replace('/', ':') elif path.endswith('/'): pagename = path[:-1].replace('/', ':') else: raise PageNotFoundError(path) path = self.notebook.resolve_path(pagename) page = self.notebook.get_page(path) if page.hascontent: content = self.render_page(page) elif page.haschildren: content = self.render_index(page) else: raise PageNotFoundError(page) except Exception, error: headerlist = [] headers = Headers(headerlist) headers.add_header('Content-Type', 'text/plain', charset='utf-8') if isinstance(error, (WWWError, FileNotFoundError)): logger.error(error.msg) if isinstance(error, FileNotFoundError): error = PageNotFoundError(path) # show url path instead of file path if error.headers: for key, value in error.headers: headers.add_header(key, value) start_response(error.status, headerlist) content = unicode(error).splitlines(True) # TODO also handle template errors as special here else: # Unexpected error - maybe a bug, do not expose output on bugs # to the outside world logger.exception('Unexpected error:') start_response('500 Internal Server Error', headerlist) content = ['Internal Server Error'] if environ['REQUEST_METHOD'] == 'HEAD': return [] else: return [string.encode('utf-8') for string in content] else: