parse additional kwargs internally as flags to avoid bad_any_cast

There seem to be somehow multiple py::kwargs classes created in
different libraries, because of this the any_cast is failing.
To circumvent this we attach them to the MeshingParameters object
as flags.
This commit is contained in:
Christopher Lackner 2019-08-06 17:38:44 +02:00
parent 114a517030
commit 9e63ba0943
4 changed files with 79 additions and 24 deletions

View File

@ -40,7 +40,7 @@ namespace ngcore
if (py::isinstance<py::list>(value))
{
py::list vdl(value);
auto vdl = py::cast<py::list>(value);
if (py::len(vdl) > 0)
{
if(py::isinstance<double>(vdl[0]))
@ -59,7 +59,7 @@ namespace ngcore
if (py::isinstance<py::tuple>(value))
{
py::tuple vdt(value);
auto vdt = py::cast<py::tuple>(value);
if (py::isinstance<py::float_>(value))
flags.SetFlag(s, makeCArray<double>(vdt));
if (py::isinstance<py::int_>(value))
@ -69,29 +69,32 @@ namespace ngcore
}
}
Flags CreateFlagsFromKwArgs(py::object pyclass, const py::kwargs& kwargs, py::list info)
Flags CreateFlagsFromKwArgs(const py::kwargs& kwargs, py::object pyclass, py::list info)
{
static std::shared_ptr<Logger> logger = GetLogger("Flags");
auto flags_doc = pyclass.attr("__flags_doc__")();
py::dict flags_dict;
if (kwargs.contains("flags"))
{
logger->warn("WARNING: using flags as kwarg is deprecated in {}, use the flag arguments as kwargs instead!",
std::string(py::str(pyclass)));
logger->warn("WARNING: using flags as kwarg is deprecated{}, use the flag arguments as kwargs instead!",
pyclass.is_none() ? "" : std::string(" in ") + std::string(py::str(pyclass)));
auto addflags = py::cast<py::dict>(kwargs["flags"]);
for (auto item : addflags)
flags_dict[item.first.cast<string>().c_str()] = item.second;
}
for (auto item : kwargs)
if (!flags_doc.contains(item.first.cast<string>().c_str()) &&
!(item.first.cast<string>() == "flags"))
logger->warn("WARNING: kwarg '{}' is an undocumented flags option for class {}, maybe there is a typo?",
item.first.cast<string>(), std::string(py::str(pyclass)));
py::dict special;
if(py::hasattr(pyclass,"__special_treated_flags__"))
special = pyclass.attr("__special_treated_flags__")();
if(!pyclass.is_none())
{
auto flags_doc = pyclass.attr("__flags_doc__")();
for (auto item : kwargs)
if (!flags_doc.contains(item.first.cast<string>().c_str()) &&
!(item.first.cast<string>() == "flags"))
logger->warn("WARNING: kwarg '{}' is an undocumented flags option for class {}, maybe there is a typo?",
item.first.cast<string>(), std::string(py::str(pyclass)));
if(py::hasattr(pyclass,"__special_treated_flags__"))
special = pyclass.attr("__special_treated_flags__")();
}
for (auto item : kwargs)
{
auto name = item.first.cast<string>();
@ -116,4 +119,47 @@ namespace ngcore
return flags;
}
py::dict CreateDictFromFlags(const Flags& flags)
{
py::dict d;
std::string key;
for(auto i : Range(flags.GetNFlagsFlags()))
{
auto& f = flags.GetFlagsFlag(i, key);
d[key.c_str()] = CreateDictFromFlags(f);
}
for(auto i : Range(flags.GetNStringListFlags()))
{
auto strlistflag = flags.GetStringListFlag(i, key);
py::list lst;
for(auto& val : *strlistflag)
lst.append(val);
d[key.c_str()] = lst;
}
for(auto i : Range(flags.GetNNumListFlags()))
{
auto numlistflag = flags.GetNumListFlag(i, key);
py::list lst;
for(auto& val : *numlistflag)
lst.append(val);
d[key.c_str()] = lst;
}
for(auto i : Range(flags.GetNStringFlags()))
{
auto val = flags.GetStringFlag(i, key);
d[key.c_str()] = val;
}
for(auto i : Range(flags.GetNNumFlags()))
{
auto val = flags.GetNumFlag(i, key);
d[key.c_str()] = val;
}
for(auto i : Range(flags.GetNDefineFlags()))
{
auto val = flags.GetDefineFlag(i, key);
d[key.c_str()] = val;
}
return d;
}
} // namespace ngcore

View File

@ -16,10 +16,9 @@ namespace ngcore
Array<T> makeCArray(const py::object& obj)
{
Array<T> arr;
arr.SetAllocSize(py::len(obj));
if(py::isinstance<py::list>(obj))
for(auto& val : py::cast<py::list>(obj))
arr.Append(py::cast<T>(val));
for(auto& val : py::cast<py::list>(obj))
arr.Append(py::cast<T>(val));
else if(py::isinstance<py::tuple>(obj))
for(auto& val : py::cast<py::tuple>(obj))
arr.Append(py::cast<T>(val));
@ -30,7 +29,10 @@ namespace ngcore
void NGCORE_API SetFlag(Flags &flags, std::string s, py::object value);
// Parse python kwargs to flags
Flags NGCORE_API CreateFlagsFromKwArgs(py::object pyclass, const py::kwargs& kwargs, py::list info = py::list());
Flags NGCORE_API CreateFlagsFromKwArgs(const py::kwargs& kwargs, py::object pyclass = py::none(),
py::list info = py::list());
// Create python dict from kwargs
py::dict NGCORE_API CreateDictFromFlags(const Flags& flags);
// *************** Archiving functionality **************

View File

@ -1,5 +1,9 @@
#ifndef NETGEN_MESHING_PYTHON_MESH_HPP
#define NETGEN_MESHING_PYTHON_MESH_HPP
#include <pybind11/pybind11.h>
#include <core/python_ngcore.hpp>
#include "meshing.hpp"
namespace netgen
@ -168,7 +172,10 @@ inline void CreateMPfromKwargs(MeshingParameters& mp, py::kwargs kwargs, bool th
{
if(throw_if_not_all_parsed)
throw Exception(string("Not all kwargs given to GenerateMesh could be parsed:") + string(py::str(kwargs)));
mp.geometrySpecificParameters = kwargs;
mp.geometrySpecificParameters = CreateFlagsFromKwArgs(kwargs);
}
}
} // namespace netgen
#endif // NETGEN_MESHING_PYTHON_MESH_HPP

View File

@ -32,7 +32,7 @@ edgecornerangle: float =
)delimiter";
void CreateSTLParametersFromKwargs(STLParameters& stlparam, py::kwargs kwargs)
void CreateSTLParametersFromKwargs(STLParameters& stlparam, py::dict kwargs)
{
if(kwargs.contains("yangle"))
stlparam.yangle = py::cast<double>(kwargs.attr("pop")("yangle"));
@ -198,14 +198,14 @@ DLL_HEADER void ExportSTL(py::module & m)
STLParameters stlparam;
if(pars)
{
if(pars->geometrySpecificParameters.has_value() &&
(pars->geometrySpecificParameters.type() == typeid(py::kwargs)))
try
{
auto mp_kwargs = any_cast<py::kwargs>(pars->geometrySpecificParameters);
py::print("geometry specific kwargs:", mp_kwargs);
auto mp_flags = any_cast<Flags>(pars->geometrySpecificParameters);
auto mp_kwargs = CreateDictFromFlags(mp_flags);
CreateSTLParametersFromKwargs(stlparam, mp_kwargs);
pars->geometrySpecificParameters.reset();
}
catch(std::bad_any_cast) {}
mp = *pars;
}
CreateSTLParametersFromKwargs(stlparam, kwargs);