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

Eoff, Ullysses A ullysses.a.eoff at intel.com
Wed Jan 19 17:32:17 PST 2011


I decided to go with the logging wrapper after all.  However, it
has been even more simplified than the previous attempt for now.
Also, I made sure to use the coding style and license/copyright advice
that was suggested earlier.

--Artie

> -----Original Message-----
> From: U. Artie Eoff [mailto:ullysses.a.eoff at intel.com]
> Sent: Wednesday, January 19, 2011 5:26 PM
> To: piglit at lists.freedesktop.org
> Cc: Eoff, Ullysses A
> Subject: [PATCH] Added a simple logging class. Updated Test::doRun to
> use the new log.
> 
> 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