1 # -*- coding: iso-8859-1 -*-
3 MoinMoin - MoinMoin.wikiutil Tests
5 @copyright: 2003-2004 by Juergen Hermann <jh@web.de>,
7 @license: GNU GPL, see COPYING for details.
12 from MoinMoin import config, wikiutil
14 from werkzeug.utils import MultiDict
17 class TestQueryStringSupport:
20 ('key1=value1', {'key1': 'value1'}, {'key1': u'value1'}),
21 ('key1=value1&key2=value2', {'key1': 'value1', 'key2': 'value2'}, {'key1': u'value1', 'key2': u'value2'}),
22 ('rc_de=Aktuelle%C3%84nderungen', {'rc_de': 'Aktuelle\xc3\x84nderungen'}, {'rc_de': u'Aktuelle\xc4nderungen'}),
24 def testParseQueryString(self):
25 for qstr, expected_str, expected_unicode in self.tests:
26 assert wikiutil.parseQueryString(qstr) == MultiDict(expected_unicode)
27 assert wikiutil.parseQueryString(unicode(qstr)) == MultiDict(expected_unicode)
29 def testMakeQueryString(self):
30 for qstr, in_str, in_unicode in self.tests:
31 assert wikiutil.parseQueryString(wikiutil.makeQueryString(in_unicode)) == MultiDict(in_unicode)
32 assert wikiutil.parseQueryString(wikiutil.makeQueryString(in_str)) == MultiDict(in_unicode)
36 def testTickets(self):
37 from MoinMoin.Page import Page
38 # page name with double quotes
39 self.request.page = Page(self.request, u'bla"bla')
40 ticket1 = wikiutil.createTicket(self.request)
41 assert wikiutil.checkTicket(self.request, ticket1)
42 # page name with non-ASCII chars
43 self.request.page = Page(self.request, u'\xc4rger')
44 ticket2 = wikiutil.createTicket(self.request)
45 assert wikiutil.checkTicket(self.request, ticket2)
46 # same page with another action
47 self.request.page = Page(self.request, u'\xc4rger')
48 self.request.action = 'another'
49 ticket3 = wikiutil.createTicket(self.request)
50 assert wikiutil.checkTicket(self.request, ticket3)
52 assert ticket1 != ticket2
53 assert ticket2 != ticket3
57 def testCleanInput(self):
58 tests = [(u"", u""), # empty
59 (u"aaa\r\n\tbbb", u"aaa bbb"), # ws chars -> blanks
60 (u"aaa\x00\x01bbb", u"aaabbb"), # strip weird chars
61 (u"a"*500, u""), # too long
63 for instr, outstr in tests:
64 assert wikiutil.clean_input(instr) == outstr
68 def testSplitWiki(self):
69 tests = [('SomePage', ('Self', 'SomePage')),
70 ('OtherWiki:OtherPage', ('OtherWiki', 'OtherPage')),
71 (':OtherPage', ('', 'OtherPage')),
72 # broken ('/OtherPage', ('Self', '/OtherPage')),
73 # wrong interpretation ('MainPage/OtherPage', ('Self', 'MainPage/OtherPage')),
75 for markup, (wikiname, pagename) in tests:
76 assert wikiutil.split_wiki(markup) == (wikiname, pagename)
78 def testJoinWiki(self):
79 tests = [(('http://example.org/', u'SomePage'), 'http://example.org/SomePage'),
80 (('http://example.org/?page=$PAGE&action=show', u'SomePage'), 'http://example.org/?page=SomePage&action=show'),
81 (('http://example.org/', u'Aktuelle\xc4nderungen'), 'http://example.org/Aktuelle%C3%84nderungen'),
82 (('http://example.org/$PAGE/show', u'Aktuelle\xc4nderungen'), 'http://example.org/Aktuelle%C3%84nderungen/show'),
84 for (baseurl, pagename), url in tests:
85 assert wikiutil.join_wiki(baseurl, pagename) == url
88 class TestSystemPagesGroup:
89 def testSystemPagesGroupNotEmpty(self):
90 assert self.request.dicts.members('SystemPagesGroup')
94 # First level, on SystemPagesGroup
95 'SystemPagesInEnglishGroup',
96 # Second level, on one of the pages above
101 'NoSuchPageYetAndWillNeverBe',
104 def testSystemPage(self):
105 """wikiutil: good system page names accepted, bad rejected"""
106 for name in self.systemPages:
107 assert wikiutil.isSystemPage(self.request, name)
108 for name in self.notSystemPages:
109 assert not wikiutil.isSystemPage(self.request, name)
112 class TestTemplatePage:
125 def testTemplatePage(self):
126 """wikiutil: good template names accepted, bad rejected"""
127 for name in self.good:
128 assert wikiutil.isTemplatePage(self.request, name)
129 for name in self.bad:
130 assert not wikiutil.isTemplatePage(self.request, name)
133 class TestParmeterParser:
135 def testParameterParser(self):
141 ('%s%i%f%b', '"test",42,23.0,True', 4, {0: 'test', 1: 42, 2: 23.0, 3: True}),
144 ('%s%(x)i%(y)i', '"test"', 1, {0: 'test', 'x': None, 'y': None}),
145 ('%s%(x)i%(y)i', '"test",1', 1, {0: 'test', 'x': 1, 'y': None}),
146 ('%s%(x)i%(y)i', '"test",1,2', 1, {0: 'test', 'x': 1, 'y': 2}),
147 ('%s%(x)i%(y)i', '"test",x=1', 1, {0: 'test', 'x': 1, 'y': None}),
148 ('%s%(x)i%(y)i', '"test",x=1,y=2', 1, {0: 'test', 'x': 1, 'y': 2}),
149 ('%s%(x)i%(y)i', '"test",y=2', 1, {0: 'test', 'x': None, 'y': 2}),
151 # test mixed acceptance
152 ("%ifs", '100', 1, {0: 100}),
153 ("%ifs", '100.0', 1, {0: 100.0}),
154 ("%ifs", '"100"', 1, {0: "100"}),
157 ("%(t)b%(f)b", '', 0, {'t': None, 'f': None}),
158 ("%(t)b%(f)b", 't=1', 0, {'t': True, 'f': None}),
159 ("%(t)b%(f)b", 'f=False', 0, {'t': None, 'f': False}),
160 ("%(t)b%(f)b", 't=True, f=0', 0, {'t': True, 'f': False}),
163 ("%(width)i%(height)i", '', 0, {'width': None, 'height': None}),
164 ("%(width)i%(height)i", 'width=100', 0, {'width': 100, 'height': None}),
165 ("%(width)i%(height)i", 'height=200', 0, {'width': None, 'height': 200}),
166 ("%(width)i%(height)i", 'width=100, height=200', 0, {'width': 100, 'height': 200}),
169 ("%(width)f%(height)f", '', 0, {'width': None, 'height': None}),
170 ("%(width)f%(height)f", 'width=100.0', 0, {'width': 100.0, 'height': None}),
171 ("%(width)f%(height)f", 'height=2.0E2', 0, {'width': None, 'height': 200.0}),
172 ("%(width)f%(height)f", 'width=1000.0E-1, height=200.0', 0, {'width': 100.0, 'height': 200.0}),
175 ("%(width)s%(height)s", '', 0, {'width': None, 'height': None}),
176 ("%(width)s%(height)s", 'width="really wide"', 0, {'width': 'really wide', 'height': None}),
177 ("%(width)s%(height)s", 'height="not too high"', 0, {'width': None, 'height': 'not too high'}),
178 ("%(width)s%(height)s", 'width="really wide", height="not too high"', 0, {'width': 'really wide', 'height': 'not too high'}),
179 # conversion from given type to expected type
180 ("%(width)s%(height)s", 'width=100', 0, {'width': '100', 'height': None}),
181 ("%(width)s%(height)s", 'width=100, height=200', 0, {'width': '100', 'height': '200'}),
184 ("%i%sf%s%ifs%(a)s|%(b)s", ' 4,"DI\'NG", b=retry, a="DING"', 2, {0: 4, 1: "DI'NG", 'a': 'DING', 'b': 'retry'}),
187 for format, args, expected_fixed_count, expected_dict in tests:
188 argParser = wikiutil.ParameterParser(format)
189 fixed_count, arg_dict = argParser.parse_parameters(args)
190 assert (fixed_count, arg_dict) == (expected_fixed_count, expected_dict)
192 def testTooMuchWantedArguments(self):
193 args = 'width=100, height=200, alt=Example'
194 argParser = wikiutil.ParameterParser("%(width)s%(height)s")
195 py.test.raises(ValueError, argParser.parse_parameters, args)
197 def testMalformedArguments(self):
199 argParser = wikiutil.ParameterParser("%(width)s%(height)s")
200 py.test.raises(ValueError, argParser.parse_parameters, args)
202 def testWrongTypeFixedPosArgument(self):
204 argParser = wikiutil.ParameterParser("%b")
205 py.test.raises(ValueError, argParser.parse_parameters, args)
207 def testWrongTypeNamedArgument(self):
209 argParser = wikiutil.ParameterParser("%(flag)b")
210 py.test.raises(ValueError, argParser.parse_parameters, args)
213 class TestParamParsing:
214 def testMacroArgs(self):
215 abcd = [u'a', u'b', u'c', u'd']
216 abcd_dict = {u'a': u'1', u'b': u'2', u'c': u'3', u'd': u'4'}
218 # regular and quoting tests
219 (u'd = 4,c=3,b=2,a= 1 ', ([], abcd_dict, [])),
220 (u'a,b,c,d', (abcd, {}, [])),
221 (u' a , b , c , d ', (abcd, {}, [])),
222 (u' a ', ([u'a'], {}, [])),
223 (u'" a "', ([u' a '], {}, [])),
224 (u'a,b,c,d, "a,b,c,d"', (abcd+[u'a,b,c,d'], {}, [])),
225 (u'quote " :), b', ([u'quote " :)', u'b'], {}, [])),
226 (u'"quote "" :)", b', ([u'quote " :)', u'b'], {}, [])),
227 (u'=7', ([], {u'': u'7'}, [])),
228 (u',,', ([None, None, None], {}, [])),
229 (u',"",', ([None, u'', None], {}, [])),
230 (u',"", ""', ([None, u'', u''], {}, [])),
231 (u' "" ,"", ""', ([u'', u'', u''], {}, [])),
232 # some name=value test
233 (u'd = 4,c=3,b=2,a= 1 ', ([], abcd_dict, [])),
234 (u'd=d,e="a,b,c,d"', ([], {u'd': u'd',
235 u'e': u'a,b,c,d'}, [])),
236 (u'd = d,e = "a,b,c,d"', ([], {u'd': u'd',
237 u'e': u'a,b,c,d'}, [])),
238 (u'd = d, e = "a,b,c,d"', ([], {u'd': u'd',
239 u'e': u'a,b,c,d'}, [])),
240 (u'd = , e = "a,b,c,d"', ([], {u'd': None,
241 u'e': u'a,b,c,d'}, [])),
242 (u'd = "", e = "a,b,c,d"', ([], {u'd': u'',
243 u'e': u'a,b,c,d'}, [])),
244 (u'd = "", e = ', ([], {u'd': u'', u'e': None},
246 (u'd=""', ([], {u'd': u''}, [])),
247 (u'd = "", e = ""', ([], {u'd': u'', u'e': u''},
249 # no, None as key isn't accepted
250 (u' = "", e = ""', ([], {u'': u'', u'e': u''},
252 # can quote both name and value:
253 (u'd = d," e "= "a,b,c,d"', ([], {u'd': u'd',
254 u' e ': u'a,b,c,d'}, [])),
256 (u'1,2,a=b,3,4', ([u'1', u'2'], {u'a': u'b'},
259 (u'd = """d"', ([], {u'd': u'"d'}, [])),
260 (u'd = """d"""', ([], {u'd': u'"d"'}, [])),
261 (u'd = "d"" ", e=7', ([], {u'd': u'd" ', u'e': u'7'},
263 (u'd = "d""", e=8', ([], {u'd': u'd"', u'e': u'8'},
266 for args, expected in tests:
267 result = wikiutil.parse_quoted_separated(args)
268 assert expected == result
269 for val in result[0]:
270 assert val is None or isinstance(val, unicode)
271 for val in result[1].keys():
272 assert val is None or isinstance(val, unicode)
273 for val in result[1].values():
274 assert val is None or isinstance(val, unicode)
275 for val in result[2]:
276 assert val is None or isinstance(val, unicode)
278 def testLimited(self):
280 # regular and quoting tests
281 (u'd = 4,c=3,b=2,a= 1 ', ([], {u'd': u'4',
282 u'c': u'3,b=2,a= 1'}, [])),
283 (u'a,b,c,d', ([u'a', u'b,c,d'], {}, [])),
284 (u'a=b,b,c,d', ([], {u'a': u'b'}, [u'b,c,d'])),
286 for args, expected in tests:
287 result = wikiutil.parse_quoted_separated(args, seplimit=1)
288 assert expected == result
289 for val in result[0]:
290 assert val is None or isinstance(val, unicode)
291 for val in result[1].keys():
292 assert val is None or isinstance(val, unicode)
293 for val in result[1].values():
294 assert val is None or isinstance(val, unicode)
295 for val in result[2]:
296 assert val is None or isinstance(val, unicode)
298 def testDoubleNameValueSeparator(self):
300 # regular and quoting tests
301 (u'd==4,=3 ', ([], {u'd': u'=4', u'': u'3'}, [])),
302 (u'===a,b,c,d', ([], {u'': u'==a'}, [u'b', u'c', u'd'])),
303 (u'a,b,===,c,d', ([u'a', u'b'], {u'': u'=='}, [u'c', u'd'])),
307 r = wikiutil.parse_quoted_separated(a)
310 for args, expected in tests:
311 yield _check, args, expected
313 def testNoNameValue(self):
314 abcd = [u'a', u'b', u'c', u'd']
316 # regular and quoting tests
317 (u'd = 4,c=3,b=2,a= 1 ', [u'd = 4', u'c=3',
320 (u' a , b , c , d ', abcd),
322 (u'" a "', [u' a ']),
323 (u'a,b,c,d, "a,b,c,d"', abcd + [u'a,b,c,d']),
324 (u'quote " :), b', [u'quote " :)', u'b']),
325 (u'"quote "" :)", b', [u'quote " :)', u'b']),
326 (u'"unended quote', [u'"unended quote']),
328 (u'd=d,e="a,b,c,d"', [u'd=d', u'e="a', u'b',
331 for args, expected in tests:
332 result = wikiutil.parse_quoted_separated(args, name_value=False)
333 assert expected == result
335 assert val is None or isinstance(val, unicode)
337 def testUnitArgument(self):
338 result = wikiutil.UnitArgument('7mm', float, ['%', 'mm'])
339 assert result.get_default() == (7.0, 'mm')
340 assert result.parse_argument('8%') == (8.0, '%')
341 py.test.raises(ValueError, result.parse_argument, u'7m')
342 py.test.raises(ValueError, result.parse_argument, u'7')
343 py.test.raises(ValueError, result.parse_argument, u'mm')
345 def testExtendedParser(self):
347 (u'"a", "b", "c"', u',', None, [u'a', u'b', u'c']),
348 (u'a:b, b:c, c:d', u',', u':', [(u'a', u'b'), (u'b', u'c'), (u'c', u'd')]),
349 (u'a:b, b:c, c:d', u',', None, [u'a:b', u'b:c', u'c:d']),
350 (u'a=b, b=c, c=d', u',', None, [u'a=b', u'b=c', u'c=d']),
351 (u'a=b, b=c, c=d', u',', u'=', [(u'a', u'b'), (u'b', u'c'), (u'c', u'd')]),
352 (u'"a"; "b"; "c"', u';', None, [u'a', u'b', u'c']),
353 (u'a:b; b:c; c:d', u';', u':', [(u'a', u'b'), (u'b', u'c'), (u'c', u'd')]),
354 (u'a:b; b:c; c:d', u';', None, [u'a:b', u'b:c', u'c:d']),
355 (u'a=b; b=c; c=d', u';', None, [u'a=b', u'b=c', u'c=d']),
356 (u'a=b; b=c; c=d', u';', u'=', [(u'a', u'b'), (u'b', u'c'), (u'c', u'd')]),
357 (u'"a" "b" "c"', None, None, [u'a', u'b', u'c']),
358 (u'" a " "b" "c"', None, None, [u' a ', u'b', u'c']),
359 (u'"a " "b" "c"', None, None, [u'a ', u'b', u'c']),
360 (u'" a" "b" "c"', None, None, [u' a', u'b', u'c']),
361 (u'" a" "b" "c"', None, u':', [u' a', u'b', u'c']),
362 (u'"a:a" "b:b" "c:b"', None, u':', [u'a:a', u'b:b', u'c:b']),
363 (u' a:a ', None, u':', [None, None, None, (u'a', u'a'), None, None]),
364 (u'a a: a', None, u':', [u'a', (u'a', None), u'a']),
365 (u'a a:"b c d" a', None, u':', [u'a', (u'a', u'b c d'), u'a']),
366 (u'a a:"b "" d" a', None, u':', [u'a', (u'a', u'b " d'), u'a']),
367 (u'title:Help* dog cat', None, u':', [(u'title', u'Help*'), u'dog', u'cat']),
368 (u'title:Help* "dog cat"', None, u':', [(u'title', u'Help*'), u'dog cat']),
369 (u'a:b:c d:e:f', None, u':', [(u'a', u'b:c'), (u'd', 'e:f')]),
370 (u'a:b:c:d', None, u':', [(u'a', u'b:c:d')]),
373 def _check(args, sep, kwsep, expected):
374 res = wikiutil.parse_quoted_separated_ext(args, sep, kwsep)
375 assert res == expected
378 yield [_check] + list(test)
380 def testExtendedParserBracketing(self):
382 (u'"a", "b", "c"', u',', None, [u'a', u'b', u'c']),
383 (u'("a", "b", "c")', u',', None, [[u'(', u'a', u'b', u'c']]),
384 (u'("a"("b", "c"))', u',', None, [[u'(', u'a', [u'(', u'b', u'c']]]),
385 (u'("a"("b)))", "c"))', u',', None, [[u'(', u'a', [u'(', u'b)))', u'c']]]),
386 (u'("a"("b>>> ( ab )>", "c"))', u',', None, [[u'(', u'a', [u'(', u'b>>> ( ab )>', u'c']]]),
387 (u'("a" ("b" "c"))', None, None, [[u'(', u'a', [u'(', u'b', u'c']]]),
388 (u'("a"("b", "c") ) ', u',', None, [[u'(', u'a', [u'(', u'b', u'c']]]),
389 (u'("a", <"b", ("c")>)', u',', None, [[u'(', u'a', [u'<', u'b', [u'(', u'c']]]]),
390 (u',,,(a, b, c)', u',', None, [None, None, None, [u'(', u'a', u'b', u'c']]),
393 def _check(args, sep, kwsep, expected):
394 res = wikiutil.parse_quoted_separated_ext(args, sep, kwsep, brackets=(u'<>', u'()'))
395 assert res == expected
398 yield [_check] + list(test)
400 def testExtendedParserQuoting(self):
402 (u'"a b" -a b-', u'"', [u'a b', u'-a', u'b-']),
403 (u'"a b" -a b-', u"-", [u'"a', u'b"', u'a b']),
404 (u'"a b" -a b-', u'"-', [u'a b', u'a b']),
405 (u'"a- b" -a b-', u'"-', [u'a- b', u'a b']),
406 (u'"a- b" -a" b-', u'"-', [u'a- b', u'a" b']),
409 def _check(args, quotes, expected):
410 res = wikiutil.parse_quoted_separated_ext(args, quotes=quotes)
411 assert res == expected
414 yield [_check] + list(test)
416 def testExtendedParserMultikey(self):
418 (u'"a", "b", "c"', u',', None, [u'a', u'b', u'c']),
419 (u'a:b, b:c, c:d', u',', u':', [(u'a', u'b'), (u'b', u'c'), (u'c', u'd')]),
420 (u'a:b, b:c, c:d', u',', None, [u'a:b', u'b:c', u'c:d']),
421 (u'a=b, b=c, c=d', u',', None, [u'a=b', u'b=c', u'c=d']),
422 (u'a=b, b=c, c=d', u',', u'=', [(u'a', u'b'), (u'b', u'c'), (u'c', u'd')]),
423 (u'"a"; "b"; "c"', u';', None, [u'a', u'b', u'c']),
424 (u'a:b; b:c; c:d', u';', u':', [(u'a', u'b'), (u'b', u'c'), (u'c', u'd')]),
425 (u'a:b; b:c; c:d', u';', None, [u'a:b', u'b:c', u'c:d']),
426 (u'a=b; b=c; c=d', u';', None, [u'a=b', u'b=c', u'c=d']),
427 (u'a=b; b=c; c=d', u';', u'=', [(u'a', u'b'), (u'b', u'c'), (u'c', u'd')]),
428 (u'"a" "b" "c"', None, None, [u'a', u'b', u'c']),
429 (u'" a " "b" "c"', None, None, [u' a ', u'b', u'c']),
430 (u'"a " "b" "c"', None, None, [u'a ', u'b', u'c']),
431 (u'" a" "b" "c"', None, None, [u' a', u'b', u'c']),
432 (u'" a" "b" "c"', None, u':', [u' a', u'b', u'c']),
433 (u'"a:a" "b:b" "c:b"', None, u':', [u'a:a', u'b:b', u'c:b']),
434 (u' a:a ', None, u':', [None, None, None, (u'a', u'a'), None, None]),
435 (u'a a: a', None, u':', [u'a', (u'a', None), u'a']),
436 (u'a a:"b c d" a', None, u':', [u'a', (u'a', u'b c d'), u'a']),
437 (u'a a:"b "" d" a', None, u':', [u'a', (u'a', u'b " d'), u'a']),
438 (u'title:Help* dog cat', None, u':', [(u'title', u'Help*'), u'dog', u'cat']),
439 (u'title:Help* "dog cat"', None, u':', [(u'title', u'Help*'), u'dog cat']),
440 (u'a:b:c d:e:f', None, u':', [(u'a', u'b', u'c'), (u'd', 'e', u'f')]),
441 (u'a:b:c:d', None, u':', [(u'a', u'b', u'c', u'd')]),
442 (u'a:"b:c":d', None, u':', [(u'a', u'b:c', u'd')]),
445 def _check(args, sep, kwsep, expected):
446 res = wikiutil.parse_quoted_separated_ext(args, sep, kwsep, multikey=True)
447 assert res == expected
450 yield [_check] + list(test)
452 def testExtendedParserPrefix(self):
453 P = wikiutil.ParserPrefix('+')
454 M = wikiutil.ParserPrefix('-')
456 (u'"a", "b", "c"', u',', None, [u'a', u'b', u'c']),
457 (u'a:b, b:c, c:d', u',', u':', [(u'a', u'b'), (u'b', u'c'), (u'c', u'd')]),
458 (u'a:b, b:c, c:d', u',', None, [u'a:b', u'b:c', u'c:d']),
459 (u'a=b, b=c, c=d', u',', None, [u'a=b', u'b=c', u'c=d']),
460 (u'a=b, b=c, c=d', u',', u'=', [(u'a', u'b'), (u'b', u'c'), (u'c', u'd')]),
461 (u'"a"; "b"; "c"', u';', None, [u'a', u'b', u'c']),
462 (u'a:b; b:c; c:d', u';', u':', [(u'a', u'b'), (u'b', u'c'), (u'c', u'd')]),
463 (u'a:b; b:c; c:d', u';', None, [u'a:b', u'b:c', u'c:d']),
464 (u'a=b; b=c; c=d', u';', None, [u'a=b', u'b=c', u'c=d']),
465 (u'a=b; b=c; c=d', u';', u'=', [(u'a', u'b'), (u'b', u'c'), (u'c', u'd')]),
466 (u'"a" "b" "c"', None, None, [u'a', u'b', u'c']),
467 (u'" a " "b" "c"', None, None, [u' a ', u'b', u'c']),
468 (u'"a " "b" "c"', None, None, [u'a ', u'b', u'c']),
469 (u'" a" "b" "c"', None, None, [u' a', u'b', u'c']),
470 (u'" a" "b" "c"', None, u':', [u' a', u'b', u'c']),
471 (u'"a:a" "b:b" "c:b"', None, u':', [u'a:a', u'b:b', u'c:b']),
472 (u' a:a ', None, u':', [None, None, None, (u'a', u'a'), None, None]),
473 (u'a a: a', None, u':', [u'a', (u'a', None), u'a']),
474 (u'a a:"b c d" a', None, u':', [u'a', (u'a', u'b c d'), u'a']),
475 (u'a a:"b "" d" a', None, u':', [u'a', (u'a', u'b " d'), u'a']),
476 (u'title:Help* dog cat', None, u':', [(u'title', u'Help*'), u'dog', u'cat']),
477 (u'title:Help* "dog cat"', None, u':', [(u'title', u'Help*'), u'dog cat']),
478 (u'a:b:c d:e:f', None, u':', [(u'a', u'b', u'c'), (u'd', 'e', u'f')]),
479 (u'a:b:c:d', None, u':', [(u'a', u'b', u'c', u'd')]),
480 (u'a:"b:c":d', None, u':', [(u'a', u'b:c', u'd')]),
482 (u'-a:b:d', None, u':', [(M, u'a', u'b', u'd')]),
483 (u'"-a:b:d"', None, u':', [(u'-a:b:d')]),
484 (u'-"a:b:d"', None, u':', [(M, u'a:b:d')]),
485 (u'-a:"b:c":"d e f g"', None, u':', [(M, u'a', u'b:c', u'd e f g')]),
486 (u'+-a:b:d', None, u':', [(P, u'-a', u'b', u'd')]),
487 (u'-"+a:b:d"', None, u':', [(M, u'+a:b:d')]),
488 # bit of a weird case...
489 (u'-+"a:b:d"', None, u':', [(M, u'+"a', u'b', u'd"')]),
490 (u'-a:"b:c" a +b', None, u':', [(M, u'a', u'b:c'), u'a', (P, u'b')]),
493 def _check(args, sep, kwsep, expected):
494 res = wikiutil.parse_quoted_separated_ext(args, sep, kwsep, multikey=True, prefixes='-+')
495 assert res == expected
498 yield [_check] + list(test)
500 def testExtendedParserBracketingErrors(self):
501 UCE = wikiutil.BracketUnexpectedCloseError
502 MCE = wikiutil.BracketMissingCloseError
504 (u'("a", "b", "c"', u',', None, MCE),
505 (u'("a"("b", "c")', u',', None, MCE),
506 (u'("a"<"b", "c")>', u',', None, UCE),
507 (u')("a" ("b" "c"))', None, None, UCE),
508 (u'("a", ("b", "c">))', u',', None, UCE),
509 (u'("a", ("b", <"c">>))', u',', None, UCE),
510 (u'(<(<)>)>', u',', None, UCE),
513 def _check(args, sep, kwsep, err):
515 wikiutil.parse_quoted_separated_ext,
517 brackets=(u'<>', u'()'))
520 yield [_check] + list(test)
522 class TestArgGetters:
523 def testGetBoolean(self):
525 # default testing for None value
526 (None, None, None, None),
527 (None, None, False, False),
528 (None, None, True, True),
531 (u'0', None, None, False),
532 (u'1', None, None, True),
533 (u'false', None, None, False),
534 (u'true', None, None, True),
535 (u'FALSE', None, None, False),
536 (u'TRUE', None, None, True),
537 (u'no', None, None, False),
538 (u'yes', None, None, True),
539 (u'NO', None, None, False),
540 (u'YES', None, None, True),
542 for arg, name, default, expected in tests:
543 assert wikiutil.get_bool(self.request, arg, name, default) == expected
545 def testGetBooleanRaising(self):
547 py.test.raises(AssertionError, wikiutil.get_bool, self.request, None, None, 42)
549 # anything except None or unicode raises TypeError
550 py.test.raises(TypeError, wikiutil.get_bool, self.request, True)
551 py.test.raises(TypeError, wikiutil.get_bool, self.request, 42)
552 py.test.raises(TypeError, wikiutil.get_bool, self.request, 42.0)
553 py.test.raises(TypeError, wikiutil.get_bool, self.request, '')
554 py.test.raises(TypeError, wikiutil.get_bool, self.request, tuple())
555 py.test.raises(TypeError, wikiutil.get_bool, self.request, [])
556 py.test.raises(TypeError, wikiutil.get_bool, self.request, {})
558 # any value not convertable to boolean raises ValueError
559 py.test.raises(ValueError, wikiutil.get_bool, self.request, u'')
560 py.test.raises(ValueError, wikiutil.get_bool, self.request, u'42')
561 py.test.raises(ValueError, wikiutil.get_bool, self.request, u'wrong')
562 py.test.raises(ValueError, wikiutil.get_bool, self.request, u'"True"') # must not be quoted!
564 def testGetInt(self):
566 # default testing for None value
567 (None, None, None, None),
568 (None, None, -23, -23),
569 (None, None, 42, 42),
572 (u'0', None, None, 0),
573 (u'42', None, None, 42),
574 (u'-23', None, None, -23),
576 for arg, name, default, expected in tests:
577 assert wikiutil.get_int(self.request, arg, name, default) == expected
579 def testGetIntRaising(self):
581 py.test.raises(AssertionError, wikiutil.get_int, self.request, None, None, 42.23)
583 # anything except None or unicode raises TypeError
584 py.test.raises(TypeError, wikiutil.get_int, self.request, True)
585 py.test.raises(TypeError, wikiutil.get_int, self.request, 42)
586 py.test.raises(TypeError, wikiutil.get_int, self.request, 42.0)
587 py.test.raises(TypeError, wikiutil.get_int, self.request, '')
588 py.test.raises(TypeError, wikiutil.get_int, self.request, tuple())
589 py.test.raises(TypeError, wikiutil.get_int, self.request, [])
590 py.test.raises(TypeError, wikiutil.get_int, self.request, {})
592 # any value not convertable to int raises ValueError
593 py.test.raises(ValueError, wikiutil.get_int, self.request, u'')
594 py.test.raises(ValueError, wikiutil.get_int, self.request, u'23.42')
595 py.test.raises(ValueError, wikiutil.get_int, self.request, u'wrong')
596 py.test.raises(ValueError, wikiutil.get_int, self.request, u'"4711"') # must not be quoted!
598 def testGetFloat(self):
600 # default testing for None value
601 (None, None, None, None),
602 (None, None, -23.42, -23.42),
603 (None, None, 42.23, 42.23),
606 (u'0', None, None, 0),
607 (u'42.23', None, None, 42.23),
608 (u'-23.42', None, None, -23.42),
609 (u'-23.42E3', None, None, -23.42E3),
610 (u'23.42E-3', None, None, 23.42E-3),
612 for arg, name, default, expected in tests:
613 assert wikiutil.get_float(self.request, arg, name, default) == expected
615 def testGetFloatRaising(self):
617 py.test.raises(AssertionError, wikiutil.get_float, self.request, None, None, u'42')
619 # anything except None or unicode raises TypeError
620 py.test.raises(TypeError, wikiutil.get_float, self.request, True)
621 py.test.raises(TypeError, wikiutil.get_float, self.request, 42)
622 py.test.raises(TypeError, wikiutil.get_float, self.request, 42.0)
623 py.test.raises(TypeError, wikiutil.get_float, self.request, '')
624 py.test.raises(TypeError, wikiutil.get_float, self.request, tuple())
625 py.test.raises(TypeError, wikiutil.get_float, self.request, [])
626 py.test.raises(TypeError, wikiutil.get_float, self.request, {})
628 # any value not convertable to int raises ValueError
629 py.test.raises(ValueError, wikiutil.get_float, self.request, u'')
630 py.test.raises(ValueError, wikiutil.get_float, self.request, u'wrong')
631 py.test.raises(ValueError, wikiutil.get_float, self.request, u'"47.11"') # must not be quoted!
633 def testGetComplex(self):
635 # default testing for None value
636 (None, None, None, None),
637 (None, None, -23.42, -23.42),
638 (None, None, 42.23, 42.23),
641 (u'0', None, None, 0),
642 (u'42.23', None, None, 42.23),
643 (u'-23.42', None, None, -23.42),
644 (u'-23.42E3', None, None, -23.42E3),
645 (u'23.42E-3', None, None, 23.42E-3),
646 (u'23.42E-3+3.04j', None, None, 23.42E-3+3.04j),
647 (u'3.04j', None, None, 3.04j),
648 (u'-3.04j', None, None, -3.04j),
649 (u'23.42E-3+3.04i', None, None, 23.42E-3+3.04j),
650 (u'3.04i', None, None, 3.04j),
651 (u'-3.04i', None, None, -3.04j),
652 (u'-3', None, None, -3L),
653 (u'-300000000000000000000', None, None, -300000000000000000000L),
655 for arg, name, default, expected in tests:
656 assert wikiutil.get_complex(self.request, arg, name, default) == expected
658 def testGetComplexRaising(self):
660 py.test.raises(AssertionError, wikiutil.get_complex, self.request, None, None, u'42')
662 # anything except None or unicode raises TypeError
663 py.test.raises(TypeError, wikiutil.get_complex, self.request, True)
664 py.test.raises(TypeError, wikiutil.get_complex, self.request, 42)
665 py.test.raises(TypeError, wikiutil.get_complex, self.request, 42.0)
666 py.test.raises(TypeError, wikiutil.get_complex, self.request, 3j)
667 py.test.raises(TypeError, wikiutil.get_complex, self.request, '')
668 py.test.raises(TypeError, wikiutil.get_complex, self.request, tuple())
669 py.test.raises(TypeError, wikiutil.get_complex, self.request, [])
670 py.test.raises(TypeError, wikiutil.get_complex, self.request, {})
672 # any value not convertable to int raises ValueError
673 py.test.raises(ValueError, wikiutil.get_complex, self.request, u'')
674 py.test.raises(ValueError, wikiutil.get_complex, self.request, u'3jj')
675 py.test.raises(ValueError, wikiutil.get_complex, self.request, u'3Ij')
676 py.test.raises(ValueError, wikiutil.get_complex, self.request, u'3i-3i')
677 py.test.raises(ValueError, wikiutil.get_complex, self.request, u'wrong')
678 py.test.raises(ValueError, wikiutil.get_complex, self.request, u'"47.11"') # must not be quoted!
680 def testGetUnicode(self):
682 # default testing for None value
683 (None, None, None, None),
684 (None, None, u'', u''),
685 (None, None, u'abc', u'abc'),
688 (u'', None, None, u''),
689 (u'abc', None, None, u'abc'),
690 (u'"abc"', None, None, u'"abc"'),
692 for arg, name, default, expected in tests:
693 assert wikiutil.get_unicode(self.request, arg, name, default) == expected
695 def testGetUnicodeRaising(self):
697 py.test.raises(AssertionError, wikiutil.get_unicode, self.request, None, None, 42)
699 # anything except None or unicode raises TypeError
700 py.test.raises(TypeError, wikiutil.get_unicode, self.request, True)
701 py.test.raises(TypeError, wikiutil.get_unicode, self.request, 42)
702 py.test.raises(TypeError, wikiutil.get_unicode, self.request, 42.0)
703 py.test.raises(TypeError, wikiutil.get_unicode, self.request, '')
704 py.test.raises(TypeError, wikiutil.get_unicode, self.request, tuple())
705 py.test.raises(TypeError, wikiutil.get_unicode, self.request, [])
706 py.test.raises(TypeError, wikiutil.get_unicode, self.request, {})
709 class TestExtensionInvoking:
710 def _test_invoke_bool(self, b=bool):
713 def _test_invoke_bool_def(self, v=bool, b=False):
715 assert isinstance(b, bool)
716 assert isinstance(v, bool)
718 def _test_invoke_int_None(self, i=int):
719 assert i == 1 or i is None
721 def _test_invoke_float_None(self, i=float):
722 assert i == 1.4 or i is None
724 def _test_invoke_float_required(self, i=wikiutil.required_arg(float)):
727 def _test_invoke_choice(self, a, choice=[u'a', u'b', u'c']):
729 assert choice == u'a'
731 def _test_invoke_choicet(self, a, choice=(u'a', u'b', u'c')):
733 assert choice == u'a'
735 def _test_invoke_choice_required(self, i=wikiutil.required_arg((u'b', u'a'))):
738 def _test_trailing(self, a, _trailing_args=[]):
739 assert _trailing_args == [u'a']
741 def _test_arbitrary_kw(self, expect, _kwargs={}):
742 assert _kwargs == expect
744 def testInvoke(self):
745 def _test_invoke_int(i=int):
748 def _test_invoke_int_fixed(a, b, i=int):
751 assert i == 1 or i is None
753 ief = wikiutil.invoke_extension_function
754 ief(self.request, self._test_invoke_bool, u'False')
755 ief(self.request, self._test_invoke_bool, u'b=False')
756 ief(self.request, _test_invoke_int, u'1')
757 ief(self.request, _test_invoke_int, u'i=1')
758 ief(self.request, self._test_invoke_bool_def, u'False, False')
759 ief(self.request, self._test_invoke_bool_def, u'b=False, v=False')
760 ief(self.request, self._test_invoke_bool_def, u'False')
761 ief(self.request, self._test_invoke_int_None, u'i=1')
762 ief(self.request, self._test_invoke_int_None, u'i=')
763 ief(self.request, self._test_invoke_int_None, u'')
764 py.test.raises(ValueError, ief, self.request,
765 self._test_invoke_int_None, u'x')
766 py.test.raises(ValueError, ief, self.request,
767 self._test_invoke_int_None, u'""')
768 py.test.raises(ValueError, ief, self.request,
769 self._test_invoke_int_None, u'i=""')
770 py.test.raises(ValueError, ief, self.request,
771 _test_invoke_int_fixed, u'a=7', [7, 8])
772 ief(self.request, _test_invoke_int_fixed, u'i=1', [7, 8])
773 py.test.raises(ValueError, ief, self.request,
774 _test_invoke_int_fixed, u'i=""', [7, 8])
775 ief(self.request, _test_invoke_int_fixed, u'i=', [7, 8])
777 for choicefn in (self._test_invoke_choice, self._test_invoke_choicet):
778 ief(self.request, choicefn, u'', [7])
779 ief(self.request, choicefn, u'choice=a', [7])
780 ief(self.request, choicefn, u'choice=', [7])
781 ief(self.request, choicefn, u'choice="a"', [7])
782 py.test.raises(ValueError, ief, self.request,
784 py.test.raises(ValueError, ief, self.request,
785 choicefn, u'choice=x', [7])
787 ief(self.request, self._test_invoke_float_None, u'i=1.4')
788 ief(self.request, self._test_invoke_float_None, u'i=')
789 ief(self.request, self._test_invoke_float_None, u'')
790 ief(self.request, self._test_invoke_float_None, u'1.4')
791 py.test.raises(ValueError, ief, self.request,
792 self._test_invoke_float_None, u'x')
793 py.test.raises(ValueError, ief, self.request,
794 self._test_invoke_float_None, u'""')
795 py.test.raises(ValueError, ief, self.request,
796 self._test_invoke_float_None, u'i=""')
797 ief(self.request, self._test_trailing, u'a=7, a')
798 ief(self.request, self._test_trailing, u'7, a')
799 ief(self.request, self._test_arbitrary_kw, u'test=x, \xc3=test',
800 [{u'\xc3': 'test', 'test': u'x'}])
801 ief(self.request, self._test_arbitrary_kw, u'test=x, "\xc3"=test',
802 [{u'\xc3': 'test', 'test': u'x'}])
803 ief(self.request, self._test_arbitrary_kw, u'test=x, "7 \xc3"=test',
804 [{u'7 \xc3': 'test', 'test': u'x'}])
805 ief(self.request, self._test_arbitrary_kw, u'test=x, 7 \xc3=test',
806 [{u'7 \xc3': 'test', 'test': u'x'}])
807 ief(self.request, self._test_arbitrary_kw, u'7 \xc3=test, test= x ',
808 [{u'7 \xc3': 'test', 'test': u'x'}])
809 py.test.raises(ValueError, ief, self.request,
810 self._test_invoke_float_required, u'')
811 ief(self.request, self._test_invoke_float_required, u'1.4')
812 ief(self.request, self._test_invoke_float_required, u'i=1.4')
813 py.test.raises(ValueError, ief, self.request,
814 self._test_invoke_choice_required, u'')
815 ief(self.request, self._test_invoke_choice_required, u'a')
816 ief(self.request, self._test_invoke_choice_required, u'i=a')
817 py.test.raises(ValueError, ief, self.request,
818 self._test_invoke_float_required, u',')
820 def testConstructors(self):
821 ief = wikiutil.invoke_extension_function
825 def __init__(self, a=int):
826 self.constructed = True
832 obj = ief(self.request, TEST1, u'a=7')
833 assert isinstance(obj, TEST1)
834 assert obj.constructed
835 py.test.raises(ValueError, ief, self.request, TEST1, u'b')
837 obj = ief(self.request, TEST2, u'a=7')
838 assert isinstance(obj, TEST1)
839 assert isinstance(obj, TEST2)
840 assert obj.constructed
841 py.test.raises(ValueError, ief, self.request, TEST2, u'b')
845 def __init__(self, a=int):
846 self.constructed = True
852 obj = ief(self.request, TEST3, u'a=7')
853 assert isinstance(obj, TEST3)
854 assert obj.constructed
855 py.test.raises(ValueError, ief, self.request, TEST3, u'b')
857 obj = ief(self.request, TEST4, u'a=7')
858 assert isinstance(obj, TEST3)
859 assert isinstance(obj, TEST4)
860 assert obj.constructed
861 py.test.raises(ValueError, ief, self.request, TEST4, u'b')
863 def testFailing(self):
864 ief = wikiutil.invoke_extension_function
866 py.test.raises(TypeError, ief, self.request, hex, u'15')
867 py.test.raises(TypeError, ief, self.request, cmp, u'15')
868 py.test.raises(AttributeError, ief, self.request, unicode, u'15')
870 def testAllDefault(self):
871 ief = wikiutil.invoke_extension_function
873 def has_many_defaults(a=1, b=2, c=3, d=4):
880 assert ief(self.request, has_many_defaults, u'1, 2, 3, 4')
881 assert ief(self.request, has_many_defaults, u'2, 3, 4', [1])
882 assert ief(self.request, has_many_defaults, u'3, 4', [1, 2])
883 assert ief(self.request, has_many_defaults, u'4', [1, 2, 3])
884 assert ief(self.request, has_many_defaults, u'', [1, 2, 3, 4])
885 assert ief(self.request, has_many_defaults, u'd=4,c=3,b=2,a=1')
886 assert ief(self.request, has_many_defaults, u'd=4,c=3,b=2', [1])
887 assert ief(self.request, has_many_defaults, u'd=4,c=3', [1, 2])
888 assert ief(self.request, has_many_defaults, u'd=4', [1, 2, 3])
890 def testInvokeComplex(self):
891 ief = wikiutil.invoke_extension_function
893 def has_complex(a=complex, b=complex):
897 assert ief(self.request, has_complex, u'3-3i, 3-3j')
898 assert ief(self.request, has_complex, u'2i, 2j')
899 assert ief(self.request, has_complex, u'b=2i, a=2j')
900 assert ief(self.request, has_complex, u'2.007, 2.007')
901 assert ief(self.request, has_complex, u'2.007', [2.007])
902 assert ief(self.request, has_complex, u'b=2.007', [2.007])
905 class TestAnchorNames:
906 def test_anchor_name_encoding(self):
908 # text expected output
909 (u'\xf6\xf6ll\xdf\xdf', 'A.2BAPYA9g-ll.2BAN8A3w-'),
910 (u'level 2', 'level_2'),
911 (u'level_2', 'level_2'),
914 # make sure that a valid anchor is not modified:
915 (u'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789:_.-',
916 u'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789:_.-')
918 for text, expected in tests:
919 yield self._check, text, expected
921 def _check(self, text, expected):
922 encoded = wikiutil.anchor_name_from_text(text)
923 assert expected == encoded
925 class TestPageLinkMarkup:
926 def test_pagelinkmarkup(self):
928 # pagename (no link text), expected markup
929 (('SomePage', ), 'SomePage'),
930 (('Somepage', ), '[[Somepage]]'),
931 (('somepage', ), '[[somepage]]'),
932 (('Some Page', ), '[[Some Page]]'),
934 (('SomePage', 'SomePage'), 'SomePage'),
935 (('SomePage', 'some page'), '[[SomePage|some page]]'),
936 (('Some Page', 'Some Page'), '[[Some Page]]'),
937 (('Some Page', 'some Page'), '[[Some Page|some Page]]'),
939 for params, expected in tests:
940 yield self._check, params, expected
942 def _check(self, params, expected):
943 assert expected == wikiutil.pagelinkmarkup(*params)
945 class TestRelativeTools:
947 # test expected output
949 (('MainPage', '/SubPage1'), 'MainPage/SubPage1'),
950 (('MainPage', '/SubPage1/SubPage2'), 'MainPage/SubPage1/SubPage2'),
951 (('MainPage/SubPage1', '/SubPage2/SubPage3'), 'MainPage/SubPage1/SubPage2/SubPage3'),
952 (('', '/OtherMainPage'), 'OtherMainPage'), # strange
954 (('MainPage/SubPage', '../SisterPage'), 'MainPage/SisterPage'),
955 (('MainPage/SubPage1/SubPage2', '../SisterPage'), 'MainPage/SubPage1/SisterPage'),
956 (('MainPage/SubPage1/SubPage2', '../../SisterPage'), 'MainPage/SisterPage'),
957 (('MainPage', '../SisterPage'), 'SisterPage'), # strange
959 def test_abs_pagename(self):
960 for (current_page, relative_page), absolute_page in self.tests:
961 yield self._check_abs_pagename, current_page, relative_page, absolute_page
963 def _check_abs_pagename(self, current_page, relative_page, absolute_page):
964 assert absolute_page == wikiutil.AbsPageName(current_page, relative_page)
966 def test_rel_pagename(self):
967 for (current_page, relative_page), absolute_page in self.tests:
968 yield self._check_rel_pagename, current_page, absolute_page, relative_page
970 def _check_rel_pagename(self, current_page, absolute_page, relative_page):
971 assert relative_page == wikiutil.RelPageName(current_page, absolute_page)
974 class TestNormalizePagename(object):
976 def testPageInvalidChars(self):
977 """ request: normalize pagename: remove invalid unicode chars
979 Assume the default setting
981 test = u'\u0000\u202a\u202b\u202c\u202d\u202e'
983 result = wikiutil.normalize_pagename(test, self.request.cfg)
984 assert result == expected
986 def testNormalizeSlashes(self):
987 """ request: normalize pagename: normalize slashes """
992 (u'a/////b/////c', u'a/b/c'),
993 (u'a b/////c d/////e f', u'a b/c d/e f'),
995 for test, expected in cases:
996 result = wikiutil.normalize_pagename(test, self.request.cfg)
997 assert result == expected
999 def testNormalizeWhitespace(self):
1000 """ request: normalize pagename: normalize whitespace """
1005 (u'a b c', u'a b c'),
1006 (u'a b / c d / e f', u'a b/c d/e f'),
1007 # All 30 unicode spaces
1008 (config.chars_spaces, u''),
1010 for test, expected in cases:
1011 result = wikiutil.normalize_pagename(test, self.request.cfg)
1012 assert result == expected
1014 def testUnderscoreTestCase(self):
1015 """ request: normalize pagename: underscore convert to spaces and normalized
1017 Underscores should convert to spaces, then spaces should be
1018 normalized, order is important!
1024 (u'a b c', u'a b c'),
1025 (u'a b / c d / e f', u'a b/c d/e f'),
1027 for test, expected in cases:
1028 result = wikiutil.normalize_pagename(test, self.request.cfg)
1029 assert result == expected
1031 class TestGroupPages(object):
1033 def testNormalizeGroupName(self):
1034 """ request: normalize pagename: restrict groups to alpha numeric Unicode
1036 Spaces should normalize after invalid chars removed!
1040 (u'Name,:Group', u'NameGroup'),
1041 # remove than normalize spaces
1042 (u'Name ! @ # $ % ^ & * ( ) + Group', u'Name Group'),
1044 for test, expected in cases:
1045 # validate we are testing valid group names
1046 if wikiutil.isGroupPage(test, self.request.cfg):
1047 result = wikiutil.normalize_pagename(test, self.request.cfg)
1048 assert result == expected
1050 coverage_modules = ['MoinMoin.wikiutil']