file ScannerBit/python_utils.hpp
[No description available]
Namespaces
Name |
---|
Gambit TODO: see if we can use this one: |
Gambit::Scanner |
Source code
#ifndef __SCAN_PYTHON_UTILS_HPP__
#define __SCAN_PYTHON_UTILS_HPP__
#include "gambit/Utils/begin_ignore_warnings_pybind11.hpp"
#include "gambit/Utils/begin_ignore_warnings_eigen.hpp"
#include <pybind11/embed.h>
#include <pybind11/eigen.h>
#include <pybind11/stl.h>
#include <pybind11/stl_bind.h>
#include "gambit/Utils/end_ignore_warnings.hpp"
namespace py = pybind11;
namespace Gambit
{
namespace Scanner
{
/**
* @brief Determines the Python type of a given object.
*
* This function inspects a Python object and returns a string representation of its type.
*
* @param obj The Python object whose type is to be determined.
* @return A string representation of the Python object's type.
*/
inline std::string pytype(py::handle o)
{
return o.attr("__class__").attr("__name__").template cast<std::string>();
}
/**
* @brief Checks if a given Python object matches a specified type.
*
* This function inspects a Python object and checks if it matches the specified type.
*
* @tparam T The type to check against.
* @param args The Python kwargs object containing the arguments.
* @param type The key in the kwargs to check the type of. Defaults to "dtype".
* @param def_type The default return value if the type key is not found in the kwargs. Defaults to false.
* @return True if the object matches the specified type, false otherwise.
*/
template<typename T>
bool is_pytype(py::kwargs args, const std::string &type = "dtype", bool def_type = false)
{
if (args.contains(type.c_str()))
{
auto arg = args[type.c_str()];
if (pytype(arg) == "type" ? py::handle(arg).is(T().get_type()) :
pytype(arg) == "str" || pytype(arg) == "unicode" ? arg.template cast<std::string>() == pytype(T()) : false)
return true;
else
return false;
}
else
return def_type;
}
/**
* @brief Converts a YAML node to a Python dictionary.
*
* This function recursively traverses a YAML node and constructs a corresponding Python dictionary.
*
* @param node The YAML node to be converted.
* @return A Python dictionary that represents the YAML node.
*/
inline py::object yaml_to_dict(const YAML::Node &node)
{
if (node.IsNull())
{
return py::dict();
}
else if (node.IsMap())
{
py::dict d;
for (auto &&n : node)
{
d[py::cast(n.first.template as<std::string>())] = yaml_to_dict(n.second);
}
return d;
}
else if (node.IsSequence())
{
py::list l;
for (auto &&n : node)
{
l.append(yaml_to_dict(n));
}
return l;
}
else if (node.IsScalar())
{
int ret_i;
if (YAML::convert<int>::decode(node, ret_i))
{
return py::cast(ret_i);
}
double ret_d;
if (YAML::convert<double>::decode(node, ret_d))
{
return py::cast(ret_d);
}
bool ret_b;
if (YAML::convert<bool>::decode(node, ret_b))
{
return py::cast(ret_b);
}
return py::cast(node.template as<std::string>());
}
else
{
return py::object();
}
}
/**
* @brief Converts a Python dictionary to a YAML node.
*
* This function recursively traverses a Python dictionary and constructs a corresponding YAML node.
*
* @param o The Python object to be converted.
* @return A YAML node that represents the Python dictionary.
*/
inline YAML::Node dict_to_yaml(py::handle o)
{
YAML::Node node;
std::string type = pytype(o);
if (type == "dict")
{
for (auto &&it : py::cast<py::dict>(o))
{
node[dict_to_yaml(it.first)] = dict_to_yaml(it.second);
}
}
else if(type == "list")
{
for (auto &&it : py::cast<py::list>(o))
{
node.push_back(dict_to_yaml(it));
}
}
else if(type == "tuple")
{
for (auto &&it : py::cast<py::tuple>(o))
{
node.push_back(dict_to_yaml(it));
}
}
else if (type == "float" || type == "float64")
{
node = o.template cast<double>();
}
else if (type == "int")
{
node = o.template cast<int>();
}
else if (type == "str" || type == "unicode")
{
node = o.template cast<std::string>();
}
else if (type == "bool")
{
node = o.template cast<bool>();
}
else if (type == "NoneType")
{
node = YAML::Node();
}
else
{
throw std::invalid_argument("Error converting python dictionary to YAML node: " + type + " type not recognized.");
}
return node;
}
}
}
#endif
Updated on 2024-07-18 at 13:53:33 +0000