Refactor stdlib PartialObject

Merges PartialObject and PartialMethodObject. Also adds more tests.
Some parts are still WIP, see: #1522.

Fixes #1519
This commit is contained in:
Daniel Lemm
2020-03-13 23:47:48 +01:00
parent fd6540a9e5
commit 2406e58386
2 changed files with 17 additions and 44 deletions

View File

@@ -473,49 +473,9 @@ def collections_namedtuple(value, arguments, callback):
return ValueSet([ClassValue(inference_state, parent_context, generated_class)]) return ValueSet([ClassValue(inference_state, parent_context, generated_class)])
class PartialObject(object): class PartialObject(ValueWrapper):
def __init__(self, actual_value, arguments):
self._actual_value = actual_value
self._arguments = arguments
def __getattr__(self, name):
return getattr(self._actual_value, name)
def _get_function(self, unpacked_arguments):
key, lazy_value = next(unpacked_arguments, (None, None))
if key is not None or lazy_value is None:
debug.warning("Partial should have a proper function %s", self._arguments)
return None
return lazy_value.infer()
def get_signatures(self):
unpacked_arguments = self._arguments.unpack()
func = self._get_function(unpacked_arguments)
if func is None:
return []
arg_count = 0
keys = set()
for key, _ in unpacked_arguments:
if key is None:
arg_count += 1
else:
keys.add(key)
return [PartialSignature(s, arg_count, keys) for s in func.get_signatures()]
def py__call__(self, arguments):
func = self._get_function(self._arguments.unpack())
if func is None:
return NO_VALUES
return func.execute(
MergedPartialArguments(self._arguments, arguments)
)
class PartialMethodObject(ValueWrapper):
def __init__(self, actual_value, arguments, instance=None): def __init__(self, actual_value, arguments, instance=None):
super(PartialMethodObject, self).__init__(actual_value) super(PartialObject, self).__init__(actual_value)
self._actual_value = actual_value self._actual_value = actual_value
self._arguments = arguments self._arguments = arguments
self._instance = instance self._instance = instance
@@ -545,7 +505,7 @@ class PartialMethodObject(ValueWrapper):
return [PartialSignature(s, arg_count, keys) for s in func.get_signatures()] return [PartialSignature(s, arg_count, keys) for s in func.get_signatures()]
def py__get__(self, instance, class_value): def py__get__(self, instance, class_value):
return ValueSet([PartialMethodObject(self._actual_value, self._arguments, self._instance)]) return ValueSet([PartialObject(self._actual_value, self._arguments, self._instance)])
def py__call__(self, arguments): def py__call__(self, arguments):
func = self._get_function(self._arguments.unpack()) func = self._get_function(self._arguments.unpack())
@@ -596,7 +556,9 @@ def functools_partial(value, arguments, callback):
def functools_partialmethod(value, arguments, callback): def functools_partialmethod(value, arguments, callback):
return ValueSet( return ValueSet(
PartialMethodObject(instance, arguments, instance) # FIXME pass correct instance as last arg # XXX last argument is a placeholder. See:
# https://github.com/davidhalter/jedi/pull/1522#discussion_r392474671
PartialObject(instance, arguments, True)
for instance in value.py__call__(arguments) for instance in value.py__call__(arguments)
) )

View File

@@ -169,6 +169,11 @@ X().a('')[0]
#? str() #? str()
X().a('')[1] X().a('')[1]
#? int()
X.a('')[0]
#? str()
X.a('')[1]
#? int() #? int()
X.a(X(), '')[0] X.a(X(), '')[0]
#? str() #? str()
@@ -180,6 +185,12 @@ tup[0]
#? float() #? float()
tup[1] tup[1]
tup = X.kw(1)
#? int()
tup[0]
#? float()
tup[1]
tup = X.kw(X(), 1) tup = X.kw(X(), 1)
#? int() #? int()
tup[0] tup[0]