PyAPI: use keyword only arguments for Text.region_{from/to} string

This is the convention for most parts of Blender Python API.
This commit is contained in:
Campbell Barton 2022-04-08 12:49:02 +10:00
parent 982aea88e0
commit ee292a1d66
Notes: blender-bot 2023-04-24 11:49:24 +02:00
Referenced by pull request #107285, Fix #107261: bpy.types.Text (region_as_string/region_from_string) crash
Referenced by commit e4afa06dab, Fix #107261: bpy.types.Text (region_as_string/region_from_string) crash
2 changed files with 41 additions and 19 deletions

View File

@ -36,6 +36,8 @@ typedef struct TextRegion {
int selc;
} TextRegion;
/** \} */
/* -------------------------------------------------------------------- */
/** \name Text Editor Get / Set region text API
* \{ */
@ -53,18 +55,27 @@ PyDoc_STRVAR(bpy_rna_region_as_string_doc,
" :return: The specified region as a string.\n"
" :rtype: str.\n");
/* Receive a Python Tuple as parameter to represent the region range. */
static PyObject *bpy_rna_region_as_string(PyObject *self, PyObject *args)
static PyObject *bpy_rna_region_as_string(PyObject *self, PyObject *args, PyObject *kwds)
{
BPy_StructRNA *pyrna = (BPy_StructRNA *)self;
Text *text = pyrna->ptr.data;
/* Parse the region range. */
TextRegion region;
if (!PyArg_ParseTuple(
args, "|((ii)(ii))", &region.curl, &region.curc, &region.sell, &region.selc)) {
static const char *_keywords[] = {"range", NULL};
static _PyArg_Parser _parser = {
"|$" /* Optional keyword only arguments. */
"((ii)(ii))" /* `range` */
":region_as_string",
_keywords,
0,
};
if (!_PyArg_ParseTupleAndKeywordsFast(
args, kwds, &_parser, &region.curl, &region.curc, &region.sell, &region.selc)) {
return NULL;
}
if (PyTuple_GET_SIZE(args) > 0) {
if (PyDict_GET_SIZE(kwds) > 0) {
txt_sel_set(text, region.curl, region.curc, region.sell, region.selc);
}
@ -98,7 +109,7 @@ PyDoc_STRVAR(bpy_rna_region_from_string_doc,
" The values match Python's slicing logic "
"(negative values count backwards from the end, the end value is not inclusive).\n"
" :type range: Two pairs of ints\n");
static PyObject *bpy_rna_region_from_string(PyObject *self, PyObject *args)
static PyObject *bpy_rna_region_from_string(PyObject *self, PyObject *args, PyObject *kwds)
{
BPy_StructRNA *pyrna = (BPy_StructRNA *)self;
Text *text = pyrna->ptr.data;
@ -107,18 +118,29 @@ static PyObject *bpy_rna_region_from_string(PyObject *self, PyObject *args)
const char *buf;
Py_ssize_t buf_len;
TextRegion region;
if (!PyArg_ParseTuple(args,
"s#|((ii)(ii))",
&buf,
&buf_len,
&region.curl,
&region.curc,
&region.sell,
&region.selc)) {
static const char *_keywords[] = {"", "range", NULL};
static _PyArg_Parser _parser = {
"s#" /* `buf` (positional). */
"|$" /* Optional keyword only arguments. */
"((ii)(ii))" /* `range` */
":region_from_string",
_keywords,
0,
};
if (!_PyArg_ParseTupleAndKeywordsFast(args,
kwds,
&_parser,
&buf,
&buf_len,
&region.curl,
&region.curc,
&region.sell,
&region.selc)) {
return NULL;
}
if (PyTuple_GET_SIZE(args) > 1) {
if (PyDict_GET_SIZE(kwds) > 0) {
txt_sel_set(text, region.curl, region.curc, region.sell, region.selc);
}
@ -133,7 +155,7 @@ static PyObject *bpy_rna_region_from_string(PyObject *self, PyObject *args)
PyMethodDef BPY_rna_region_from_string_method_def = {
"region_from_string",
(PyCFunction)bpy_rna_region_from_string,
METH_VARARGS,
METH_VARARGS | METH_KEYWORDS,
bpy_rna_region_from_string_doc,
};

View File

@ -40,9 +40,9 @@ class TestText(unittest.TestCase):
)
self.text.write(tmp_text)
# Get string in the middle of the text.
self.assertEqual(self.text.region_as_string(((1, 0), (1, -1))), "Line 2: test line 2")
self.assertEqual(self.text.region_as_string(range=((1, 0), (1, -1))), "Line 2: test line 2")
# Big range test.
self.assertEqual(self.text.region_as_string(((-10000, -10000), (10000, 10000))), tmp_text)
self.assertEqual(self.text.region_as_string(range=((-10000, -10000), (10000, 10000))), tmp_text)
def test_text_region_from_string(self):
tmp_text = (
@ -52,10 +52,10 @@ class TestText(unittest.TestCase):
)
self.text.write(tmp_text)
# Set string in the middle of the text.
self.text.region_from_string("line 2", ((1, 0), (1, -1)))
self.text.region_from_string("line 2", range=((1, 0), (1, -1)))
self.assertEqual(self.text.as_string(), tmp_text.replace("Line 2: test line 2", "line 2") + "\n")
# Large range test.
self.text.region_from_string("New Text", ((-10000, -10000), (10000, 10000)))
self.text.region_from_string("New Text", range=((-10000, -10000), (10000, 10000)))
self.assertEqual(self.text.as_string(), "New Text\n")