Skip to content

Commit 878531c

Browse files
committed
-
1 parent 881b537 commit 878531c

File tree

3 files changed

+45
-11
lines changed

3 files changed

+45
-11
lines changed

source_py3/python_toolbox/dict_tools.py

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
from python_toolbox import comparison_tools
1010

1111

12-
def filter_items(d, condition, force_dict_type=None):
12+
def filter_items(d, condition, double=False, force_dict_type=None):
1313
'''
1414
Get new dict with items from `d` that satisfy the `condition` functions.
1515
@@ -18,16 +18,31 @@ def filter_items(d, condition, force_dict_type=None):
1818
The newly created dict will be of the same class as `d`, e.g. if you passed
1919
an ordered dict as `d`, the result will be an ordered dict, using the
2020
correct order.
21+
22+
Specify `double=True` to get a tuple of two dicts instead of one. The
23+
second dict will have all the rejected items.
2124
'''
2225
# todo future: possibly shallow-copy `d` to allow for dict classes that
2326
# have more state, (like default factory.)
2427
if force_dict_type is not None:
2528
dict_type = force_dict_type
2629
else:
2730
dict_type = type(d) if (type(d).__name__ != 'dictproxy') else dict
28-
return dict_type(
29-
(key, value) for (key, value) in d.items() if condition(key, value)
30-
)
31+
32+
if double:
33+
return tuple(
34+
map(
35+
dict_type,
36+
cute_iter_tools.double_filter(
37+
lambda key_value: condition(key_value[0], key_value[1]),
38+
d.items()
39+
)
40+
)
41+
)
42+
else:
43+
return dict_type(
44+
(key, value) for (key, value) in d.items() if condition(key, value)
45+
)
3146

3247

3348
def get_list(d, iterable):

source_py3/python_toolbox/monkeypatching_tools.py

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -88,29 +88,48 @@ def decorator(function):
8888
return decorator
8989

9090

91-
def change_defaults(function, new_defaults={}):
91+
def change_defaults(function=None, new_defaults={}):
9292
def change_defaults_(function_, new_defaults_):
9393
signature = inspect.Signature.from_function(function_)
9494
defaults = list(function_.__defaults__ or ())
95+
kwdefaults = function_.__kwdefaults__ or {}
9596
defaultful_parameters = dict_tools.filter_items(
9697
signature.parameters,
9798
lambda name, parameter: parameter.default != inspect._empty,
9899
force_dict_type=collections.OrderedDict
99100
)
100-
for i, parameter_name in enumerate(defaultful_parameters):
101+
(keyword_only_defaultful_parameters,
102+
non_keyword_only_defaultful_parameters) = dict_tools.filter_items(
103+
defaultful_parameters,
104+
lambda name, parameter: parameter.kind == inspect._KEYWORD_ONLY,
105+
double=True,
106+
)
107+
108+
for parameter_name in keyword_only_defaultful_parameters:
109+
if parameter_name in new_defaults_:
110+
kwdefaults[parameter_name] = new_defaults_[parameter_name]
111+
112+
for i, parameter_name in \
113+
enumerate(non_keyword_only_defaultful_parameters):
101114
if parameter_name in new_defaults_:
102115
defaults[i] = new_defaults_[parameter_name]
103116

104117
function_.__defaults__ = tuple(defaults)
118+
function_.__kwdefaults__ = kwdefaults
119+
120+
return function_
105121

106-
if not callable(function) and new_defaults == {}:
122+
if not callable(function):
107123
# Decorator mode:
108-
actual_new_defaults = new_defaults or function or {}
124+
if function is None:
125+
actual_new_defaults = new_defaults
126+
else:
127+
actual_new_defaults = function
109128
return lambda function_: change_defaults_(function_,
110129
actual_new_defaults)
111130
else:
112131
# Normal usage mode:
113-
change_defaults_(function, new_defaults)
132+
return change_defaults_(function, new_defaults)
114133

115134

116135

source_py3/test_python_toolbox/test_monkeypatching_tools/test_change_defaults.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@ def f1(alpha, beta, *args, gamma=10, delta=20, **kwargs):
1717
@monkeypatching_tools.change_defaults({'gamma': 100})
1818
def f2(alpha, beta, *args, gamma=10, delta=20, **kwargs):
1919
return (alpha, beta, args, gamma, delta, kwargs)
20-
assert f2(1, 2) == (1, 2, (), 100, 400, {})
20+
assert f2(1, 2) == (1, 2, (), 100, 20, {})
2121

2222
@monkeypatching_tools.change_defaults(new_defaults={'gamma': 1000})
2323
def f3(alpha, beta, *args, gamma=10, delta=20, **kwargs):
2424
return (alpha, beta, args, gamma, delta, kwargs)
25-
assert f3(1, 2) == (1, 2, (), 1000, 400, {})
25+
assert f3(1, 2) == (1, 2, (), 1000, 20, {})
2626

0 commit comments

Comments
 (0)