code: def takes(*type_list):
      
      def inner(f):
          if enabled:
              # deal with the real function, not a wrapper
              f = getattr(f, 'wrapped_fn', f)
  
              # need to check if 'self' is the first arg,
              # since @pre doesn't want the self param
              member_function = is_member_function(f)
  
              # need metadata for defaults check
              method_args, method_defaults = inspect.getargspec(f)[0::3]
              if member_function:
                  method_args = method_args[member_function:]
  
              def check_condition(args, kwargs):
                  if method_defaults is not None and len(method_defaults) > 0 \
                  and len(method_args) - len(method_defaults) <= len(args) < len(method_args):
                      args += method_defaults[len(args) - len(method_args):]
  
                  for i, (arg, t) in enumerate(zip(args[member_function:], type_list)):
                      method_arg = method_args[i]
                      if method_arg not in kwargs and not check_type(t, arg):
                          raise AssertionError('Precondition failure, wrong type for argument')
  
                  for kwarg in kwargs:
                      arg_position = method_args.index(kwarg)
                      if arg_position < len(type_list):
                          t = type_list[arg_position]
                          if not check_type(t, kwargs.get(kwarg)):
                              raise AssertionError('Precondition failure, wrong type for argument %s' % kwarg)
  
              # append to the rest of the postconditions attached to this method
              if not hasattr(f, 'preconditions'):
                  f.preconditions = []
              f.preconditions.append(check_condition)
  
              return check(f)
          else:
              return f
  
      return inner
docs: Decorates a function with type checks. Examples
  
      @takes(int): take an int as the first param
      @takes(int, str): take and int as first, string as 2nd
      @takes(int, (int, None)): take an int as first, and an int or None as second