mirror of
https://github.com/NGSolve/netgen.git
synced 2024-12-26 22:00:33 +05:00
move python export of flags to ngcore
This commit is contained in:
parent
dc8d96aefa
commit
262f1ea12c
@ -10,6 +10,10 @@ add_library(ngcore SHARED
|
|||||||
utils.cpp
|
utils.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if(USE_PYTHON)
|
||||||
|
target_sources(ngcore PRIVATE python_ngcore.cpp)
|
||||||
|
endif(USE_PYTHON)
|
||||||
|
|
||||||
target_compile_definitions(ngcore PRIVATE NGCORE_EXPORTS)
|
target_compile_definitions(ngcore PRIVATE NGCORE_EXPORTS)
|
||||||
if(NOT WIN32)
|
if(NOT WIN32)
|
||||||
target_compile_options(ngcore PRIVATE -fvisibility=hidden)
|
target_compile_options(ngcore PRIVATE -fvisibility=hidden)
|
||||||
@ -53,7 +57,7 @@ if(ENABLE_CPP_CORE_GUIDELINES_CHECK)
|
|||||||
endif(ENABLE_CPP_CORE_GUIDELINES_CHECK)
|
endif(ENABLE_CPP_CORE_GUIDELINES_CHECK)
|
||||||
|
|
||||||
if(USE_PYTHON)
|
if(USE_PYTHON)
|
||||||
pybind11_add_module(pyngcore SHARED python_ngcore.cpp)
|
pybind11_add_module(pyngcore SHARED python_ngcore_export.cpp)
|
||||||
target_link_libraries(pyngcore PUBLIC ngcore ${PYTHON_LIBRARIES})
|
target_link_libraries(pyngcore PUBLIC ngcore ${PYTHON_LIBRARIES})
|
||||||
set_target_properties(pyngcore PROPERTIES INSTALL_RPATH "${NG_RPATH_TOKEN}/${NETGEN_PYTHON_RPATH}")
|
set_target_properties(pyngcore PROPERTIES INSTALL_RPATH "${NG_RPATH_TOKEN}/${NETGEN_PYTHON_RPATH}")
|
||||||
install(TARGETS pyngcore DESTINATION ${NG_INSTALL_DIR_PYTHON} COMPONENT netgen)
|
install(TARGETS pyngcore DESTINATION ${NG_INSTALL_DIR_PYTHON} COMPONENT netgen)
|
||||||
|
@ -1,30 +1,119 @@
|
|||||||
|
|
||||||
#include <pybind11/pybind11.h>
|
#include <pybind11/pybind11.h>
|
||||||
|
|
||||||
|
#include "python_ngcore.hpp"
|
||||||
|
|
||||||
|
#include "array.hpp"
|
||||||
|
#include "flags.hpp"
|
||||||
#include "logging.hpp"
|
#include "logging.hpp"
|
||||||
|
|
||||||
namespace py = pybind11;
|
namespace py = pybind11;
|
||||||
using namespace ngcore;
|
using std::string;
|
||||||
|
|
||||||
PYBIND11_MODULE(pyngcore, m) // NOLINT
|
namespace ngcore
|
||||||
{
|
{
|
||||||
py::enum_<level::level_enum>(m, "LOG_LEVEL", "Logging level")
|
|
||||||
.value("Trace", level::trace)
|
|
||||||
.value("Debug", level::debug)
|
|
||||||
.value("Info", level::info)
|
|
||||||
.value("Warn", level::warn)
|
|
||||||
.value("Error", level::err)
|
|
||||||
.value("Critical", level::critical)
|
|
||||||
.value("Off", level::off);
|
|
||||||
|
|
||||||
m.def("SetLoggingLevel", &SetLoggingLevel, py::arg("level"), py::arg("logger")="",
|
void SetFlag(Flags &flags, string s, py::object value)
|
||||||
"Set logging level, if name is given only to the specific logger, else set the global logging level");
|
{
|
||||||
m.def("AddFileSink", &AddFileSink, py::arg("filename"), py::arg("level"), py::arg("logger")="",
|
if (py::isinstance<py::dict>(value))
|
||||||
"Add File sink, either only to logger specified or globally to all loggers");
|
{
|
||||||
m.def("AddConsoleSink", &AddConsoleSink, py::arg("level"), py::arg("logger")="",
|
py::dict vdd(value);
|
||||||
"Add console output for specific logger or all if none given");
|
// call recursively to set dictionary
|
||||||
m.def("ClearLoggingSinks", &ClearLoggingSinks, py::arg("logger")="",
|
for (auto item : vdd) {
|
||||||
"Clear sinks of specific logger, or all if none given");
|
string name = item.first.cast<string>();
|
||||||
m.def("FlushOnLoggingLevel", &FlushOnLoggingLevel, py::arg("level"), py::arg("logger")="",
|
py::object val = py::reinterpret_borrow<py::object>(item.second);
|
||||||
"Flush every message with level at least `level` for specific logger or all loggers if none given.");
|
SetFlag(flags, name, val);
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (py::isinstance<py::bool_>(value))
|
||||||
|
flags.SetFlag(s, value.cast<bool>());
|
||||||
|
|
||||||
|
if (py::isinstance<py::float_>(value))
|
||||||
|
flags.SetFlag(s, value.cast<double>());
|
||||||
|
|
||||||
|
if (py::isinstance<py::int_>(value))
|
||||||
|
flags.SetFlag(s, double(value.cast<int>()));
|
||||||
|
|
||||||
|
if (py::isinstance<py::str>(value))
|
||||||
|
flags.SetFlag(s, value.cast<string>());
|
||||||
|
|
||||||
|
if (py::isinstance<py::list>(value))
|
||||||
|
{
|
||||||
|
py::list vdl(value);
|
||||||
|
if (py::len(vdl) > 0)
|
||||||
|
{
|
||||||
|
if(py::isinstance<double>(vdl[0]))
|
||||||
|
flags.SetFlag(s, makeCArray<double>(vdl));
|
||||||
|
if(py::isinstance<py::str>(vdl[0]))
|
||||||
|
flags.SetFlag(s, makeCArray<string>(vdl));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Array<string> dummystr;
|
||||||
|
Array<double> dummydbl;
|
||||||
|
flags.SetFlag(s,dummystr);
|
||||||
|
flags.SetFlag(s,dummydbl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (py::isinstance<py::tuple>(value))
|
||||||
|
{
|
||||||
|
py::tuple vdt(value);
|
||||||
|
if (py::isinstance<py::float_>(value))
|
||||||
|
flags.SetFlag(s, makeCArray<double>(vdt));
|
||||||
|
if (py::isinstance<py::int_>(value))
|
||||||
|
flags.SetFlag(s, makeCArray<double>(vdt));
|
||||||
|
if (py::isinstance<py::str>(value))
|
||||||
|
flags.SetFlag(s, makeCArray<string>(vdt));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Flags CreateFlagsFromKwArgs(py::object pyclass, const py::kwargs& kwargs, 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)));
|
||||||
|
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__")();
|
||||||
|
for (auto item : kwargs)
|
||||||
|
{
|
||||||
|
auto name = item.first.cast<string>();
|
||||||
|
if (name != "flags")
|
||||||
|
{
|
||||||
|
if(!special.contains(name.c_str()))
|
||||||
|
flags_dict[name.c_str()] = item.second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto flags = py::cast<Flags>(flags_dict);
|
||||||
|
|
||||||
|
for (auto item : kwargs)
|
||||||
|
{
|
||||||
|
auto name = item.first.cast<string>();
|
||||||
|
if (name != "flags")
|
||||||
|
{
|
||||||
|
if(special.contains(name.c_str()))
|
||||||
|
special[name.c_str()](item.second, &flags, info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace ngcore
|
||||||
|
@ -3,11 +3,37 @@
|
|||||||
|
|
||||||
#include <pybind11/pybind11.h>
|
#include <pybind11/pybind11.h>
|
||||||
|
|
||||||
|
#include "array.hpp"
|
||||||
#include "archive.hpp"
|
#include "archive.hpp"
|
||||||
|
#include "flags.hpp"
|
||||||
|
#include "ngcore_api.hpp"
|
||||||
|
|
||||||
namespace ngcore
|
namespace ngcore
|
||||||
{
|
{
|
||||||
|
namespace py = pybind11;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
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));
|
||||||
|
else if(py::isinstance<py::tuple>(obj))
|
||||||
|
for(auto& val : py::cast<py::tuple>(obj))
|
||||||
|
arr.Append(py::cast<T>(val));
|
||||||
|
else
|
||||||
|
throw py::type_error("Cannot convert Python object to C Array");
|
||||||
|
return arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
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());
|
||||||
|
|
||||||
|
// *************** Archiving functionality **************
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
Archive& Archive :: Shallow(T& val)
|
Archive& Archive :: Shallow(T& val)
|
||||||
{
|
{
|
||||||
|
87
libsrc/core/python_ngcore_export.cpp
Normal file
87
libsrc/core/python_ngcore_export.cpp
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
|
||||||
|
#include "python_ngcore.hpp"
|
||||||
|
|
||||||
|
using namespace ngcore;
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
PYBIND11_MODULE(pyngcore, m) // NOLINT
|
||||||
|
{
|
||||||
|
py::class_<Flags>(m, "Flags")
|
||||||
|
.def(py::init<>())
|
||||||
|
.def("__str__", &ToString<Flags>)
|
||||||
|
.def(py::init([](py::object & obj) {
|
||||||
|
Flags flags;
|
||||||
|
py::dict d(obj);
|
||||||
|
SetFlag (flags, "", d);
|
||||||
|
return flags;
|
||||||
|
}), py::arg("obj"), "Create Flags by given object")
|
||||||
|
.def(py::pickle([] (const Flags& self)
|
||||||
|
{
|
||||||
|
std::stringstream str;
|
||||||
|
self.SaveFlags(str);
|
||||||
|
return py::make_tuple(py::cast(str.str()));
|
||||||
|
},
|
||||||
|
[] (py::tuple state)
|
||||||
|
{
|
||||||
|
string s = state[0].cast<string>();
|
||||||
|
std::stringstream str(s);
|
||||||
|
Flags flags;
|
||||||
|
flags.LoadFlags(str);
|
||||||
|
return flags;
|
||||||
|
}
|
||||||
|
))
|
||||||
|
.def("Set",[](Flags & self,const py::dict & aflags)->Flags&
|
||||||
|
{
|
||||||
|
SetFlag(self, "", aflags);
|
||||||
|
return self;
|
||||||
|
}, py::arg("aflag"), "Set the flags by given dict")
|
||||||
|
|
||||||
|
.def("Set",[](Flags & self, const char * akey, const py::object & value)->Flags&
|
||||||
|
{
|
||||||
|
SetFlag(self, akey, value);
|
||||||
|
return self;
|
||||||
|
}, py::arg("akey"), py::arg("value"), "Set flag by given value.")
|
||||||
|
|
||||||
|
.def("__getitem__", [](Flags & self, const string& name) -> py::object {
|
||||||
|
|
||||||
|
if(self.NumListFlagDefined(name))
|
||||||
|
return py::cast(self.GetNumListFlag(name));
|
||||||
|
|
||||||
|
if(self.StringListFlagDefined(name))
|
||||||
|
return py::cast(self.GetStringListFlag(name));
|
||||||
|
|
||||||
|
if(self.NumFlagDefined(name))
|
||||||
|
return py::cast(*self.GetNumFlagPtr(name));
|
||||||
|
|
||||||
|
if(self.StringFlagDefined(name))
|
||||||
|
return py::cast(self.GetStringFlag(name));
|
||||||
|
|
||||||
|
if(self.FlagsFlagDefined(name))
|
||||||
|
return py::cast(self.GetFlagsFlag(name));
|
||||||
|
|
||||||
|
return py::cast(self.GetDefineFlag(name));
|
||||||
|
}, py::arg("name"), "Return flag by given name")
|
||||||
|
;
|
||||||
|
py::implicitly_convertible<py::dict, Flags>();
|
||||||
|
|
||||||
|
|
||||||
|
py::enum_<level::level_enum>(m, "LOG_LEVEL", "Logging level")
|
||||||
|
.value("Trace", level::trace)
|
||||||
|
.value("Debug", level::debug)
|
||||||
|
.value("Info", level::info)
|
||||||
|
.value("Warn", level::warn)
|
||||||
|
.value("Error", level::err)
|
||||||
|
.value("Critical", level::critical)
|
||||||
|
.value("Off", level::off);
|
||||||
|
|
||||||
|
m.def("SetLoggingLevel", &SetLoggingLevel, py::arg("level"), py::arg("logger")="",
|
||||||
|
"Set logging level, if name is given only to the specific logger, else set the global logging level");
|
||||||
|
m.def("AddFileSink", &AddFileSink, py::arg("filename"), py::arg("level"), py::arg("logger")="",
|
||||||
|
"Add File sink, either only to logger specified or globally to all loggers");
|
||||||
|
m.def("AddConsoleSink", &AddConsoleSink, py::arg("level"), py::arg("logger")="",
|
||||||
|
"Add console output for specific logger or all if none given");
|
||||||
|
m.def("ClearLoggingSinks", &ClearLoggingSinks, py::arg("logger")="",
|
||||||
|
"Clear sinks of specific logger, or all if none given");
|
||||||
|
m.def("FlushOnLoggingLevel", &FlushOnLoggingLevel, py::arg("level"), py::arg("logger")="",
|
||||||
|
"Flush every message with level at least `level` for specific logger or all loggers if none given.");
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user