support for scoped enums and operators in Python

This commit is contained in:
Erik Frojdh 2021-07-16 14:48:22 +02:00
parent 1b348f9b3a
commit 09391b767a
9 changed files with 138 additions and 21 deletions

View File

@ -11,14 +11,29 @@ import subprocess
from parse import remove_comments from parse import remove_comments
allow_bitwise_op = ["EthernetInterface"]
op_key = {"operator|": "__or__",
"operator&" : "__and__"}
def single_line_enum(line): def single_line_enum(line):
sub = line[line.find('{')+1:line.find('}')] sub = line[line.find('{')+1:line.find('}')]
return sub.strip().split(',') return sub.strip().split(',')
def extract_enums(lines): def extract_enums(lines):
# deal with enum class EthernetInterface : int32_t
# and normal enum burstMode {
line_iter = iter(lines) line_iter = iter(lines)
enums = {} enums = {}
for line in line_iter: for line in line_iter:
#Hack away class enum defs
if "class" in line:
line = line.replace("class", "")
line = line.replace(line[line.find(':'):line.find('{')], "")
line = line.replace(" ", " ")
m = re.search("(?<=enum )\w+(?= {)", line) m = re.search("(?<=enum )\w+(?= {)", line)
if m: if m:
enum_name = m.group() enum_name = m.group()
@ -44,25 +59,80 @@ def extract_enums(lines):
pass pass
fields = [f.strip() for f in fields] fields = [f.strip() for f in fields]
enums[enum_name] = fields enums[enum_name] = fields
#Loop again to find operators
for key in enums:
for line in lines:
if key in line and "operator" in line:
pos = line.find("operator")
op_type = line[pos:pos+9]
enums[key].append(op_type)
return enums return enums
def generate_enum_string(enums): def generate_enum_string(enums):
data = [] data = []
for key, value in enums.items(): for key, value in enums.items():
data.append(f'py::enum_<slsDetectorDefs::{key}>(Defs, "{key}")\n') if key in allow_bitwise_op:
tag=", py::arithmetic()"
else:
tag=""
data.append(f'py::enum_<slsDetectorDefs::{key}>(Defs, "{key}"{tag})\n')
operators = []
for v in value: for v in value:
if "operator" not in v:
data.append(f'\t.value("{v}", slsDetectorDefs::{key}::{v})\n') data.append(f'\t.value("{v}", slsDetectorDefs::{key}::{v})\n')
data.append('.export_values();\n\n') else:
operators.append(v)
data.append('\t.export_values()')
#Here add the operators
for op in operators:
data.append(f"\n\t.def(\"{op_key[op]}\", py::overload_cast< const slsDetectorDefs::EthernetInterface&, const slsDetectorDefs::EthernetInterface&>(&{op}))")
data.append(';\n\n')
return ''.join(data) return ''.join(data)
def remove_ifdefs(lines):
"""Keeps C++ version of the code"""
out = []
it = iter(lines)
skip = False
for line in it:
if "#ifdef __cplusplus" in line:
line = next(it)
if "#else" in line:
skip = True
if "#endif" in line:
skip = False
if not skip and "#endif" not in line:
out.append(line)
return out
with open('../../slsSupportLib/include/sls/sls_detector_defs.h') as f: with open('../../slsSupportLib/include/sls/sls_detector_defs.h') as f:
data = f.read() data = f.read()
data = remove_comments(data) data = remove_comments(data)
data = data.splitlines() data = data.splitlines()
data = remove_ifdefs(data)
enums = extract_enums(data) enums = extract_enums(data)
s = generate_enum_string(enums) s = generate_enum_string(enums)
# print(s)
# for i, line in enumerate(data):
# print(i, line)
with open('../src/enums_in.cpp') as f: with open('../src/enums_in.cpp') as f:
data = f.read() data = f.read()

View File

@ -2332,6 +2332,18 @@ class Detector(CppDetectorApi):
ut.set_using_dict(self.setVetoReference, *args) ut.set_using_dict(self.setVetoReference, *args)
@property
@element
def vetostream(self):
return self.getVetoStream()
@vetostream.setter
def vetostream(self, args):
if not isinstance(args, tuple):
args = (args,)
ut.set_using_dict(self.setVetoStream, *args)
""" """
Mythen3 specific Mythen3 specific
""" """

View File

@ -1074,6 +1074,16 @@ void init_det(py::module &m) {
(void (Detector::*)(const bool, sls::Positions)) & (void (Detector::*)(const bool, sls::Positions)) &
Detector::setVeto, Detector::setVeto,
py::arg(), py::arg() = Positions{}) py::arg(), py::arg() = Positions{})
.def("getVetoStream",
(Result<defs::EthernetInterface>(Detector::*)(sls::Positions)
const) &
Detector::getVetoStream,
py::arg() = Positions{})
.def("setVetoStream",
(void (Detector::*)(const defs::EthernetInterface,
sls::Positions)) &
Detector::setVetoStream,
py::arg(), py::arg() = Positions{})
.def("getADCConfiguration", .def("getADCConfiguration",
(Result<int>(Detector::*)(const int, const int, sls::Positions) (Result<int>(Detector::*)(const int, const int, sls::Positions)
const) & const) &

View File

@ -277,4 +277,20 @@ void init_enums(py::module &m) {
.value("TIMING_EXTERNAL", .value("TIMING_EXTERNAL",
slsDetectorDefs::timingSourceType::TIMING_EXTERNAL) slsDetectorDefs::timingSourceType::TIMING_EXTERNAL)
.export_values(); .export_values();
py::enum_<slsDetectorDefs::EthernetInterface>(Defs, "EthernetInterface",
py::arithmetic())
.value("NONE", slsDetectorDefs::EthernetInterface::NONE)
.value("I3GBE", slsDetectorDefs::EthernetInterface::I3GBE)
.value("I10GBE", slsDetectorDefs::EthernetInterface::I10GBE)
.value("ALL", slsDetectorDefs::EthernetInterface::ALL)
.export_values()
.def("__or__",
py::overload_cast<const slsDetectorDefs::EthernetInterface &,
const slsDetectorDefs::EthernetInterface &>(
&operator|))
.def("__and__",
py::overload_cast<const slsDetectorDefs::EthernetInterface &,
const slsDetectorDefs::EthernetInterface &>(
&operator&));
} }

View File

@ -1584,13 +1584,13 @@ Result<defs::EthernetInterface> Detector::getVetoStream(Positions pos) const {
void Detector::setVetoStream(defs::EthernetInterface interface, Positions pos) { void Detector::setVetoStream(defs::EthernetInterface interface, Positions pos) {
// 3gbe // 3gbe
bool i3gbe = (interface & defs::EthernetInterface::I3GBE); bool i3gbe = (interface & defs::EthernetInterface::I3GBE) == defs::EthernetInterface::I3GBE;
pimpl->Parallel(&Module::setVetoStream, pos, i3gbe); pimpl->Parallel(&Module::setVetoStream, pos, i3gbe);
// 10gbe (debugging interface) opens 2nd udp interface in receiver // 10gbe (debugging interface) opens 2nd udp interface in receiver
int old_numinterfaces = getNumberofUDPInterfaces_(pos).tsquash( int old_numinterfaces = getNumberofUDPInterfaces_(pos).tsquash(
"retrieved inconsistent number of udp interfaces"); "retrieved inconsistent number of udp interfaces");
int numinterfaces = (interface & defs::EthernetInterface::I10GBE) ? 2 : 1; int numinterfaces = ((interface & defs::EthernetInterface::I10GBE) == defs::EthernetInterface::I3GBE) ? 2 : 1;
if (numinterfaces != old_numinterfaces) { if (numinterfaces != old_numinterfaces) {
setNumberofUDPInterfaces_(numinterfaces, pos); setNumberofUDPInterfaces_(numinterfaces, pos);
} }

View File

@ -395,7 +395,7 @@ typedef struct {
enum timingSourceType { TIMING_INTERNAL, TIMING_EXTERNAL }; enum timingSourceType { TIMING_INTERNAL, TIMING_EXTERNAL };
#ifdef __cplusplus #ifdef __cplusplus
enum class EthernetInterface : int32_t { enum class EthernetInterface {
#else #else
enum EthernetInterface { enum EthernetInterface {
#endif #endif
@ -497,15 +497,15 @@ typedef struct {
#ifdef __cplusplus #ifdef __cplusplus
}; };
inline slsDetectorDefs::EthernetInterface inline slsDetectorDefs::EthernetInterface
operator|(const slsDetectorDefs::EthernetInterface &a, operator|( const slsDetectorDefs::EthernetInterface &a,
const slsDetectorDefs::EthernetInterface &b) { const slsDetectorDefs::EthernetInterface &b) {
return slsDetectorDefs::EthernetInterface(static_cast<int32_t>(a) | return slsDetectorDefs::EthernetInterface(static_cast<int32_t>(a) |
static_cast<int32_t>(b)); static_cast<int32_t>(b));
}; };
inline bool operator&(const slsDetectorDefs::EthernetInterface &a, inline slsDetectorDefs::EthernetInterface operator&( const slsDetectorDefs::EthernetInterface &a,
const slsDetectorDefs::EthernetInterface &b) { const slsDetectorDefs::EthernetInterface &b) {
return (static_cast<int32_t>(a) & static_cast<int32_t>(b)); return slsDetectorDefs::EthernetInterface(static_cast<int32_t>(a) & static_cast<int32_t>(b));
}; };
#endif #endif
@ -653,3 +653,4 @@ using Positions = const std::vector<int> &;
using defs = slsDetectorDefs; using defs = slsDetectorDefs;
} // namespace sls } // namespace sls
#endif #endif

View File

@ -526,9 +526,9 @@ std::string ToString(const defs::EthernetInterface s) {
case defs::EthernetInterface::NONE: case defs::EthernetInterface::NONE:
return std::string("none"); return std::string("none");
default: default:
if (s & defs::EthernetInterface::I3GBE) if ((s & defs::EthernetInterface::I3GBE)!=defs::EthernetInterface::NONE)
os << "3gbe, "; os << "3gbe, ";
if (s & defs::EthernetInterface::I10GBE) if ((s & defs::EthernetInterface::I10GBE)!=defs::EthernetInterface::NONE)
os << "10gbe, "; os << "10gbe, ";
auto rs = os.str(); auto rs = os.str();
rs.erase(rs.end() - 2, rs.end()); rs.erase(rs.end() - 2, rs.end());

View File

@ -4,6 +4,7 @@
#include <chrono> #include <chrono>
#include <future> #include <future>
#include <iostream> #include <iostream>
#include <thread>
std::vector<char> server() { std::vector<char> server() {
std::cout << "starting server\n"; std::cout << "starting server\n";

View File

@ -1,10 +1,10 @@
#include "catch.hpp" #include "catch.hpp"
#include "sls/Pattern.h"
#include "sls/TimeHelper.h" #include "sls/TimeHelper.h"
#include "sls/ToString.h" #include "sls/ToString.h"
#include "sls/network_utils.h"
#include "sls/Pattern.h"
#include "sls/sls_detector_defs.h"
#include "sls/container_utils.h" #include "sls/container_utils.h"
#include "sls/network_utils.h"
#include "sls/sls_detector_defs.h"
#include <array> #include <array>
#include <map> #include <map>
#include <sstream> #include <sstream>
@ -302,25 +302,32 @@ TEST_CASE("Streaming of slsDetectorDefs::scanParameters") {
} }
} }
TEST_CASE("Printing c style arrays of int"){ TEST_CASE("Printing c style arrays of int") {
int arr[]{3, 5}; int arr[]{3, 5};
REQUIRE(ToString(arr) == "[3, 5]"); REQUIRE(ToString(arr) == "[3, 5]");
} }
TEST_CASE("Printing c style arrays of uint8"){ TEST_CASE("Printing c style arrays of uint8") {
uint8_t arr[]{1,2,3,4,5}; uint8_t arr[]{1, 2, 3, 4, 5};
REQUIRE(ToString(arr) == "[1, 2, 3, 4, 5]"); REQUIRE(ToString(arr) == "[1, 2, 3, 4, 5]");
} }
TEST_CASE("Printing c style arrays of double"){ TEST_CASE("Printing c style arrays of double") {
double arr[]{3.4, 5.3, 6.2}; double arr[]{3.4, 5.3, 6.2};
REQUIRE(ToString(arr) == "[3.4, 5.3, 6.2]"); REQUIRE(ToString(arr) == "[3.4, 5.3, 6.2]");
} }
TEST_CASE("Print a member of patternParameters"){ TEST_CASE("Print a member of patternParameters") {
auto pat = sls::make_unique<sls::patternParameters>(); auto pat = sls::make_unique<sls::patternParameters>();
pat->limits[0] = 4; pat->limits[0] = 4;
pat->limits[1] = 100; pat->limits[1] = 100;
REQUIRE(ToString(pat->limits) == "[4, 100]"); REQUIRE(ToString(pat->limits) == "[4, 100]");
}
TEST_CASE("EthernetInterface") {
REQUIRE(ToString(sls::defs::EthernetInterface::NONE) == "none");
REQUIRE(ToString(sls::defs::EthernetInterface::I10GBE) == "10gbe");
REQUIRE(ToString(sls::defs::EthernetInterface::I3GBE) == "3gbe");
REQUIRE(ToString(sls::defs::EthernetInterface::I3GBE |
sls::defs::EthernetInterface::I10GBE) == "3gbe, 10gbe");
} }