Example #1
0
	def runTest(self):
		'''Test Page object'''
		TestPath.runTest(self)

		tree = ParseTree().fromstring('''\
<zim-tree>
<link href='foo:bar'>foo:bar</link>
<link href='bar'>bar</link>
</zim-tree>
'''		)
		page = Page(Path('Foo'))
		page.readonly = False
		page.set_parsetree(tree)

		links = list(page.get_links())
		self.assertEqual(links, [
			('page', 'foo:bar', {}),
			('page', 'bar', {}),
		] )

		self.assertEqual(page.get_parsetree().tostring(), tree.tostring())
			# ensure we didn't change the tree

		# TODO test get / set parse tree with and without source

		tree = ParseTree().fromstring('<zim-tree></zim-tree>')
		self.assertFalse(tree.hascontent)
		page.set_parsetree(tree)
		self.assertFalse(page.hascontent)
Example #2
0
def deserialize_parse_tree(register_buf, content_buf, iter, data, length,
                           create_tags, user_data):
    notebook, path = user_data
    tree = ParseTree().fromstring(data)
    tree.resolve_images(notebook, path)
    content_buf.insert_parsetree(iter, tree, interactive=True)
    return True
Example #3
0
	def testMain(self):
		'''Test Page object'''
		TestPath.runTest(self)

		tree = ParseTree().fromstring('''\
<zim-tree>
<link href='foo:bar'>foo:bar</link>
<link href='bar'>bar</link>
<tag name='baz'>@baz</tag>
</zim-tree>
'''		)
		page = self.generator('Foo')
		page.set_parsetree(tree)

		links = list(page.get_links())
		self.assertEqual(links, [
			('page', 'foo:bar', {}),
			('page', 'bar', {}),
		] )

		tags = list(page.get_tags())
		self.assertEqual(tags, [
			('baz', {'name': 'baz'}),
		])

		self.assertEqual(page.get_parsetree().tostring(), tree.tostring())
			# ensure we didn't change the tree

		# TODO test get / set parse tree with and without source

		tree = ParseTree().fromstring('<zim-tree></zim-tree>')
		self.assertFalse(tree.hascontent)
		page.set_parsetree(tree)
		self.assertFalse(page.hascontent)
def main(orig_file, notebook_path):
    assert(os.path.isdir(notebook_path))
    assert(os.path.isfile(orig_file))

    dumper = get_format('wiki').Dumper()
    parser = get_format('wiki').Parser()

    text = open(orig_file).read()
    parsetree = parser.parse(text)
    newtree = ParseTree().fromstring("<zim-tree></zim-tree>")

    for para in parsetree.findall('p'):
        p = Element("p")
        for node in flatten_list(para, para):
            p.append(node)
        newtree.getroot().extend(p)

    # new todo list
    text = ''.join(dumper.dump(newtree)).encode('utf-8')

    tomorrow = date.today() + timedelta(1)

    directory = os.path.join(notebook_path, "Calendar", str("%04d" % tomorrow.year), str("%02d" % tomorrow.month))
    filename = "%02d.txt" % tomorrow.day
    if (not os.path.exists(directory)): os.makedirs(directory)

    # write tasks to tomorrow page.
    with open(os.path.join(directory, filename), 'a+') as the_file:
         the_file.write(text)

    # update original wiki page.
    text = ''.join(dumper.dump(parsetree) ).encode('utf-8')
    with open(orig_file, 'w') as the_file:
         the_file.write(text)
Example #5
0
File: gui.py Project: Jam71/Zim-QDA
	def testRenamePageDialogWithHeadingChanges(self):
		'''Test RenamePageDialog's heading auto-change option depending on
		whether we have a changed heading or not.
		'''
		tree = ParseTree().fromstring('<zim-tree></zim-tree>')
		tree.set_heading("bar")
		self.ui.page = Page(Path("Test:foo:bar"), parsetree=tree)
		self.ui.notebook.get_page = lambda path: self.ui.page
		dialog = zim.gui.RenamePageDialog(self.ui, path=Path("Test:foo:bar"))
		self.assertTrue(dialog.form['head'])
		tree.set_heading("different")
		dialog = zim.gui.RenamePageDialog(self.ui, path=Path("Test:foo:bar"))
		self.assertFalse(dialog.form['head'])
Example #6
0
 def testSortListItems(self):
     from zim.formats import ParseTree
     template = '<?xml version=\'1.0\' encoding=\'utf-8\'?>\n<zim-tree><p><ul>%s</ul></p></zim-tree>'
     tree = ParseTree().fromstring(
         template %
         '<li>B list item</li><li>C list item</li><li>A list item</li>')
     self.buffer.set_parsetree(tree)
     self.select_range(0, 42)
     self.extension.sort_selected_lines()
     tree = self.buffer.get_parsetree()
     self.assertEqual(
         tree.tostring(), template %
         '<li bullet="*">A list item</li><li bullet="*">B list item</li><li bullet="*">C list item</li>'
     )
Example #7
0
def _link_tree(links, notebook, path):
	# Convert a list of links (of any type) into a parsetree
	#~ print 'LINKS: ', links
	#~ print 'NOTEBOOK and PATH:', notebook, path
	builder = TreeBuilder()
	builder.start('zim-tree')
	for i in range(len(links)):
		if i > 0:
			builder.data(' ')

		link = links[i]
		type = link_type(link)
		isimage = False
		if type == 'file':
			try:
				file = File(link)
				isimage = file.isimage()
			except:
				pass

		logger.debug('Pasting link: %s (type: %s, isimage: %s)', link, type, isimage)

		if isimage:
			src = notebook.relative_filepath(file, path) or file.uri
			builder.start('img', {'src': src})
			builder.end('img')
		elif link.startswith('@'):
			# FIXME - is this ever used ??
			builder.start('tag', {'name': links[i][1:]})
			builder.data(links[i])
			builder.end('tag')
		else:
			if type == 'page':
				href = Path(notebook.cleanup_pathname(link)) # Assume links are always absolute
				link = notebook.relative_link(path, href) or link
			elif type == 'file':
				file = File(link) # Assume links are always URIs
				link = notebook.relative_filepath(file, path) or file.uri

			builder.start('link', {'href': link})
			builder.data(link)
			builder.end('link')

	builder.end('zim-tree')
	tree = ParseTree(builder.close())
	tree.resolve_images(notebook, path)
	tree.decode_urls()
	return tree
Example #8
0
def new_parsetree_from_xml(xml):
    # For some reason this does not work with cElementTree.XMLBuilder ...
    from xml.etree.ElementTree import XMLParser
    from zim.formats import ParseTree
    builder = XMLParser()
    builder.feed(xml)
    root = builder.close()
    return ParseTree(root)
Example #9
0
    def testPageSource(self):
        from zim.newfs.mock import MockFile, MockFolder

        file = MockFile('/mock/test/page.txt')
        folder = MockFile('/mock/test/page/')
        page = Page(Path('Foo'), False, file, folder)

        self.assertFalse(page.readonly)
        self.assertFalse(page.hascontent)
        self.assertIsNone(page.ctime)
        self.assertIsNone(page.mtime)
        self.assertIsNone(page.get_parsetree())

        page1 = Page(Path('Foo'), False, file, folder)
        self.assertTrue(page.isequal(page1))

        tree = ParseTree().fromstring('''\
<zim-tree>
<link href='foo:bar'>foo:bar</link>
<link href='bar'>bar</link>
<tag name='baz'>@baz</tag>
</zim-tree>
''')
        page.set_parsetree(tree)
        page._store()

        self.assertTrue(file.exists())
        self.assertTrue(page.hascontent)
        self.assertIsInstance(page.ctime, float)
        self.assertIsInstance(page.mtime, float)

        lines = file.readlines()
        self.assertEqual(lines[0], 'Content-Type: text/x-zim-wiki\n')
        self.assertEqual(lines[1][:11], 'Wiki-Format')
        self.assertEqual(lines[2][:13], 'Creation-Date')

        self.assertEqual(page.get_parsetree(), tree)

        self.assertTrue(page.isequal(page1))
        self.assertTrue(page1.hascontent)
        self.assertIsInstance(page1.ctime, float)
        self.assertIsInstance(page1.mtime, float)
        self.assertIsNotNone(page1.get_parsetree())

        file.write('foo 123')
        page.set_parsetree(tree)

        self.assertRaises(zim.newfs.FileChangedError, page._store)

        ### Custom header should be preserved
        file.writelines(lines[0:3] + ['X-Custom-Header: MyTest'] + lines[3:])
        page = Page(Path('Foo'), False, file, folder)
        tree = page.get_parsetree()
        page.set_parsetree(tree)
        page._store()
        lines = file.readlines()
        self.assertEqual(lines[0], 'Content-Type: text/x-zim-wiki\n')
        self.assertEqual(lines[3], 'X-Custom-Header: MyTest\n')
	def testModelFromData(self):
		notebook = self.setUpNotebook()
		page = notebook.get_page(Path('Test'))
		model = self.otype.model_from_data(notebook, page, {}, TABLE_WIKI_TEXT)

		builder = OldParseTreeBuilder() # XXX
		builder.start('zim-tree')
		self.otype.dump(builder, model)
		builder.end('zim-tree')
		tree = ParseTree(builder.close())

		#self.assertEquals(list(tree.iter_tokens()), TABLE_TOKENS) -- XXX should work but doesn;t :(
		self.assertEquals(''.join(WikiDumper().dump(tree)), TABLE_WIKI_TEXT[1:-1])
Example #11
0
    def testDumpHtml(self):
        xml = '''\
<?xml version='1.0' encoding='utf-8'?>
<zim-tree><object lang="python" linenumbers="false" type="code">
def foo(a, b):
	print "FOO", a >= b

</object></zim-tree>'''
        tree = ParseTree().fromstring(xml)
        dumper = HtmlDumper(StubLinker())
        html = dumper.dump(tree)
        #~ print '>>', html
        self.assertIn('\tprint "FOO", a &gt;= b\n', html)
	def testModelFromElement(self):
		tree = WikiParser().parse(TABLE_WIKI_TEXT)
		element = tree._etree.getroot().find('table')
		self.assertIsNotNone(element)
		model = self.otype.model_from_element(element.attrib, element)

		builder = OldParseTreeBuilder() # XXX
		builder.start('zim-tree')
		self.otype.dump(builder, model)
		builder.end('zim-tree')
		tree = ParseTree(builder.close())

		#self.assertEquals(list(tree.iter_tokens()), TABLE_TOKENS) -- XXX should work but doesn;t :(
		self.assertEquals(''.join(WikiDumper().dump(tree)), TABLE_WIKI_TEXT[1:-1])
Example #13
0
	def testShouldAutochangeHeading(self):
		page = Page(Path("Foo"))
		page.readonly = False
		tree = ParseTree().fromstring('<zim-tree></zim-tree>')
		tree.set_heading("Foo")
		page.set_parsetree(tree)
		self.assertTrue(page.heading_matches_pagename())
		tree.set_heading("Bar")
		page.set_parsetree(tree)
		self.assertFalse(page.heading_matches_pagename())
 def _clicked(self, tv, event):
     pos_path = self.get_path_at_pos(int(event.x), int(event.y))
     buffer = self.app_window.pageview.view.get_buffer()
     # paste link at current cursor if middle click
     if event.button == 2 and pos_path is not None:
         path, col, cellx, celly = pos_path
         page = Path(self.get_model()[path][0].decode('utf-8'))
         # make link
         xml = """<?xml version='1.0' encoding='utf-8'?>""" + \
            """<zim-tree partial="True">""" + \
            '<link href=":%(path)s">:%(disp)s</link> ' + \
            '</zim-tree>'
         dispdict = {'path': page, 'disp': page}
         link = ParseTree().fromstring(xml % dispdict)
         # insert into current page
         buffer.insert_parsetree_at_cursor(link)
         self.window.get_parent().destroy()
Example #15
0
    def testShouldAutochangeHeading(self):
        from zim.newfs.mock import MockFile, MockFolder
        file = MockFile('/mock/test/page.txt')
        folder = MockFile('/mock/test/page/')
        page = Page(Path('Foo'), False, file, folder)

        tree = ParseTree().fromstring('<zim-tree></zim-tree>')
        tree.set_heading("Foo")
        page.set_parsetree(tree)
        self.assertTrue(page.heading_matches_pagename())
        tree.set_heading("Bar")
        page.set_parsetree(tree)
        self.assertFalse(page.heading_matches_pagename())
Example #16
0
    def testRenamePageDialogWithHeadingChanges(self):
        '''Test RenamePageDialog's heading auto-change option depending on
		whether we have a changed heading or not.
		'''
        tree = ParseTree().fromstring('<zim-tree></zim-tree>')
        tree.set_heading("bar")
        self.ui.page = Page(Path("Test:foo:bar"), parsetree=tree)
        self.ui.notebook.get_page = lambda path: self.ui.page
        dialog = zim.gui.RenamePageDialog(self.ui, path=Path("Test:foo:bar"))
        self.assertTrue(dialog.form['head'])
        tree.set_heading("different")
        dialog = zim.gui.RenamePageDialog(self.ui, path=Path("Test:foo:bar"))
        self.assertFalse(dialog.form['head'])
Example #17
0
    def testPageSource(self):
        from zim.newfs.mock import MockFile, MockFolder

        file = MockFile('/mock/test/page.txt')
        folder = MockFile('/mock/test/page/')
        page = Page(Path('Foo'), False, file, folder)

        self.assertFalse(page.readonly)
        self.assertFalse(page.hascontent)
        self.assertIsNone(page.ctime)
        self.assertIsNone(page.mtime)
        self.assertIsNone(page.get_parsetree())

        page1 = Page(Path('Foo'), False, file, folder)
        self.assertTrue(page.isequal(page1))

        tree = ParseTree().fromstring('''\
<zim-tree>
<link href='foo:bar'>foo:bar</link>
<link href='bar'>bar</link>
<tag name='baz'>@baz</tag>
</zim-tree>
''')
        page.set_parsetree(tree)
        page._store()

        self.assertTrue(file.exists())
        self.assertTrue(page.hascontent)
        self.assertIsInstance(page.ctime, float)
        self.assertIsInstance(page.mtime, float)

        self.assertEqual(page.get_parsetree(), tree)

        self.assertTrue(page.isequal(page1))
        self.assertTrue(page1.hascontent)
        self.assertIsInstance(page1.ctime, float)
        self.assertIsInstance(page1.mtime, float)
        self.assertIsNotNone(page1.get_parsetree())

        file.write('foo 123')
        page.set_parsetree(tree)

        self.assertRaises(zim.newfs.FileChangedError, page._store)
Example #18
0
	def testAPI(self):
		'''Test various notebook methods'''
		self.assertTrue(
			isinstance(self.notebook.get_home_page(), Page))

		page1 = self.notebook.get_page(Path('Tree:foo'))
		page2 = self.notebook.get_page(Path('Tree:foo'))
		self.assertTrue(page1.valid)
		self.assertTrue(id(page2) == id(page1)) # check usage of weakref
		self.notebook.flush_page_cache(Path('Tree:foo'))
		page3 = self.notebook.get_page(Path('Tree:foo'))
		self.assertTrue(id(page3) != id(page1))
		self.assertFalse(page1.valid)

		page = self.notebook.get_page(Path('Test:foo'))
		text = page.dump('plain')
		newtext = ['Some new content\n']
		assert newtext != text
		self.assertEqual(page.dump('plain'), text)
		#~ page.parse('plain', newtext)
		#~ self.assertEqual(page.dump('plain'), newtext)
		#~ self.assertTrue(page.modified)
		#~ re = self.notebook.revert_page(page)
		#~ self.assertFalse(re) # no return value
		#~ self.assertEqual(page.dump('plain'), text) # object reverted
		#~ self.assertFalse(page.modified)
		self.notebook.flush_page_cache(page)
		page = self.notebook.get_page(page) # new object
		self.assertEqual(page.dump('plain'), text)
		page.parse('plain', newtext)
		self.assertEqual(page.dump('plain'), newtext)
		self.notebook.store_page(page)
		self.notebook.flush_page_cache(page)
		page = self.notebook.get_page(page) # new object
		self.assertEqual(page.dump('plain'), newtext)

		# ensure storing empty tree works
		emptytree = ParseTree()
		self.assertFalse(emptytree.hascontent)
		page.set_parsetree(emptytree)
		self.notebook.store_page(page)
Example #19
0
    def testRenamePageDialogWithHeadingChanges(self):
        '''Test RenamePageDialog's heading auto-change option depending on
		whether we have a changed heading or not.
		'''
        from zim.newfs.mock import MockFile, MockFolder
        file = MockFile('/mock/test/page.txt')
        folder = MockFile('/mock/test/page/')
        page = Page(Path("Test:foo:bar"), False, file, folder)

        tree = ParseTree().fromstring('<zim-tree></zim-tree>')
        tree.set_heading("bar")
        page.set_parsetree(tree)

        self.ui.page = page
        self.ui.notebook.get_page = lambda path: self.ui.page
        dialog = zim.gui.RenamePageDialog(self.ui, path=Path("Test:foo:bar"))
        self.assertTrue(dialog.form['head'])
        tree.set_heading("different")
        dialog = zim.gui.RenamePageDialog(self.ui, path=Path("Test:foo:bar"))
        self.assertFalse(dialog.form['head'])
Example #20
0
def parsetree_from_selectiondata(selectiondata, notebook=None, path=None):
	'''Function to get a parsetree based on the selectiondata contents
	if at all possible. Used by both copy-paste and drag-and-drop
	methods.

	The 'notebook' and optional 'path' arguments are used to format
	links relative to the page which is the target for the pasting or
	drop operation.

	For image data, the parameters notebook and page are used
	to save the image to the correct attachment folder and return a
	parsetree with the correct image link.

	@param selectiondata: a C{gtk.SelectionData} object
	@param notebook: a L{Notebook} object
	@param path: a L{Path} object

	@returns: a L{ParseTree} or C{None}
	'''
	# TODO: check relative linking for all parsetrees !!!

	targetname = str(selectiondata.target)
	if targetname == PARSETREE_TARGET_NAME:
		return ParseTree().fromstring(selectiondata.data)
	elif targetname in (INTERNAL_PAGELIST_TARGET_NAME, PAGELIST_TARGET_NAME) \
	or targetname in URI_TARGET_NAMES:
		links = unpack_urilist(selectiondata.data)
		return _link_tree(links, notebook, path)
	elif targetname in TEXT_TARGET_NAMES:
		# plain text parser should highlight urls etc.
		# FIXME some apps drop text/uri-list as a text/plain mimetype
		# try to catch this situation by a check here
		text = selectiondata.get_text()
		if text:
			return get_format('plain').Parser().parse(text.decode('utf-8'), partial=True)
		else:
			return None
	elif targetname in IMAGE_TARGET_NAMES:
		# save image
		pixbuf = selectiondata.get_pixbuf()
		if not pixbuf:
			return None

		dir = notebook.get_attachments_dir(path)
		if not dir.exists():
			logger.debug("Creating attachment dir: %s", dir)
			dir.touch()

		format, extension = _get_image_info(targetname)
		if format is None or format == 'bmp':
			# default to png format
			# special casing bmp since many window apps use it internally
			# but is quite large to store, so compress by using png
			format, extension = 'png', 'png'

		file = dir.new_file('pasted_image.%s' % extension)
		logger.debug("Saving image from clipboard to %s", file)
		pixbuf.save(file.path, format)
		FS.emit('path-created', file) # notify version control

		links = [file.uri]
		return _link_tree(links, notebook, path)
	else:
		return None
Example #21
0
    def runTest(self):
        '''Test indexing'''
        # This is one big test instead of seperate sub tests because in the
        # subclass we generate a file based notebook in setUp, and we do not
        # want to do that many times

        #~ print self.__class__.__name__
        self.index.update()

        #~ print '\n==== DB ===='
        #~ cursor = self.index.db.cursor()
        #~ cursor.execute('select * from pages')
        #~ for row in cursor:
        #~ print row
        #~ cursor.execute('select * from links')
        #~ for row in cursor:
        #~ print row

        # paths / ids
        path = self.index.lookup_path(Path('Test:foo:bar'))
        self.assertTrue(isinstance(path, IndexPath))
        path = self.index.lookup_id(path.id)
        self.assertTrue(isinstance(path, IndexPath))
        self.assertEqual(path.name, 'Test:foo:bar')

        # pages
        pagelist = list(self.index.list_pages(None))
        self.assertTrue(len(pagelist) > 0)
        pagelist = list(self.index.list_pages(Path('Test')))
        self.assertTrue(len(pagelist) > 0)
        for page in pagelist:
            self.assertTrue(page.name.startswith('Test:'))
            self.assertTrue(page.name.count(':') == 1)
        pagelist = list(self.index.list_pages(Path('Linking')))
        self.assertTrue(Path('Linking:Dus') in pagelist)
        pagelist = list(self.index.list_pages(Path('Some:Non:Existing:Path')))
        self.assertTrue(len(pagelist) == 0)

        # links
        forwlist = list(self.index.list_links(Path('Test:foo:bar')))
        backlist = list(
            self.index.list_links(Path('Test:foo:bar'), LINK_DIR_BACKWARD))
        bothlist = list(
            self.index.list_links(Path('Test:foo:bar'), LINK_DIR_BOTH))
        for l in forwlist, backlist, bothlist:
            self.assertTrue(len(l) > 0)
            for link in l:
                self.assertTrue(isinstance(link, Link))
                self.assertTrue(isinstance(link.source, IndexPath))
                self.assertTrue(isinstance(link.href, IndexPath))
        self.assertTrue(len(forwlist) + len(backlist) == len(bothlist))

        n = self.index.n_list_links(Path('Test:foo:bar'), LINK_DIR_BACKWARD)
        self.assertEqual(n, len(backlist))

        # tags
        taglist = list(self.index.list_tags(Path('Test:tags')))
        self.assertTrue(len(taglist) == 11)
        for tag in taglist:
            self.assertTrue(isinstance(tag, IndexTag))
        tagnames = [t.name for t in taglist]
        aretags = [
            'tags', 'beginning', 'end', 'tabs', 'verbatim', 'enumerations',
            'encoding', 's', 'num6ers', 'wit', 'cr'
        ]
        nottags = ['places', 'links', 'captions', 'Headings', 'word']
        for t in aretags:
            self.assertTrue(t in tagnames)
        for t in nottags:
            self.assertTrue(not t in tagnames)

        # cursor.row_count is not reliable - see docs
        def count_pages(db):
            c = db.cursor()
            c.execute('select id from pages')
            r = c.fetchall()
            return len(r)

        def dump_db(db):
            c = db.cursor()
            c.execute('select * from pages')
            text = ''
            for row in c:
                # HACK iterating of sqlite3.Row objects only supported for python 2.6
                myrow = []
                for i in range(len(row)):
                    myrow.append(row[i])
                text += ', '.join(map(str, myrow)) + '\n'
            return text

        # repeat update() to check if update is stable
        manifest = len(self.notebook.testdata_manifest)
        self.assertTrue(count_pages(self.index.db) >= manifest)
        origdb = dump_db(self.index.db)
        self.index.update()
        self.assertEqual(dump_db(self.index.db), origdb)

        # indexkey
        for path in (Path('Test'), Path('Test:foo')):
            indexpath = self.index.lookup_path(path)
            self.assertEqual(indexpath.contentkey,
                             self.notebook.get_page_indexkey(path))
            self.assertEqual(indexpath.childrenkey,
                             self.notebook.get_pagelist_indexkey(path))

        # other functions
        path = self.index.get_unique_path(Path('non-existing-path'))
        self.assertEqual(path, Path('non-existing-path'))
        path = self.index.get_unique_path(Path('Test:foo'))
        self.assertEqual(path, Path('Test:foo_1'))

        # get_previous / get_next
        page = list(self.index.list_pages(None))[0]
        seen = 0
        while page:
            seen = max(seen, page.name.count(':'))
            page = self.index.get_next(page)
        self.assertTrue(seen >= 2)

        page = list(self.index.list_pages(None))[-1]
        seen = 0
        while page:
            seen = max(seen, page.name.count(':'))
            page = self.index.get_previous(page)
        self.assertTrue(seen >= 2)

        # now go through the flush loop
        self.index.flush()
        self.assertEqual(count_pages(self.index.db), 1)
        self.index.update()
        self.assertEqual(dump_db(self.index.db), origdb)

        # now index only part of the tree - and repeat
        self.index.flush()
        self.assertEqual(count_pages(self.index.db), 1)
        self.index.update(Path('Test'))
        self.assertTrue(count_pages(self.index.db) > 2)
        partdb = dump_db(self.index.db)
        self.index.update(Path('Test'))
        self.assertEqual(dump_db(self.index.db), partdb)

        # Index whole tree again
        self.index.update()

        # Check cleanup
        path = Path('New:Nested:Path')
        self.index.touch(path)
        parent = self.index.lookup_path(path.parent)
        self.assertTrue(parent and parent.haschildren)
        self.index.delete(path)
        parent = self.index.lookup_path(path.parent)
        self.assertTrue(parent is None)

        # Check cleanup for links
        links = [
            link.href for link in self.index.list_links(Path('roundtrip'))
        ]
        for p in ('foo:bar', 'Bar'):
            self.assertTrue(Path(p) in links)
            path = self.index.lookup_path(Path('foo:bar'))
            self.assertTrue(path)

        # Check for tag indexing
        tags = [tag.name for tag in self.index.list_tags(Path('roundtrip'))]
        for t in ('foo', 'bar'):
            self.assertTrue(t in tags)
            tagged = list(self.index.list_tagged_pages(t))
            self.assertTrue(Path('roundtrip') in tagged)

        tree = ParseTree().fromstring(
            '<zim-tree><link href=":foo:bar">:foo:bar</link></zim-tree>')
        page = self.notebook.get_page(Path('roundtrip'))
        page.set_parsetree(tree)
        self.notebook.store_page(page)
        path = self.index.lookup_path(Path('Bar'))
        self.assertTrue(path is None)
        path = self.index.lookup_path(Path('foo:bar'))
        self.assertTrue(path)

        self.notebook.delete_page(Path('roundtrip'))
        path = self.index.lookup_path(Path('foo:bar'))
        self.assertTrue(path is None)

        # Check get_page_index() to double check stable sorting
        def check_index(path):
            for i, child in enumerate(self.index.list_pages(path)):
                index = self.index.get_page_index(child)
                #~ print 'INDEX', i, child, '-->', index
                self.assertTrue(index == i, 'Index mismatch for %s' % child)
                if child.haschildren:
                    check_index(child)  # recurs

        check_index(Path(':'))
Example #22
0
def parsetree_from_selectiondata(selectiondata,
                                 notebook=None,
                                 path=None,
                                 text_format='plain'):
    '''Function to get a parsetree based on the selectiondata contents
	if at all possible. Used by both copy-paste and drag-and-drop
	methods.

	The 'notebook' and optional 'path' arguments are used to format
	links relative to the page which is the target for the pasting or
	drop operation.

	For image data, the parameters notebook and page are used
	to save the image to the correct attachment folder and return a
	parsetree with the correct image link.

	@param selectiondata: a C{Gtk.SelectionData} object
	@param notebook: a L{Notebook} object
	@param path: a L{Path} object
	@param text_format: format to parse pasted text, as a special case

		- "verbatim" will wrap content in VERBARIM_BLOCK or VERBATIM element based on the content
		- "verbatim-pre" will wrap the content in a VERBATIM_BLOCK element and
		- "verbatim-code" will wrap the content in a VERBATIM element

	@returns: a L{ParseTree} or C{None}
	'''
    # TODO: check relative linking for all parsetrees !!!

    targetname = selectiondata.get_target().name()
    if targetname == PARSETREE_TARGET_NAME:
        return ParseTree().fromstring(selectiondata.get_data())
    elif targetname in (INTERNAL_PAGELIST_TARGET_NAME, PAGELIST_TARGET_NAME) \
    or targetname in URI_TARGET_NAMES:
        links = selectiondata.get_uris()
        return _link_tree(links, notebook, path)
    elif targetname in TEXT_TARGET_NAMES:
        # plain text parser should highlight urls etc.
        # FIXME some apps drop text/uri-list as a text/plain mimetype
        # try to catch this situation by a check here
        text = selectiondata.get_text()
        if text:
            if text_format in ('verbatim', 'verbatim-pre', 'verbatim-code'):
                if text_format == 'verbatim':
                    tag_name = 'pre' if '\n' in text else 'code'
                else:
                    tag_name = text_format[9:]
                builder = ParseTreeBuilder(partial=True)
                builder.start('zim-tree', {})
                builder.start(tag_name, {})
                builder.text(text)
                builder.end(tag_name)
                builder.end('zim-tree')
                return builder.get_parsetree()
            else:
                return get_format(text_format).Parser().parse(text,
                                                              partial=True)
        else:
            return None
    elif targetname in IMAGE_TARGET_NAMES:
        # save image
        pixbuf = selectiondata.get_pixbuf()
        if not pixbuf:
            return None

        dir = notebook.get_attachments_dir(path)
        assert isinstance(dir, LocalFolder) or hasattr(
            dir, '_folder') and isinstance(dir._folder, LocalFolder)
        # XXX: assert we have local path  - HACK to deal with FilesAttachmentFolder
        if not dir.exists():
            logger.debug("Creating attachment dir: %s", dir)
            dir.touch()

        format, extension = _get_image_info(targetname)
        if format is None or format == 'bmp':
            # default to png format
            # special casing bmp since many window apps use it internally
            # but is quite large to store, so compress by using png
            format, extension = 'png', 'png'

        file = dir.new_file('pasted_image.%s' % extension)
        logger.debug("Saving image from clipboard to %s", file)
        pixbuf.savev(file.path, format, [], [])
        FS.emit('path-created', file)  # notify version control

        links = [file.uri]
        return _link_tree(links, notebook, path)
    else:
        return None
Example #23
0
    def testManipulate(self):
        '''Test moving and deleting pages in the memory store'''

        # Check we can get / store a page
        page = self.store.get_page(Path('Test:foo'))
        self.assertTrue(page.get_parsetree())
        self.assertTrue('Foo' in ''.join(page.dump('plain')))
        self.assertFalse(page.modified)
        wikitext = tests.WikiTestData.get('roundtrip')
        page.parse('wiki', wikitext)
        self.assertEqual(''.join(page.dump('wiki')), wikitext)
        self.assertTrue(page.modified)
        self.store.store_page(page)
        self.assertFalse(page.modified)
        self.assertEqual(''.join(page.dump('wiki')), wikitext)
        page = self.store.get_page(Path('Test:foo'))
        self.assertEqual(''.join(page.dump('wiki')), wikitext)

        page = self.store.get_page(Path('Test:foo'))
        text = page.dump('plain')
        newtext = ['Some new content\n']
        assert newtext != text
        self.assertEqual(page.dump('plain'), text)
        page.parse('plain', newtext)
        self.assertEqual(page.dump('plain'), newtext)
        self.assertTrue(page.modified)
        re = self.store.revert_page(page)
        self.assertFalse(re)  # no return value
        self.assertEqual(page.dump('plain'), text)  # object reverted
        self.assertFalse(page.modified)  # no longer modified
        page = self.store.get_page(page)  # new object
        self.assertEqual(page.dump('plain'), text)
        page.parse('plain', newtext)
        self.assertEqual(page.dump('plain'), newtext)
        self.store.store_page(page)
        page = self.store.get_page(page)  # new object
        self.assertEqual(page.dump('plain'), newtext)

        # check revert page triggers ui object
        page._ui_object = tests.MockObject()
        self.store.revert_page(page)
        self.assertEqual(page._ui_object.mock_calls[-1][0], 'set_parsetree')

        if hasattr(page, 'source') and isinstance(page.source, File):
            # check revert also works when the actual file changed
            # (and not trigger mtime check failure)
            from tests.fs import modify_file_mtime, FilterOverWriteWarning
            page = self.store.get_page(Path('Test:foo'))
            text = page.dump('plain')
            newtext = ['Foo bar baz\n']
            othertext = ['Dus ja\n']
            assert newtext != text
            assert othertext != text
            page.parse('plain', newtext)
            modify_file_mtime(page.source.path,
                              lambda p: open(p, 'w').writelines(othertext))
            with FilterOverWriteWarning():
                self.assertRaises(FileWriteError, self.store.store_page, page)
            self.store.revert_page(page)
            self.assertEqual(page.dump('plain'), othertext)
            page.parse('plain', newtext)
            self.store.store_page(page)
            page = self.store.get_page(page)  # new object
            self.assertEqual(page.dump('plain'), newtext)

        # check test setup OK
        for path in (Path('Test:BAR'), Path('NewPage')):
            page = self.store.get_page(path)
            self.assertFalse(page.haschildren)
            self.assertFalse(page.hascontent)

        # check errors
        self.assertRaises(LookupError, self.store.move_page, Path('NewPage'),
                          Path('Test:BAR'))
        self.assertRaises(PageExistsError, self.store.move_page,
                          Path('Test:foo'), Path('TaskList'))

        for oldpath, newpath in (
            (Path('Test:foo'), Path('Test:BAR')),
            (Path('TaskList'), Path('NewPage:Foo:Bar:Baz')),
        ):
            page = self.store.get_page(oldpath)
            text = page.dump('wiki')
            self.assertTrue(page.haschildren)

            #~ print ascii_page_tree(self.store)
            self.store.move_page(oldpath, newpath)
            #~ print ascii_page_tree(self.store)

            # newpath should exist and look like the old one
            page = self.store.get_page(newpath)
            self.assertTrue(page.haschildren)
            self.assertEqual(page.dump('wiki'), text)

            # oldpath should be deleted
            page = self.store.get_page(oldpath)
            self.assertFalse(page.haschildren)
            self.assertFalse(page.hascontent)

            # let's delete the newpath again
            page = self.store.get_page(newpath)
            self.assertTrue(self.store.delete_page(page))
            self.assertFalse(page.haschildren)
            self.assertFalse(page.hascontent)
            page = self.store.get_page(newpath)
            self.assertFalse(page.haschildren)
            self.assertFalse(page.hascontent)

            # delete again should silently fail
            self.assertFalse(self.store.delete_page(newpath))

        # check cleaning up works OK
        page = self.store.get_page(Path('NewPage'))
        self.assertFalse(page.haschildren)
        self.assertFalse(page.hascontent)

        # check case-sensitive move
        self.store.move_page(Path('utf8'), Path('UTF8'))
        page = self.store.get_page(Path('utf8'))
        # self.assertFalse(page.haschildren) - fails on case-insensitive FS
        self.assertFalse(
            Path('utf8') in list(self.store.get_pagelist(Path(':'))))
        self.assertTrue(
            Path('UTF8') in list(self.store.get_pagelist(Path(':'))))
        newpage = self.store.get_page(Path('UTF8'))
        self.assertTrue(newpage.haschildren)
        self.assertFalse(newpage == page)
        # TODO here we only move dir case insensitive - also test file

        # check hascontents
        page = self.store.get_page(Path('NewPage'))
        tree = ParseTree().fromstring('<zim-tree></zim-tree>')
        self.assertFalse(tree.hascontent)
        page.set_parsetree(tree)
        self.assertFalse(page.hascontent)
        self.store.store_page(page)
        page = self.store.get_page(Path('NewPage'))
        self.assertFalse(page.hascontent)

        # check trashing
        trashing = True
        try:
            page = self.store.get_page(Path('TrashMe'))
            self.assertTrue(page.haschildren)
            self.assertTrue(page.hascontent)
            self.store.trash_page(page)
            self.assertFalse(page.haschildren)
            self.assertFalse(page.hascontent)
            page = self.store.get_page(Path('TrashMe'))
            self.assertFalse(page.haschildren)
            self.assertFalse(page.hascontent)
        except TrashNotSupportedError:
            trashing = False
            print '(trashing not supported for this store)'
            self.assertTrue(page.haschildren)
            self.assertTrue(page.hascontent)
            page = self.store.get_page(Path('TrashMe'))
            self.assertTrue(page.haschildren)
            self.assertTrue(page.hascontent)

        page = self.store.get_page(Path('NonExistingPage'))
        if trashing:
            # fail silently for non-existing page
            self.assertFalse(self.store.trash_page(page))
        else:
            # check error consistent
            self.assertRaises(TrashNotSupportedError, self.store.trash_page,
                              page)