We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
There was an error while loading. Please reload this page.
1 parent 1c8d73e commit a8bd3aeCopy full SHA for a8bd3ae
Lib/functools.py
@@ -343,10 +343,8 @@ def _partial_new(cls, func, /, *args, **keywords):
343
if nargs > pto_phcount:
344
tot_args += args[pto_phcount:]
345
phcount, merger = _partial_prepare_merger(tot_args)
346
- elif pto_phcount: # not args and pto_phcount
+ else: # works for both pto_phcount == 0 and != 0
347
phcount, merger = pto_phcount, func._merger
348
- else: # not args and not pto_phcount
349
- phcount, merger = 0, None
350
keywords = {**func.keywords, **keywords}
351
func = func.func
352
else:
Lib/inspect.py
@@ -1933,7 +1933,10 @@ def _signature_get_partial(wrapped_sig, partial, extra_args=()):
1933
# If positional-only parameter is bound by partial,
1934
# it effectively disappears from the signature
1935
# However, if it is a Placeholder it is not removed
1936
- if arg_value is not functools.Placeholder:
+ # And also looses default value
1937
+ if arg_value is functools.Placeholder:
1938
+ new_params[param_name] = param.replace(default=_empty)
1939
+ else:
1940
new_params.pop(param_name)
1941
continue
1942
@@ -1957,9 +1960,13 @@ def _signature_get_partial(wrapped_sig, partial, extra_args=()):
1957
1960
1958
1961
# was passed as a positional argument
1959
1962
# Do not pop if it is a Placeholder
- # and change kind to positional only
1963
+ # also change kind to positional only
1964
+ # and remove default
1965
if arg_value is functools.Placeholder:
- new_param = param.replace(kind=_POSITIONAL_ONLY)
1966
+ new_param = param.replace(
1967
+ kind=_POSITIONAL_ONLY,
1968
+ default=_empty
1969
+ )
1970
new_params[param_name] = new_param
1971
1972
Lib/test/test_functools.py
@@ -242,6 +242,12 @@ def test_placeholders_optimization(self):
242
got, empty = p3(5)
243
expected = (-1, 0, 1, 2, 3, 4, 5)
244
self.assertTrue(expected == got and empty == {})
245
+ # inner partial has placeholders and outer partial has no args case
246
+ p = self.partial(capture, PH, 0)
247
+ p2 = self.partial(p)
248
+ expected = (PH, 0)
249
+ self.assertTrue(expected == p2.args)
250
+ self.assertTrue(((1, 0), {}) == p2(1))
251
252
def test_construct_placeholder_singleton(self):
253
PH = self.module.Placeholder
@@ -550,7 +556,7 @@ class TestPartialPySubclass(TestPartialPy):
550
556
def test_subclass_optimization(self):
551
557
p = py_functools.partial(min, 2)
552
558
p2 = self.partial(p, 1)
553
- assert p2.func == min
559
+ assert p2.func is min
554
560
assert p2(0) == 0
555
561
562
@@ -696,7 +702,7 @@ class PartialMethodSubclass(functools.partialmethod):
696
702
pass
697
703
p = functools.partialmethod(min, 2)
698
704
p2 = PartialMethodSubclass(p, 1)
699
705
700
706
assert p2.__get__(0)() == 0
701
707
708
Lib/test/test_inspect/test_inspect.py
@@ -3523,16 +3523,16 @@ def foo(a=0, b=1, /, c=2, d=3):
3523
# Positional
3524
p = partial(foo, Placeholder, 1, c=0, d=1)
3525
self.assertEqual(self.signature(p),
3526
- ((('a', 0, ..., "positional_only"),
+ ((('a', ..., ..., "positional_only"),
3527
('c', 0, ..., "keyword_only"),
3528
('d', 1, ..., "keyword_only")),
3529
...))
3530
3531
# Positional or Keyword - transformed to positional
3532
p = partial(foo, Placeholder, 1, Placeholder, 1)
3533
3534
3535
- ('c', 2, ..., "positional_only")),
+ ('c', ..., ..., "positional_only")),
3536
3537
3538
def test_signature_on_partialmethod(self):
Modules/_functoolsmodule.c
@@ -656,12 +656,6 @@ partial_setstate(partialobject *pto, PyObject *state)
656
PyErr_SetString(PyExc_TypeError, "invalid partial state");
657
return NULL;
658
}
659
- Py_ssize_t state_len = PyTuple_GET_SIZE(state);
660
- if (state_len != 4) {
661
- PyErr_Format(PyExc_TypeError,
662
- "expected 4 items in state, got %zd", state_len);
663
- return NULL;
664
- }
665
if (!PyArg_ParseTuple(state, "OOOO", &fn, &fnargs, &kw, &dict) ||
666
!PyCallable_Check(fn) ||
667
!PyTuple_Check(fnargs) ||
0 commit comments