Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit a1a4b59

Browse files
author
Moshe Zadka
committed
Closing patch #101120 -- After everyone agreed.
1 parent dc3d606 commit a1a4b59

3 files changed

Lines changed: 76 additions & 61 deletions

File tree

Doc/lib/libcgi.tex

Lines changed: 40 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ \subsection{Introduction}
4545
generate a minimal header section looks like this:
4646

4747
\begin{verbatim}
48-
print "Content-type: text/html" # HTML is following
48+
print "Content-Type: text/html" # HTML is following
4949
print # blank line, end of headers
5050
\end{verbatim}
5151

@@ -59,9 +59,6 @@ \subsection{Introduction}
5959
print "Hello, world!"
6060
\end{verbatim}
6161

62-
(It may not be fully legal HTML according to the letter of the
63-
standard, but any browser will understand it.)
64-
6562
\subsection{Using the cgi module}
6663
\nodename{Using the cgi module}
6764

@@ -77,61 +74,69 @@ \subsection{Using the cgi module}
7774
standard). Since it may consume standard input, it should be
7875
instantiated only once.
7976

80-
The \class{FieldStorage} instance can be accessed as if it were a Python
81-
dictionary. For instance, the following code (which assumes that the
82-
\code{content-type} header and blank line have already been printed)
77+
The \class{FieldStorage} instance can be indexed like a Python
78+
dictionary, and also supports the standard dictionary methods
79+
\function{has_key()} and \function{keys()}.
80+
Form fields containing empty strings are ignored
81+
and do not appear in the dictionary; to keep such values, provide
82+
the optional \samp{keep_blank_values} argument when creating the
83+
\class {FieldStorage} instance.
84+
85+
For instance, the following code (which assumes that the
86+
\code{Content-Type} header and blank line have already been printed)
8387
checks that the fields \code{name} and \code{addr} are both set to a
8488
non-empty string:
8589

8690
\begin{verbatim}
8791
form = cgi.FieldStorage()
8892
form_ok = 0
8993
if form.has_key("name") and form.has_key("addr"):
90-
if form["name"].value != "" and form["addr"].value != "":
91-
form_ok = 1
94+
form_ok = 1
9295
if not form_ok:
9396
print "<H1>Error</H1>"
9497
print "Please fill in the name and addr fields."
9598
return
99+
print "<p>name:", form["name"].value
100+
print "<p>addr:", form["addr"].value
96101
...further form processing here...
97102
\end{verbatim}
98103

99104
Here the fields, accessed through \samp{form[\var{key}]}, are
100105
themselves instances of \class{FieldStorage} (or
101106
\class{MiniFieldStorage}, depending on the form encoding).
107+
The \member{value} attribute of the instance yields the string value
108+
of the field. The \function{getvalue()} method returns this string value
109+
directly; it also accepts an optional second argument as a default to
110+
return if the requested key is not present.
102111

103112
If the submitted form data contains more than one field with the same
104113
name, the object retrieved by \samp{form[\var{key}]} is not a
105114
\class{FieldStorage} or \class{MiniFieldStorage}
106-
instance but a list of such instances. If you expect this possibility
115+
instance but a list of such instances. Similarly, in this situation,
116+
\samp{form.getvalue(\var{key})} would return a list of strings.
117+
If you expect this possibility
107118
(i.e., when your HTML form contains multiple fields with the same
108119
name), use the \function{type()} function to determine whether you
109120
have a single instance or a list of instances. For example, here's
110121
code that concatenates any number of username fields, separated by
111122
commas:
112123

113124
\begin{verbatim}
114-
username = form["username"]
115-
if type(username) is type([]):
125+
value = form.getvalue("username", "")
126+
if type(value) is type([]):
116127
# Multiple username fields specified
117-
usernames = ""
118-
for item in username:
119-
if usernames:
120-
# Next item -- insert comma
121-
usernames = usernames + "," + item.value
122-
else:
123-
# First item -- don't insert comma
124-
usernames = item.value
128+
usernames = ",".join(value)
125129
else:
126-
# Single username field specified
127-
usernames = username.value
130+
# Single or no username field specified
131+
usernames = value
128132
\end{verbatim}
129133

130-
If a field represents an uploaded file, the value attribute reads the
134+
If a field represents an uploaded file, accessing the value via the
135+
\member{value} attribute or the \function{getvalue()} method reads the
131136
entire file in memory as a string. This may not be what you want.
132-
You can test for an uploaded file by testing either the filename
133-
attribute or the file attribute. You can then read the data at
134-
leisure from the file attribute:
137+
You can test for an uploaded file by testing either the \member{filename}
138+
attribute or the \member{file} attribute. You can then read the data at
139+
leisure from the \member{file} attribute:
135140

136141
\begin{verbatim}
137142
fileitem = form["userfile"]
@@ -157,7 +162,8 @@ \subsection{Using the cgi module}
157162
as a single data part of type
158163
\mimetype{application/x-www-form-urlencoded}), the items will actually
159164
be instances of the class \class{MiniFieldStorage}. In this case, the
160-
list, file and filename attributes are always \code{None}.
165+
\member{list}, \member{file}, and \member{filename} attributes are
166+
always \code{None}.
161167

162168

163169
\subsection{Old classes}
@@ -233,23 +239,22 @@ \subsection{Functions}
233239
\begin{funcdesc}{parse_multipart}{fp, pdict}
234240
Parse input of type \mimetype{multipart/form-data} (for
235241
file uploads). Arguments are \var{fp} for the input file and
236-
\var{pdict} for the dictionary containing other parameters of
237-
\code{content-type} header
242+
\var{pdict} for a dictionary containing other parameters in
243+
the \code{Content-Type} header.
238244

239245
Returns a dictionary just like \function{parse_qs()} keys are the
240246
field names, each value is a list of values for that field. This is
241247
easy to use but not much good if you are expecting megabytes to be
242248
uploaded --- in that case, use the \class{FieldStorage} class instead
243-
which is much more flexible. Note that \code{content-type} is the
244-
raw, unparsed contents of the \code{content-type} header.
249+
which is much more flexible.
245250

246251
Note that this does not parse nested multipart parts --- use
247252
\class{FieldStorage} for that.
248253
\end{funcdesc}
249254

250255
\begin{funcdesc}{parse_header}{string}
251-
Parse a header like \code{content-type} into a main
252-
content-type and a dictionary of parameters.
256+
Parse a MIME header (such as \code{Content-Type}) into a main
257+
value and a dictionary of parameters.
253258
\end{funcdesc}
254259

255260
\begin{funcdesc}{test}{}
@@ -432,7 +437,7 @@ \subsection{Debugging CGI scripts}
432437
\begin{verbatim}
433438
import sys
434439
import traceback
435-
print "Content-type: text/html"
440+
print "Content-Type: text/html"
436441
print
437442
sys.stderr = sys.stdout
438443
try:
@@ -454,7 +459,7 @@ \subsection{Debugging CGI scripts}
454459
\begin{verbatim}
455460
import sys
456461
sys.stderr = sys.stdout
457-
print "Content-type: text/plain"
462+
print "Content-Type: text/plain"
458463
print
459464
...your code here...
460465
\end{verbatim}

Lib/cgi.py

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
# responsible for its maintenance.
2020
#
2121

22-
__version__ = "2.2"
22+
__version__ = "2.3"
2323

2424

2525
# Imports
@@ -31,6 +31,7 @@
3131
import urllib
3232
import mimetools
3333
import rfc822
34+
import UserDict
3435
from StringIO import StringIO
3536

3637

@@ -166,11 +167,10 @@ def parse_qs(qs, keep_blank_values=0, strict_parsing=0):
166167
"""
167168
dict = {}
168169
for name, value in parse_qsl(qs, keep_blank_values, strict_parsing):
169-
if len(value) or keep_blank_values:
170-
if dict.has_key(name):
171-
dict[name].append(value)
172-
else:
173-
dict[name] = [value]
170+
if dict.has_key(name):
171+
dict[name].append(value)
172+
else:
173+
dict[name] = [value]
174174
return dict
175175

176176
def parse_qsl(qs, keep_blank_values=0, strict_parsing=0):
@@ -201,9 +201,10 @@ def parse_qsl(qs, keep_blank_values=0, strict_parsing=0):
201201
if strict_parsing:
202202
raise ValueError, "bad query field: %s" % `name_value`
203203
continue
204-
name = urllib.unquote(string.replace(nv[0], '+', ' '))
205-
value = urllib.unquote(string.replace(nv[1], '+', ' '))
206-
r.append((name, value))
204+
if len(nv[1]) or keep_blank_values:
205+
name = urllib.unquote(string.replace(nv[0], '+', ' '))
206+
value = urllib.unquote(string.replace(nv[1], '+', ' '))
207+
r.append((name, value))
207208

208209
return r
209210

@@ -537,6 +538,17 @@ def __getitem__(self, key):
537538
else:
538539
return found
539540

541+
def getvalue(self, key, default=None):
542+
"""Dictionary style get() method, including 'value' lookup."""
543+
if self.has_key(key):
544+
value = self[key]
545+
if type(value) is type([]):
546+
return map(lambda v: v.value, value)
547+
else:
548+
return value.value
549+
else:
550+
return default
551+
540552
def keys(self):
541553
"""Dictionary style keys() method."""
542554
if self.list is None:
@@ -706,7 +718,7 @@ def make_file(self, binary=None):
706718
# Backwards Compatibility Classes
707719
# ===============================
708720

709-
class FormContentDict:
721+
class FormContentDict(UserDict.UserDict):
710722
"""Basic (multiple values per field) form content as dictionary.
711723
712724
form = FormContentDict()
@@ -720,20 +732,8 @@ class FormContentDict:
720732
721733
"""
722734
def __init__(self, environ=os.environ):
723-
self.dict = parse(environ=environ)
735+
self.dict = self.data = parse(environ=environ)
724736
self.query_string = environ['QUERY_STRING']
725-
def __getitem__(self,key):
726-
return self.dict[key]
727-
def keys(self):
728-
return self.dict.keys()
729-
def has_key(self, key):
730-
return self.dict.has_key(key)
731-
def values(self):
732-
return self.dict.values()
733-
def items(self):
734-
return self.dict.items()
735-
def __len__( self ):
736-
return len(self.dict)
737737

738738

739739
class SvFormContentDict(FormContentDict):

Lib/test/test_cgi.py

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -116,19 +116,27 @@ def main():
116116
d = do_test(orig, "POST")
117117
assert d == expect, "Error parsing %s" % repr(orig)
118118

119-
d = {'QUERY_STRING': orig}
120-
fcd = cgi.FormContentDict(d)
121-
sd = cgi.SvFormContentDict(d)
119+
env = {'QUERY_STRING': orig}
120+
fcd = cgi.FormContentDict(env)
121+
sd = cgi.SvFormContentDict(env)
122+
fs = cgi.FieldStorage(environ=env)
122123
if type(expect) == type({}):
123124
# test dict interface
124125
assert len(expect) == len(fcd)
125126
assert norm(expect.keys()) == norm(fcd.keys())
126127
assert norm(expect.values()) == norm(fcd.values())
127128
assert norm(expect.items()) == norm(fcd.items())
129+
assert fcd.get("nonexistent field", "default") == "default"
130+
assert len(sd) == len(fs)
131+
assert norm(sd.keys()) == norm(fs.keys())
132+
assert fs.getvalue("nonexistent field", "default") == "default"
133+
# test individual fields
128134
for key in expect.keys():
129135
expect_val = expect[key]
130136
assert fcd.has_key(key)
131137
assert norm(fcd[key]) == norm(expect[key])
138+
assert fcd.get(key, "default") == fcd[key]
139+
assert fs.has_key(key)
132140
if len(expect_val) > 1:
133141
single_value = 0
134142
else:
@@ -137,9 +145,11 @@ def main():
137145
val = sd[key]
138146
except IndexError:
139147
assert not single_value
148+
assert fs.getvalue(key) == expect_val
140149
else:
141150
assert single_value
142151
assert val == expect_val[0]
152+
assert fs.getvalue(key) == expect_val[0]
143153
assert norm(sd.getlist(key)) == norm(expect_val)
144154
if single_value:
145155
assert norm(sd.values()) == \

0 commit comments

Comments
 (0)