Browse Source

[commands] Use eval instead of get_type_hints to resolve typehints

The previous usage of `typing.get_type_hints` caused issues as it would
incorrectly decide to convert annotations into their equivalent
`typing` form -- which is not what we want to happen here.

Due to some use-cases about how setting `Command.callback` work and
the amount of moving parts that have changed due to this patch, it is
probably better to refactor the way it is set so users can have this
use-case handled transparently for them.
pull/1531/head
Rapptz 7 years ago
parent
commit
fdc71695dc
  1. 33
      discord/ext/commands/core.py

33
discord/ext/commands/core.py

@ -174,21 +174,7 @@ class Command:
self.description = inspect.cleandoc(kwargs.get('description', ''))
self.hidden = kwargs.get('hidden', False)
signature = inspect.signature(callback)
annotations = typing.get_type_hints(callback)
self.params = signature.parameters.copy()
# PEP-563 allows postponing evaluation of annotations with a __future__
# import. When postponed, Parameter.annotation will be a string and must
# be replaced with the real class from typing.get_type_hints() for the
# converters to work later on
for key, value in self.params.items():
if isinstance(value.annotation, str) and key in annotations:
self.params[key] = value.replace(annotation=annotations[key])
self.checks = kwargs.get('checks', [])
self.module = callback.__module__
self.ignore_extra = kwargs.get('ignore_extra', True)
self.instance = None
self.parent = None
@ -196,6 +182,25 @@ class Command:
self._before_invoke = None
self._after_invoke = None
@property
def callback(self):
return self._callback
@callback.setter
def callback(self, function):
self._callback = function
self.module = function.__module__
signature = inspect.signature(function)
self.params = signature.parameters.copy()
# PEP-563 allows postponing evaluation of annotations with a __future__
# import. When postponed, Parameter.annotation will be a string and must
# be replaced with the real value for the converters to work later on
for key, value in self.params.items():
if isinstance(value.annotation, str):
self.params[key] = value.replace(annotation=eval(value.annotation, function.__globals__))
async def dispatch_error(self, ctx, error):
ctx.command_failed = True
cog = self.instance

Loading…
Cancel
Save