Skip to content

Commit 7b4f745

Browse files
committed
Error propagation for cmd.get_object_list()
1 parent a71b212 commit 7b4f745

File tree

2 files changed

+36
-29
lines changed

2 files changed

+36
-29
lines changed

layer4/Cmd.cpp

Lines changed: 26 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -4063,39 +4063,36 @@ static PyObject *CmdDirty(PyObject * self, PyObject * args)
40634063
return APISuccess();
40644064
}
40654065

4066-
static PyObject *CmdGetObjectList(PyObject * self, PyObject * args)
4066+
static pymol::Result<PyObject*> _getObjectMoleculeNamePyList(
4067+
PyMOLGlobals* G, char const* sele)
40674068
{
4068-
PyMOLGlobals *G = nullptr;
4069-
char *str1;
4070-
OrthoLineType s1;
4071-
int ok = false;
4072-
PyObject *result = nullptr;
4073-
4074-
ok = PyArg_ParseTuple(args, "Os", &self, &str1);
4075-
4076-
if(ok) {
4077-
API_SETUP_PYMOL_GLOBALS;
4078-
ok = (G != nullptr);
4079-
} else {
4080-
API_HANDLE_ERROR;
4069+
if (!sele[0]) {
4070+
// preserve non-error legacy behavior: Empty selection returns None
4071+
return APIAutoNone(nullptr);
40814072
}
4082-
if(ok && (ok = APIEnterBlockedNotModal(G))) {
4083-
ok = (SelectorGetTmp(G, str1, s1) >= 0);
4084-
auto list = ExecutiveGetObjectMoleculeVLA(G, s1);
4085-
if(list) {
4086-
unsigned int size = VLAGetSize(list);
4087-
result = PyList_New(size);
4088-
if(result) {
4089-
unsigned int a;
4090-
for(a = 0; a < size; a++) {
4091-
PyList_SetItem(result, a, PyString_FromString(list[a]->Name));
4092-
}
4093-
}
4073+
auto tmpsele1 = SelectorTmp::make(G, sele);
4074+
p_return_if_error(tmpsele1);
4075+
auto const list = ExecutiveGetObjectMoleculeVLA(G, tmpsele1->getName());
4076+
assert(list);
4077+
auto const size = list.size();
4078+
auto result = PyList_New(size);
4079+
if (result) {
4080+
for (unsigned a = 0; a < size; ++a) {
4081+
PyList_SetItem(result, a, PyUnicode_FromString(list[a]->Name));
40944082
}
4095-
SelectorFreeTmp(G, s1);
4096-
APIExitBlocked(G);
40974083
}
4098-
return (APIAutoNone(result));
4084+
return result;
4085+
}
4086+
4087+
static PyObject *CmdGetObjectList(PyObject * self, PyObject * args)
4088+
{
4089+
PyMOLGlobals *G = nullptr;
4090+
char *str1;
4091+
API_SETUP_ARGS(G, self, args, "Os", &self, &str1);
4092+
API_ASSERT(APIEnterBlockedNotModal(G));
4093+
auto res = _getObjectMoleculeNamePyList(G, str1);
4094+
APIExitBlocked(G);
4095+
return APIResult(G, res);
40994096
}
41004097

41014098
static PyObject *CmdGetDistance(PyObject * self, PyObject * args)

testing/tests/api/querying.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,16 @@ def testGetObjectList(self):
339339
cmd.ramp_new('ramp1', 'none') # non-molecular object
340340
self.assertEqual(cmd.get_object_list(), ['gly', 'cys'])
341341
self.assertEqual(cmd.get_object_list('elem S'), ['cys'])
342+
self.assertTrue(cmd.get_object_list('none') == [])
343+
# whitespace string is empty selection
344+
self.assertTrue(cmd.get_object_list(' ') == [])
345+
# empty string is a silent None
346+
# https://github.com/schrodinger/pymol-open-source/issues/478
347+
self.assertTrue(cmd.get_object_list('') is None)
348+
349+
def testGetObjectList__invalid_selection(self):
350+
self.assertRaises(CmdException, cmd.get_object_list, 'invalid_selection_name')
351+
self.assertRaises(CmdException, cmd.get_object_list, '(none') # malformed
342352

343353
@testing.requires_version('1.6')
344354
def testGetObjectMatrix(self):

0 commit comments

Comments
 (0)