Skip to content
Snippets Groups Projects
Commit 0c12da2b authored by Piotr Maślanka's avatar Piotr Maślanka
Browse files

2.11.33 bugfix

parent facb0e12
No related branches found
No related tags found
No related merge requests found
# v2.11.33
* bugfix release: a fix for a certain bug involving `get_arguments` and `classmethod`
__version__ = '2.11.33_a1'
__version__ = '2.11.33'
......@@ -104,6 +104,9 @@ def get_arguments(function: tp.Callable, *args, **kwargs) -> \
Return local variables that would be defined for given function if called with
provided arguments.
Note that this function will not return the "self" argument of methods
and it won't return the class of "cls" of classmethods.
:param function: callable to examine
:param args: arguments to provide
:param kwargs: keyword arguments to provide
......@@ -129,36 +132,36 @@ def _get_arguments(function: tp.Callable, special_behaviour: bool, *args, **kwar
Parameter.VAR_POSITIONAL)]
args = list(reversed(args))
params_taken = set()
while len(positionals) > 0:
arguments_left = set(param.name for param in params)
while len(positionals):
arg = positionals.pop()
if arg.kind == Parameter.VAR_POSITIONAL and not special_behaviour:
local_vars[arg.name] = tuple(reversed(args))
arg_kind = arg.kind
arg_name = arg.name
if arg_kind == Parameter.VAR_POSITIONAL and not special_behaviour:
local_vars[arg_name] = tuple(reversed(args))
else:
try:
v = args.pop()
arguments_left.remove(arg_name)
except IndexError:
if arg.default == Parameter.empty:
if special_behaviour:
v = None
else:
raise TypeError('Not enough arguments')
break
else:
v = arg.default
local_vars[arg.name] = v
params_taken.add(arg.name)
local_vars[arg_name] = v
keywords = [param for param in params if param.kind in (Parameter.POSITIONAL_OR_KEYWORD,
Parameter.KEYWORD_ONLY,
Parameter.VAR_KEYWORD)
and param.name not in params_taken]
and param.name in arguments_left]
for keyword in keywords:
keyword_name = keyword.name
if keyword.kind == Parameter.VAR_KEYWORD and not special_behaviour:
local_vars[keyword.name] = kwargs
local_vars[keyword_name] = kwargs
else:
try:
v = kwargs.pop(keyword.name)
v = kwargs.pop(keyword_name)
except KeyError:
if keyword.default == Parameter.empty:
if special_behaviour:
......@@ -168,7 +171,15 @@ def _get_arguments(function: tp.Callable, special_behaviour: bool, *args, **kwar
else:
v = keyword.default
local_vars[keyword.name] = v
local_vars[keyword_name] = v
for param in params:
param_name = param.name
if param_name not in local_vars:
if special_behaviour:
local_vars[param_name] = None
else:
raise TypeError('Not enough keyword arguments')
return local_vars
......
import unittest
from satella.coding import precondition, short_none, has_keys, update_if_not_none, postcondition
from satella.coding import precondition, short_none, has_keys, update_if_not_none, postcondition, \
get_arguments
from satella.coding.decorators import for_argument
from satella.exceptions import PreconditionError
class TestTypecheck(unittest.TestCase):
def test_get_arguments_bug(self):
class Class:
@classmethod
def execute(cls, password: str, service: str,
absolute_expiration=None,
metadata=None):
pass
def method_call(self, password: str, service: str,
absolute_expiration=None,
metadata=None):
pass
kls = Class()
args = get_arguments(Class.execute, '1234',
'service', metadata={'ok': 'meta'})
self.assertEqual(args, {
'password': '1234',
'service': 'service',
'metadata': {'ok': 'meta'},
'absolute_expiration': None
})
args = get_arguments(kls.method_call, '1234', 'service', metadata={'ok': 'meta'})
self.assertEqual(args, {
'password': '1234',
'service': 'service',
'metadata': {'ok': 'meta'},
'absolute_expiration': None
})
self.assertRaises(TypeError, lambda: get_arguments(kls.method_call, '1234'))
self.assertRaises(TypeError, lambda: get_arguments(Class.execute, '1234'))
def test_for_argument_extended(self):
@for_argument(int)
def accept_default(a=5):
def accept_default(a='5'):
return a
self.assertEqual(accept_default(6), 6)
self.assertEqual(accept_default('6'), 6)
self.assertEqual(accept_default(), 5)
def test_for_argument_str(self):
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment