Merge pull request #25938 from Connor9220/AddAnnotationsToCommand

CAM: Add annotations support to Command constructor and Python bindings
This commit is contained in:
sliptonic
2025-12-12 12:17:09 -06:00
committed by GitHub
4 changed files with 69 additions and 4 deletions

View File

@@ -47,6 +47,16 @@ Command::Command(const char* name, const std::map<std::string, double>& paramete
, Annotations()
{}
Command::Command(
const char* name,
const std::map<std::string, double>& parameters,
const std::map<std::string, std::variant<std::string, double>>& annotations
)
: Name(name)
, Parameters(parameters)
, Annotations(annotations)
{}
Command::Command()
: Annotations()
{}

View File

@@ -44,6 +44,11 @@ public:
// constructors
Command();
Command(const char* name, const std::map<std::string, double>& parameters);
Command(
const char* name,
const std::map<std::string, double>& parameters,
const std::map<std::string, std::variant<std::string, double>>& annotations
);
~Command() override;
// from base class
unsigned int getMemSize() const override;

View File

@@ -13,10 +13,11 @@ from Base.Placement import Placement
@class_declarations("mutable Py::Dict parameters_copy_dict;")
class Command(Persistence):
"""
Command([name],[parameters]): Represents a basic Gcode command
Command([name],[parameters],[annotations]): Represents a basic Gcode command
name (optional) is the name of the command, ex. G1
parameters (optional) is a dictionary containing string:number
pairs, or a placement, or a vector
annotations (optional) is a dictionary containing string:string or string:number pairs
"""
@constmethod

View File

@@ -71,9 +71,20 @@ PyObject* CommandPy::PyMake(struct _typeobject*, PyObject*, PyObject*) // Pytho
int CommandPy::PyInit(PyObject* args, PyObject* kwd)
{
PyObject* parameters = nullptr;
PyObject* annotations = nullptr;
const char* name = "";
static const std::array<const char*, 3> kwlist {"name", "parameters", nullptr};
if (Base::Wrapped_ParseTupleAndKeywords(args, kwd, "|sO!", kwlist, &name, &PyDict_Type, &parameters)) {
static const std::array<const char*, 4> kwlist {"name", "parameters", "annotations", nullptr};
if (Base::Wrapped_ParseTupleAndKeywords(
args,
kwd,
"|sO!O!",
kwlist,
&name,
&PyDict_Type,
&parameters,
&PyDict_Type,
&annotations
)) {
std::string sname(name);
boost::to_upper(sname);
try {
@@ -112,16 +123,54 @@ int CommandPy::PyInit(PyObject* args, PyObject* kwd)
}
getCommandPtr()->Parameters[ckey] = cvalue;
}
// Parse annotations
pos = 0;
while (annotations && PyDict_Next(annotations, &pos, &key, &value)) {
std::string ckey;
if (PyUnicode_Check(key)) {
ckey = PyUnicode_AsUTF8(key);
}
else {
PyErr_SetString(
PyExc_TypeError,
"The annotations dictionary can only contain string keys"
);
return -1;
}
if (PyUnicode_Check(value)) {
std::string cvalue = PyUnicode_AsUTF8(value);
getCommandPtr()->setAnnotation(ckey, cvalue);
}
else if (PyObject_TypeCheck(value, &(PyLong_Type))) {
double cvalue = (double)PyLong_AsLong(value);
getCommandPtr()->setAnnotation(ckey, cvalue);
}
else if (PyObject_TypeCheck(value, &(PyFloat_Type))) {
double cvalue = PyFloat_AsDouble(value);
getCommandPtr()->setAnnotation(ckey, cvalue);
}
else {
PyErr_SetString(
PyExc_TypeError,
"The annotations dictionary can only contain string or number values"
);
return -1;
}
}
parameters_copy_dict.clear();
return 0;
}
PyErr_Clear(); // set by PyArg_ParseTuple()
static const std::array<const char*, 3> kwlist_placement {"name", "parameters", nullptr};
if (Base::Wrapped_ParseTupleAndKeywords(
args,
kwd,
"|sO!",
kwlist,
kwlist_placement,
&name,
&(Base::PlacementPy::Type),
&parameters