Use base class for config file parsers

The configuration file parsers have a defined API, but we aren't
enforcing use of that. This adds an abstract base class that they
all will now inherit from. Additionally, new tests are added to
ensure the classes inherit from the new base class.

Moves tests for files in the config/ directory into their own
test directory.

Fixes the test class name for the ToxIni tests.

Change-Id: I003b4add6060075676da0f23cc37445ea50ffe88
This commit is contained in:
David Shrewsbury 2014-09-24 17:47:59 -04:00
parent 629ef2d69d
commit a21659d31e
11 changed files with 193 additions and 20 deletions

View File

@ -18,11 +18,16 @@ __all__ = [
'Commands',
]
import logging
import dox.config.dox_yaml
import dox.config.tox_ini
import dox.config.travis_yaml
logger = logging.getLogger(__name__)
def get_commands():
'''Examine the local environment and figure out what we should run.'''
@ -32,6 +37,7 @@ def get_commands():
for source in (dox_yaml, tox_ini, travis_yaml):
if source.exists():
logger.debug("Command source is: %s" % source.source_name())
return source
raise Exception("dox cannot figure out what command to run")

78
dox/config/base.py Normal file
View File

@ -0,0 +1,78 @@
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import abc
import six
@six.add_metaclass(abc.ABCMeta)
class ConfigBase(object):
"""Configuration file reader base class."""
@abc.abstractmethod
def exists(self):
"""Check if the configuration file is present.
:returns: True if the file is present.
:returns: False if the file is not present.
"""
@abc.abstractmethod
def get_images(self):
"""Get list of docker source images used to build the test image.
:returns: List of image names in <user>/<repo>[:<tag>] format.
"""
@abc.abstractmethod
def get_commands(self):
"""Get list of commands to execute with the final test image.
These commands will be executed via the 'docker run' command
with the final test image.
:returns: List of executable commands.
"""
@abc.abstractmethod
def get_prep_commands(self):
"""Get list of commands to run while building the test image.
These commands will be executed while building the test image,
thus allowing for any software installation, configuration, etc.
to be built into the test image.
:returns: List of executable commands.
"""
@abc.abstractmethod
def get_add_files(self):
"""Get list of files to add to the test image.
The named files will be placed in the working directory of the
built test image.
:returns: List of file names.
"""
@abc.abstractmethod
def source_name(self):
"""The source of the configuration.
This identifies the source of the configuration values. E.g.,
a file name, or other descriptive text.
:returns: String describing the source.
"""

View File

@ -13,14 +13,16 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import os
import yaml
import dox.config.base as base
__all__ = [
'get_dox_yaml',
]
import os
import yaml
_dox_yaml = None
@ -31,9 +33,10 @@ def get_dox_yaml():
return _dox_yaml
class DoxYaml(object):
class DoxYaml(base.ConfigBase):
_yaml = None
_dox_file = 'dox.yml'
def _open_dox_yaml(self):
if self._yaml is None:
@ -41,8 +44,11 @@ class DoxYaml(object):
self._yaml = yaml.load(f)
return self._yaml
def source_name(self):
return self._dox_file
def exists(self):
return os.path.exists('dox.yml')
return os.path.exists(self._dox_file)
def get_images(self):
return self._open_dox_yaml().get('images', [])

View File

@ -13,13 +13,16 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import ConfigParser
import os
import dox.config.base as base
__all__ = [
'get_tox_ini',
]
import ConfigParser
import os
_tox_ini = None
@ -30,7 +33,7 @@ def get_tox_ini():
return _tox_ini
class ToxIni(object):
class ToxIni(base.ConfigBase):
_ini = None
tox_ini_file = 'tox.ini'
@ -41,6 +44,9 @@ class ToxIni(object):
self._ini.read(self.tox_ini_file)
return self._ini
def source_name(self):
return self.tox_ini_file
def exists(self):
return os.path.exists(self.tox_ini_file)

View File

@ -13,14 +13,16 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import os
import yaml
import dox.config.base as base
__all__ = [
'get_travis_yaml',
]
import os
import yaml
_travis_yaml = None
@ -31,9 +33,10 @@ def get_travis_yaml():
return _travis_yaml
class TravisYaml(object):
class TravisYaml(base.ConfigBase):
_yaml = None
_travis_file = 'travis.yml'
def _open_travis_yaml(self):
if self._yaml is None:
@ -41,10 +44,13 @@ class TravisYaml(object):
self._yaml = yaml.load(f)
return self._yaml
def exists(self):
return os.path.exists('travis.yml')
def source_name(self):
return self._travis_file
def get_command(self, command):
def exists(self):
return os.path.exists(self._travis_file)
def get_commands(self, command):
return self._open_travis_yaml().get('script', command)
def get_prep_commands(self):
@ -59,3 +65,11 @@ class TravisYaml(object):
else:
prep.append(val)
return []
# TODO(Shrews): Implement this
def get_add_files(self):
return []
# TODO(Shrews): Implement this
def get_images(self):
return []

View File

View File

@ -0,0 +1,28 @@
# -*- coding: utf-8 -*-
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import dox.config.base as cfg_base
from dox.config import dox_yaml
from dox.tests import base
class TestDoxYaml(base.TestCase):
def setUp(self):
super(TestDoxYaml, self).setUp()
self.doxyaml = dox_yaml.DoxYaml()
def test_base_class(self):
self.assertIsInstance(self.doxyaml, cfg_base.ConfigBase)

View File

@ -12,17 +12,20 @@
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import mock
import os
import dox.config.base as cfg_base
from dox.config import tox_ini
from dox.tests import base
class TestImages(base.TestCase):
class TestToxIni(base.TestCase):
def setUp(self):
super(TestImages, self).setUp()
super(TestToxIni, self).setUp()
self.toxini = tox_ini.ToxIni()
self.toxini.tox_ini_file = os.path.join(base.SAMPLEDIR,
@ -34,6 +37,9 @@ class TestImages(base.TestCase):
self.assertEqual(tox_ini.get_tox_ini(),
tox_ini_new)
def test_base_class(self):
self.assertIsInstance(self.toxini, cfg_base.ConfigBase)
def test_exists_ini_file(self):
self.assertTrue(self.toxini.exists())

View File

@ -0,0 +1,28 @@
# -*- coding: utf-8 -*-
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import dox.config.base as cfg_base
from dox.config import travis_yaml
from dox.tests import base
class TestTravisYaml(base.TestCase):
def setUp(self):
super(TestTravisYaml, self).setUp()
self.travisyaml = travis_yaml.TravisYaml()
def test_base_class(self):
self.assertIsInstance(self.travisyaml, cfg_base.ConfigBase)

View File

@ -2,3 +2,4 @@ pbr>=0.5.21,<1.0
argparse
PyYAML
six