Source code for repobuddy.client_info
#
# Copyright (C) 2013 Ash (Tuxdude) <tuxdude.github@gmail.com>
#
# This file is part of repobuddy.
#
# 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.
#
"""
.. module: repobuddy.client_info
:platform: Unix, Windows
:synopsis: Parses/Stores/Retrieves client specific configuration.
.. moduleauthor: Ash <tuxdude.github@gmail.com>
"""
import sys as _sys
if _sys.version_info >= (3, 0):
import configparser as _configparser # pylint: disable=F0401
else:
import ConfigParser as _configparser # pylint: disable=F0401
from repobuddy.utils import RepoBuddyBaseException
[docs]class ClientInfoError(RepoBuddyBaseException):
"""Exception raised by :class:`ClientInfo`."""
[docs] def __init__(self, error_str):
"""Initializer.
:param error_str: The error string to store in the exception.
:type error_str: str
"""
super(ClientInfoError, self).__init__(error_str)
return
[docs]class ClientInfo(object):
"""Parses/Stores/Retrieves the client configuration."""
def _validate_config(self):
"""Validate the config.
Verifies that ``client_spec`` and ``manifest`` options exist in the
ClientInfo instance.
:returns: None
"""
self.get_client_spec()
self.get_manifest()
return
def _get_config(self, section, option):
"""Get the configuration value.
:param section: The name of the section in the config file.
:type section: str
:param option: The name of the option in the config file.
:type option: str
:returns: The value of the option under the section.
:raises: :exc:`ClientInfoError` when the section or the option or both
do not exist.
"""
try:
return self._config.get(section, option)
except (_configparser.NoOptionError,
_configparser.NoSectionError) as err:
raise ClientInfoError('Error: ' + str(err))
return
def _set_config(self, section, option, value):
"""Set the configuration value.
:param section: The name of the section in the config file.
:type section: str
:param option: The name of the option in the config file.
:type option: str
:param value: The new value for the option under the section.
:type value: str
:returns: None
:raises: :exc:`ClientInfoError` when the section does not exist.
"""
try:
self._config.set(section, option, value)
except _configparser.NoSectionError as err:
raise ClientInfoError('Error: ' + str(err))
return
[docs] def __init__(self, config_file_name=None):
"""Initializer.
:param config_file_name: The name of the config file. If
``config_file_name`` is set to ``None``, the configuration is
just stored in-memory until :meth:`write()` is invoked. Instead
if ``config_file_name`` **is** specified, the config file is
opened, parsed and the instance represents the state of the config
file.
:type config_file_name: str
:raises: :exc:`ClientInfoError` when ``config_file_name`` is not
``None`` and any of the following conditions are met:
- Failed to open the config file.
- Parsing errors have been detected.
- Validating the config failed.
"""
if not config_file_name is None:
try:
with open(config_file_name, 'r') as file_handle:
self._config = _configparser.RawConfigParser()
try:
self._config.readfp(file_handle)
except _configparser.ParsingError as err:
raise ClientInfoError(
'Error: Parsing config failed => ' + str(err))
except IOError as err:
raise ClientInfoError('Error: ' + str(err))
self._validate_config()
self._config_file_name = config_file_name
else:
self._config = _configparser.RawConfigParser()
self._config.add_section('RepoBuddyClientInfo')
self._config_file_name = None
return
[docs] def set_client_spec(self, client_spec_name):
"""Set the client_spec in the config.
:param client_spec_name: The value for ``client_spec`` in the config.
:type client_spec_name: str
:returns: None
:raises: :exc:`ClientInfoError` if the config does not already have the
``RepoBuddyClientInfo`` section.
"""
self._set_config('RepoBuddyClientInfo',
'client_spec',
client_spec_name)
return
[docs] def set_manifest(self, manifest_xml):
"""Set the ``manifest`` in the config.
:param manifest_xml: The value for ``manifest`` in the config.
:type manifest_xml: str
:returns: None
:raises: :exc:`ClientInfoError` if the config does not have the
``RepoBuddyClientInfo`` section.
"""
self._set_config('RepoBuddyClientInfo', 'manifest', manifest_xml)
return
[docs] def get_client_spec(self):
"""Get the value of ``client_spec`` in the config.
:returns: The value of ``client_spec`` in the config.
:rtype: str
:raises: :exc:`ClientInfoError` if the config does not have the
``client_spec`` option.
"""
return self._get_config('RepoBuddyClientInfo', 'client_spec')
[docs] def get_manifest(self):
"""Get the value of ``manifest`` in the config.
:returns: The value of ``manifest`` in the config.
:rtype: str
:raises: :exc:`ClientInfoError` if the config does not have the
``manifest`` option.
"""
return self._get_config('RepoBuddyClientInfo', 'manifest')
[docs] def write(self, file_name=None):
"""Write the config to a file.
If ``file_name`` is set to ``None``, the filename passed during the
class initialization is used instead. If there was a file name
specified during both initialization, as well as in the parameter
``file_name``, this method's parameter takes precedece, and the file
name specififed during initialization remains unmodified.
:param file_name: The name of the file to write the config into.
:type file_name: str
:returns: None
:raises: :exc:`ClientInfoError` when any of the following conditions
are met:
- ``file_name`` parameter is ``None`` and no file name was
provided during initialization.
- validation of the config failed.
- writing the config to the file failed.
"""
# If file_name parameter is empty, check if the file name was
# specified in the constructor
if file_name is None:
if self._config_file_name is None:
raise ClientInfoError(
'Error: file_name parameter cannot be empty')
else:
file_name = self._config_file_name
# Verify that the config is valid
try:
self._validate_config()
except ClientInfoError as err:
raise ClientInfoError(
'Error: Missing options. ' + str(err).split('Error: ')[1])
try:
with open(file_name, 'w') as config_file:
self._config.write(config_file)
except IOError as err:
raise ClientInfoError('Error: ' + str(err))
return