prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Possible issue with checking of Quantity input
  In my branch ji_diff_rot3 I've started using the quantity_input decorator.  It now decorates rot_hpc, a differential rotation calculator.  The decorator crashes when applied to this function
  
  ``` python
  In [1]: from sunpy.physics.transforms.differential_rotation import rot_hpc
  In [2]: import astropy.units as u
  In [3]: rot_hpc( -570 * u.arcsec, 120 * u.arcsec, '2010-09-10 12:34:56', '2010-09-10 13:34:56')
  ---------------------------------------------------------------------------
  KeyError                                  Traceback (most recent call last)
  <ipython-input-3-0803dabeac04> in <module>()
  ----> 1 rot_hpc( -570 * u.arcsec, 120 * u.arcsec, '2010-09-10 12:34:56', '2010-09-10 13:34:56')
  
  /Users/ireland/sunpy/sunpy/util/unit_decorators.pyc in wrapper(*func_args, **func_kwargs)
       81 
       82                 # Get the value of this parameter (argument to new function)
  ---> 83                 arg = bound_args.arguments[param.name]
       84 
       85                 # Get target unit, either from decotrator kwargs or annotations
  
  KeyError: 'kwargs'
  ```
  
  The error is reproducible with much simpler functions:
  
  ``` python
  In [2]: import astropy.units as u
  In [3]: from sunpy.util import quantity_input
  
  In [4]: @quantity_input(a=u.deg)
     ...: def funct(a, **kwargs):
     ...:     pass
     ...: 
  
  In [5]: funct(1 * u.deg)
  ---------------------------------------------------------------------------
  KeyError                                  Traceback (most recent call last)
  <ipython-input-5-5fb4e89adcc1> in <module>()
  ----> 1 funct(1 * u.deg)
  
  /Users/ireland/sunpy/sunpy/util/unit_decorators.pyc in wrapper(*func_args, **func_kwargs)
       81 
       82                 # Get the value of this parameter (argument to new function)
  ---> 83                 arg = bound_args.arguments[param.name]
       84 
       85                 # Get target unit, either from decotrator kwargs or annotations
  
  KeyError: 'kwargs'
  ```
  
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `sunpy/util/unit_decorators.py`
  Content:
  ```
  1 # -*- coding: utf-8 -*-
  2 # Lovingly borrowed from Astropy
  3 # Licensed under a 3-clause BSD style license - see licences/ASTROPY.rst
  4 
  5 __all__ = ['quantity_input']
  6 
  7 from ..util.compat import funcsigs
  8 
  9 from astropy.units import UnitsError, add_enabled_equivalencies
  10 
  11 class QuantityInput(object):
  12 
  13     @classmethod
  14     def as_decorator(cls, func=None, **kwargs):
  15         """
  16         A decorator for validating the units of arguments to functions.
  17 
  18         Unit specifications can be provided as keyword arguments to the decorator,
  19         or by using Python 3's function annotation syntax. Arguments to the decorator
  20         take precidence over any function annotations present.
  21 
  22         A `~astropy.units.UnitsError` will be raised if the unit attribute of
  23         the argument is not equivalent to the unit specified to the decorator
  24         or in the annotation.
  25         If the argument has no unit attribute, i.e. it is not a Quantity object, a
  26         `~exceptions.ValueError` will be raised.
  27 
  28         Where an equivalency is specified in the decorator, the function will be
  29         executed with that equivalency in force.
  30 
  31         Examples
  32         --------
  33 
  34         Python 2 and 3::
  35 
  36             import astropy.units as u
  37             @u.quantity_input(myangle=u.arcsec)
  38             def myfunction(myangle):
  39                 return myangle**2
  40 
  41         Python 3 only::
  42 
  43             import astropy.units as u
  44             @u.quantity_input
  45             def myfunction(myangle: u.arcsec):
  46                 return myangle**2
  47 
  48         Using equivalencies::
  49 
  50             import astropy.units as u
  51             @u.quantity_input(myenergy=u.eV, equivalencies=u.mass_energy())
  52             def myfunction(myenergy):
  53                 return myenergy**2
  54 
  55         """
  56         self = cls(**kwargs)
  57         if func is not None and not kwargs:
  58             return self(func)
  59         else:
  60             return self
  61 
  62     def __init__(self, func=None, **kwargs):
  63         self.equivalencies = kwargs.pop('equivalencies', [])
  64         self.decorator_kwargs = kwargs
  65 
  66     def __call__(self, wrapped_function):
  67 
  68         # Extract the function signature for the function we are wrapping.
  69         wrapped_signature = funcsigs.signature(wrapped_function)
  70 
  71         # Define a new function to return in place of the wrapped one
  72         def wrapper(*func_args, **func_kwargs):
  73             # Bind the arguments to our new function to the signature of the original.
  74             bound_args = wrapped_signature.bind(*func_args, **func_kwargs)
  75 
  76             # Iterate through the parameters of the original signature
  77             for param in wrapped_signature.parameters.values():
  78                 # Catch the (never triggered) case where bind relied on a default value.
  79                 if param.name not in bound_args.arguments and param.default is not param.empty:
  80                     bound_args.arguments[param.name] = param.default
  81 
  82                 # Get the value of this parameter (argument to new function)
  83                 arg = bound_args.arguments[param.name]
  84 
  85                 # Get target unit, either from decotrator kwargs or annotations
  86                 if param.name in self.decorator_kwargs:
  87                     target_unit = self.decorator_kwargs[param.name]
  88                 else:
  89                     target_unit = param.annotation
  90 
  91                 # If the target unit is empty, then no unit was specified so we
  92                 # move past it
  93                 if target_unit is not funcsigs.Parameter.empty:
  94                     try:
  95                         equivalent = arg.unit.is_equivalent(target_unit,
  96                                                   equivalencies=self.equivalencies)
  97 
  98                         if not equivalent:
  99                             raise UnitsError("Argument '{0}' to function '{1}'"
  100                                              " must be in units convertable to"
  101                                              " '{2}'.".format(param.name,
  102                                                      wrapped_function.__name__,
  103                                                      target_unit.to_string()))
  104 
  105                     # Either there is no .unit or no .is_equivalent
  106                     except AttributeError:
  107                         if hasattr(arg, "unit"):
  108                             error_msg = "a 'unit' attribute without an 'is_equivalent' method"
  109                         else:
  110                             error_msg = "no 'unit' attribute"
  111                         raise TypeError("Argument '{0}' to function has '{1}' {2}. "
  112                               "You may want to pass in an astropy Quantity instead."
  113                                  .format(param.name, wrapped_function.__name__, error_msg))
  114 
  115             # Call the original function with any equivalencies in force.
  116             with add_enabled_equivalencies(self.equivalencies):
  117                 return wrapped_function(*func_args, **func_kwargs)
  118 
  119         return wrapper
  120 
  121 quantity_input = QuantityInput.as_decorator
  122
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/sunpy/util/unit_decorators.py b/sunpy/util/unit_decorators.py
  --- a/sunpy/util/unit_decorators.py
  +++ b/sunpy/util/unit_decorators.py
  @@ -75,6 +75,11 @@
   
               # Iterate through the parameters of the original signature
               for param in wrapped_signature.parameters.values():
  +                 # We do not support variable arguments (*args,
  +                 # **kwargs)
  +                if param.kind in (funcsigs.Parameter.VAR_KEYWORD,
  +                                  funcsigs.Parameter.VAR_POSITIONAL):
  +                    continue
                   # Catch the (never triggered) case where bind relied on a default value.
                   if param.name not in bound_args.arguments and param.default is not param.empty:
                       bound_args.arguments[param.name] = param.default
  
verification_info: {"golden_diff": "diff --git a/sunpy/util/unit_decorators.py b/sunpy/util/unit_decorators.py\n--- a/sunpy/util/unit_decorators.py\n+++ b/sunpy/util/unit_decorators.py\n@@ -75,6 +75,11 @@\n \n             # Iterate through the parameters of the original signature\n             for param in wrapped_signature.parameters.values():\n+                 # We do not support variable arguments (*args,\n+                 # **kwargs)\n+                if param.kind in (funcsigs.Parameter.VAR_KEYWORD,\n+                                  funcsigs.Parameter.VAR_POSITIONAL):\n+                    continue\n                 # Catch the (never triggered) case where bind relied on a default value.\n                 if param.name not in bound_args.arguments and param.default is not param.empty:\n                     bound_args.arguments[param.name] = param.default\n", "issue": "Possible issue with checking of Quantity input\nIn my branch ji_diff_rot3 I've started using the quantity_input decorator.  It now decorates rot_hpc, a differential rotation calculator.  The decorator crashes when applied to this function\n\n``` python\nIn [1]: from sunpy.physics.transforms.differential_rotation import rot_hpc\nIn [2]: import astropy.units as u\nIn [3]: rot_hpc( -570 * u.arcsec, 120 * u.arcsec, '2010-09-10 12:34:56', '2010-09-10 13:34:56')\n---------------------------------------------------------------------------\nKeyError                                  Traceback (most recent call last)\n<ipython-input-3-0803dabeac04> in <module>()\n----> 1 rot_hpc( -570 * u.arcsec, 120 * u.arcsec, '2010-09-10 12:34:56', '2010-09-10 13:34:56')\n\n/Users/ireland/sunpy/sunpy/util/unit_decorators.pyc in wrapper(*func_args, **func_kwargs)\n     81 \n     82                 # Get the value of this parameter (argument to new function)\n---> 83                 arg = bound_args.arguments[param.name]\n     84 \n     85                 # Get target unit, either from decotrator kwargs or annotations\n\nKeyError: 'kwargs'\n```\n\nThe error is reproducible with much simpler functions:\n\n``` python\nIn [2]: import astropy.units as u\nIn [3]: from sunpy.util import quantity_input\n\nIn [4]: @quantity_input(a=u.deg)\n   ...: def funct(a, **kwargs):\n   ...:     pass\n   ...: \n\nIn [5]: funct(1 * u.deg)\n---------------------------------------------------------------------------\nKeyError                                  Traceback (most recent call last)\n<ipython-input-5-5fb4e89adcc1> in <module>()\n----> 1 funct(1 * u.deg)\n\n/Users/ireland/sunpy/sunpy/util/unit_decorators.pyc in wrapper(*func_args, **func_kwargs)\n     81 \n     82                 # Get the value of this parameter (argument to new function)\n---> 83                 arg = bound_args.arguments[param.name]\n     84 \n     85                 # Get target unit, either from decotrator kwargs or annotations\n\nKeyError: 'kwargs'\n```\n\n", "before_files": [{"content": "# -*- coding: utf-8 -*-\n# Lovingly borrowed from Astropy\n# Licensed under a 3-clause BSD style license - see licences/ASTROPY.rst\n\n__all__ = ['quantity_input']\n\nfrom ..util.compat import funcsigs\n\nfrom astropy.units import UnitsError, add_enabled_equivalencies\n\nclass QuantityInput(object):\n\n    @classmethod\n    def as_decorator(cls, func=None, **kwargs):\n        \"\"\"\n        A decorator for validating the units of arguments to functions.\n\n        Unit specifications can be provided as keyword arguments to the decorator,\n        or by using Python 3's function annotation syntax. Arguments to the decorator\n        take precidence over any function annotations present.\n\n        A `~astropy.units.UnitsError` will be raised if the unit attribute of\n        the argument is not equivalent to the unit specified to the decorator\n        or in the annotation.\n        If the argument has no unit attribute, i.e. it is not a Quantity object, a\n        `~exceptions.ValueError` will be raised.\n\n        Where an equivalency is specified in the decorator, the function will be\n        executed with that equivalency in force.\n\n        Examples\n        --------\n\n        Python 2 and 3::\n\n            import astropy.units as u\n            @u.quantity_input(myangle=u.arcsec)\n            def myfunction(myangle):\n                return myangle**2\n\n        Python 3 only::\n\n            import astropy.units as u\n            @u.quantity_input\n            def myfunction(myangle: u.arcsec):\n                return myangle**2\n\n        Using equivalencies::\n\n            import astropy.units as u\n            @u.quantity_input(myenergy=u.eV, equivalencies=u.mass_energy())\n            def myfunction(myenergy):\n                return myenergy**2\n\n        \"\"\"\n        self = cls(**kwargs)\n        if func is not None and not kwargs:\n            return self(func)\n        else:\n            return self\n\n    def __init__(self, func=None, **kwargs):\n        self.equivalencies = kwargs.pop('equivalencies', [])\n        self.decorator_kwargs = kwargs\n\n    def __call__(self, wrapped_function):\n\n        # Extract the function signature for the function we are wrapping.\n        wrapped_signature = funcsigs.signature(wrapped_function)\n\n        # Define a new function to return in place of the wrapped one\n        def wrapper(*func_args, **func_kwargs):\n            # Bind the arguments to our new function to the signature of the original.\n            bound_args = wrapped_signature.bind(*func_args, **func_kwargs)\n\n            # Iterate through the parameters of the original signature\n            for param in wrapped_signature.parameters.values():\n                # Catch the (never triggered) case where bind relied on a default value.\n                if param.name not in bound_args.arguments and param.default is not param.empty:\n                    bound_args.arguments[param.name] = param.default\n\n                # Get the value of this parameter (argument to new function)\n                arg = bound_args.arguments[param.name]\n\n                # Get target unit, either from decotrator kwargs or annotations\n                if param.name in self.decorator_kwargs:\n                    target_unit = self.decorator_kwargs[param.name]\n                else:\n                    target_unit = param.annotation\n\n                # If the target unit is empty, then no unit was specified so we\n                # move past it\n                if target_unit is not funcsigs.Parameter.empty:\n                    try:\n                        equivalent = arg.unit.is_equivalent(target_unit,\n                                                  equivalencies=self.equivalencies)\n\n                        if not equivalent:\n                            raise UnitsError(\"Argument '{0}' to function '{1}'\"\n                                             \" must be in units convertable to\"\n                                             \" '{2}'.\".format(param.name,\n                                                     wrapped_function.__name__,\n                                                     target_unit.to_string()))\n\n                    # Either there is no .unit or no .is_equivalent\n                    except AttributeError:\n                        if hasattr(arg, \"unit\"):\n                            error_msg = \"a 'unit' attribute without an 'is_equivalent' method\"\n                        else:\n                            error_msg = \"no 'unit' attribute\"\n                        raise TypeError(\"Argument '{0}' to function has '{1}' {2}. \"\n                              \"You may want to pass in an astropy Quantity instead.\"\n                                 .format(param.name, wrapped_function.__name__, error_msg))\n\n            # Call the original function with any equivalencies in force.\n            with add_enabled_equivalencies(self.equivalencies):\n                return wrapped_function(*func_args, **func_kwargs)\n\n        return wrapper\n\nquantity_input = QuantityInput.as_decorator\n", "path": "sunpy/util/unit_decorators.py"}], "after_files": [{"content": "# -*- coding: utf-8 -*-\n# Lovingly borrowed from Astropy\n# Licensed under a 3-clause BSD style license - see licences/ASTROPY.rst\n\n__all__ = ['quantity_input']\n\nfrom ..util.compat import funcsigs\n\nfrom astropy.units import UnitsError, add_enabled_equivalencies\n\nclass QuantityInput(object):\n\n    @classmethod\n    def as_decorator(cls, func=None, **kwargs):\n        \"\"\"\n        A decorator for validating the units of arguments to functions.\n\n        Unit specifications can be provided as keyword arguments to the decorator,\n        or by using Python 3's function annotation syntax. Arguments to the decorator\n        take precidence over any function annotations present.\n\n        A `~astropy.units.UnitsError` will be raised if the unit attribute of\n        the argument is not equivalent to the unit specified to the decorator\n        or in the annotation.\n        If the argument has no unit attribute, i.e. it is not a Quantity object, a\n        `~exceptions.ValueError` will be raised.\n\n        Where an equivalency is specified in the decorator, the function will be\n        executed with that equivalency in force.\n\n        Examples\n        --------\n\n        Python 2 and 3::\n\n            import astropy.units as u\n            @u.quantity_input(myangle=u.arcsec)\n            def myfunction(myangle):\n                return myangle**2\n\n        Python 3 only::\n\n            import astropy.units as u\n            @u.quantity_input\n            def myfunction(myangle: u.arcsec):\n                return myangle**2\n\n        Using equivalencies::\n\n            import astropy.units as u\n            @u.quantity_input(myenergy=u.eV, equivalencies=u.mass_energy())\n            def myfunction(myenergy):\n                return myenergy**2\n\n        \"\"\"\n        self = cls(**kwargs)\n        if func is not None and not kwargs:\n            return self(func)\n        else:\n            return self\n\n    def __init__(self, func=None, **kwargs):\n        self.equivalencies = kwargs.pop('equivalencies', [])\n        self.decorator_kwargs = kwargs\n\n    def __call__(self, wrapped_function):\n\n        # Extract the function signature for the function we are wrapping.\n        wrapped_signature = funcsigs.signature(wrapped_function)\n\n        # Define a new function to return in place of the wrapped one\n        def wrapper(*func_args, **func_kwargs):\n            # Bind the arguments to our new function to the signature of the original.\n            bound_args = wrapped_signature.bind(*func_args, **func_kwargs)\n\n            # Iterate through the parameters of the original signature\n            for param in wrapped_signature.parameters.values():\n                 # We do not support variable arguments (*args,\n                 # **kwargs)\n                if param.kind in (funcsigs.Parameter.VAR_KEYWORD,\n                                  funcsigs.Parameter.VAR_POSITIONAL):\n                    continue\n                # Catch the (never triggered) case where bind relied on a default value.\n                if param.name not in bound_args.arguments and param.default is not param.empty:\n                    bound_args.arguments[param.name] = param.default\n\n                # Get the value of this parameter (argument to new function)\n                arg = bound_args.arguments[param.name]\n\n                # Get target unit, either from decotrator kwargs or annotations\n                if param.name in self.decorator_kwargs:\n                    target_unit = self.decorator_kwargs[param.name]\n                else:\n                    target_unit = param.annotation\n\n                # If the target unit is empty, then no unit was specified so we\n                # move past it\n                if target_unit is not funcsigs.Parameter.empty:\n                    try:\n                        equivalent = arg.unit.is_equivalent(target_unit,\n                                                  equivalencies=self.equivalencies)\n\n                        if not equivalent:\n                            raise UnitsError(\"Argument '{0}' to function '{1}'\"\n                                             \" must be in units convertable to\"\n                                             \" '{2}'.\".format(param.name,\n                                                     wrapped_function.__name__,\n                                                     target_unit.to_string()))\n\n                    # Either there is no .unit or no .is_equivalent\n                    except AttributeError:\n                        if hasattr(arg, \"unit\"):\n                            error_msg = \"a 'unit' attribute without an 'is_equivalent' method\"\n                        else:\n                            error_msg = \"no 'unit' attribute\"\n                        raise TypeError(\"Argument '{0}' to function has '{1}' {2}. \"\n                              \"You may want to pass in an astropy Quantity instead.\"\n                                 .format(param.name, wrapped_function.__name__, error_msg))\n\n            # Call the original function with any equivalencies in force.\n            with add_enabled_equivalencies(self.equivalencies):\n                return wrapped_function(*func_args, **func_kwargs)\n\n        return wrapper\n\nquantity_input = QuantityInput.as_decorator\n", "path": "sunpy/util/unit_decorators.py"}]}