b9cbc1b0f1ee80f3d7f85f35d733cb3d84bf5b09
[ZTUtils_hotfix.git] / __init__.py
1 """
2 This hotfix patch ZTUtils.Zope.make_query and make_hidden_input
3 to make a recursive marshal from a REQUEST.form data.
4
5 pinbe 2004/09/23
6 """
7
8 import urllib, cgi
9 from DateTime import DateTime
10
11 def make_query(*args, **kwargs):
12 '''Construct a URL query string, with marshalling markup.
13
14 If there are positional arguments, they must be dictionaries.
15 They are combined with the dictionary of keyword arguments to form
16 a dictionary of query names and values.
17
18 Query names (the keys) must be strings. Values may be strings,
19 integers, floats, or DateTimes, and they may also be lists or
20 namespaces containing these types. Names and string values
21 should not be URL-quoted. All arguments are marshalled with
22 complex_marshal().
23 '''
24 d = {}
25 for arg in args:
26 d.update(arg)
27 d.update(kwargs)
28
29 qlist = []
30 uq = urllib.quote
31 for k, v in d.items() :
32 for field in recurse_marshal(k, v) :
33 qlist.append( '%s%s=%s' % (uq(field['k']), field['m'], uq(str(field['v']))) )
34
35 return '&'.join(qlist)
36
37 def make_hidden_input(*args, **kwargs):
38 '''Construct a set of hidden input elements, with marshalling markup.
39
40 If there are positional arguments, they must be dictionaries.
41 They are combined with the dictionary of keyword arguments to form
42 a dictionary of query names and values.
43
44 Query names (the keys) must be strings. Values may be strings,
45 integers, floats, or DateTimes, and they may also be lists or
46 namespaces containing these types. All arguments are marshalled with
47 complex_marshal().
48 '''
49
50 d = {}
51 for arg in args:
52 d.update(arg)
53 d.update(kwargs)
54
55 hq = cgi.escape
56 qlist = []
57 for k, v in d.items() :
58 for field in recurse_marshal(k, v) :
59 qlist.append( ('<input type="hidden" name="%s%s" value="%s"/>'
60 % (hq(field['k']), field['m'], hq(str(field['v'])))) )
61
62 return '\n'.join(qlist)
63
64
65 def _simple_marshal(v) : # ! It's not a simple_marshal patch, the returned value is not the same.
66
67 if isinstance(v, bool) :
68 m = ':boolean'
69 elif isinstance(v, int) :
70 m = ':int'
71 elif isinstance(v, float) :
72 m = ':float'
73 elif isinstance(v, long) :
74 m = ':long'
75 elif isinstance(v, DateTime) :
76 m = ':date'
77 elif isinstance(v, unicode) :
78 m = ':utf8:ustring'
79 v = v.encode('utf8')
80 elif hasattr(v, 'items') :
81 m = ':record'
82 elif isinstance(v, list) :
83 if len(v) > 0 and hasattr(v[0], 'items') :
84 m = ':records'
85 else :
86 m = ':list'
87 else :
88 m = ''
89
90 return m, v
91
92
93 def recurse_marshal(k, v, nested='') :
94
95 marshalList = []
96 m, v = _simple_marshal(v)
97 n = nested
98 if m == ':list' :
99 n = ':list' + n
100 for sv in v :
101 if isinstance(sv, list) : # only strings into sv
102 white_space_found = False
103 for ssv in sv :
104 if ssv.find(' ') >=0 : white_space_found = True
105 if white_space_found :
106 sv = '\n'.join(sv)
107 insertM = ':lines'
108 else :
109 sv = ' '.join(sv)
110 insertM = ':tokens'
111
112 if isinstance(sv, unicode) :
113 sv = sv.encode('utf8')
114 insertM = ':utf8:u' + insertM[1:]
115 marshalList.extend(recurse_marshal(k, sv, nested=insertM + n))
116 else :
117 marshalList.extend(recurse_marshal(k, sv, n))
118 elif m == ':record' :
119 if n.find(':records') < 0 :
120 n = ':record' + n
121 for sk, sv in v.items() :
122 marshalList.extend(recurse_marshal('%s.%s' % (k, sk), sv, nested=n))
123 elif m == ':records' :
124 n = ':records' + n
125 for sv in v :
126 for ssk, ssv in sv.items() :
127 marshalList.extend(recurse_marshal('%s.%s' % (k, ssk), ssv, nested=n))
128 else :
129 marshalList.append({'k' : k,
130 'm' : m + nested,
131 'v' : v})
132
133 return marshalList
134
135
136 def initialize(context) :
137 import ZTUtils as ztu
138 ztu.make_query = ztu.Zope.make_query = make_query
139 ztu.make_hidden_input = ztu.Zope.make_hidden_input = make_hidden_input