[Piglit] [PATCH 04/16] framework/core.py: Add a custom PiglitConfig class

Dylan Baker baker.dylan.c at gmail.com
Tue Apr 21 15:44:21 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 | 53 +++++++++++++++++++++++++++++++++++-----
 2 files changed, 101 insertions(+), 8 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 108d5ee..3a605f7 100644
--- a/framework/tests/core_tests.py
+++ b/framework/tests/core_tests.py
@@ -24,13 +24,14 @@ from __future__ import print_function, absolute_import
 import os
 import collections
 import shutil
-import ConfigParser
 import textwrap
 
 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]
@@ -66,7 +67,7 @@ class GetConfigFixture(object):
             if os.path.exists('piglit.conf'):
                 shutil.move('piglit.conf', 'piglit.conf.restore')
                 self.restore = True
-            core.PIGLIT_CONFIG = ConfigParser.SafeConfigParser(
+            core.PIGLIT_CONFIG = core.PiglitConfig(
                 allow_no_value=True)
         except Exception as e:
             raise utils.UtilsError(e)
@@ -82,7 +83,7 @@ class GetConfigFixture(object):
 
             if self.restore:
                 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,7 +91,7 @@ class GetConfigFixture(object):
 
 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)
 
 
 def check_initialize(target):
@@ -113,7 +114,7 @@ def test_generate_initialize():
     """
     yieldable = check_initialize
 
-    for target in [core.Options]:
+    for target in [core.Options, core.PiglitConfig]:
         yieldable.description = "Test that {} initializes".format(
             target.__name__)
         yield yieldable, target
@@ -237,3 +238,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.3.5



More information about the Piglit mailing list