Risk: Medium
Visibility: Changes the test keyval interface, deprecating the existing
test.write_keyval method in favour of a pair of write_*_keyval methods
for writing test & iteration keyvals. The deprecated method will still
work as it did before, but will generate a warning.

Adds a new iteration_attributes table to the database for storing
generic string attributes on a per-iteration basis, in the same way
that test_attributes allows generic string attributes on a per-test
basis.

This also adds new methods to the test class for writing these keyvals
so that tests can write out attributes by calling
self.write_test_keyval (or self.write_iteration_keyval). The iteration
method accepts parameters for both generic attributes and performance
data.

In order to store both performance and non-performance data in the
iteration keyvals, the format of the line has been extended to look
like "key{blah}=value", with no {blah} being interpreted as equvalent
to "{perf}", for backwards compatiblity.

Signed-off-by: John Admanski <jadmanski@google.com>



git-svn-id: http://test.kernel.org/svn/autotest/trunk@1535 592f7852-d20e-0410-864c-8624ca9c26a4
diff --git a/client/common_lib/utils.py b/client/common_lib/utils.py
index d2fb9d3..c6ec525 100644
--- a/client/common_lib/utils.py
+++ b/client/common_lib/utils.py
@@ -37,13 +37,31 @@
 	return keyval
 
 
-def write_keyval(path, dictionary):
+def write_keyval(path, dictionary, type_tag=None):
+	"""
+	Write a key-value pair format file out to a file. This uses append
+	mode to open the file, so existing text will not be overwritten or
+	reparsed.
+
+	If type_tag is None, then the key must be composed of alphanumeric
+	characters (or dashes+underscores). However, if type-tag is not
+	null then the keys must also have "{type_tag}" as a suffix. At
+	the moment the only valid values of type_tag are "attr" and "perf".
+	"""
 	if os.path.isdir(path):
 		path = os.path.join(path, 'keyval')
 	keyval = open(path, 'a')
+
+	if type_tag is None:
+		key_regex = re.compile(r'^[-\w]+$')
+	else:
+		if type_tag not in ('attr', 'perf'):
+			raise ValueError('Invalid type tag: %s' % type_tag)
+		escaped_tag = re.escape(type_tag)
+		key_regex = re.compile(r'^[-\w]+\{%s\}$' % escaped_tag)
 	try:
 		for key, value in dictionary.iteritems():
-			if re.search(r'[^-\w]', key):
+			if not key_regex.search(key):
 				raise ValueError('Invalid key: %s' % key)
 			keyval.write('%s=%s\n' % (key, value))
 	finally: