summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--openstack/common/cliutils.py66
-rw-r--r--tests/unit/test_cliutils.py398
2 files changed, 464 insertions, 0 deletions
diff --git a/openstack/common/cliutils.py b/openstack/common/cliutils.py
new file mode 100644
index 0000000..8f4dc44
--- /dev/null
+++ b/openstack/common/cliutils.py
@@ -0,0 +1,66 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 Red Hat, Inc.
+#
+# 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 inspect
+import string
+
+
+class MissingArgs(Exception):
+
+ def __init__(self, missing):
+ self.missing = missing
+
+ def __str__(self):
+ if len(self.missing) == 1:
+ return ("An argument is missing: %(missing)s" %
+ dict(missing=self.missing[0]))
+ else:
+ return ("%(num)d arguments are missing: %(missing)s" %
+ dict(num=len(self.missing),
+ missing=string.join(self.missing, ', ')))
+
+
+def validate_args(fn, *args, **kwargs):
+ """Check that the supplied args are sufficient for calling a function.
+
+ >>> validate_args(lambda a: None)
+ Traceback (most recent call last):
+ ...
+ MissingArgs: An argument is missing: a
+ >>> validate_args(lambda a, b, c, d: None, 0, c=1)
+ Traceback (most recent call last):
+ ...
+ MissingArgs: 2 arguments are missing: b, d
+
+ :param fn: the function to check
+ :param arg: the positional arguments supplied
+ :param kwargs: the keyword arguments supplied
+ """
+ argspec = inspect.getargspec(fn)
+
+ num_defaults = len(argspec.defaults or [])
+ required_args = argspec.args[:len(argspec.args) - num_defaults]
+
+ def isbound(method):
+ return getattr(method, 'im_self', None) is not None
+
+ if isbound(fn):
+ required_args.pop(0)
+
+ missing = [arg for arg in required_args if arg not in kwargs]
+ missing = missing[len(args):]
+ if missing:
+ raise MissingArgs(missing)
diff --git a/tests/unit/test_cliutils.py b/tests/unit/test_cliutils.py
new file mode 100644
index 0000000..49339a0
--- /dev/null
+++ b/tests/unit/test_cliutils.py
@@ -0,0 +1,398 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 Red Hat, Inc.
+#
+# 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 unittest
+
+from openstack.common.cliutils import *
+
+
+class ValidateArgsTest(unittest.TestCase):
+
+ def test_lambda_no_args(self):
+ validate_args(lambda: None)
+
+ def _test_lambda_with_args(self, *args, **kwargs):
+ validate_args(lambda x, y: None, *args, **kwargs)
+
+ def test_lambda_positional_args(self):
+ self._test_lambda_with_args(1, 2)
+
+ def test_lambda_kwargs(self):
+ self._test_lambda_with_args(x=1, y=2)
+
+ def test_lambda_mixed_kwargs(self):
+ self._test_lambda_with_args(1, y=2)
+
+ def test_lambda_missing_args1(self):
+ self.assertRaises(MissingArgs, self._test_lambda_with_args)
+
+ def test_lambda_missing_args2(self):
+ self.assertRaises(MissingArgs, self._test_lambda_with_args, 1)
+
+ def test_lambda_missing_args3(self):
+ self.assertRaises(MissingArgs, self._test_lambda_with_args, y=2)
+
+ def _test_lambda_with_default(self, *args, **kwargs):
+ validate_args(lambda x, y, z=3: None, *args, **kwargs)
+
+ def test_lambda_positional_args_with_default(self):
+ self._test_lambda_with_default(1, 2)
+
+ def test_lambda_kwargs_with_default(self):
+ self._test_lambda_with_default(x=1, y=2)
+
+ def test_lambda_mixed_kwargs_with_default(self):
+ self._test_lambda_with_default(1, y=2)
+
+ def test_lambda_positional_args_all_with_default(self):
+ self._test_lambda_with_default(1, 2, 3)
+
+ def test_lambda_kwargs_all_with_default(self):
+ self._test_lambda_with_default(x=1, y=2, z=3)
+
+ def test_lambda_mixed_kwargs_all_with_default(self):
+ self._test_lambda_with_default(1, y=2, z=3)
+
+ def test_lambda_with_default_missing_args1(self):
+ self.assertRaises(MissingArgs, self._test_lambda_with_default)
+
+ def test_lambda_with_default_missing_args2(self):
+ self.assertRaises(MissingArgs, self._test_lambda_with_default, 1)
+
+ def test_lambda_with_default_missing_args3(self):
+ self.assertRaises(MissingArgs, self._test_lambda_with_default, y=2)
+
+ def test_lambda_with_default_missing_args4(self):
+ self.assertRaises(MissingArgs,
+ self._test_lambda_with_default, y=2, z=3)
+
+ def test_function_no_args(self):
+ def func():
+ pass
+ validate_args(func)
+
+ def _test_function_with_args(self, *args, **kwargs):
+ def func(x, y):
+ pass
+ validate_args(func, *args, **kwargs)
+
+ def test_function_positional_args(self):
+ self._test_function_with_args(1, 2)
+
+ def test_function_kwargs(self):
+ self._test_function_with_args(x=1, y=2)
+
+ def test_function_mixed_kwargs(self):
+ self._test_function_with_args(1, y=2)
+
+ def test_function_missing_args1(self):
+ self.assertRaises(MissingArgs, self._test_function_with_args)
+
+ def test_function_missing_args2(self):
+ self.assertRaises(MissingArgs, self._test_function_with_args, 1)
+
+ def test_function_missing_args3(self):
+ self.assertRaises(MissingArgs, self._test_function_with_args, y=2)
+
+ def _test_function_with_default(self, *args, **kwargs):
+ def func(x, y, z=3):
+ pass
+ validate_args(func, *args, **kwargs)
+
+ def test_function_positional_args_with_default(self):
+ self._test_function_with_default(1, 2)
+
+ def test_function_kwargs_with_default(self):
+ self._test_function_with_default(x=1, y=2)
+
+ def test_function_mixed_kwargs_with_default(self):
+ self._test_function_with_default(1, y=2)
+
+ def test_function_positional_args_all_with_default(self):
+ self._test_function_with_default(1, 2, 3)
+
+ def test_function_kwargs_all_with_default(self):
+ self._test_function_with_default(x=1, y=2, z=3)
+
+ def test_function_mixed_kwargs_all_with_default(self):
+ self._test_function_with_default(1, y=2, z=3)
+
+ def test_function_with_default_missing_args1(self):
+ self.assertRaises(MissingArgs, self._test_function_with_default)
+
+ def test_function_with_default_missing_args2(self):
+ self.assertRaises(MissingArgs, self._test_function_with_default, 1)
+
+ def test_function_with_default_missing_args3(self):
+ self.assertRaises(MissingArgs, self._test_function_with_default, y=2)
+
+ def test_function_with_default_missing_args4(self):
+ self.assertRaises(MissingArgs,
+ self._test_function_with_default, y=2, z=3)
+
+ def test_bound_method_no_args(self):
+ class Foo:
+ def bar(self):
+ pass
+ validate_args(Foo().bar)
+
+ def _test_bound_method_with_args(self, *args, **kwargs):
+ class Foo:
+ def bar(self, x, y):
+ pass
+ validate_args(Foo().bar, *args, **kwargs)
+
+ def test_bound_method_positional_args(self):
+ self._test_bound_method_with_args(1, 2)
+
+ def test_bound_method_kwargs(self):
+ self._test_bound_method_with_args(x=1, y=2)
+
+ def test_bound_method_mixed_kwargs(self):
+ self._test_bound_method_with_args(1, y=2)
+
+ def test_bound_method_missing_args1(self):
+ self.assertRaises(MissingArgs, self._test_bound_method_with_args)
+
+ def test_bound_method_missing_args2(self):
+ self.assertRaises(MissingArgs, self._test_bound_method_with_args, 1)
+
+ def test_bound_method_missing_args3(self):
+ self.assertRaises(MissingArgs, self._test_bound_method_with_args, y=2)
+
+ def _test_bound_method_with_default(self, *args, **kwargs):
+ class Foo:
+ def bar(self, x, y, z=3):
+ pass
+ validate_args(Foo().bar, *args, **kwargs)
+
+ def test_bound_method_positional_args_with_default(self):
+ self._test_bound_method_with_default(1, 2)
+
+ def test_bound_method_kwargs_with_default(self):
+ self._test_bound_method_with_default(x=1, y=2)
+
+ def test_bound_method_mixed_kwargs_with_default(self):
+ self._test_bound_method_with_default(1, y=2)
+
+ def test_bound_method_positional_args_all_with_default(self):
+ self._test_bound_method_with_default(1, 2, 3)
+
+ def test_bound_method_kwargs_all_with_default(self):
+ self._test_bound_method_with_default(x=1, y=2, z=3)
+
+ def test_bound_method_mixed_kwargs_all_with_default(self):
+ self._test_bound_method_with_default(1, y=2, z=3)
+
+ def test_bound_method_with_default_missing_args1(self):
+ self.assertRaises(MissingArgs, self._test_bound_method_with_default)
+
+ def test_bound_method_with_default_missing_args2(self):
+ self.assertRaises(MissingArgs, self._test_bound_method_with_default, 1)
+
+ def test_bound_method_with_default_missing_args3(self):
+ self.assertRaises(MissingArgs,
+ self._test_bound_method_with_default, y=2)
+
+ def test_bound_method_with_default_missing_args4(self):
+ self.assertRaises(MissingArgs,
+ self._test_bound_method_with_default, y=2, z=3)
+
+ def test_unbound_method_no_args(self):
+ class Foo:
+ def bar(self):
+ pass
+ validate_args(Foo.bar, Foo())
+
+ def _test_unbound_method_with_args(self, *args, **kwargs):
+ class Foo:
+ def bar(self, x, y):
+ pass
+ validate_args(Foo.bar, Foo(), *args, **kwargs)
+
+ def test_unbound_method_positional_args(self):
+ self._test_unbound_method_with_args(1, 2)
+
+ def test_unbound_method_kwargs(self):
+ self._test_unbound_method_with_args(x=1, y=2)
+
+ def test_unbound_method_mixed_kwargs(self):
+ self._test_unbound_method_with_args(1, y=2)
+
+ def test_unbound_method_missing_args1(self):
+ self.assertRaises(MissingArgs, self._test_unbound_method_with_args)
+
+ def test_unbound_method_missing_args2(self):
+ self.assertRaises(MissingArgs, self._test_unbound_method_with_args, 1)
+
+ def test_unbound_method_missing_args3(self):
+ self.assertRaises(MissingArgs,
+ self._test_unbound_method_with_args, y=2)
+
+ def _test_unbound_method_with_default(self, *args, **kwargs):
+ class Foo:
+ def bar(self, x, y, z=3):
+ pass
+ validate_args(Foo.bar, Foo(), *args, **kwargs)
+
+ def test_unbound_method_positional_args_with_default(self):
+ self._test_unbound_method_with_default(1, 2)
+
+ def test_unbound_method_kwargs_with_default(self):
+ self._test_unbound_method_with_default(x=1, y=2)
+
+ def test_unbound_method_mixed_kwargs_with_default(self):
+ self._test_unbound_method_with_default(1, y=2)
+
+ def test_unbound_method_with_default_missing_args1(self):
+ self.assertRaises(MissingArgs, self._test_unbound_method_with_default)
+
+ def test_unbound_method_with_default_missing_args2(self):
+ self.assertRaises(MissingArgs,
+ self._test_unbound_method_with_default, 1)
+
+ def test_unbound_method_with_default_missing_args3(self):
+ self.assertRaises(MissingArgs,
+ self._test_unbound_method_with_default, y=2)
+
+ def test_unbound_method_with_default_missing_args4(self):
+ self.assertRaises(MissingArgs,
+ self._test_unbound_method_with_default, y=2, z=3)
+
+ def test_class_method_no_args(self):
+ class Foo:
+ @classmethod
+ def bar(cls):
+ pass
+ validate_args(Foo.bar)
+
+ def _test_class_method_with_args(self, *args, **kwargs):
+ class Foo:
+ @classmethod
+ def bar(cls, x, y):
+ pass
+ validate_args(Foo.bar, *args, **kwargs)
+
+ def test_class_method_positional_args(self):
+ self._test_class_method_with_args(1, 2)
+
+ def test_class_method_kwargs(self):
+ self._test_class_method_with_args(x=1, y=2)
+
+ def test_class_method_mixed_kwargs(self):
+ self._test_class_method_with_args(1, y=2)
+
+ def test_class_method_missing_args1(self):
+ self.assertRaises(MissingArgs, self._test_class_method_with_args)
+
+ def test_class_method_missing_args2(self):
+ self.assertRaises(MissingArgs, self._test_class_method_with_args, 1)
+
+ def test_class_method_missing_args3(self):
+ self.assertRaises(MissingArgs, self._test_class_method_with_args, y=2)
+
+ def _test_class_method_with_default(self, *args, **kwargs):
+ class Foo:
+ @classmethod
+ def bar(cls, x, y, z=3):
+ pass
+ validate_args(Foo.bar, *args, **kwargs)
+
+ def test_class_method_positional_args_with_default(self):
+ self._test_class_method_with_default(1, 2)
+
+ def test_class_method_kwargs_with_default(self):
+ self._test_class_method_with_default(x=1, y=2)
+
+ def test_class_method_mixed_kwargs_with_default(self):
+ self._test_class_method_with_default(1, y=2)
+
+ def test_class_method_with_default_missing_args1(self):
+ self.assertRaises(MissingArgs, self._test_class_method_with_default)
+
+ def test_class_method_with_default_missing_args2(self):
+ self.assertRaises(MissingArgs, self._test_class_method_with_default, 1)
+
+ def test_class_method_with_default_missing_args3(self):
+ self.assertRaises(MissingArgs,
+ self._test_class_method_with_default, y=2)
+
+ def test_class_method_with_default_missing_args4(self):
+ self.assertRaises(MissingArgs,
+ self._test_class_method_with_default, y=2, z=3)
+
+ def test_static_method_no_args(self):
+ class Foo:
+ @staticmethod
+ def bar():
+ pass
+ validate_args(Foo.bar)
+
+ def _test_static_method_with_args(self, *args, **kwargs):
+ class Foo:
+ @staticmethod
+ def bar(x, y):
+ pass
+ validate_args(Foo.bar, *args, **kwargs)
+
+ def test_static_method_positional_args(self):
+ self._test_static_method_with_args(1, 2)
+
+ def test_static_method_kwargs(self):
+ self._test_static_method_with_args(x=1, y=2)
+
+ def test_static_method_mixed_kwargs(self):
+ self._test_static_method_with_args(1, y=2)
+
+ def test_static_method_missing_args1(self):
+ self.assertRaises(MissingArgs, self._test_static_method_with_args)
+
+ def test_static_method_missing_args2(self):
+ self.assertRaises(MissingArgs, self._test_static_method_with_args, 1)
+
+ def test_static_method_missing_args3(self):
+ self.assertRaises(MissingArgs, self._test_static_method_with_args, y=2)
+
+ def _test_static_method_with_default(self, *args, **kwargs):
+ class Foo:
+ @staticmethod
+ def bar(x, y, z=3):
+ pass
+ validate_args(Foo.bar, *args, **kwargs)
+
+ def test_static_method_positional_args_with_default(self):
+ self._test_static_method_with_default(1, 2)
+
+ def test_static_method_kwargs_with_default(self):
+ self._test_static_method_with_default(x=1, y=2)
+
+ def test_static_method_mixed_kwargs_with_default(self):
+ self._test_static_method_with_default(1, y=2)
+
+ def test_static_method_with_default_missing_args1(self):
+ self.assertRaises(MissingArgs, self._test_static_method_with_default)
+
+ def test_static_method_with_default_missing_args2(self):
+ self.assertRaises(MissingArgs,
+ self._test_static_method_with_default, 1)
+
+ def test_static_method_with_default_missing_args3(self):
+ self.assertRaises(MissingArgs,
+ self._test_static_method_with_default, y=2)
+
+ def test_static_method_with_default_missing_args4(self):
+ self.assertRaises(MissingArgs,
+ self._test_static_method_with_default, y=2, z=3)