35 #pragma GCC diagnostic push 36 #if GCC_IS_AT_LEAST(7, 1, 0) || CLANG_IS_AT_LEAST(6, 0, 0) || \ 37 APPLE_CLANG_IS_AT_LEAST(10, 0, 0) 38 #pragma GCC diagnostic ignored "-Wregister" 40 #include "pybind11/pybind11.h" 41 #pragma GCC diagnostic pop 43 #include "cetlib_except/exception.h" 53 namespace py = pybind11;
60 using any_t = std::any;
66 void enter_table(
key_t const&
key, any_t
const& any)
override;
67 void enter_sequence(
key_t const&
key, any_t
const& any)
override;
68 void atom(
key_t const&
key, any_t
const& any)
override;
69 void exit_table(
key_t const&
key, any_t
const& any)
override;
70 void exit_sequence(
key_t const&
key, any_t
const& any)
override;
77 std::vector<pybind11::list> lists_{};
82 std::vector<pybind11::dict> dicts_{pybind11::dict{}};
96 if (dicts_.size() != 1)
98 <<
"Result stack has wrong size: " << dicts_.size() <<
std::endl;
104 PythonDictConverter::enter_table(
key_t const&
key, any_t
const&)
116 add_object(key, dict);
122 PythonDictConverter::enter_sequence(
key_t const& key, any_t
const& any)
131 auto const& anyvec = std::any_cast<std::vector<any_t>
const&>(any);
132 unsigned int const n = anyvec.size();
138 add_object(key, list);
145 PythonDictConverter::atom(
key_t const& key, any_t
const& any)
154 auto const& atom = std::any_cast<
std::string const&>(any);
158 std::transform(lcatom.begin(),
161 [](
unsigned char c) {
return std::tolower(
c); });
165 return add_object(key, py::bool_{
true});
168 return add_object(key, py::bool_{
false});
172 auto const n = atom.size();
173 if (n >= 2 && atom[0] ==
'"' && atom[n - 1] ==
'"') {
175 return add_object(key,
py::str(s));
180 std::istringstream iss(atom);
182 iss >> std::noskipws >> i;
183 if (iss.eof() && !iss.fail()) {
184 return add_object(key, py::int_(i));
190 std::istringstream iss(atom);
192 iss >> std::noskipws >>
x;
193 if (iss.eof() && !iss.fail()) {
194 return add_object(key, py::float_(x));
199 add_object(key,
py::str(atom));
203 PythonDictConverter::exit_table(
key_t const&, any_t
const&)
209 if (dicts_.size() < 2)
211 <<
"Result stack has wrong size: " << dicts_.size() <<
std::endl;
218 PythonDictConverter::exit_sequence(
key_t const&, any_t
const&)
229 <<
"Result stack has wrong size: " << dicts_.size() <<
std::endl;
236 PythonDictConverter::add_object(
key_t const& key, py::object pyobj)
246 assert(!dicts_.empty());
248 auto&
parent = dicts_.back();
253 assert(!lists_.empty());
254 auto& parent_list = lists_.back();
256 parent_list[i] = pyobj;
260 format(py::handle
const obj,
262 unsigned int const indent,
263 unsigned int const maxlen)
287 using py::isinstance;
288 std::ostringstream ss;
289 if (isinstance<py::bool_>(obj)) {
290 ss << (obj.cast<py::bool_>() ?
"True" :
"False");
291 }
else if (isinstance<py::int_>(obj)) {
292 ss << obj.cast<
long>();
293 }
else if (isinstance<py::float_>(obj)) {
294 ss << obj.cast<
double>();
295 }
else if (isinstance<py::str>(obj)) {
298 }
else if (isinstance<py::dict>(obj)) {
299 auto const dict = obj.cast<py::dict>();
300 auto const n = dict.size();
304 std::size_t keymaxlen{};
305 for (
auto const& pr : dict) {
307 if (key_str.size() > keymaxlen)
308 keymaxlen = key_str.size();
313 for (
auto const& [key,
value] : dict) {
315 auto const py_value =
316 format(
value, indent + keymaxlen + 7, indent + 2, maxlen);
317 auto const value_str = py_value.cast<
std::string>();
321 <<
std::left << ksquote <<
" : " << value_str;
328 }
else if (isinstance<py::list>(obj) || isinstance<py::tuple>(obj)) {
329 bool const is_list = isinstance<py::list>(obj);
333 char const open_seq = is_list ?
'[' :
'(';
334 char const close_seq = is_list ?
']' :
')';
335 auto const seq = obj.cast<py::sequence>();
340 unsigned int const break_indent = pos + 1;
341 for (
auto const ele : seq) {
346 auto const value_str =
format(ele, pos, break_indent, maxlen);
350 auto const fs =
f.size();
351 auto const n1 =
std::min(
f.find(
'\n'), fs);
358 bool const force_break{isinstance<py::list>(ele) ||
359 isinstance<py::tuple>(ele) ||
360 isinstance<py::dict>(ele)};
361 if (i > 0 && (force_break || pos + n1 > maxlen)) {
362 ss <<
'\n' <<
std::setw(break_indent) <<
"";
364 auto const value_str =
format(ele, pos, break_indent, maxlen);
374 auto const n2 = f.find_last_of(
'\n');
384 if (seq.size() == 0ull) {
403 PythonDictConverter converter;
404 pset.
walk(converter);
405 return converter.result();
409 pretty(py::dict dict)
419 return format(dict, 0, 0, 80);
425 m.doc() =
"Extention module for reading a FHiCL configuration file into a " 426 "native Python dictionary.";
427 m.def(
"make_pset", &make_pset,
"Make dictionary from parameter set.");
430 "Print the in-memory dictionary. Note that what is printed is not a " 431 "FHiCL-conforming string.");
432 py::register_exception<cet::exception>(
m,
"CetException");
bool is_sequence_element(std::string const &key)
static bool format(QChar::Decomposition tag, QString &str, int index, int len)
void make_ParameterSet(intermediate_table const &tbl, ParameterSet &ps)
std::size_t index_for_sequence_element(std::string const &name)
void walk(ParameterSetWalker &psw) const
Q_EXPORT QTSManip setw(int w)
T min(sqlite3 *const db, std::string const &table_name, std::string const &column_name)
const GenericPointer< typename T::ValueType > T2 value
PYBIND11_MODULE(fhicl, m)
def maker(G, ac, typename)
def parent(G, child, parent_type)
cet::coded_exception< error, detail::translate > exception
QTextStream & endl(QTextStream &s)