summaryrefslogtreecommitdiff
path: root/python
diff options
context:
space:
mode:
authorRobert Collins <robertc@robertcollins.net>2009-10-13 16:43:05 +1100
committerRobert Collins <robertc@robertcollins.net>2009-10-13 16:43:05 +1100
commit39b7a1cc39710acc6ed0deff19d1dcaaa46970a8 (patch)
treee5376e264ca95c82afc1dff257c8b90477fb9be8 /python
parent236a0392e2d4ae550addac6bea02c7edb093c75f (diff)
downloadsubunit-git-39b7a1cc39710acc6ed0deff19d1dcaaa46970a8.tar.gz
Gather multipart details.
Diffstat (limited to 'python')
-rw-r--r--python/subunit/details.py36
-rw-r--r--python/subunit/tests/test_details.py20
2 files changed, 55 insertions, 1 deletions
diff --git a/python/subunit/details.py b/python/subunit/details.py
index 4f121cc..1460170 100644
--- a/python/subunit/details.py
+++ b/python/subunit/details.py
@@ -16,6 +16,11 @@
"""Handlers for outcome details."""
+from cStringIO import StringIO
+
+import chunked, content, content_type
+
+
class DetailsParser(object):
"""Base class/API reference for details parsing."""
@@ -50,9 +55,40 @@ class MultipartDetailsParser(DetailsParser):
def __init__(self, state):
self._state = state
self._details = {}
+ self._parse_state = self._look_for_content
+
+ def _look_for_content(self, line):
+ if line == "]\n":
+ self._state.endDetails()
+ return
+ # TODO error handling
+ field, value = line[:-1].split(' ', 1)
+ main, sub = value.split('/')
+ self._content_type = content_type.ContentType(main, sub)
+ self._parse_state = self._get_name
+
+ def _get_name(self, line):
+ self._name = line[:-1]
+ self._body = StringIO()
+ self._chunk_parser = chunked.Decoder(self._body)
+ self._parse_state = self._feed_chunks
+
+ def _feed_chunks(self, line):
+ residue = self._chunk_parser.write(line)
+ if residue is not None:
+ # Line based use always ends on no residue.
+ assert residue == ''
+ body = self._body
+ self._details[self._name] = content.Content(
+ self._content_type, lambda:[body.getvalue()])
+ self._chunk_parser.close()
+ self._parse_state = self._look_for_content
def get_details(self):
return self._details
def get_message(self):
return None
+
+ def lineReceived(self, line):
+ self._parse_state(line)
diff --git a/python/subunit/tests/test_details.py b/python/subunit/tests/test_details.py
index bc0930a..f76d505 100644
--- a/python/subunit/tests/test_details.py
+++ b/python/subunit/tests/test_details.py
@@ -18,7 +18,7 @@ from cStringIO import StringIO
import unittest
import subunit.tests
-from subunit import details
+from subunit import content, content_type, details
def test_suite():
@@ -60,3 +60,21 @@ class TestMultipartDetails(unittest.TestCase):
def test_get_details(self):
parser = details.MultipartDetailsParser(None)
self.assertEqual({}, parser.get_details())
+
+ def test_parts(self):
+ parser = details.MultipartDetailsParser(None)
+ parser.lineReceived("Content-Type: text/plain\n")
+ parser.lineReceived("something\n")
+ parser.lineReceived("F\r\n")
+ parser.lineReceived("serialised\n")
+ parser.lineReceived("form0\r\n")
+ expected = {}
+ expected['something'] = content.Content(
+ content_type.ContentType("text", "plain"),
+ lambda:["serialised\nform"])
+ found = parser.get_details()
+ self.assertEqual(expected.keys(), found.keys())
+ self.assertEqual(expected['something'].content_type,
+ found['something'].content_type)
+ self.assertEqual(''.join(expected['something'].iter_bytes()),
+ ''.join(found['something'].iter_bytes()))