[Piglit] [PATCH 1/4] framework: Add class JSONWriter

Chad Versace chad at chad-versace.us
Tue Jul 26 15:51:50 PDT 2011


JSONWriter writes to a JSON file stream.

It will be used by a subsequent commit to write each test result to the
result file as the test completes.

CC: Ian Romanick <ian.d.romanick at intel.com>
Signed-off-by: Chad Versace <chad at chad-versace.us>
---
 framework/core.py |  126 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 126 insertions(+), 0 deletions(-)

diff --git a/framework/core.py b/framework/core.py
index 56c78a4..921f19b 100644
--- a/framework/core.py
+++ b/framework/core.py
@@ -36,6 +36,7 @@ from log import log
 from cStringIO import StringIO
 from textwrap import dedent
 from threads import ConcurrentTestPool
+from threads import synchronized_self
 import threading
 
 __all__ = [
@@ -52,6 +53,131 @@ __all__ = [
 	'ResultFileInOldFormatError',
 ]
 
+class JSONWriter:
+	'''
+	Writes to a JSON file stream
+
+	JSONWriter is threadsafe.
+
+	Example
+	-------
+
+	This call to ``json.dump``::
+	    json.dump(
+		{
+		    'a': [1, 2, 3],
+		    'b': 4,
+		    'c': {
+		        'x': 100,
+		    },
+		}
+		file,
+		indent=JSONWriter.INDENT)
+
+	is equivalent to::
+	    w = JSONWriter(file)
+	    w.open_dict()
+	    w.write_dict_item('a', [1, 2, 3])
+	    w.write_dict_item('b', 4)
+	    w.write_dict_item('c', {'x': 100})
+	    w.close_dict()
+
+	which is also equivalent to::
+	    w = JSONWriter(file)
+	    w.open_dict()
+	    w.write_dict_item('a', [1, 2, 3])
+	    w.write_dict_item('b', 4)
+
+	    w.write_dict_key('c')
+	    w.open_dict()
+	    w.write_dict_item('x', 100)
+	    w.close_dict()
+
+	    w.close_dict()
+	'''
+
+	INDENT = 4
+
+	def __init__(self, file):
+		self.file = file
+		self.__indent_level = 0
+		self.__inhibit_next_indent = False
+		self.__encoder = json.JSONEncoder(indent=self.INDENT)
+
+		# self.__is_collection_empty
+		#
+		# A stack that indicates if the currect collection is empty
+		#
+		# When open_dict is called, True is pushed onto the
+		# stack. When the first element is written to the newly
+		# opened dict, the top of the stack is set to False.
+		# When the close_dict is called, the stack is popped.
+		#
+		# The top of the stack is element -1.
+		#
+		# XXX: How does one attach docstrings to member variables?
+		#
+		self.__is_collection_empty = []
+
+	@synchronized_self
+	def __write_indent(self):
+		if self.__inhibit_next_indent:
+			self.__inhibit_next_indent = False
+			return
+		else:
+			i = ' ' * self.__indent_level * self.INDENT
+			self.file.write(i)
+
+	@synchronized_self
+	def __write(self, obj):
+		lines = list(self.__encoder.encode(obj).split('\n'))
+		n = len(lines)
+		for i in range(n):
+			self.__write_indent()
+			self.file.write(lines[i])
+			if i != n - 1:
+				self.file.write('\n')
+
+	@synchronized_self
+	def open_dict(self):
+		self.__write_indent()
+		self.file.write('{')
+
+		self.__indent_level += 1
+		self.__is_collection_empty.append(True)
+
+	@synchronized_self
+	def close_dict(self, comma=True):
+		self.__indent_level -= 1
+		self.__is_collection_empty.pop()
+
+		self.file.write('\n')
+		self.__write_indent()
+		self.file.write('}')
+
+	@synchronized_self
+	def write_dict_item(self, key, value):
+		# Write key.
+		self.write_dict_key(key)
+
+		# Write value.
+		self.__indent_level += 1
+		self.__write(value)
+		self.__indent_level -= 1
+
+	@synchronized_self
+	def write_dict_key(self, key):
+		# Write comma if this is not the initial item in the dict.
+		if self.__is_collection_empty[-1]:
+			self.__is_collection_empty[-1] = False
+		else:
+			self.file.write(',')
+
+		self.file.write('\n')
+		self.__write(key)
+		self.file.write(': ')
+
+		self.__inhibit_next_indent = True
 
 #############################################################################
 ##### Helper functions
-- 
1.7.6



More information about the Piglit mailing list