Skip to content
This repository was archived by the owner on Nov 1, 2023. It is now read-only.

Sendable::InitSendable: force builder to be a reference #40

Merged
merged 1 commit into from
Dec 30, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions gen/Sendable.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,8 @@ classes:
shared_ptr: true
methods:
InitSendable:
virtual_xform: |
[&](py::function fn) {
auto builderHandle = py::cast(builder, py::return_value_policy::reference);
fn(builderHandle);
}
1 change: 1 addition & 0 deletions tests/cpp/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ extension = "module"
depends = ["wpiutil"]
sources = [
"wpiutil_test/module.cpp",
"wpiutil_test/sendable_test.cpp",
]

[tool.robotpy-build.metadata]
Expand Down
4 changes: 4 additions & 0 deletions tests/cpp/wpiutil_test/module.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -144,9 +144,13 @@ wpi::json cast_json_val(std::function<wpi::json()> fn) {
return fn();
}

void sendable_test(py::module &m);


RPYBUILD_PYBIND11_MODULE(m) {

sendable_test(m);

// array
m.def("load_array_int", &load_array_int);
m.def("load_array_int1", &load_array_int1);
Expand Down
127 changes: 127 additions & 0 deletions tests/cpp/wpiutil_test/sendable_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@

#include <robotpy_build.h>
#include <pybind11/stl.h>
#include <pybind11/functional.h>
#include <wpi/sendable/SendableBuilder.h>
#include <wpi/sendable/SendableRegistry.h>

class MySendableBuilder : public wpi::SendableBuilder {
public:
MySendableBuilder(py::dict keys) : keys(keys) {}

~MySendableBuilder() {
// leak this so the python interpreter doesn't crash on shutdown
keys.release();
}

void SetSmartDashboardType(std::string_view type) override {}

void SetActuator(bool value) override {}

void SetSafeState(std::function<void()> func) override {}

void AddBooleanProperty(std::string_view key, std::function<bool()> getter,
std::function<void(bool)> setter) override {}

void AddIntegerProperty(std::string_view key, std::function<int64_t()> getter,
std::function<void(int64_t)> setter) override {}

void AddFloatProperty(std::string_view key, std::function<float()> getter,
std::function<void(float)> setter) override {}

void AddDoubleProperty(std::string_view key, std::function<double()> getter,
std::function<void(double)> setter) override {
py::gil_scoped_acquire gil;
py::object pykey = py::cast(key);
keys[pykey] = std::make_tuple(getter, setter);
}

void
AddStringProperty(std::string_view key, std::function<std::string()> getter,
std::function<void(std::string_view)> setter) override {}

void AddBooleanArrayProperty(
std::string_view key, std::function<std::vector<int>()> getter,
std::function<void(std::span<const int>)> setter) override {}

void AddIntegerArrayProperty(
std::string_view key, std::function<std::vector<int64_t>()> getter,
std::function<void(std::span<const int64_t>)> setter) override {}

void AddFloatArrayProperty(
std::string_view key, std::function<std::vector<float>()> getter,
std::function<void(std::span<const float>)> setter) override {}

void AddDoubleArrayProperty(
std::string_view key, std::function<std::vector<double>()> getter,
std::function<void(std::span<const double>)> setter) override {}

void AddStringArrayProperty(
std::string_view key, std::function<std::vector<std::string>()> getter,
std::function<void(std::span<const std::string>)> setter) override {}

void AddRawProperty(
std::string_view key, std::string_view typeString,
std::function<std::vector<uint8_t>()> getter,
std::function<void(std::span<const uint8_t>)> setter) override {}

void AddSmallStringProperty(
std::string_view key,
std::function<std::string_view(wpi::SmallVectorImpl<char> &buf)> getter,
std::function<void(std::string_view)> setter) override {}

void AddSmallBooleanArrayProperty(
std::string_view key,
std::function<std::span<const int>(wpi::SmallVectorImpl<int> &buf)>
getter,
std::function<void(std::span<const int>)> setter) override {}

void AddSmallIntegerArrayProperty(
std::string_view key,
std::function<
std::span<const int64_t>(wpi::SmallVectorImpl<int64_t> &buf)>
getter,
std::function<void(std::span<const int64_t>)> setter) override {}

void AddSmallFloatArrayProperty(
std::string_view key,
std::function<std::span<const float>(wpi::SmallVectorImpl<float> &buf)>
getter,
std::function<void(std::span<const float>)> setter) override {}

void AddSmallDoubleArrayProperty(
std::string_view key,
std::function<std::span<const double>(wpi::SmallVectorImpl<double> &buf)>
getter,
std::function<void(std::span<const double>)> setter) override {}

void AddSmallStringArrayProperty(
std::string_view key,
std::function<
std::span<const std::string>(wpi::SmallVectorImpl<std::string> &buf)>
getter,
std::function<void(std::span<const std::string>)> setter) override {}

void AddSmallRawProperty(
std::string_view key, std::string_view typeString,
std::function<std::span<uint8_t>(wpi::SmallVectorImpl<uint8_t> &buf)>
getter,
std::function<void(std::span<const uint8_t>)> setter) override {}

wpi::SendableBuilder::BackendKind GetBackendKind() const override {
return wpi::SendableBuilder::BackendKind::kUnknown;
}

bool IsPublished() const override { return false; }
void Update() override {}
void ClearProperties() override {}

py::dict keys;
};

void Publish(wpi::SendableRegistry::UID sendableUid, py::dict keys) {
auto builder = std::make_unique<MySendableBuilder>(keys);
wpi::SendableRegistry::Publish(sendableUid, std::move(builder));
}

void sendable_test(py::module &m) { m.def("publish", Publish); }
35 changes: 35 additions & 0 deletions tests/test_sendable.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import typing
import wpiutil
from wpiutil_test import module


class MySendable(wpiutil.Sendable):
def __init__(self):
super().__init__()
wpiutil.SendableRegistry.add(self, "Test", 1)
self.value = 0

def initSendable(self, builder: wpiutil.SendableBuilder):
builder.addDoubleProperty("key", self._get, self._set)

def _set(self, value: float):
self.value = value

def _get(self) -> float:
return self.value


def test_custom_sendable():
ms = MySendable()

uid = wpiutil.SendableRegistry.getUniqueId(ms)
keys = {}

module.publish(uid, keys)
assert ms.value == 0

getter, setter = keys["key"]
assert getter() == 0
setter(1)
assert getter() == 1
assert ms.value == 1
13 changes: 12 additions & 1 deletion wpiutil/src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,22 @@
void setup_stack_trace_hook(py::object fn);
void cleanup_stack_trace_hook();

namespace wpi::impl {
void ResetSendableRegistry();
} // namespace wpi::impl

RPYBUILD_PYBIND11_MODULE(m) {
initWrapper(m);

static int unused;
py::capsule cleanup(&unused, [](void *) { cleanup_stack_trace_hook(); });
py::capsule cleanup(&unused, [](void *) {
{
py::gil_scoped_release unlock;
wpi::impl::ResetSendableRegistry();
}

cleanup_stack_trace_hook();
});

m.def("_setup_stack_trace_hook", &setup_stack_trace_hook);
m.add_object("_st_cleanup", cleanup);
Expand Down