"""WebUtils.Funcs
This module provides some basic functions that are useful
in HTML and web development.
You can safely import * from WebUtils.Funcs if you like.
"""
__all__ = [
'htmlEncode', 'htmlEncodeStr', 'htmlDecode', 'urlEncode', 'urlDecode',
'htmlForDict', 'requestURI', 'normURL']
htmlForNone = '-'
htmlCodes = (
('&', '&'),
('<', '<'),
('>', '>'),
('"', '"'),
)
htmlCodesReversed = tuple(reversed(htmlCodes))
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'):
ht = what.html
if callable(ht):
ht = ht()
return ht
what = str(what)
return htmlEncodeStr(what, codes)
def htmlEncodeStr(s, codes=htmlCodes):
"""Return the HTML encoded version of the given string.
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)
return s
def htmlDecode(s, codes=htmlCodesReversed):
"""Return the ASCII decoded version of the given HTML string.
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)
return s
from urllib import quote_plus as urlEncode, unquote_plus as urlDecode
def htmlForDict(d, addSpace=None, filterValueCallBack=None,
maxValueLength=None, topHeading=None, isEncoded=None):
"""Return an HTML string with a table where each row is a key-value pair."""
if not d:
return ''
html = ['<table class="NiceTable">\n']
if topHeading:
html.append('<tr class="TopHeading"><th')
html.append((isinstance(topHeading, tuple)
and '>%s</th><th>%s' or ' colspan="2">%s') % topHeading)
html.append('</th></tr>\n')
for key in sorted(d):
value = d[key]
if addSpace and key in addSpace:
target = addSpace[key]
value = (target + ' ').join(value.split(target))
if filterValueCallBack:
value = filterValueCallBack(value, key, d)
if maxValueLength and not isEncoded:
value = str(value)
if len(value) > maxValueLength:
value = value[:maxValueLength-3] + '...'
key = htmlEncode(key)
if not isEncoded:
value = htmlEncode(value)
html.append('<tr><th align="left">%s</th><td>%s</td></tr>\n'
% (key, value))
html.append('</table>')
return ''.join(html)
def requestURI(env):
"""Return the request URI for a given CGI-style dictionary.
Uses REQUEST_URI if available, otherwise constructs and returns it
from SCRIPT_URL, SCRIPT_NAME, PATH_INFO and QUERY_STRING.
"""
uri = env.get('REQUEST_URI')
if uri is None:
uri = env.get('SCRIPT_URL')
if uri is None:
uri = env.get('SCRIPT_NAME', '') + env.get('PATH_INFO', '')
query = env.get('QUERY_STRING', '')
if query != '':
uri += '?' + query
return uri
def normURL(path):
"""Normalizes a URL path, like os.path.normpath.
Acts on a URL independant of operating system environment.
"""
if not path:
return
initialslash = path[0] == '/'
lastslash = path[-1] == '/'
comps = path.split('/')
newcomps = []
for comp in comps:
if comp in ('', '.'):
continue
if comp != '..':
newcomps.append(comp)
elif newcomps:
newcomps.pop()
path = '/'.join(newcomps)
if path and lastslash:
path += '/'
if initialslash:
path = '/' + path
return path