[robotpy] Run wpiformat on non-python robotpy files (#8362)

This turns the styleguide on for the non-python robotpy files.

The overwhelming amount of changes were
related to whitespace, followed by some IWYU for standard library
headers.
This commit is contained in:
PJ Reiniger
2026-06-21 22:36:03 -04:00
committed by GitHub
parent 6bc7051e23
commit 4a2cd3e5d0
71 changed files with 877 additions and 739 deletions

View File

@@ -1,3 +1,2 @@
defaults:
ignore: true

View File

@@ -1,5 +1,5 @@
#include <semiwrap_init.wpiutil._wpiutil.hpp>
#include "semiwrap_init.wpiutil._wpiutil.hpp"
void setup_stack_trace_hook(py::object fn);
void cleanup_stack_trace_hook();
@@ -14,7 +14,7 @@ void cleanup_now_impl();
namespace wpi::util::impl {
void ResetSendableRegistry();
} // namespace wpi::util::impl
} // namespace wpi::util::impl
void cleanup_sendable_registry() {
py::gil_scoped_release unlock;
@@ -31,7 +31,7 @@ SEMIWRAP_PYBIND11_MODULE(m) {
initWrapper(m);
static int unused;
py::capsule cleanup(&unused, [](void *) {
py::capsule cleanup(&unused, [](void*) {
cleanup_sendable_registry();
cleanup_stack_trace_hook();
cleanup_safethread_gil();

View File

@@ -1,29 +1,30 @@
#include <atomic>
#include <gilsafe_object.h>
#include <semiwrap.h>
using OnThreadStartFn = void *(*)();
using OnThreadEndFn = void (*)(void *);
using OnThreadStartFn = void* (*)();
using OnThreadEndFn = void (*)(void*);
namespace wpi::util::impl {
void SetSafeThreadNotifiers(OnThreadStartFn OnStart, OnThreadEndFn OnEnd);
}
struct SafeThreadState {
py::gil_scoped_acquire *acquire = nullptr;
py::gil_scoped_release *release = nullptr;
py::gil_scoped_acquire* acquire = nullptr;
py::gil_scoped_release* release = nullptr;
};
std::atomic<bool> g_gilstate_managed = false;
void *on_safe_thread_start() {
if (Py_IsFinalizing() // python is shutting down
|| !g_gilstate_managed.load() // python has shutdown)
void* on_safe_thread_start() {
if (Py_IsFinalizing() // python is shutting down
|| !g_gilstate_managed.load() // python has shutdown)
) {
return nullptr;
}
auto *st = new SafeThreadState;
auto* st = new SafeThreadState;
// acquires the GIL and creates pybind11's thread state for this thread
st->acquire = new py::gil_scoped_acquire;
@@ -33,20 +34,20 @@ void *on_safe_thread_start() {
return st;
}
void on_safe_thread_end(void *opaque) {
void on_safe_thread_end(void* opaque) {
// on entry, GIL should not be acquired
// don't cleanup if it's unsafe to do so. Several possibilities here:
if (!opaque // internal error?
|| Py_IsFinalizing() // python is shutting down
|| !g_gilstate_managed.load() // python has shutdown
if (!opaque // internal error?
|| Py_IsFinalizing() // python is shutting down
|| !g_gilstate_managed.load() // python has shutdown
) {
return;
}
auto *st = (SafeThreadState *)opaque;
delete st->release; // causes GIL to be acquired
delete st->acquire; // causes GIL to be released and thread state deleted
auto* st = reinterpret_cast<SafeThreadState*>(opaque);
delete st->release; // causes GIL to be acquired
delete st->acquire; // causes GIL to be released and thread state deleted
delete st;
}
@@ -59,7 +60,10 @@ void setup_safethread_gil() {
atexit.attr("register")(
py::cpp_function([]() { g_gilstate_managed = false; }));
wpi::util::impl::SetSafeThreadNotifiers(on_safe_thread_start, on_safe_thread_end);
wpi::util::impl::SetSafeThreadNotifiers(on_safe_thread_start,
on_safe_thread_end);
}
void cleanup_safethread_gil() { g_gilstate_managed = false; }
void cleanup_safethread_gil() {
g_gilstate_managed = false;
}

View File

@@ -1,14 +1,18 @@
#include <string>
#include <semiwrap.h>
#include "wpi/util/StackTrace.hpp"
py::object &get_hook_ref() {
py::object& get_hook_ref() {
static py::object hook;
return hook;
}
std::string final_py_stack_trace_hook(int offset) {
std::string msg = "\tat <python stack trace not available due to interpreter shutdown>\n";
std::string msg =
"\tat <python stack trace not available due to interpreter shutdown>\n";
msg += wpi::util::GetStackTraceDefault(offset);
return msg;
}
@@ -17,11 +21,11 @@ std::string py_stack_trace_hook(int offset) {
py::gil_scoped_acquire gil;
try {
auto &hook = get_hook_ref();
auto& hook = get_hook_ref();
if (hook) {
return py::cast<std::string>(hook(offset));
}
} catch (py::error_already_set &e) {
} catch (py::error_already_set& e) {
e.discard_as_unraisable("wpiutil._stacktrace._stack_trace_hook");
}
@@ -37,9 +41,9 @@ void cleanup_stack_trace_hook() {
wpi::util::SetGetStackTraceImpl(final_py_stack_trace_hook);
// release the function during interpreter shutdown
auto &hook = get_hook_ref();
auto& hook = get_hook_ref();
if (hook) {
hook.dec_ref();
hook.release();
}
}
}

View File

@@ -1,11 +1,11 @@
#include <pybind11/pybind11.h>
#include <pybind11/functional.h>
#include "wpi/util/timestamp.hpp"
#include <pybind11/functional.h>
#include <pybind11/pybind11.h>
namespace py = pybind11;
py::object &get_now_impl_ref() {
py::object& get_now_impl_ref() {
static py::object get_now_impl_ref;
return get_now_impl_ref;
}
@@ -14,11 +14,11 @@ py::object &get_now_impl_ref() {
uint64_t now_impl_trampoline() {
py::gil_scoped_acquire acquire;
try {
auto &hook = get_now_impl_ref();
auto& hook = get_now_impl_ref();
if (hook) {
return hook().cast<uint64_t>();
}
} catch (py::error_already_set &e) {
} catch (py::error_already_set& e) {
e.discard_as_unraisable("wpiutil.now_impl_trampoline");
}
@@ -26,21 +26,21 @@ uint64_t now_impl_trampoline() {
}
void set_now_impl(py::object func) {
get_now_impl_ref() = func;
if (func.is_none()) {
wpi::util::SetNowImpl(nullptr);
} else {
wpi::util::SetNowImpl(&now_impl_trampoline);
}
get_now_impl_ref() = func;
if (func.is_none()) {
wpi::util::SetNowImpl(nullptr);
} else {
wpi::util::SetNowImpl(&now_impl_trampoline);
}
}
void cleanup_now_impl() {
wpi::util::SetNowImpl(nullptr);
// release the function during interpreter shutdown
auto &hook = get_now_impl_ref();
auto& hook = get_now_impl_ref();
if (hook) {
hook.dec_ref();
hook.release();
}
}
}

View File

@@ -3,17 +3,18 @@
#include <functional>
#include <memory>
#include <string>
#include <string_view>
#include <fmt/format.h>
#include "wpi/util/struct/Struct.hpp"
#include <pybind11/functional.h>
#include <pybind11/typing.h>
#include <semiwrap.h>
static inline std::string pytypename(const py::type &t) {
return ((PyTypeObject *)t.ptr())->tp_name;
#include "wpi/util/struct/Struct.hpp"
static inline std::string pytypename(const py::type& t) {
return (reinterpret_cast<PyTypeObject*>(t.ptr()))->tp_name;
}
//
@@ -23,15 +24,14 @@ static inline std::string pytypename(const py::type &t) {
// This merely holds the python object being operated on, the actual
// serialization work is done in WPyStructConverter
struct WPyStruct {
WPyStruct() = default;
WPyStruct(const WPyStruct &other) {
WPyStruct(const WPyStruct& other) {
py::gil_scoped_acquire gil;
py = other.py;
}
WPyStruct &operator=(const WPyStruct &other) {
WPyStruct& operator=(const WPyStruct& other) {
{
py::gil_scoped_acquire gil;
py = other.py;
@@ -39,9 +39,9 @@ struct WPyStruct {
return *this;
}
WPyStruct(WPyStruct &&) = default;
WPyStruct(WPyStruct&&) = default;
WPyStruct(const py::object &py) : py(py) {}
explicit WPyStruct(const py::object& py) : py(py) {}
~WPyStruct() {
py::gil_scoped_acquire gil;
@@ -51,10 +51,10 @@ struct WPyStruct {
py::object py;
};
namespace pybind11 {
namespace detail {
namespace pybind11::detail {
template <> struct type_caster<WPyStruct> {
template <>
struct type_caster<WPyStruct> {
// TODO: wpiutil.struct.T/TV?
PYBIND11_TYPE_CASTER(WPyStruct, const_name("object"));
@@ -64,7 +64,7 @@ template <> struct type_caster<WPyStruct> {
return true;
}
static handle cast(const WPyStruct &src, py::return_value_policy policy,
static handle cast(const WPyStruct& src, py::return_value_policy policy,
py::handle parent) {
py::handle v = src.py;
v.inc_ref();
@@ -72,8 +72,7 @@ template <> struct type_caster<WPyStruct> {
}
};
} // namespace detail
} // namespace pybind11
} // namespace pybind11::detail
//
// Struct info class implementation
@@ -88,7 +87,7 @@ struct WPyStructConverter {
virtual std::string_view GetSchema() const = 0;
virtual void Pack(std::span<uint8_t> data, const WPyStruct &value) const = 0;
virtual void Pack(std::span<uint8_t> data, const WPyStruct& value) const = 0;
virtual WPyStruct Unpack(std::span<const uint8_t> data) const = 0;
@@ -96,12 +95,13 @@ struct WPyStructConverter {
// std::span<const uint8_t> data) const = 0;
virtual void ForEachNested(
const std::function<void(std::string_view, std::string_view)> &fn)
const std::function<void(std::string_view, std::string_view)>& fn)
const = 0;
};
// static C++ converter
template <typename T> struct WPyStructCppConverter : WPyStructConverter {
template <typename T>
struct WPyStructCppConverter : WPyStructConverter {
std::string_view GetTypeName() const override {
return wpi::util::Struct<T>::GetTypeName();
}
@@ -112,9 +112,9 @@ template <typename T> struct WPyStructCppConverter : WPyStructConverter {
return wpi::util::Struct<T>::GetSchema();
}
void Pack(std::span<uint8_t> data, const WPyStruct &value) const override {
void Pack(std::span<uint8_t> data, const WPyStruct& value) const override {
py::gil_scoped_acquire gil;
const T &v = value.py.cast<const T &>();
const T& v = value.py.cast<const T&>();
wpi::util::Struct<T>::Pack(data, v);
}
@@ -131,7 +131,7 @@ template <typename T> struct WPyStructCppConverter : WPyStructConverter {
// }
void ForEachNested(
const std::function<void(std::string_view, std::string_view)> &fn)
const std::function<void(std::string_view, std::string_view)>& fn)
const override {
if constexpr (wpi::util::HasNestedStruct<T>) {
wpi::util::Struct<T>::ForEachNested(fn);
@@ -139,13 +139,13 @@ template <typename T> struct WPyStructCppConverter : WPyStructConverter {
}
};
template <typename T> void SetupWPyStruct(auto pycls) {
auto *sptr =
template <typename T>
void SetupWPyStruct(auto pycls) {
auto* sptr =
new std::shared_ptr<WPyStructConverter>(new WPyStructCppConverter<T>());
py::capsule c(sptr, "WPyStruct", [](void *ptr) {
delete (std::shared_ptr<WPyStructConverter> *)ptr;
py::capsule c(sptr, "WPyStruct", [](void* ptr) {
delete (std::shared_ptr<WPyStructConverter>*)ptr;
});
pycls.def_property_readonly_static("WPIStruct",
@@ -154,8 +154,7 @@ template <typename T> void SetupWPyStruct(auto pycls) {
// dynamic python converter
struct WPyStructPyConverter : WPyStructConverter {
WPyStructPyConverter(py::object o) {
explicit WPyStructPyConverter(py::object o) {
m_typename = o.attr("typename").cast<std::string>();
m_schema = o.attr("schema").cast<std::string>();
m_size = o.attr("size").cast<size_t>();
@@ -163,7 +162,8 @@ struct WPyStructPyConverter : WPyStructConverter {
m_pack = py::reinterpret_borrow<py::function>(o.attr("pack"));
m_packInto = py::reinterpret_borrow<py::function>(o.attr("packInto"));
m_unpack = py::reinterpret_borrow<py::function>(o.attr("unpack"));
// m_unpackInto = py::reinterpret_borrow<py::function>(o.attr("unpackInto"));
// m_unpackInto =
// py::reinterpret_borrow<py::function>(o.attr("unpackInto"));
m_forEachNested =
py::reinterpret_borrow<py::function>(o.attr("forEachNested"));
}
@@ -177,7 +177,7 @@ struct WPyStructPyConverter : WPyStructConverter {
py::function m_packInto;
py::function m_unpack;
// py::function m_unpackInto;
py::function m_forEachNested; // might be none
py::function m_forEachNested; // might be none
std::string_view GetTypeName() const override { return m_typename; }
@@ -185,7 +185,7 @@ struct WPyStructPyConverter : WPyStructConverter {
std::string_view GetSchema() const override { return m_schema; }
void Pack(std::span<uint8_t> data, const WPyStruct &value) const override {
void Pack(std::span<uint8_t> data, const WPyStruct& value) const override {
py::gil_scoped_acquire gil;
py::bytes result = m_pack(value.py);
std::string_view rview = result;
@@ -196,13 +196,13 @@ struct WPyStructPyConverter : WPyStructConverter {
throw py::value_error(msg);
}
rview.copy((char *)data.data(), rview.size());
rview.copy(reinterpret_cast<char*>(data.data()), rview.size());
}
WPyStruct Unpack(std::span<const uint8_t> data) const override {
py::gil_scoped_acquire gil;
auto view =
py::memoryview::from_memory((const void *)data.data(), data.size());
py::memoryview::from_memory((const void*)data.data(), data.size());
return WPyStruct(m_unpack(view));
}
@@ -215,7 +215,7 @@ struct WPyStructPyConverter : WPyStructConverter {
// }
void ForEachNested(
const std::function<void(std::string_view, std::string_view)> &fn)
const std::function<void(std::string_view, std::string_view)>& fn)
const override {
py::gil_scoped_acquire gil;
if (!m_forEachNested.is_none()) {
@@ -227,9 +227,8 @@ struct WPyStructPyConverter : WPyStructConverter {
// passed as I... to the wpi::util::Struct methods
struct WPyStructInfo {
WPyStructInfo() = default;
WPyStructInfo(const py::type &t) {
explicit WPyStructInfo(const py::type& t) {
if (!py::hasattr(t, "WPIStruct")) {
throw py::type_error(
fmt::format("{} is not struct serializable (does not have WPIStruct)",
pytypename(t)));
@@ -238,9 +237,9 @@ struct WPyStructInfo {
py::object s = t.attr("WPIStruct");
// C++ version
void *c = PyCapsule_GetPointer(s.ptr(), "WPyStruct");
void* c = PyCapsule_GetPointer(s.ptr(), "WPyStruct");
if (c != NULL) {
cvt = *(std::shared_ptr<WPyStructConverter> *)c;
cvt = *(std::shared_ptr<WPyStructConverter>*)c;
return;
}
@@ -249,7 +248,7 @@ struct WPyStructInfo {
// Python version
try {
cvt = std::make_shared<WPyStructPyConverter>(s);
} catch (py::error_already_set &e) {
} catch (py::error_already_set& e) {
std::string msg = fmt::format(
"{} is not struct serializable (invalid WPIStruct)", pytypename(t));
py::raise_from(e, PyExc_TypeError, msg.c_str());
@@ -257,10 +256,11 @@ struct WPyStructInfo {
}
}
WPyStructInfo(const WPyStruct &v) : WPyStructInfo(py::type::of(v.py)) {}
explicit WPyStructInfo(const WPyStruct& v)
: WPyStructInfo(py::type::of(v.py)) {}
const WPyStructConverter* operator->() const {
const auto *c = cvt.get();
const auto* c = cvt.get();
if (c == nullptr) {
// TODO: would be nice to have a better error here, but we don't have
// a good way to know our current context
@@ -269,27 +269,26 @@ struct WPyStructInfo {
return c;
}
private:
private:
// holds something used to do serialization
std::shared_ptr<WPyStructConverter> cvt;
};
// Leverages the converter stored in WPyStructInfo to do the actual work
template <> struct wpi::util::Struct<WPyStruct, WPyStructInfo> {
static std::string_view GetTypeName(const WPyStructInfo &info) {
template <>
struct wpi::util::Struct<WPyStruct, WPyStructInfo> {
static std::string_view GetTypeName(const WPyStructInfo& info) {
return info->GetTypeName();
}
static size_t GetSize(const WPyStructInfo &info) {
return info->GetSize();
}
static size_t GetSize(const WPyStructInfo& info) { return info->GetSize(); }
static std::string_view GetSchema(const WPyStructInfo &info) {
static std::string_view GetSchema(const WPyStructInfo& info) {
return info->GetSchema();
}
static WPyStruct Unpack(std::span<const uint8_t> data,
const WPyStructInfo &info) {
const WPyStructInfo& info) {
return info->Unpack(data);
}
@@ -298,14 +297,14 @@ template <> struct wpi::util::Struct<WPyStruct, WPyStructInfo> {
// info->UnpackInto(v, data);
// }
static void Pack(std::span<uint8_t> data, const WPyStruct &value,
const WPyStructInfo &info) {
static void Pack(std::span<uint8_t> data, const WPyStruct& value,
const WPyStructInfo& info) {
info->Pack(data, value);
}
static void
ForEachNested(std::invocable<std::string_view, std::string_view> auto fn,
const WPyStructInfo &info) {
static void ForEachNested(
std::invocable<std::string_view, std::string_view> auto fn,
const WPyStructInfo& info) {
info->ForEachNested(fn);
}
};
@@ -314,4 +313,5 @@ static_assert(wpi::util::StructSerializable<WPyStruct, WPyStructInfo>);
static_assert(wpi::util::HasNestedStruct<WPyStruct, WPyStructInfo>);
// This breaks on readonly structs, so we disable for now
// static_assert(wpi::util::MutableStructSerializable<WPyStruct, WPyStructInfo>);
// static_assert(wpi::util::MutableStructSerializable<WPyStruct,
// WPyStructInfo>);

View File

@@ -1,51 +1,53 @@
#include "wpystruct_fns.h"
#include "wpystruct.h"
void forEachNested(
const py::type &t,
const std::function<void(std::string_view, std::string_view)> &fn) {
const py::type& t,
const std::function<void(std::string_view, std::string_view)>& fn) {
WPyStructInfo info(t);
wpi::util::ForEachStructSchema<WPyStruct, WPyStructInfo>(fn, info);
}
py::str getTypeName(const py::type &t) {
py::str getTypeName(const py::type& t) {
WPyStructInfo info(t);
return wpi::util::GetStructTypeName<WPyStruct, WPyStructInfo>(info);
}
py::str getSchema(const py::type &t) {
py::str getSchema(const py::type& t) {
WPyStructInfo info(t);
return wpi::util::GetStructSchema<WPyStruct, WPyStructInfo>(info);
}
size_t getSize(const py::type &t) {
size_t getSize(const py::type& t) {
WPyStructInfo info(t);
return wpi::util::GetStructSize<WPyStruct>(info);
}
py::bytes pack(const WPyStruct &v) {
py::bytes pack(const WPyStruct& v) {
WPyStructInfo info(v);
auto sz = wpi::util::GetStructSize<WPyStruct>(info);
PyObject *b = PyBytes_FromStringAndSize(NULL, sz);
PyObject* b = PyBytes_FromStringAndSize(NULL, sz);
if (b == NULL) {
throw py::error_already_set();
}
char *pybuf;
char* pybuf;
py::ssize_t pysz;
if (PyBytes_AsStringAndSize(b, &pybuf, &pysz) != 0) {
Py_DECREF(b);
throw py::error_already_set();
}
auto s = std::span((uint8_t *)pybuf, pysz);
auto s = std::span(reinterpret_cast<uint8_t*>(pybuf), pysz);
wpi::util::PackStruct(s, v, info);
return py::reinterpret_steal<py::bytes>(b);
}
py::bytes packArray(const py::sequence &seq) {
py::bytes packArray(const py::sequence& seq) {
auto len = seq.size();
if (len == 0) {
return {};
@@ -53,14 +55,14 @@ py::bytes packArray(const py::sequence &seq) {
WPyStructInfo info(py::type::of(seq[0]));
auto sz = wpi::util::GetStructSize<WPyStruct>(info);
auto total = sz*len;
auto total = sz * len;
PyObject *b = PyBytes_FromStringAndSize(NULL, total);
PyObject* b = PyBytes_FromStringAndSize(NULL, total);
if (b == NULL) {
throw py::error_already_set();
}
char *pybuf;
char* pybuf;
py::ssize_t pysz;
if (PyBytes_AsStringAndSize(b, &pybuf, &pysz) != 0) {
Py_DECREF(b);
@@ -69,9 +71,9 @@ py::bytes packArray(const py::sequence &seq) {
auto bytes_obj = py::reinterpret_steal<py::bytes>(b);
for (const auto &v: seq) {
for (const auto& v : seq) {
WPyStruct wv(v);
auto s = std::span((uint8_t *)pybuf, sz);
auto s = std::span(reinterpret_cast<uint8_t*>(pybuf), sz);
wpi::util::PackStruct(s, wv, info);
pybuf += sz;
}
@@ -79,7 +81,7 @@ py::bytes packArray(const py::sequence &seq) {
return bytes_obj;
}
void packInto(const WPyStruct &v, py::buffer &b) {
void packInto(const WPyStruct& v, py::buffer& b) {
WPyStructInfo info(v);
py::ssize_t sz = wpi::util::GetStructSize<WPyStruct>(info);
@@ -94,11 +96,11 @@ void packInto(const WPyStruct &v, py::buffer &b) {
throw py::value_error("buffer must be " + std::to_string(sz) + " bytes");
}
auto s = std::span((uint8_t *)req.ptr, req.size);
auto s = std::span(reinterpret_cast<uint8_t*>(req.ptr), req.size);
wpi::util::PackStruct(s, v, info);
}
WPyStruct unpack(const py::type &t, const py::buffer &b) {
WPyStruct unpack(const py::type& t, const py::buffer& b) {
WPyStructInfo info(t);
py::ssize_t sz = wpi::util::GetStructSize<WPyStruct>(info);
@@ -113,11 +115,12 @@ WPyStruct unpack(const py::type &t, const py::buffer &b) {
throw py::value_error("buffer must be " + std::to_string(sz) + " bytes");
}
auto s = std::span((const uint8_t *)req.ptr, req.size);
auto s = std::span(reinterpret_cast<const uint8_t*>(req.ptr), req.size);
return wpi::util::UnpackStruct<WPyStruct, WPyStructInfo>(s, info);
}
py::typing::List<WPyStruct> unpackArray(const py::type &t, const py::buffer &b) {
py::typing::List<WPyStruct> unpackArray(const py::type& t,
const py::buffer& b) {
WPyStructInfo info(t);
py::ssize_t sz = wpi::util::GetStructSize<WPyStruct>(info);
@@ -129,12 +132,13 @@ py::typing::List<WPyStruct> unpackArray(const py::type &t, const py::buffer &b)
}
if (req.size % sz != 0) {
throw py::value_error("buffer must be multiple of " + std::to_string(sz) + " bytes");
throw py::value_error("buffer must be multiple of " + std::to_string(sz) +
" bytes");
}
auto items = req.size / sz;
py::list a(items);
const uint8_t *ptr = (const uint8_t *)req.ptr;
const uint8_t* ptr = reinterpret_cast<const uint8_t*>(req.ptr);
for (py::ssize_t i = 0; i < items; i++) {
auto s = std::span(ptr, sz);
auto v = wpi::util::UnpackStruct<WPyStruct, WPyStructInfo>(s, info);

View File

@@ -7,50 +7,50 @@
Call a function to retrieve the (type string, schema) for each nested struct
*/
void forEachNested(
const py::type &t,
const std::function<void(std::string_view, std::string_view)> &fn);
const py::type& t,
const std::function<void(std::string_view, std::string_view)>& fn);
/**
Retrieve the type name for the specified type
*/
py::str getTypeName(const py::type &t);
py::str getTypeName(const py::type& t);
/**
Retrieve schema for the specified type
*/
py::str getSchema(const py::type &t);
py::str getSchema(const py::type& t);
/**
Returns the serialized size in bytes
*/
size_t getSize(const py::type &t);
size_t getSize(const py::type& t);
/**
Serialize object into byte buffer
*/
py::bytes pack(const WPyStruct &v);
py::bytes pack(const WPyStruct& v);
/**
Serialize objects into byte buffer
*/
py::bytes packArray(const py::sequence &seq);
py::bytes packArray(const py::sequence& seq);
/**
Serialize object into byte buffer. Buffer must be exact size.
*/
void packInto(const WPyStruct &v, py::buffer &b);
void packInto(const WPyStruct& v, py::buffer& b);
/**
Convert byte buffer into object of specified type. Buffer must be exact
size.
*/
WPyStruct unpack(const py::type &t, const py::buffer &b);
WPyStruct unpack(const py::type& t, const py::buffer& b);
/**
Convert byte buffer into list of objects of specified type. Buffer must be
exact size.
*/
py::typing::List<WPyStruct> unpackArray(const py::type &t, const py::buffer &b);
py::typing::List<WPyStruct> unpackArray(const py::type& t, const py::buffer& b);
// /**
// Convert byte buffer into passed in object. Buffer must be exact

View File

@@ -13,6 +13,8 @@
#include <limits>
#include <functional>
#include <string>
#include <vector>
#include <pybind11/functional.h>
@@ -178,7 +180,6 @@ StructWithWPI_String cast_struct_with_wpi_string() {
}
PYBIND11_MODULE(module, m) {
sendable_test(m);
struct_test(m);
@@ -209,7 +210,7 @@ PYBIND11_MODULE(module, m) {
m.def("load_stringmap_int", &load_stringmap_int);
m.def("cast_stringmap", &cast_stringmap);
// JSON
m.def("cast_json_arg", &cast_json_arg);
m.def("cast_json_arg", &cast_json_arg);
m.def("cast_json_val", &cast_json_val);
m.attr("max_uint64") = std::numeric_limits<uint64_t>::max();
m.attr("max_int64") = std::numeric_limits<int64_t>::max();
@@ -220,7 +221,7 @@ PYBIND11_MODULE(module, m) {
// WPI_String
m.def("load_wpi_string", &load_wpi_string);
m.def("cast_wpi_string", &cast_wpi_string);
py::class_<StructWithWPI_String> structWithWpiStringCls(m, "StructWithWPI_String");
structWithWpiStringCls.def_readwrite("x", &StructWithWPI_String::x);
structWithWpiStringCls.def_readonly("str", &StructWithWPI_String::str);

View File

@@ -1,15 +1,20 @@
#include <memory>
#include <string>
#include <utility>
#include <pybind11/functional.h>
#include <pybind11/stl.h>
#include <semiwrap.h>
#include "wpi/util/sendable/SendableBuilder.hpp"
#include "wpi/util/sendable/SendableRegistry.hpp"
class MySendableBuilder : public wpi::util::SendableBuilder {
public:
MySendableBuilder(py::dict keys) : keys(keys) {}
public:
explicit MySendableBuilder(py::dict keys) : keys(keys) {}
~MySendableBuilder() {
~MySendableBuilder() override {
// leak this so the python interpreter doesn't crash on shutdown
keys.release();
}
@@ -42,9 +47,9 @@ public:
void PublishConstDouble(std::string_view key, double value) override {}
void
AddStringProperty(std::string_view key, std::function<std::string()> getter,
std::function<void(std::string_view)> setter) override {}
void AddStringProperty(
std::string_view key, std::function<std::string()> getter,
std::function<void(std::string_view)> setter) override {}
void PublishConstString(std::string_view key,
std::string_view value) override {}
@@ -94,44 +99,48 @@ public:
void AddSmallStringProperty(
std::string_view key,
std::function<std::string_view(wpi::util::SmallVectorImpl<char> &buf)> getter,
std::function<std::string_view(wpi::util::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::util::SmallVectorImpl<int> &buf)>
std::function<std::span<const int>(wpi::util::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::util::SmallVectorImpl<int64_t> &buf)>
std::span<const int64_t>(wpi::util::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::util::SmallVectorImpl<float> &buf)>
std::function<
std::span<const float>(wpi::util::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::util::SmallVectorImpl<double> &buf)>
std::function<
std::span<const double>(wpi::util::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::util::SmallVectorImpl<std::string> &buf)>
std::function<std::span<const std::string>(
wpi::util::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::util::SmallVectorImpl<uint8_t> &buf)>
std::function<
std::span<uint8_t>(wpi::util::SmallVectorImpl<uint8_t>& buf)>
getter,
std::function<void(std::span<const uint8_t>)> setter) override {}
@@ -151,4 +160,6 @@ void Publish(wpi::util::SendableRegistry::UID sendableUid, py::dict keys) {
wpi::util::SendableRegistry::Publish(sendableUid, std::move(builder));
}
void sendable_test(py::module &m) { m.def("publish", Publish); }
void sendable_test(py::module& m) {
m.def("publish", Publish);
}

View File

@@ -8,33 +8,34 @@
struct ThingA {
ThingA() = default;
ThingA(int x) : x(x) {}
explicit ThingA(int x) : x(x) {}
const int x = 0;
bool operator==(const ThingA &other) const { return x == other.x; }
bool operator==(const ThingA& other) const { return x == other.x; }
};
template <> struct wpi::util::Struct<ThingA> {
template <>
struct wpi::util::Struct<ThingA> {
static constexpr std::string_view GetTypeName() { return "ThingA"; }
static constexpr size_t GetSize() { return 1; }
static constexpr std::string_view GetSchema() { return "uint8 value"; }
static ThingA Unpack(std::span<const uint8_t> data) {
return ThingA{data[0]};
}
static void Pack(std::span<uint8_t> data, const ThingA &value) {
static void Pack(std::span<uint8_t> data, const ThingA& value) {
data[0] = value.x;
}
};
struct Outer {
Outer() = default;
Outer(const ThingA &t, int c) : inner(t), c(c) {}
Outer(const ThingA& t, int c) : inner(t), c(c) {}
ThingA inner;
int c = 0;
bool operator==(const Outer &other) const {
bool operator==(const Outer& other) const {
return inner == other.inner && c == other.c;
}
};
@@ -42,7 +43,9 @@ struct Outer {
template <>
struct wpi::util::Struct<Outer> {
static constexpr std::string_view GetTypeName() { return "Outer"; }
static constexpr size_t GetSize() { return wpi::util::GetStructSize<ThingA>() + 4; }
static constexpr size_t GetSize() {
return wpi::util::GetStructSize<ThingA>() + 4;
}
static constexpr std::string_view GetSchema() {
return "ThingA inner; int32 c";
}
@@ -63,8 +66,7 @@ struct wpi::util::Struct<Outer> {
}
};
void struct_test(py::module &m) {
void struct_test(py::module& m) {
py::class_<ThingA> thingCls(m, "ThingA");
thingCls.def(py::init<>());
thingCls.def(py::init<int>());
@@ -81,4 +83,4 @@ void struct_test(py::module &m) {
outerCls.def(py::self == py::self);
SetupWPyStruct<Outer>(outerCls);
}
}