[Piglit] [PATCH v2 04/16] framework/core.py: Add a custom PiglitConfig class
Dylan Baker
baker.dylan.c at gmail.com
Mon May 18 10:57:38 PDT 2015
This allows us to encapsulate a lot of the error handling logic into a
single place with easy to use methods. This should reduce the amount of
code in consumers of PIGLIT_CONFIG.
It adds two new methods, safe_get and required_get, which operate on
NoOptionError or NoSectionError. With safe_get, if either of these is
raised None will be return, for required_get a PiglitFatalError will be
raised.
Signed-off-by: Dylan Baker <dylanx.c.baker at intel.com>
---
framework/core.py | 56 +++++++++++++++++++++++++++++--
framework/tests/core_tests.py | 76 ++++++++++++++++++++++++++++++++++++++-----
2 files changed, 122 insertions(+), 10 deletions(-)
diff --git a/framework/core.py b/framework/core.py
index 3ee2870..f9cdbfe 100644
--- a/framework/core.py
+++ b/framework/core.py
@@ -30,17 +30,69 @@ import subprocess
import sys
import ConfigParser
+from framework import exceptions
+
__all__ = [
'PIGLIT_CONFIG',
'PLATFORMS',
+ 'PiglitConfig',
'Options',
'collect_system_info',
'parse_listfile',
]
-
PLATFORMS = ["glx", "x11_egl", "wayland", "gbm", "mixed_glx_egl"]
-PIGLIT_CONFIG = ConfigParser.SafeConfigParser(allow_no_value=True)
+
+
+class PiglitConfig(ConfigParser.SafeConfigParser):
+ """Custom Config parser that provides a few extra helpers."""
+ def __init__(self, *args, **kwargs):
+ # In Python2 the ConfigParser classes are old style, you can't use
+ # super() on them. sigh
+ ConfigParser.SafeConfigParser.__init__(self, *args, **kwargs)
+ self.filename = None
+
+ def readfp(self, fp, filename=None):
+ # In Python2 the ConfigParser classes are old style, you can't use
+ # super() on them. sigh
+ ConfigParser.SafeConfigParser.readfp(self, fp, filename)
+ self.filename = os.path.abspath(filename or fp.name)
+
+ def safe_get(self, *args, **kwargs):
+ """A version of self.get that doesn't raise NoSectionError or
+ NoOptionError.
+
+ This is equivalent to passing if the option isn't found. It will return
+ None if an error is caught
+
+ """
+ try:
+ return self.get(*args, **kwargs)
+ except (ConfigParser.NoOptionError, ConfigParser.NoSectionError):
+ return None
+
+ def required_get(self, section, option, **kwargs):
+ """A version fo self.get that raises PiglitFatalError.
+
+ If self.get returns NoSectionError or NoOptionError then this will
+ raise a PiglitFatalException, aborting the program.
+
+ """
+ try:
+ return self.get(section, option, **kwargs)
+ except ConfigParser.NoSectionError:
+ raise exceptions.PiglitFatalError(
+ 'No Section "{}" in file "{}".\n'
+ 'This section is required.'.format(
+ section, self.filename))
+ except ConfigParser.NoOptionError:
+ raise exceptions.PiglitFatalError(
+ 'No option "{}" from section "{}" in file "{}".\n'
+ 'This option is required.'.format(
+ option, section, self.filename))
+
+
+PIGLIT_CONFIG = PiglitConfig(allow_no_value=True)
def get_config(arg=None):
diff --git a/framework/tests/core_tests.py b/framework/tests/core_tests.py
index d3ca563..9a49515 100644
--- a/framework/tests/core_tests.py
+++ b/framework/tests/core_tests.py
@@ -24,14 +24,16 @@ from __future__ import print_function, absolute_import
import os
import collections
import shutil
-import ConfigParser
import textwrap
import functools
+import ConfigParser
import nose.tools as nt
+from framework import core, exceptions
import framework.tests.utils as utils
-import framework.core as core
+
+# pylint: disable=line-too-long,invalid-name
_CONF_FILE = textwrap.dedent("""\
[nose-test]
@@ -80,7 +82,7 @@ def _save_core_config(func):
if restore_piglitconf:
shutil.move('piglit.conf.restore', 'piglit.conf')
- core.PIGLIT_CONFIG = ConfigParser.SafeConfigParser(
+ core.PIGLIT_CONFIG = core.PiglitConfig(
allow_no_value=True)
except Exception as e:
raise utils.UtilsError(e)
@@ -90,13 +92,31 @@ def _save_core_config(func):
def _reset_piglit_config():
""" Set core.PIGLIT_CONFIG back to pristine """
- core.PIGLIT_CONFIG = ConfigParser.SafeConfigParser()
+ core.PIGLIT_CONFIG = core.PiglitConfig(allow_no_value=True)
- at utils.no_error
-def test_options_init():
- """core.Options(): Class initializes"""
- core.Options()
+ at utils.nose_generator
+def test_generate_initialize():
+ """ Generator that creates tests to initialize all of the classes in core
+
+ In a compiled language the compiler provides this kind of checking, but in
+ an interpreted language like python you don't have a compiler test. The
+ unit tests generated by this function serve as a similar test, does this
+ even work?
+
+ """
+ def check_initialize(target):
+ """ Check that a class initializes without error """
+ func = target()
+ # Asserting that func exists will fail for Group and TestrunResult which
+ # are dict subclasses
+ assert isinstance(func, target)
+
+
+ for target in [core.Options, core.PiglitConfig]:
+ check_initialize.description = "Test that {} initializes".format(
+ target.__name__)
+ yield check_initialize, target
def test_parse_listfile_return():
@@ -213,3 +233,43 @@ def test_piglit_root():
nt.ok_(core.PIGLIT_CONFIG.has_section('nose-test'),
msg='$PIGLIT_ROOT not found')
+
+
+class TestPiglitConfig(object):
+ """Tests for PiglitConfig methods."""
+ @classmethod
+ def setup_class(cls):
+ cls.conf = core.PiglitConfig()
+ cls.conf.add_section('set')
+ cls.conf.set('set', 'options', 'bool')
+
+ def test_safe_get_valid(self):
+ """core.PiglitConfig: safe_get returns a value if its in the Config"""
+ nt.assert_equal(self.conf.safe_get('set', 'options'), 'bool')
+
+ def test_PiglitConfig_required_get_valid(self):
+ """core.PiglitConfig: required_get returns a value if its in the Config
+ """
+ nt.assert_equal(self.conf.required_get('set', 'options'), 'bool')
+
+ def test_safe_get_missing_option(self):
+ """core.PiglitConfig: safe_get returns None if the option is missing
+ """
+ nt.assert_equal(self.conf.safe_get('set', 'invalid'), None)
+
+ def test_safe_get_missing_section(self):
+ """core.PiglitConfig: safe_get returns None if the section is missing
+ """
+ nt.assert_equal(self.conf.safe_get('invalid', 'invalid'), None)
+
+ @nt.raises(exceptions.PiglitFatalError)
+ def test_required_get_missing_option(self):
+ """core.PiglitConfig: required_get raises PiglitFatalError if the option is missing
+ """
+ self.conf.required_get('set', 'invalid')
+
+ @nt.raises(exceptions.PiglitFatalError)
+ def test_required_get_missing_section(self):
+ """core.PiglitConfig: required_get raises PiglitFatalError if the section is missing
+ """
+ self.conf.required_get('invalid', 'invalid')
--
2.4.0
More information about the Piglit
mailing list