Scarab  2.8.1
Project 8 C++ Utility Library
param_pybind.hh
Go to the documentation of this file.
1 /*
2  * param_pybind.hh
3  *
4  * Created on: Feb 1, 2018
5  * Author: N. Oblath, L. Gladstone, B.H. LaRoque
6  */
7 
8 #ifndef PARAM_PYBIND_HH_
9 #define PARAM_PYBIND_HH_
10 
11 #include <algorithm> //for std::replace on string
12 
13 #include "param.hh"
14 #include "error.hh"
15 
16 #include "pybind11/pybind11.h"
17 #include "pybind11/pytypes.h"
18 
19 
20 namespace scarab_pybind
21 {
22  scarab::param_ptr_t to_param( const pybind11::object& an_object, bool hyphenate_keys=false )
23  {
24  using namespace pybind11;
25  if( isinstance< none >( an_object ) )
26  {
27  return scarab::param_ptr_t( new scarab::param() );
28  }
29  else if( isinstance< bool_ >( an_object ) )
30  {
31  return scarab::param_ptr_t( new scarab::param_value( static_cast< const bool_& >(an_object) ) );
32  }
33  else if( isinstance< int_ >( an_object ) )
34  {
35  return scarab::param_ptr_t( new scarab::param_value( (int64_t)static_cast< const int_& >(an_object) ) );
36  }
37  else if( isinstance< float_ >( an_object ) )
38  {
39  return scarab::param_ptr_t( new scarab::param_value( (double)static_cast< const float_& >(an_object) ) );
40  }
41  else if( isinstance< str >( an_object ) )
42  {
43  return scarab::param_ptr_t( new scarab::param_value( static_cast< const str& >(an_object) ) );
44  }
45  else if( isinstance< list >( an_object ) )
46  {
47  scarab::param_ptr_t the_return( new scarab::param_array() );
48  scarab::param_array& the_return_arr = the_return->as_array();
49  for( auto an_item = an_object.begin(); an_item != an_object.end(); ++an_item )
50  {
51  the_return_arr.push_back( to_param( reinterpret_borrow< object >( *an_item ) ) );
52  }
53  return the_return;
54  }
55  else if( isinstance< dict >( an_object ) )
56  {
57  scarab::param_ptr_t the_return( new scarab::param_node() );
58  scarab::param_node& the_return_arr = the_return->as_node();
59  const dict& a_dict = static_cast< const dict& >( an_object );
60  for( auto an_item = a_dict.begin(); an_item != a_dict.end(); ++an_item )
61  {
62  if( ! isinstance< str >(an_item->first) || ! isinstance< object >(an_item->second) )
63  {
64  throw scarab::error() << "Cannot convert dict to param";
65  }
66  std::string new_key = pybind11::str(an_item->first);
67  if ( hyphenate_keys )
68  {
69  std::replace( new_key.begin(), new_key.end(), '_', '-' );
70  }
71  the_return_arr.add( new_key, to_param( static_cast< const object& >(an_item->second) ) );
72  }
73  return the_return;
74  }
75  throw scarab::error() << "Unknown python type cannot be converted to param";
76  }
77 
78  pybind11::object to_python( const scarab::param& a_param, bool underscore_keys = false )
79  {
80  if (a_param.is_null())
81  {
82  return pybind11::none();
83  }
84  else if (a_param.is_value())
85  {
86  const scarab::param_value& this_value = a_param.as_value();
87  pybind11::object to_return;
88  if (this_value.is_bool()) to_return = pybind11::cast(this_value.as_bool());
89  else if (this_value.is_uint()) to_return = pybind11::cast(this_value.as_uint());
90  else if (this_value.is_int()) to_return = pybind11::cast(this_value.as_int());
91  else if (this_value.is_double()) to_return = pybind11::cast(this_value.as_double());
92  else if (this_value.is_string()) to_return = pybind11::cast(this_value.as_string());
93  return to_return;
94  }
95  else if (a_param.is_array())
96  {
97  const scarab::param_array& this_array = a_param.as_array();
98  pybind11::list to_return;
99  for (scarab::param_array_const_iterator an_item=this_array.begin(); an_item != this_array.end(); ++an_item)
100  {
101  to_return.append( to_python( *an_item ) );
102  }
103  return std::move(to_return);
104  }
105  else if (a_param.is_node())
106  {
107  const scarab::param_node& this_node = a_param.as_node();
108  pybind11::dict to_return;
109  for (scarab::param_node_const_iterator an_item=this_node.begin(); an_item != this_node.end(); ++an_item)
110  {
111  std::string new_key = an_item.name();
112  if ( underscore_keys )
113  {
114  std::replace( new_key.begin(), new_key.end(), '-', '_' );
115  }
116  to_return[ new_key.c_str() ] = to_python( *an_item );
117  }
118  return std::move(to_return);
119  }
120  throw scarab::error() << "Unknown param type cannot be converted to Python";
121  }
122 
123  std::list< std::string > export_param( pybind11::module& mod )
124  {
125  std::list< std::string > all_members;
126 
127  all_members.push_back( "to_param" );
128  mod.def( "to_param",
129  &to_param,
130  pybind11::arg( "object"),
131  pybind11::arg( "hyphenate_keys" ) = false,
132  "Convert native python types to a param structure." );
133 
134  // param
135  all_members.push_back( "Param" );
136  pybind11::class_< scarab::param >( mod, "Param", "param data structure base class and null object" )
137  .def( pybind11::init< >() )
138  .def( pybind11::init< scarab::param_value >() )
139 
140  .def( "__str__", &scarab::param::to_string )
141  .def( "__call__", (scarab::param_value& (scarab::param::*)()) &scarab::param::operator(),
143 
144  .def( "is_null", &scarab::param::is_null, "return whether the param object is an empty param type" )
145  .def( "is_node", &scarab::param::is_node, "return whether the param object is a ParamNode" )
146  .def( "is_array", &scarab::param::is_array, "return whether the param object is a ParamArray" )
147  .def( "is_value", &scarab::param::is_value, "return whether the param object is a ParamValue" )
148 
149  .def( "as_array",
152  "returns Param object as a ParamArray" )
153  .def( "as_node",
156  "returns Param object as ParamNode" )
157  .def( "as_value",
160  "returns Param object as ParamValue" )
161 
162  .def( "to_python",
163  &to_python,
164  pybind11::arg( "underscore_keys" ) = false,
165  "recursively converts param object to native python data structure" )
166 
167  //TODO: has_subset()
168 
169  //TODO: get_value() in its various types
170 
171  //TODO: merge()
172 
173  ;
174  return all_members;
175  }
176 
177 } /* namespace scarab_pybind */
178 #endif /* PARAM_PYBIND_HH_ */
int64_t as_int() const
Definition: param_value.hh:522
bool is_bool() const
Definition: param_value.hh:487
iterator end() const
Return a sentinel which ends iteration.
Definition: pytypes.h:1403
virtual bool is_value() const
bool isinstance< object >(handle obj)
Definition: pytypes.h:374
pybind11::object to_python(const scarab::param &a_param, bool underscore_keys=false)
Definition: param_pybind.hh:78
iterator begin()
Definition: param_node.hh:328
glibc defines I as a macro which breaks things, e.g., boost template names
Definition: attr.h:15
boost::indirect_iterator< param_array_contents::const_iterator, const param > param_array_const_iterator
Definition: param_array.hh:29
std::list< std::string > export_param(pybind11::module &mod)
bool is_uint() const
Definition: param_value.hh:492
Wrapper for Python extension modules.
Definition: pybind11.h:789
double as_double() const
Definition: param_value.hh:527
virtual bool is_null() const
detail::dict_iterator end() const
Definition: pytypes.h:1226
bool as_bool() const
Definition: param_value.hh:512
param_value & as_value()
virtual bool is_array() const
iterator begin() const
Definition: pytypes.h:1402
scarab::param_ptr_t to_param(const pybind11::object &an_object, bool hyphenate_keys=false)
Definition: param_pybind.hh:22
bool is_double() const
Definition: param_value.hh:502
virtual bool is_node() const
std::unique_ptr< param > param_ptr_t
Definition: param_base.hh:23
detail::enable_if_t<!detail::move_never< T >::value, T > move(object &&obj)
Definition: cast.h:1685
bool is_string() const
Definition: param_value.hh:507
return os str()
param_node & as_node()
uint64_t as_uint() const
Definition: param_value.hh:517
param_array & as_array()
virtual std::string to_string() const
T cast(const handle &handle)
Definition: cast.h:1659
void push_back(const param &a_value)
Definition: param_array.hh:238
bool add(const std::string &a_name, const param &a_value)
Definition: param_node.hh:228
bool is_int() const
Definition: param_value.hh:497
std::string as_string() const
Definition: param_value.hh:532
detail::dict_iterator begin() const
Definition: pytypes.h:1225
bool typename Extra class_ & def(const char *name_, Func &&f, const Extra &... extra)
Definition: pybind11.h:1110