TerrainGen coverage


terraingen/
Coverage:
low: ≥ 0%
medium: ≥ 75.0%
high: ≥ 90.0%
Lines:
294 / 294
100.0%
Branches:
12 / 12
100.0%
Functions:
86 / 86, 1 excl
100.0%

python/src/common.h
Line Branch Exec Source
1 /// @file
2 /// @brief What every binding file shares: the nanobind alias, casters and option helpers.
3 #pragma once
4
5 #include "casters.h"
6
7 #include <nanobind/nanobind.h>
8 #include <nanobind/stl/filesystem.h>
9 #include <nanobind/stl/function.h>
10 #include <nanobind/stl/optional.h>
11 #include <nanobind/stl/pair.h>
12 #include <nanobind/stl/shared_ptr.h>
13 #include <nanobind/stl/string.h>
14 #include <nanobind/stl/string_view.h>
15 #include <nanobind/stl/tuple.h>
16 #include <nanobind/stl/vector.h>
17
18 #include <limits>
19 #include <memory>
20 #include <optional>
21
22 namespace terraingen::python {
23
24 namespace nb = nanobind;
25 using namespace nb::literals;
26
27 /// Binds `__init__(**kwargs)` for an option struct: the defaults, then each keyword set as the
28 /// attribute of that name, so `BoulderLayerOptions(coverage=0.05)` reads like its config.
29 2684 template <typename T, typename Class> void BindKwargsInit(Class& cls) {
30 cls.def(
31 "__init__",
32 2598 [](T* self, nb::kwargs kwargs) {
33 2 new (self) T{};
34 2 const nb::handle instance = nb::find(self);
35 2 nb::inst_mark_ready(instance);
36
10/10
terraingen::python::BindKwargsInit<terraingen::GeoTiffWriteOptions, nanobind::class_<terraingen::GeoTiffWriteOptions> >(nanobind::class_<terraingen::GeoTiffWriteOptions>&)::{lambda(terraingen::GeoTiffWriteOptions*, nanobind::kwargs)#1}::operator()(terraingen::GeoTiffWriteOptions*, nanobind::kwargs) const:
✓ Branch 1 taken 1 time.
✓ Branch 5 taken 2 times.
✓ Branch 10 taken 2 times.
✓ Branch 13 taken 2 times.
✓ Branch 14 taken 1 time.
terraingen::python::BindKwargsInit<terraingen::RasterFieldOptions, nanobind::class_<terraingen::RasterFieldOptions> >(nanobind::class_<terraingen::RasterFieldOptions>&)::{lambda(terraingen::RasterFieldOptions*, nanobind::kwargs)#1}::operator()(terraingen::RasterFieldOptions*, nanobind::kwargs) const:
✓ Branch 1 taken 1 time.
✓ Branch 5 taken 1 time.
✓ Branch 10 taken 1 time.
✓ Branch 13 taken 1 time.
✓ Branch 14 taken 1 time.
5 for (auto [key, value] : kwargs) {
37
2/2
terraingen::python::BindKwargsInit<terraingen::GeoTiffWriteOptions, nanobind::class_<terraingen::GeoTiffWriteOptions> >(nanobind::class_<terraingen::GeoTiffWriteOptions>&)::{lambda(terraingen::GeoTiffWriteOptions*, nanobind::kwargs)#1}::operator()(terraingen::GeoTiffWriteOptions*, nanobind::kwargs) const:
✓ Branch 1 taken 2 times.
terraingen::python::BindKwargsInit<terraingen::RasterFieldOptions, nanobind::class_<terraingen::RasterFieldOptions> >(nanobind::class_<terraingen::RasterFieldOptions>&)::{lambda(terraingen::RasterFieldOptions*, nanobind::kwargs)#1}::operator()(terraingen::RasterFieldOptions*, nanobind::kwargs) const:
✓ Branch 1 taken 1 time.
3 nb::setattr(instance, key, value);
38 }
39 },
40 "Defaults, with each keyword setting the attribute of that name.");
41 2684 }
42
43 /// Binds `name` as an attribute of `Outer` that reads and writes `(outer.*group).*field`,
44 /// so options grouped into structs in C++ keep the flat attribute names of their config.
45 template <typename Outer, typename Group, typename T, typename Class>
46 1892 void BindGrouped(Class& cls, const char* name, Group Outer::* group, T Group::* field) {
47 cls.def_prop_rw(
48 3784 name, [group, field](Outer& outer) -> T& { return (outer.*group).*field; },
49 1892 [group, field](Outer& outer, const T& value) { (outer.*group).*field = value; });
50 1892 }
51
52 /// Binds the fields of an options struct's `CraterSelection` under their flat config
53 /// names: the diameter bounds as `minDiameter` and `maxDiameter`, then `min_age_gyr`,
54 /// `max_age_gyr` and `manual`.
55 template <typename Outer, typename Selection, typename Class>
56 132 void BindSelection(Class& cls, Selection Outer::* selection, const char* minDiameter,
57 const char* maxDiameter) {
58 132 BindGrouped(cls, minDiameter, selection, &Selection::minDiameter);
59 132 BindGrouped(cls, maxDiameter, selection, &Selection::maxDiameter);
60 132 BindGrouped(cls, "min_age_gyr", selection, &Selection::minAgeGyr);
61 132 BindGrouped(cls, "max_age_gyr", selection, &Selection::maxAgeGyr);
62 132 BindGrouped(cls, "manual", selection, &Selection::manual);
63 132 }
64
65 /// An upper bound from an optional value: `value`, or infinity for None.
66 7 inline double Bound(const std::optional<double>& value) {
67 7 return value.value_or(std::numeric_limits<double>::infinity());
68 }
69
70 /// `pointer` without const, since Python objects are never const.
71 21 template <typename T> std::shared_ptr<T> Mutable(const std::shared_ptr<const T>& pointer) {
72 21 return std::const_pointer_cast<T>(pointer);
73 }
74
75 /// The docstring of every `validate_*` function.
76 inline constexpr const char* kValidateDoc = "Raises ValueError naming the first invalid setting.";
77
78 } // namespace terraingen::python
79