<div dir="ltr">Here's a proof-of-concept for the decorator. It does not address the issue of passing aliases to positional arguments to **kwargs - I guess this requires changes in the CPython's core.<div><br></div><div>(Sorry about the coloring, that's how it's pasted)<br><br><div><pre style="background-color:rgb(43,43,43);color:rgb(169,183,198);font-family:"courier new";font-size:9pt"><span style="color:rgb(204,120,50);font-weight:bold">from </span>inspect <span style="color:rgb(204,120,50);font-weight:bold">import </span>signature<span style="color:rgb(204,120,50)">, </span>Parameter<br><span style="color:rgb(204,120,50);font-weight:bold">from </span>functools <span style="color:rgb(204,120,50);font-weight:bold">import </span>wraps<br><br><br><span style="color:rgb(204,120,50);font-weight:bold">def </span><span style="font-weight:bold">positional_only</span>(n):<br> <span style="color:rgb(204,120,50);font-weight:bold">def </span><span style="font-weight:bold">wrap</span>(f):<br> s = signature(f)<br> params = <span style="color:rgb(136,136,198)">list</span>(s.parameters.values())<br> <span style="color:rgb(204,120,50);font-weight:bold">for </span>i <span style="color:rgb(204,120,50);font-weight:bold">in </span><span style="color:rgb(136,136,198)">range</span>(n):<br> <span style="color:rgb(204,120,50);font-weight:bold">if </span>params[i].kind != Parameter.POSITIONAL_OR_KEYWORD:<br> <span style="color:rgb(204,120,50);font-weight:bold">raise </span><span style="color:rgb(136,136,198)">TypeError</span>(<span style="color:rgb(0,128,128)">'{} has less than {} positional arguments'</span>.format(f.<span style="color:rgb(178,0,178)">__name__</span><span style="color:rgb(204,120,50)">, </span>n))<br> params[i] = params[i].replace(<span style="color:rgb(170,73,38)">kind</span>=Parameter.POSITIONAL_ONLY)<br> f.__signature__ = s.replace(<span style="font-size:9pt;color:rgb(170,73,38)">parameters</span><span style="font-size:9pt">=params)</span>
<br> @<span style="color:rgb(187,181,41)">wraps</span>(f)<br> <span style="color:rgb(204,120,50);font-weight:bold">def </span><span style="font-weight:bold">inner</span>(*args<span style="color:rgb(204,120,50)">, </span>**kwargs):<br> <span style="color:rgb(204,120,50);font-weight:bold">if </span><span style="color:rgb(136,136,198)">len</span>(args) < n:<br> <span style="color:rgb(204,120,50);font-weight:bold">raise </span><span style="color:rgb(136,136,198)">TypeError</span>(<span style="color:rgb(0,128,128)">'{} takes at least {} positional arguments'</span>.format(f.<span style="color:rgb(178,0,178)">__name__</span><span style="color:rgb(204,120,50)">, </span>n))<br> <span style="color:rgb(204,120,50);font-weight:bold">return </span>f(*args<span style="color:rgb(204,120,50)">, </span>**kwargs)<br> <span style="color:rgb(204,120,50);font-weight:bold">return </span>inner<br> <span style="color:rgb(204,120,50);font-weight:bold">return </span>wrap<br><br><br>@<span style="color:rgb(187,181,41)">positional_only</span>(<span style="color:rgb(104,151,187)">2</span>)<br><span style="color:rgb(204,120,50);font-weight:bold">def </span><span style="font-weight:bold">f</span>(a<span style="color:rgb(204,120,50)">, </span>b<span style="color:rgb(204,120,50)">, </span>c):<br> <span style="color:rgb(136,136,198)">print</span>(a<span style="color:rgb(204,120,50)">, </span>b<span style="color:rgb(204,120,50)">, </span>c)<br><br><br><span style="color:rgb(136,136,198)">help</span>(f)<br><span style="color:rgb(128,128,128)"># f(a, b, /, c, **kwargs)<br></span><span style="color:rgb(128,128,128)"><br></span>f(<span style="color:rgb(104,151,187)">1</span><span style="color:rgb(204,120,50)">, </span><span style="color:rgb(104,151,187)">2</span><span style="color:rgb(204,120,50)">, </span><span style="color:rgb(170,73,38)">c</span>=<span style="color:rgb(104,151,187)">2</span>)<br><br><span style="color:rgb(128,128,128)"># f(1, b=2, c=3)<br></span><span style="color:rgb(128,128,128)"># TypeError: f takes at least 2 positional arguments<br></span><span style="color:rgb(128,128,128)"><br></span><span style="color:rgb(128,128,128)"><br></span>@<span style="color:rgb(187,181,41)">positional_only</span>(<span style="color:rgb(104,151,187)">3</span>)<br><span style="color:rgb(204,120,50);font-weight:bold">def </span><span style="font-weight:bold">g</span>(a<span style="color:rgb(204,120,50)">, </span>b<span style="color:rgb(204,120,50)">, </span>*<span style="color:rgb(204,120,50)">, </span>c):<br> <span style="color:rgb(136,136,198)">print</span>(a<span style="color:rgb(204,120,50)">, </span>b<span style="color:rgb(204,120,50)">, </span>c)<br><br><span style="color:rgb(128,128,128)"># TypeError: g has less than 3 positional arguments<br></span></pre></div><div>Elazar</div></div></div>