From ada736696e93e8048996753561199bf41b51d77f Mon Sep 17 00:00:00 2001 From: Chris Hennes Date: Fri, 25 Aug 2023 13:13:57 -0500 Subject: [PATCH] Base: Add wrapper for PyArg_ParseTupleAndKeywords Enable strict const-correctness for the keywords argument and address several linter complaints related to using a C function in C++ code. --- src/Base/PyWrapParseTupleAndKeywords.h | 70 ++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 src/Base/PyWrapParseTupleAndKeywords.h diff --git a/src/Base/PyWrapParseTupleAndKeywords.h b/src/Base/PyWrapParseTupleAndKeywords.h new file mode 100644 index 0000000000..3b1d151b9b --- /dev/null +++ b/src/Base/PyWrapParseTupleAndKeywords.h @@ -0,0 +1,70 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later +/**************************************************************************** + * * + * Copyright (c) 2023 The FreeCAD Project Association * + * * + * This file is part of FreeCAD. * + * * + * FreeCAD is free software: you can redistribute it and/or modify it * + * under the terms of the GNU Lesser General Public License as * + * published by the Free Software Foundation, either version 2.1 of the * + * License, or (at your option) any later version. * + * * + * FreeCAD is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with FreeCAD. If not, see * + * . * + * * + ***************************************************************************/ + +#ifndef FREECAD_PYWRAPPARSETUPLEANDKEYWORDS_H +#define FREECAD_PYWRAPPARSETUPLEANDKEYWORDS_H + +#include +#include +#include + +namespace Base { + + /// A thin C++ wrapper around PyArg_ParseTupleAndKeywords providing const-correctness for the keywords argument + /// \arg args The Python args object + /// \arg kw The Python kw object + /// \arg format The format string describing the expected arguments + /// \arg keywords A std::array of keywords, terminated by a nullptr (required by CPython) + /// \arg (variadic) Pointers to the storage locations for the parameters + /// \returns boolean true on success, or false on failure + template + bool Wrapped_ParseTupleAndKeywords(PyObject *args, + PyObject *kw, + const char *format, + const std::array keywords, + ...) + { + // NOTE: This code is from getargs.c in the Python source code (modified to use the public interface at + // PyArg_VaParseTupleAndKeywords and to return a bool). + va_list va; // NOLINT + + if ((args == nullptr || !PyTuple_Check(args)) || + (kw != nullptr && !PyDict_Check(kw)) || + format == nullptr || + keywords.empty() || // It must at least have a single nullptr in it (TODO: compilation error instead) + keywords.back() != nullptr) // It must END with a nullptr + { + PyErr_BadInternalCall(); + return false; + } + + va_start(va, keywords); + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast) + int retval = PyArg_VaParseTupleAndKeywords(args, kw, format, const_cast(keywords.data()), va); + va_end(va); + return retval != 0; // Convert to a true C++ boolean + } + +} + +#endif //FREECAD_PYWRAPPARSETUPLEANDKEYWORDS_H