From 940768c132d2ae4bd44f35e4e31a35523f765a9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Franz=20P=C3=B6schel?= Date: Wed, 25 Oct 2023 12:24:04 +0200 Subject: [PATCH] Adapt to refactored Python bindings after rebasing --- CMakeLists.txt | 1 - include/openPMD/binding/python/Common.hpp | 6 + include/openPMD/binding/python/Container.H | 28 ++-- include/openPMD/binding/python/Container.hpp | 152 ------------------ .../binding/python/RecordComponent.hpp | 7 + src/binding/python/BaseRecord.cpp | 59 ------- src/binding/python/Iteration.cpp | 5 +- src/binding/python/Mesh.cpp | 4 +- src/binding/python/MeshRecordComponent.cpp | 17 +- src/binding/python/ParticlePatches.cpp | 5 +- src/binding/python/ParticleSpecies.cpp | 5 +- src/binding/python/PatchRecord.cpp | 5 +- src/binding/python/PatchRecordComponent.cpp | 17 +- src/binding/python/Record.cpp | 4 +- src/binding/python/RecordComponent.cpp | 18 ++- src/binding/python/openPMD.cpp | 1 - 16 files changed, 84 insertions(+), 250 deletions(-) delete mode 100644 include/openPMD/binding/python/Container.hpp delete mode 100644 src/binding/python/BaseRecord.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 253b7b8bbe..20673b1c50 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -604,7 +604,6 @@ if(openPMD_HAVE_PYTHON) src/binding/python/openPMD.cpp src/binding/python/Access.cpp src/binding/python/Attributable.cpp - src/binding/python/BaseRecord.cpp src/binding/python/BaseRecordComponent.cpp src/binding/python/ChunkInfo.cpp src/binding/python/Dataset.cpp diff --git a/include/openPMD/binding/python/Common.hpp b/include/openPMD/binding/python/Common.hpp index ea6fff2832..7b42b919d8 100644 --- a/include/openPMD/binding/python/Common.hpp +++ b/include/openPMD/binding/python/Common.hpp @@ -13,6 +13,7 @@ #include "openPMD/ParticlePatches.hpp" #include "openPMD/ParticleSpecies.hpp" #include "openPMD/Record.hpp" +#include "openPMD/RecordComponent.hpp" #include "openPMD/Series.hpp" #include "openPMD/backend/BaseRecord.hpp" #include "openPMD/backend/BaseRecordComponent.hpp" @@ -42,6 +43,9 @@ using PyPatchRecordContainer = Container; using PyRecordComponentContainer = Container; using PyMeshRecordComponentContainer = Container; using PyPatchRecordComponentContainer = Container; +using PyBaseRecordRecordComponent = BaseRecord; +using PyBaseRecordMeshRecordComponent = BaseRecord; +using PyBaseRecordPatchRecordComponent = BaseRecord; PYBIND11_MAKE_OPAQUE(PyIterationContainer) PYBIND11_MAKE_OPAQUE(PyMeshContainer) PYBIND11_MAKE_OPAQUE(PyPartContainer) @@ -51,3 +55,5 @@ PYBIND11_MAKE_OPAQUE(PyPatchRecordContainer) PYBIND11_MAKE_OPAQUE(PyRecordComponentContainer) PYBIND11_MAKE_OPAQUE(PyMeshRecordComponentContainer) PYBIND11_MAKE_OPAQUE(PyPatchRecordComponentContainer) +PYBIND11_MAKE_OPAQUE(PyBaseRecordRecordComponent) +PYBIND11_MAKE_OPAQUE(PyBaseRecordPatchRecordComponent) diff --git a/include/openPMD/binding/python/Container.H b/include/openPMD/binding/python/Container.H index 28d0abedd1..3ee7ab33aa 100644 --- a/include/openPMD/binding/python/Container.H +++ b/include/openPMD/binding/python/Container.H @@ -47,16 +47,14 @@ namespace openPMD * * BSD-style license, see pybind11 LICENSE file. */ -template < - typename Map, - typename holder_type = std::unique_ptr, - typename... Args> -py::class_ -declare_container(py::handle scope, std::string const &name, Args &&...args) +template +py::class_, Args...> +declare_container(py::handle scope, std::string const &name) { + using holder_type = std::unique_ptr; using KeyType = typename Map::key_type; using MappedType = typename Map::mapped_type; - using Class_ = py::class_; + using Class_ = py::class_; // If either type is a non-module-local bound type then make the map // binding non-local as well; otherwise (e.g. both types are either @@ -69,13 +67,9 @@ declare_container(py::handle scope, std::string const &name, Args &&...args) local = !tinfo || tinfo->module_local; } - Class_ cl( - scope, - name.c_str(), - py::module_local(local), - std::forward(args)...); + Class_ cl(scope, name.c_str(), py::module_local(local)); - cl.def(py::init()); + // cl.def(py::init()); // Register stream insertion operator (if possible) py::detail::map_if_insertion_operator(cl, name); @@ -110,15 +104,11 @@ declare_container(py::handle scope, std::string const &name, Args &&...args) return cl; } -template < - typename Map, - typename holder_type = std::unique_ptr> -py::class_ -finalize_container(py::class_ cl) +template +Class_ finalize_container(Class_ cl) { using KeyType = typename Map::key_type; using MappedType = typename Map::mapped_type; - using Class_ = py::class_; cl.def( "items", diff --git a/include/openPMD/binding/python/Container.hpp b/include/openPMD/binding/python/Container.hpp deleted file mode 100644 index 0b24951108..0000000000 --- a/include/openPMD/binding/python/Container.hpp +++ /dev/null @@ -1,152 +0,0 @@ -/* Copyright 2018-2022 Axel Huebl and Franz Poeschel - * - * This file is part of openPMD-api. - * - * openPMD-api is free software: you can redistribute it and/or modify - * it under the terms of of either the GNU General Public License or - * the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * openPMD-api is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License and the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License - * and the GNU Lesser General Public License along with openPMD-api. - * If not, see . - * - * The function `bind_container` is based on std_bind.h in pybind11 - * Copyright (c) 2016 Sergey Lyskov and Wenzel Jakob - * - * BSD-style license, see pybind11 LICENSE file. - */ - -#pragma once - -#include "openPMD/backend/Attributable.hpp" - -#include -#include -#include - -#include -#include -#include -#include - -namespace py = pybind11; - -namespace openPMD::detail -{ -/* based on std_bind.h in pybind11 - * - * Copyright (c) 2016 Sergey Lyskov and Wenzel Jakob - * - * BSD-style license, see pybind11 LICENSE file. - */ -template -Class_ bind_container(Class_ &cl, std::string const &name) -{ - using KeyType = typename Map::key_type; - using MappedType = typename Map::mapped_type; - - // Register stream insertion operator (if possible) - py::detail::map_if_insertion_operator(cl, name); - - cl.def( - "__bool__", - [](const Map &m) -> bool { return !m.empty(); }, - "Check whether the container is nonempty"); - - cl.def( - "__iter__", - [](Map &m) { return py::make_key_iterator(m.begin(), m.end()); }, - // keep container alive while iterator exists - py::keep_alive<0, 1>()); - - cl.def("__repr__", [name](Map const &m) { - std::stringstream stream; - stream << ""; - return stream.str(); - }); - - cl.def( - "items", - [](Map &m) { return py::make_iterator(m.begin(), m.end()); }, - // keep container alive while iterator exists - py::keep_alive<0, 1>()); - - // keep same policy as Container class: missing keys are created - cl.def( - "__getitem__", - [](Map &m, KeyType const &k) -> MappedType & { return m[k]; }, - // copy + keepalive - // All objects in the openPMD object model are handles, so using a copy - // is safer and still performant. - py::return_value_policy::copy, - py::keep_alive<0, 1>()); - - // Assignment provided only if the type is copyable - py::detail::map_assignment(cl); - - cl.def("__delitem__", [](Map &m, KeyType const &k) { - auto it = m.find(k); - if (it == m.end()) - throw py::key_error(); - m.erase(it); - }); - - cl.def("__len__", &Map::size); - - cl.def("_ipython_key_completions_", [](Map &m) { - auto l = py::list(); - for (const auto &myPair : m) - l.append(myPair.first); - return l; - }); - - return cl; -} - -template -py::class_, Args...> -create_and_bind_container(py::handle scope, std::string const &name) -{ - using holder_type = std::unique_ptr; - using KeyType = typename Map::key_type; - using MappedType = typename Map::mapped_type; - using Class_ = py::class_; - - // If either type is a non-module-local bound type then make the map - // binding non-local as well; otherwise (e.g. both types are either - // module-local or converting) the map will be module-local. - auto tinfo = py::detail::get_type_info(typeid(MappedType)); - bool local = !tinfo || tinfo->module_local; - if (local) - { - tinfo = py::detail::get_type_info(typeid(KeyType)); - local = !tinfo || tinfo->module_local; - } - - Class_ cl( - scope, - name.c_str(), - py::module_local(local), - py::multiple_inheritance()); - - return bind_container(cl, name); -} -} // namespace openPMD::detail diff --git a/include/openPMD/binding/python/RecordComponent.hpp b/include/openPMD/binding/python/RecordComponent.hpp index 70a957791a..80a349bfd4 100644 --- a/include/openPMD/binding/python/RecordComponent.hpp +++ b/include/openPMD/binding/python/RecordComponent.hpp @@ -46,6 +46,13 @@ py::array load_chunk(RecordComponent &r, py::tuple const &slices); void store_chunk(RecordComponent &r, py::array &a, py::tuple const &slices); +namespace docstring +{ +constexpr static char const *is_scalar = R"docstr( +Returns true if this record only contains a single component. +)docstr"; +} + template Class &&addRecordComponentSetGet(Class &&class_) { diff --git a/src/binding/python/BaseRecord.cpp b/src/binding/python/BaseRecord.cpp deleted file mode 100644 index dd90006c23..0000000000 --- a/src/binding/python/BaseRecord.cpp +++ /dev/null @@ -1,59 +0,0 @@ -/* Copyright 2018-2021 Axel Huebl - * - * This file is part of openPMD-api. - * - * openPMD-api is free software: you can redistribute it and/or modify - * it under the terms of of either the GNU General Public License or - * the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * openPMD-api is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License and the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License - * and the GNU Lesser General Public License along with openPMD-api. - * If not, see . - */ -#include "openPMD/backend/BaseRecord.hpp" -#include "openPMD/backend/BaseRecordComponent.hpp" -#include "openPMD/backend/Container.hpp" -#include "openPMD/backend/MeshRecordComponent.hpp" -#include "openPMD/backend/PatchRecordComponent.hpp" - -#include "openPMD/binding/python/Common.hpp" -#include "openPMD/binding/python/Container.hpp" -#include "openPMD/binding/python/RecordComponent.hpp" -#include "openPMD/binding/python/UnitDimension.hpp" - -void init_BaseRecord(py::module &m) -{ - constexpr auto doc_scalar = R"docstr( -Returns true if this record only contains a single component. -)docstr"; - - addRecordComponentSetGet( - detail::create_and_bind_container< - BaseRecord, - Container, - RecordComponent>(m, "Base_Record_Record_Component")) - .def_property_readonly( - "scalar", &BaseRecord::scalar, doc_scalar); - addRecordComponentSetGet( - detail::create_and_bind_container< - BaseRecord, - Container, - MeshRecordComponent>(m, "Base_Record_Mesh_Record_Component")) - .def_property_readonly( - "scalar", &BaseRecord::scalar, doc_scalar); - addRecordComponentSetGet( - detail::create_and_bind_container< - BaseRecord, - Container, - PatchRecordComponent>(m, "Base_Record_Patch_Record_Component")) - .def_property_readonly( - "scalar", &BaseRecord::scalar, doc_scalar); -} diff --git a/src/binding/python/Iteration.cpp b/src/binding/python/Iteration.cpp index a9dc2c23c8..df017114e6 100644 --- a/src/binding/python/Iteration.cpp +++ b/src/binding/python/Iteration.cpp @@ -20,6 +20,7 @@ */ #include "openPMD/Iteration.hpp" +#include "openPMD/backend/Attributable.hpp" #include "openPMD/binding/python/Common.hpp" #include "openPMD/binding/python/Container.H" @@ -29,8 +30,8 @@ void init_Iteration(py::module &m) { - auto py_it_cont = - declare_container(m, "Iteration_Container"); + auto py_it_cont = declare_container( + m, "Iteration_Container"); py::class_(m, "Iteration") .def(py::init()) diff --git a/src/binding/python/Mesh.cpp b/src/binding/python/Mesh.cpp index 506e1bba70..55c6fd13a4 100644 --- a/src/binding/python/Mesh.cpp +++ b/src/binding/python/Mesh.cpp @@ -19,6 +19,7 @@ * If not, see . */ #include "openPMD/Mesh.hpp" +#include "openPMD/backend/Attributable.hpp" #include "openPMD/backend/BaseRecord.hpp" #include "openPMD/backend/MeshRecordComponent.hpp" @@ -32,7 +33,8 @@ void init_Mesh(py::module &m) { - auto py_m_cont = declare_container(m, "Mesh_Container"); + auto py_m_cont = + declare_container(m, "Mesh_Container"); py::class_ > cl(m, "Mesh"); diff --git a/src/binding/python/MeshRecordComponent.cpp b/src/binding/python/MeshRecordComponent.cpp index e2e5e7b42a..1a43f0e289 100644 --- a/src/binding/python/MeshRecordComponent.cpp +++ b/src/binding/python/MeshRecordComponent.cpp @@ -23,17 +23,20 @@ #include "openPMD/RecordComponent.hpp" #include "openPMD/Series.hpp" +#include "openPMD/backend/Attributable.hpp" #include "openPMD/binding/python/Common.hpp" #include "openPMD/binding/python/Container.H" #include "openPMD/binding/python/Pickle.hpp" +#include "openPMD/binding/python/RecordComponent.hpp" #include #include void init_MeshRecordComponent(py::module &m) { - auto py_mrc_cnt = declare_container( - m, "Mesh_Record_Component_Container"); + auto py_mrc_cnt = + declare_container( + m, "Mesh_Record_Component_Container"); py::class_ cl( m, "Mesh_Record_Component"); @@ -85,4 +88,14 @@ void init_MeshRecordComponent(py::module &m) }); finalize_container(py_mrc_cnt); + addRecordComponentSetGet( + finalize_container( + declare_container< + PyBaseRecordMeshRecordComponent, + PyMeshRecordComponentContainer, + MeshRecordComponent>(m, "Base_Record_Mesh_Record_Component"))) + .def_property_readonly( + "scalar", + &BaseRecord::scalar, + &docstring::is_scalar[1]); } diff --git a/src/binding/python/ParticlePatches.cpp b/src/binding/python/ParticlePatches.cpp index f04f36bf09..dbe4546514 100644 --- a/src/binding/python/ParticlePatches.cpp +++ b/src/binding/python/ParticlePatches.cpp @@ -19,6 +19,7 @@ * If not, see . */ #include "openPMD/ParticlePatches.hpp" +#include "openPMD/backend/Attributable.hpp" #include "openPMD/backend/Container.hpp" #include "openPMD/backend/PatchRecord.hpp" @@ -29,8 +30,8 @@ void init_ParticlePatches(py::module &m) { - auto py_pp_cnt = - declare_container(m, "Particle_Patches_Container"); + auto py_pp_cnt = declare_container( + m, "Particle_Patches_Container"); py::class_ >(m, "Particle_Patches") .def( diff --git a/src/binding/python/ParticleSpecies.cpp b/src/binding/python/ParticleSpecies.cpp index ae8f08b711..55fe0aaef0 100644 --- a/src/binding/python/ParticleSpecies.cpp +++ b/src/binding/python/ParticleSpecies.cpp @@ -21,6 +21,7 @@ #include "openPMD/ParticleSpecies.hpp" #include "openPMD/Record.hpp" #include "openPMD/Series.hpp" +#include "openPMD/backend/Attributable.hpp" #include "openPMD/backend/Container.hpp" #include "openPMD/binding/python/Common.hpp" @@ -33,8 +34,8 @@ void init_ParticleSpecies(py::module &m) { - auto py_ps_cnt = - declare_container(m, "Particle_Container"); + auto py_ps_cnt = declare_container( + m, "Particle_Container"); py::class_ > cl(m, "ParticleSpecies"); cl.def( diff --git a/src/binding/python/PatchRecord.cpp b/src/binding/python/PatchRecord.cpp index efeea08a97..72a0eec012 100644 --- a/src/binding/python/PatchRecord.cpp +++ b/src/binding/python/PatchRecord.cpp @@ -20,6 +20,7 @@ */ #include "openPMD/backend/PatchRecord.hpp" +#include "openPMD/backend/Attributable.hpp" #include "openPMD/backend/BaseRecord.hpp" #include "openPMD/backend/PatchRecordComponent.hpp" @@ -29,8 +30,8 @@ void init_PatchRecord(py::module &m) { - auto py_pr_cnt = - declare_container(m, "Patch_Record_Container"); + auto py_pr_cnt = declare_container( + m, "Patch_Record_Container"); py::class_ >( m, "Patch_Record") diff --git a/src/binding/python/PatchRecordComponent.cpp b/src/binding/python/PatchRecordComponent.cpp index 08059826e7..394afbec35 100644 --- a/src/binding/python/PatchRecordComponent.cpp +++ b/src/binding/python/PatchRecordComponent.cpp @@ -21,11 +21,13 @@ #include "openPMD/backend/PatchRecordComponent.hpp" #include "openPMD/DatatypeHelpers.hpp" +#include "openPMD/backend/Attributable.hpp" #include "openPMD/backend/BaseRecordComponent.hpp" #include "openPMD/binding/python/Common.hpp" #include "openPMD/binding/python/Container.H" #include "openPMD/binding/python/Numpy.hpp" +#include "openPMD/binding/python/RecordComponent.hpp" namespace { @@ -43,8 +45,9 @@ struct Prc_Load void init_PatchRecordComponent(py::module &m) { - auto py_prc_cnt = declare_container( - m, "Patch_Record_Component_Container"); + auto py_prc_cnt = + declare_container( + m, "Patch_Record_Component_Container"); py::class_( m, "Patch_Record_Component") @@ -201,4 +204,14 @@ void init_PatchRecordComponent(py::module &m) .def("set_unit_SI", &PatchRecordComponent::setUnitSI); finalize_container(py_prc_cnt); + addRecordComponentSetGet( + finalize_container( + declare_container< + PyBaseRecordPatchRecordComponent, + PyPatchRecordComponentContainer, + PatchRecordComponent>(m, "Base_Record_Patch_Record_Component"))) + .def_property_readonly( + "scalar", + &BaseRecord::scalar, + &docstring::is_scalar[1]); } diff --git a/src/binding/python/Record.cpp b/src/binding/python/Record.cpp index 4b16088268..9cad75d03a 100644 --- a/src/binding/python/Record.cpp +++ b/src/binding/python/Record.cpp @@ -20,6 +20,7 @@ */ #include "openPMD/Record.hpp" #include "openPMD/RecordComponent.hpp" +#include "openPMD/backend/Attributable.hpp" #include "openPMD/backend/BaseRecord.hpp" #include "openPMD/binding/python/Common.hpp" @@ -32,7 +33,8 @@ void init_Record(py::module &m) { - auto py_r_cnt = declare_container(m, "Record_Container"); + auto py_r_cnt = declare_container( + m, "Record_Container"); py::class_ > cl(m, "Record"); cl.def(py::init()) diff --git a/src/binding/python/RecordComponent.cpp b/src/binding/python/RecordComponent.cpp index 9a0332b2c5..875fdfa6d1 100644 --- a/src/binding/python/RecordComponent.cpp +++ b/src/binding/python/RecordComponent.cpp @@ -22,8 +22,6 @@ #include #include -#include "openPMD/binding/python/RecordComponent.hpp" - #include "openPMD/DatatypeHelpers.hpp" #include "openPMD/Error.hpp" #include "openPMD/Series.hpp" @@ -33,6 +31,7 @@ #include "openPMD/binding/python/Container.H" #include "openPMD/binding/python/Numpy.hpp" #include "openPMD/binding/python/Pickle.hpp" +#include "openPMD/binding/python/RecordComponent.hpp" #include #include @@ -763,8 +762,9 @@ void init_RecordComponent(py::module &m) return view.currentView(); }); - auto py_rc_cnt = declare_container( - m, "Record_Component_Container"); + auto py_rc_cnt = + declare_container( + m, "Record_Component_Container"); py::class_ cl(m, "Record_Component"); cl.def( @@ -1084,6 +1084,16 @@ void init_RecordComponent(py::module &m) addRecordComponentSetGet(cl); finalize_container(py_rc_cnt); + addRecordComponentSetGet( + finalize_container( + declare_container< + PyBaseRecordRecordComponent, + PyRecordComponentContainer, + RecordComponent>(m, "Base_Record_Record_Component"))) + .def_property_readonly( + "scalar", + &BaseRecord::scalar, + &docstring::is_scalar[1]); py::enum_(m, "Allocation") .value("USER", RecordComponent::Allocation::USER) diff --git a/src/binding/python/openPMD.cpp b/src/binding/python/openPMD.cpp index da6ebb0ebd..fe26bfced8 100644 --- a/src/binding/python/openPMD.cpp +++ b/src/binding/python/openPMD.cpp @@ -95,7 +95,6 @@ PYBIND11_MODULE(openpmd_api_cxx, m) init_MeshRecordComponent(m); init_PatchRecordComponent(m); - init_BaseRecord(m); init_Record(m); init_PatchRecord(m); init_ParticlePatches(m);