diff options
author | Georg Brandl <georg@python.org> | 2010-10-15 15:57:45 (GMT) |
---|---|---|
committer | Georg Brandl <georg@python.org> | 2010-10-15 15:57:45 (GMT) |
commit | 1f7fffb308390d10a2c6a4ec624f18cfeef97aeb (patch) | |
tree | 65e2437904ba089004c69c77b49e5059623b83fb /Lib | |
parent | 70543acfa1bce2e5f448d8d0085df595bfa9a2f9 (diff) | |
download | cpython-1f7fffb308390d10a2c6a4ec624f18cfeef97aeb.zip cpython-1f7fffb308390d10a2c6a4ec624f18cfeef97aeb.tar.gz cpython-1f7fffb308390d10a2c6a4ec624f18cfeef97aeb.tar.bz2 |
#2830: add html.escape() helper and move cgi.escape() uses in the standard library to it. It defaults to quote=True and also escapes single quotes, which makes casual use safer. The cgi.escape() interface is not touched, but emits a (silent) PendingDeprecationWarning.
Diffstat (limited to 'Lib')
-rwxr-xr-x | Lib/cgi.py | 25 | ||||
-rw-r--r-- | Lib/html/__init__.py | 21 | ||||
-rw-r--r-- | Lib/http/server.py | 6 | ||||
-rw-r--r-- | Lib/lib2to3/tests/test_util.py | 4 | ||||
-rw-r--r-- | Lib/test/test_html.py | 24 | ||||
-rw-r--r-- | Lib/test/test_xml_etree.py | 4 |
6 files changed, 64 insertions, 20 deletions
@@ -31,13 +31,13 @@ __version__ = "2.6" # Imports # ======= -from operator import attrgetter from io import StringIO import sys import os import urllib.parse import email.parser from warnings import warn +import html __all__ = ["MiniFieldStorage", "FieldStorage", "parse", "parse_qs", "parse_qsl", "parse_multipart", @@ -800,8 +800,8 @@ def print_exception(type=None, value=None, tb=None, limit=None): list = traceback.format_tb(tb, limit) + \ traceback.format_exception_only(type, value) print("<PRE>%s<B>%s</B></PRE>" % ( - escape("".join(list[:-1])), - escape(list[-1]), + html.escape("".join(list[:-1])), + html.escape(list[-1]), )) del tb @@ -812,7 +812,7 @@ def print_environ(environ=os.environ): print("<H3>Shell Environment:</H3>") print("<DL>") for key in keys: - print("<DT>", escape(key), "<DD>", escape(environ[key])) + print("<DT>", html.escape(key), "<DD>", html.escape(environ[key])) print("</DL>") print() @@ -825,10 +825,10 @@ def print_form(form): print("<P>No form fields.") print("<DL>") for key in keys: - print("<DT>" + escape(key) + ":", end=' ') + print("<DT>" + html.escape(key) + ":", end=' ') value = form[key] - print("<i>" + escape(repr(type(value))) + "</i>") - print("<DD>" + escape(repr(value))) + print("<i>" + html.escape(repr(type(value))) + "</i>") + print("<DD>" + html.escape(repr(value))) print("</DL>") print() @@ -839,9 +839,9 @@ def print_directory(): try: pwd = os.getcwd() except os.error as msg: - print("os.error:", escape(str(msg))) + print("os.error:", html.escape(str(msg))) else: - print(escape(pwd)) + print(html.escape(pwd)) print() def print_arguments(): @@ -899,9 +899,9 @@ environment as well. Here are some common variable names: # ========= def escape(s, quote=None): - '''Replace special characters "&", "<" and ">" to HTML-safe sequences. - If the optional flag quote is true, the quotation mark character (") - is also translated.''' + """Deprecated API.""" + warn("cgi.escape is deprecated, use html.escape instead", + PendingDeprecationWarning, stacklevel=2) s = s.replace("&", "&") # Must be done first! s = s.replace("<", "<") s = s.replace(">", ">") @@ -909,6 +909,7 @@ def escape(s, quote=None): s = s.replace('"', """) return s + def valid_boundary(s, _vb_pattern="^[ -~]{0,200}[!-~]$"): import re return re.match(_vb_pattern, s) diff --git a/Lib/html/__init__.py b/Lib/html/__init__.py index 196d378..335d214 100644 --- a/Lib/html/__init__.py +++ b/Lib/html/__init__.py @@ -1 +1,20 @@ -# This directory is a Python package. +""" +General functions for HTML manipulation. +""" + + +_escape_map = {ord('&'): '&', ord('<'): '<', ord('>'): '>'} +_escape_map_full = {ord('&'): '&', ord('<'): '<', ord('>'): '>', + ord('"'): '"', ord('\''): '''} + +# NB: this is a candidate for a bytes/string polymorphic interface + +def escape(s, quote=True): + """ + Replace special characters "&", "<" and ">" to HTML-safe sequences. + If the optional flag quote is true (the default), the quotation mark + character (") is also translated. + """ + if quote: + return s.translate(_escape_map_full) + return s.translate(_escape_map) diff --git a/Lib/http/server.py b/Lib/http/server.py index 894342a..f6d0db4 100644 --- a/Lib/http/server.py +++ b/Lib/http/server.py @@ -84,7 +84,7 @@ __version__ = "0.6" __all__ = ["HTTPServer", "BaseHTTPRequestHandler"] -import cgi +import html import email.message import email.parser import http.client @@ -705,7 +705,7 @@ class SimpleHTTPRequestHandler(BaseHTTPRequestHandler): return None list.sort(key=lambda a: a.lower()) r = [] - displaypath = cgi.escape(urllib.parse.unquote(self.path)) + displaypath = html.escape(urllib.parse.unquote(self.path)) r.append('<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">') r.append("<html>\n<title>Directory listing for %s</title>\n" % displaypath) r.append("<body>\n<h2>Directory listing for %s</h2>\n" % displaypath) @@ -721,7 +721,7 @@ class SimpleHTTPRequestHandler(BaseHTTPRequestHandler): displayname = name + "@" # Note: a link to a directory displays with @ and links with / r.append('<li><a href="%s">%s</a>\n' - % (urllib.parse.quote(linkname), cgi.escape(displayname))) + % (urllib.parse.quote(linkname), html.escape(displayname))) r.append("</ul>\n<hr>\n</body>\n</html>\n") enc = sys.getfilesystemencoding() encoded = ''.join(r).encode(enc) diff --git a/Lib/lib2to3/tests/test_util.py b/Lib/lib2to3/tests/test_util.py index 0ab7537..d2be82c 100644 --- a/Lib/lib2to3/tests/test_util.py +++ b/Lib/lib2to3/tests/test_util.py @@ -568,8 +568,8 @@ class Test_touch_import(support.TestCase): def test_from_import(self): node = parse('bar()') - fixer_util.touch_import("cgi", "escape", node) - self.assertEqual(str(node), 'from cgi import escape\nbar()\n\n') + fixer_util.touch_import("html", "escape", node) + self.assertEqual(str(node), 'from html import escape\nbar()\n\n') def test_name_import(self): node = parse('bar()') diff --git a/Lib/test/test_html.py b/Lib/test/test_html.py new file mode 100644 index 0000000..30dac58 --- /dev/null +++ b/Lib/test/test_html.py @@ -0,0 +1,24 @@ +""" +Tests for the html module functions. +""" + +import html +import unittest +from test.support import run_unittest + + +class HtmlTests(unittest.TestCase): + def test_escape(self): + self.assertEqual( + html.escape('\'<script>"&foo;"</script>\''), + ''<script>"&foo;"</script>'') + self.assertEqual( + html.escape('\'<script>"&foo;"</script>\'', False), + '\'<script>"&foo;"</script>\'') + + +def test_main(): + run_unittest(HtmlTests) + +if __name__ == '__main__': + test_main() diff --git a/Lib/test/test_xml_etree.py b/Lib/test/test_xml_etree.py index 7914d1f..e802359 100644 --- a/Lib/test/test_xml_etree.py +++ b/Lib/test/test_xml_etree.py @@ -12,7 +12,7 @@ # except if the test is specific to the Python implementation. import sys -import cgi +import html import unittest from test import support @@ -1328,7 +1328,7 @@ XINCLUDE["default.xml"] = """\ <p>Example.</p> <xi:include href="{}"/> </document> -""".format(cgi.escape(SIMPLE_XMLFILE, True)) +""".format(html.escape(SIMPLE_XMLFILE, True)) def xinclude_loader(href, parse="xml", encoding=None): try: |