[Piglit] [PATCH] Added a simple logging class. Updated Test::doRun to use the new log.

U. Artie Eoff ullysses.a.eoff at intel.com
Wed Jan 19 17:25:57 PST 2011


Added log.py which includes a simple Logger class that wraps some
basic functions from the Python logging module. The log wrapper
simplifies setup and will accommodate thread synchronization in the
future.  Test::doRun now uses the new log facility.
NOTE: this changes the format of the 'test progress' previously
printed via stdout.

Added patterns.py which includes a Singleton class design pattern
to support the Logger class.  Future design patterns can be added
to this file.

Tested with Python 2.7 on Linux.  All should be compatible with
Windows and Mac and most earlier widely-used versions of Python.
---
 framework/core.py     |   12 ++++--
 framework/log.py      |   46 ++++++++++++++++++++++++++
 framework/patterns.py |   87 +++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 141 insertions(+), 4 deletions(-)
 create mode 100644 framework/log.py
 create mode 100644 framework/patterns.py

diff --git a/framework/core.py b/framework/core.py
index b975cb3..8d98f70 100644
--- a/framework/core.py
+++ b/framework/core.py
@@ -31,6 +31,7 @@ import subprocess
 import sys
 import time
 import traceback
+from log import log
 from cStringIO import StringIO
 
 __all__ = [
@@ -304,10 +305,14 @@ class Test:
 		if len(env.exclude_filter) > 0:
 			if True in map(lambda f: f.search(path) != None, env.exclude_filter):
 				return None
+
+		def status(msg):
+			log(msg = msg, channel = path)
+
 		# Run the test
 		if env.execute:
 			try:
-				print "Test: %(path)s" % locals()
+				status("running")
 				time_start = time.time()
 				result = self.run()
 				time_end = time.time()
@@ -325,9 +330,8 @@ class Test:
 				result['exception'] = str(sys.exc_info()[0]) + str(sys.exc_info()[1])
 				result['traceback'] = '@@@' + "".join(traceback.format_tb(sys.exc_info()[2]))
 
-			if result['result'] != 'pass':
-				print "    result: %(result)s" % { 'result': result['result'] }
-
+			status(result['result'])
+			
 			result.write(env.file, path)
 			if Test.sleep:
 				time.sleep(Test.sleep)
diff --git a/framework/log.py b/framework/log.py
new file mode 100644
index 0000000..c3fbdd7
--- /dev/null
+++ b/framework/log.py
@@ -0,0 +1,46 @@
+#
+# Copyright (c) 2010 Intel Corporation
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice (including the next
+# paragraph) shall be included in all copies or substantial portions of the
+# Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+# IN THE SOFTWARE.
+#
+
+from patterns import Singleton
+import logging
+
+class Logger(Singleton):
+	def __logMessage(self, logfunc, message, **kwargs):
+		[logfunc(line, **kwargs) for line in message.split('\n')]
+
+	def getLogger(self, channel = None):
+		if 0 == len(logging.root.handlers):
+			logging.basicConfig(
+				format = "[%(asctime)s] :: %(message)+8s :: %(name)s",
+				datefmt = "%c",
+				level = logging.INFO,
+			)
+		if channel is None:
+			channel = "base"
+		logger = logging.getLogger(channel)
+		return logger
+
+	def log(self, type = logging.INFO, msg = "", channel = None):
+		self.__logMessage(lambda m, **kwargs: self.getLogger(channel).log(type, m, **kwargs), msg)
+
+log = Logger().log
diff --git a/framework/patterns.py b/framework/patterns.py
new file mode 100644
index 0000000..3d7f22b
--- /dev/null
+++ b/framework/patterns.py
@@ -0,0 +1,87 @@
+#
+# Copyright (c) 2010 Intel Corporation
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice (including the next
+# paragraph) shall be included in all copies or substantial portions of the
+# Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+# IN THE SOFTWARE.
+#
+
+import threading
+
+class Singleton(object):
+	'''
+		Modeled after http://www.python.org/download/releases/2.2.3/descrintro/*__new__
+
+		A thread-safe (mostly -- see NOTE) Singleton class pattern.
+
+		NOTE: deleting a singleton instance (i.e. Singleton::delInstance) does not guarantee that something
+		else is currently using it. To reduce this risk, a program should not hold a reference to the
+		instance.  Rather, use the create/construct syntax (see example below) to access the instance.  Yet,
+		this still does not guarantee that this type of usage will result in a desired effect in a
+		multithreaded program.
+		You've been warned so use the singleton pattern wisely!
+
+		Example:
+		
+		class MySingletonClass(Singleton):
+			def init(self):
+				print "in MySingletonClass::init()", self
+
+			def foo(self):
+				print "in MySingletonClass::foo()", self
+
+		MySingletonClass().foo()
+		MySingletonClass().foo()
+		MySingletonClass().foo()
+
+		---> output will look something like this:
+		in MySingletonClass::init() <__main__.MySingletonClass object at 0x7ff5b322f3d0>
+		in MySingletonClass::foo() <__main__.MySingletonClass object at 0x7ff5b322f3d0>
+		in MySingletonClass::foo() <__main__.MySingletonClass object at 0x7ff5b322f3d0>
+		in MySingletonClass::foo() <__main__.MySingletonClass object at 0x7ff5b322f3d0>
+	'''
+
+	lock = threading.RLock()
+
+	def __new__(cls, *args, **kwargs):
+		try:
+			cls.lock.acquire()
+			it = cls.__dict__.get('__it__')
+			if it is not None:
+				return it
+			cls.__it__ = it = object.__new__(cls)
+			it.init(*args, **kwargs)
+			return it
+		finally: # this always gets called, even when returning from within the try block
+			cls.lock.release()
+
+	def init(self, *args, **kwargs):
+		'''
+			Derived classes should override this method to do its initializations
+			The derived class should not implement a '__init__' method.
+		'''
+		pass
+
+	@classmethod
+	def delInstance(cls):
+		cls.lock.acquire()
+		try:
+			if cls.__dict__.get('__it__') is not None:
+				del cls.__it__
+		finally:
+			cls.lock.release()
-- 
1.7.3.4



More information about the Piglit mailing list