From 3f2f7f72a73caf087066c75d2e2b6e5ed908d34d Mon Sep 17 00:00:00 2001 From: Helmut Grohne Date: Fri, 29 Jun 2012 09:26:09 +0200 Subject: fix more bytes related issues not covered by test.py * applications returned errors as str instead of bytes * filters documentation updated with bytes * various filters expecting str where bytes are passed * escape_string also needs to use bytes.isalnum instead of str.isalnum * middlewares injecting str where bytes are expected --- wsgitools/applications.py | 6 +++--- wsgitools/filters.py | 40 ++++++++++++++++------------------------ wsgitools/middlewares.py | 8 ++++---- 3 files changed, 23 insertions(+), 31 deletions(-) diff --git a/wsgitools/applications.py b/wsgitools/applications.py index cdaf0ae..dfd8a2f 100644 --- a/wsgitools/applications.py +++ b/wsgitools/applications.py @@ -50,7 +50,7 @@ class StaticContent: assert isinstance(environ, dict) if environ["REQUEST_METHOD"].upper() not in ["GET", "HEAD"] and \ not self.anymethod: - resp = "Request method not implemented" + resp = b"Request method not implemented" start_response("501 Not Implemented", [("Content-length", str(len(resp)))]) return [resp] @@ -102,7 +102,7 @@ class StaticFile: assert isinstance(environ, dict) if environ["REQUEST_METHOD"].upper() not in ["GET", "HEAD"]: - resp = "Request method not implemented" + resp = b"Request method not implemented" start_response("501 Not Implemented", [("Content-length", str(len(resp)))]) return [resp] @@ -121,7 +121,7 @@ class StaticFile: size = stream.tell() stream.seek(0) except IOError: - resp = "File not found" + resp = b"File not found" start_response("404 File not found", [("Content-length", str(len(resp)))]) return [resp] diff --git a/wsgitools/filters.py b/wsgitools/filters.py index 6f90903..882a0bf 100644 --- a/wsgitools/filters.py +++ b/wsgitools/filters.py @@ -12,6 +12,8 @@ import time import gzip import io +from wsgitools.internal import str2bytes + __all__.append("CloseableIterator") class CloseableIterator: """Concatenating iterator with close attribute.""" @@ -122,15 +124,15 @@ class BaseWSGIFilter: """For each string that is either written by the C{write} callable or returned from the wrapped wsgi application this method is invoked. It must return a string. - @type data: str - @rtype: str + @type data: bytes + @rtype: bytes """ return data def append_data(self): """This function can be used to append data to the response. A list of strings or some kind of iterable yielding strings has to be returned. The default is to return an empty list. - @rtype: gen([str]) + @rtype: gen([bytes]) """ return [] def handle_close(self): @@ -152,7 +154,7 @@ class WSGIFilterMiddleware: def __call__(self, environ, start_response): """wsgi interface @type environ: {str, str} - @rtype: gen([str]) + @rtype: gen([bytes]) """ assert isinstance(environ, dict) reqfilter = self.filterclass() @@ -196,7 +198,7 @@ class WSGIFilterMiddleware: # default arguments. Also note that neither ' nor " are considered printable. # For escape_string to be reversible \ is also not considered printable. def escape_string(string, replacer=list(map( - lambda i: chr(i) if chr(i).isalnum() or + lambda i: chr(i) if str2bytes(chr(i)).isalnum() or chr(i) in '!#$%&()*+,-./:;<=>?@[]^_`{|}~ ' else r"\x%2.2x" % i, range(256)))): @@ -267,11 +269,7 @@ class RequestLogWSGIFilter(BaseWSGIFilter): self.status = status.split()[0] return status def filter_data(self, data): - """BaseWSGIFilter interface - @type data: str - @rtype: str - """ - assert isinstance(data, str) + assert isinstance(data, bytes) self.length += len(data) return data def handle_close(self): @@ -306,30 +304,31 @@ class TimerWSGIFilter(BaseWSGIFilter): def creator(cls, pattern): """Returns a function creating L{TimerWSGIFilter}s with a given pattern beeing a string of exactly eight bytes. - @type pattern: str + @type pattern: bytes """ return lambda:cls(pattern) - def __init__(self, pattern="?GenTime"): + def __init__(self, pattern=b"?GenTime"): """ @type pattern: str """ BaseWSGIFilter.__init__(self) + assert isinstance(pattern, bytes) self.pattern = pattern self.start = time.time() def filter_data(self, data): """BaseWSGIFilter interface - @type data: str - @rtype: str + @type data: bytes + @rtype: bytes """ if data == self.pattern: - return "%8.3g" % (time.time() - self.start) + return str2bytes("%8.3g" % (time.time() - self.start)) return data __all__.append("EncodeWSGIFilter") class EncodeWSGIFilter(BaseWSGIFilter): """Encodes all body data (no headers) with given charset. @note: This violates the wsgi standard as it requires unicode objects - whereas wsgi mandates the use of str. + whereas wsgi mandates the use of bytes. """ @classmethod def creator(cls, charset): @@ -347,7 +346,7 @@ class EncodeWSGIFilter(BaseWSGIFilter): def filter_data(self, data): """BaseWSGIFilter interface @type data: str - @rtype: str + @rtype: bytes """ return data.encode(self.charset) def filter_header(self, header, value): @@ -414,10 +413,6 @@ class GzipWSGIFilter(BaseWSGIFilter): headers.append(("Content-encoding", "gzip")) return headers def filter_data(self, data): - """BaseWSGIFilter interface - @type data: str - @rtype: str - """ if not self.compress: return data self.gzip.write(data) @@ -428,9 +423,6 @@ class GzipWSGIFilter(BaseWSGIFilter): self.sio.seek(0) return data def append_data(self): - """BaseWSGIFilter interface - @rtype: [str] - """ if not self.compress: return [] self.gzip.close() diff --git a/wsgitools/middlewares.py b/wsgitools/middlewares.py index 725deb1..4061d3b 100644 --- a/wsgitools/middlewares.py +++ b/wsgitools/middlewares.py @@ -33,7 +33,7 @@ class SubdirMiddleware: def __call__(self, environ, start_response): """wsgi interface @type environ: {str: str} - @rtype: gen([str]) + @rtype: gen([bytes]) """ assert isinstance(environ, dict) app = None @@ -65,7 +65,7 @@ class NoWriteCallableMiddleware: def __call__(self, environ, start_response): """wsgi interface @type environ: {str, str} - @rtype: gen([str]) + @rtype: gen([bytes]) """ assert isinstance(environ, dict) todo = [None] @@ -89,7 +89,7 @@ class NoWriteCallableMiddleware: ret = self.app(environ, modified_start_response) assert hasattr(ret, "__iter__") - first = "" + first = b"" if not isinstance(ret, list): ret = iter(ret) stopped = False @@ -171,7 +171,7 @@ class ContentLengthMiddleware: return ret ret = iter(ret) - first = "" + first = b"" stopped = False while not (first or stopped): try: -- cgit v1.2.3