Skip to content

[C API] Move undocumented private _PyArg C API to pycore_modsupport.h internal C API #110964

Description

@vstinner

If a 3rd party C extension uses one of these functions, we should consider adding a clean, documented and tested public function to replace it.

Private functions and structures:

  • _PyArg_BadArgument()
  • _PyArg_CheckPositional()
  • _PyArg_NoKeywords()
  • _PyArg_NoPositional()
  • _PyArg_ParseStack()
  • _PyArg_ParseStackAndKeywords()
  • _PyArg_Parser structure
  • _PyArg_UnpackKeywords()
  • _PyArg_UnpackKeywordsWithVararg()
  • _PyArg_UnpackStack()
  • _Py_ANY_VARARGS()

Linked PRs

Activity

  1. changed the title [-][C API] Move undocumented private _PyArg C API to the pycore_modsupport.h internal C API[/-] [+][C API] Move undocumented private _PyArg C API to pycore_modsupport.h internal C API[/+] on Oct 17, 2023
  2. added 2 commits that reference this issue on Oct 17, 2023
  3. vstinner commented on Oct 17, 2023

    @vstinner
    MemberAuthor

    Basically, these functions are only used by Argument Clinic.

    _PyArg_ParseTupleAndKeywordsFast(), _PyArg_ParseStackAndKeywords(), _PyArg_UnpackKeywords() and _PyArg_UnpackKeywordsWithVararg() have a _PyArg_Parser argument which is not really used without using the internal C API anyway. AC generates complex code using internal header files:

    #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
    #  include "pycore_gc.h"          // PyGC_Head
    #  include "pycore_runtime.h"     // _Py_ID()
    #endif
    
    (...)
    
        #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
    
        #define NUM_KEYWORDS 1
        static struct {
            PyGC_Head _this_is_not_used;
            PyObject_VAR_HEAD
            PyObject *ob_item[NUM_KEYWORDS];
        } _kwtuple = {
            .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
            .ob_item = { &_Py_ID(loop), },
        };
        #undef NUM_KEYWORDS
        #define KWTUPLE (&_kwtuple.ob_base.ob_base)
    
        #else  // !Py_BUILD_CORE
        #  define KWTUPLE NULL
        #endif  // !Py_BUILD_CORE
    
        static const char * const _keywords[] = {"loop", NULL};
        static _PyArg_Parser _parser = {
            .keywords = _keywords,
            .fname = "Future",
            .kwtuple = KWTUPLE,
        };
        #undef KWTUPLE

    PyGC_Head and _Py_ID() API are part of the internal C API, and _Py_ID() must not be used outside Python code base, since we don't guarantee which identifiers are available or not.

  4. vstinner commented on Oct 17, 2023

    @vstinner
    MemberAuthor

    _PyArg_ParseStack(args, nargs, format, ...) is like PyArg_ParseTuple(args, format, ...) but for METH_FASTCALL and METH_VECTORCALL calling convention. We should provide an API like _PyArg_ParseStack() in the public API, but I don't know if this API is good or ,not.

    These helper functions are used by AC. I don't know if it would make sense to make them public or not. They should not be complicated to rewrite if they are no longer usable in the public C API:

    • _PyArg_BadArgument()
    • _PyArg_CheckPositional()
    • _PyArg_NoKeywords()
    • _PyArg_NoPositional()
    • _PyArg_ParseStack()
    • _PyArg_UnpackStack()
  5. added 4 commits that reference this issue on Oct 17, 2023
  6. encukou commented on Oct 17, 2023

    @encukou
    Member

    I don't know if this API is good or ,not.

    They're vararg functions that return borrowed references, which makes them C-specific and dependent on CPython implementation details. They're quite handy in C, but IMO they'll need a good deal of design work if we're to expose them properly.

  7. vstinner commented on Oct 17, 2023

    @vstinner
    MemberAuthor

    IMO they'll need a good deal of design work if we're to expose them properly.

    Yeah, I agree with you.

  8. added 2 commits that reference this issue on Oct 18, 2023
  9. 19 remaining items

  10. rdb commented on Jan 9, 2026

    @rdb

    @vstinner what's the intended replacement for parsing arguments when using METH_FASTCALL? Fastcall is a public API, are we not supposed to use it after all?

  11. vstinner commented on Jan 14, 2026

    @vstinner
    MemberAuthor

    @rdb: Hi. This issue is closed. Would you mind to open a new issue to request a public C API for these functions? Describe your use case and explain why we should make these functions public.

  12. rdb commented on Jan 14, 2026

    @rdb

    @vstinner yes, I know the issue is closed, but my question is most relevant to this issue.

    I'm not asking you to make the functions public, I'm asking you what the intended replacement is. Before fastcall we had PyArg_ParseTupleAndKeywords for argument parsing. The removed functions were the equivalent for fastcall, and fastcall is a public API. So I want to understand whether the intent was to move people away from fastcall or whether there is a different API.

  13. vstinner commented on Jan 15, 2026

    @vstinner
    MemberAuthor

    No, the intent was not to move users away from fastcall/vectorcall. The intent was only to remove private functions in the public C API.

  14. rdb commented on Jan 15, 2026

    @rdb

    I appreciate you taking the time to respond.

    I will attempt one more time to rephrase my question as concisely as possible. What is the intended mechanism by which METH_FASTCALL methods should parse their (keyword) arguments?

  15. vstinner commented on Jan 15, 2026

    @vstinner
    MemberAuthor

    What is the intended mechanism by which METH_FASTCALL methods should parse their (keyword) arguments?

    There is no replacement. If you need a public C API for METH_FASTCALL, please open an issue to request such API.

  16. vstinner commented on Jan 23, 2026

    @vstinner
    MemberAuthor

    @rdb: Can you please open a new issue?

  17. vstinner commented on Mar 10, 2026

    @vstinner
    MemberAuthor

    @rdb: Can you please open a new issue?

    The new API was added in issue #144175.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions