diff --git a/src/octoprint/plugin/__init__.py b/src/octoprint/plugin/__init__.py index 9cc49b41..4b8beaf5 100644 --- a/src/octoprint/plugin/__init__.py +++ b/src/octoprint/plugin/__init__.py @@ -117,40 +117,40 @@ class PluginSettings(object): ) self.deprecated_access_methods = dict(getInt="get_int", getFloat="get_float", getBoolean="get_boolean", setInt="set_int", setFloat="set_float", setBoolean="set_boolean") - def global_get(self, path): - return self.settings.get(path) + def global_get(self, path, **kwargs): + return self.settings.get(path, **kwargs) globalGet = deprecated("globalGet has been renamed to global_get")(global_get) - def global_get_int(self, path): - return self.settings.getInt(path) + def global_get_int(self, path, **kwargs): + return self.settings.getInt(path, **kwargs) globalGetInt = deprecated("globalGetInt has been renamed to global_get_int")(global_get_int) - def global_get_float(self, path): - return self.settings.getFloat(path) + def global_get_float(self, path, **kwargs): + return self.settings.getFloat(path, **kwargs) globalGetFloat = deprecated("globalGetFloat has been renamed to global_get_float")(global_get_float) - def global_get_boolean(self, path): - return self.settings.getBoolean(path) + def global_get_boolean(self, path, **kwargs): + return self.settings.getBoolean(path, **kwargs) globalGetBoolean = deprecated("globalGetBoolean has been renamed to global_get_boolean")(global_get_boolean) - def global_set(self, path, value): - self.settings.set(path, value) + def global_set(self, path, value, **kwargs): + self.settings.set(path, value, **kwargs) globalSet = deprecated("globalSet has been renamed to global_set")(global_set) - def global_set_int(self, path, value): - self.settings.setInt(path, value) + def global_set_int(self, path, value, **kwargs): + self.settings.setInt(path, value, **kwargs) globalSetInt = deprecated("globalSetInt has been renamed to global_set_int")(global_set_int) - def global_set_float(self, path, value): - self.settings.setFloat(path, value) + def global_set_float(self, path, value, **kwargs): + self.settings.setFloat(path, value, **kwargs) globalSetFloat = deprecated("globalSetFloat has been renamed to global_set_float")(global_set_float) - def global_set_boolean(self, path, value): - self.settings.setBoolean(path, value) + def global_set_boolean(self, path, value, **kwargs): + self.settings.setBoolean(path, value, **kwargs) globalSetBoolean = deprecated("globalSetBoolean has been renamed to global_set_boolean")(global_set_boolean) - def global_get_basefolder(self, folder_type): - return self.settings.getBaseFolder(folder_type) + def global_get_basefolder(self, folder_type, **kwargs): + return self.settings.getBaseFolder(folder_type, **kwargs) globalGetBaseFolder = deprecated("globalGetBaseFolder has been renamed to global_get_basefolder")(global_get_basefolder) def get_plugin_logfile_path(self, postfix=None): @@ -176,6 +176,10 @@ class PluginSettings(object): if decorator is not None: orig_func = decorator(orig_func) - return lambda *args, **kwargs: orig_func(*args_mapper(args), **kwargs_mapper(kwargs)) + def _func(*args, **kwargs): + return orig_func(*args_mapper(args), **kwargs_mapper(kwargs)) + _func.__name__ = item + + return _func return getattr(self.settings, item) diff --git a/tests/plugin/test_settings.py b/tests/plugin/test_settings.py new file mode 100644 index 00000000..67b3d2b1 --- /dev/null +++ b/tests/plugin/test_settings.py @@ -0,0 +1,258 @@ +# coding=utf-8 +from __future__ import absolute_import + +__author__ = "Gina Häußge " +__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' +__copyright__ = "Copyright (C) 2014 The OctoPrint Project - Released under terms of the AGPLv3 License" + + +import unittest +import mock +import warnings + +from ddt import ddt, unpack, data + +import octoprint.plugin +import octoprint.settings + +@ddt +class SettingsTestCase(unittest.TestCase): + + def setUp(self): + warnings.simplefilter("always") + + self.plugin_key = "test_plugin" + + self.settings = mock.create_autospec(octoprint.settings.Settings) + + self.defaults = dict( + some_raw_key="some_raw_value", + some_int_key=1, + some_float_key=2.5, + some_boolean_key=True, + ) + + self.plugin_settings = octoprint.plugin.PluginSettings(self.settings, self.plugin_key, defaults=self.defaults) + + @data( + ("get", (["some_raw_key",],), dict(), "get"), + ("get", (["some_raw_key",],), dict(merged=True), "get"), + ("get", (["some_raw_key",],), dict(asdict=True), "get"), + ("get", (["some_raw_key",],), dict(merged=True, asdict=True), "get"), + ("get_int", (["some_int_key,"],), dict(), "getInt"), + ("get_float", (["some_float_key"],), dict(), "getFloat"), + ("get_boolean", (["some_boolean_key",],), dict(), "getBoolean"), + ) + @unpack + def test_forwarded_getter(self, getter, getter_args, getter_kwargs, forwarded): + method_under_test = getattr(self.plugin_settings, getter) + self.assertTrue(callable(method_under_test)) + + method_under_test(*getter_args, **getter_kwargs) + + forwarded_method = getattr(self.settings, forwarded) + forwarded_args = (["plugins", self.plugin_key] + getter_args[0],) + forwarded_kwargs = getter_kwargs + forwarded_kwargs.update(dict(defaults=dict(plugins=dict(test_plugin=self.defaults)))) + forwarded_method.assert_called_once_with(*forwarded_args, **forwarded_kwargs) + + @data( + ("global_get", (["some_raw_key"],), dict(), "get"), + ("global_get", (["some_raw_key"],), dict(merged=True), "get"), + ("global_get", (["some_raw_key"],), dict(asdict=True), "get"), + ("global_get", (["some_raw_key"],), dict(merged=True, asdict=True), "get"), + ("global_get_int", (["some_int_key"],), dict(), "getInt"), + ("global_get_float", (["some_float_key"],), dict(), "getFloat"), + ("global_get_boolean", (["some_boolean_key"],), dict(), "getBoolean") + ) + @unpack + def test_global_getter(self, getter, getter_args, getter_kwargs, forwarded): + method_under_test = getattr(self.plugin_settings, getter) + self.assertTrue(callable(method_under_test)) + + method_under_test(*getter_args, **getter_kwargs) + + forwarded_method = getattr(self.settings, forwarded) + forwarded_method.assert_called_once_with(*getter_args, **getter_kwargs) + + @data( + ("getInt", "get_int", "getInt"), + ("getFloat", "get_float", "getFloat"), + ("getBoolean", "get_boolean", "getBoolean"), + ) + @unpack + def test_deprecated_forwarded_getter(self, deprecated, current, forwarded): + with warnings.catch_warnings(record=True) as w: + called_method = getattr(self.settings, forwarded) + called_method.__name__ = forwarded + + method = getattr(self.plugin_settings, deprecated) + self.assertTrue(callable(method)) + method(["some_raw_key"]) + + called_method.assert_called_once_with(["plugins", self.plugin_key, "some_raw_key"], defaults=dict(plugins=dict(test_plugin=self.defaults))) + + self.assertEquals(1, len(w)) + self.assertTrue(issubclass(w[-1].category, DeprecationWarning)) + self.assertTrue("{old} has been renamed to {new}".format(old=deprecated, new=current) in (w[-1].message)) + + @data( + ("globalGet", "global_get", "get"), + ("globalGetInt", "global_get_int", "getInt"), + ("globalGetFloat", "global_get_float", "getFloat"), + ("globalGetBoolean", "global_get_boolean", "getBoolean") + ) + @unpack + def test_deprecated_global_getter(self, deprecated, current, forwarded): + with warnings.catch_warnings(record=True) as w: + called_method = getattr(self.settings, forwarded) + called_method.__name__ = forwarded + + method = getattr(self.plugin_settings, deprecated) + self.assertTrue(callable(method)) + method(["some_raw_key"]) + + called_method.assert_called_once_with(["some_raw_key",]) + + self.assertEquals(1, len(w)) + self.assertTrue(issubclass(w[-1].category, DeprecationWarning)) + self.assertTrue("{old} has been renamed to {new}".format(old=deprecated, new=current) in (w[-1].message)) + + @data( + ("set", (["some_raw_key",], "some_value"), dict(), "set"), + ("set", (["some_raw_key",], "some_value"), dict(force=True), "set"), + ("set_int", (["some_int_key",], 23), dict(), "setInt"), + ("set_int", (["some_int_key",], 23), dict(force=True), "setInt"), + ("set_float", (["some_float_key",], 2.3), dict(), "setFloat"), + ("set_float", (["some_float_key",], 2.3), dict(force=True), "setFloat"), + ("set_boolean", (["some_boolean_key",], True), dict(), "setBoolean"), + ("set_boolean", (["some_boolean_key",], True), dict(force=True), "setBoolean"), + ) + @unpack + def test_forwarded_setter(self, setter, setter_args, setter_kwargs, forwarded): + method_under_test = getattr(self.plugin_settings, setter) + self.assertTrue(callable(method_under_test)) + + method_under_test(*setter_args, **setter_kwargs) + + forwarded_method = getattr(self.settings, forwarded) + forwarded_args = (["plugins", self.plugin_key] + setter_args[0], setter_args[1]) + forwarded_kwargs = setter_kwargs + forwarded_kwargs.update(dict(defaults=dict(plugins=dict(test_plugin=self.defaults)))) + forwarded_method.assert_called_once_with(*forwarded_args, **forwarded_kwargs) + + @data( + ("global_set", (["some_raw_key",], "some_value"), dict(), "set"), + ("global_set", (["some_raw_key",], "some_value"), dict(force=True), "set"), + ("global_set_int", (["some_int_key",], 23), dict(), "setInt"), + ("global_set_int", (["some_int_key",], 23), dict(force=True), "setInt"), + ("global_set_float", (["some_float_key",], 2.3), dict(), "setFloat"), + ("global_set_float", (["some_float_key",], 2.3), dict(force=True), "setFloat"), + ("global_set_boolean", (["some_boolean_key",], True), dict(), "setBoolean"), + ("global_set_boolean", (["some_boolean_key",], True), dict(force=True), "setBoolean"), + ) + @unpack + def test_global_setter(self, setter, setter_args, setter_kwargs, forwarded): + method_under_test = getattr(self.plugin_settings, setter) + self.assertTrue(callable(method_under_test)) + + method_under_test(*setter_args, **setter_kwargs) + + forwarded_method = getattr(self.settings, forwarded) + forwarded_method.assert_called_once_with(*setter_args, **setter_kwargs) + + @data( + ("setInt", "set_int", "setInt", 1), + ("setFloat", "set_float", "setFloat", 2.5), + ("setBoolean", "set_boolean", "setBoolean", True) + ) + @unpack + def test_deprecated_forwarded_setter(self, deprecated, current, forwarded, value): + with warnings.catch_warnings(record=True) as w: + called_method = getattr(self.settings, forwarded) + called_method.__name__ = forwarded + + method = getattr(self.plugin_settings, deprecated) + self.assertTrue(callable(method)) + method(["some_raw_key"], value) + + called_method.assert_called_once_with(["plugins", self.plugin_key, "some_raw_key"], value, defaults=dict(plugins=dict(test_plugin=self.defaults))) + + self.assertEquals(1, len(w)) + self.assertTrue(issubclass(w[-1].category, DeprecationWarning)) + self.assertTrue("{old} has been renamed to {new}".format(old=deprecated, new=current) in (w[-1].message)) + + @data( + ("globalSet", "global_set", "set", "some_value"), + ("globalSetInt", "global_set_int", "setInt", 1), + ("globalSetFloat", "global_set_float", "setFloat", 2.5), + ("globalSetBoolean", "global_set_boolean", "setBoolean", True) + ) + @unpack + def test_deprecated_global_setter(self, deprecated, current, forwarded, value): + with warnings.catch_warnings(record=True) as w: + called_method = getattr(self.settings, forwarded) + called_method.__name__ = forwarded + + method = getattr(self.plugin_settings, deprecated) + self.assertTrue(callable(method)) + method(["some_raw_key"], value) + + called_method.assert_called_once_with(["some_raw_key"], value) + + self.assertEquals(1, len(w)) + self.assertTrue(issubclass(w[-1].category, DeprecationWarning)) + self.assertTrue("{old} has been renamed to {new}".format(old=deprecated, new=current) in (w[-1].message)) + + def test_global_get_basefolder(self): + self.plugin_settings.global_get_basefolder("some_folder") + self.settings.getBaseFolder.assert_called_once_with("some_folder") + + def test_deprecated_global_get_basefolder(self): + with warnings.catch_warnings(record=True) as w: + self.plugin_settings.globalGetBaseFolder("some_folder") + self.settings.getBaseFolder.assert_called_once_with("some_folder") + + self.assertEquals(1, len(w)) + self.assertTrue(issubclass(w[-1].category, DeprecationWarning)) + self.assertTrue("globalGetBaseFolder has been renamed to global_get_basefolder" in (w[-1].message)) + + def test_logfile_path(self): + import os + + self.settings.getBaseFolder.return_value = "/some/folder" + + path = self.plugin_settings.get_plugin_logfile_path() + + self.settings.getBaseFolder.assert_called_once_with("logs") + self.assertEquals("/some/folder/plugin_{key}.log".format(key=self.plugin_key), path.replace(os.sep, "/")) + + def test_logfile_path_with_postfix(self): + import os + + self.settings.getBaseFolder.return_value = "/some/folder" + + path = self.plugin_settings.get_plugin_logfile_path(postfix="mypostfix") + + self.settings.getBaseFolder.assert_called_once_with("logs") + self.assertEquals("/some/folder/plugin_{key}_mypostfix.log".format(key=self.plugin_key), path.replace(os.sep, "/")) + + def test_deprecated_logfile_path(self): + import os + + with warnings.catch_warnings(record=True) as w: + self.settings.getBaseFolder.return_value = "/some/folder" + path = self.plugin_settings.getPluginLogfilePath() + + self.settings.getBaseFolder.assert_called_once_with("logs") + self.assertEquals("/some/folder/plugin_{key}.log".format(key=self.plugin_key), path.replace(os.sep, "/")) + + self.assertEquals(1, len(w)) + self.assertTrue(issubclass(w[-1].category, DeprecationWarning)) + self.assertTrue("getPluginLogfilePath has been renamed to get_plugin_logfile_path" in (w[-1].message)) + + def test_unhandled_method(self): + try: + self.plugin_settings.some_method("some_parameter") + except AttributeError as e: + self.assertTrue("Mock object has no attribute 'some_method'" in str(e)) \ No newline at end of file