For example, the << left-shift operator in the C++ entry is translated to <<—
a pair of HTML escape codes. Because printing each code snippet effectively em-
beds it in the HTML response stream, we must escape any special HTML characters
it contains. HTML parsers (including Python’s standard html.parser module pre-
sented in Chapter 19) translate escape codes back to the original characters when
a page is rendered.
More generally, because CGI is based upon the notion of passing formatted strings
across the Net, escaping special characters is a ubiquitous operation. CGI scripts
almost always need to escape text generated as part of the reply to be safe. For
instance, if we send back arbitrary text input from a user or read from a data source
on the server, we usually can’t be sure whether it will contain HTML characters,
so we must escape it just in case.
In later examples, we’ll also find that characters inserted into URL address strings
generated by our scripts may need to be escaped as well. A literal & in a URL is
special, for example, and must be escaped if it appears embedded in text we insert
into a URL. However, URL syntax reserves different special characters than HTML
code, and so different escaping conventions and tools must be used. As we’ll see
later in this chapter, cgi.escape implements escape translations in HTML code,
but urllib.parse.quote (and its relatives) escapes characters in URL strings.
Mocking up form inputs
Here again, form inputs are “mocked up” (simulated), both for debugging and for
responding to a request for all languages in the table. If the script’s global
debugme variable is set to a true value, for instance, the script creates a dictionary
that is plug-and-play compatible with the result of a cgi.FieldStorage call—its
“languages” key references an instance of the dummy mock-up class. This class in
turn creates an object that has the same interface as the contents of a cgi.Field
Storage result—it makes an object with a value attribute set to a passed-in string.
The net effect is that we can test this script by running it from the system command
line: the generated dictionary fools the script into thinking it was invoked by a
browser over the Net. Similarly, if the requested language name is “All,” the script
iterates over all entries in the languages table, making a mocked-up form dictionary
for each (as though the user had requested each language in turn).
This lets us reuse the existing showHello logic to display each language’s code in a
single page. As always in Python, object interfaces and protocols are what we
usually code for, not specific datatypes. The showHello function will happily proc-
ess any object that responds to the syntax form['language'].value.# Notice that
#If you are reading closely, you might notice that this is the second time we’ve used mock-ups in this chapter
(see the earlier tutor4.cgi example). If you find this technique generally useful, it would probably make sense
to put the dummy class, along with a function for populating a form dictionary on demand, into a module so
that it can be reused. In fact, we will do that in the next section. Even for two-line classes like this, typing the
same code the third time around will do much to convince you of the power of code reuse.
The Hello World Selector | 1187