11#!/usr/bin/python
2+
23###############################################################################
4+ #
35# Formatting filter for urllib2's HTTPHandler(debuglevel=1) output
46# Copyright (c) 2013, Analytics Pros
5- #
6- # This project is free software, distributed under the BSD license.
7- # Analytics Pros offers consulting and integration services if your firm needs
7+ #
8+ # This project is free software, distributed under the BSD license.
9+ # Analytics Pros offers consulting and integration services if your firm needs
810# assistance in strategy, implementation, or auditing existing work.
11+ #
912###############################################################################
1013
14+ # Standard library imports
15+ from __future__ import division , print_function , with_statement
16+ import re
17+ import sys
1118
12- import sys , re , os
13- from cStringIO import StringIO
14-
19+ # Third party libraries
20+ from six . moves import cStringIO as StringIO # Used by tests
21+ import six
1522
1623
1724class BufferTranslator (object ):
18- """ Provides a buffer-compatible interface for filtering buffer content.
25+ """
26+ Provides a buffer-compatible interface for filtering buffer content.
1927 """
2028 parsers = []
2129
30+ @staticmethod
31+ def stripslashes (content ):
32+ if six .PY3 :
33+ content = content .encode ('UTF-8' )
34+ return content .decode ('unicode_escape' )
35+ else :
36+ return content .decode ('string_escape' )
37+
38+ @staticmethod
39+ def addslashes (content ):
40+ if six .PY3 :
41+ return content .encode ('unicode_escape' )
42+ else :
43+ return content .encode ('string_escape' )
44+
2245 def __init__ (self , output ):
2346 self .output = output
2447 self .encoding = getattr (output , 'encoding' , None )
@@ -27,56 +50,51 @@ def write(self, content):
2750 content = self .translate (content )
2851 self .output .write (content )
2952
30-
31- @staticmethod
32- def stripslashes (content ):
33- return content .decode ('string_escape' )
34-
35- @staticmethod
36- def addslashes (content ):
37- return content .encode ('string_escape' )
38-
3953 def translate (self , line ):
4054 for pattern , method in self .parsers :
4155 match = pattern .match (line )
4256 if match :
4357 return method (match )
44-
4558 return line
46-
59+
60+ def flush (self ):
61+ pass
4762
4863
4964class LineBufferTranslator (BufferTranslator ):
50- """ Line buffer implementation supports translation of line-format input
51- even when input is not already line-buffered. Caches input until newlines
52- occur, and then dispatches translated input to output buffer.
5365 """
54- def __init__ (self , * a , ** kw ):
66+ Line buffer implementation supports translation of line-format input
67+ even when input is not already line-buffered. Caches input until newlines
68+ occur, and then dispatches translated input to output buffer.
69+ """
70+ def __init__ (self , * args , ** kwargs ):
5571 self ._linepending = []
56- super (LineBufferTranslator , self ).__init__ (* a , ** kw )
57-
72+ super (LineBufferTranslator , self ).__init__ (* args , ** kwargs )
73+
5874 def write (self , _input ):
5975 lines = _input .splitlines (True )
76+ last = 0
6077 for i in range (0 , len (lines )):
6178 last = i
6279 if lines [i ].endswith ('\n ' ):
63- prefix = len (self ._linepending ) and '' .join (self ._linepending ) or ''
80+ prefix = (len (self ._linepending ) and
81+ '' .join (self ._linepending ) or '' )
6482 self .output .write (self .translate (prefix + lines [i ]))
6583 del self ._linepending [0 :]
6684 last = - 1
67-
68- if last >= 0 :
69- self ._linepending .append (lines [ last ])
7085
86+ if lines and last >= 0 :
87+ self ._linepending .append (lines [last ])
7188
7289 def __del__ (self ):
7390 if len (self ._linepending ):
7491 self .output .write (self .translate ('' .join (self ._linepending )))
7592
7693
7794class HTTPTranslator (LineBufferTranslator ):
78- """ Translates output from |urllib2| HTTPHandler(debuglevel = 1) into
79- HTTP-compatible, readible text structures for human analysis.
95+ """
96+ Translates output from |urllib2| HTTPHandler(debuglevel = 1) into
97+ HTTP-compatible, readible text structures for human analysis.
8098 """
8199
82100 RE_LINE_PARSER = re .compile (r'^(?:([a-z]+):)\s*(\'?)([^\r\n]*)\2(?:[\r\n]*)$' )
@@ -89,14 +107,13 @@ def spacer(cls, line):
89107 return cls .RE_PARAMETER_SPACER .sub (r' &\1= ' , line )
90108
91109 def translate (self , line ):
92-
93110 parsed = self .RE_LINE_PARSER .match (line )
94111
95112 if parsed :
96113 value = parsed .group (3 )
97114 stage = parsed .group (1 )
98115
99- if stage == 'send' : # query string is rendered here
116+ if stage == 'send' : # query string is rendered here
100117 return '\n # HTTP Request:\n ' + self .stripslashes (value )
101118 elif stage == 'reply' :
102119 return '\n \n # HTTP Response:\n ' + self .stripslashes (value )
@@ -105,17 +122,17 @@ def translate(self, line):
105122 else :
106123 return value
107124
108-
109125 return line
110126
111127
112- def consume (outbuffer = None ): # Capture standard output
128+ def consume (outbuffer = None ):
129+ """
130+ Capture standard output.
131+ """
113132 sys .stdout = HTTPTranslator (outbuffer or sys .stdout )
114133 return sys .stdout
115134
116135
117136if __name__ == '__main__' :
118137 consume (sys .stdout ).write (sys .stdin .read ())
119- print '\n '
120-
121- # vim: set nowrap tabstop=4 shiftwidth=4 softtabstop=0 expandtab textwidth=0 filetype=python foldmethod=indent foldcolumn=4
138+ print ('\n ' )
0 commit comments