diff --git a/python/cable_cell_io.cpp b/python/cable_cell_io.cpp index b5c1272cf5cc171460a6d6f3d7d45054e3d4fe13..2ff3ac8bb670a71609f51e3d02dacca11957e705 100644 --- a/python/cable_cell_io.cpp +++ b/python/cable_cell_io.cpp @@ -9,14 +9,18 @@ #include <arborio/cableio.hpp> #include "error.hpp" +#include "util.hpp" #include "strprintf.hpp" namespace pyarb { -arborio::cable_cell_component load_component(const std::string& fname) { +namespace py = pybind11; + +arborio::cable_cell_component load_component(py::object fn) { + const auto fname = util::to_path(fn); std::ifstream fid{fname}; if (!fid.good()) { - throw pyarb_error("Can't open file '{}'" + fname); + throw arb::file_not_found_error(fname); } auto component = arborio::parse_component(fid); if (!component) { @@ -26,13 +30,13 @@ arborio::cable_cell_component load_component(const std::string& fname) { }; template<typename T> -void write_component(const T& component, const std::string& fname) { - std::ofstream fid(fname); +void write_component(const T& component, py::object fn) { + std::ofstream fid(util::to_path(fn)); arborio::write_component(fid, component, arborio::meta_data{}); } -void write_component(const arborio::cable_cell_component& component, const std::string& fname) { - std::ofstream fid(fname); +void write_component(const arborio::cable_cell_component& component, py::object fn) { + std::ofstream fid(util::to_path(fn)); arborio::write_component(fid, component); } @@ -43,40 +47,40 @@ void register_cable_loader(pybind11::module& m) { "Load arbor-component (decor, morphology, label_dict, cable_cell) from file."); m.def("write_component", - [](const arborio::cable_cell_component& d, const std::string& fname) { - return write_component(d, fname); + [](const arborio::cable_cell_component& d, py::object fn) { + return write_component(d, fn); }, pybind11::arg_v("object", "the cable_component object."), - pybind11::arg_v("filename", "the name of the file."), + pybind11::arg_v("filename", "the path of the file."), "Write cable_component to file."); m.def("write_component", - [](const arb::decor& d, const std::string& fname) { - return write_component<arb::decor>(d, fname); + [](const arb::decor& d, py::object fn) { + return write_component<arb::decor>(d, fn); }, pybind11::arg_v("object", "the decor object."), pybind11::arg_v("filename", "the name of the file."), "Write decor to file."); m.def("write_component", - [](const arb::label_dict& d, const std::string& fname) { - return write_component<arb::label_dict>(d, fname); + [](const arb::label_dict& d, py::object fn) { + return write_component<arb::label_dict>(d, fn); }, pybind11::arg_v("object", "the label_dict object."), pybind11::arg_v("filename", "the name of the file."), "Write label_dict to file."); m.def("write_component", - [](const arb::morphology& d, const std::string& fname) { - return write_component<arb::morphology>(d, fname); + [](const arb::morphology& d, py::object fn) { + return write_component<arb::morphology>(d, fn); }, pybind11::arg_v("object", "the morphology object."), pybind11::arg_v("filename", "the name of the file."), "Write morphology to file."); m.def("write_component", - [](const arb::cable_cell& d, const std::string& fname) { - return write_component<arb::cable_cell>(d, fname); + [](const arb::cable_cell& d, py::object fn) { + return write_component<arb::cable_cell>(d, fn); }, pybind11::arg_v("object", "the cable_cell object."), pybind11::arg_v("filename", "the name of the file."), diff --git a/python/mechanism.cpp b/python/mechanism.cpp index a774cad46c9f6fd5e8cf9fa33d6e9389d964c13f..80db103093da13430aefdcd59c7e2a8c2ca90627 100644 --- a/python/mechanism.cpp +++ b/python/mechanism.cpp @@ -11,6 +11,7 @@ #include "arbor/mechinfo.hpp" +#include "util.hpp" #include "conversion.hpp" #include "strprintf.hpp" @@ -197,7 +198,7 @@ void register_mechanisms(pybind11::module& m) { m.def("default_catalogue", [](){return arb::global_default_catalogue();}); m.def("allen_catalogue", [](){return arb::global_allen_catalogue();}); m.def("bbp_catalogue", [](){return arb::global_bbp_catalogue();}); - m.def("load_catalogue", [](const std::string& fn){return arb::load_catalogue(fn);}); + m.def("load_catalogue", [](pybind11::object fn) { return arb::load_catalogue(util::to_string(fn)); }); // arb::mechanism_desc // For specifying a mechanism in the cable_cell interface. diff --git a/python/morphology.cpp b/python/morphology.cpp index a5d3fb0d15804616503c23b69c9109b67a5d19ca..8f4293ca13dba4128ee1f66e9ff5fc32c3ec8f54 100644 --- a/python/morphology.cpp +++ b/python/morphology.cpp @@ -20,6 +20,7 @@ #include <arborio/neuroml.hpp> #endif +#include "util.hpp" #include "error.hpp" #include "proxy.hpp" #include "strprintf.hpp" @@ -250,10 +251,11 @@ void register_morphology(py::module& m) { // Function that creates a morphology from an swc file. // Wraps calls to C++ functions arborio::parse_swc() and arborio::load_swc_arbor(). m.def("load_swc_arbor", - [](std::string fname) { + [](py::object fn) { + const auto fname = util::to_path(fn); std::ifstream fid{fname}; if (!fid.good()) { - throw pyarb_error(util::pprintf("can't open file '{}'", fname)); + throw arb::file_not_found_error(fname); } try { auto data = arborio::parse_swc(fid); @@ -275,10 +277,11 @@ void register_morphology(py::module& m) { " are no gaps in the resulting morphology."); m.def("load_swc_neuron", - [](std::string fname) { + [](py::object fn) { + const auto fname = util::to_path(fn); std::ifstream fid{fname}; if (!fid.good()) { - throw pyarb_error(util::pprintf("can't open file '{}'", fname)); + throw arb::file_not_found_error(fname); } try { auto data = arborio::parse_swc(fid); @@ -383,10 +386,11 @@ void register_morphology(py::module& m) { neuroml // constructors .def(py::init( - [](std::string fname) { + [](py::object fn) { + const auto fname = util::to_path(fn); std::ifstream fid{fname}; if (!fid.good()) { - throw pyarb_error(util::pprintf("can't open file '{}'", fname)); + throw arb::file_not_found_error(fname); } try { std::string string_data((std::istreambuf_iterator<char>(fid)), diff --git a/python/util.hpp b/python/util.hpp new file mode 100644 index 0000000000000000000000000000000000000000..fe1b6b07d100b7e46fe41b82029aa51282344b33 --- /dev/null +++ b/python/util.hpp @@ -0,0 +1,27 @@ +#pragma once + +#include <pybind11/pybind11.h> + +#include "strprintf.hpp" + +namespace pyarb { +namespace util { + +namespace py = pybind11; + +inline +std::string to_path(py::object fn) { + if (py::isinstance<py::str>(fn)) { + return std::string{py::str(fn)}; + } + else if (py::isinstance(fn, + py::module_::import("pathlib").attr("Path"))) { + return std::string{py::str(fn)}; + } + throw std::runtime_error( + util::strprintf("Cannot convert objects of type '{}' to a path-like.", + std::string{py::str(fn.get_type())})); +} + +} +}