Fix PartialMethodObject (WIP)

Implemented feedback from PR #1522.
Does not pass new tests in test/completion/stdlib.py
This commit is contained in:
Daniel Lemm
2020-03-13 21:40:58 +01:00
parent 96c969687a
commit fd6540a9e5
3 changed files with 28 additions and 10 deletions

View File

@@ -513,13 +513,12 @@ class PartialObject(object):
) )
class PartialMethodObject(object): class PartialMethodObject(ValueWrapper):
def __init__(self, actual_value, arguments): def __init__(self, actual_value, arguments, instance=None):
super(PartialMethodObject, self).__init__(actual_value)
self._actual_value = actual_value self._actual_value = actual_value
self._arguments = arguments self._arguments = arguments
self._instance = instance
def __getattr__(self, name):
return getattr(self._actual_value, name)
def _get_function(self, unpacked_arguments): def _get_function(self, unpacked_arguments):
key, lazy_value = next(unpacked_arguments, (None, None)) key, lazy_value = next(unpacked_arguments, (None, None))
@@ -534,7 +533,9 @@ class PartialMethodObject(object):
if func is None: if func is None:
return [] return []
arg_count = 1 arg_count = 0
if self._instance is not None:
arg_count = 1
keys = set() keys = set()
for key, _ in unpacked_arguments: for key, _ in unpacked_arguments:
if key is None: if key is None:
@@ -544,7 +545,7 @@ class PartialMethodObject(object):
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([self]) return ValueSet([PartialMethodObject(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())
@@ -552,7 +553,7 @@ class PartialMethodObject(object):
return NO_VALUES return NO_VALUES
return func.execute( return func.execute(
MergedPartialArguments(self._arguments, arguments) MergedPartialArguments(self._arguments, arguments, self._instance)
) )
@@ -568,15 +569,18 @@ class PartialSignature(SignatureWrapper):
class MergedPartialArguments(AbstractArguments): class MergedPartialArguments(AbstractArguments):
def __init__(self, partial_arguments, call_arguments): def __init__(self, partial_arguments, call_arguments, instance=None):
self._partial_arguments = partial_arguments self._partial_arguments = partial_arguments
self._call_arguments = call_arguments self._call_arguments = call_arguments
self._instance = instance
def unpack(self, funcdef=None): def unpack(self, funcdef=None):
unpacked = self._partial_arguments.unpack(funcdef) unpacked = self._partial_arguments.unpack(funcdef)
# Ignore this one, it's the function. It was checked before that it's # Ignore this one, it's the function. It was checked before that it's
# there. # there.
next(unpacked) next(unpacked)
if self._instance is not None:
yield None, LazyKnownValue(self._instance)
for key_lazy_value in unpacked: for key_lazy_value in unpacked:
yield key_lazy_value yield key_lazy_value
for key_lazy_value in self._call_arguments.unpack(funcdef): for key_lazy_value in self._call_arguments.unpack(funcdef):
@@ -592,7 +596,7 @@ 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) PartialMethodObject(instance, arguments, instance) # FIXME pass correct instance as last arg
for instance in value.py__call__(arguments) for instance in value.py__call__(arguments)
) )

View File

@@ -169,12 +169,24 @@ X().a('')[0]
#? str() #? str()
X().a('')[1] X().a('')[1]
#? int()
X.a(X(), '')[0]
#? str()
X.a(X(), '')[1]
tup = X().kw(1) tup = X().kw(1)
#? int() #? int()
tup[0] tup[0]
#? float() #? float()
tup[1] tup[1]
tup = X.kw(X(), 1)
#? int()
tup[0]
#? float()
tup[1]
def my_decorator(f): def my_decorator(f):
@functools.wraps(f) @functools.wraps(f)
def wrapper(*args, **kwds): def wrapper(*args, **kwds):

View File

@@ -100,6 +100,8 @@ class X:
(partialmethod_code + 'X().b(', 'func(b, c)'), (partialmethod_code + 'X().b(', 'func(b, c)'),
(partialmethod_code + 'X().c(', 'func(b)'), (partialmethod_code + 'X().c(', 'func(b)'),
(partialmethod_code + 'X().d(', None), (partialmethod_code + 'X().d(', None),
(partialmethod_code + 'X.c(', 'func(b)'),
(partialmethod_code + 'X.d(', None),
] ]
) )
def test_tree_signature(Script, environment, code, expected): def test_tree_signature(Script, environment, code, expected):