Author: chrisz
Date: Sun Apr 18 07:52:44 2010
New Revision: 8119
Modified:
Webware/trunk/MiscUtils/Funcs.py
Webware/trunk/MiscUtils/Tests/TestFuncs.py
Webware/trunk/WebUtils/Funcs.py
Webware/trunk/WebUtils/Tests/TestFuncs.py
Webware/trunk/WebUtils/Tests/TestHTMLTag.py
Log:
Improved unit tests for Funcs module in MiscUtils and WebUtils.
Modified: Webware/trunk/MiscUtils/Funcs.py
==============================================================================
--- Webware/trunk/MiscUtils/Funcs.py (original)
+++ Webware/trunk/MiscUtils/Funcs.py Sun Apr 18 07:52:44 2010
@@ -1,6 +1,8 @@
-"""Funcs.py
+"""MiscUtils.Funcs
-Funcs.py, a member of MiscUtils, holds functions that don't fit in anywhere else.
+This module holds functions that don't fit in anywhere else.
+
+You can safely import * from MiscUtils.Funcs if you like.
"""
@@ -10,6 +12,7 @@
import datetime
import time
import datetime
+import textwrap
from struct import calcsize
@@ -19,6 +22,11 @@
from md5 import new as md5
from sha import new as sha1
+__all__ = [
+ 'commas', 'charWrap', 'wordWrap', 'excstr', 'hostName', 'localIP',
+ 'positive_id', 'safeDescription', 'asclocaltime', 'timestamp',
+ 'localTimeDelta', 'uniqueId', 'valueForString']
+
def commas(number):
"""Insert commas in a number.
@@ -62,25 +70,26 @@
"""
if not s:
return s
- assert hanging < width
+ if hanging < 0 or width < 1 or hanging >= width:
+ raise ValueError("Invalid width or indentation")
hanging = ' ' * hanging
lines = s.splitlines()
i = 0
while i < len(lines):
s = lines[i]
while len(s) > width:
- t = s[width:]
- s = s[:width]
- lines[i] = s
+ lines[i], s = s[:width].rstrip(), hanging + s[width:].lstrip()
i += 1
- lines.insert(i, None)
- s = hanging + t
- else:
- lines[i] = s
+ lines.insert(i, s)
i += 1
return '\n'.join(lines)
+def wordWrap(s, width=78):
+ """Return a version of the string word wrapped to the given width."""
+ return textwrap.fill(s, width)
+
+
def excstr(e):
"""Return a string for the exception.
@@ -96,20 +105,6 @@
return '%s: %s' % (e.__class__.__name__, e)
-def wordWrap(s, width=78):
- """Return a version of the string word wrapped to the given width.
-
- Respects existing newlines in the string.
-
- Taken from:
- http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/148061
-
- """
- return reduce(lambda line, word, width=width: "%s%s%s" % (
- line, ' \n'[(len(line[line.rfind('\n')+1:]) + len(word) >= width)],
- word), s.split())
-
-
def hostName():
"""Return the host name.
@@ -188,11 +183,11 @@
return _localIP
-# Addresses can "look negative" on some boxes, some of the time. If you
-# feed a "negative address" to an %x format, Python 2.3 displays it as
-# unsigned, but produces a FutureWarning, because Python 2.4 will display
-# it as signed. So when you want to prodce an address, use positive_id()
-# to obtain it. _address_mask is 2**(number_of_bits_in_a_native_pointer).
+# Addresses can "look negative" on some boxes, some of the time.
+# If you feed a "negative address" to an %x format, modern Python
+# versions will display it as signed. So when you want to produce
+# an address, use positive_id() to obtain it.
+# _address_mask is 2**(number_of_bits_in_a_native_pointer).
# Adding this to a negative address gives a positive int with the same
# hex representation as the significant bits in the original.
# This idea and code were taken from ZODB (http://svn.zope.org).
@@ -220,7 +215,6 @@
except Exception:
return '(exception from repr(%s))' % reprOfWhat
-
def safeDescription(obj, what='what'):
"""Return the repr() of obj and its class (or type) for help in debugging.
@@ -268,7 +262,6 @@
"""Return a dictionary whose keys give different versions of the timestamp.
The dictionary will contain the following timestamp versions:
- 'numSecs': the number of seconds
'tuple': (year, month, day, hour, min, sec)
'pretty': 'YYYY-MM-DD HH:MM:SS'
'condensed': 'YYYYMMDDHHMMSS'
@@ -282,18 +275,18 @@
formats are generally more appropriate for filenames.
"""
- tuple = time.localtime(t)[:6]
- pretty = '%4i-%02i-%02i %02i:%02i:%02i' % tuple
- condensed = '%4i%02i%02i%02i%02i%02i' % tuple
- dashed = '%4i-%02i-%02i-%02i-%02i-%02i' % tuple
- return locals()
+ t = time.localtime(t)[:6]
+ return dict(tuple=t,
+ pretty='%4i-%02i-%02i %02i:%02i:%02i' % t,
+ condensed='%4i%02i%02i%02i%02i%02i' % t,
+ dashed='%4i-%02i-%02i-%02i-%02i-%02i' % t)
def localTimeDelta(t=None):
"""Return timedelta of local zone from GMT."""
if t is None:
t = time.time()
- dt =datetime.datetime
+ dt = datetime.datetime
return dt.fromtimestamp(t) - dt.utcfromtimestamp(t)
Modified: Webware/trunk/MiscUtils/Tests/TestFuncs.py
==============================================================================
--- Webware/trunk/MiscUtils/Tests/TestFuncs.py (original)
+++ Webware/trunk/MiscUtils/Tests/TestFuncs.py Sun Apr 18 07:52:44 2010
@@ -1,3 +1,4 @@
+import time
import unittest
import FixPath
@@ -33,55 +34,93 @@
source = eval(tests[i])
result = eval(tests[i+1])
#print '%r yields %r' % (source, result)
- assert commas(source) == result, (
- '%r %r' % (commas(source), result))
+ self.assertEqual(commas(source), result)
# Now try the source as a string instead of a number:
source = eval("'%s'" % tests[i])
#print '%r yields %r' % (source, result)
- assert commas(source) == result, (
- '%r %r' % (commas(source), result))
+ self.assertEqual(commas(source), result)
i += 2
- def testLocalIP(self):
- ip = localIP()
- assert ip and not ip.startswith('127.')
- assert localIP() == ip # second invocation
- assert localIP(useCache=None) == ip
- assert localIP(remote=None, useCache=None) == ip, (
- 'See if this works: localIP(remote=None).'
- ' If this fails, dont worry.')
- assert localIP(remote=('www.aslkdjsfliasdfoivnoiedndfgncvb.com', 80),
- useCache=None) == ip # not existing remote address
+ def testCharWrap(self):
+ self.assertEqual(charWrap("""
+ Sparse is better than dense.
+ Readability counts.""", 34, 16), """
+ Sparse is better than
+ dense.
+ Readability counts.""")
+
+ def testWordWrap(self):
+ # an example with some spaces and newlines
+ msg = """Arthur: "The Lady of the Lake, her arm clad in the purest \
+shimmering samite, held aloft Excalibur from the bosom of the water, \
+signifying by Divine Providence that I, Arthur, was to carry \
+Excalibur. That is why I am your king!"
+
+Dennis: "Listen. Strange women lying in ponds distributing swords is \
+no basis for a system of government. Supreme executive power derives \
+from a mandate from the masses, not from some farcical aquatic \
+ceremony!\""""
+
+ for margin in range(20, 200, 29):
+ if margin == 78:
+ s = wordWrap(msg)
+ else:
+ s = wordWrap(msg, margin)
+ for line in s.splitlines():
+ self.assertTrue(len(line) <= margin,
+ 'len=%i, margin=%i, line=%r' % (len(line), margin, line))
+ self.assertEquals(msg.split(), s.split())
+
+ def testExcstr(self):
+ self.assertEqual(excstr(None), None)
+ self.assertEqual(excstr(ValueError('Kawoom!')),
+ 'ValueError: Kawoom!')
def testHostName(self):
- # About all we can do is invoke hostName() to see that no
- # exceptions are thrown, and do a little type checking on the
- # return type.
+ # About all we can do is invoke hostName() to see that no exceptions
+ # are thrown, and do a little type checking on the return type.
host = hostName()
- assert host is None or isinstance(host, str), (
+ self.assertTrue(host is None or isinstance(host, str),
'host type = %s, host = %s' % (type(host), repr(host)))
+ def testLocalIP(self):
+ ip = localIP()
+ self.assertTrue(ip and not ip.startswith('127.'))
+ self.assertEqual(localIP(), ip) # second invocation
+ self.assertEqual(localIP(useCache=None), ip)
+ self.assertEqual(localIP(remote=None, useCache=None), ip,
+ 'See if this works: localIP(remote=None).'
+ ' If this fails, dont worry.')
+ self.assertEqual(localIP(
+ remote=('www.aslkdjsfliasdfoivnoiedndfgncvb.com', 80),
+ useCache=None), ip) # not existing remote address
+
+ def testPositiveId(self):
+ # About all we can do is invoke positive_id()
+ # to see that no exceptions are thrown and the result is positive.
+ self.assertTrue(positive_id(self) > 0)
+
def testSafeDescription(self):
sd = safeDescription
# basics:
s = sd(1).replace('type=', 'class=')
- assert s == "what=1 class=<type 'int'>", s
+ self.assertEqual(s, "what=1 class=<type 'int'>")
s = sd(1, 'x').replace('type=', 'class=')
- assert s == "x=1 class=<type 'int'>", s
+ self.assertEqual(s, "x=1 class=<type 'int'>")
s = sd('x').replace('type=', 'class=')
s = s.replace("<type 'string'>", "<type 'str'>")
- assert s == "what='x' class=<type 'str'>", s
+ self.assertEqual(s, "what='x' class=<type 'str'>")
class OldStyle:
pass
old = OldStyle()
- assert ('%s.OldStyle' % __name__) in sd(old), sd(old)
+ self.assertTrue('%s.OldStyle' % __name__ in sd(old))
class NewStyle(object):
pass
new = NewStyle()
- assert ('%s.NewStyle' % __name__) in sd(new), sd(new)
+ self.assertTrue('%s.NewStyle' % __name__ in sd(new))
# okay now test that safeDescription eats exceptions from repr():
class Bogus(object):
@@ -92,16 +131,49 @@
s = sd(b)
except Exception:
s = 'failure: should not throw exception'
- assert "(exception from repr(obj): KeyError: 'bogus')" in s, s
+ self.assertTrue("(exception from repr(obj): KeyError: 'bogus')" in s)
+
+ def testAsclocaltime(self):
+ self.assertEqual(len(asclocaltime()), 24)
+ t = time.time()
+ self.assertEqual(asclocaltime(t), time.asctime(time.localtime(t)))
+
+ def testTimestamp(self):
+ d = timestamp()
+ self.assertTrue(isinstance(d, dict))
+ self.assertEqual(','.join(sorted(d)), 'condensed,dashed,pretty,tuple')
+ self.assertEqual(len(d['tuple']), 6)
+ self.assertEqual(len(d['condensed']), 14)
+ self.assertEqual(len(d['pretty']), 19)
+ self.assertEqual(len(d['dashed']), 19)
+ t = time.time()
+ d = timestamp(t)
+ t = time.localtime(t)[:6]
+ self.assertEqual(d['tuple'], t)
+ self.assertEqual(d['condensed'], '%4i%02i%02i%02i%02i%02i' % t)
+ self.assertEqual(d['condensed'],
+ d['pretty'].replace('-', '').replace(':', '').replace(' ', ''))
+ self.assertEqual(d['condensed'], d['dashed'].replace('-', ''))
+
+ def testLocalTimeDelta(self):
+ # we only check if the result is a multiple of one hour
+ d = localTimeDelta()
+ self.assertEqual(d.microseconds, 0)
+ self.assertEqual(d.seconds % 3600, 0)
+ self.assertEqual(d.days, 0)
+ d = localTimeDelta(time.time())
+ self.assertEqual(d.microseconds, 0)
+ self.assertEqual(d.seconds % 3600, 0)
+ self.assertEqual(d.days, 0)
def testUniqueId(self):
def checkId(i, sha, past):
- assert isinstance(i, str)
- assert len(i) == (sha and 40 or 32)
+ self.assertTrue(isinstance(i, str), type(i))
+ self.assertEqual(len(i), sha and 40 or 32)
for c in i:
- assert c in '0123456789abcdef'
- assert i not in past
+ self.assertTrue(c in '0123456789abcdef')
+ self.assertTrue(i not in past)
past[i] = i
for sha in (False, True):
@@ -142,34 +214,16 @@
evalCases = [s.strip() for s in evalCases.strip().splitlines()]
for case in evalCases:
- assert valueForString(case) == eval(case), (
+ self.assertEqual(valueForString(case), eval(case),
'case=%r, valueForString()=%r, eval()=%r'
% (case, valueForString(case), eval(case)))
stringCases = [s.strip() for s in stringCases.strip().splitlines()]
for case in stringCases:
- assert valueForString(case) == case, (
+ self.assertEqual(valueForString(case), case,
'case=%r, valueForString()=%r'
% (case, valueForString(case)))
- def testWordWrap(self):
- # an example with some spaces and newlines
- msg = """Arthur: "The Lady of the Lake, her arm clad in the purest \
-shimmering samite, held aloft Excalibur from the bosom of the water, \
-signifying by Divine Providence that I, Arthur, was to carry \
-Excalibur. That is why I am your king!"
-
-Dennis: "Listen. Strange women lying in ponds distributing swords is \
-no basis for a system of government. Supreme executive power derives \
-from a mandate from the masses, not from some farcical aquatic \
-ceremony!\""""
-
- for margin in range(20, 200, 20):
- s = wordWrap(msg, margin)
- for line in s.splitlines():
- assert len(line) <= margin, (
- 'len=%i, margin=%i, line=%r' % (len(line), margin, line))
-
if __name__ == '__main__':
unittest.main()
Modified: Webware/trunk/WebUtils/Funcs.py
==============================================================================
--- Webware/trunk/WebUtils/Funcs.py (original)
+++ Webware/trunk/WebUtils/Funcs.py Sun Apr 18 07:52:44 2010
@@ -5,12 +5,12 @@
You can safely import * from WebUtils.Funcs if you like.
-TO DO
-
- * Document the 'codes' arg of htmlEncode/Decode.
-
"""
+__all__ = [
+ 'htmlEncode', 'htmlEncodeStr', 'htmlDecode', 'urlEncode', 'urlDecode',
+ 'htmlForDict', 'requestURI', 'normURL']
+
htmlForNone = '-' # used by htmlEncode
@@ -26,6 +26,11 @@
def htmlEncode(what, codes=htmlCodes):
+ """Return the HTML encoded version of the given object.
+
+ The optional 'codes' parameter allows passing custom translations.
+
+ """
if what is None:
return htmlForNone
if hasattr(what, 'html'):
@@ -44,6 +49,8 @@
This is useful to display a plain ASCII text string on a web page.
+ The optional 'codes' parameter allows passing custom translations.
+
"""
for c, e in codes:
s = s.replace(c, e)
@@ -56,6 +63,8 @@
This does NOT remove normal HTML tags like <p>.
It is the inverse of htmlEncode().
+ The optional 'codes' parameter allows passing custom translations.
+
"""
for c, e in codes:
s = s.replace(e, c)
@@ -88,7 +97,7 @@
if maxValueLength and not isEncoded:
value = str(value)
if len(value) > maxValueLength:
- value = value[:maxValueLength] + '...'
+ value = value[:maxValueLength-3] + '...'
key = htmlEncode(key)
if not isEncoded:
value = htmlEncode(value)
Modified: Webware/trunk/WebUtils/Tests/TestFuncs.py
==============================================================================
--- Webware/trunk/WebUtils/Tests/TestFuncs.py (original)
+++ Webware/trunk/WebUtils/Tests/TestFuncs.py Sun Apr 18 07:52:44 2010
@@ -1,136 +1,126 @@
#!/usr/bin/env python
-"""
-TestFuncs.py
-Webware for Python
-
-This tests the performace of utility functions in WebUtils
-vs. their standard Python alternatives.
-
-"""
-
-import os, string, sys, time
-sys.path.insert(1, os.path.abspath(os.pardir))
-from Funcs import *
-import urllib
-
-allChars = string.join(map(chr, range(256)), '')
-
-URLEncodeTests = [
- 'NothingIsChangedTest',
- 'This test has spaces',
- 'This test has tabs',
- 'This:test:has:colons',
- ' boundary ',
- allChars
-]
-
-URLDecodeTests = [
- '%3E and %A7',
- '%3e and %a7',
- '& and + and -',
- 'illegal %3g?',
- 'illegal %x1?',
- '1 % 2 %% 3 %%%4 %%20'
-]
-
-def TestURLEncode():
- print 'Test URLEncode'
- for test in URLEncodeTests:
- if urlEncode(test) == urllib.quote_plus(test, '/'):
- print ' Passed test'
- else:
- print ' Failed test!'
- print ' string = (%s)' % test
- print ' urlEncode = (%s)' % urlEncode(test)
- print ' quote_plus = (%s)' % urllib.quote_plus(test, '/')
- print
-
-def TestURLDecode():
- print 'Test URLDecode'
- for test in URLDecodeTests:
- if urlDecode(test) == urllib.unquote_plus(test):
- print ' Passed test'
- else:
- print ' Failed test!'
- print ' string = (%s)' % test
- print ' urlDecode = (%s)' % urlDecode(test)
- print ' unquote_plus = (%s)' % urllib.unquote_plus(test)
- print
-
-def TestEncodeAndDecode(encodeFunc, decodeFunc, tests):
- print 'Test %s and %s' % (encodeFunc.__name__, decodeFunc.__name__)
- for test in tests:
- if decodeFunc(encodeFunc(test)) == test:
- print ' Passed test'
- else:
- print ' Failed test!'
- print ' string = (%s)' % test
- print ' encoded = (%s)' % encodeFunc(test)
- print ' decoded = (%s)' % decodeFunc(encodeFunc(test))
- print
-
-def TestURLEncodeAndDecode():
- TestEncodeAndDecode(urlEncode, urlDecode, URLEncodeTests)
-
-def Benchmark(func, tests, metacount=500, count=20):
- start = time.time()
- for majorLoop in xrange(metacount):
- for test in tests:
- for minorLoop in xrange(count):
- func(test)
- stop = time.time()
- return stop - start
-
-def BenchmarkURLEncode():
- print 'Benchmark urlEncode() vs. quote_plus()'
- tests = URLEncodeTests + map(urlEncode, URLEncodeTests)
- t1 = Benchmark(urllib.quote_plus, tests)
- t2 = Benchmark(urlEncode, tests)
- print ' quote_plus() = %6.2f secs' % t1
- print ' urlEncode() = %6.2f secs' % t2
- print ' diff = %6.2f secs' % (t2 - t1)
- print ' diff %% = %6.2f %%' % ((t2 - t1) / t1 * 100.0)
- print ' factor = %6.2f X' % (t1/t2)
- print
-
-def BenchmarkURLDecode():
- print 'Benchmark urlDecode() vs. unquote_plus()'
- tests = map(urlEncode, URLEncodeTests) + URLDecodeTests
- t1 = Benchmark(urllib.unquote_plus, tests)
- t2 = Benchmark(urlDecode, tests)
- print ' unquote_plus() = %6.2f secs' % t1
- print ' urlDecode() = %6.2f secs' % t2
- print ' diff = %6.2f secs' % (t2 - t1)
- print ' diff %% = %6.2f %%' % ((t2 - t1) / t1 * 100.0)
- print ' factor = %6.2f X' % (t1/t2)
- print
-
-HTMLEncodeTests = [
- 'Nothing special.',
- 'Put your HTML tags in <brackets>.',
- 'a & b & c',
- 'A \n newline',
- 'A newline \n x < y < z \n <tag>&<tag>'
-]
-def TestHTMLEncodeAndDecode():
- TestEncodeAndDecode(htmlEncode, htmlDecode, HTMLEncodeTests)
+import os
+import sys
+import unittest
+
+sys.path.insert(1, os.path.abspath('../..'))
+
+from WebUtils import Funcs
+
+
+class TestFuncs(unittest.TestCase):
+
+ def testHtmlEncode(self):
+ f = Funcs.htmlEncode
+ self.assertEqual(f('"1 < 2 & 2 > 1"'),
+ '"1 < 2 & 2 > 1"')
+ self.assertEqual(f('quarks & co', (('&', 'and'),)),
+ 'quarks and co')
+ self.assertEqual(f(None), '-')
+ class T(object):
+ @staticmethod
+ def html():
+ return 'bazong!'
+ t = T()
+ self.assertEqual(f(t), 'bazong!')
+ t.html = 'bazz!'
+ self.assertEqual(f(t), 'bazz!')
+
+ def testHtmlEncodeStr(self):
+ f = Funcs.htmlEncodeStr
+ self.assertEqual(f('"1 < 2 & 2 > 1"'),
+ '"1 < 2 & 2 > 1"')
+ self.assertEqual(f('quarks & co', (('&', 'and'),)),
+ 'quarks and co')
+
+ def testHtmlDecode(self):
+ f = Funcs.htmlDecode
+ self.assertEqual(f('"1 < 2 & 2 > 1"'),
+ '"1 < 2 & 2 > 1"')
+ self.assertEqual(f('quarks and co', (('&', 'and'),)),
+ 'quarks & co')
+
+ def testHtmlRoundTrip(self):
+ t = '<test>\n\t"1 < 2 & 2 > 1"\n</test>'
+ self.assertEqual(Funcs.htmlDecode(Funcs.htmlEncode(t)), t)
+
+ def testUrlEncode(self):
+ f = Funcs.urlEncode
+ self.assertEqual(f('"hello, world!"'), '%22hello%2C+world%21%22')
+
+ def testUrlDecode(self):
+ f = Funcs.urlDecode
+ self.assertEqual(f('%22hello%2C+world%21%22'), '"hello, world!"')
+
+ def testUrlRoundTrip(self):
+ t = '<test>\n\t"50% = 50,50?"\n</test>'
+ self.assertEqual(Funcs.urlDecode(Funcs.urlEncode(t)), t)
+
+ def testHtmlDorDict(self):
+ f = Funcs.htmlForDict
+ self.assertEqual(f(dict(foo='bar', answer=42)),
+ '<table class="NiceTable">\n'
+ '<tr><th align="left">answer</th><td>42</td></tr>\n'
+ '<tr><th align="left">foo</th><td>bar</td></tr>\n'
+ '</table>')
+ self.assertEqual(f(dict(foo='ba,zong', bar='ka;woom'),
+ addSpace=dict(foo=',', bar=';')),
+ '<table class="NiceTable">\n'
+ '<tr><th align="left">bar</th><td>ka; woom</td></tr>\n'
+ '<tr><th align="left">foo</th><td>ba, zong</td></tr>\n'
+ '</table>')
+ self.assertEqual(f(dict(foo='barbarabarbarabarbarabarbara'),
+ maxValueLength=12),
+ '<table class="NiceTable">\n'
+ '<tr><th align="left">foo</th><td>barbaraba...</td></tr>\n'
+ '</table>')
+ self.assertEqual(f(dict(foo='zing', bar='zang'),
+ filterValueCallBack=lambda v, k, d:
+ k == 'bar' and 'zung' or v),
+ '<table class="NiceTable">\n'
+ '<tr><th align="left">bar</th><td>zung</td></tr>\n'
+ '<tr><th align="left">foo</th><td>zing</td></tr>\n'
+ '</table>')
+ self.assertEqual(f(dict(foo='bar'), topHeading='twinkle'),
+ '<table class="NiceTable">\n'
+ '<tr class="TopHeading"><th colspan="2">twinkle</th></tr>\n'
+ '<tr><th align="left">foo</th><td>bar</td></tr>\n'
+ '</table>')
+ self.assertEqual(f(dict(foo='bar'), topHeading=('key', 'value')),
+ '<table class="NiceTable">\n'
+ '<tr class="TopHeading"><th>key</th><th>value</th></tr>\n'
+ '<tr><th align="left">foo</th><td>bar</td></tr>\n'
+ '</table>')
+ self.assertEqual(f({'a & b': 'c & d'}),
+ '<table class="NiceTable">\n'
+ '<tr><th align="left">a & b</th><td>c & d</td></tr>\n'
+ '</table>')
+ self.assertEqual(f({'a & b': 'c & d'}, isEncoded=True),
+ '<table class="NiceTable">\n'
+ '<tr><th align="left">a & b</th><td>c & d</td></tr>\n'
+ '</table>')
+
+ def testRequestURI(self):
+ f = Funcs.requestURI
+ self.assertEqual(f(dict(REQUEST_URI='http://w4py.org')),
+ 'http://w4py.org')
+ self.assertEqual(f(dict(SCRIPT_URL='http://w4py.org',
+ QUERY_STRING='foo=bar')), 'http://w4py.org?foo=bar')
+ self.assertEqual(f(dict(SCRIPT_NAME='/test',
+ QUERY_STRING='foo=bar')), '/test?foo=bar')
+
+ def testNormURL(self):
+ f = Funcs.normURL
+ self.assertEqual(f('foo/bar'), 'foo/bar')
+ self.assertEqual(f('/foo/bar'), '/foo/bar')
+ self.assertEqual(f('foo/bar/'), 'foo/bar/')
+ self.assertEqual(f('/foo/bar/../baz/../biz/./'), '/foo/biz/')
+ self.assertEqual(f('/foo/bar/baz/biz/../../../'), '/foo/')
+ self.assertEqual(f('/foo/./././././././'), '/foo/')
+ self.assertEqual(f('/foo/../../../'), '/')
+ self.assertEqual(f('foo///bar'), 'foo/bar')
if __name__ == '__main__':
-
- # To remove allChars, change to 'if 1:'
- # (With allChars, we look really good - URLEncode() is 6 X faster.
- # However, it's not a realistic case; reality is 2 X faster,
- # and with newer Python versions, we don't look so good any more).
- if 0:
- del URLEncodeTests[-1]
-
- # run tests
- TestURLEncode()
- TestURLDecode()
- TestURLEncodeAndDecode()
- BenchmarkURLEncode()
- BenchmarkURLDecode()
-
- TestHTMLEncodeAndDecode()
+ unittest.main()
Modified: Webware/trunk/WebUtils/Tests/TestHTMLTag.py
==============================================================================
--- Webware/trunk/WebUtils/Tests/TestHTMLTag.py (original)
+++ Webware/trunk/WebUtils/Tests/TestHTMLTag.py Sun Apr 18 07:52:44 2010
@@ -1,12 +1,11 @@
-import os, sys
+import os
+import sys
+import unittest
sys.path.insert(1, os.path.abspath('../..'))
-from WebUtils.HTMLTag import HTMLReader
from MiscUtils import StringIO
-
-#from MiscUtils import unittest
-import unittest
+from WebUtils.HTMLTag import HTMLReader
class HTMLTagTest(unittest.TestCase):
|