summaryrefslogtreecommitdiffstats
path: root/nova/validate.py
diff options
context:
space:
mode:
authorJoshua McKenty <jmckenty@gmail.com>2010-06-24 04:11:56 +0100
committerandy <github@anarkystic.com>2010-06-24 04:11:56 +0100
commitc168754e1a822c98c9574946986113d4f827e9d7 (patch)
tree67c76a8d18ae0eb9d82e9720da97e96d4c79d3f4 /nova/validate.py
parent8c535fae46a6944e1ca5fd8bb44db739befb0054 (diff)
downloadnova-c168754e1a822c98c9574946986113d4f827e9d7.tar.gz
nova-c168754e1a822c98c9574946986113d4f827e9d7.tar.xz
nova-c168754e1a822c98c9574946986113d4f827e9d7.zip
Set volume status properly, first pass at validation decorators.
Diffstat (limited to 'nova/validate.py')
-rw-r--r--nova/validate.py83
1 files changed, 83 insertions, 0 deletions
diff --git a/nova/validate.py b/nova/validate.py
new file mode 100644
index 000000000..d1358d402
--- /dev/null
+++ b/nova/validate.py
@@ -0,0 +1,83 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+# Copyright [2010] [Anso Labs, LLC]
+#
+# 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.
+
+"""
+ Decorators for argument validation, courtesy of
+ http://rmi.net/~lutz/rangetest.html
+"""
+
+def rangetest(**argchecks): # validate ranges for both+defaults
+ def onDecorator(func): # onCall remembers func and argchecks
+ import sys
+ code = func.__code__ if sys.version_info[0] == 3 else func.func_code
+ allargs = code.co_varnames[:code.co_argcount]
+ funcname = func.__name__
+
+ def onCall(*pargs, **kargs):
+ # all pargs match first N args by position
+ # the rest must be in kargs or omitted defaults
+ positionals = list(allargs)
+ positionals = positionals[:len(pargs)]
+
+ for (argname, (low, high)) in argchecks.items():
+ # for all args to be checked
+ if argname in kargs:
+ # was passed by name
+ if kargs[argname] < low or kargs[argname] > high:
+ errmsg = '{0} argument "{1}" not in {2}..{3}'
+ errmsg = errmsg.format(funcname, argname, low, high)
+ raise TypeError(errmsg)
+
+ elif argname in positionals:
+ # was passed by position
+ position = positionals.index(argname)
+ if pargs[position] < low or pargs[position] > high:
+ errmsg = '{0} argument "{1}" not in {2}..{3}'
+ errmsg = errmsg.format(funcname, argname, low, high)
+ raise TypeError(errmsg)
+ else:
+ pass
+
+ return func(*pargs, **kargs) # okay: run original call
+ return onCall
+ return onDecorator
+
+def typetest(**argchecks):
+ def onDecorator(func):
+ import sys
+ code = func.__code__ if sys.version_info[0] == 3 else func.func_code
+ allargs = code.co_varnames[:code.co_argcount]
+ funcname = func.__name__
+
+ def onCall(*pargs, **kargs):
+ positionals = list(allargs)[:len(pargs)]
+ for (argname, type) in argchecks.items():
+ if argname in kargs:
+ if not isinstance(kargs[argname], type):
+ errmsg = '{0} argument "{1}" not of type {2}'
+ errmsg = errmsg.format(funcname, argname, type)
+ raise TypeError(errmsg)
+ elif argname in positionals:
+ position = positionals.index(argname)
+ if not isinstance(pargs[position], type):
+ errmsg = '{0} argument "{1}" not of type {2}'
+ errmsg = errmsg.format(funcname, argname, type)
+ raise TypeError(errmsg)
+ else:
+ pass
+ return func(*pargs, **kargs)
+ return onCall
+ return onDecorator
+