Author: jprantan
Date: Wed May 20 03:49:40 2009
New Revision: 64

Added:
   trunk/utest/test_settings_utils.py
Modified:
   trunk/src/mabot/settings/__init__.py
   trunk/src/mabot/settings/utils.py
   trunk/utest/test_settings.py

Log:
Improved writing settings. Now it supports also i.e. unicode.

Modified: trunk/src/mabot/settings/__init__.py
==============================================================================
--- trunk/src/mabot/settings/__init__.py        (original)
+++ trunk/src/mabot/settings/__init__.py        Wed May 20 03:49:40 2009
@@ -19,16 +19,14 @@
 from types import ListType
 from types import StringType

-from utils import get_settings_file
-
-USER_SETTINGS_FILE = get_settings_path('mabotsettings.py')
-COMPILED_USER_SETTINGS_FILE = USER_SETTINGS_FILE + 'c'
-sys.path.append(os.path.dirname(USER_SETTINGS_FILE))
+import utils

+USER_SETTINGS_FILE = utils.get_settings_path('mabotsettings.py')

 class Settings:

     def __init__(self):
+        self._user_settings = utils.SettingsIO(USER_SETTINGS_FILE)
         self.load_settings()

     def update(self, new_settings, suite):
@@ -41,34 +39,14 @@
         self.save_settings()

     def save_settings(self):
-        self._remove_user_settings()
-        try:
-            settings_file = open(USER_SETTINGS_FILE, 'w')
-            settings_file.write(str(self))
-        finally:
-            settings_file.close()
-
-    def __str__(self):
-        data = 'settings = {\n'
-        for key, value in self.settings.items():
- data += ' "%s": %s,\n' % (key, self._value_to_str(value))
-        return data + '           }\n'
-
-    def _value_to_str(self, value):
-        if type(value) is StringType:
-            return '"""%s"""' % (value)
-        elif type(value) is ListType:
-            string_values = [self._value_to_str(item) for item in value ]
-            return "[ %s ]" % (', '.join(string_values))
-        return value
-
+        self._user_settings.write_settings(self.settings)
+
     def __getitem__(self, name):
         return self.settings[name]

     def __setitem__(self, name, value):
         self.settings[name] = value

-
     def load_settings(self):
         from defaultsettings import default_settings
         self.settings = default_settings.copy()
@@ -79,21 +57,17 @@
         except (ImportError, KeyError):
             pass
         try:
-            import mabotsettings
-            reload(mabotsettings)
-            for key in mabotsettings.settings.keys():
-                self.settings[key] = mabotsettings.settings[key]
-        except (ImportError, KeyError):
+            user_settings = self._user_settings.read_settings()
+        except (utils.MissingSettings, utils.InvalidSettings):
             pass
+        else:
+            for key in user_settings.keys():
+                self.settings[key] = user_settings[key]
+

     def restore_settings(self):
-        self._remove_user_settings()
+        self._user_settings.remove_settings()
         self.load_settings()

-    def _remove_user_settings(self):
-        if os.path.exists(USER_SETTINGS_FILE):
-            os.remove(USER_SETTINGS_FILE)
-        if os.path.exists(COMPILED_USER_SETTINGS_FILE):
-            os.remove(COMPILED_USER_SETTINGS_FILE)

 SETTINGS = Settings()

Modified: trunk/src/mabot/settings/utils.py
==============================================================================
--- trunk/src/mabot/settings/utils.py   (original)
+++ trunk/src/mabot/settings/utils.py   Wed May 20 03:49:40 2009
@@ -1,4 +1,8 @@
 import os
+from pprint import pprint
+import sys
+
+
 if os.name == 'nt':
SETTINGS_DIRECTORY = os.path.join(os.environ['APPDATA'], 'RobotFramework')
 else:
@@ -12,3 +16,66 @@
     if not file_name:
         return SETTINGS_DIRECTORY
     return os.path.join(SETTINGS_DIRECTORY, file_name)
+
+
+class MissingSettings(Exception):
+    """ Used when setting file does not exist."""
+
+
+class InvalidSettings(Exception):
+ """ Used when setting file exists, but it is not a valid Python file."""
+
+
+class SettingsIO:
+
+    def __init__(self, path):
+        self.path = path
+        sys.path.insert(0, os.path.dirname(self.path))
+        self._settings_module_name = os.path.basename(self.path)[:-3]
+
+
+    def write_settings(self, settings_dict):
+        """ Writes given settings dict to settings file.
+
+        Setting names (keys) should not contain spaces.
+        """
+        self._validate_setting_names(settings_dict)
+ # settings can be read from old pyc if reading happens in the same second
+        self.remove_settings()
+        out = open(self.path, 'w')
+        for key in settings_dict.keys():
+            out.write('%s = ' % key)
+            pprint(settings_dict[key], out)
+        out.close()
+
+    def remove_settings(self):
+        for path in [self.path, '%sc' % self.path]:
+            if os.path.exists(path):
+                os.remove(path)
+
+    def _validate_setting_names(self, settings_dict):
+        for name in settings_dict.keys():
+            if ' ' in name:
+                msg = "Setting name '%s' contains space." % (name)
+                raise InvalidSettings(msg)
+
+    def read_settings(self):
+        settings_module = self._load_settings_module()
+        settings = {}
+        for item in dir(settings_module):
+            if not item.startswith('_'):
+                settings[item] = getattr(settings_module, item)
+        return settings
+
+    def _load_settings_module(self):
+        try:
+            settings_module = __import__(self._settings_module_name)
+            settings_module = reload(settings_module)
+        except ImportError:
+            message = "Could not import settings file '%s'" % self.path
+            raise MissingSettings(message)
+        except SyntaxError, e:
+            message = "Settings file '%s' is not a valid Python file.\n%s"
+            message = message % (self.path, e)
+            raise InvalidSettings(message)
+        return settings_module

Modified: trunk/utest/test_settings.py
==============================================================================
--- trunk/utest/test_settings.py        (original)
+++ trunk/utest/test_settings.py        Wed May 20 03:49:40 2009
@@ -19,7 +19,6 @@
 from mabot.settings import Settings
 from mabot.settings.defaultsettings import default_settings
 from mabot.settings import USER_SETTINGS_FILE
-from mabot.settings import COMPILED_USER_SETTINGS_FILE


 class TestSettings(unittest.TestCase):
@@ -29,10 +28,9 @@
         self.settings = Settings()

     def _remove_settings(self):
-        if os.path.exists(USER_SETTINGS_FILE):
-            os.remove(USER_SETTINGS_FILE)
-        if os.path.exists(COMPILED_USER_SETTINGS_FILE):
-            os.remove(COMPILED_USER_SETTINGS_FILE)
+        for path in [USER_SETTINGS_FILE, '%sc' % USER_SETTINGS_FILE ]:
+            if os.path.exists(path):
+                os.remove(path)

     def tearDown(self):
         self._remove_settings()
@@ -47,23 +45,21 @@

     def test_saving_with_default_settings(self):
         self.settings.save_settings()
-        settings = self._import_settings()
-        reload(settings)
-        self.assertEquals(self.settings.settings, settings.settings)
+        self.assertEquals(self.settings.settings,
+                          self._read_settings_from_file())

     def test_saving_with_modified_settings(self):
         self.settings.save_settings()
-        settings = self._import_settings()
-        reload(settings)
-        self.assertEquals(self.settings.settings, settings.settings)
+        settings = self._read_settings_from_file()
+        self.assertEquals(self.settings.settings, settings)
         self.settings.settings["default_message"] = "My message"
         self.settings.settings["exclude"] = ["a", "b", "c"]
         self.settings.save_settings()
-        reload(settings)
-        self.assertEquals(self.settings.settings, settings.settings)
+        settings = self._read_settings_from_file()
+        self.assertEquals(self.settings.settings, settings)
self.assertEquals(self.settings.settings["exclude"], ["a", "b", "c"])
         self.settings.load_settings()
-        self.assertEquals(self.settings.settings, settings.settings)
+        self.assertEquals(self.settings.settings, settings)

     def test_reverting_default_settings(self):
         defaults = self.settings.settings.copy()
@@ -76,13 +72,14 @@
         self.assertEquals(self.settings.settings, defaults)
         self.assertFalse(os.path.exists(USER_SETTINGS_FILE))

-    def _import_settings(self):
-        if os.sep == '\\':
-            from mabot.settings import settings
-        else:
-            import settings
-            return settings
-
+    def _read_settings_from_file(self):
+        import mabotsettings
+        reload(mabotsettings)
+        settings = {}
+        for item in dir(mabotsettings):
+            if not item.startswith('_'):
+                settings[item] = getattr(mabotsettings, item)
+        return settings

 if __name__ == "__main__":
     unittest.main()

Added: trunk/utest/test_settings_utils.py
==============================================================================
--- (empty file)
+++ trunk/utest/test_settings_utils.py  Wed May 20 03:49:40 2009
@@ -0,0 +1,100 @@
+#  Copyright 2008 Nokia Siemens Networks Oyj
+#
+#  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 os
+import sys
+import unittest
+
+from mabot.settings.utils import SettingsIO, MissingSettings, InvalidSettings
+
+
+class TestSettingsIO(unittest.TestCase):
+
+    def setUp(self):
+ self.settings_file = os.path.join(os.path.dirname(__file__), 'data',
+                                          'testsettings.py')
+        self.settings = SettingsIO(self.settings_file)
+
+    def tearDown(self):
+        sys.path.pop(0)
+        self.settings.remove_settings()
+
+ # Note: This tests needs to be first (aaa) before setting module is imported.
+    def test_aaa_no_settings_exists(self):
+        self.assertRaises(MissingSettings, self.settings.read_settings)
+
+    def test_settings_does_not_exist_anymore(self):
+        self._test_settings_io({'string':'value'})
+        self.settings.remove_settings()
+        self.assertRaises(MissingSettings, self.settings.read_settings)
+
+    def test_invalid_settings_exists(self):
+        f = open(self.settings_file, 'w')
+        f.write('foo = invalid syntax::')
+        f.close()
+        self.assertRaises(InvalidSettings, self.settings.read_settings)
+
+    def test_setting_name_with_spaces(self):
+        self.assertRaises(InvalidSettings, self._test_settings_io,
+                          {'setting name spaces': 'value'})
+
+    def test_writing_string_setting(self):
+        self._test_settings_io({'string':'value'})
+
+    def test_writing_unicode_setting(self):
+ self._test_settings_io({'unicode_string':u'non-ascii character \xe4'})
+
+    def test_writing_list_setting(self):
+        self._test_settings_io({'unicode_string': [1, 'string',
+ u'non-ascii character \xe4']})
+
+    def test_writing_dictionary_setting(self):
+        self._test_settings_io({'dictionary': {'a': 1, 'b': 2, 'c': 3}})
+
+    def test_writing_none_setting(self):
+        self._test_settings_io({'none': None})
+
+    def test_writing_boolean_setting(self):
+        self._test_settings_io({'boolean': True})
+
+    def test_writing_multiline_string_setting(self):
+        multiline = u"""Multi line string
+with non-ascii chars \xe4
+and quotes "foo" 'bar'
+and even triple quotes \"\"\" '''
+"""
+        self._test_settings_io({'multiline': multiline})
+
+    def test_multiple_settings(self):
+        multiline = u"""Multi line string
+with non-ascii chars \xe4
+and quotes "foo" 'bar'
+and even triple quotes \"\"\" '''
+"""
+        self._test_settings_io({'multiline': multiline, 'string': u'some',
+                                'bool': False, 'int':1, 'float':2.4})
+
+    def test_updating_setting(self):
+        self._test_settings_io({'string': u'some', 'bool': False, 'int':1})
+ self.settings.write_settings({'string': u'new', 'bool': True, 'int':1})
+        self._test_settings_io({'string': u'new', 'bool': False, 'int':4})
+
+    def _test_settings_io(self, expected):
+        self.settings.write_settings(expected)
+        actual = self.settings.read_settings()
+        for key in expected.keys():
+            self.assertEqual(expected[key], actual[key])
+
+if __name__ == "__main__":
+    unittest.main()
\ No newline at end of file

Reply via email to