mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 21:51:50 +00:00 
			
		
		
		
	bpo-37122: Make co->co_argcount represent the total number of positonal arguments in the code object (GH-13726)
This commit is contained in:
		
							parent
							
								
									059b9ea5ac
								
							
						
					
					
						commit
						cd74e66a8c
					
				
					 14 changed files with 74 additions and 88 deletions
				
			
		|  | @ -42,6 +42,8 @@ bound into a function. | ||||||
| 
 | 
 | ||||||
|    .. versionchanged:: 3.8 |    .. versionchanged:: 3.8 | ||||||
|       An extra parameter is required (*posonlyargcount*) to support :PEP:`570`. |       An extra parameter is required (*posonlyargcount*) to support :PEP:`570`. | ||||||
|  |       The first parameter (*argcount*) now represents the total number of positional arguments, | ||||||
|  |       including positional-only. | ||||||
| 
 | 
 | ||||||
|    .. audit-event:: code.__new__ "code filename name argcount kwonlyargcount nlocals stacksize flags" |    .. audit-event:: code.__new__ "code filename name argcount kwonlyargcount nlocals stacksize flags" | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -907,24 +907,26 @@ Internal types | ||||||
|          single: co_freevars (code object attribute) |          single: co_freevars (code object attribute) | ||||||
| 
 | 
 | ||||||
|       Special read-only attributes: :attr:`co_name` gives the function name; |       Special read-only attributes: :attr:`co_name` gives the function name; | ||||||
|       :attr:`co_argcount` is the number of positional arguments (including arguments |       :attr:`co_argcount` is the total number of positional arguments | ||||||
|       with default values); :attr:`co_posonlyargcount` is the number of |       (including positional-only arguments and arguments with default values); | ||||||
|       positional-only arguments (including arguments with default values); |       :attr:`co_posonlyargcount` is the number of positional-only arguments | ||||||
|       :attr:`co_kwonlyargcount` is the number of keyword-only arguments (including |       (including arguments with default values); :attr:`co_kwonlyargcount` is | ||||||
|       arguments with default values); :attr:`co_nlocals` is the number of local |       the number of keyword-only arguments (including arguments with default | ||||||
|       variables used by the function (including arguments); :attr:`co_varnames` is a |       values); :attr:`co_nlocals` is the number of local variables used by the | ||||||
|       tuple containing the names of the local variables (starting with the argument |       function (including arguments); :attr:`co_varnames` is a tuple containing | ||||||
|       names); :attr:`co_cellvars` is a tuple containing the names of local variables |       the names of the local variables (starting with the argument names); | ||||||
|  |       :attr:`co_cellvars` is a tuple containing the names of local variables | ||||||
|       that are referenced by nested functions; :attr:`co_freevars` is a tuple |       that are referenced by nested functions; :attr:`co_freevars` is a tuple | ||||||
|       containing the names of free variables; :attr:`co_code` is a string representing |       containing the names of free variables; :attr:`co_code` is a string | ||||||
|       the sequence of bytecode instructions; :attr:`co_consts` is a tuple containing |       representing the sequence of bytecode instructions; :attr:`co_consts` is | ||||||
|       the literals used by the bytecode; :attr:`co_names` is a tuple containing the |       a tuple containing the literals used by the bytecode; :attr:`co_names` is | ||||||
|       names used by the bytecode; :attr:`co_filename` is the filename from which the |       a tuple containing the names used by the bytecode; :attr:`co_filename` is | ||||||
|       code was compiled; :attr:`co_firstlineno` is the first line number of the |       the filename from which the code was compiled; :attr:`co_firstlineno` is | ||||||
|       function; :attr:`co_lnotab` is a string encoding the mapping from bytecode |       the first line number of the function; :attr:`co_lnotab` is a string | ||||||
|       offsets to line numbers (for details see the source code of the interpreter); |       encoding the mapping from bytecode offsets to line numbers (for details | ||||||
|       :attr:`co_stacksize` is the required stack size (including local variables); |       see the source code of the interpreter); :attr:`co_stacksize` is the | ||||||
|       :attr:`co_flags` is an integer encoding a number of flags for the interpreter. |       required stack size (including local variables); :attr:`co_flags` is an | ||||||
|  |       integer encoding a number of flags for the interpreter. | ||||||
| 
 | 
 | ||||||
|       .. index:: object: generator |       .. index:: object: generator | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1177,8 +1177,10 @@ Changes in the Python API | ||||||
| 
 | 
 | ||||||
| * :class:`types.CodeType` has a new parameter in the second position of the | * :class:`types.CodeType` has a new parameter in the second position of the | ||||||
|   constructor (*posonlyargcount*) to support positional-only arguments defined |   constructor (*posonlyargcount*) to support positional-only arguments defined | ||||||
|   in :pep:`570`. A new ``replace()`` method of :class:`types.CodeType` can be |   in :pep:`570`. The first argument (*argcount*) now represents the total | ||||||
|   used to make the code future-proof. |   number of positional arguments (including positional-only arguments). A new | ||||||
|  |   ``replace()`` method of :class:`types.CodeType` can be used to make the code | ||||||
|  |   future-proof. | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| Changes in the C API | Changes in the C API | ||||||
|  |  | ||||||
|  | @ -1037,15 +1037,11 @@ def getargs(co): | ||||||
| 
 | 
 | ||||||
|     names = co.co_varnames |     names = co.co_varnames | ||||||
|     nargs = co.co_argcount |     nargs = co.co_argcount | ||||||
|     nposonlyargs = co.co_posonlyargcount |  | ||||||
|     nkwargs = co.co_kwonlyargcount |     nkwargs = co.co_kwonlyargcount | ||||||
|     nposargs = nargs + nposonlyargs |     args = list(names[:nargs]) | ||||||
|     posonlyargs = list(names[:nposonlyargs]) |     kwonlyargs = list(names[nargs:nargs+nkwargs]) | ||||||
|     args = list(names[nposonlyargs:nposonlyargs+nargs]) |  | ||||||
|     kwonlyargs = list(names[nposargs:nposargs+nkwargs]) |  | ||||||
|     step = 0 |     step = 0 | ||||||
| 
 | 
 | ||||||
|     nargs += nposonlyargs |  | ||||||
|     nargs += nkwargs |     nargs += nkwargs | ||||||
|     varargs = None |     varargs = None | ||||||
|     if co.co_flags & CO_VARARGS: |     if co.co_flags & CO_VARARGS: | ||||||
|  | @ -1054,7 +1050,7 @@ def getargs(co): | ||||||
|     varkw = None |     varkw = None | ||||||
|     if co.co_flags & CO_VARKEYWORDS: |     if co.co_flags & CO_VARKEYWORDS: | ||||||
|         varkw = co.co_varnames[nargs] |         varkw = co.co_varnames[nargs] | ||||||
|     return Arguments(posonlyargs + args + kwonlyargs, varargs, varkw) |     return Arguments(args + kwonlyargs, varargs, varkw) | ||||||
| 
 | 
 | ||||||
| ArgSpec = namedtuple('ArgSpec', 'args varargs keywords defaults') | ArgSpec = namedtuple('ArgSpec', 'args varargs keywords defaults') | ||||||
| 
 | 
 | ||||||
|  | @ -2136,11 +2132,9 @@ def _signature_from_function(cls, func, skip_bound_arg=True): | ||||||
|     pos_count = func_code.co_argcount |     pos_count = func_code.co_argcount | ||||||
|     arg_names = func_code.co_varnames |     arg_names = func_code.co_varnames | ||||||
|     posonly_count = func_code.co_posonlyargcount |     posonly_count = func_code.co_posonlyargcount | ||||||
|     positional_count = posonly_count + pos_count |     positional = arg_names[:pos_count] | ||||||
|     positional_only = tuple(arg_names[:posonly_count]) |  | ||||||
|     positional = tuple(arg_names[posonly_count:positional_count]) |  | ||||||
|     keyword_only_count = func_code.co_kwonlyargcount |     keyword_only_count = func_code.co_kwonlyargcount | ||||||
|     keyword_only = arg_names[positional_count:(positional_count + keyword_only_count)] |     keyword_only = arg_names[pos_count:pos_count + keyword_only_count] | ||||||
|     annotations = func.__annotations__ |     annotations = func.__annotations__ | ||||||
|     defaults = func.__defaults__ |     defaults = func.__defaults__ | ||||||
|     kwdefaults = func.__kwdefaults__ |     kwdefaults = func.__kwdefaults__ | ||||||
|  | @ -2152,13 +2146,11 @@ def _signature_from_function(cls, func, skip_bound_arg=True): | ||||||
| 
 | 
 | ||||||
|     parameters = [] |     parameters = [] | ||||||
| 
 | 
 | ||||||
|     non_default_count = positional_count - pos_default_count |     non_default_count = pos_count - pos_default_count | ||||||
|     all_positional = positional_only + positional |  | ||||||
| 
 |  | ||||||
|     posonly_left = posonly_count |     posonly_left = posonly_count | ||||||
| 
 | 
 | ||||||
|     # Non-keyword-only parameters w/o defaults. |     # Non-keyword-only parameters w/o defaults. | ||||||
|     for name in all_positional[:non_default_count]: |     for name in positional[:non_default_count]: | ||||||
|         kind = _POSITIONAL_ONLY if posonly_left else _POSITIONAL_OR_KEYWORD |         kind = _POSITIONAL_ONLY if posonly_left else _POSITIONAL_OR_KEYWORD | ||||||
|         annotation = annotations.get(name, _empty) |         annotation = annotations.get(name, _empty) | ||||||
|         parameters.append(Parameter(name, annotation=annotation, |         parameters.append(Parameter(name, annotation=annotation, | ||||||
|  | @ -2167,7 +2159,7 @@ def _signature_from_function(cls, func, skip_bound_arg=True): | ||||||
|             posonly_left -= 1 |             posonly_left -= 1 | ||||||
| 
 | 
 | ||||||
|     # ... w/ defaults. |     # ... w/ defaults. | ||||||
|     for offset, name in enumerate(all_positional[non_default_count:]): |     for offset, name in enumerate(positional[non_default_count:]): | ||||||
|         kind = _POSITIONAL_ONLY if posonly_left else _POSITIONAL_OR_KEYWORD |         kind = _POSITIONAL_ONLY if posonly_left else _POSITIONAL_OR_KEYWORD | ||||||
|         annotation = annotations.get(name, _empty) |         annotation = annotations.get(name, _empty) | ||||||
|         parameters.append(Parameter(name, annotation=annotation, |         parameters.append(Parameter(name, annotation=annotation, | ||||||
|  | @ -2178,7 +2170,7 @@ def _signature_from_function(cls, func, skip_bound_arg=True): | ||||||
| 
 | 
 | ||||||
|     # *args |     # *args | ||||||
|     if func_code.co_flags & CO_VARARGS: |     if func_code.co_flags & CO_VARARGS: | ||||||
|         name = arg_names[positional_count + keyword_only_count] |         name = arg_names[pos_count + keyword_only_count] | ||||||
|         annotation = annotations.get(name, _empty) |         annotation = annotations.get(name, _empty) | ||||||
|         parameters.append(Parameter(name, annotation=annotation, |         parameters.append(Parameter(name, annotation=annotation, | ||||||
|                                     kind=_VAR_POSITIONAL)) |                                     kind=_VAR_POSITIONAL)) | ||||||
|  | @ -2195,7 +2187,7 @@ def _signature_from_function(cls, func, skip_bound_arg=True): | ||||||
|                                     default=default)) |                                     default=default)) | ||||||
|     # **kwargs |     # **kwargs | ||||||
|     if func_code.co_flags & CO_VARKEYWORDS: |     if func_code.co_flags & CO_VARKEYWORDS: | ||||||
|         index = positional_count + keyword_only_count |         index = pos_count + keyword_only_count | ||||||
|         if func_code.co_flags & CO_VARARGS: |         if func_code.co_flags & CO_VARARGS: | ||||||
|             index += 1 |             index += 1 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1132,7 +1132,7 @@ def do_args(self, arg): | ||||||
|         """ |         """ | ||||||
|         co = self.curframe.f_code |         co = self.curframe.f_code | ||||||
|         dict = self.curframe_locals |         dict = self.curframe_locals | ||||||
|         n = co.co_argcount + co.co_posonlyargcount + co.co_kwonlyargcount |         n = co.co_argcount + co.co_kwonlyargcount | ||||||
|         if co.co_flags & inspect.CO_VARARGS: n = n+1 |         if co.co_flags & inspect.CO_VARARGS: n = n+1 | ||||||
|         if co.co_flags & inspect.CO_VARKEYWORDS: n = n+1 |         if co.co_flags & inspect.CO_VARKEYWORDS: n = n+1 | ||||||
|         for i in range(n): |         for i in range(n): | ||||||
|  |  | ||||||
|  | @ -112,7 +112,7 @@ | ||||||
| 
 | 
 | ||||||
| >>> dump(posonly_args.__code__) | >>> dump(posonly_args.__code__) | ||||||
| name: posonly_args | name: posonly_args | ||||||
| argcount: 1 | argcount: 3 | ||||||
| posonlyargcount: 2 | posonlyargcount: 2 | ||||||
| kwonlyargcount: 0 | kwonlyargcount: 0 | ||||||
| names: () | names: () | ||||||
|  |  | ||||||
|  | @ -640,7 +640,7 @@ def f(c=c): | ||||||
| code_info_tricky = """\ | code_info_tricky = """\ | ||||||
| Name:              tricky | Name:              tricky | ||||||
| Filename:          (.*) | Filename:          (.*) | ||||||
| Argument count:    3 | Argument count:    5 | ||||||
| Positional-only arguments: 2 | Positional-only arguments: 2 | ||||||
| Kw-only arguments: 3 | Kw-only arguments: 3 | ||||||
| Number of locals:  10 | Number of locals:  10 | ||||||
|  |  | ||||||
|  | @ -100,14 +100,14 @@ def test_pos_only_definition(self): | ||||||
|         def f(a, b, c, /, d, e=1, *, f, g=2): |         def f(a, b, c, /, d, e=1, *, f, g=2): | ||||||
|             pass |             pass | ||||||
| 
 | 
 | ||||||
|         self.assertEqual(2, f.__code__.co_argcount)  # 2 "standard args" |         self.assertEqual(5, f.__code__.co_argcount)  # 3 posonly + 2 "standard args" | ||||||
|         self.assertEqual(3, f.__code__.co_posonlyargcount) |         self.assertEqual(3, f.__code__.co_posonlyargcount) | ||||||
|         self.assertEqual((1,), f.__defaults__) |         self.assertEqual((1,), f.__defaults__) | ||||||
| 
 | 
 | ||||||
|         def f(a, b, c=1, /, d=2, e=3, *, f, g=4): |         def f(a, b, c=1, /, d=2, e=3, *, f, g=4): | ||||||
|             pass |             pass | ||||||
| 
 | 
 | ||||||
|         self.assertEqual(2, f.__code__.co_argcount)  # 2 "standard args" |         self.assertEqual(5, f.__code__.co_argcount)  # 3 posonly + 2 "standard args" | ||||||
|         self.assertEqual(3, f.__code__.co_posonlyargcount) |         self.assertEqual(3, f.__code__.co_posonlyargcount) | ||||||
|         self.assertEqual((1, 2, 3), f.__defaults__) |         self.assertEqual((1, 2, 3), f.__defaults__) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -0,0 +1,5 @@ | ||||||
|  | Make the *co_argcount* attribute of code objects represent the total number | ||||||
|  | of positional arguments (including positional-only arguments). The value of | ||||||
|  | *co_posonlyargcount* can be used to distinguish which arguments are | ||||||
|  | positional only, and the difference (*co_argcount* - *co_posonlyargcount*) | ||||||
|  | is the number of positional-or-keyword arguments. Patch by Pablo Galindo. | ||||||
|  | @ -308,11 +308,11 @@ _PyFunction_FastCallDict(PyObject *func, PyObject *const *args, Py_ssize_t nargs | ||||||
|         (co->co_flags & ~PyCF_MASK) == (CO_OPTIMIZED | CO_NEWLOCALS | CO_NOFREE)) |         (co->co_flags & ~PyCF_MASK) == (CO_OPTIMIZED | CO_NEWLOCALS | CO_NOFREE)) | ||||||
|     { |     { | ||||||
|         /* Fast paths */ |         /* Fast paths */ | ||||||
|         if (argdefs == NULL && co->co_argcount + co->co_posonlyargcount == nargs) { |         if (argdefs == NULL && co->co_argcount == nargs) { | ||||||
|             return function_code_fastcall(co, args, nargs, globals); |             return function_code_fastcall(co, args, nargs, globals); | ||||||
|         } |         } | ||||||
|         else if (nargs == 0 && argdefs != NULL |         else if (nargs == 0 && argdefs != NULL | ||||||
|                  && co->co_argcount + co->co_posonlyargcount == PyTuple_GET_SIZE(argdefs)) { |                  && co->co_argcount == PyTuple_GET_SIZE(argdefs)) { | ||||||
|             /* function called with no arguments, but all parameters have
 |             /* function called with no arguments, but all parameters have
 | ||||||
|                a default value: use default values as arguments .*/ |                a default value: use default values as arguments .*/ | ||||||
|             args = _PyTuple_ITEMS(argdefs); |             args = _PyTuple_ITEMS(argdefs); | ||||||
|  | @ -396,11 +396,11 @@ _PyFunction_Vectorcall(PyObject *func, PyObject* const* stack, | ||||||
|     if (co->co_kwonlyargcount == 0 && nkwargs == 0 && |     if (co->co_kwonlyargcount == 0 && nkwargs == 0 && | ||||||
|         (co->co_flags & ~PyCF_MASK) == (CO_OPTIMIZED | CO_NEWLOCALS | CO_NOFREE)) |         (co->co_flags & ~PyCF_MASK) == (CO_OPTIMIZED | CO_NEWLOCALS | CO_NOFREE)) | ||||||
|     { |     { | ||||||
|         if (argdefs == NULL && co->co_argcount + co->co_posonlyargcount== nargs) { |         if (argdefs == NULL && co->co_argcount == nargs) { | ||||||
|             return function_code_fastcall(co, stack, nargs, globals); |             return function_code_fastcall(co, stack, nargs, globals); | ||||||
|         } |         } | ||||||
|         else if (nargs == 0 && argdefs != NULL |         else if (nargs == 0 && argdefs != NULL | ||||||
|                  && co->co_argcount + co->co_posonlyargcount == PyTuple_GET_SIZE(argdefs)) { |                  && co->co_argcount == PyTuple_GET_SIZE(argdefs)) { | ||||||
|             /* function called with no arguments, but all parameters have
 |             /* function called with no arguments, but all parameters have
 | ||||||
|                a default value: use default values as arguments .*/ |                a default value: use default values as arguments .*/ | ||||||
|             stack = _PyTuple_ITEMS(argdefs); |             stack = _PyTuple_ITEMS(argdefs); | ||||||
|  |  | ||||||
|  | @ -114,8 +114,9 @@ PyCode_New(int argcount, int posonlyargcount, int kwonlyargcount, | ||||||
|     Py_ssize_t i, n_cellvars, n_varnames, total_args; |     Py_ssize_t i, n_cellvars, n_varnames, total_args; | ||||||
| 
 | 
 | ||||||
|     /* Check argument types */ |     /* Check argument types */ | ||||||
|     if (argcount < 0 || posonlyargcount < 0 || kwonlyargcount < 0 || |     if (argcount < posonlyargcount || posonlyargcount < 0 || | ||||||
|         nlocals < 0 || stacksize < 0 || flags < 0 || |         kwonlyargcount < 0 || nlocals < 0 || | ||||||
|  |         stacksize < 0 || flags < 0 || | ||||||
|         code == NULL || !PyBytes_Check(code) || |         code == NULL || !PyBytes_Check(code) || | ||||||
|         consts == NULL || !PyTuple_Check(consts) || |         consts == NULL || !PyTuple_Check(consts) || | ||||||
|         names == NULL || !PyTuple_Check(names) || |         names == NULL || !PyTuple_Check(names) || | ||||||
|  | @ -152,11 +153,9 @@ PyCode_New(int argcount, int posonlyargcount, int kwonlyargcount, | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     n_varnames = PyTuple_GET_SIZE(varnames); |     n_varnames = PyTuple_GET_SIZE(varnames); | ||||||
|     if (posonlyargcount + argcount <= n_varnames |     if (argcount <= n_varnames && kwonlyargcount <= n_varnames) { | ||||||
|         && kwonlyargcount <= n_varnames) { |  | ||||||
|         /* Never overflows. */ |         /* Never overflows. */ | ||||||
|         total_args = (Py_ssize_t)posonlyargcount + (Py_ssize_t)argcount |         total_args = (Py_ssize_t)argcount + (Py_ssize_t)kwonlyargcount + | ||||||
|                       + (Py_ssize_t)kwonlyargcount + |  | ||||||
|                       ((flags & CO_VARARGS) != 0) + ((flags & CO_VARKEYWORDS) != 0); |                       ((flags & CO_VARARGS) != 0) + ((flags & CO_VARKEYWORDS) != 0); | ||||||
|     } |     } | ||||||
|     else { |     else { | ||||||
|  |  | ||||||
|  | @ -7807,7 +7807,7 @@ super_init(PyObject *self, PyObject *args, PyObject *kwds) | ||||||
|                             "super(): no code object"); |                             "super(): no code object"); | ||||||
|             return -1; |             return -1; | ||||||
|         } |         } | ||||||
|         if (co->co_posonlyargcount + co->co_argcount == 0) { |         if (co->co_argcount == 0) { | ||||||
|             PyErr_SetString(PyExc_RuntimeError, |             PyErr_SetString(PyExc_RuntimeError, | ||||||
|                             "super(): no arguments"); |                             "super(): no arguments"); | ||||||
|             return -1; |             return -1; | ||||||
|  |  | ||||||
|  | @ -3757,10 +3757,10 @@ missing_arguments(PyThreadState *tstate, PyCodeObject *co, | ||||||
|         return; |         return; | ||||||
|     if (positional) { |     if (positional) { | ||||||
|         start = 0; |         start = 0; | ||||||
|         end = co->co_posonlyargcount + co->co_argcount - defcount; |         end = co->co_argcount - defcount; | ||||||
|     } |     } | ||||||
|     else { |     else { | ||||||
|         start = co->co_posonlyargcount + co->co_argcount; |         start = co->co_argcount; | ||||||
|         end = start + co->co_kwonlyargcount; |         end = start + co->co_kwonlyargcount; | ||||||
|     } |     } | ||||||
|     for (i = start; i < end; i++) { |     for (i = start; i < end; i++) { | ||||||
|  | @ -3788,25 +3788,23 @@ too_many_positional(PyThreadState *tstate, PyCodeObject *co, | ||||||
|     Py_ssize_t kwonly_given = 0; |     Py_ssize_t kwonly_given = 0; | ||||||
|     Py_ssize_t i; |     Py_ssize_t i; | ||||||
|     PyObject *sig, *kwonly_sig; |     PyObject *sig, *kwonly_sig; | ||||||
|     Py_ssize_t co_posonlyargcount = co->co_posonlyargcount; |  | ||||||
|     Py_ssize_t co_argcount = co->co_argcount; |     Py_ssize_t co_argcount = co->co_argcount; | ||||||
|     Py_ssize_t total_positional = co_argcount + co_posonlyargcount; |  | ||||||
| 
 | 
 | ||||||
|     assert((co->co_flags & CO_VARARGS) == 0); |     assert((co->co_flags & CO_VARARGS) == 0); | ||||||
|     /* Count missing keyword-only args. */ |     /* Count missing keyword-only args. */ | ||||||
|     for (i = total_positional; i < total_positional + co->co_kwonlyargcount; i++) { |     for (i = co_argcount; i < co_argcount + co->co_kwonlyargcount; i++) { | ||||||
|         if (GETLOCAL(i) != NULL) { |         if (GETLOCAL(i) != NULL) { | ||||||
|             kwonly_given++; |             kwonly_given++; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     if (defcount) { |     if (defcount) { | ||||||
|         Py_ssize_t atleast = total_positional - defcount; |         Py_ssize_t atleast = co_argcount - defcount; | ||||||
|         plural = 1; |         plural = 1; | ||||||
|         sig = PyUnicode_FromFormat("from %zd to %zd", atleast, total_positional); |         sig = PyUnicode_FromFormat("from %zd to %zd", atleast, co_argcount); | ||||||
|     } |     } | ||||||
|     else { |     else { | ||||||
|         plural = (total_positional != 1); |         plural = (co_argcount != 1); | ||||||
|         sig = PyUnicode_FromFormat("%zd", total_positional); |         sig = PyUnicode_FromFormat("%zd", co_argcount); | ||||||
|     } |     } | ||||||
|     if (sig == NULL) |     if (sig == NULL) | ||||||
|         return; |         return; | ||||||
|  | @ -3917,7 +3915,7 @@ _PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals, | ||||||
|     PyObject *retval = NULL; |     PyObject *retval = NULL; | ||||||
|     PyObject **fastlocals, **freevars; |     PyObject **fastlocals, **freevars; | ||||||
|     PyObject *x, *u; |     PyObject *x, *u; | ||||||
|     const Py_ssize_t total_args = co->co_argcount + co->co_kwonlyargcount + co->co_posonlyargcount; |     const Py_ssize_t total_args = co->co_argcount + co->co_kwonlyargcount; | ||||||
|     Py_ssize_t i, j, n; |     Py_ssize_t i, j, n; | ||||||
|     PyObject *kwdict; |     PyObject *kwdict; | ||||||
| 
 | 
 | ||||||
|  | @ -3953,9 +3951,9 @@ _PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals, | ||||||
|         kwdict = NULL; |         kwdict = NULL; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /* Copy positional only arguments into local variables */ |     /* Copy all positional arguments into local variables */ | ||||||
|     if (argcount > co->co_argcount + co->co_posonlyargcount) { |     if (argcount > co->co_argcount) { | ||||||
|         n = co->co_posonlyargcount; |         n = co->co_argcount; | ||||||
|     } |     } | ||||||
|     else { |     else { | ||||||
|         n = argcount; |         n = argcount; | ||||||
|  | @ -3966,20 +3964,6 @@ _PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals, | ||||||
|         SETLOCAL(j, x); |         SETLOCAL(j, x); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
|     /* Copy positional arguments into local variables */ |  | ||||||
|     if (argcount > co->co_argcount + co->co_posonlyargcount) { |  | ||||||
|         n += co->co_argcount; |  | ||||||
|     } |  | ||||||
|     else { |  | ||||||
|         n = argcount; |  | ||||||
|     } |  | ||||||
|     for (i = j; i < n; i++) { |  | ||||||
|         x = args[i]; |  | ||||||
|         Py_INCREF(x); |  | ||||||
|         SETLOCAL(i, x); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /* Pack other positional arguments into the *args argument */ |     /* Pack other positional arguments into the *args argument */ | ||||||
|     if (co->co_flags & CO_VARARGS) { |     if (co->co_flags & CO_VARARGS) { | ||||||
|         u = _PyTuple_FromArray(args + n, argcount - n); |         u = _PyTuple_FromArray(args + n, argcount - n); | ||||||
|  | @ -4059,14 +4043,14 @@ _PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals, | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /* Check the number of positional arguments */ |     /* Check the number of positional arguments */ | ||||||
|     if ((argcount > co->co_argcount + co->co_posonlyargcount) && !(co->co_flags & CO_VARARGS)) { |     if ((argcount > co->co_argcount) && !(co->co_flags & CO_VARARGS)) { | ||||||
|         too_many_positional(tstate, co, argcount, defcount, fastlocals); |         too_many_positional(tstate, co, argcount, defcount, fastlocals); | ||||||
|         goto fail; |         goto fail; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /* Add missing positional arguments (copy default values from defs) */ |     /* Add missing positional arguments (copy default values from defs) */ | ||||||
|     if (argcount < co->co_posonlyargcount + co->co_argcount) { |     if (argcount < co->co_argcount) { | ||||||
|         Py_ssize_t m = co->co_posonlyargcount + co->co_argcount - defcount; |         Py_ssize_t m = co->co_argcount - defcount; | ||||||
|         Py_ssize_t missing = 0; |         Py_ssize_t missing = 0; | ||||||
|         for (i = argcount; i < m; i++) { |         for (i = argcount; i < m; i++) { | ||||||
|             if (GETLOCAL(i) == NULL) { |             if (GETLOCAL(i) == NULL) { | ||||||
|  | @ -4093,7 +4077,7 @@ _PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals, | ||||||
|     /* Add missing keyword arguments (copy default values from kwdefs) */ |     /* Add missing keyword arguments (copy default values from kwdefs) */ | ||||||
|     if (co->co_kwonlyargcount > 0) { |     if (co->co_kwonlyargcount > 0) { | ||||||
|         Py_ssize_t missing = 0; |         Py_ssize_t missing = 0; | ||||||
|         for (i = co->co_posonlyargcount + co->co_argcount; i < total_args; i++) { |         for (i = co->co_argcount; i < total_args; i++) { | ||||||
|             PyObject *name; |             PyObject *name; | ||||||
|             if (GETLOCAL(i) != NULL) |             if (GETLOCAL(i) != NULL) | ||||||
|                 continue; |                 continue; | ||||||
|  |  | ||||||
|  | @ -5764,7 +5764,7 @@ makecode(struct compiler *c, struct assembler *a) | ||||||
|     Py_ssize_t nlocals; |     Py_ssize_t nlocals; | ||||||
|     int nlocals_int; |     int nlocals_int; | ||||||
|     int flags; |     int flags; | ||||||
|     int argcount, posonlyargcount, kwonlyargcount, maxdepth; |     int posorkeywordargcount, posonlyargcount, kwonlyargcount, maxdepth; | ||||||
| 
 | 
 | ||||||
|     consts = consts_dict_keys_inorder(c->u->u_consts); |     consts = consts_dict_keys_inorder(c->u->u_consts); | ||||||
|     names = dict_keys_inorder(c->u->u_names, 0); |     names = dict_keys_inorder(c->u->u_names, 0); | ||||||
|  | @ -5808,15 +5808,15 @@ makecode(struct compiler *c, struct assembler *a) | ||||||
|         goto error; |         goto error; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     argcount = Py_SAFE_DOWNCAST(c->u->u_argcount, Py_ssize_t, int); |  | ||||||
|     posonlyargcount = Py_SAFE_DOWNCAST(c->u->u_posonlyargcount, Py_ssize_t, int); |     posonlyargcount = Py_SAFE_DOWNCAST(c->u->u_posonlyargcount, Py_ssize_t, int); | ||||||
|  |     posorkeywordargcount = Py_SAFE_DOWNCAST(c->u->u_argcount, Py_ssize_t, int); | ||||||
|     kwonlyargcount = Py_SAFE_DOWNCAST(c->u->u_kwonlyargcount, Py_ssize_t, int); |     kwonlyargcount = Py_SAFE_DOWNCAST(c->u->u_kwonlyargcount, Py_ssize_t, int); | ||||||
|     maxdepth = stackdepth(c); |     maxdepth = stackdepth(c); | ||||||
|     if (maxdepth < 0) { |     if (maxdepth < 0) { | ||||||
|         goto error; |         goto error; | ||||||
|     } |     } | ||||||
|     co = PyCode_New(argcount, posonlyargcount, kwonlyargcount, |     co = PyCode_New(posonlyargcount+posorkeywordargcount, posonlyargcount, | ||||||
|                     nlocals_int, maxdepth, flags, |                     kwonlyargcount, nlocals_int, maxdepth, flags, | ||||||
|                     bytecode, consts, names, varnames, |                     bytecode, consts, names, varnames, | ||||||
|                     freevars, cellvars, |                     freevars, cellvars, | ||||||
|                     c->c_filename, c->u->u_name, |                     c->c_filename, c->u->u_name, | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Pablo Galindo
						Pablo Galindo