8
8
#include " nanobind/nanobind.h"
9
9
#include " nanobind/stl/vector.h"
10
10
#include " nanobind/stl/string.h"
11
- #include < nanobind/ndarray.h>
11
+ #include " nanobind/ndarray.h"
12
12
#include " nlohmann/json.hpp"
13
13
// #include "nanobind_json/nanobind_json.hpp"
14
14
// #include "pybind11_json/pybind11_json.hpp"
22
22
// #include "run_part_opt.hpp"
23
23
#include " aero_data.hpp"
24
24
// #include "aero_dist.hpp"
25
- // #include "aero_mode.hpp"
25
+ #include " aero_mode.hpp"
26
26
// #include "aero_state.hpp"
27
27
// #include "env_state.hpp"
28
28
// // #include "gas_data.hpp"
39
39
#define STRINGIFY (x ) #x
40
40
#define MACRO_STRINGIFY (x ) STRINGIFY(x)
41
41
42
- // namespace py = pybind11;
43
-
44
42
namespace nb = nanobind;
45
43
namespace nl = nlohmann;
46
44
47
- #include < iostream>
48
45
namespace pyjson
49
46
{
50
47
inline nb::handle from_json (const nl::json& j)
@@ -91,7 +88,7 @@ namespace pyjson
91
88
}
92
89
}
93
90
94
- nl::json to_json (const nb::handle& obj)
91
+ inline nl::json to_json (const nb::handle& obj, std::set< const PyObject*> prevs )
95
92
{
96
93
if (obj.ptr () == nullptr || obj.is_none ())
97
94
{
@@ -109,32 +106,43 @@ namespace pyjson
109
106
{
110
107
return nb::cast<double >(obj);
111
108
}
112
- // if (nb::isinstance<nb::bytes>(obj))
113
- // {
114
- // nb::module base64 = nb::module::import("base64");
115
- // // return base64.attr("b64encode")(obj).attr("decode")("utf-8").cast<std::string>();
116
- // return nb::cast<std::string>(base64.attr("b64encode")(obj).attr("decode")("utf-8"));
117
- // }
109
+ if (nb::isinstance<nb::bytes>(obj))
110
+ {
111
+ nb::module_ base64 = nb::module_::import_ (" base64" );
112
+ return nb::cast<std::string>(base64.attr (" b64encode" )(obj).attr (" decode" )(" utf-8" ));
113
+ }
118
114
if (nb::isinstance<nb::str>(obj))
119
115
{
120
116
return nb::cast<std::string>(obj);
121
117
}
122
118
if (nb::isinstance<nb::tuple>(obj) || nb::isinstance<nb::list>(obj))
123
119
{
120
+ auto insert_return = prevs.insert (obj.ptr ());
121
+ if (!insert_return.second ) {
122
+ throw std::runtime_error (" Circular reference detected" );
123
+ }
124
+
124
125
auto out = nl::json::array ();
126
+
125
127
for (const nb::handle value : obj)
126
128
{
127
- out.push_back (to_json (value));
129
+ out.push_back (to_json (value, prevs ));
128
130
}
129
131
130
132
return out;
131
133
}
132
- if (nb::isinstance<nb::dict>(obj) || nb::isinstance<nb::tuple>(obj) || nb::isinstance<nb::list>(obj) )
134
+ if (nb::isinstance<nb::dict>(obj))
133
135
{
136
+ auto insert_return = prevs.insert (obj.ptr ());
137
+ if (!insert_return.second ) {
138
+ throw std::runtime_error (" Circular reference detected" );
139
+ }
140
+
134
141
auto out = nl::json::object ();
142
+
135
143
for (const nb::handle key : obj)
136
144
{
137
- out[nb::cast<std::string>(nb::str (key))] = to_json (obj[key]);
145
+ out[nb::cast<std::string>(nb::str (key))] = to_json (obj[key], prevs );
138
146
}
139
147
return out;
140
148
}
@@ -208,7 +216,7 @@ namespace nanobind
208
216
209
217
bool from_python (handle src, uint8_t flags, cleanup_list *cleanup) noexcept {
210
218
try {
211
- value = pyjson::to_json (src);
219
+ value = pyjson::to_json (src, std::set< const PyObject*>() );
212
220
return true ;
213
221
}
214
222
catch (...)
@@ -225,14 +233,30 @@ namespace nanobind
225
233
};
226
234
227
235
template <typename Type> struct type_caster <std::valarray<Type>> {
228
- NB_TYPE_CASTER (std::valarray<Type>, const_name(" [" ) +
229
- const_name (" valarray" ) +
230
- const_name (" ]" ))
236
+ NB_TYPE_CASTER (std::valarray<Type>, const_name(" [" ) + const_name(" std::valarray" ) + const_name(" ]" ))
231
237
232
238
using Caster = make_caster<Type>;
233
239
234
240
bool from_python (handle src, uint8_t flags, cleanup_list *cleanup) noexcept {
235
- if (nb::isinstance<nb::list>(src) || nb::isinstance<nb::ndarray<Type, nb::ndim<1 >>>(src)) {
241
+ if (nb::isinstance<nb::list>(src)) {
242
+ try {
243
+ auto py_array = nb::cast<nb::list>(src);
244
+ size_t size = py_array.size ();
245
+
246
+ value.resize (size);
247
+
248
+ for (size_t i = 0 ; i < size; i++) {
249
+ value[i] = nb::cast<Type>(py_array[i]);
250
+ }
251
+
252
+ return true ;
253
+ }
254
+ catch (...) {
255
+ PyErr_Clear ();
256
+ return false ;
257
+ }
258
+ }
259
+ else if (nb::isinstance<nb::ndarray<Type, nb::ndim<1 >>>(src)) {
236
260
try {
237
261
auto py_array = nb::cast<nb::ndarray<Type, nb::ndim<1 >>>(src);
238
262
size_t size = py_array.size ();
@@ -668,31 +692,31 @@ NB_MODULE(_PyPartMC, m) {
668
692
.def_prop_ro (" centers" , BinGrid::centers, " Bin centers" )
669
693
;
670
694
671
- // py ::class_<AeroMode>(m,"AeroMode")
672
- // .def(py ::init<AeroData&, const nlohmann::json&>())
673
- // .def_property ("num_conc", &AeroMode::get_num_conc, &AeroMode::set_num_conc,
674
- // "provides access (read or write) to the total number concentration of a mode")
675
- // .def("num_dist", &AeroMode::num_dist,
676
- // "returns the binned number concenration of a mode")
677
- // .def_property ("vol_frac", &AeroMode::get_vol_frac,
678
- // &AeroMode::set_vol_frac, "Species fractions by volume")
679
- // .def_property ("vol_frac_std", &AeroMode::get_vol_frac_std,
680
- // &AeroMode::set_vol_frac_std, "Species fraction standard deviation")
681
- // .def_property ("char_radius", &AeroMode::get_char_radius,
682
- // &AeroMode::set_char_radius,
683
- // "Characteristic radius, with meaning dependent on mode type (m)")
684
- // .def_property ("gsd", &AeroMode::get_gsd,
685
- // &AeroMode::set_gsd, "Geometric standard deviation")
686
- // .def("set_sample", &AeroMode::set_sampled)
687
- // .def_property_readonly ("sample_num_conc", &AeroMode::get_sample_num_conc,
688
- // "Sample bin number concentrations (m^{-3})")
689
- // .def_property_readonly ("sample_radius", &AeroMode::get_sample_radius,
690
- // "Sample bin radii (m).")
691
- // .def_property ("type", &AeroMode::get_type, &AeroMode::set_type,
692
- // "Mode type (given by module constants)")
693
- // .def_property ("name", &AeroMode::get_name, &AeroMode::set_name,
694
- // "Mode name, used to track particle sources")
695
- // ;
695
+ nb ::class_<AeroMode>(m," AeroMode" )
696
+ .def (nb ::init<AeroData&, const nlohmann::json&>())
697
+ . def_prop_rw (" num_conc" , &AeroMode::get_num_conc, &AeroMode::set_num_conc,
698
+ " provides access (read or write) to the total number concentration of a mode" )
699
+ .def (" num_dist" , &AeroMode::num_dist,
700
+ " returns the binned number concenration of a mode" )
701
+ . def_prop_rw (" vol_frac" , &AeroMode::get_vol_frac,
702
+ &AeroMode::set_vol_frac, " Species fractions by volume" )
703
+ . def_prop_rw (" vol_frac_std" , &AeroMode::get_vol_frac_std,
704
+ &AeroMode::set_vol_frac_std, " Species fraction standard deviation" )
705
+ . def_prop_rw (" char_radius" , &AeroMode::get_char_radius,
706
+ &AeroMode::set_char_radius,
707
+ " Characteristic radius, with meaning dependent on mode type (m)" )
708
+ . def_prop_rw (" gsd" , &AeroMode::get_gsd,
709
+ &AeroMode::set_gsd, " Geometric standard deviation" )
710
+ .def (" set_sample" , &AeroMode::set_sampled)
711
+ . def_prop_ro (" sample_num_conc" , &AeroMode::get_sample_num_conc,
712
+ " Sample bin number concentrations (m^{-3})" )
713
+ . def_prop_ro (" sample_radius" , &AeroMode::get_sample_radius,
714
+ " Sample bin radii (m)." )
715
+ . def_prop_rw (" type" , &AeroMode::get_type, &AeroMode::set_type,
716
+ " Mode type (given by module constants)" )
717
+ . def_prop_rw (" name" , &AeroMode::get_name, &AeroMode::set_name,
718
+ " Mode name, used to track particle sources" )
719
+ ;
696
720
697
721
// py::class_<AeroDist>(m,"AeroDist")
698
722
// .def(py::init<std::shared_ptr<AeroData>, const nlohmann::json&>())
0 commit comments