changeset 2896:179099ff37c8

merge main
author Radomir Dopieralski <moindev@sheep.art.pl>
date Sun, 21 Oct 2007 13:42:00 +0200
parents e24aaec5a557 (current diff) f009ead62bfd (diff)
children 7f07db1306d1
files
diffstat 3 files changed, 63 insertions(+), 19 deletions(-) [+]
line wrap: on
line diff
--- a/MoinMoin/request/__init__.py	Sun Oct 21 13:41:19 2007 +0200
+++ b/MoinMoin/request/__init__.py	Sun Oct 21 13:42:00 2007 +0200
@@ -148,6 +148,7 @@
         # Pages meta data that we collect in one request
         self.pages = {}
 
+        self.sent_headers = False
         self.user_headers = []
         self.cacheable = 0 # may this output get cached by http proxies/caches?
         self.http_caching_disabled = 0 # see disableHttpCaching()
@@ -1281,7 +1282,7 @@
         url = self.getQualifiedURL(url)
         self.emit_http_headers(["Status: 302 Found", "Location: %s" % url])
 
-    def emit_http_headers(self, more_headers=[]):
+    def emit_http_headers(self, more_headers=[], testing=False):
         """ emit http headers after some preprocessing / checking
 
             Makes sure we only emit headers once.
@@ -1289,23 +1290,21 @@
             Make sure we have exactly one Content-Type and one Status header.
             Make sure Status header string begins with a integer number.
 
-            For emitting, it calls the server specific _emit_http_headers
-            method.
+            For emitting (testing == False), it calls the server specific
+            _emit_http_headers method. For testing, it returns the result.
 
             @param more_headers: list of additional header strings
+            @param testing: set to True by test code
         """
-        user_headers = getattr(self, 'user_headers', [])
+        user_headers = self.user_headers
         self.user_headers = []
         all_headers = more_headers + user_headers
 
-        # Send headers only once
-        sent_headers = getattr(self, 'sent_headers', 0)
-        sent_headers += 1
-        self.sent_headers = sent_headers
-        if sent_headers > 1:
-            raise HeadersAlreadySentException("emit_http_headers called multiple (%d) times! Headers: %r" % (sent_headers, all_headers))
-        #else:
-        #    self.log("Notice: emit_http_headers called first time. Headers: %r" % all_headers)
+        if self.sent_headers:
+            # Send headers only once
+            raise HeadersAlreadySentException("emit_http_headers has already been called before! Headers: %r" % all_headers)
+        else:
+            self.sent_headers = True
 
         # assemble dict of http headers
         headers = {}
@@ -1316,7 +1315,12 @@
             lkey = key.lower()
             value = value.lstrip()
             if lkey in headers:
-                self.log("Duplicate http header: %r (ignored)" % header)
+                if lkey in ['vary', 'cache-control', 'content-language', ]:
+                    # these headers (list might be incomplete) allow multiple values
+                    # that can be merged into a comma separated list
+                    headers[lkey] = headers[lkey][0], '%s, %s' % (headers[lkey][1], value)
+                else:
+                    self.log("Duplicate http header: %r (ignored)" % header)
             else:
                 headers[lkey] = (key, value)
 
@@ -1342,10 +1346,10 @@
 
         headers = [header_format % kv_tuple for kv_tuple in headers.values()] # make a list of strings
         headers = [st_header, ct_header] + headers # do NOT change order!
-        self._emit_http_headers(headers)
-
-        #from pprint import pformat
-        #sys.stderr.write(pformat(headers))
+        if not testing:
+            self._emit_http_headers(headers)
+        else:
+            return headers
 
     def _emit_http_headers(self, headers):
         """ server specific method to emit http headers.
@@ -1377,7 +1381,7 @@
         """
         self.failed = 1 # save state for self.run()
         # we should not generate the headers two times
-        if not getattr(self, 'sent_headers', 0):
+        if not self.sent_headers:
             self.emit_http_headers(['Status: 500 MoinMoin Internal Error'])
         from MoinMoin import failure
         failure.handle(self, err)
--- a/MoinMoin/request/_tests/test_request.py	Sun Oct 21 13:41:19 2007 +0200
+++ b/MoinMoin/request/_tests/test_request.py	Sun Oct 21 13:42:00 2007 +0200
@@ -11,6 +11,8 @@
 
 from MoinMoin import config, wikiutil
 
+from MoinMoin.request import HeadersAlreadySentException
+
 class TestNormalizePagename(object):
 
     def testPageInvalidChars(self):
@@ -107,5 +109,35 @@
         assert self.request.httpDate(0, rfc='850') == 'Thursday, 01-Jan-70 00:00:00 GMT'
 
 
+class TestHTTPHeaders(object):
+    std_headers = ['Status: 200 OK', 'Content-type: text/html; charset=%s' % config.charset]
+
+    def setup_method(self, method):
+        self.request.sent_headers = False
+
+    def testAutoAddStdHeaders(self):
+        """ test if the usual headers get auto-added if not specified """
+        headers_out = self.request.emit_http_headers(testing=True)
+        assert headers_out == self.std_headers
+
+    def testHeadersOnlyOnce(self):
+        """ test if trying to call emit_http_headers multiple times raises an exception """
+        self.request.emit_http_headers(testing=True)
+        py.test.raises(HeadersAlreadySentException, self.request.emit_http_headers, [], {'testing': True})
+
+    def testDuplicateHeadersIgnored(self):
+        """ test if duplicate headers get ignored """
+        headers_in = self.std_headers + ['Status: 500 Server Error']
+        headers_expected = self.std_headers
+        headers_out = self.request.emit_http_headers(headers_in, testing=True)
+        assert headers_out == headers_expected
+
+    def testListHeaders(self):
+        """ test if header values get merged into a list for headers supporting it """
+        headers_in = self.std_headers + ['Vary: aaa', 'vary: bbb']
+        headers_expected = self.std_headers + ['Vary: aaa, bbb']
+        headers_out = self.request.emit_http_headers(headers_in, testing=True)
+        assert headers_out == headers_expected
+
 coverage_modules = ['MoinMoin.request']
 
--- a/MoinMoin/wikidicts.py	Sun Oct 21 13:41:19 2007 +0200
+++ b/MoinMoin/wikidicts.py	Sun Oct 21 13:42:00 2007 +0200
@@ -92,14 +92,21 @@
     # strip free links markup if exists.
     regex = r'^ \* +(?:\[\[)?(?P<member>.+?)(?:\]\])? *$'
 
+    def __init__(self, request=None, pagename=None):
+        self._list = []
+        DictBase.__init__(self, request, pagename)
+
     def initFromText(self, text):
         for match in self.regex.finditer(text):
             member = match.group('member')
             self.addmember(member)
 
+    def __iter__(self):
+        return iter(self._list)
+
     def members(self):
         """ return the group's members """
-        return self.keys()
+        return self._list[:]
 
     def addmembers(self, members):
         """ add a list of members to the group """
@@ -109,6 +116,7 @@
     def addmember(self, member):
         """ add a member to the group """
         self[member] = 1
+        self._list.append(member)
 
     def has_member(self, member):
         """ check if the group has member <member> """