#!/usr/bin/env python
from __future__ import with_statement
import sys, os
sys.path = ([os.path.dirname(os.path.dirname(os.path.realpath(__file__)))]
+ sys.path)
__requires__='Bazki'
import pkg_resources
pkg_resources.require('Bazki')
import unittest, warnings
import re
import unicodedata
from bazbase import custom, db, flavors, wiki, testing, structure
from bazbase.conversion import invalidate_cache, to_python, render, render_propval
#custom.get_sqlalchemy_args = lambda: {'url': 'sqlite://'}
testing.set_up_for_tests()
if '-v' in sys.argv:
def debug(*s):
print >>sys.stderr,' '.join(s)
else:
def debug(*s):
pass
from redbeans.creole import tokenize
g_query_count = 0
from sqlalchemy import event
from sqlalchemy.engine import Engine
@event.listens_for(Engine, "after_cursor_execute")
def after_cursor_execute(conn, cursor, statement,
parameters, context, executemany):
global g_query_count
g_query_count += 1
class TestHelpers(unittest.TestCase):
def test_safesplit_tags(self):
self.assertEqual([([Text(u'Foo')], None),
([Text(u'Bar')], (u'else', None))],
wiki.safesplit_tags(tokenize('Foo< >Bar'),
('else',)))
self.assertEqual([([Text(u'FooBar')], None)],
wiki.safesplit_tags(tokenize('FooBar'), ('else',)))
self.assertEqual([([Start(MACRO, (u'if', None)),
Text(u'Foo'),
Entity(MACRO, (u'else', None)),
Text(u'Bar'),
End(MACRO, u'if')], None)],
wiki.safesplit_tags(
tokenize('<>Foo< >Bar< >'),
('else',)))
class TestBazbase(unittest.TestCase):
def setUp(self):
custom.APP_NAME = 'BazbaseTest'
invalidate_cache()
debug("=== Setup B ===")
db.begin_transaction()
try:
structure.clear_database()
disp = structure.create_prop(u'disposition', u'string')
disp.set_default('')
structure.create_prop(u'listed', u'boolean')
root = structure.create_root_element(u'Root')
root.set_prop(u'comment', 'cheese')
root.set_prop(u'disposition', 'sunny')
root.set_prop(u'listed', 'false')
structure.get_element(u'Root')
debug("Child...")
child = root.create_child(u'Child')
debug("Bees...")
child.set_prop(u'comment', 'bees')
page = root.create_child(u'Page')
page.set_prop(u'comment', '[[http://sevenmonkey.mit.edu/Japan/Early Netsuke]]')
page.set_prop(u'product', '[[Early Netsuke]] were pretty \emph{awesome}...')
page.set_prop(u'product2', '[[EarlyNetsuke]] were pretty \emph{awesome}...')
debug("Flushing...")
structure.flush_database_for_test()
except:
db.abort_transaction()
raise
def tearDown(self):
db.abort_transaction()
wiki.clear_eval_state()
def testBasics(self):
root = structure.get_element(u'Root')
self.assertEqual(render(root, u'disposition'),
u'sunny')
self.assertEqual(
render(structure.get_element_with({u'disposition': u'sunny'}),
u'comment'),
u'cheese')
self.assertEqual(render(root, u'listed'),
u'False')
self.assertFalse(to_python(root, u'listed'))
def testTeX(self):
root = structure.get_element(u'Root')
root.set_prop(u'disposition', "PB&J")
self.assertEqual(r'PB\&J', render(root, u'disposition', u'tex'))
root.set_prop(u'disposition', 'Examples & Such')
root.set_prop(u'comment',
'[[http://example.com|< >]]')
self.assertEqual(render(root, u'comment', u'tex'),
u'\\href{http://example.com}{Examples \\& Such}')
def testHTML(self):
self.assertEqual(render_propval(u'Page', u'comment', u'html'),
u'
http://sevenmonkey.mit.edu/Japan/Early Netsuke
')
self.assertEqual(render_propval(u'Page', u'product', u'html'),
u'Early Netsuke were pretty awesome \u2026
')
self.assertEqual(render_propval(u'Page', u'product2', u'html'),
u'EarlyNetsuke were pretty awesome \u2026
')
def testReference(self):
structure.create_prop(u'mother',u'reference')
root = structure.get_element(u'Root')
root.set_prop(u'mother', '')
child = structure.get_element(u'Child')
child.set_prop(u'mother', '[[%s]]' % root.ename.encode('utf-8'))
self.assertEqual(flavors.Reference(root, [], child),
to_python(child, u'mother'))
kids = structure.search_elements({u'mother':
structure.get_element(u'Root')})
self.assertEqual([child], kids)
self.assertEqual(None, to_python(root, u'mother'))
self.assertEqual('', render(root, u'mother'))
root.set_prop(u'comment', '< >')
self.assertEqual('sunny', render(root, u'comment'))
def testReferences(self):
structure.create_prop(u'fish', u'references')
page = structure.get_element(u'Page')
page.set_prop(u'name', 'Page')
root = structure.get_element(u'Root')
root.set_prop(u'fish', '[[Page]]')
self.assertEqual([flavors.Reference(page, [], root)],
to_python(root, u'fish'))
root.set_prop(u'comment',
'<>< >< >')
self.assertEqual(u'Page', render(root, u'comment'))
root.set_prop(u'fish', '[[Page]], [[Nonexistent]]')
wiki.init_eval_state(None, None, 'txt', None)
self.assertRaises(wiki.WikiException, wiki.baz_eval, 'Root.fish')
def testArgReferences(self):
structure.create_prop(u'fish', u'references')
page = structure.get_element(u'Page')
page.set_prop(u'name', 'Page: <<1/>>')
root = structure.get_element(u'Root')
root.set_prop(u'fish', '[[Page/Tree]]')
self.assertEqual([flavors.Reference(page, [u'Tree'], root)],
to_python(root, u'fish'))
root.set_prop(u'comment', '<>< >< >')
self.assertEqual(u'Page: Tree', render(root, u'comment'))
def testMultiArgReferences(self):
structure.create_prop(u'fish', u'references')
structure.create_prop(u'thing', u'string')
structure.create_prop(u'other', u'string')
page = structure.get_element(u'Page')
page.set_prop(u'name',
r'Page: \1, not \2 (\thing, \other, \disposition)')
page.set_prop(u'disposition', 'Dispo')
page.set_prop(u'thing', 'Thing')
child = structure.get_element(u'Child')
child.set_prop(u'fish', '[[Page/Tree/Grass]]')
child.set_prop(u'other', 'Other')
root = structure.get_element(u'Root')
third = root.create_child(u'Third')
third.set_prop(u'disposition', 'Royal')
third.set_prop(u'thing', 'Crown')
third.set_prop(u'other', 'Wish')
self.assertEqual([flavors.Reference(page, [u'Tree', u'Grass'], child)],
to_python(child, u'fish'))
child.set_prop(u'comment', '<>< >< >')
self.assertEqual(u'Page: Tree, not Grass (Thing, Other, Dispo)', render(child, u'comment'))
child.set_prop(u'comment', '<><>< >< >< >')
self.assertEqual(u'Page: Tree, not Grass (Thing, Other, Dispo)', render(child, u'comment'))
def testMetadata(self):
child = structure.get_element(u'Child')
self.assertEqual({u'comment': u'bees',
u'listed': u'false',
u'disposition': u''},
child.get_nice_value_map())
def testMetadataQueries(self):
keys = ['get_value_map']
child = structure.get_element(u'Child')
for k in keys:
was = g_query_count
getattr(child, k)()
self.assertEqual(1, g_query_count - was)
class TestTransactions(unittest.TestCase):
def setUp(self):
debug("=== Setup T ===")
db.begin_transaction()
try:
structure.clear_database()
disp = structure.create_prop(u'disposition', u'string')
disp.set_default('')
root = structure.create_root_element(u'Root')
root.set_prop(u'comment', 'cheese')
root.set_prop(u'disposition', 'sunny')
child = root.create_child(u'Child')
child.set_prop(u'comment', 'bees')
except:
db.abort_transaction()
raise
else:
db.commit_transaction()
def testBasics(self):
db.begin_transaction()
try:
root = structure.get_element(u'Root')
root.set_prop(u'comment', 'fleas')
self.assertEqual(render_propval(u'Root', u'comment'),
u'fleas')
finally:
db.abort_transaction()
db.begin_transaction()
try:
self.assertEqual(render_propval(u'Root', u'comment'),
u'cheese')
finally:
db.abort_transaction()
def testSearchability(self):
db.begin_transaction()
try:
self.assertEqual(
render(structure.get_element_with({u'disposition': u'sunny'}),
u'comment'),
u'cheese')
finally:
db.abort_transaction()
db.begin_transaction()
try:
root = structure.get_element(u'Root')
root.set_prop(u'comment', 'fleas')
self.assertEqual(
render(structure.get_element_with({u'disposition': u'sunny'}),
u'comment'),
u'fleas')
finally:
db.abort_transaction()
db.begin_transaction()
try:
self.assertEqual(
render(structure.get_element_with({u'disposition': u'sunny'}),
u'comment'),
u'cheese')
finally:
db.abort_transaction()
def testChildren(self):
structure.verify_tree_for_test()
with db.begin_transaction():
e = structure.get_element(u'Child').create_child(u'Fish')
e.set_prop(u'comment', '42')
structure.verify_tree_for_test()
db.begin_transaction()
try:
e = structure.get_element(u'Child').create_child(u'Dish')
e.set_prop(u'comment', '47')
self.assertEqual(e.get_parent(), structure.get_element(u'Child'))
finally:
db.abort_transaction()
structure.verify_tree_for_test()
with db.begin_transaction():
fish = structure.get_element(u'Fish')
e = fish.create_child(u'Sish')
e.set_prop(u'comment', '11')
f = fish.create_child(u'Cish')
f.set_prop(u'comment', '12')
g = e.create_child(u'Eish')
g.set_prop(u'comment', '13')
self.assertEqual(fish.get_parent(),
structure.get_element(u'Child'))
self.assertEqual(e.get_parent(), fish)
self.assertEqual(f.get_parent(), fish)
self.assertEqual(g.get_parent(), e)
structure.verify_tree_for_test()
with db.begin_transaction():
c= structure.get_element(u'Child')
d= structure.get_element(u'Fish')
e= structure.get_element(u'Sish')
f= structure.get_element(u'Cish')
g= structure.get_element(u'Eish')
f.set_parent(c)
self.assertEqual(d.get_parent(),c)
self.assertEqual(e.get_parent(),d)
self.assertEqual(f.get_parent(),c)
self.assertEqual(g.get_parent(),e)
structure.verify_tree_for_test()
with db.begin_transaction():
c= structure.get_element(u'Child')
d= structure.get_element(u'Fish')
e= structure.get_element(u'Sish')
f= structure.get_element(u'Cish')
g= structure.get_element(u'Eish')
e.set_parent(c)
f.set_parent(d)
self.assertEqual(d.get_parent(),c)
self.assertEqual(e.get_parent(),c)
self.assertEqual(f.get_parent(),d)
self.assertEqual(g.get_parent(),e)
structure.verify_tree_for_test()
with db.begin_transaction():
# Emulate exactly what bazki.edit does
e = structure.get_element(u'Wombat')
if e is None:
e = structure.get_element(u'Child').create_child(u'Wombat')
else:
self.fail("There shouldn't already be a Wombat.")
e.set_prop(u'comment', 'waah')
structure.verify_tree_for_test()
with db.begin_transaction():
e = structure.get_element(u'Dombat')
if e is None:
e = structure.get_element(u'Child').create_child(u'Dombat')
else:
self.fail("There shouldn't already be a Dombat.")
e.set_prop(u'comment', 'daah')
structure.verify_tree_for_test()
from redbeans.parser import Parser
from redbeans.formats import Format
from redbeans.tokens import *
class TestWiki(unittest.TestCase):
def test_parse_macro_args(self):
self.assertEqual(wiki.parse_macro_args(['4']),
{1:'4'})
self.assertEqual(wiki.parse_macro_args(['4','17']),
{1:'4',2:'17'})
self.assertEqual(wiki.parse_macro_args(['4', '"17"']),
{1:'4',2:'"17"'})
self.assertEqual(wiki.parse_macro_args(['4', 'foo="17"']),
{1:'4','foo':'"17"'})
self.assertEqual(wiki.parse_macro_args(['4', '(foo=="17")']),
{1:'4',2:'(foo=="17")'})
self.assertEqual(wiki.parse_macro_args(['4', '(foo!="17")']),
{1:'4',2:'(foo!="17")'})
self.assertEqual(wiki.parse_macro_args(['4', 'foo=="17"']),
{1:'4',2:'foo=="17"'})
self.assertEqual(wiki.parse_macro_args(['4', 'foo!="17"']),
{1:'4',2:'foo!="17"'})
self.assertEqual(wiki.parse_macro_args(
["recursive_get(leaf, 'stuff')"]),
{1: "recursive_get(leaf, 'stuff')"})
def test_baz_eval(self):
with db.begin_transaction():
wiki.init_eval_state(None, None, 'txt', None)
self.assertEqual(wiki.baz_eval("3+5"), 8)
self.assertEqual(wiki.baz_eval("'3+5'"), "3+5")
self.assertEqual(wiki.baz_eval(""), "")
self.assertRaises(wiki.WikiException, wiki.baz_eval,
"'3'.__class__")
class TestWikiWithDB(unittest.TestCase):
def setUp(self):
debug("=== Setup B ===")
db.begin_transaction()
try:
structure.clear_database()
disp = structure.create_prop(u'disposition', u'string')
disp.set_default('')
answ = structure.create_prop(u'answer', u'integer')
answ.set_default('42')
root = structure.create_root_element(u'Root')
root.set_prop(u'comment', 'cheese')
root.set_prop(u'disposition', 'sunny')
root.set_prop(u'answer', '17')
structure.get_element(u'Root')
debug("Child...")
child = root.create_child(u'Child')
debug("Bees...")
child.set_prop(u'comment', 'bees')
page = root.create_child(u'Page')
page.set_prop(u'comment', '[[http://sevenmonkey.mit.edu/Japan/Early Netsuke]]')
page.set_prop(u'product', '[[Early Netsuke]]')
debug("Flushing...")
structure.flush_database_for_test()
wiki.clear_eval_state()
wiki.init_eval_state(root, None, 'txt', 'text')
except:
db.abort_transaction()
raise
def tearDown(self):
db.abort_transaction()
wiki.clear_eval_state()
def test_baz_eval(self):
parser = Parser(Format, wiki.macro_func)
self.assertEquals(wiki.baz_eval(u"Root.disposition"),
"sunny")
self.assertEquals(wiki.baz_eval(u"Root.answer"),
17)
self.assertEquals(wiki.baz_eval(u"Root.answer+Root.answer"),
34)
self.assertEquals(wiki.baz_eval(u"'test'"),
"test")
def test_full_eval(self):
parser = Parser(Format, wiki.macro_func)
self.assertEquals(list(wiki.full_eval(u"Root.disposition")),
[Text(u"sunny")])
self.assertEquals(list(wiki.full_eval(u"Root.answer")),
[Text(u"17")])
self.assertEquals(list(wiki.full_eval(u"Root.answer+Root.answer")),
[Text(u"17"), Text(u"17")])
self.assertEquals(list(wiki.full_eval(u"Root.comment")),
[Text(u"cheese")])
self.assertEquals(list(wiki.full_eval(u"'test'")),
[Text(u"test")])
class TestMacros(unittest.TestCase):
def setUp(self):
debug("=== Setup B ===")
db.begin_transaction()
try:
structure.clear_database()
disp = structure.create_prop(u'disposition', u'string')
disp.set_default('')
answ = structure.create_prop(u'answer', u'integer')
answ.set_default('42')
root = structure.create_root_element(u'Root')
root.set_prop(u'comment', 'cheese')
root.set_prop(u'disposition', 'sunny')
root.set_prop(u'answer', '17')
structure.flush_database_for_test()
except:
db.abort_transaction()
raise
def tearDown(self):
db.abort_transaction()
def test_if(self):
root = structure.get_element(u'Root')
root.set_prop(u'comment', '<>42< >')
self.assertEqual('42', render(root, u'comment'))
root.set_prop(u'comment', '<>37< >')
self.assertEqual('37', render(root, u'comment'))
root.set_prop(u'comment', '<>2<>8< >4< >')
self.assertEqual('284', render(root, u'comment'))
root.set_prop(u'comment', '<>0<>9< >6< >< >4< >')
self.assertEqual('06', render(root, u'comment'))
root.set_prop(u'comment', '''<>
<>
9
< >
+6
< >
< >
4
< >''')
self.assertEqual('+6', render(root, u'comment').strip())
def test_link(self):
root = structure.get_element(u'Root')
root.set_prop(u'comment', '< >Packet as PDF<>')
root.set_prop(u'username', 'fish')
self.assertEqual(
'Packet as PDF
',
render(root, u'comment', u'html'))
def test_local_link(self):
root = structure.get_element(u'Root')
root.set_prop(u'comment', '< >Root<>')
self.assertEqual(
'Root
',
render(root, u'comment', u'html'))
def test_foreach(self):
root = structure.get_element(u'Root')
t = root.create_child(u'Tree')
a = t.create_child(u'Aspen')
a.set_prop(u'disposition', 'arid')
a.set_prop(u'answer', '42')
b = t.create_child(u'Birch')
b.set_prop(u'disposition', 'balmy')
b.set_prop(u'answer', '7')
c = t.create_child(u'Cedar')
c.set_prop(u'disposition', 'cloudy')
c.set_prop(u'answer', '17')
root.set_prop(u'comment', '''<>
* < >< >''')
self.assertEqual(''' * arid
* balmy
* cloudy''', render(root, u'comment'))
root.set_prop(u'comment', '''<>
* < >< >''')
self.assertEqual(''' * balmy
* cloudy
* arid''', render(root, u'comment'))
root.set_prop(u'comment', '''<>
* < >< >''')
self.assertEqual(''' * arid
* balmy''', render(root, u'comment'))
root.set_prop(u'comment', '''<>
* < >< >''')
self.assertEqual(''' * arid
* balmy
* cloudy''', render(root, u'comment'))
root.set_prop(u'comment', '''<>
* < >< >''')
self.assertEqual(''' * None.''', render(root, u'comment'))
trees = structure.create_prop(u'trees', u'labeledrefs')
trees.set_default('')
root.set_prop(u'trees', '[[Birch|your favorite]], [[Aspen|nice too]]')
root.set_prop(u'comment', '''<>
* **< >**: < >< >''')
self.assertEqual(''' * *Birch*: your favorite
* *Aspen*: nice too''', render(root, u'comment'))
root.set_prop(u'comment', '''<>
* < >< >
<>
* < >< >''')
root.set_prop(u'dream', '''< >''')
self.assertEqual(''' * arid
* balmy
* cloudy
* Aspen
* Birch
* Cedar''', render(root, u'comment'))
self.assertEqual('''
''', render(root, u'comment', 'html'))
self.assertEqual('''
''', render(root, u'dream', 'html'))
root.set_prop(u'comment', '''== Trees ==
<>
* < >< >''')
self.assertEqual('''Trees
''', render(root, u'comment', 'html'))
self.assertEqual('''Trees
''', render(root, u'dream', 'html'))
def test_recursive_get(self):
root = structure.get_element(u'Root')
stuff = structure.create_prop(u'stuff', u'references')
stuff.set_default('')
root.set_prop(u'stuff', '[[Aspen]]')
t = root.create_child(u'Tree')
a = t.create_child(u'Aspen')
a.set_prop(u'stuff', '[[Cedar]]')
b = t.create_child(u'Birch')
c = t.create_child(u'Cedar')
root.set_prop(u'comment', '''<>
* < >< >''')
self.assertEqual(''' * Aspen
* Cedar''', render(root, u'comment'))
def test_foreachpropin(self):
root = structure.get_element(u'Root')
structure.create_prop(u'fish', u'raw')
structure.create_prop(u'dish', u'raw')
structure.create_prop(u'wish', u'raw')
root.set_prop(u'fish', 'carp')
root.set_prop(u'dish', 'bowl')
root.set_prop(u'wish', 'star')
root.set_prop(u'comment', '''<>
* **< >**: < >< >''')
self.assertEqual(''' * *fish*: carp
* *dish*: bowl
* *wish*: star''', render(root, u'comment'))
def test_eval(self):
root = structure.get_element(u'Root')
root.set_prop(u'comment', '''< >''')
self.assertEqual('''True''', render(root, u'comment'))
def test_accents(self):
root = structure.get_element(u'Root')
root.set_prop(u'comment', r'''Pok\'emon ma\~nana look\`ed at Zo\"e in T\=oky\=o.''')
self.assertEqual(u'''Pok\u00e9mon ma\u00f1ana look\u00e8d at Zo\u00eb in T\u014dky\u014d.''', unicodedata.normalize('NFC', render(root, u'comment')))
def test_implicit(self):
root = structure.get_element(u'Root')
root.set_prop(u'substitution', r'''\disposition: \answer''')
self.assertEqual('''sunny: 17''', render(root, u'substitution'))
page = root.create_child(u'Page')
page.set_prop(u'comment', r'''I said, "\Root".''')
page.set_prop(u'disposition', 'sad')
self.assertEqual(u'I said, \u201Csunny: 17\u201D.',
render(page, u'comment'))
structure.create_prop(u'end', u'string')
page.set_prop(u'end', '!')
root.set_prop(u'substitution', r'''\disposition: \answer\end''')
self.assertEqual(u'I said, \u201Csunny: 17!\u201D.',
render(page, u'comment'))
class TestCaching(unittest.TestCase):
def setUp(self):
invalidate_cache()
debug("=== Setup C ===")
TestCaching.index = 0
# Put nondeterministic macros that do and don't add DISCORDIA
def arbitrary(arglist):
TestCaching.index += 1
yield Text(unicode(TestCaching.index))
wiki.macros.arbitrary = arbitrary
def discord(arglist):
wiki.eval_state.dependencies.makeUncacheable()
TestCaching.index += 1
yield Text(unicode(TestCaching.index))
wiki.macros.discord = discord
with db.begin_transaction():
structure.clear_database()
structure.create_prop(u'disposition', u'string')
root = structure.create_root_element(u'Root')
root.set_prop(u'comment', '< >')
root.set_prop(u'disposition', '< >')
root.set_prop(u'mood', '< >')
root.set_prop(u'attitude', '< >')
structure.flush_database_for_test()
def test_txt(self):
with db.begin_transaction():
e = structure.get_element(u'Root')
# This is uncachable.
self.assertNotEqual(render(e, u'comment'), render(e, u'comment'))
# Caching should ensure that these are the same.
disposition = render(e, u'disposition')
self.assertEqual(disposition, render(e, u'disposition'))
self.assertEqual(render(e, u'mood'), render(e, u'mood'))
# These should be diffferent, because references skip caching.
self.assertNotEqual(render(e, u'disposition'), render(e, u'mood'))
# These should be the same because of explicit caching.
self.assertEqual(render(e, u'disposition'), render(e, u'attitude'))
# Should be consistent with the same thing in a separate transaction.
with db.begin_transaction():
e = structure.get_element(u'Root')
self.assertEqual(disposition, render(e, u'disposition'))
class TestRenderer(unittest.TestCase):
def setUp(self):
with db.begin_transaction():
structure.clear_database()
root = structure.create_root_element(u'Root')
root.set_prop(u'comment', 'wombat')
root.set_prop(u'name', 'Root')
def test_render(self):
from bazbase import renderer
renderer.start_render(u'Root', [u'comment'], u'html')
self.assertEqual({u'comment': u'wombat
'},
renderer.wait_for_render(u'Root', [u'comment'],
u'html'))
def test_two(self):
from bazbase import renderer
renderer.start_render(u'Root', [u'comment', u'name'], u'html')
m = renderer.wait_for_render(u'Root', [u'comment', u'name'], u'html')
self.assertTrue(u'comment' in m or u'name' in m, repr(m))
if __name__ == "__main__":
warnings.simplefilter("error")
warnings.filterwarnings('ignore', "cgi.parse_qsl is deprecated")
unittest.main()