Revision: 143
Author:   janne.t.harkonen
Date:     Wed Aug 22 21:55:10 2012
Log:      Add Configuration class
http://code.google.com/p/robotframework-sshlibrary/source/detail?r=143

Added:
 /trunk/src/SSHLibrary/config.py
 /trunk/utest/test_config.py

=======================================
--- /dev/null
+++ /trunk/src/SSHLibrary/config.py     Wed Aug 22 21:55:10 2012
@@ -0,0 +1,106 @@
+from robot import utils
+
+
+class ConfigurationException(Exception):
+ """Raised when creating, updating or accessing a Configuration entry fails."""
+    pass
+
+
+class Configuration(object):
+    """A simple configuration class.
+
+ Configuration is defined with keyword arguments, in which the value must + be an instance of :py:class:`Entry`. Different subclasses of `Entry` can
+    be used to handle common types and conversions.
+
+    Example::
+
+        cfg = Configuration(name=StringEntry('initial'),
+                            age=IntegerEntry('42'))
+        assert cfg.name == initial
+        assert cfg.age == 42
+        cfg.update(name='John Doe')
+        assert cfg.name == 'John Doe'
+    """
+
+    def __init__(self, **config):
+        self._config = config
+
+    def update(self, **config):
+        """Update configuration entries. See `__init__` for an example."""
+        for name in config:
+            self._config[name].set(config[name])
+
+    def __getattr__(self, name):
+        if name in self._config:
+            return self._config[name].value
+        msg = "Configuration parameter '%s' is not defined" % name
+        raise ConfigurationException(msg)
+
+
+class Entry(object):
+    """A base class for values stored in :py:class:`Configuration`.
+
+        :param:`initial` the initial value of this entry.
+    """
+
+    def __init__(self, initial=None):
+        self._value = self._create_value(initial)
+
+    @property
+    def value(self):
+        return self._value
+
+    def set(self, value):
+        self._value = self._parse_value(value)
+
+    def _create_value(self, value):
+        if value is None:
+            return None
+        return self._parse_value(value)
+
+
+class StringEntry(Entry):
+    """String value to be stored in :py:class:`Configuration`."""
+    def _parse_value(self, value):
+        return value
+
+
+class IntegerEntry(Entry):
+    """Integer value to be stored in stored in :py:class:`Configuration`.
+
+    Given value is converted to string using `int()`.
+    """
+    def _parse_value(self, value):
+        return int(value)
+
+
+class TimeEntry(Entry):
+    """Time string to be stored in :py:class:`Configuration`.
+
+    Given time string will be converted to seconds using
+    :py:func:`robot.utils.timestr_to_secs`.
+    """
+    def _parse_value(self, value):
+        return utils.timestr_to_secs(value) if value else None
+
+
+class LogLevelEntry(Entry):
+    """Log level to be stored in :py:class:`Configuration`.
+
+    Given string must be on of 'TRACE', 'DEBUG', 'INFO' or 'WARN', case
+    insensitively.
+    """
+    def _parse_value(self, value):
+        return value.upper()
+
+
+class NewlineEntry(Entry):
+    """New line sequence to be stored in :py:class:`Configuration`.
+
+    Following conversion are performed on the given string:
+        * 'LF' -> '\n'
+        * 'CR' -> '\r'
+    """
+    def _parse_value(self, value):
+        return value.upper().replace('LF', '\n').replace('CR', '\r')
=======================================
--- /dev/null
+++ /trunk/utest/test_config.py Wed Aug 22 21:55:10 2012
@@ -0,0 +1,61 @@
+import unittest
+from SSHLibrary.config import (Configuration, StringEntry, TimeEntry,
+    IntegerEntry, LogLevelEntry, NewlineEntry, ConfigurationException)
+
+
+STRING_VALUE = 'some value'
+INTEGER_STRING = '42'
+INTEGER_VALUE = 42
+TIME_STRING = '3 minutes 25 seconds'
+TIME = 205
+
+
+class TestConfigurationEntries(unittest.TestCase):
+
+    def test_creating_with_initial_value(self):
+        entry = StringEntry(initial=STRING_VALUE)
+        self._assert_entry(entry, STRING_VALUE)
+
+    def test_setting_value(self):
+        entry = StringEntry()
+        entry.set(STRING_VALUE)
+        self._assert_entry(entry, STRING_VALUE)
+
+    def test_integer_entry(self):
+        entry = IntegerEntry(INTEGER_STRING)
+        self._assert_entry(entry, INTEGER_VALUE)
+
+    def test_time_entry(self):
+        entry = TimeEntry(TIME_STRING)
+        self._assert_entry(entry, 205)
+
+    def test_log_level_entry(self):
+        entry = LogLevelEntry('debug')
+        self._assert_entry(entry, 'DEBUG')
+
+    def test_newline_entry(self):
+        entry = NewlineEntry('crlf')
+        self._assert_entry(entry, '\r\n')
+
+    def _assert_entry(self, entry, expected_value):
+        self.assertEquals(entry.value, expected_value)
+
+
+class TestConfiguration(unittest.TestCase):
+
+    def test_creating_configuration(self):
+        cfg = Configuration(name=StringEntry(STRING_VALUE))
+        self.assertEquals(cfg.name, STRING_VALUE)
+
+    def test_updating_configuration_values(self):
+        cfg = Configuration(entry=StringEntry('other value'))
+        cfg.update(entry=STRING_VALUE)
+        self.assertEquals(cfg.entry, STRING_VALUE)
+
+    def test_missing_config_item(self):
+        self.assertRaises(ConfigurationException,
+                lambda: Configuration().missing)
+
+
+if __name__ == '__main__':
+    unittest.main()

Reply via email to