Skip to content

Commit d9a2488

Browse files
Fixed up handling of container indexing, and complex value_types.
1 parent 58cb79b commit d9a2488

File tree

2 files changed

+60
-72
lines changed

2 files changed

+60
-72
lines changed

RESTProcessExample/example.py

+20-17
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,9 @@ def expectThrow(f):
5757
assert root.bar.c()=='hello world'
5858

5959
assert root.bar.c1()==['\r','\r']
60-
assert root.bar.c1[0]()=='\r'
60+
assert root.bar.c1[0]=='\r'
6161
root.bar.c1[0]='x'
62-
assert root.bar.c1[0]()=='x'
62+
assert root.bar.c1[0]=='x'
6363

6464
assert root.bar.ef()=='ea'
6565
assert root.bar.ef('eb')=='eb'
@@ -72,21 +72,21 @@ def expectThrow(f):
7272

7373
assert root.bar.d()==[0,1,2]
7474
assert len(root.bar.d)==3
75-
assert root.bar.d[1]()==1
75+
assert root.bar.d[1]==1
7676
root.bar.d[1]=5
77-
assert root.bar.d[1]()==5
77+
assert root.bar.d[1]==5
7878

7979
assert len(root.bar.d1)==2
8080
assert root.bar.d1[1]()==[3,4,5]
8181
root.bar.d1[1]=[6,7,8]
8282
assert root.bar.d1[1]()==[6,7,8]
8383
assert root.bar.d1()==[[0,1,2],[6,7,8]]
8484
root.bar.d1[1][2]=10
85-
assert root.bar.d1[1][2]()==10
85+
assert root.bar.d1[1][2]==10
8686
assert root.bar.h()==[2,2,2]
87-
assert root.bar.h[1]()==2
87+
assert root.bar.h[1]==2
8888
root.bar.h[1]=3
89-
assert root.bar.h[1]()==3
89+
assert root.bar.h[1]==3
9090
root.bar.h.insert(5)
9191
assert root.bar.h()==[2,3,2,5]
9292
root.bar.h.erase(1)
@@ -96,25 +96,25 @@ def expectThrow(f):
9696
assert root.bar.h._list()==[".@elem",".@elemNoThrow",".@erase",".@insert",".@size"]
9797

9898
assert root.bar.l()==[2,2,2]
99-
assert root.bar.l[1]()==2
99+
assert root.bar.l[1]==2
100100
root.bar.l[1]=3
101-
assert root.bar.l[1]()==3
101+
assert root.bar.l[1]==3
102102
root.bar.l.insert(5)
103103
assert root.bar.l()==[2,3,2,5]
104104
assert root.bar.l([2,2,2,2])()==[2,2,2,2]
105105

106106
assert root.bar.m()==[{"first":0,"second":5},{"first":3,"second":2}]
107107
assert len(root.bar.m)==2
108108
assert root.bar.m._signature()==[{"args":[],"ret":"std::map<int,int>"},{"args":["std::map<int,int>"],"ret":"std::map<int,int>"}]
109-
assert root.bar.m[3]()==2
109+
assert root.bar.m[3]==2
110110
root.bar.m[3]=5
111-
assert root.bar.m[3]()==5
111+
assert root.bar.m[3]==5
112112

113113
root.bar.m.insert({"first":1,"second":2})
114-
assert root.bar.m[1]()==2
114+
assert root.bar.m[1]==2
115115
assert root.bar.m.contains(1)
116116
root.bar.m[10]=2
117-
assert root.bar.m[10]()==2
117+
assert root.bar.m[10]==2
118118
assert root.bar.m.contains(10)
119119
assert root.bar.m._type()=="std::map<int,int>"
120120
assert root.bar.m._list()==[".@elem",".@elemNoThrow",".@erase",".@insert",".@keys",".@size"]
@@ -129,14 +129,14 @@ def expectThrow(f):
129129
root.bar.um.insert({"first":1,"second":3})
130130
assert root.bar.um()==[{"first":1,"second":3}]
131131
root.bar.um[1]=5
132-
assert root.bar.um[1]()==5
132+
assert root.bar.um[1]==5
133133

134134
assert root.bar.llex()==[["hello","hello"],["hello","hello"]]
135135
root.bar.llex[1]=["baa","baa","blacksheep"]
136136
assert root.bar.llex[1]()==["baa","baa","blacksheep"]
137137
assert root.bar.llex()==[["hello","hello"],["baa","baa","blacksheep"]]
138138
assert root.bar.llex._signature()==[{"args":[],"ret":"std::list<std::list<std::string>>"},{"args":["std::list<std::list<std::string>>"],"ret":"std::list<std::list<std::string>>"}]
139-
assert root.bar.llex[1][1]()=="baa"
139+
assert root.bar.llex[1][1]=="baa"
140140

141141
# Should fail
142142
expectThrow(lambda: root.bar.iex())
@@ -161,9 +161,12 @@ def expectThrow(f):
161161
assert root.bar1.fooRef().b()==2
162162
assert root.bar1.f.name()=='Foo'
163163

164-
assert root.bar1.vFoo[1]._properties()['b']==1
164+
assert root.bar1.vFoo[1]()['b']==1
165+
assert root.bar1.vFoo[1].b()==1
165166
expectThrow(lambda: root.bar1.vFoo[10])
166167

168+
assert root.bar.mFoo['foo'].b()==2
169+
167170
assert root.bar1.foo().b(3)==3
168171
assert root.bar1.foo().b()==2
169172
assert root.bar1.fooRef().b(3)==3
@@ -191,7 +194,7 @@ def expectThrow(f):
191194
assert root.bar.sm({"foo":1,"bar":2})._properties()=={"foo":1,"bar":2}
192195
assert root.bar.sm()=={"foo":1,"bar":2}
193196
assert root.bar.sm({"foo":1,"foobar":3})._properties()=={"foo":1,"foobar":3}
194-
assert root.bar.sm['foo']()==1
197+
assert root.bar.sm['foo']==1
195198
assert root.bar.sm.contains("foobar")
196199
root.bar.sm.erase("foobar")
197200
assert not root.bar.sm.contains("foobar")

pythonBuffer.h

+40-55
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,18 @@
3030
#include <numeric>
3131
#include <Python.h>
3232

33-
#define CLASSDESC_PY_EXCEPTION_ABSORB(ret) \
34-
catch (const std::exception& ex) \
35-
{ \
36-
PyErr_SetString(PyExc_RuntimeError, ex.what()); \
37-
return ret; \
33+
#define CLASSDESC_PY_EXCEPTION_ABSORB(ret) \
34+
catch (const std::exception& ex) \
35+
{ \
36+
PyErr_SetString(PyExc_RuntimeError, ex.what()); \
37+
return ret; \
38+
} \
39+
catch (...) \
40+
{ \
41+
PyErr_SetString(PyExc_RuntimeError, "Unknown exception"); \
42+
return ret; \
3843
}
39-
44+
4045
namespace classdesc
4146
{
4247
// map of registries, one per module
@@ -407,10 +412,6 @@ namespace classdesc
407412
return b;
408413
}
409414

410-
/// call \a command on \a registry with \a arguments
411-
/// returns a python object representing function's return value.
412-
PyObject* callOnRegistry(const RPPtr& command, const string& remainder, const PythonBuffer& arguments);
413-
414415
/// C++ wrapper to default initialise the PyObject
415416
struct CppPyObject: public PyObject
416417
{
@@ -421,7 +422,6 @@ namespace classdesc
421422
class CppWrapper;
422423
void attachRegistryObjects(const RESTProcess_t& registry, CppWrapper& object,const std::string& prefix);
423424

424-
425425
struct CppWrapper: public CppPyObject
426426
{
427427
const bool special; // if true, command takes a key as an argument
@@ -430,6 +430,27 @@ namespace classdesc
430430
static CppWrapper* create(const RPPtr& command, bool special) {return new CppWrapper(command,special);}
431431
CppWrapper(CppWrapper&&)=default;
432432

433+
static PyObject* returnResult(const RPPtr& result)
434+
{
435+
PythonBuffer resultBuffer(result->asBuffer());
436+
auto pyResult=resultBuffer.getPyObject();
437+
switch (resultBuffer.type())
438+
{
439+
case RESTProcessType::object:
440+
case RESTProcessType::array:
441+
{
442+
auto r=CppWrapper::create(result, false);
443+
PyObjectRef ref(r);
444+
attachRegistryObjects(result->list(),*r,".");
445+
return ref.release();
446+
}
447+
default: break;
448+
}
449+
if (PyErr_Occurred())
450+
PyErr_Print();
451+
return pyResult.release();
452+
}
453+
433454
static PyObject* list(CppWrapper* self, PyObject*)
434455
try
435456
{
@@ -511,7 +532,7 @@ namespace classdesc
511532
{"contains",(PyCFunction)CppWrapper::contains,METH_O,"Retrun true/false whether map/set contains a key"},
512533
{nullptr, nullptr, 0, nullptr}
513534
};
514-
535+
515536
struct CppWrapperType: public PyTypeObject
516537
{
517538
// container commands that take a key as as an argument
@@ -538,7 +559,11 @@ namespace classdesc
538559
arguments.push_back(PySequence_GetItem(args,i));
539560
if (PyErr_Occurred())
540561
PyErr_Print();
541-
return callOnRegistry(command, remainder, arguments);
562+
try
563+
{
564+
return CppWrapper::returnResult(command->process(remainder,arguments.get<json_pack_t>()));
565+
}
566+
CLASSDESC_PY_EXCEPTION_ABSORB(nullptr);
542567
}
543568

544569
static void deleteCppWrapper(PyObject* x) {
@@ -588,14 +613,9 @@ namespace classdesc
588613
auto cppWrapper=static_cast<CppWrapper*>(self);
589614
try
590615
{
591-
auto result=cppWrapper->command->getElem(PythonBuffer(key).get<json_pack_t>());
592-
return CppWrapper::create(result, false);
593-
}
594-
catch (const std::exception& ex)
595-
{
596-
PyErr_SetString(PyExc_RuntimeError, ex.what());
597-
return nullptr;
616+
return CppWrapper::returnResult(cppWrapper->command->getElem(PythonBuffer(key).get<json_pack_t>()));
598617
}
618+
CLASSDESC_PY_EXCEPTION_ABSORB(nullptr);
599619
}
600620

601621
static int setElem(PyObject* self, PyObject* key, PyObject* val)
@@ -665,41 +685,6 @@ namespace classdesc
665685
}
666686
}
667687

668-
inline PyObject* callOnRegistry(const RPPtr& command, const std::string& remainder, const PythonBuffer& arguments)
669-
{
670-
try
671-
{
672-
auto args=arguments.get<json_pack_t>();
673-
auto result=command->process(remainder,args);
674-
PythonBuffer resultBuffer(result->asBuffer());
675-
auto pyResult=resultBuffer.getPyObject();
676-
switch (resultBuffer.type())
677-
{
678-
case RESTProcessType::object:
679-
case RESTProcessType::array:
680-
{
681-
auto r=CppWrapper::create(result, false);
682-
PyObjectRef ref(r);
683-
attachRegistryObjects(result->list(),*r,".");
684-
return ref.release();
685-
}
686-
}
687-
if (PyErr_Occurred())
688-
PyErr_Print();
689-
return pyResult.release();
690-
}
691-
catch (const std::exception& ex)
692-
{
693-
PyErr_SetString(PyExc_RuntimeError, ex.what());
694-
return nullptr;
695-
}
696-
catch (...)
697-
{
698-
PyErr_SetString(PyExc_RuntimeError, "Unknown exception");
699-
return nullptr;
700-
}
701-
}
702-
703688
template <class F>
704689
struct RESTProcessFactory: public RESTProcessFunction<F>
705690
{

0 commit comments

Comments
 (0)