Skip to content

Commit 7de4feb

Browse files
committed
Document Series constructor, add filepath option for config
Also test
1 parent e34539a commit 7de4feb

File tree

2 files changed

+53
-5
lines changed

2 files changed

+53
-5
lines changed

src/binding/python/Series.cpp

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -86,9 +86,26 @@ struct DefineSeriesConstructorPerPathType
8686

8787
static auto json_cfg_as_string(py::object const &obj) -> std::string
8888
{
89+
#if !openPMD_USE_FILESYSTEM_HEADER
90+
auto type_repr = py::repr(obj).cast<std::string>();
91+
if (type_repr.substr(0, 9) == "PosixPath" ||
92+
type_repr.substr(0, 11) == "WindowsPath")
93+
{
94+
auto casted = obj.attr("__str__")();
95+
return "@" + py::cast<std::string>(casted);
96+
}
97+
#endif
8998
return ::auxiliary::json_dumps(obj);
9099
}
91100

101+
#if openPMD_USE_FILESYSTEM_HEADER
102+
static auto json_cfg_as_string(std::filesystem::path const &cfg_path)
103+
-> std::string
104+
{
105+
return "@" + std::string(cfg_path);
106+
}
107+
#endif
108+
92109
static constexpr auto filepath_as_string(std::string const &str)
93110
-> std::string const &
94111
{
@@ -104,7 +121,6 @@ struct DefineSeriesConstructorPerPathType
104121
#else
105122
static auto filepath_as_string(py::object const &path) -> std::string
106123
{
107-
auto casted = path.attr("__str__")();
108124
auto type_repr = py::repr(path).cast<std::string>();
109125
if (type_repr.substr(0, 9) != "PosixPath" &&
110126
type_repr.substr(0, 11) != "WindowsPath")
@@ -113,6 +129,7 @@ struct DefineSeriesConstructorPerPathType
113129
"openpmd.Series constructor: 'filepath' argument may either be "
114130
"a String or pathlib.Path.");
115131
}
132+
auto casted = path.attr("__str__")();
116133
return py::cast<std::string>(casted);
117134
}
118135
#endif
@@ -139,11 +156,15 @@ struct DefineSeriesConstructorPerPathType
139156
R"END(
140157
Construct a new Series. Parameters:
141158
142-
* filepath: The file path.
159+
* filepath: The file path, either as a String or as pathlib.Path.
143160
* at: Access mode.
144161
* options: Advanced backend configuration via JSON.
145-
May be specified as a JSON-formatted string directly, or as a path
146-
to a JSON textfile, prepended by an at sign '@'.
162+
May be specified as:
163+
164+
1. a Python object representing the JSON structure,
165+
2. a JSON-formatted string directly,
166+
3. a pathlib.Path to a JSON textfile,
167+
3. as a String-type path to a JSON textfile, prepended by an at sign '@'.
147168
148169
For details on access modes, JSON/TOML configuration and iteration encoding,
149170
refer to:
@@ -375,12 +396,19 @@ not possible once it has been closed.
375396
py::class_<Series, Attributable> cl(m, "Series");
376397
::auxiliary::ForEachType<
377398
::internal::DefineSeriesConstructorPerPathType,
399+
// First tuple components are eligible types for the path argument
400+
// second component for the config argument
401+
// py::object needs to always come last, as a catch-all pattern
402+
#if openPMD_USE_FILESYSTEM_HEADER
378403
std::tuple<std::string, std::string>,
404+
std::tuple<std::string, std::filesystem::path>,
379405
std::tuple<std::string, py::object>,
380-
#if openPMD_USE_FILESYSTEM_HEADER
381406
std::tuple<std::filesystem::path, std::string>,
407+
std::tuple<std::filesystem::path, std::filesystem::path>,
382408
std::tuple<std::filesystem::path, py::object>
383409
#else
410+
std::tuple<std::string, std::string>,
411+
std::tuple<std::string, py::object>,
384412
std::tuple<py::object, std::string>,
385413
std::tuple<py::object, py::object>
386414
#endif

test/python/unittest/API/APITest.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2219,6 +2219,26 @@ def testCustomGeometries(self):
22192219
self.assertEqual(e_chargeDensity.geometry, io.Geometry.other)
22202220
self.assertEqual(e_chargeDensity.geometry_string, "other")
22212221

2222+
def testSeriesConstructors(self):
2223+
import json
2224+
from pathlib import Path
2225+
2226+
cfg = {"iteration_encoding": "variable_based"}
2227+
cfg_as_string = json.dumps(cfg)
2228+
cfg_as_file = "../samples/cfg.json"
2229+
with open(cfg_as_file, 'w') as f:
2230+
json.dump(cfg, f)
2231+
cfg_as_filepath = Path(cfg_as_file)
2232+
2233+
series_path = "../samples/series_constructors.json"
2234+
series_filepath = Path(series_path)
2235+
2236+
for f in [series_path, series_filepath]:
2237+
for c in [cfg, cfg_as_string, f"@{cfg_as_file}", cfg_as_filepath]:
2238+
# print(f"Creating Series with '{f}'\t'{c}'")
2239+
s = io.Series(f, io.Access.create, c)
2240+
s.close()
2241+
22222242

22232243
if __name__ == '__main__':
22242244
unittest.main()

0 commit comments

Comments
 (0)