def testSignals(self): pages = [] self.assertGreater(self.model.on_iter_n_children(None), 0) # delete all pages for path in list(self.notebook.pages.walk_bottomup()): page = self.notebook.get_page(path) pages.append((page.name, page.dump('wiki'))) self.notebook.delete_page(page) self.assertEqual(self.notebook.pages.n_list_pages(), 0) self.assertEqual(self.model.on_iter_n_children(None), 0) # TODO: assert something on the view ? # and add them again for name, content in reversed(pages): page = self.notebook.get_page(Path(name)) page.parse('wiki', content) self.notebook.store_page(page) self.assertGreater(self.model.on_iter_n_children(None), 0)
def __init__(self, layout, template, format, index_page=None, document_root_url=None): '''Constructor @param layout: a L{ExportLayout} to map pages to files @param template: a L{Template} object @param format: the format for the file content @param index_page: a page to output the index or C{None} @param document_root_url: optional URL for the document root ''' FilesExporterBase.__init__(self, layout, template, format, document_root_url) if index_page: if isinstance(index_page, basestring): self.index_page = Path(Path.makeValidPageName(index_page)) else: self.index_page = index_page else: self.index_page = None
def runTest(self): dir = Dir(self.create_tmp_dir()) #~ dir = VirtualDir('/test') i = 0 print '' for template, file in list_templates(self.format): print 'Testing template: %s' % template notebook = tests.new_notebook(fakedir='/foo') pages = AllPages(notebook) # TODO - sub-section ? exporter = build_notebook_exporter(dir.subdir(template), self.format, template) self.assertIsInstance(exporter, MultiFileExporter) exporter.export(pages) file = exporter.layout.page_file(Path('roundtrip')) text = file.read() self.assertIn('Lorem ipsum dolor sit amet', text) i += 1 if self.format in ('html', 'latex'): self.assertTrue(i >= 3)
def testParseExec(self): '''Test parsing of custom tool Exec strings''' # %f for source file as tmp file current page # %d for attachment directory # %s for real source file (if any) # %p for the page name # %n for notebook location (file or directory) # %D for document root # %t for selected text or word under cursor # %T for selected text or word under cursor with wiki format path = self.get_tmp_name() notebook = tests.new_notebook(fakedir=path) page = notebook.get_page(Path('Test:Foo')) pageview = StubPageView() args = (notebook, page, pageview) tmpfile = TmpFile('tmp-page-source.txt').path dir = notebook.dir tool = CustomToolDict() tool.update({ 'Name': 'Test', 'Comment': 'Test 1 2 3', 'X-Zim-ExecTool': 'foo', }) for cmd, wanted in ( ('foo %f', ('foo', tmpfile)), ('foo %d', ('foo', dir.subdir('Test/Foo').path)), ('foo %s', ('foo', page.source.path)), ('foo %p', ('foo', 'Test:Foo')), ('foo %n', ('foo', dir.path)), ('foo %D', ('foo', '')), # no document root ('foo %t', ('foo', 'FooBar')), ('foo %T', ('foo', '**FooBar**')), ): #~ print '>>>', cmd tool['Desktop Entry']['X-Zim-ExecTool'] = cmd self.assertEqual(tool.parse_exec(args), wanted)
def setUp(self): self.notebook = self.setUpNotebook(content={ 'Test:foo': 'test 123', 'Test:link': '[[:Placeholder]]', # link 'Test:foo:bar': 'test 123', 'Test:bar': 'test 123', 'Bar': 'test 123', 'Maßnahmen': 'test 123', # unicode 'žžž': 'test 123' # unicde with accent }) self.reference = Path('Test:foo') widgets_before = tests.find_widgets(Gtk.TreeView) self.entry = self.entryklass(self.notebook, self.reference) # There's no direct way to access the model that contains the final # completion items. There is no getter for it in Gtk.EntryCompletion. # Instead, walk through children of all top level windows and find the # view that is used to render the completion popup, that view provides # access to the completion model completion_view = (set(tests.find_widgets(Gtk.TreeView)) - set(widgets_before)).pop() self.completion_model = completion_view.get_model()
def runTest(self): notebook = self.setUpNotebook( content={'Öffnungszeiten': 'Öffnungszeiten ... 123\n'}) results = SearchSelection(notebook) path = Path('Öffnungszeiten') for string in ( '*zeiten', # no unicode - just check test case 'Öffnungszeiten', 'öffnungszeiten', # case insensitive version 'content:Öffnungszeiten', 'content:öffnungszeiten', 'name:Öffnungszeiten', 'name:öffnungszeiten', 'content:Öff*', 'content:öff*', 'name:Öff*', 'name:öff*', ): query = Query(string) results.search(query) self.assertIn(path, results, 'query did not match: "%s"' % string)
def soutMenu(self, displayImmediately=False): """ Displays menu and handles caret position. """ if self.timeoutOpenPage: GObject.source_remove(self.timeoutOpenPage) self.gui.resize(300, 100) # reset size # treat possible caret deflection if self.caret['pos'] < 0 or self.caret['pos'] > len( self.state.items ) - 1: # place the caret to the beginning or the end of list self.caret['pos'] = self.caret['altPos'] text = "" i = 0 for item in self.state.items: score = self.state.menu[item].score + self.state.menu[item].bonus self.state.menu[item].lastOrder = i if i == self.caret['pos']: self.caret['text'] = item # caret is at this position text += '→ {} ({}) {}\n'.format( item, score, "" if self.state.menu[item].sure else "?") else: try: text += '{} ({}) {}\n'.format( item, score, "" if self.state.menu[item].sure else "?") except: text += "CHYBA\n" text += item[0:-1] + "\n" i += 1 self.labelObject.set_text(text) self.menuPage = Path( self.caret['text'] if len(self.state.items) else self.originalPage) if not displayImmediately: self.timeoutOpenPage = GObject.timeout_add( self.keystroke_delay, self._open_page, self.menuPage) # ideal delay between keystrokes else: self._open_page(self.menuPage)
def runTest(self): db = new_test_database() linksview = LinksView(db) for name, links, backlinks in LINKS: path = Path(name) mylinks = [l.target.name for l in linksview.list_links(path)] n_links = linksview.n_list_links(path) self.assertEqual(mylinks, links) self.assertEqual(n_links, len(links)) mybacklinks = [ l.source.name for l in linksview.list_links(path, LINK_DIR_BACKWARD) ] n_backlinks = linksview.n_list_links(path, LINK_DIR_BACKWARD) self.assertEqual(mybacklinks, backlinks) self.assertEqual(n_backlinks, len(backlinks)) all_links = [(l.source.name, l.target.name) for l in linksview.list_links(path, LINK_DIR_BOTH)] n_all_links = linksview.n_list_links(path, LINK_DIR_BOTH) self.assertEqual(all_links, [(name, l) for l in links] + [(l, name) for l in backlinks]) self.assertEqual(n_all_links, len(all_links)) if path.parent.isroot: mylinks = list(linksview.list_links_section(path)) self.assertTrue(len(mylinks) >= len(links)) n_links = linksview.n_list_links_section(path) self.assertEqual(n_links, len(mylinks)) lclinks = [(l.source, l.target) for l in linksview.list_floating_links('foo')] uclinks = [(l.source, l.target) for l in linksview.list_floating_links('FOO')] self.assertGreater(len(lclinks), 0) self.assertEqual(lclinks, uclinks)
def testNewFile(self): attachment_dir = self.setUpFolder(mock=tests.MOCK_ALWAYS_REAL) notebook = self.setUpNotebook() notebook.get_attachments_dir = lambda *a: attachment_dir page = notebook.get_page(Path('Test')) for name in ( 'equation.png', 'equation.tex', 'equation001.png', 'equation001.tex', 'equation002.tex', 'equation003.png', 'equation004.png', 'equation004.tex', ): attachment_dir.file(name).touch() otype = PluginManager.insertedobjects['image+equation'] model = otype.model_from_data(notebook, page, {}, '') self.assertEqual(model.image_file.basename, 'equation005.png') self.assertEqual(model.script_file.basename, 'equation005.tex')
def testMovePageDialog(self): '''Test MovePageDialog''' # Can't test much here except for the call to do_move_page self.ui.mock_method('do_move_page', True) dialog = zim.gui.MovePageDialog(self.ui, path=Path('Test:foo:bar')) self.assertTrue(dialog.form['update']) self.assertTrue( dialog.form.widgets['update'].get_property('sensitive')) dialog.form['parent'] = Path('New') dialog.assert_response_ok() self.assertEqual( self.ui.mock_calls[-1], ('do_move_page', Path('Test:foo:bar'), Path('New:bar'), True)) dialog = zim.gui.MovePageDialog(self.ui, path=Path('New:bar')) self.assertFalse(dialog.form['update']) self.assertFalse( dialog.form.widgets['update'].get_property('sensitive')) dialog.form['parent'] = Path('foo') dialog.assert_response_ok() self.assertEqual( self.ui.mock_calls[-1], ('do_move_page', Path('New:bar'), Path('foo:bar'), False))
def do_response_ok(self): name = self.form['name'] parent = self.form['parent'] head = self.form['head'] update = self.form['update'] newbasename = Path.makeValidPageName(name) newpath = parent + newbasename if parent else Path(newbasename) if newpath == self.path: return False self.hide() # hide this dialog before showing the progressbar op = NotebookOperation( self.notebook, _('Updating Links'), # T: label for progress dialog self.notebook.move_page_iter(self.path, newpath, update_links=update, update_heading=head)) dialog = ProgressDialog(self, op) dialog.run() return True
def runTest(self): output_folder = self.setUpFolder() notebook = self.setUpNotebook(content=tests.FULL_NOTEBOOK) i = 0 print('') for template, file in list_templates(self.format): #print 'Testing template: %s' % template pages = AllPages(notebook) # TODO - sub-section ? exporter = build_notebook_exporter(output_folder.folder(template), self.format, template) self.assertIsInstance(exporter, MultiFileExporter) with tests.LoggingFilter('zim.formats.latex', 'Could not find latex equation'): exporter.export(pages) file = exporter.layout.page_file(Path('roundtrip')) text = file.read() self.assertIn('Lorem ipsum dolor sit amet', text) i += 1 if self.format in ('html', 'latex'): self.assertTrue(i >= 3) # Ensure we actually tested something ..
def testInsertObjectDialog(self): attachment_dir = self.setUpFolder(mock=tests.MOCK_ALWAYS_REAL) notebook = self.setUpNotebook() notebook.get_attachments_dir = lambda *a: attachment_dir page = notebook.get_page(Path('Test')) otype = PluginManager.insertedobjects['image+equation'] def edit_dialog(dialog): self.assertIsInstance(dialog, ImageGeneratorDialog) dialog.set_text(r'c = \sqrt{ a^2 + b^2 }') dialog.update_image() dialog.assert_response_ok() with tests.DialogContext(edit_dialog): model = otype.new_model_interactive(None, notebook, page) attrib, data = otype.data_from_model(model) self.assertTrue(attrib['src']) self.assertEqual( attachment_dir.file('equation.tex').read(), r'c = \sqrt{ a^2 + b^2 }') assertIsPNG(attachment_dir.file('equation.png'))
def runTest(self): path = Path('Test:foo:bar') window = setUpMainWindow(self.setUpNotebook(), path) #self.assertTrue(window.uistate['show_menubar']) window.toggle_menubar() #self.assertFalse(window.uistate['show_menubar']) window.toggle_menubar() #self.assertTrue(window.uistate['show_menubar']) mywidget = MockSidePaneWidget() mywidget.show_all() window.add_tab('Test', mywidget, LEFT_PANE) self.assertTrue(window.uistate['left_pane'][0]) window.toggle_panes() self.assertFalse(window.uistate['left_pane'][0]) window.toggle_panes() self.assertTrue(window.uistate['left_pane'][0]) # .. window.toggle_fullscreen() window.toggle_fullscreen()
def testDownHistory(self): pages = ( 'A', 'A:B', 'A:C' ) window = setUpMainWindow(self.setUpNotebook(content=pages), path='A') self.assertEqual(window.page, Path('A')) window.open_page_child() self.assertEqual(window.page, Path('A:B')) window.open_page(Path('A:C')) window.open_page(Path('A')) self.assertEqual(window.page, Path('A')) window.open_page_child() self.assertEqual(window.page, Path('A:C'))
def runTest(self): '''Test PageEntry widget''' entry = self.entry reference = self.reference entry.set_path(Path('Test')) self.assertEqual(entry.get_text(), ':Test') self.assertEqual(entry.get_path(), Path('Test')) entry.set_text('bar') self.assertEqual(entry.get_path(), Path('Bar')) # resolved due to placeholder entry.set_text('non existing') self.assertEqual(entry.get_path(), Path('Test:non existing')) entry.set_text('+bar') self.assertEqual(entry.get_path(), Path('Test:foo:bar')) entry.set_text(':bar') self.assertEqual(entry.get_path(), Path('Bar')) ## Test completion def get_completions(entry): completion = entry.get_completion() model = completion.get_model() return [r[0] for r in model] entry.set_text('+T') self.assertEqual(get_completions(entry), ['+bar']) entry.set_text(':T') completions = get_completions(entry) self.assertTrue(len(completions) > 5 and ':Test' in completions) entry.set_text('T') self.assertTrue(len(completions) > 5 and ':Test' in completions) # completion now has full notebook entry.set_text('Test:') self.assertEqual(get_completions(entry), [ 'Test:foo', 'Test:Foo Bar', 'Test:Foo(Bar)', 'Test:tags', 'Test:wiki' ])
def testAttachFileDialog(self): '''Test AttachFileDialog''' tmp_dir = self.create_tmp_dir('testAttachFileDialog') file = File((tmp_dir, 'file_to_be_attached')) file.write('Test 1 2 3\n') newfile = File( (tmp_dir, 'attachments', 'Test', 'foo', 'file_to_be_attached')) self.assertTrue(file.exists()) self.assertFalse(newfile.exists()) mainwindow = tests.MockObject() mainwindow.pageview = tests.MockObject() mainwindow.ui = self.ui dialog = zim.gui.AttachFileDialog(mainwindow, self.ui.notebook, path=Path('Test:foo')) dialog.set_file(file) tests.gtk_process_events() dialog.assert_response_ok() self.assertTrue(file.exists()) # No move or delete happened self.assertTrue(newfile.exists()) self.assertTrue(newfile.compare(file))
def runTest(self): tdir = Dir(self.get_tmp_name()) topfile = tdir.file('page.html') dir = tdir.subdir('page_files') rdir = dir.subdir('_resources') layout = SingleFileLayout(topfile, page=Path('Test')) self.assertEqual(layout.relative_root, dir) self.assertEqual(layout.resources_dir(), rdir) for path, file, adir in ( (Path('Test'), topfile, dir), (Path('Test:Foo'), topfile, dir.subdir('Foo')), (Path('Test:Foo:Bar'), topfile, dir.subdir('Foo/Bar')), ): self.assertEqual(layout.page_file(path), file) self.assertEqual(layout.attachments_dir(path), adir) self.assertRaises(PathLookupError, layout.page_file, Path(':')) self.assertRaises(PathLookupError, layout.page_file, Path('Foo'))
def runTest(self): tdir = self.setUpFolder() topfile = tdir.file('page.html') dir = tdir.folder('page_files') rdir = dir.folder('_resources') layout = FileLayout(topfile, Path('Test'), 'html') self.assertEqual(layout.relative_root, dir) self.assertEqual(layout.resources_dir(), rdir) for path, file, adir in ( (Path('Test'), topfile, dir), (Path('Test:Foo'), dir.file('Foo.html'), dir.folder('Foo')), (Path('Test:Foo:Bar'), dir.file('Foo/Bar.html'), dir.folder('Foo/Bar')), ): self.assertEqual(layout.page_file(path), file) self.assertEqual(layout.attachments_dir(path), adir) self.assertRaises(PathLookupError, layout.page_file, Path(':')) self.assertRaises(PathLookupError, layout.page_file, Path('Foo'))
def on_row_activated(self, view, path, col): page = Path(view.get_model()[path][view.NAME_COL]) self.navigation.open_page(page)
def testActivatePage(self): navigation = tests.MockObject() pathbar = MyPathBar(None, None, navigation) button = pathbar.get_children()[2] button.clicked() self.assertEqual(navigation.mock_calls, [('open_page', Path('bbb'))])
def get_paths(self): return [Path(n) for n in ['aaa', 'bbb', 'ccc']]
def setUp(self): self.format = get_format('html') notebook = self.setUpNotebook(content=tests.FULL_NOTEBOOK) self.page = notebook.get_page(Path('Foo'))
class ZimClipPlugin(PluginClass): ''' Zimclip plugin: copy app manifests and configure namespaces ''' plugin_info = { 'name': 'Zim Clip', # T: plugin name 'description': _('Copy app manifests files for\n' 'the zim-clip web browser addon.\n' 'Only for Firefox and Chromium\n' 'on Linux and Mac OS X.\n'), # T: plugin description 'author': 'Rui Nibau', 'version': '1.0.3' } plugin_preferences = ( # key, type, label, default ('marks', 'namespace', _('Marks page'), Path(':marks') ), # T: input label ('clips', 'namespace', _('Clips namespace'), Path(':clips')), # T: input label ) def __init__(self, config=None): PluginClass.__init__(self, config) self.add_manifests() self.preferences.connect('changed', self.on_preferences_changed) self.on_preferences_changed(self.preferences) def teardown(self): ''' Remove app manifests on deactivation ''' self.remove_manifests() def on_preferences_changed(self, preferences): ''' Write data for zimclip web browser extension ''' cfg_file = open(CFG_PATH, 'w') cfg_file.write( json.dumps({ 'path': ZIM_EXECUTABLE, 'marks': str(preferences['marks']), 'clips': str(preferences['clips']) })) cfg_file.close() def add_manifests(self): ''' Add app manifests for supported browsers. ''' platform = sys.platform if platform in MANIFEST_PATHS: for browser, path in MANIFEST_PATHS[platform].items(): if not os.path.exists(path): os.makedirs(path) mpath = os.path.join(path, MANIFEST_NAME) if os.path.isfile(mpath) is False: logger.info('zim-clip: Installing app manifest for ' + browser) logger.debug(mpath) # read template tpl_file = open( os.path.join(BASE_PATH, 'data', browser + '.json'), 'r') tpl = tpl_file.read() tpl_file.close() data = json.loads(tpl) # Update template data data['path'] = os.path.join(BASE_PATH, 'zimclip.py') # write manifest m_file = open(mpath, 'w') m_file.write(json.dumps(data)) m_file.close() else: logger.info('zim-clip: Platform not supported') def remove_manifests(self): ''' Remove app manifests. ''' platform = sys.platform if platform in MANIFEST_PATHS: for browser, path in MANIFEST_PATHS[platform].items(): mpath = os.path.join(path, MANIFEST_NAME) if os.path.isfile(mpath): logger.info('zim-clip: Removing app manifest for ' + browser) logger.debug(mpath) os.remove(mpath)
def runTest(self): 'Test WWW interface' notebook = self.setUpNotebook(content=tests.FULL_NOTEBOOK) notebook.index.check_and_update() interface = WWWInterface(notebook, template=self.template) validator = wsgiref.validate.validator(interface) def call(command, path): #print("CALL:", command, path) environ = { 'REQUEST_METHOD': command, 'SCRIPT_NAME': '', 'PATH_INFO': path, 'QUERY_STRING': '', 'SERVER_NAME': 'localhost', 'SERVER_PORT': '80', 'SERVER_PROTOCOL': '1.0' } rfile = BytesIO(b'') wfile = BytesIO() handler = wsgiref.handlers.SimpleHandler(rfile, wfile, sys.stderr, environ) handler.run(validator) return wfile.getvalue() # index for path in ('/', '/Test/'): response = call('HEAD', path) self.assertResponseOK(response, expectbody=False) response = call('GET', path) #print('>'*80, '\n', response, '<'*80) header, body = self.assertResponseOK(response) self.assertIn( b'<li><a href="/Test/foo.html" title="foo" class="page">foo</a>', body) # page afolder = notebook.get_attachments_dir(Path('Test:foo')) afile = afolder.file('attachment.pdf') afile.touch() response = call('GET', '/Test/foo.html') header, body = self.assertResponseOK(response) self.assertIn(b'<h1>Foo <a name=\'Test:foo\'></a></h1>', body) # - ensure page link works self.assertIn(b'<a href="/Test/foo/bar.html"', body) # - ensure attachment link works self.assertIn( b"<td><a href='/%2Bfile/Test/foo/attachment.pdf'>attachment.pdf</a></td>", body) # - ensure sub page does not show up as attachment self.assertNotIn(b'bar.txt', body) # page not found with Filter404(): for path in self.file_not_found_paths: response = call('GET', path) header, body = self.assertResponseWellFormed(response) self.assertEqual(header[0], 'HTTP/1.0 404 Not Found') # favicon and other files for path in self.file_found_paths: response = call('GET', path) header, body = self.assertResponseWellFormed(response) self.assertEqual(header[0], 'HTTP/1.0 200 OK')
def runTest(self): # Test in 4 parts: # 1. insert files # 2. update files # 3. add some placeholders # 4. delete files self.root = self.setUpFolder() layout = FilesLayout(self.root) db = sqlite3.connect(':memory:') db.row_factory = sqlite3.Row file_indexer = tests.MockObject() indexer = PagesIndexer(db, layout, file_indexer) def cb_filter_func(name, o, a): if name == 'page-changed': row, content = a elif name == 'page-row-changed': row, oldrow = a else: row, = a self.assertIsInstance(row, sqlite3.Row) return row['name'] signals = tests.SignalLogger(indexer, cb_filter_func) # 1. insert files for i, path in enumerate(self.FILES): file = self.root.file(path) file.write('test 123') row = {'id': i, 'path': path} indexer.on_file_row_inserted(file_indexer, row) self.assertPagesDBConsistent(db) self.assertPagesDBEquals(db, self.PAGES) self.assertEqual(set(signals['page-row-inserted']), set(self.PAGES)) self.assertEqual(set(signals['page-row-changed']), set(self.NAMESPACES)) self.assertEqual(signals['page-row-deleted'], []) self.assertEqual(signals['page-changed'], []) # 2. update files signals.clear() for i, path in enumerate(self.FILES): row = {'id': i, 'path': path} indexer.on_file_row_changed(file_indexer, row) self.assertPagesDBConsistent(db) self.assertPagesDBEquals(db, self.PAGES) self.assertEqual(signals['page-row-inserted'], []) self.assertEqual(set(signals['page-row-changed']), set(self.CONTENT)) self.assertEqual(signals['page-row-deleted'], []) self.assertEqual(set(signals['page-changed']), set(self.CONTENT)) # 3. add some placeholders for pagename in self.PLACEHOLDERS: indexer.insert_link_placeholder(Path(pagename)) self.assertPagesDBConsistent(db) self.assertPagesDBEquals(db, self.PAGES + self.PLACEHOLDERS_ALL) for pagename in self.PLACEHOLDERS: indexer.delete_link_placeholder(Path(pagename)) self.assertPagesDBConsistent(db) self.assertPagesDBEquals(db, self.PAGES) # 4. delete files signals.clear() for i, path in enumerate(self.FILES): file = self.root.file(path) file.remove() row = {'id': i, 'path': path} indexer.on_file_row_deleted(file_indexer, row) self.assertPagesDBConsistent(db) self.assertPagesDBEquals(db, []) self.assertEqual(signals['page-row-inserted'], []) self.assertEqual(set(signals['page-row-changed']), set(['foo'])) # "foo" has source that is deleted before children self.assertEqual(set(signals['page-row-deleted']), set(self.PAGES)) self.assertEqual(signals['page-changed'], ['foo'])
def row_activated(self, path, column): '''Open page in the view.''' iter = self.model.get_iter(path) name = self.model.get_value(iter, self.PAGE_COL) self.ui.open_page(Path(name))
def _do_open_page(self, view, path, col): page = Path(self.get_model()[path][self.NAME_COL].decode('utf-8')) self.ui.open_page(page)
def runTest(self): notebook = self.setUpNotebook(content=tests.FULL_NOTEBOOK) treestore = PageTreeStore(notebook.index) init_model_validator_wrapper(self, treestore) self.assertEqual(treestore.get_flags(), 0) self.assertEqual(treestore.get_n_columns(), 7) for i in range(treestore.get_n_columns()): self.assertTrue(not treestore.get_column_type(i) is None) n = treestore.on_iter_n_children(None) self.assertTrue(n > 0) n = treestore.iter_n_children(None) self.assertTrue(n > 0) # Quick check for basic methods iter = treestore.on_get_iter((0, )) self.assertTrue(isinstance(iter, MyTreeIter)) self.assertFalse(iter.row['name'] == '') self.assertEqual(iter.treepath, Gtk.TreePath((0, ))) self.assertEqual(treestore.on_get_path(iter), Gtk.TreePath((0, ))) self.assertEqual(treestore.find(Path(iter.row['name'])), Gtk.TreePath((0, ))) basename = treestore.on_get_value(iter, 0) self.assertTrue(len(basename) > 0) iter2 = treestore.on_iter_children(None) self.assertIs(iter2, iter) self.assertIsNone(treestore.on_get_iter((20, 20, 20, 20, 20))) self.assertRaises(IndexNotFoundError, treestore.find, Path('nonexisting')) self.assertRaises(ValueError, treestore.find, Path(':')) # Now walk through the whole notebook testing the API # with nested pages and stuff npages = 0 path = [] for page in notebook.pages.walk(): #~ print('>>', page) npages += 1 names = page.name.split(':') if len(names) > len(path): path.append(0) # always increment by one elif len(names) < len(path): while len(names) < len(path): path.pop() path[-1] += 1 else: path[-1] += 1 #~ print('>>', page, path) iter = treestore.get_iter(tuple(path)) indexpath = treestore.get_indexpath(iter) #~ print('>>>', indexpath) self.assertEqual(indexpath, page) self.assertEqual(treestore.get_value(iter, NAME_COL), page.basename) self.assertEqual(treestore.get_value(iter, PATH_COL), page) if not treestore.get_value(iter, EXISTS_COL): self.assertEqual(treestore.get_value(iter, STYLE_COL), Pango.Style.ITALIC) else: self.assertEqual(treestore.get_value(iter, STYLE_COL), Pango.Style.NORMAL) self.assertEqual(treestore.get_path(iter), Gtk.TreePath(path)) if indexpath.haschildren: self.assertTrue(treestore.iter_has_child(iter)) child = treestore.iter_children(iter) self.assertTrue(not child is None) child = treestore.iter_nth_child(iter, 0) self.assertTrue(not child is None) parent = treestore.iter_parent(child) self.assertEqual(treestore.get_indexpath(parent), page) childpath = treestore.get_path(child) self.assertEqual(childpath, Gtk.TreePath(tuple(path) + (0, ))) n = treestore.iter_n_children(iter) for i in range(1, n): child = treestore.iter_next(child) childpath = treestore.get_path(child) self.assertEqual(childpath, Gtk.TreePath(tuple(path) + (i, ))) child = treestore.iter_next(child) self.assertIsNone(child) # children exhausted else: self.assertTrue(not treestore.iter_has_child(iter)) child = treestore.iter_children(iter) self.assertTrue(child is None) child = treestore.iter_nth_child(iter, 0) self.assertTrue(child is None) self.assertTrue(npages > 10) # double check sanity of walk() method
def _process_content(self, terms, results, scope, operator, callback=None): # Process terms for content, process many at once in order to # only open the page once and allow for a linear behavior of the # callback function. (We could also have relied on page objects # caching the parsetree, but then there is no way to support a # useful callback method.) # Note that this rationale is for flat searches, once sub-groups # are involved things get less optimized. # # For AND 'scope' will be the results of previous steps, we make a subset # of this. In 'results' will only be any final results already obtained from # contentorname optimization # For OR 'results' is whatever was found so far while 'scope' can be larger # we extend the results with any matches from scope for term in terms: term.content_regex = self._content_regex(term.string) # term.name_regex already defined in _process_from_index if scope: def page_generator(): for path in scope: try: yield self.notebook.get_page(path) except PageNotFoundError: pass generator = page_generator() else: generator = map(self.notebook.get_page, self.notebook.pages.walk()) if results is None: results = SearchSelection(None) for page in generator: #~ print '!! Search content', page try: tree = page.get_parsetree() except: logger.exception('Exception while reading: %s', page) continue if tree is None: continue # Assume need to have content even for negative query path = Path(page.name) if operator == OPERATOR_AND: score = 0 for term in terms: #~ print '!! Count AND %s' % term myscore = tree.countre(term.content_regex) if term.keyword == 'contentorname' \ and term.name_regex.match(path.name): myscore += 1 # effective score going to 11 if bool(myscore) != term.inverse: # implicit XOR score += myscore or 1 else: score = 0 break if score: results.add(path) self._count_score(path, score) else: # OPERATOR_OR for term in terms: #~ print '!! Count OR %s' % term score = tree.countre(term.content_regex) if term.keyword == 'contentorname' \ and term.name_regex.match(path.name): score += 1 # effective score going to 11 if bool(score) != term.inverse: # implicit XOR results.add(path) self._count_score(path, score or 1) if callback: # Since we are always last in the processing of the # (top-level) group, we can call the callback with all results cont = callback(results, path) if not cont: self.cancelled = True break return results