summaryrefslogtreecommitdiff
path: root/paste/debug/wdg_validate.py
diff options
context:
space:
mode:
authorianb <devnull@localhost>2005-12-18 21:35:03 +0000
committerianb <devnull@localhost>2005-12-18 21:35:03 +0000
commit5e543609a56386342f95e56e5b0635f71792b3dc (patch)
tree13199c7c5b6ed7640e8e5e114cff5e4fce76db4b /paste/debug/wdg_validate.py
parentb8ca6badae7723920446824bff540164f2cb1e3e (diff)
downloadpaste-5e543609a56386342f95e56e5b0635f71792b3dc.tar.gz
Moved wdg_validate and profile to debug package
Diffstat (limited to 'paste/debug/wdg_validate.py')
-rw-r--r--paste/debug/wdg_validate.py99
1 files changed, 99 insertions, 0 deletions
diff --git a/paste/debug/wdg_validate.py b/paste/debug/wdg_validate.py
new file mode 100644
index 0000000..307d407
--- /dev/null
+++ b/paste/debug/wdg_validate.py
@@ -0,0 +1,99 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+
+from cStringIO import StringIO
+try:
+ import subprocess
+except ImportError:
+ from paste.util import subprocess24 as subprocess
+from paste import wsgilib
+import re
+import cgi
+
+__all__ = ['WDGValidateMiddleware']
+
+class WDGValidateMiddleware(object):
+
+ """
+ Middleware that checks HTML and appends messages about the validity of
+ the HTML. Uses: http://www.htmlhelp.com/tools/validator/ -- interacts
+ with the command line client. Use the configuration ``wdg_path`` to
+ override the path (default: looks for ``validate`` in $PATH).
+
+ To install, in your web context's __init__.py::
+
+ def urlparser_wrap(environ, start_response, app):
+ return wdg_validate.WDGValidateMiddleware(app)(
+ environ, start_response)
+
+ Or in your configuration::
+
+ middleware.append('paste.wdg_validate.WDGValidateMiddleware')
+ """
+
+ _end_body_regex = re.compile(r'</body>', re.I)
+
+ def __init__(self, app, global_conf=None, wdg_path='validate'):
+ self.app = app
+ self.wdg_path = wdg_path
+
+ def __call__(self, environ, start_response):
+ output = StringIO()
+ response = []
+
+ def writer_start_response(status, headers, exc_info=None):
+ response.extend((status, headers))
+ start_response(status, headers, exc_info)
+ return output.write
+
+ app_iter = self.app(environ, writer_start_response)
+ try:
+ for s in app_iter:
+ output.write(s)
+ finally:
+ if hasattr(app_iter, 'close'):
+ app_iter.close()
+ page = output.getvalue()
+ status, headers = response
+ v = wsgilib.header_value(headers, 'content-type')
+ if (not v.startswith('text/html')
+ and not v.startswith('text/xhtml+xml')):
+ # Can't validate
+ # @@: Should validate CSS too... but using what?
+ return [page]
+ ops = []
+ if v.startswith('text/xhtml+xml'):
+ ops.append('--xml')
+ # @@: Should capture encoding too
+ html_errors = self.call_wdg_validate(
+ self.wdg_path, ops, page)
+ if not html_errors:
+ return [page]
+ return self.add_error(page, html_errors)
+
+ def call_wdg_validate(self, wdg_path, ops, page):
+ if subprocess is None:
+ raise ValueError(
+ "This middleware requires the subprocess module from "
+ "Python 2.4")
+ proc = subprocess.Popen([wdg_path] + ops,
+ shell=False,
+ close_fds=True,
+ stdout=subprocess.PIPE,
+ stdin=subprocess.PIPE,
+ stderr=subprocess.STDOUT)
+ stdout = proc.communicate(page)[0]
+ proc.wait()
+ return stdout
+
+ def add_error(self, html_page, html_errors):
+ add_text = ('<pre style="background-color: #ffd; color: #600; '
+ 'border: 1px solid #000;">%s</pre>'
+ % cgi.escape(html_errors))
+ match = self._end_body_regex.search(html_page)
+ if match:
+ return [html_page[:match.start()]
+ + add_text
+ + html_page[match.end():]]
+ else:
+ return [html_page + add_text]