87 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			87 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
# vim: tabstop=4 shiftwidth=4 softtabstop=4
 | 
						|
 | 
						|
# Copyright 2010 United States Government as represented by the
 | 
						|
# Administrator of the National Aeronautics and Space Administration.
 | 
						|
# All Rights Reserved.
 | 
						|
#
 | 
						|
#    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 float(kargs[argname]) < low or float(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 float(pargs[position]) < low or float(pargs[position]) > high:
 | 
						|
                        errmsg = '{0} argument "{1}" with value of {4} not in {2}..{3}'
 | 
						|
                        errmsg = errmsg.format(funcname, argname, low, high, pargs[position])
 | 
						|
                        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, typeof) in argchecks.items():
 | 
						|
                if argname in kargs:
 | 
						|
                    if not isinstance(kargs[argname], typeof):
 | 
						|
                        errmsg = '{0} argument "{1}" not of type {2}'
 | 
						|
                        errmsg = errmsg.format(funcname, argname, typeof)
 | 
						|
                        raise TypeError(errmsg)
 | 
						|
                elif argname in positionals:
 | 
						|
                    position = positionals.index(argname)
 | 
						|
                    if not isinstance(pargs[position], typeof):
 | 
						|
                        errmsg = '{0} argument "{1}" with value of {2} not of type {3}'
 | 
						|
                        errmsg = errmsg.format(funcname, argname, pargs[position], typeof)
 | 
						|
                        raise TypeError(errmsg)
 | 
						|
                else:
 | 
						|
                    pass
 | 
						|
            return func(*pargs, **kargs)
 | 
						|
        return onCall
 | 
						|
    return onDecorator
 | 
						|
 |