|
welder 0.1.0
Bindings for annotated C++ types, from C++26 reflection
|
The pybind11 rod: a stateless policy type satisfying welder::rod. More...
#include <welder/rods/python/pybind11/rod.hpp>
Classes | |
| struct | enum_handle |
| Owning handle for a py::native_enum<E>, plus the scope + name to reach the finalized enum object. More... | |
Public Types | |
| using | module_type = py::module_ |
| pybind11's module handle. | |
| template<class T> | |
| using | construction_type |
| The type welder constructs when binding T — its registered trampoline if one exists, else T — so an abstract base with a trampoline stays constructible from a Python subclass. | |
| template<class T> | |
| using | class_handle_type |
| The class / enum handles the per-class / per-enum hooks operate on — exactly what make_class / make_enum yield. | |
| template<class E> | |
| using | enum_handle_type = enum_handle<E> |
Static Public Member Functions | |
| static consteval const char * | special_method_name (std::meta::info op_fn) |
| Map a member operator to its Python dunder (nullptr = not exposed). | |
| template<class T, auto Bases, std::size_t... I> | |
| static auto | make_class (module_type &m, const char *name, const char *doc, std::index_sequence< I... > seq) |
| Create the py::class_<T, Bases…> handle, weaving in a trampoline when T is a welded virtual type with a registered welder::rods::python::trampoline_for. | |
| template<class T, auto Bases, std::size_t... I> | |
| static auto | make_nested_class (module_type &, auto &outer_cls, const char *name, const char *doc, std::index_sequence< I... > seq) |
| Create the py::class_ for a nested member type T, registered under its enclosing type's class handle rather than the module — Python then sees it as module.Outer.Inner (and __qualname__ nests), exactly like a hand-written py::class_<Outer::Inner>(outer_cls, "Inner"). | |
| template<class T, auto Ctors, bool HasDefault, bool Aggregate> | |
| static void | add_constructors (auto &cls) |
| Bind T's whole constructor set (a chained-def framework just loops it): the default constructor when HasDefault, a py::init<…> per member of Ctors, and the synthesized aggregate field constructor when Aggregate. | |
| template<std::meta::info Mem, class Style = ::welder::naming::none> | |
| static void | add_field (auto &cls) |
| Bind data member Mem as an attribute. | |
| template<auto Fns, class Style = ::welder::naming::none> | |
| static void | add_method (auto &cls) |
| Bind method overload group Fns (name from Fns[0]; pybind11 chains one .def per overload and dispatches at call time). | |
| template<auto Fns, class Style = ::welder::naming::none> | |
| static void | add_static_method (auto &cls) |
| Bind static-method overload group Fns. | |
| template<auto Fns> | |
| static void | add_operator (auto &cls) |
| Bind operator overload group Fns under its Python dunder (one operator + arity per group, so Fns[0] names the slot). | |
| template<class E> | |
| static enum_handle< E > | make_enum (module_type &m, const char *name, const char *doc) |
| Create the enum_handle for E (a non-null doc becomes its docstring). | |
| template<class E> | |
| static enum_handle< E > | make_nested_enum (module_type &, auto &outer_cls, const char *name, const char *doc) |
| Create the enum_handle for a nested member enum E, scoped to its enclosing type's class handle — Python sees module.Outer.Mode, and an unscoped* nested enum's export_values() lands its enumerators on the class (mirroring C++'s Outer::red). | |
| template<std::meta::info Enum, class Style = ::welder::naming::none> | |
| static void | add_enumerator (auto &e) |
| Add enumerator Enum to the enum handle. | |
| template<class E> | |
| static void | finish_enum (auto &e) |
| Finalize enum E: export an unscoped enum's values into the enclosing scope, then commit the enum to the module. | |
| static py::dict | open_module (module_type &) |
| Open a per-module session: a dict accumulating live (mutable-variable) properties; _install_live_properties() applies them in one __class__ swap at close. | |
| static void | set_module_doc (module_type &m, const char *doc) |
| Set the (sub)module docstring. | |
| template<auto Fns, class Style = ::welder::naming::none> | |
| static py::object | add_function (module_type &m, const char *name=nullptr) |
| Bind free-function overload group Fns as one module-level function (name from Fns[0]; one chained .def per overload). | |
| template<std::meta::info Var, class Style = ::welder::naming::none> | |
| static void | add_variable (module_type &m, py::dict &live, const char *name_override=nullptr) |
| Bind namespace variable Var as a module attribute. | |
| static module_type | add_submodule (module_type &m, const char *name) |
| Create a submodule named name under m. | |
| static void | close_module (module_type &m, py::dict &live) |
| Close the session: apply any accumulated live properties. | |
Static Public Attributes | |
| static constexpr lang | language {lang::py} |
| welder::lang::py. | |
| template<class T> | |
| static constexpr bool | has_native_caster = !_needs_registration<T> |
| caster_oracle: T is convertible without welder registering a class for it iff pybind11 does not fall back to runtime class registration. | |
Static Protected Member Functions | |
| static consteval py::return_value_policy | _return_value_policy (::welder::rv_kind k) |
| Map welder's neutral welder::rv_kind to pybind11's return_value_policy. | |
| template<std::meta::info Fn, class Def, std::size_t... I, std::size_t... K> | |
| static void | _def_function (const char *name, Def def_into, std::index_sequence< I... >, std::index_sequence< K... >) |
| Register the function/method reflected by Fn onto a pybind11 target. | |
| template<std::meta::info Fn, class Def> | |
| static void | _def_function (const char *name, Def def_into) |
| Convenience overload: derive the parameter and keep_alive index sequences from Fn. | |
| template<std::meta::info Ctor, std::size_t... I> | |
| static void | _def_init (auto &cls, std::index_sequence< I... >) |
| Register py::init<P0, P1, …>() for constructor Ctor. | |
| template<class T, std::size_t... I> | |
| static void | _def_aggregate_init (auto &cls, std::index_sequence< I... >) |
| Synthesize a field constructor for a baseless aggregate T. | |
| static void | _install_live_properties (py::module_ &m, py::dict props) |
| Give module m live get/set semantics for the names in props. | |
| template<class T, class Trampoline, auto Bases, std::size_t... I> | |
| static auto | _make_class (py::handle scope, const char *name, const char *doc, std::index_sequence< I... >) |
| Construct py::class_<T, NativeBases...> from a reflected base-type array. | |
| template<class T, auto Bases, std::size_t... I> | |
| static auto | _make_class_at (py::handle scope, const char *name, const char *doc, std::index_sequence< I... > seq) |
| The trampoline-aware class factory over an arbitrary registration scope — the shared body of make_class (scope = the module) and make_nested_class (scope = the enclosing class handle). | |
Static Protected Attributes | |
| template<class T> | |
| static constexpr bool | _needs_registration |
| Whether pybind11 can only convert T via runtime class registration. | |
The pybind11 rod: a stateless policy type satisfying welder::rod.
Its public static members are the pybind11 emission primitives welder's driver calls; the driver supplies all the reflection-derived decisions. Each implements the correspondingly-named hook of the welder::rod contract (and welder::caster_oracle) — every one carries a @see back to it, where the shared parameter and return-value semantics are documented once rather than repeated on each backend's mirror. The protected members below are pybind11-specific implementation helpers (prefixed _), not part of the contract.
| DocStyle | the docstring convention this rod folds function/parameter/ return docs into (a welder::doc_style). Defaults to welder::rods::python::google_style; pass welder::rods::python::numpy_style or welder::rods::python::sphinx_style to emit those dialects. Defaulted, so rod<> is the Google-style rod and code that wants a different dialect names rod<numpy_style>. |
| using welder::rods::pybind11::rod< DocStyle >::class_handle_type |
The class / enum handles the per-class / per-enum hooks operate on — exactly what make_class / make_enum yield.
class_handle_type<T> tracks make_class itself (so it captures the woven-in trampoline for a virtual T); it is its return type for a base-less T — welded bases, chosen by the carriage's resolution* rather than by T, are appended by make_class and so cannot be a function of T alone. Named as associated types so the welder::rod concept can shape-check the per-handle hooks against them. (Co-located with enum_handle, its definition.)
| using welder::rods::pybind11::rod< DocStyle >::construction_type |
The type welder constructs when binding T — its registered trampoline if one exists, else T — so an abstract base with a trampoline stays constructible from a Python subclass.
The driver reads this to decide default constructibility.
| using welder::rods::pybind11::rod< DocStyle >::enum_handle_type = enum_handle<E> |
| using welder::rods::pybind11::rod< DocStyle >::module_type = py::module_ |
|
inlinestaticprotected |
Synthesize a field constructor for a baseless aggregate T.
Emits py::init([](F0 f0, …) { return T{f0, …}; }, py::arg("f0"), …) so Python can build it from field values (T(f0, f1)) rather than only default-construct then assign.
| T | the aggregate type. |
| I | the field index pack. |
| cls | the class handle. |
Definition at line 229 of file rod.hpp.
References welder::detail::aggregate_fields().
Referenced by add_constructors().
|
inlinestaticprotected |
Convenience overload: derive the parameter and keep_alive index sequences from Fn.
Definition at line 194 of file rod.hpp.
References _def_function(), and welder::detail::keep_alive_pairs().
|
inlinestaticprotected |
Register the function/method reflected by Fn onto a pybind11 target.
The folded docstring is passed when non-empty, and py::arg(name)... when every parameter is named (so Python callers see real keyword arguments, not arg0/arg1). Two call policies ride along as trailing .def extras: the [[=welder::return_policy]] (mapped to return_value_policy, always passed — automatic is pybind11's default, so an unannotated call is unchanged) and each [[=welder::keep_alive]] (spliced as py::keep_alive<nurse, patient>()). A reference-category policy on a by-value return is rejected first (welder::validate_return_policy).
| Fn | a reflection of the function. |
| Def | the target-adapter callable type. |
| I | the parameter index pack. |
| K | the keep_alive-dependency index pack. |
| name | the Python name. |
| def_into | adapts the target — cls.def, cls.def_static, or m.def. |
Definition at line 163 of file rod.hpp.
References _return_value_policy(), welder::detail::all_params_named(), welder::doc(), welder::function_docstring(), welder::detail::keep_alive_pairs(), language, welder::none, welder::detail::param_names(), welder::return_policy_of(), and welder::validate_return_policy().
Referenced by _def_function(), add_function(), add_method(), add_operator(), and add_static_method().
|
inlinestaticprotected |
Register py::init<P0, P1, …>() for constructor Ctor.
Names the parameters (py::arg) when all are named, otherwise positional.
| Ctor | a reflection of the constructor. |
| I | the parameter index pack. |
| cls | the class handle. |
Definition at line 210 of file rod.hpp.
References welder::detail::all_params_named(), welder::detail::param_names(), and welder::detail::param_types().
Referenced by add_constructors().
|
inlinestaticprotected |
Give module m live get/set semantics for the names in props.
Reassigns m's Python class to a fresh subclass of its current class carrying props (name → property). Python modules don't support properties directly, but a module's __class__ may be swapped for a ModuleType subclass. Used only when a (sub)module exposes a mutable variable.
Subclassing the module's current class — rather than ModuleType outright — means repeated installs onto the same handle accumulate: welding a standalone variable and then a whole namespace onto the same module each add a layer, and the earlier properties survive in the MRO instead of being clobbered.
| m | the module handle. |
| props | a dict of name → property. |
Definition at line 252 of file rod.hpp.
Referenced by close_module().
|
inlinestaticprotected |
Construct py::class_<T, NativeBases...> from a reflected base-type array.
A non-null doc becomes the class docstring (pybind11 treats a bare const char* extra as the doc); nullptr is branched out rather than passed, since pybind11 would strdup it.
| T | the class type. |
| Bases | the static array of native base type reflections. |
| I | the base index pack. |
| scope | the registration scope — the module, or (for a nested type) the enclosing class handle; pybind11 accepts any handle. |
| name | the Python class name. |
| doc | the class docstring, or nullptr. |
Definition at line 282 of file rod.hpp.
References welder::doc().
Referenced by _make_class_at().
|
inlinestaticprotected |
The trampoline-aware class factory over an arbitrary registration scope — the shared body of make_class (scope = the module) and make_nested_class (scope = the enclosing class handle).
A type carrying virtual methods is bound overridable — it must register a trampoline (so Python subclasses can override those virtuals) or opt out with [[=welder::rods::python::bind_flat]]. When a trampoline is present, its coverage of T's virtuals is checked at compile time.
Definition at line 307 of file rod.hpp.
References _make_class(), and welder::doc().
Referenced by make_class(), and make_nested_class().
|
inlinestaticconstevalprotected |
Map welder's neutral welder::rv_kind to pybind11's return_value_policy.
pybind11 has no analogue of nanobind's none, so rv_kind::none is rejected at the bind site (a static_assert in _def_function) rather than mapped here; it falls through to automatic only to keep this total.
| k | the neutral policy. |
Definition at line 131 of file rod.hpp.
Referenced by _def_function().
|
inlinestatic |
Bind T's whole constructor set (a chained-def framework just loops it): the default constructor when HasDefault, a py::init<…> per member of Ctors, and the synthesized aggregate field constructor when Aggregate.
Definition at line 402 of file rod.hpp.
References _def_aggregate_init(), _def_init(), and welder::detail::aggregate_fields().
|
inlinestatic |
Add enumerator Enum to the enum handle.
Definition at line 588 of file rod.hpp.
References welder::name_of().
|
inlinestatic |
Bind data member Mem as an attribute.
pybind11 data members are already Python properties (data descriptors on the class), so a [[=welder::doc]] on the member rides along as the property's __doc__ — and thus reaches .pyi stubs. A const member is read-only (def_readonly); a mutable one is read/write (def_readwrite). The doc, when present, is passed as the property docstring. There is deliberately no setter docstring: a Python property surfaces only the getter's __doc__, so one would be pure overhead.
Definition at line 426 of file rod.hpp.
References welder::doc(), welder::doc_of(), and welder::name_of().
|
inlinestatic |
Bind free-function overload group Fns as one module-level function (name from Fns[0]; one chained .def per overload).
A non-null name overrides the resolved name (including any weld_as), used verbatim; nullptr falls back to the styled/weld_as name.
Definition at line 624 of file rod.hpp.
References _def_function(), welder::function, language, and welder::name_of_or().
|
inlinestatic |
Bind method overload group Fns (name from Fns[0]; pybind11 chains one .def per overload and dispatches at call time).
Definition at line 471 of file rod.hpp.
References _def_function(), and welder::name_of().
|
inlinestatic |
Bind operator overload group Fns under its Python dunder (one operator + arity per group, so Fns[0] names the slot).
Definition at line 497 of file rod.hpp.
References _def_function(), and welder::rods::python::operator_dunder().
|
inlinestatic |
Bind static-method overload group Fns.
Definition at line 483 of file rod.hpp.
References _def_function(), language, welder::name_of(), and welder::static_method.
|
inlinestatic |
|
inlinestatic |
Bind namespace variable Var as a module attribute.
A const/constexpr variable becomes a value snapshot; a mutable one becomes a live get/set property over the C++ global (accumulated in live). A non-null name_override is used verbatim (beating any weld_as); nullptr falls back to the styled/weld_as name.
Definition at line 642 of file rod.hpp.
References welder::name_of_or().
|
inlinestatic |
Close the session: apply any accumulated live properties.
Definition at line 668 of file rod.hpp.
References _install_live_properties().
|
inlinestatic |
Finalize enum E: export an unscoped enum's values into the enclosing scope, then commit the enum to the module.
|
inlinestatic |
Create the py::class_<T, Bases…> handle, weaving in a trampoline when T is a welded virtual type with a registered welder::rods::python::trampoline_for.
A type carrying virtual methods is bound overridable — it must register a trampoline (so Python subclasses can override those virtuals) or opt out with [[=welder::rods::python::bind_flat]]. When a trampoline is present, its coverage of T's virtuals is checked at compile time.
Definition at line 381 of file rod.hpp.
References _make_class_at(), and welder::doc().
|
inlinestatic |
Create the enum_handle for E (a non-null doc becomes its docstring).
Definition at line 564 of file rod.hpp.
References welder::doc().
|
inlinestatic |
Create the py::class_ for a nested member type T, registered under its enclosing type's class handle rather than the module — Python then sees it as module.Outer.Inner (and __qualname__ nests), exactly like a hand-written py::class_<Outer::Inner>(outer_cls, "Inner").
Same trampoline weaving as make_class.
Definition at line 392 of file rod.hpp.
References _make_class_at(), and welder::doc().
|
inlinestatic |
Create the enum_handle for a nested member enum E, scoped to its enclosing type's class handle — Python sees module.Outer.Mode, and an unscoped* nested enum's export_values() lands its enumerators on the class (mirroring C++'s Outer::red).
Definition at line 578 of file rod.hpp.
References welder::doc().
|
inlinestatic |
Open a per-module session: a dict accumulating live (mutable-variable) properties; _install_live_properties() applies them in one __class__ swap at close.
|
inlinestatic |
Set the (sub)module docstring.
Definition at line 614 of file rod.hpp.
References welder::doc().
|
inlinestaticconsteval |
Map a member operator to its Python dunder (nullptr = not exposed).
|
staticconstexprprotected |
Whether pybind11 can only convert T via runtime class registration.
True iff T's caster is (or derives from) the generic type_caster_base fallback, which looks T up in pybind11's registered-types map. True for program-defined classes and enums; false for scalars, strings and the pybind11 wrapper types (py::object, py::dict, …). This is the one bindability fact welder's core cannot know on its own; it drives has_native_caster below.
Two things it deliberately does NOT see through — both making it conservative* (it may over-report needs-registration, never under-report):
A user type_caster is trusted (reads false) only when it is self-contained* — it does not itself derive from type_caster_base (e.g. a PYBIND11_TYPE_CASTER caster). One that derives from type_caster_base still needs T registered, so it correctly still reads true.
Enums are forced into the needs-registration bucket**: pybind11 3's dedicated enum caster does not derive type_caster_base, but it converts only once the enum is registered (py::native_enum / legacy py::enum_) — an unregistered enum raises at call time and renders raw C++ names in docstrings/stubs. Forcing it keeps welder's gate honest (a welded enum's registration is required) and matches every other rod.
| T | the type whose caster to classify. |
|
staticconstexpr |
caster_oracle: T is convertible without welder registering a class for it iff pybind11 does not fall back to runtime class registration.
| T | the type to classify. |
|
staticconstexpr |
Definition at line 72 of file rod.hpp.
Referenced by _def_function(), add_function(), and add_static_method().