code: def get_func_full_args(func):
      
      if six.PY2:
          argspec = inspect.getargspec(func)
          args = argspec.args[1:]  # ignore 'self'
          defaults = argspec.defaults or []
          # Split args into two lists depending on whether they have default value
          no_default = args[:len(args) - len(defaults)]
          with_default = args[len(args) - len(defaults):]
          # Join the two lists and combine it with default values
          args = [(arg,) for arg in no_default] + zip(with_default, defaults)
          # Add possible *args and **kwargs and prepend them with '*' or '**'
          varargs = [('*' + argspec.varargs,)] if argspec.varargs else []
          kwargs = [('**' + argspec.keywords,)] if argspec.keywords else []
          return args + varargs + kwargs
  
      sig = inspect.signature(func)
      args = []
      for arg_name, param in sig.parameters.items():
          name = arg_name
          # Ignore 'self'
          if name == 'self':
              continue
          if param.kind == inspect.Parameter.VAR_POSITIONAL:
              name = '*' + name
          elif param.kind == inspect.Parameter.VAR_KEYWORD:
              name = '**' + name
          if param.default != inspect.Parameter.empty:
              args.append((name, param.default))
          else:
              args.append((name,))
      return args
docs: Return a list of (argument name, default value) tuples. If the argument
      does not have a default value, omit it in the tuple. Arguments such as
      *args and **kwargs are also included.