diff options
author | Mark Spruiell <mes@zeroc.com> | 2012-09-14 15:30:12 -0700 |
---|---|---|
committer | Mark Spruiell <mes@zeroc.com> | 2012-09-14 15:30:12 -0700 |
commit | c912d30d47799bbba77d0f2532704d8aaba12a4a (patch) | |
tree | 8611fdb0b73a9a78f7c319ca4bb08f1f9d2e9cd0 | |
parent | Fixed optional test issues (diff) | |
download | ice-c912d30d47799bbba77d0f2532704d8aaba12a4a.tar.bz2 ice-c912d30d47799bbba77d0f2532704d8aaba12a4a.tar.xz ice-c912d30d47799bbba77d0f2532704d8aaba12a4a.zip |
Python support for optionals
35 files changed, 3114 insertions, 555 deletions
diff --git a/cpp/include/Ice/BasicStream.h b/cpp/include/Ice/BasicStream.h index 69bfc1a2e53..fcffd268000 100644 --- a/cpp/include/Ice/BasicStream.h +++ b/cpp/include/Ice/BasicStream.h @@ -457,6 +457,19 @@ public: Ice::Int readAndCheckSeqSize(int); + void startSize() + { + _sizePos = static_cast<int>(b.size()); + write(Ice::Int(0)); + } + + void endSize() + { + assert(_sizePos >= 0); + rewrite(b.size() - _sizePos - 4, _sizePos); + _sizePos = -1; + } + void writeBlob(const std::vector<Ice::Byte>&); void readBlob(std::vector<Ice::Byte>&, Ice::Int); @@ -1126,6 +1139,8 @@ private: int _startSeq; int _minSeqSize; + int _sizePos; + static const Ice::Byte FLAG_HAS_TYPE_ID_STRING; static const Ice::Byte FLAG_HAS_TYPE_ID_INDEX; static const Ice::Byte FLAG_HAS_OPTIONAL_MEMBERS; diff --git a/cpp/include/Ice/SlicedData.h b/cpp/include/Ice/SlicedData.h index 974cf001472..54542c12c52 100644 --- a/cpp/include/Ice/SlicedData.h +++ b/cpp/include/Ice/SlicedData.h @@ -85,6 +85,8 @@ public: const std::string& getUnknownTypeId() const; + SlicedDataPtr getSlicedData() const; + virtual void __addObject(::IceInternal::GCCountMap&); virtual bool __usesGC(); virtual void __gcReachable(::IceInternal::GCCountMap&) const; diff --git a/cpp/include/Ice/Stream.h b/cpp/include/Ice/Stream.h index ad662f490b4..e5dc75b074c 100644 --- a/cpp/include/Ice/Stream.h +++ b/cpp/include/Ice/Stream.h @@ -67,7 +67,7 @@ public: virtual void usesClasses(bool) = 0; virtual ::std::string ice_name() const = 0; - virtual UserExceptionReader* ice_clone() const = 0; + virtual UserException* ice_clone() const = 0; virtual void ice_throw() const = 0; virtual void __write(IceInternal::BasicStream*) const; @@ -332,7 +332,10 @@ public: virtual void write(const Float*, const Float*) = 0; virtual void write(const Double*, const Double*) = 0; - virtual void writeOptional(Int, OptionalType) = 0; + virtual bool writeOptional(Int, OptionalType) = 0; + + virtual void startSize() = 0; + virtual void endSize() = 0; // // COMPILER FIX: clang using libc++ cannot use the StreamHelper to write @@ -423,7 +426,7 @@ public: virtual bool usesClasses() const = 0; virtual ::std::string ice_name() const = 0; - virtual UserExceptionWriter* ice_clone() const = 0; + virtual UserException* ice_clone() const = 0; virtual void ice_throw() const = 0; virtual void __write(IceInternal::BasicStream*) const; diff --git a/cpp/src/Ice/BasicStream.cpp b/cpp/src/Ice/BasicStream.cpp index 199ef69d639..105afb804bc 100755 --- a/cpp/src/Ice/BasicStream.cpp +++ b/cpp/src/Ice/BasicStream.cpp @@ -97,7 +97,8 @@ IceInternal::BasicStream::BasicStream(Instance* instance, const EncodingVersion& _unlimited(unlimited), _stringConverter(instance->initializationData().stringConverter), _wstringConverter(instance->initializationData().wstringConverter), - _startSeq(-1) + _startSeq(-1), + _sizePos(-1) { // // Initialize the encoding members of our pre-allocated encapsulations, in case @@ -126,6 +127,8 @@ IceInternal::BasicStream::clear() _startSeq = -1; + _sizePos = -1; + _sliceObjects = true; } @@ -163,6 +166,7 @@ IceInternal::BasicStream::swap(BasicStream& other) std::swap(_unlimited, other._unlimited); std::swap(_startSeq, other._startSeq); std::swap(_minSeqSize, other._minSeqSize); + std::swap(_sizePos, other._sizePos); } void @@ -2754,12 +2758,39 @@ IceInternal::BasicStream::EncapsDecoder::readInstance() skipSlice(); // - // If this is the last slice, keep the object as an opaque - // UnknownSlicedData object. + // If this is the last slice, keep the object as an opaque UnknownSlicedObject. // if(_sliceFlags & FLAG_IS_LAST_SLICE) { - v = new UnknownSlicedObject(mostDerivedId); + // + // Provide a factory with an opportunity to supply the object. + // We pass the "::Ice::Object" ID to indicate that this is the + // last chance to preserve the object. + // + userFactory = servantFactoryManager->find(Object::ice_staticId()); + if(userFactory) + { + v = userFactory->create(Object::ice_staticId()); + } + + // + // If that fails, invoke the default factory if one has been + // registered. + // + if(!v) + { + userFactory = servantFactoryManager->find(""); + if(userFactory) + { + v = userFactory->create(Object::ice_staticId()); + } + } + + if(!v) + { + v = new UnknownSlicedObject(mostDerivedId); + } + break; } diff --git a/cpp/src/Ice/SlicedData.cpp b/cpp/src/Ice/SlicedData.cpp index 9b2e88b609c..5332719eec9 100644 --- a/cpp/src/Ice/SlicedData.cpp +++ b/cpp/src/Ice/SlicedData.cpp @@ -82,6 +82,12 @@ Ice::UnknownSlicedObject::getUnknownTypeId() const return _unknownTypeId; } +SlicedDataPtr +Ice::UnknownSlicedObject::getSlicedData() const +{ + return _slicedData; +} + void Ice::UnknownSlicedObject::__addObject(IceInternal::GCCountMap& _c) { diff --git a/cpp/src/Ice/StreamI.cpp b/cpp/src/Ice/StreamI.cpp index e1e73f94617..431926d64b0 100644 --- a/cpp/src/Ice/StreamI.cpp +++ b/cpp/src/Ice/StreamI.cpp @@ -570,10 +570,10 @@ OutputStreamI::write(const Double* begin, const Double* end) _os->write(begin, end); } -void +bool OutputStreamI::writeOptional(Int tag, OptionalType type) { - _os->writeOpt(tag, type); + return _os->writeOpt(tag, type); } void @@ -677,6 +677,18 @@ OutputStreamI::rewrite(Int sz, size_type p) _os->rewrite(sz, p); } +void +OutputStreamI::startSize() +{ + _os->startSize(); +} + +void +OutputStreamI::endSize() +{ + _os->endSize(); +} + // // ObjectReader // diff --git a/cpp/src/Ice/StreamI.h b/cpp/src/Ice/StreamI.h index 8d9bba4e977..ba0d103a640 100644 --- a/cpp/src/Ice/StreamI.h +++ b/cpp/src/Ice/StreamI.h @@ -147,7 +147,7 @@ public: using OutputStream::write; #endif - virtual void writeOptional(Int, OptionalType); + virtual bool writeOptional(Int, OptionalType); virtual void startObject(const SlicedDataPtr&); virtual void endObject(); @@ -173,6 +173,9 @@ public: virtual size_type pos(); virtual void rewrite(Int, size_type); + virtual void startSize(); + virtual void endSize(); + private: const CommunicatorPtr _communicator; diff --git a/cpp/src/Slice/PythonUtil.cpp b/cpp/src/Slice/PythonUtil.cpp index 4e363c17d18..45ded5d48bc 100755 --- a/cpp/src/Slice/PythonUtil.cpp +++ b/cpp/src/Slice/PythonUtil.cpp @@ -565,7 +565,7 @@ Slice::Python::CodeVisitor::visitClassDefStart(const ClassDefPtr& p) string fixedOpName = fixIdent((*oli)->name()); if(!p->isLocal() && (p->hasMetaData("amd") || (*oli)->hasMetaData("amd"))) { - _out << sp << nl << "def " << fixedOpName << "_async(self, _cb"; + _out << sp << nl << "def " << (*oli)->name() << "_async(self, _cb"; ParamDeclList params = (*oli)->parameters(); @@ -749,7 +749,7 @@ Slice::Python::CodeVisitor::visitClassDefStart(const ClassDefPtr& p) { _out << nl << comment; } - _out << nl << "def " << fixedOpName << "_async(self, _cb"; + _out << nl << "def " << (*oli)->name() << "_async(self, _cb"; if(!inParams.empty()) { _out << ", " << inParams; @@ -832,7 +832,7 @@ Slice::Python::CodeVisitor::visitClassDefStart(const ClassDefPtr& p) // // Data members are represented as a tuple: // - // ('MemberName', MemberMetaData, MemberType) + // ('MemberName', MemberMetaData, MemberType, Optional, Tag) // // where MemberType is either a primitive type constant (T_INT, etc.) or the id of a constructed type. // @@ -858,7 +858,8 @@ Slice::Python::CodeVisitor::visitClassDefStart(const ClassDefPtr& p) writeMetaData((*r)->getMetaData()); _out << ", "; writeType((*r)->type()); - _out << ')'; + _out << ", " << ((*r)->optional() ? "True" : "False") << ", " + << ((*r)->optional() ? (*r)->tag() : 0) << ')'; } if(members.size() == 1) { @@ -875,7 +876,7 @@ Slice::Python::CodeVisitor::visitClassDefStart(const ClassDefPtr& p) // // Define each operation. The arguments to the IcePy.Operation constructor are: // - // 'opName', Mode, SendMode, AMD, (MetaData), (InParams), (OutParams), ReturnType, (Exceptions) + // 'opName', Mode, SendMode, AMD, Format, MetaData, (InParams), (OutParams), ReturnParam, (Exceptions) // // where InParams and OutParams are tuples of type descriptions, and Exceptions // is a tuple of exception type ids. @@ -923,7 +924,8 @@ Slice::Python::CodeVisitor::visitClassDefStart(const ClassDefPtr& p) writeMetaData((*t)->getMetaData()); _out << ", "; writeType((*t)->type()); - _out << ')'; + _out << ", " << ((*t)->optional() ? "True" : "False") << ", " + << ((*t)->optional() ? (*t)->tag() : 0) << ')'; ++count; } } @@ -944,7 +946,8 @@ Slice::Python::CodeVisitor::visitClassDefStart(const ClassDefPtr& p) writeMetaData((*t)->getMetaData()); _out << ", "; writeType((*t)->type()); - _out << ')'; + _out << ", " << ((*t)->optional() ? "True" : "False") << ", " + << ((*t)->optional() ? (*t)->tag() : 0) << ')'; ++count; } } @@ -956,7 +959,15 @@ Slice::Python::CodeVisitor::visitClassDefStart(const ClassDefPtr& p) TypePtr returnType = (*s)->returnType(); if(returnType) { + // + // The return type has the same format as an in/out parameter: + // + // MetaData, Type, Optional?, OptionalTag + // + _out << "((), "; writeType(returnType); + _out << ", " << ((*s)->returnIsOptional() ? "True" : "False") << ", " + << ((*s)->returnIsOptional() ? (*s)->returnTag() : 0) << ')'; } else { @@ -1125,7 +1136,7 @@ Slice::Python::CodeVisitor::visitExceptionStart(const ExceptionPtr& p) // // Data members are represented as a tuple: // - // ('MemberName', MemberMetaData, MemberType) + // ('MemberName', MemberMetaData, MemberType, Optional, Tag) // // where MemberType is either a primitive type constant (T_INT, etc.) or the id of a constructed type. // @@ -1139,7 +1150,8 @@ Slice::Python::CodeVisitor::visitExceptionStart(const ExceptionPtr& p) writeMetaData((*dmli)->getMetaData()); _out << ", "; writeType((*dmli)->type()); - _out << ')'; + _out << ", " << ((*dmli)->optional() ? "True" : "False") << ", " + << ((*dmli)->optional() ? (*dmli)->tag() : 0) << ')'; } if(members.size() == 1) { @@ -1762,24 +1774,27 @@ Slice::Python::CodeVisitor::writeMetaData(const StringList& meta) void Slice::Python::CodeVisitor::writeAssign(const MemberInfo& info) { + string paramName = info.fixedName; + string memberName = info.fixedName; + // // Structures are treated differently (see bug 3676). // StructPtr st = StructPtr::dynamicCast(info.dataMember->type()); - if(st) + if(st && !info.dataMember->optional()) { - _out << nl << "if " << info.fixedName << " is Ice._struct_marker:"; + _out << nl << "if " << paramName << " is Ice._struct_marker:"; _out.inc(); - _out << nl << "self." << info.fixedName << " = " << getSymbol(st) << "()"; + _out << nl << "self." << memberName << " = " << getSymbol(st) << "()"; _out.dec(); _out << nl << "else:"; _out.inc(); - _out << nl << "self." << info.fixedName << " = " << info.fixedName; + _out << nl << "self." << memberName << " = " << paramName; _out.dec(); } else { - _out << nl << "self." << info.fixedName << " = " << info.fixedName; + _out << nl << "self." << memberName << " = " << paramName; } } @@ -1933,6 +1948,10 @@ Slice::Python::CodeVisitor::writeConstructorParams(const MemberInfoList& members { writeConstantValue(member->type(), member->defaultValueType(), member->defaultValue()); } + else if(member->optional()) + { + _out << "Ice.Unset"; + } else { writeInitializer(member->type()); diff --git a/cs/test/Ice/optional/AllTests.cs b/cs/test/Ice/optional/AllTests.cs index 191bef1ca3c..b3bf727e01b 100644 --- a/cs/test/Ice/optional/AllTests.cs +++ b/cs/test/Ice/optional/AllTests.cs @@ -743,14 +743,14 @@ public class AllTests : TestCommon.TestApp os = Ice.Util.createOutputStream(communicator); os.startEncapsulation(); - os.writeOptional(2, Ice.OptionalType.F8); + os.writeOptional(1, Ice.OptionalType.F8); os.writeLong(p1.Value); os.endEncapsulation(); inEncaps = os.finished(); initial.ice_invoke("opLong", Ice.OperationMode.Normal, inEncaps, out outEncaps); @in = Ice.Util.createInputStream(communicator, outEncaps); @in.startEncapsulation(); - test(@in.readOptional(1, Ice.OptionalType.F8)); + test(@in.readOptional(2, Ice.OptionalType.F8)); test(@in.readLong() == 56); test(@in.readOptional(3, Ice.OptionalType.F8)); test(@in.readLong() == 56); diff --git a/cs/test/Ice/optional/Test.ice b/cs/test/Ice/optional/Test.ice index 6a0ad658d87..d16a8985b0c 100644 --- a/cs/test/Ice/optional/Test.ice +++ b/cs/test/Ice/optional/Test.ice @@ -184,7 +184,7 @@ class Initial optional(1) int opInt(optional(2) int p1, out optional(3) int p3); - optional(1) long opLong(optional(2) long p1, out optional(3) long p3); + optional(3) long opLong(optional(1) long p1, out optional(2) long p3); optional(1) float opFloat(optional(2) float p1, out optional(3) float p3); diff --git a/cs/test/Ice/optional/TestAMD.ice b/cs/test/Ice/optional/TestAMD.ice index 36230b44f90..27de98b60ee 100644 --- a/cs/test/Ice/optional/TestAMD.ice +++ b/cs/test/Ice/optional/TestAMD.ice @@ -184,7 +184,7 @@ class Initial optional(1) int opInt(optional(2) int p1, out optional(3) int p3); - optional(1) long opLong(optional(2) long p1, out optional(3) long p3); + optional(3) long opLong(optional(1) long p1, out optional(2) long p3); optional(1) float opFloat(optional(2) float p1, out optional(3) float p3); diff --git a/cs/test/Ice/optional/TestI.cs b/cs/test/Ice/optional/TestI.cs index 731c60579ce..f396e276ce0 100644 --- a/cs/test/Ice/optional/TestI.cs +++ b/cs/test/Ice/optional/TestI.cs @@ -25,24 +25,7 @@ public class InitialI : Test.Initial public override void opOptionalException(Ice.Optional<int> a, Ice.Optional<string> b, Ice.Optional<Test.OneOptional> o, Ice.Current current) { - Test.OptionalException ex = new Test.OptionalException(); - if(a.HasValue) - { - ex.a = a.Value; - } - else - { - ex.a = Ice.Util.None; // The member "a" has a default value. - } - if(b.HasValue) - { - ex.b = b.Value; - } - if(o.HasValue) - { - ex.o = o.Value; - } - throw ex; + throw new Test.OptionalException(a, b, o); } public override Ice.Optional<byte> opByte(Ice.Optional<byte> p1, out Ice.Optional<byte> p3, Ice.Current current) diff --git a/java/test/Ice/optional/AllTests.java b/java/test/Ice/optional/AllTests.java index 98538ba7311..e530835908e 100644 --- a/java/test/Ice/optional/AllTests.java +++ b/java/test/Ice/optional/AllTests.java @@ -710,14 +710,14 @@ public class AllTests os = Ice.Util.createOutputStream(communicator); os.startEncapsulation(); - os.writeOptional(2, Ice.OptionalType.F8); + os.writeOptional(1, Ice.OptionalType.F8); os.writeLong(p1.get()); os.endEncapsulation(); inEncaps = os.finished(); initial.ice_invoke("opLong", Ice.OperationMode.Normal, inEncaps, outEncaps); in = Ice.Util.createInputStream(communicator, outEncaps.value); in.startEncapsulation(); - test(in.readOptional(1, Ice.OptionalType.F8)); + test(in.readOptional(2, Ice.OptionalType.F8)); test(in.readLong() == 56); test(in.readOptional(3, Ice.OptionalType.F8)); test(in.readLong() == 56); diff --git a/java/test/Ice/optional/Test.ice b/java/test/Ice/optional/Test.ice index ce4c442d93b..ed73ce4aa89 100644 --- a/java/test/Ice/optional/Test.ice +++ b/java/test/Ice/optional/Test.ice @@ -181,8 +181,8 @@ class Initial optional(1) int opInt(optional(2) int p1, out optional(3) int p3); ["java:optional"] optional(1) int opIntOpt(optional(2) int p1, out optional(3) int p3); - optional(1) long opLong(optional(2) long p1, out optional(3) long p3); - ["java:optional"] optional(1) long opLongOpt(optional(2) long p1, out optional(3) long p3); + optional(3) long opLong(optional(1) long p1, out optional(2) long p3); + ["java:optional"] optional(3) long opLongOpt(optional(1) long p1, out optional(2) long p3); optional(1) float opFloat(optional(2) float p1, out optional(3) float p3); ["java:optional"] optional(1) float opFloatOpt(optional(2) float p1, out optional(3) float p3); diff --git a/java/test/Ice/optional/TestAMD.ice b/java/test/Ice/optional/TestAMD.ice index 42209e9ee1e..2a7476373ee 100644 --- a/java/test/Ice/optional/TestAMD.ice +++ b/java/test/Ice/optional/TestAMD.ice @@ -181,8 +181,8 @@ class Initial optional(1) int opInt(optional(2) int p1, out optional(3) int p3); ["java:optional"] optional(1) int opIntOpt(optional(2) int p1, out optional(3) int p3); - optional(1) long opLong(optional(2) long p1, out optional(3) long p3); - ["java:optional"] optional(1) long opLongOpt(optional(2) long p1, out optional(3) long p3); + optional(3) long opLong(optional(1) long p1, out optional(2) long p3); + ["java:optional"] optional(3) long opLongOpt(optional(1) long p1, out optional(2) long p3); optional(1) float opFloat(optional(2) float p1, out optional(3) float p3); ["java:optional"] optional(1) float opFloatOpt(optional(2) float p1, out optional(3) float p3); diff --git a/py/allTests.py b/py/allTests.py index 3c5db62ace4..d43e65c8c9e 100755 --- a/py/allTests.py +++ b/py/allTests.py @@ -48,7 +48,8 @@ tests = [ ("Ice/blobject", ["core"]), ("Ice/defaultServant", ["core"]), ("Ice/defaultValue", ["core"]), - ("Ice/ami", ["core"]) + ("Ice/ami", ["core"]), + ("Ice/optional", ["core"]) ] if __name__ == "__main__": diff --git a/py/modules/IcePy/ObjectFactory.cpp b/py/modules/IcePy/ObjectFactory.cpp index 4af8965349a..336ca9dc902 100644 --- a/py/modules/IcePy/ObjectFactory.cpp +++ b/py/modules/IcePy/ObjectFactory.cpp @@ -49,7 +49,20 @@ IcePy::ObjectFactory::create(const string& id) // // Get the type information. // - ClassInfoPtr info = lookupClassInfo(id); + ClassInfoPtr info; + if(id == Ice::Object::ice_staticId()) + { + // + // When the ID is that of Ice::Object, it indicates that the stream has not + // found a factory and is providing us an opportunity to preserve the object. + // + info = lookupClassInfo("::Ice::UnknownSlicedObject"); + } + else + { + info = lookupClassInfo(id); + } + if(!info) { return 0; diff --git a/py/modules/IcePy/Operation.cpp b/py/modules/IcePy/Operation.cpp index 7960fc41796..036b2da4aad 100644 --- a/py/modules/IcePy/Operation.cpp +++ b/py/modules/IcePy/Operation.cpp @@ -46,9 +46,12 @@ public: Ice::StringSeq metaData; TypeInfoPtr type; + bool optional; + int tag; + int pos; }; typedef IceUtil::Handle<ParamInfo> ParamInfoPtr; -typedef vector<ParamInfoPtr> ParamInfoList; +typedef list<ParamInfoPtr> ParamInfoList; // // Encapsulates attributes of an operation. @@ -68,7 +71,9 @@ public: Ice::FormatType format; Ice::StringSeq metaData; ParamInfoList inParams; + ParamInfoList optionalInParams; ParamInfoList outParams; + ParamInfoList optionalOutParams; ParamInfoPtr returnType; ExceptionInfoList exceptions; string dispatchName; @@ -80,7 +85,8 @@ private: string _deprecateMessage; - static void convertParams(PyObject*, ParamInfoList&, bool&); + static void convertParams(PyObject*, ParamInfoList&, int, bool&); + static ParamInfoPtr convertParam(PyObject*, int); }; typedef IceUtil::Handle<Operation> OperationPtr; @@ -530,19 +536,19 @@ operationInit(OperationObject* self, PyObject* args, PyObject* /*kwds*/) PyObject* sendMode; int amd; PyObject* format; - PyObject* meta; + PyObject* metaData; PyObject* inParams; PyObject* outParams; PyObject* returnType; PyObject* exceptions; if(!PyArg_ParseTuple(args, STRCAST("sO!O!iOO!O!O!OO!"), &name, modeType, &mode, modeType, &sendMode, &amd, - &format, &PyTuple_Type, &meta, &PyTuple_Type, &inParams, &PyTuple_Type, &outParams, + &format, &PyTuple_Type, &metaData, &PyTuple_Type, &inParams, &PyTuple_Type, &outParams, &returnType, &PyTuple_Type, &exceptions)) { return -1; } - OperationPtr op = new Operation(name, mode, sendMode, amd, format, meta, inParams, outParams, returnType, + OperationPtr op = new Operation(name, mode, sendMode, amd, format, metaData, inParams, outParams, returnType, exceptions); self->op = new OperationPtr(op); @@ -1036,7 +1042,7 @@ IcePy::Operation::Operation(const char* n, PyObject* m, PyObject* sm, int amdFla amd = amdFlag ? true : false; if(amd) { - dispatchName = fixIdent(name) + "_async"; + dispatchName = name + "_async"; } else { @@ -1060,42 +1066,75 @@ IcePy::Operation::Operation(const char* n, PyObject* m, PyObject* sm, int amdFla // // metaData // + assert(PyTuple_Check(meta)); #ifndef NDEBUG bool b = #endif tupleToStringSeq(meta, metaData); assert(b); - Py_ssize_t i, sz; + // + // returnType + // + if(ret != Py_None) + { + returnType = convertParam(ret, 0); + if(!returnsClasses) + { + returnsClasses = returnType->type->usesClasses(); + } + } // // inParams // - convertParams(in, inParams, sendsClasses); + convertParams(in, inParams, 0, sendsClasses); // // outParams // - convertParams(out, outParams, returnsClasses); + convertParams(out, outParams, returnType ? 1 : 0, returnsClasses); - // - // returnType - // - if(ret != Py_None) + class SortFn { - returnType = new ParamInfo; - returnType->type = getType(ret); - if(!returnsClasses) + public: + static bool compare(const ParamInfoPtr& lhs, const ParamInfoPtr& rhs) { - returnsClasses = returnType->type->usesClasses(); + return lhs->tag < rhs->tag; } + + static bool isRequired(const ParamInfoPtr& i) + { + return !i->optional; + } + }; + + // + // The inParams list represents the parameters in the order of declaration. + // We also need a sorted list of optional parameters. + // + ParamInfoList l = inParams; + copy(l.begin(), remove_if(l.begin(), l.end(), SortFn::isRequired), back_inserter(optionalInParams)); + optionalInParams.sort(SortFn::compare); + + // + // The outParams list represents the parameters in the order of declaration. + // We also need a sorted list of optional parameters. If the return value is + // optional, we must include it in this list. + // + l = outParams; + copy(l.begin(), remove_if(l.begin(), l.end(), SortFn::isRequired), back_inserter(optionalOutParams)); + if(returnType && returnType->optional) + { + optionalOutParams.push_back(returnType); } + optionalOutParams.sort(SortFn::compare); // // exceptions // - sz = PyTuple_GET_SIZE(ex); - for(i = 0; i < sz; ++i) + Py_ssize_t sz = PyTuple_GET_SIZE(ex); + for(Py_ssize_t i = 0; i < sz; ++i) { exceptions.push_back(getException(PyTuple_GET_ITEM(ex, i))); } @@ -1120,33 +1159,14 @@ IcePy::Operation::deprecate(const string& msg) } void -IcePy::Operation::convertParams(PyObject* p, ParamInfoList& params, bool& usesClasses) +IcePy::Operation::convertParams(PyObject* p, ParamInfoList& params, int posOffset, bool& usesClasses) { usesClasses = false; int sz = static_cast<int>(PyTuple_GET_SIZE(p)); for(int i = 0; i < sz; ++i) { PyObject* item = PyTuple_GET_ITEM(p, i); - assert(PyTuple_Check(item)); - assert(PyTuple_GET_SIZE(item) == 2); - - ParamInfoPtr param = new ParamInfo; - - // - // metaData - // - PyObject* meta = PyTuple_GET_ITEM(item, 0); - assert(PyTuple_Check(meta)); -#ifndef NDEBUG - bool b = -#endif - tupleToStringSeq(meta, param->metaData); - assert(b); - - // - // type - // - param->type = getType(PyTuple_GET_ITEM(item, 1)); + ParamInfoPtr param = convertParam(item, i + posOffset); params.push_back(param); if(!usesClasses) { @@ -1155,6 +1175,52 @@ IcePy::Operation::convertParams(PyObject* p, ParamInfoList& params, bool& usesCl } } +ParamInfoPtr +IcePy::Operation::convertParam(PyObject* p, int pos) +{ + assert(PyTuple_Check(p)); + assert(PyTuple_GET_SIZE(p) == 4); + + ParamInfoPtr param = new ParamInfo; + + // + // metaData + // + PyObject* meta = PyTuple_GET_ITEM(p, 0); + assert(PyTuple_Check(meta)); +#ifndef NDEBUG + bool b = +#endif + tupleToStringSeq(meta, param->metaData); + assert(b); + + // + // type + // + PyObject* type = PyTuple_GET_ITEM(p, 1); + if(type != Py_None) + { + param->type = getType(type); + } + + // + // optional + // + param->optional = PyObject_IsTrue(PyTuple_GET_ITEM(p, 2)); + + // + // tag + // + param->tag = static_cast<int>(PyLong_AsLong(PyTuple_GET_ITEM(p, 3))); + + // + // position + // + param->pos = pos; + + return param; +} + static PyMethodDef OperationMethods[] = { { STRCAST("invoke"), reinterpret_cast<PyCFunction>(operationInvoke), METH_VARARGS, @@ -1443,30 +1509,61 @@ IcePy::TypedInvocation::prepareRequest(PyObject* args, MappingType mapping, vect os->startEncapsulation(_prx->ice_getEncodingVersion(), _op->format); ObjectMap objectMap; - int i = 0; - for(ParamInfoList::iterator p = _op->inParams.begin(); p != _op->inParams.end(); ++p, ++i) + ParamInfoList::iterator p; + + // + // Validate the supplied arguments. + // + for(p = _op->inParams.begin(); p != _op->inParams.end(); ++p) { - PyObject* arg = PyTuple_GET_ITEM(args, i); - if(!(*p)->type->validate(arg)) + ParamInfoPtr info = *p; + PyObject* arg = PyTuple_GET_ITEM(args, info->pos); + if((!info->optional || arg != Unset) && !info->type->validate(arg)) { - string opName; + string name; if(mapping == OldAsyncMapping) { - opName = _op->name + "_async"; + name = _op->name + "_async"; } else if(mapping == AsyncMapping) { - opName = "begin_" + _op->name; + name = "begin_" + _op->name; } else { - opName = fixIdent(_op->name); + name = fixIdent(_op->name); } PyErr_Format(PyExc_ValueError, STRCAST("invalid value for argument %d in operation `%s'"), - mapping == OldAsyncMapping ? i + 2 : i + 1, const_cast<char*>(opName.c_str())); + mapping == OldAsyncMapping ? info->pos + 2 : info->pos + 1, + const_cast<char*>(name.c_str())); return false; } - (*p)->type->marshal(arg, os, &objectMap, &(*p)->metaData); + } + + // + // Marshal the required parameters. + // + for(p = _op->inParams.begin(); p != _op->inParams.end(); ++p) + { + ParamInfoPtr info = *p; + if(!info->optional) + { + PyObject* arg = PyTuple_GET_ITEM(args, info->pos); + info->type->marshal(arg, os, &objectMap, false, &info->metaData); + } + } + + // + // Marshal the optional parameters. + // + for(p = _op->optionalInParams.begin(); p != _op->optionalInParams.end(); ++p) + { + ParamInfoPtr info = *p; + PyObject* arg = PyTuple_GET_ITEM(args, info->pos); + if(arg != Unset && os->writeOptional(info->tag, info->type->optionalType())) + { + info->type->marshal(arg, os, &objectMap, true, &info->metaData); + } } os->endEncapsulation(); @@ -1490,8 +1587,11 @@ IcePy::TypedInvocation::prepareRequest(PyObject* args, MappingType mapping, vect PyObject* IcePy::TypedInvocation::unmarshalResults(const pair<const Ice::Byte*, const Ice::Byte*>& bytes) { - Py_ssize_t i = _op->returnType ? 1 : 0; - Py_ssize_t numResults = static_cast<Py_ssize_t>(_op->outParams.size()) + i; + Py_ssize_t numResults = static_cast<Py_ssize_t>(_op->outParams.size()); + if(_op->returnType) + { + numResults++; + } PyObjectHandle results = PyTuple_New(numResults); if(results.get() && numResults > 0) @@ -1508,15 +1608,50 @@ IcePy::TypedInvocation::unmarshalResults(const pair<const Ice::Byte*, const Ice: is->startEncapsulation(); - for(ParamInfoList::iterator p = _op->outParams.begin(); p != _op->outParams.end(); ++p, ++i) + ParamInfoList::iterator p; + + // + // Unmarshal the required out parameters. + // + for(p = _op->outParams.begin(); p != _op->outParams.end(); ++p) { - void* closure = reinterpret_cast<void*>(i); - (*p)->type->unmarshal(is, *p, results.get(), closure, &(*p)->metaData); + ParamInfoPtr info = *p; + if(!info->optional) + { + void* closure = reinterpret_cast<void*>(info->pos); + info->type->unmarshal(is, info, results.get(), closure, false, &info->metaData); + } } - if(_op->returnType) + // + // Unmarshal the required return value, if any. + // + if(_op->returnType && !_op->returnType->optional) { - _op->returnType->type->unmarshal(is, _op->returnType, results.get(), 0, &_op->metaData); + assert(_op->returnType->pos == 0); + void* closure = reinterpret_cast<void*>(_op->returnType->pos); + _op->returnType->type->unmarshal(is, _op->returnType, results.get(), closure, false, &_op->metaData); + } + + // + // Unmarshal the optional results. This includes an optional return value. + // + for(p = _op->optionalOutParams.begin(); p != _op->optionalOutParams.end(); ++p) + { + ParamInfoPtr info = *p; + if(is->readOptional(info->tag, info->type->optionalType())) + { + void* closure = reinterpret_cast<void*>(info->pos); + info->type->unmarshal(is, info, results.get(), closure, true, &info->metaData); + } + else + { + if(PyTuple_SET_ITEM(results.get(), info->pos, Unset) < 0) + { + return 0; + } + Py_INCREF(Unset); // PyTuple_SET_ITEM steals a reference. + } } is->endEncapsulation(); @@ -1900,7 +2035,7 @@ IcePy::AsyncTypedInvocation::invoke(PyObject* args, PyObject* /* kwds */) // IllegalArgumentException can propagate directly. // (Raised by checkAsyncTwowayOnly) // - PyErr_Format(PyExc_RuntimeError, STRCAST(ex.reason().c_str())); + PyErr_Format(PyExc_RuntimeError, "%s", STRCAST(ex.reason().c_str())); return 0; } catch(const Ice::Exception&) @@ -1986,7 +2121,7 @@ IcePy::AsyncTypedInvocation::end(const Ice::ObjectPrx& proxy, const OperationPtr } catch(const IceUtil::IllegalArgumentException& ex) { - PyErr_Format(PyExc_RuntimeError, STRCAST(ex.reason().c_str())); + PyErr_Format(PyExc_RuntimeError, "%s", STRCAST(ex.reason().c_str())); } catch(const Ice::Exception& ex) { @@ -2702,7 +2837,7 @@ IcePy::AsyncBlobjectInvocation::end(const Ice::ObjectPrx& proxy, const Ice::Asyn } catch(const IceUtil::IllegalArgumentException& ex) { - PyErr_Format(PyExc_RuntimeError, STRCAST(ex.reason().c_str())); + PyErr_Format(PyExc_RuntimeError, "%s", STRCAST(ex.reason().c_str())); } catch(const Ice::Exception& ex) { @@ -3066,11 +3201,11 @@ IcePy::TypedUpcall::dispatch(PyObject* servant, const pair<const Ice::Byte*, con // Py_ssize_t count = static_cast<Py_ssize_t>(_op->inParams.size()) + 1; - Py_ssize_t start = 0; + Py_ssize_t offset = 0; if(_op->amd) { ++count; // Leave room for a leading AMD callback argument. - start = 1; + offset = 1; } PyObjectHandle args = PyTuple_New(count); @@ -3095,11 +3230,40 @@ IcePy::TypedUpcall::dispatch(PyObject* servant, const pair<const Ice::Byte*, con { is->startEncapsulation(); - Py_ssize_t i = start; - for(ParamInfoList::iterator p = _op->inParams.begin(); p != _op->inParams.end(); ++p, ++i) + ParamInfoList::iterator p; + + // + // Unmarshal the required parameters. + // + for(p = _op->inParams.begin(); p != _op->inParams.end(); ++p) { - void* closure = reinterpret_cast<void*>(i); - (*p)->type->unmarshal(is, *p, args.get(), closure, &(*p)->metaData); + ParamInfoPtr info = *p; + if(!info->optional) + { + void* closure = reinterpret_cast<void*>(info->pos + offset); + info->type->unmarshal(is, info, args.get(), closure, false, &info->metaData); + } + } + + // + // Unmarshal the optional parameters. + // + for(p = _op->optionalInParams.begin(); p != _op->optionalInParams.end(); ++p) + { + ParamInfoPtr info = *p; + if(is->readOptional(info->tag, info->type->optionalType())) + { + void* closure = reinterpret_cast<void*>(info->pos + offset); + info->type->unmarshal(is, info, args.get(), closure, true, &info->metaData); + } + else + { + if(PyTuple_SET_ITEM(args.get(), info->pos + offset, Unset) < 0) + { + throwPythonException(); + } + Py_INCREF(Unset); // PyTuple_SET_ITEM steals a reference. + } } is->endEncapsulation(); @@ -3198,71 +3362,111 @@ IcePy::TypedUpcall::response(PyObject* args, const Ice::EncodingVersion& encodin Ice::OutputStreamPtr os = Ice::createOutputStream(_communicator); try { - Py_ssize_t i = _op->returnType ? 1 : 0; - Py_ssize_t numResults = static_cast<Py_ssize_t>(_op->outParams.size()) + i; - if(numResults > 1) + Py_ssize_t numResults = static_cast<Py_ssize_t>(_op->outParams.size()); + if(_op->returnType) + { + numResults++; + } + + if(numResults > 1 && (!PyTuple_Check(args) || PyTuple_GET_SIZE(args) != numResults)) + { + ostringstream ostr; + ostr << "operation `" << fixIdent(_op->name) << "' should return a tuple of length " << numResults; + string str = ostr.str(); + PyErr_Warn(PyExc_RuntimeWarning, const_cast<char*>(str.c_str())); + throw Ice::MarshalException(__FILE__, __LINE__); + } + + // + // Normalize the args value. For an AMD operation, or when there are multiple + // result values, args is already a tuple. Otherwise, we create a tuple to + // make the code a little simpler. + // + PyObjectHandle t; + if(_op->amd || numResults > 1) + { + t = args; + } + else { - if(!PyTuple_Check(args) || PyTuple_GET_SIZE(args) != numResults) + t = PyTuple_New(1); + if(!t.get()) { - ostringstream ostr; - ostr << "operation `" << fixIdent(_op->name) << "' should return a tuple of length " << numResults; - string str = ostr.str(); - PyErr_Warn(PyExc_RuntimeWarning, const_cast<char*>(str.c_str())); - throw Ice::MarshalException(__FILE__, __LINE__); + throw AbortMarshaling(); } + PyTuple_SET_ITEM(t.get(), 0, args); } + Py_INCREF(args); os->startEncapsulation(encoding, _op->format); ObjectMap objectMap; + ParamInfoList::iterator p; - for(ParamInfoList::iterator p = _op->outParams.begin(); p != _op->outParams.end(); ++p, ++i) + // + // Validate the results. + // + for(p = _op->outParams.begin(); p != _op->outParams.end(); ++p) { - PyObject* arg; - if(_op->amd || numResults > 1) - { - arg = PyTuple_GET_ITEM(args, i); - } - else - { - arg = args; - assert(_op->outParams.size() == 1); - } - - if(!(*p)->type->validate(arg)) + ParamInfoPtr info = *p; + PyObject* arg = PyTuple_GET_ITEM(t.get(), info->pos); + if((!info->optional || arg != Unset) && !info->type->validate(arg)) { // TODO: Provide the parameter name instead? ostringstream ostr; - ostr << "invalid value for out argument " << (i + 1) << " in operation `" << fixIdent(_op->name) - << (_op->amd ? "_async" : "") << "'"; + ostr << "invalid value for out argument " << (info->pos + 1) << " in operation `" + << _op->dispatchName << "'"; string str = ostr.str(); PyErr_Warn(PyExc_RuntimeWarning, const_cast<char*>(str.c_str())); throw Ice::MarshalException(__FILE__, __LINE__); } - (*p)->type->marshal(arg, os, &objectMap, &(*p)->metaData); } - if(_op->returnType) { - PyObject* res; - if(_op->amd || numResults > 1) - { - res = PyTuple_GET_ITEM(args, 0); - } - else - { - assert(_op->outParams.size() == 0); - res = args; - } - if(!_op->returnType->type->validate(res)) + PyObject* res = PyTuple_GET_ITEM(t.get(), 0); + if((!_op->returnType->optional || res != Unset) && !_op->returnType->type->validate(res)) { ostringstream ostr; - ostr << "invalid return value for operation `" << fixIdent(_op->name) << "'"; + ostr << "invalid return value for operation `" << _op->dispatchName << "'"; string str = ostr.str(); PyErr_Warn(PyExc_RuntimeWarning, const_cast<char*>(str.c_str())); throw Ice::MarshalException(__FILE__, __LINE__); } - _op->returnType->type->marshal(res, os, &objectMap, &_op->metaData); + } + + // + // Marshal the required out parameters. + // + for(p = _op->outParams.begin(); p != _op->outParams.end(); ++p) + { + ParamInfoPtr info = *p; + if(!info->optional) + { + PyObject* arg = PyTuple_GET_ITEM(t.get(), info->pos); + info->type->marshal(arg, os, &objectMap, false, &info->metaData); + } + } + + // + // Marshal the required return value, if any. + // + if(_op->returnType && !_op->returnType->optional) + { + PyObject* res = PyTuple_GET_ITEM(t.get(), 0); + _op->returnType->type->marshal(res, os, &objectMap, false, &_op->metaData); + } + + // + // Marshal the optional results. + // + for(p = _op->optionalOutParams.begin(); p != _op->optionalOutParams.end(); ++p) + { + ParamInfoPtr info = *p; + PyObject* arg = PyTuple_GET_ITEM(t.get(), info->pos); + if(arg != Unset && os->writeOptional(info->tag, info->type->optionalType())) + { + info->type->marshal(arg, os, &objectMap, true, &info->metaData); + } } os->endEncapsulation(); diff --git a/py/modules/IcePy/Types.cpp b/py/modules/IcePy/Types.cpp index 8eba7bce883..d8d381aab1d 100644 --- a/py/modules/IcePy/Types.cpp +++ b/py/modules/IcePy/Types.cpp @@ -20,6 +20,8 @@ #include <Ice/LocalException.h> #include <Ice/SlicedData.h> +#include <list> + using namespace std; using namespace IcePy; using namespace IceUtil; @@ -546,6 +548,11 @@ IcePy::TypeInfo::destroy() // // PrimitiveInfo implementation. // +IcePy::PrimitiveInfo::PrimitiveInfo(Kind k) : + kind(k) +{ +} + string IcePy::PrimitiveInfo::getId() const { @@ -671,8 +678,65 @@ IcePy::PrimitiveInfo::validate(PyObject* p) return true; } +bool +IcePy::PrimitiveInfo::variableLength() const +{ + return kind == KindString; +} + +int +IcePy::PrimitiveInfo::wireSize() const +{ + switch(kind) + { + case KindBool: + case KindByte: + return 1; + case KindShort: + return 2; + case KindInt: + return 4; + case KindLong: + return 8; + case KindFloat: + return 4; + case KindDouble: + return 8; + case KindString: + return 1; + } + assert(false); + return 0; +} + +Ice::OptionalType +IcePy::PrimitiveInfo::optionalType() const +{ + switch(kind) + { + case KindBool: + case KindByte: + return Ice::OptionalTypeF1; + case KindShort: + return Ice::OptionalTypeF2; + case KindInt: + return Ice::OptionalTypeF4; + case KindLong: + return Ice::OptionalTypeF8; + case KindFloat: + return Ice::OptionalTypeF4; + case KindDouble: + return Ice::OptionalTypeF8; + case KindString: + return Ice::OptionalTypeVSize; + } + + assert(false); + return Ice::OptionalTypeF1; +} + void -IcePy::PrimitiveInfo::marshal(PyObject* p, const Ice::OutputStreamPtr& os, ObjectMap*, const Ice::StringSeq*) +IcePy::PrimitiveInfo::marshal(PyObject* p, const Ice::OutputStreamPtr& os, ObjectMap*, bool, const Ice::StringSeq*) { switch(kind) { @@ -753,7 +817,7 @@ IcePy::PrimitiveInfo::marshal(PyObject* p, const Ice::OutputStreamPtr& os, Objec void IcePy::PrimitiveInfo::unmarshal(const Ice::InputStreamPtr& is, const UnmarshalCallbackPtr& cb, PyObject* target, - void* closure, const Ice::StringSeq*) + void* closure, bool, const Ice::StringSeq*) { switch(kind) { @@ -850,6 +914,24 @@ IcePy::PrimitiveInfo::print(PyObject* value, IceUtilInternal::Output& out, Print // // EnumInfo implementation. // +IcePy::EnumInfo::EnumInfo(const string& ident, PyObject* t, PyObject* e) : + id(ident), pythonType(t) +{ + assert(PyType_Check(t)); + assert(PyTuple_Check(e)); + + Py_INCREF(t); + + Py_ssize_t sz = PyTuple_GET_SIZE(e); + for(Py_ssize_t i = 0; i < sz; ++i) + { + PyObjectHandle h = PyTuple_GET_ITEM(e, i); + Py_INCREF(h.get()); + assert(PyObject_IsInstance(h.get(), t)); + const_cast<EnumeratorList&>(enumerators).push_back(h); + } +} + string IcePy::EnumInfo::getId() const { @@ -862,8 +944,26 @@ IcePy::EnumInfo::validate(PyObject* val) return PyObject_IsInstance(val, pythonType.get()) == 1; } +bool +IcePy::EnumInfo::variableLength() const +{ + return true; +} + +int +IcePy::EnumInfo::wireSize() const +{ + return 1; +} + +Ice::OptionalType +IcePy::EnumInfo::optionalType() const +{ + return Ice::OptionalTypeSize; +} + void -IcePy::EnumInfo::marshal(PyObject* p, const Ice::OutputStreamPtr& os, ObjectMap*, const Ice::StringSeq*) +IcePy::EnumInfo::marshal(PyObject* p, const Ice::OutputStreamPtr& os, ObjectMap*, bool, const Ice::StringSeq*) { assert(PyObject_IsInstance(p, pythonType.get()) == 1); // validate() should have caught this. @@ -909,7 +1009,7 @@ IcePy::EnumInfo::marshal(PyObject* p, const Ice::OutputStreamPtr& os, ObjectMap* void IcePy::EnumInfo::unmarshal(const Ice::InputStreamPtr& is, const UnmarshalCallbackPtr& cb, PyObject* target, - void* closure, const Ice::StringSeq*) + void* closure, bool, const Ice::StringSeq*) { Ice::Int val; Ice::Int count = static_cast<Ice::Int>(enumerators.size()); @@ -971,9 +1071,109 @@ IcePy::DataMember::unmarshaled(PyObject* val, PyObject* target, void*) } } +static void +convertDataMembers(PyObject* members, DataMemberList& reqMembers, DataMemberList& optMembers, bool allowOptional) +{ + list<DataMemberPtr> optList; + + Py_ssize_t sz = PyTuple_GET_SIZE(members); + for(Py_ssize_t i = 0; i < sz; ++i) + { + PyObject* m = PyTuple_GET_ITEM(members, i); + assert(PyTuple_Check(m)); + assert(PyTuple_GET_SIZE(m) == allowOptional ? 5 : 3); + + PyObject* name = PyTuple_GET_ITEM(m, 0); // Member name. + assert(checkString(name)); + PyObject* meta = PyTuple_GET_ITEM(m, 1); // Member metadata. + assert(PyTuple_Check(meta)); + PyObject* t = PyTuple_GET_ITEM(m, 2); // Member type. + + PyObject* opt = 0; + PyObject* tag = 0; + if(allowOptional) + { + opt = PyTuple_GET_ITEM(m, 3); // Optional? + tag = PyTuple_GET_ITEM(m, 4); +#if PY_VERSION_HEX < 0x03000000 + assert(PyInt_Check(tag)); +#else + assert(PyLong_Check(tag)); +#endif + } + + DataMemberPtr member = new DataMember; + member->name = getString(name); +#ifndef NDEBUG + bool b = +#endif + tupleToStringSeq(meta, member->metaData); + assert(b); + member->type = getType(t); + if(allowOptional) + { + member->optional = PyObject_IsTrue(opt); + member->tag = static_cast<int>(PyLong_AsLong(tag)); + } + else + { + member->optional = false; + member->tag = 0; + } + + if(member->optional) + { + optList.push_back(member); + } + else + { + reqMembers.push_back(member); + } + } + + if(allowOptional) + { + class SortFn + { + public: + static bool compare(const DataMemberPtr& lhs, const DataMemberPtr& rhs) + { + return lhs->tag < rhs->tag; + } + }; + + optList.sort(SortFn::compare); + copy(optList.begin(), optList.end(), back_inserter(optMembers)); + } +} + // // StructInfo implementation. // +IcePy::StructInfo::StructInfo(const string& ident, PyObject* t, PyObject* m) : + id(ident), pythonType(t) +{ + assert(PyType_Check(t)); + assert(PyTuple_Check(m)); + + Py_INCREF(t); + + DataMemberList opt; + convertDataMembers(m, const_cast<DataMemberList&>(members), opt, false); + assert(opt.empty()); + + _variableLength = false; + _wireSize = 0; + for(DataMemberList::const_iterator p = members.begin(); p != members.end(); ++p) + { + if(!_variableLength && (*p)->type->variableLength()) + { + _variableLength = true; + } + _wireSize += (*p)->type->wireSize(); + } +} + string IcePy::StructInfo::getId() const { @@ -989,7 +1189,7 @@ IcePy::StructInfo::validate(PyObject* val) bool IcePy::StructInfo::usesClasses() { - for(DataMemberList::iterator q = members.begin(); q != members.end(); ++q) + for(DataMemberList::const_iterator q = members.begin(); q != members.end(); ++q) { if((*q)->type->usesClasses()) { @@ -1000,12 +1200,43 @@ IcePy::StructInfo::usesClasses() return false; } +bool +IcePy::StructInfo::variableLength() const +{ + return _variableLength; +} + +int +IcePy::StructInfo::wireSize() const +{ + return _wireSize; +} + +Ice::OptionalType +IcePy::StructInfo::optionalType() const +{ + return _variableLength ? Ice::OptionalTypeFSize : Ice::OptionalTypeVSize; +} + void -IcePy::StructInfo::marshal(PyObject* p, const Ice::OutputStreamPtr& os, ObjectMap* objectMap, const Ice::StringSeq*) +IcePy::StructInfo::marshal(PyObject* p, const Ice::OutputStreamPtr& os, ObjectMap* objectMap, bool optional, + const Ice::StringSeq*) { assert(PyObject_IsInstance(p, pythonType.get()) == 1); // validate() should have caught this. - for(DataMemberList::iterator q = members.begin(); q != members.end(); ++q) + if(optional) + { + if(_variableLength) + { + os->startSize(); + } + else + { + os->writeSize(_wireSize); + } + } + + for(DataMemberList::const_iterator q = members.begin(); q != members.end(); ++q) { DataMemberPtr member = *q; char* memberName = const_cast<char*>(member->name.c_str()); @@ -1022,13 +1253,18 @@ IcePy::StructInfo::marshal(PyObject* p, const Ice::OutputStreamPtr& os, ObjectMa memberName); throw AbortMarshaling(); } - member->type->marshal(attr.get(), os, objectMap, &member->metaData); + member->type->marshal(attr.get(), os, objectMap, false, &member->metaData); + } + + if(optional && _variableLength) + { + os->endSize(); } } void IcePy::StructInfo::unmarshal(const Ice::InputStreamPtr& is, const UnmarshalCallbackPtr& cb, PyObject* target, - void* closure, const Ice::StringSeq*) + void* closure, bool optional, const Ice::StringSeq*) { PyObjectHandle args = PyTuple_New(0); PyTypeObject* type = reinterpret_cast<PyTypeObject*>(pythonType.get()); @@ -1039,10 +1275,22 @@ IcePy::StructInfo::unmarshal(const Ice::InputStreamPtr& is, const UnmarshalCallb throw AbortMarshaling(); } - for(DataMemberList::iterator q = members.begin(); q != members.end(); ++q) + if(optional) + { + if(_variableLength) + { + is->skip(4); + } + else + { + is->skipSize(); + } + } + + for(DataMemberList::const_iterator q = members.begin(); q != members.end(); ++q) { DataMemberPtr member = *q; - member->type->unmarshal(is, member, p.get(), 0, &member->metaData); + member->type->unmarshal(is, member, p.get(), 0, false, &member->metaData); } cb->unmarshaled(p.get(), target, closure); @@ -1057,7 +1305,7 @@ IcePy::StructInfo::print(PyObject* value, IceUtilInternal::Output& out, PrintObj return; } out.sb(); - for(DataMemberList::iterator q = members.begin(); q != members.end(); ++q) + for(DataMemberList::const_iterator q = members.begin(); q != members.end(); ++q) { DataMemberPtr member = *q; char* memberName = const_cast<char*>(member->name.c_str()); @@ -1078,16 +1326,32 @@ IcePy::StructInfo::print(PyObject* value, IceUtilInternal::Output& out, PrintObj void IcePy::StructInfo::destroy() { - for(DataMemberList::iterator p = members.begin(); p != members.end(); ++p) + for(DataMemberList::const_iterator p = members.begin(); p != members.end(); ++p) { (*p)->type->destroy(); } - members.clear(); + const_cast<DataMemberList&>(members).clear(); } // // SequenceInfo implementation. // +IcePy::SequenceInfo::SequenceInfo(const string& ident, PyObject* m, PyObject* t) : + id(ident) +{ + assert(PyTuple_Check(m)); + + vector<string> metaData; +#ifndef NDEBUG + bool b = +#endif + tupleToStringSeq(m, metaData); + assert(b); + + const_cast<SequenceMappingPtr&>(mapping) = new SequenceMapping(metaData); + const_cast<TypeInfoPtr&>(elementType) = getType(t); +} + string IcePy::SequenceInfo::getId() const { @@ -1106,53 +1370,137 @@ IcePy::SequenceInfo::usesClasses() return elementType->usesClasses(); } +bool +IcePy::SequenceInfo::variableLength() const +{ + return true; +} + +int +IcePy::SequenceInfo::wireSize() const +{ + return 1; +} + +Ice::OptionalType +IcePy::SequenceInfo::optionalType() const +{ + return elementType->variableLength() ? Ice::OptionalTypeFSize : Ice::OptionalTypeVSize; +} + void -IcePy::SequenceInfo::marshal(PyObject* p, const Ice::OutputStreamPtr& os, ObjectMap* objectMap, +IcePy::SequenceInfo::marshal(PyObject* p, const Ice::OutputStreamPtr& os, ObjectMap* objectMap, bool optional, const Ice::StringSeq* metaData) { - if(p == Py_None) + PrimitiveInfoPtr pi = PrimitiveInfoPtr::dynamicCast(elementType); + + if(optional) { - os->writeSize(0); - return; + if(elementType->variableLength()) + { + os->startSize(); + } + else if(elementType->wireSize() > 1) + { + // + // Determine the sequence size. + // + Py_ssize_t sz = 0; + if(p != Py_None) + { + const void* buf = 0; + if(PyObject_AsReadBuffer(p, &buf, &sz) == 0) + { + if(pi->kind == PrimitiveInfo::KindString) + { + PyErr_Format(PyExc_ValueError, STRCAST("expected sequence value")); + throw AbortMarshaling(); + } + } + else + { + PyErr_Clear(); // PyObject_AsReadBuffer sets an exception on failure. + + PyObjectHandle fs; + if(pi) + { + fs = getSequence(pi, p); + } + else + { + fs = PySequence_Fast(p, STRCAST("expected a sequence value")); + } + if(!fs.get()) + { + assert(PyErr_Occurred()); + return; + } + sz = PySequence_Fast_GET_SIZE(fs.get()); + } + } + + os->writeSize(sz == 0 ? 1 : sz * elementType->wireSize() + (sz > 254 ? 5 : 1)); + } } - PrimitiveInfoPtr pi = PrimitiveInfoPtr::dynamicCast(elementType); - if(pi) + if(p == Py_None) { - marshalPrimitiveSequence(pi, p, os); - return; + os->writeSize(0); } - - PyObjectHandle fastSeq = PySequence_Fast(p, STRCAST("expected a sequence value")); - if(!fastSeq.get()) + else if(pi) { - return; + marshalPrimitiveSequence(pi, p, os); } - - Py_ssize_t sz = PySequence_Fast_GET_SIZE(fastSeq.get()); - os->writeSize(static_cast<int>(sz)); - for(Py_ssize_t i = 0; i < sz; ++i) + else { - PyObject* item = PySequence_Fast_GET_ITEM(fastSeq.get(), i); - if(!item) + PyObjectHandle fastSeq = PySequence_Fast(p, STRCAST("expected a sequence value")); + if(!fastSeq.get()) { - assert(PyErr_Occurred()); - throw AbortMarshaling(); + return; } - if(!elementType->validate(item)) + + Py_ssize_t sz = PySequence_Fast_GET_SIZE(fastSeq.get()); + os->writeSize(static_cast<int>(sz)); + for(Py_ssize_t i = 0; i < sz; ++i) { - PyErr_Format(PyExc_ValueError, STRCAST("invalid value for element %d of `%s'"), static_cast<int>(i), - const_cast<char*>(id.c_str())); - throw AbortMarshaling(); + PyObject* item = PySequence_Fast_GET_ITEM(fastSeq.get(), i); + if(!item) + { + assert(PyErr_Occurred()); + throw AbortMarshaling(); + } + if(!elementType->validate(item)) + { + PyErr_Format(PyExc_ValueError, STRCAST("invalid value for element %d of `%s'"), static_cast<int>(i), + const_cast<char*>(id.c_str())); + throw AbortMarshaling(); + } + elementType->marshal(item, os, objectMap, false); } - elementType->marshal(item, os, objectMap); + } + + if(optional && elementType->variableLength()) + { + os->endSize(); } } void IcePy::SequenceInfo::unmarshal(const Ice::InputStreamPtr& is, const UnmarshalCallbackPtr& cb, PyObject* target, - void* closure, const Ice::StringSeq* metaData) + void* closure, bool optional, const Ice::StringSeq* metaData) { + if(optional) + { + if(elementType->variableLength()) + { + is->skip(4); + } + else if(elementType->wireSize() > 1) + { + is->skipSize(); + } + } + // // Determine the mapping to use for this sequence. Highest priority is given // to the metaData argument, otherwise we use the mapping of the sequence @@ -1195,7 +1543,7 @@ IcePy::SequenceInfo::unmarshal(const Ice::InputStreamPtr& is, const UnmarshalCal for(Ice::Int i = 0; i < sz; ++i) { void* cl = reinterpret_cast<void*>(i); - elementType->unmarshal(is, sm, result.get(), cl); + elementType->unmarshal(is, sm, result.get(), cl, false); } cb->unmarshaled(result.get(), target, closure); @@ -1245,8 +1593,41 @@ IcePy::SequenceInfo::destroy() if(elementType) { elementType->destroy(); - elementType = 0; + const_cast<TypeInfoPtr&>(elementType) = 0; + } +} + +PyObject* +IcePy::SequenceInfo::getSequence(const PrimitiveInfoPtr& pi, PyObject* p) +{ + PyObjectHandle fs; + + if(pi->kind == PrimitiveInfo::KindByte) + { +#if PY_VERSION_HEX >= 0x03000000 + // + // For sequence<byte>, accept a bytes object or a sequence. + // + if(!PyBytes_Check(p)) + { + fs = PySequence_Fast(p, STRCAST("expected a bytes, sequence, or buffer value")); + } +#else + // + // For sequence<byte>, accept a string or a sequence. + // + if(!checkString(p)) + { + fs = PySequence_Fast(p, STRCAST("expected a string, sequence, or buffer value")); + } +#endif + } + else + { + fs = PySequence_Fast(p, STRCAST("expected a sequence or buffer value")); } + + return fs.release(); } void @@ -1306,48 +1687,16 @@ IcePy::SequenceInfo::marshalPrimitiveSequence(const PrimitiveInfoPtr& pi, PyObje } return; } + else + { + PyErr_Clear(); // PyObject_AsReadBuffer sets an exception on failure. + } - PyErr_Clear(); // PyObject_AsReadBuffer sets an exception on failure. - - PyObjectHandle fs; - if(!buf) + PyObjectHandle fs = getSequence(pi, p); + if(!fs.get()) { - if(pi->kind == PrimitiveInfo::KindByte) - { -#if PY_VERSION_HEX >= 0x03000000 - // - // For sequence<byte>, accept a bytes object or a sequence. - // - if(!PyBytes_Check(p)) - { - fs = PySequence_Fast(p, STRCAST("expected a bytes, sequence, or buffer value")); - if(!fs.get()) - { - return; - } - } -#else - // - // For sequence<byte>, accept a string or a sequence. - // - if(!checkString(p)) - { - fs = PySequence_Fast(p, STRCAST("expected a string, sequence, or buffer value")); - if(!fs.get()) - { - return; - } - } -#endif - } - else - { - fs = PySequence_Fast(p, STRCAST("expected a sequence or buffer value")); - if(!fs.get()) - { - return; - } - } + assert(PyErr_Occurred()); + return; } switch(pi->kind) @@ -1896,6 +2245,12 @@ IcePy::SequenceInfo::SequenceMapping::setItem(PyObject* cont, int i, PyObject* v // // CustomInfo implementation. // +IcePy::CustomInfo::CustomInfo(const string& ident, PyObject* t) : + id(ident), pythonType(t) +{ + assert(PyType_Check(t)); +} + string IcePy::CustomInfo::getId() const { @@ -1914,8 +2269,26 @@ IcePy::CustomInfo::usesClasses() return false; } +bool +IcePy::CustomInfo::variableLength() const +{ + return true; +} + +int +IcePy::CustomInfo::wireSize() const +{ + return 1; +} + +Ice::OptionalType +IcePy::CustomInfo::optionalType() const +{ + return Ice::OptionalTypeVSize; +} + void -IcePy::CustomInfo::marshal(PyObject* p, const Ice::OutputStreamPtr& os, ObjectMap* objectMap, +IcePy::CustomInfo::marshal(PyObject* p, const Ice::OutputStreamPtr& os, ObjectMap* objectMap, bool, const Ice::StringSeq* metaData) { assert(PyObject_IsInstance(p, pythonType.get()) == 1); // validate() should have caught this. @@ -1951,7 +2324,7 @@ IcePy::CustomInfo::marshal(PyObject* p, const Ice::OutputStreamPtr& os, ObjectMa void IcePy::CustomInfo::unmarshal(const Ice::InputStreamPtr& is, const UnmarshalCallbackPtr& cb, PyObject* target, - void* closure, const Ice::StringSeq* metaData) + void* closure, bool, const Ice::StringSeq* metaData) { // // Unmarshal the raw byte sequence. @@ -2040,6 +2413,16 @@ IcePy::CustomInfo::destroy() // // DictionaryInfo implementation. // +IcePy::DictionaryInfo::DictionaryInfo(const string& ident, PyObject* kt, PyObject* vt) : + id(ident) +{ + const_cast<TypeInfoPtr&>(keyType) = getType(kt); + const_cast<TypeInfoPtr&>(valueType) = getType(vt); + + _variableLength = keyType->variableLength() || valueType->variableLength(); + _wireSize = keyType->wireSize() + valueType->wireSize(); +} + string IcePy::DictionaryInfo::getId() const { @@ -2058,49 +2441,99 @@ IcePy::DictionaryInfo::usesClasses() return valueType->usesClasses(); } +bool +IcePy::DictionaryInfo::variableLength() const +{ + return true; +} + +int +IcePy::DictionaryInfo::wireSize() const +{ + return 1; +} + +Ice::OptionalType +IcePy::DictionaryInfo::optionalType() const +{ + return _variableLength ? Ice::OptionalTypeFSize : Ice::OptionalTypeVSize; +} + void -IcePy::DictionaryInfo::marshal(PyObject* p, const Ice::OutputStreamPtr& os, ObjectMap* objectMap, +IcePy::DictionaryInfo::marshal(PyObject* p, const Ice::OutputStreamPtr& os, ObjectMap* objectMap, bool optional, const Ice::StringSeq*) { - if(p == Py_None) - { - os->writeSize(0); - return; - } - else if(!PyDict_Check(p)) + if(p != Py_None && !PyDict_Check(p)) { PyErr_Format(PyExc_ValueError, STRCAST("expected dictionary value")); throw AbortMarshaling(); } - Py_ssize_t sz = PyDict_Size(p); - os->writeSize(static_cast<int>(sz)); + Py_ssize_t sz = p == Py_None ? 0 : PyDict_Size(p); - Py_ssize_t pos = 0; - PyObject* key; - PyObject* value; - while(PyDict_Next(p, &pos, &key, &value)) + if(optional) { - if(!keyType->validate(key)) + if(_variableLength) { - PyErr_Format(PyExc_ValueError, STRCAST("invalid key in `%s' element"), const_cast<char*>(id.c_str())); - throw AbortMarshaling(); + os->startSize(); } - keyType->marshal(key, os, objectMap); + else + { + os->writeSize(sz == 0 ? 1 : sz * _wireSize + (sz > 254 ? 5 : 1)); + } + } + + if(p == Py_None) + { + os->writeSize(0); + } + else + { + os->writeSize(static_cast<int>(sz)); - if(!valueType->validate(value)) + Py_ssize_t pos = 0; + PyObject* key; + PyObject* value; + while(PyDict_Next(p, &pos, &key, &value)) { - PyErr_Format(PyExc_ValueError, STRCAST("invalid value in `%s' element"), const_cast<char*>(id.c_str())); - throw AbortMarshaling(); + if(!keyType->validate(key)) + { + PyErr_Format(PyExc_ValueError, STRCAST("invalid key in `%s' element"), const_cast<char*>(id.c_str())); + throw AbortMarshaling(); + } + keyType->marshal(key, os, objectMap, false); + + if(!valueType->validate(value)) + { + PyErr_Format(PyExc_ValueError, STRCAST("invalid value in `%s' element"), const_cast<char*>(id.c_str())); + throw AbortMarshaling(); + } + valueType->marshal(value, os, objectMap, false); } - valueType->marshal(value, os, objectMap); + } + + if(optional && _variableLength) + { + os->endSize(); } } void IcePy::DictionaryInfo::unmarshal(const Ice::InputStreamPtr& is, const UnmarshalCallbackPtr& cb, PyObject* target, - void* closure, const Ice::StringSeq*) + void* closure, bool optional, const Ice::StringSeq*) { + if(optional) + { + if(_variableLength) + { + is->skip(4); + } + else + { + is->skipSize(); + } + } + PyObjectHandle p = PyDict_New(); if(!p.get()) { @@ -2118,7 +2551,7 @@ IcePy::DictionaryInfo::unmarshal(const Ice::InputStreamPtr& is, const UnmarshalC // A dictionary key cannot be a class (or contain one), so the key must be // available immediately. // - keyType->unmarshal(is, keyCB, 0, 0); + keyType->unmarshal(is, keyCB, 0, 0, false); assert(keyCB->key.get()); // @@ -2137,7 +2570,7 @@ IcePy::DictionaryInfo::unmarshal(const Ice::InputStreamPtr& is, const UnmarshalC // so we pass it the key. // void* cl = reinterpret_cast<void*>(keyCB->key.get()); - valueType->unmarshal(is, this, p.get(), cl); + valueType->unmarshal(is, this, p.get(), cl, false); } cb->unmarshaled(p.get(), target, closure); @@ -2218,6 +2651,46 @@ IcePy::DictionaryInfo::destroy() // // ClassInfo implementation. // +IcePy::ClassInfo::ClassInfo(const string& ident) : + id(ident), isAbstract(false), preserve(false), defined(false) +{ + const_cast<PyObjectHandle&>(typeObj) = createType(this); +} + +void +IcePy::ClassInfo::define(PyObject* t, bool abstr, bool pres, PyObject* b, PyObject* i, PyObject* m) +{ + assert(PyType_Check(t)); + assert(PyTuple_Check(i)); + assert(PyTuple_Check(m)); + + const_cast<bool&>(isAbstract) = abstr; + const_cast<bool&>(preserve) = pres; + + if(b != Py_None) + { + const_cast<ClassInfoPtr&>(base) = ClassInfoPtr::dynamicCast(getType(b)); + assert(base); + } + + Py_ssize_t n, sz; + sz = PyTuple_GET_SIZE(i); + for(n = 0; n < sz; ++n) + { + PyObject* o = PyTuple_GET_ITEM(i, n); + ClassInfoPtr iface = ClassInfoPtr::dynamicCast(getType(o)); + assert(iface); + const_cast<ClassInfoList&>(interfaces).push_back(iface); + } + + convertDataMembers(m, const_cast<DataMemberList&>(members), const_cast<DataMemberList&>(optionalMembers), true); + + const_cast<PyObjectHandle&>(pythonType) = t; + Py_INCREF(t); + + const_cast<bool&>(defined) = true; +} + string IcePy::ClassInfo::getId() const { @@ -2236,8 +2709,26 @@ IcePy::ClassInfo::usesClasses() return true; } +bool +IcePy::ClassInfo::variableLength() const +{ + return true; +} + +int +IcePy::ClassInfo::wireSize() const +{ + return 1; +} + +Ice::OptionalType +IcePy::ClassInfo::optionalType() const +{ + return Ice::OptionalTypeSize; +} + void -IcePy::ClassInfo::marshal(PyObject* p, const Ice::OutputStreamPtr& os, ObjectMap* objectMap, +IcePy::ClassInfo::marshal(PyObject* p, const Ice::OutputStreamPtr& os, ObjectMap* objectMap, bool, const Ice::StringSeq*) { if(!pythonType.get()) @@ -2285,7 +2776,7 @@ IcePy::ClassInfo::marshal(PyObject* p, const Ice::OutputStreamPtr& os, ObjectMap void IcePy::ClassInfo::unmarshal(const Ice::InputStreamPtr& is, const UnmarshalCallbackPtr& cb, PyObject* target, - void* closure, const Ice::StringSeq*) + void* closure, bool, const Ice::StringSeq*) { if(!pythonType.get()) { @@ -2347,18 +2838,18 @@ IcePy::ClassInfo::print(PyObject* value, IceUtilInternal::Output& out, PrintObje void IcePy::ClassInfo::destroy() { - base = 0; - interfaces.clear(); + const_cast<ClassInfoPtr&>(base) = 0; + const_cast<ClassInfoList&>(interfaces).clear(); if(!members.empty()) { DataMemberList ml = members; - members.clear(); + const_cast<DataMemberList&>(members).clear(); for(DataMemberList::iterator p = ml.begin(); p != ml.end(); ++p) { (*p)->type->destroy(); } } - typeObj = 0; // Break circular reference. + const_cast<PyObjectHandle&>(typeObj) = 0; // Break circular reference. } void @@ -2369,7 +2860,9 @@ IcePy::ClassInfo::printMembers(PyObject* value, IceUtilInternal::Output& out, Pr base->printMembers(value, out, history); } - for(DataMemberList::iterator q = members.begin(); q != members.end(); ++q) + DataMemberList::const_iterator q; + + for(q = members.begin(); q != members.end(); ++q) { DataMemberPtr member = *q; char* memberName = const_cast<char*>(member->name.c_str()); @@ -2384,11 +2877,40 @@ IcePy::ClassInfo::printMembers(PyObject* value, IceUtilInternal::Output& out, Pr member->type->print(attr.get(), out, history); } } + + for(q = optionalMembers.begin(); q != optionalMembers.end(); ++q) + { + DataMemberPtr member = *q; + char* memberName = const_cast<char*>(member->name.c_str()); + PyObjectHandle attr = PyObject_GetAttrString(value, memberName); + out << nl << member->name << " = "; + if(!attr.get() || attr.get() == Unset) + { + out << "<not defined>"; + } + else + { + member->type->print(attr.get(), out, history); + } + } } // // ProxyInfo implementation. // +IcePy::ProxyInfo::ProxyInfo(const string& ident) : + id(ident) +{ + const_cast<PyObjectHandle&>(typeObj) = createType(this); +} + +void +IcePy::ProxyInfo::define(PyObject* t) +{ + const_cast<PyObjectHandle&>(pythonType) = t; + Py_INCREF(t); +} + string IcePy::ProxyInfo::getId() const { @@ -2401,9 +2923,32 @@ IcePy::ProxyInfo::validate(PyObject* val) return val == Py_None || PyObject_IsInstance(val, pythonType.get()) == 1; } +bool +IcePy::ProxyInfo::variableLength() const +{ + return true; +} + +int +IcePy::ProxyInfo::wireSize() const +{ + return 1; +} + +Ice::OptionalType +IcePy::ProxyInfo::optionalType() const +{ + return Ice::OptionalTypeFSize; +} + void -IcePy::ProxyInfo::marshal(PyObject* p, const Ice::OutputStreamPtr& os, ObjectMap*, const Ice::StringSeq*) +IcePy::ProxyInfo::marshal(PyObject* p, const Ice::OutputStreamPtr& os, ObjectMap*, bool optional, const Ice::StringSeq*) { + if(optional) + { + os->startSize(); + } + if(p == Py_None) { os->write(Ice::ObjectPrx()); @@ -2416,12 +2961,22 @@ IcePy::ProxyInfo::marshal(PyObject* p, const Ice::OutputStreamPtr& os, ObjectMap { assert(false); // validate() should have caught this. } + + if(optional) + { + os->endSize(); + } } void IcePy::ProxyInfo::unmarshal(const Ice::InputStreamPtr& is, const UnmarshalCallbackPtr& cb, PyObject* target, - void* closure, const Ice::StringSeq*) + void* closure, bool optional, const Ice::StringSeq*) { + if(optional) + { + is->skip(4); + } + Ice::ObjectPrx proxy; is->read(proxy); @@ -2469,7 +3024,7 @@ IcePy::ProxyInfo::print(PyObject* value, IceUtilInternal::Output& out, PrintObje void IcePy::ProxyInfo::destroy() { - typeObj = 0; // Break circular reference. + const_cast<PyObjectHandle&>(typeObj) = 0; // Break circular reference. } // @@ -2524,38 +3079,64 @@ IcePy::ObjectWriter::write(const Ice::OutputStreamPtr& os) const os->startObject(slicedData); - ClassInfoPtr info = _info; - while(info) + if(_info->id != "::Ice::UnknownSlicedObject") { - os->startSlice(info->id, !info->base); - for(DataMemberList::iterator q = info->members.begin(); q != info->members.end(); ++q) + ClassInfoPtr info = _info; + while(info) { - DataMemberPtr member = *q; - char* memberName = const_cast<char*>(member->name.c_str()); + os->startSlice(info->id, !info->base); + + writeMembers(os, info->members); + writeMembers(os, info->optionalMembers); // The optional members have already been sorted by tag. + + os->endSlice(); + + info = info->base; + } + } + + os->endObject(); +} - PyObjectHandle val = PyObject_GetAttrString(_object, memberName); - if(!val.get()) +void +IcePy::ObjectWriter::writeMembers(const Ice::OutputStreamPtr& os, const DataMemberList& members) const +{ + for(DataMemberList::const_iterator q = members.begin(); q != members.end(); ++q) + { + DataMemberPtr member = *q; + + char* memberName = const_cast<char*>(member->name.c_str()); + + PyObjectHandle val = PyObject_GetAttrString(_object, memberName); + if(!val.get()) + { + if(member->optional) { - PyErr_Format(PyExc_AttributeError, STRCAST("no member `%s' found in %s value"), memberName, - const_cast<char*>(_info->id.c_str())); - throw AbortMarshaling(); + PyErr_Clear(); + continue; } - - if(!member->type->validate(val.get())) + else { - PyErr_Format(PyExc_ValueError, STRCAST("invalid value for %s member `%s'"), - const_cast<char*>(_info->id.c_str()), memberName); + PyErr_Format(PyExc_AttributeError, STRCAST("no member `%s' found in %s value"), memberName, + const_cast<char*>(_info->id.c_str())); throw AbortMarshaling(); } + } + else if(member->optional && + (val.get() == Unset || !os->writeOptional(member->tag, member->type->optionalType()))) + { + continue; + } - member->type->marshal(val.get(), os, _map, &member->metaData); + if(!member->type->validate(val.get())) + { + PyErr_Format(PyExc_ValueError, STRCAST("invalid value for %s member `%s'"), + const_cast<char*>(_info->id.c_str()), memberName); + throw AbortMarshaling(); } - os->endSlice(); - info = info->base; + member->type->marshal(val.get(), os, _map, member->optional, &member->metaData); } - - os->endObject(); } // @@ -2591,20 +3172,43 @@ IcePy::ObjectReader::read(const Ice::InputStreamPtr& is) { is->startObject(); + const bool unknown = _info->id == "::Ice::UnknownSlicedObject"; + // // Unmarshal the slices of a user-defined class. // - if(_info->id != Ice::Object::ice_staticId()) + if(!unknown && _info->id != Ice::Object::ice_staticId()) { ClassInfoPtr info = _info; while(info) { is->startSlice(); - for(DataMemberList::iterator p = info->members.begin(); p != info->members.end(); ++p) + + DataMemberList::const_iterator p; + + for(p = info->members.begin(); p != info->members.end(); ++p) { DataMemberPtr member = *p; - member->type->unmarshal(is, member, _object, 0, &member->metaData); + member->type->unmarshal(is, member, _object, 0, false, &member->metaData); } + + // + // The optional members have already been sorted by tag. + // + for(p = info->optionalMembers.begin(); p != info->optionalMembers.end(); ++p) + { + DataMemberPtr member = *p; + if(is->readOptional(member->tag, member->type->optionalType())) + { + member->type->unmarshal(is, member, _object, 0, true, &member->metaData); + } + else if(PyObject_SetAttrString(_object, const_cast<char*>(member->name.c_str()), Unset) < 0) + { + assert(PyErr_Occurred()); + throw AbortMarshaling(); + } + } + is->endSlice(); info = info->base; @@ -2618,6 +3222,21 @@ IcePy::ObjectReader::read(const Ice::InputStreamPtr& is) SlicedDataUtil* util = reinterpret_cast<SlicedDataUtil*>(is->closure()); assert(util); util->add(this); + + // + // Define the "unknownTypeId" member for an instance of UnknownSlicedObject. + // + if(unknown) + { + assert(!_slicedData->slices.empty()); + + PyObjectHandle typeId = createString(_slicedData->slices[0]->typeId); + if(!typeId.get() || PyObject_SetAttrString(_object, STRCAST("unknownTypeId"), typeId.get()) < 0) + { + assert(PyErr_Occurred()); + throw AbortMarshaling(); + } + } } } @@ -2683,9 +3302,9 @@ IcePy::ReadObjectCallback::invoke(const Ice::ObjectPtr& p) assert(reader); // - // Verify that the unmarshaled object is compatible with the formal type. + // Verify that the object's type is compatible with the formal type. // - PyObject* obj = reader->getObject(); + PyObject* obj = reader->getObject(); // Borrowed reference. if(!PyObject_IsInstance(obj, _info->pythonType.get())) { Ice::UnexpectedObjectException ex(__FILE__, __LINE__); @@ -2731,34 +3350,58 @@ IcePy::ExceptionInfo::marshal(PyObject* p, const Ice::OutputStreamPtr& os, Objec while(info) { os->startSlice(info->id, !info->base); - for(DataMemberList::iterator q = info->members.begin(); q != info->members.end(); ++q) - { - DataMemberPtr member = *q; - char* memberName = const_cast<char*>(member->name.c_str()); - PyObjectHandle val = PyObject_GetAttrString(p, memberName); - if(!val.get()) + writeMembers(p, os, info->members, objectMap); + writeMembers(p, os, info->optionalMembers, objectMap); // The optional members have already been sorted by tag. + + os->endSlice(); + + info = info->base; + } + + os->endException(); +} + +void +IcePy::ExceptionInfo::writeMembers(PyObject* p, const Ice::OutputStreamPtr& os, const DataMemberList& members, + ObjectMap* objectMap) const +{ + for(DataMemberList::const_iterator q = members.begin(); q != members.end(); ++q) + { + DataMemberPtr member = *q; + + char* memberName = const_cast<char*>(member->name.c_str()); + + PyObjectHandle val = PyObject_GetAttrString(p, memberName); + if(!val.get()) + { + if(member->optional) { - PyErr_Format(PyExc_AttributeError, STRCAST("no member `%s' found in %s value"), memberName, - const_cast<char*>(id.c_str())); - throw AbortMarshaling(); + PyErr_Clear(); + continue; } - - if(!member->type->validate(val.get())) + else { - PyErr_Format(PyExc_ValueError, STRCAST("invalid value for %s member `%s'"), - const_cast<char*>(id.c_str()), memberName); + PyErr_Format(PyExc_AttributeError, STRCAST("no member `%s' found in %s value"), memberName, + const_cast<char*>(id.c_str())); throw AbortMarshaling(); } + } + else if(member->optional && + (val.get() == Unset || !os->writeOptional(member->tag, member->type->optionalType()))) + { + continue; + } - member->type->marshal(val.get(), os, objectMap, &member->metaData); + if(!member->type->validate(val.get())) + { + PyErr_Format(PyExc_ValueError, STRCAST("invalid value for %s member `%s'"), + const_cast<char*>(id.c_str()), memberName); + throw AbortMarshaling(); } - os->endSlice(); - info = info->base; + member->type->marshal(val.get(), os, objectMap, member->optional, &member->metaData); } - - os->endException(); } PyObject* @@ -2770,11 +3413,32 @@ IcePy::ExceptionInfo::unmarshal(const Ice::InputStreamPtr& is) while(info) { is->startSlice(); - for(DataMemberList::iterator q = info->members.begin(); q != info->members.end(); ++q) + + DataMemberList::iterator q; + + for(q = info->members.begin(); q != info->members.end(); ++q) + { + DataMemberPtr member = *q; + member->type->unmarshal(is, member, p.get(), 0, false, &member->metaData); + } + + // + // The optional members have already been sorted by tag. + // + for(q = info->optionalMembers.begin(); q != info->optionalMembers.end(); ++q) { DataMemberPtr member = *q; - member->type->unmarshal(is, member, p.get(), 0, &member->metaData); + if(is->readOptional(member->tag, member->type->optionalType())) + { + member->type->unmarshal(is, member, p.get(), 0, true, &member->metaData); + } + else if(PyObject_SetAttrString(p.get(), const_cast<char*>(member->name.c_str()), Unset) < 0) + { + assert(PyErr_Occurred()); + throw AbortMarshaling(); + } } + is->endSlice(); info = info->base; @@ -2815,7 +3479,7 @@ IcePy::ExceptionInfo::printMembers(PyObject* value, IceUtilInternal::Output& out char* memberName = const_cast<char*>(member->name.c_str()); PyObjectHandle attr = PyObject_GetAttrString(value, memberName); out << nl << member->name << " = "; - if(!attr.get()) + if(!attr.get() || attr.get() == Unset) { out << "<not defined>"; } @@ -2871,7 +3535,7 @@ IcePy::ExceptionWriter::ice_name() const return _info->id; } -IcePy::ExceptionWriter* +Ice::UserException* IcePy::ExceptionWriter::ice_clone() const { return new ExceptionWriter(*this); @@ -2931,7 +3595,7 @@ IcePy::ExceptionReader::ice_name() const return _info->id; } -IcePy::ExceptionReader* +Ice::UserException* IcePy::ExceptionReader::ice_clone() const { assert(false); @@ -3081,6 +3745,9 @@ PyTypeObject ExceptionInfoType = 0, /* tp_is_gc */ }; + +PyObject* Unset; + } bool @@ -3106,8 +3773,7 @@ IcePy::initTypes(PyObject* module) return false; } - PrimitiveInfoPtr boolType = new PrimitiveInfo; - boolType->kind = PrimitiveInfo::KindBool; + PrimitiveInfoPtr boolType = new PrimitiveInfo(PrimitiveInfo::KindBool); PyObjectHandle boolTypeObj = createType(boolType); if(PyModule_AddObject(module, STRCAST("_t_bool"), boolTypeObj.get()) < 0) { @@ -3115,8 +3781,7 @@ IcePy::initTypes(PyObject* module) } boolTypeObj.release(); // PyModule_AddObject steals a reference. - PrimitiveInfoPtr byteType = new PrimitiveInfo; - byteType->kind = PrimitiveInfo::KindByte; + PrimitiveInfoPtr byteType = new PrimitiveInfo(PrimitiveInfo::KindByte); PyObjectHandle byteTypeObj = createType(byteType); if(PyModule_AddObject(module, STRCAST("_t_byte"), byteTypeObj.get()) < 0) { @@ -3124,8 +3789,7 @@ IcePy::initTypes(PyObject* module) } byteTypeObj.release(); // PyModule_AddObject steals a reference. - PrimitiveInfoPtr shortType = new PrimitiveInfo; - shortType->kind = PrimitiveInfo::KindShort; + PrimitiveInfoPtr shortType = new PrimitiveInfo(PrimitiveInfo::KindShort); PyObjectHandle shortTypeObj = createType(shortType); if(PyModule_AddObject(module, STRCAST("_t_short"), shortTypeObj.get()) < 0) { @@ -3133,8 +3797,7 @@ IcePy::initTypes(PyObject* module) } shortTypeObj.release(); // PyModule_AddObject steals a reference. - PrimitiveInfoPtr intType = new PrimitiveInfo; - intType->kind = PrimitiveInfo::KindInt; + PrimitiveInfoPtr intType = new PrimitiveInfo(PrimitiveInfo::KindInt); PyObjectHandle intTypeObj = createType(intType); if(PyModule_AddObject(module, STRCAST("_t_int"), intTypeObj.get()) < 0) { @@ -3142,8 +3805,7 @@ IcePy::initTypes(PyObject* module) } intTypeObj.release(); // PyModule_AddObject steals a reference. - PrimitiveInfoPtr longType = new PrimitiveInfo; - longType->kind = PrimitiveInfo::KindLong; + PrimitiveInfoPtr longType = new PrimitiveInfo(PrimitiveInfo::KindLong); PyObjectHandle longTypeObj = createType(longType); if(PyModule_AddObject(module, STRCAST("_t_long"), longTypeObj.get()) < 0) { @@ -3151,8 +3813,7 @@ IcePy::initTypes(PyObject* module) } longTypeObj.release(); // PyModule_AddObject steals a reference. - PrimitiveInfoPtr floatType = new PrimitiveInfo; - floatType->kind = PrimitiveInfo::KindFloat; + PrimitiveInfoPtr floatType = new PrimitiveInfo(PrimitiveInfo::KindFloat); PyObjectHandle floatTypeObj = createType(floatType); if(PyModule_AddObject(module, STRCAST("_t_float"), floatTypeObj.get()) < 0) { @@ -3160,8 +3821,7 @@ IcePy::initTypes(PyObject* module) } floatTypeObj.release(); // PyModule_AddObject steals a reference. - PrimitiveInfoPtr doubleType = new PrimitiveInfo; - doubleType->kind = PrimitiveInfo::KindDouble; + PrimitiveInfoPtr doubleType = new PrimitiveInfo(PrimitiveInfo::KindDouble); PyObjectHandle doubleTypeObj = createType(doubleType); if(PyModule_AddObject(module, STRCAST("_t_double"), doubleTypeObj.get()) < 0) { @@ -3169,8 +3829,7 @@ IcePy::initTypes(PyObject* module) } doubleTypeObj.release(); // PyModule_AddObject steals a reference. - PrimitiveInfoPtr stringType = new PrimitiveInfo; - stringType->kind = PrimitiveInfo::KindString; + PrimitiveInfoPtr stringType = new PrimitiveInfo(PrimitiveInfo::KindString); PyObjectHandle stringTypeObj = createType(stringType); if(PyModule_AddObject(module, STRCAST("_t_string"), stringTypeObj.get()) < 0) { @@ -3178,6 +3837,14 @@ IcePy::initTypes(PyObject* module) } stringTypeObj.release(); // PyModule_AddObject steals a reference. + PyObjectHandle unsetObj = PyObject_New(PyObject, &PyBaseObject_Type); + if(PyModule_AddObject(module, STRCAST("Unset"), unsetObj.get()) < 0) + { + return false; + } + Unset = unsetObj.get(); // Borrow a reference to the object, which is held by the IcePy module. + unsetObj.release(); // PyModule_AddObject steals a reference. + return true; } @@ -3225,69 +3892,27 @@ IcePy_defineEnum(PyObject*, PyObject* args) { char* id; PyObject* type; - PyObject* meta; + PyObject* meta; // Not currently used. PyObject* enumerators; if(!PyArg_ParseTuple(args, STRCAST("sOOO"), &id, &type, &meta, &enumerators)) { return 0; } - assert(PyType_Check(type)); assert(PyTuple_Check(meta)); - assert(PyTuple_Check(enumerators)); - EnumInfoPtr info = new EnumInfo; - info->id = id; - info->pythonType = type; - Py_INCREF(type); - - Py_ssize_t sz = PyTuple_GET_SIZE(enumerators); - for(Py_ssize_t i = 0; i < sz; ++i) - { - PyObjectHandle e = PyTuple_GET_ITEM(enumerators, i); - Py_INCREF(e.get()); - assert(PyObject_IsInstance(e.get(), type)); - info->enumerators.push_back(e); - } + EnumInfoPtr info = new EnumInfo(id, type, enumerators); return createType(info); } -static void -convertDataMembers(PyObject* members, DataMemberList& l) -{ - Py_ssize_t sz = PyTuple_GET_SIZE(members); - for(Py_ssize_t i = 0; i < sz; ++i) - { - PyObject* m = PyTuple_GET_ITEM(members, i); - assert(PyTuple_Check(m)); - assert(PyTuple_GET_SIZE(m) == 3); - - PyObject* name = PyTuple_GET_ITEM(m, 0); // Member name. - assert(checkString(name)); - PyObject* meta = PyTuple_GET_ITEM(m, 1); // Member metadata. - assert(PyTuple_Check(meta)); - PyObject* t = PyTuple_GET_ITEM(m, 2); // Member type. - - DataMemberPtr member = new DataMember; - member->name = getString(name); -#ifndef NDEBUG - bool b = -#endif - tupleToStringSeq(meta, member->metaData); - assert(b); - member->type = getType(t); - l.push_back(member); - } -} - extern "C" PyObject* IcePy_defineStruct(PyObject*, PyObject* args) { char* id; PyObject* type; - PyObject* meta; + PyObject* meta; // Not currently used. PyObject* members; if(!PyArg_ParseTuple(args, STRCAST("sOOO"), &id, &type, &meta, &members)) { @@ -3298,12 +3923,7 @@ IcePy_defineStruct(PyObject*, PyObject* args) assert(PyTuple_Check(meta)); assert(PyTuple_Check(members)); - StructInfoPtr info = new StructInfo; - info->id = id; - info->pythonType = type; - Py_INCREF(type); - - convertDataMembers(members, info->members); + StructInfoPtr info = new StructInfo(id, type, members); return createType(info); } @@ -3320,19 +3940,7 @@ IcePy_defineSequence(PyObject*, PyObject* args) return 0; } - assert(PyTuple_Check(meta)); - - vector<string> metaData; -#ifndef NDEBUG - bool b = -#endif - tupleToStringSeq(meta, metaData); - assert(b); - - SequenceInfoPtr info = new SequenceInfo; - info->id = id; - info->mapping = new SequenceInfo::SequenceMapping(metaData); - info->elementType = getType(elementType); + SequenceInfoPtr info = new SequenceInfo(id, meta, elementType); return createType(info); } @@ -3348,11 +3956,7 @@ IcePy_defineCustom(PyObject*, PyObject* args) return 0; } - assert(PyType_Check(type)); - - CustomInfoPtr info = new CustomInfo; - info->id = id; - info->pythonType = type; + CustomInfoPtr info = new CustomInfo(id, type); return createType(info); } @@ -3362,7 +3966,7 @@ PyObject* IcePy_defineDictionary(PyObject*, PyObject* args) { char* id; - PyObject* meta; + PyObject* meta; // Not currently used. PyObject* keyType; PyObject* valueType; if(!PyArg_ParseTuple(args, STRCAST("sOOO"), &id, &meta, &keyType, &valueType)) @@ -3372,10 +3976,7 @@ IcePy_defineDictionary(PyObject*, PyObject* args) assert(PyTuple_Check(meta)); - DictionaryInfoPtr info = new DictionaryInfo; - info->id = id; - info->keyType = getType(keyType); - info->valueType = getType(valueType); + DictionaryInfoPtr info = new DictionaryInfo(id, keyType, valueType); return createType(info); } @@ -3396,9 +3997,7 @@ IcePy_declareProxy(PyObject*, PyObject* args) ProxyInfoPtr info = lookupProxyInfo(proxyId); if(!info) { - info = new ProxyInfo; - info->id = proxyId; - info->typeObj = createType(info); + info = new ProxyInfo(proxyId); addProxyInfo(proxyId, info); } @@ -3425,14 +4024,11 @@ IcePy_defineProxy(PyObject*, PyObject* args) ProxyInfoPtr info = lookupProxyInfo(proxyId); if(!info) { - info = new ProxyInfo; - info->id = proxyId; - info->typeObj = createType(info); + info = new ProxyInfo(proxyId); addProxyInfo(proxyId, info); } - info->pythonType = type; - Py_INCREF(type); + info->define(type); Py_INCREF(info->typeObj.get()); return info->typeObj.get(); @@ -3451,10 +4047,7 @@ IcePy_declareClass(PyObject*, PyObject* args) ClassInfoPtr info = lookupClassInfo(id); if(!info) { - info = new ClassInfo; - info->id = id; - info->typeObj = createType(info); - info->defined = false; + info = new ClassInfo(id); addClassInfo(id, info); } @@ -3468,7 +4061,7 @@ IcePy_defineClass(PyObject*, PyObject* args) { char* id; PyObject* type; - PyObject* meta; + PyObject* meta; // Not currently used. int isAbstract; int preserve; PyObject* base; @@ -3480,10 +4073,7 @@ IcePy_defineClass(PyObject*, PyObject* args) return 0; } - assert(PyType_Check(type)); assert(PyTuple_Check(meta)); - assert(PyTuple_Check(interfaces)); - assert(PyTuple_Check(members)); // // A ClassInfo object will already exist for this id if a forward declaration @@ -3493,37 +4083,11 @@ IcePy_defineClass(PyObject*, PyObject* args) ClassInfoPtr info = lookupClassInfo(id); if(!info || info->defined) { - info = new ClassInfo; - info->id = id; - info->typeObj = createType(info); + info = new ClassInfo(id); addClassInfo(id, info); } - info->isAbstract = isAbstract ? true : false; - info->preserve = preserve ? true : false; - - if(base != Py_None) - { - info->base = ClassInfoPtr::dynamicCast(getType(base)); - assert(info->base); - } - - Py_ssize_t i, sz; - sz = PyTuple_GET_SIZE(interfaces); - for(i = 0; i < sz; ++i) - { - PyObject* o = PyTuple_GET_ITEM(interfaces, i); - ClassInfoPtr iface = ClassInfoPtr::dynamicCast(getType(o)); - assert(iface); - info->interfaces.push_back(iface); - } - - convertDataMembers(members, info->members); - - info->pythonType = type; - Py_INCREF(type); - - info->defined = true; + info->define(type, isAbstract ? true : false, preserve ? true : false, base, interfaces, members); Py_INCREF(info->typeObj.get()); return info->typeObj.get(); @@ -3544,11 +4108,7 @@ IcePy_defineException(PyObject*, PyObject* args) return 0; } -#ifdef ICEPY_OLD_EXCEPTIONS - assert(PyClass_Check(type)); -#else assert(PyExceptionClass_Check(type)); -#endif assert(PyTuple_Check(meta)); assert(PyTuple_Check(members)); @@ -3565,15 +4125,7 @@ IcePy_defineException(PyObject*, PyObject* args) info->usesClasses = false; - convertDataMembers(members, info->members); - - for(DataMemberList::iterator p = info->members.begin(); p != info->members.end(); ++p) - { - if(!info->usesClasses) - { - info->usesClasses = (*p)->type->usesClasses(); - } - } + convertDataMembers(members, info->members, info->optionalMembers, true); info->pythonType = type; Py_INCREF(type); diff --git a/py/modules/IcePy/Types.h b/py/modules/IcePy/Types.h index 3334fa25b41..46e07ce3840 100644 --- a/py/modules/IcePy/Types.h +++ b/py/modules/IcePy/Types.h @@ -105,6 +105,10 @@ public: virtual bool usesClasses(); // Default implementation returns false. + virtual bool variableLength() const = 0; + virtual int wireSize() const = 0; + virtual Ice::OptionalType optionalType() const = 0; + virtual void unmarshaled(PyObject*, PyObject*, void*); // Default implementation is assert(false). virtual void destroy(); @@ -119,8 +123,8 @@ public: // The marshal and unmarshal functions can raise Ice exceptions, and may raise // AbortMarshaling if an error occurs. // - virtual void marshal(PyObject*, const Ice::OutputStreamPtr&, ObjectMap*, const Ice::StringSeq* = 0) = 0; - virtual void unmarshal(const Ice::InputStreamPtr&, const UnmarshalCallbackPtr&, PyObject*, void*, + virtual void marshal(PyObject*, const Ice::OutputStreamPtr&, ObjectMap*, bool, const Ice::StringSeq* = 0) = 0; + virtual void unmarshal(const Ice::InputStreamPtr&, const UnmarshalCallbackPtr&, PyObject*, void*, bool, const Ice::StringSeq* = 0) = 0; virtual void print(PyObject*, IceUtilInternal::Output&, PrintObjectHistory*) = 0; @@ -134,16 +138,6 @@ class PrimitiveInfo : public TypeInfo { public: - virtual std::string getId() const; - - virtual bool validate(PyObject*); - - virtual void marshal(PyObject*, const Ice::OutputStreamPtr&, ObjectMap*, const Ice::StringSeq* = 0); - virtual void unmarshal(const Ice::InputStreamPtr&, const UnmarshalCallbackPtr&, PyObject*, void*, - const Ice::StringSeq* = 0); - - virtual void print(PyObject*, IceUtilInternal::Output&, PrintObjectHistory*); - enum Kind { KindBool, @@ -156,7 +150,23 @@ public: KindString }; - Kind kind; + PrimitiveInfo(Kind); + + virtual std::string getId() const; + + virtual bool validate(PyObject*); + + virtual bool variableLength() const; + virtual int wireSize() const; + virtual Ice::OptionalType optionalType() const; + + virtual void marshal(PyObject*, const Ice::OutputStreamPtr&, ObjectMap*, bool, const Ice::StringSeq* = 0); + virtual void unmarshal(const Ice::InputStreamPtr&, const UnmarshalCallbackPtr&, PyObject*, void*, bool, + const Ice::StringSeq* = 0); + + virtual void print(PyObject*, IceUtilInternal::Output&, PrintObjectHistory*); + + const Kind kind; }; typedef IceUtil::Handle<PrimitiveInfo> PrimitiveInfoPtr; @@ -169,19 +179,25 @@ class EnumInfo : public TypeInfo { public: + EnumInfo(const std::string&, PyObject*, PyObject*); + virtual std::string getId() const; virtual bool validate(PyObject*); - virtual void marshal(PyObject*, const Ice::OutputStreamPtr&, ObjectMap*, const Ice::StringSeq* = 0); - virtual void unmarshal(const Ice::InputStreamPtr&, const UnmarshalCallbackPtr&, PyObject*, void*, + virtual bool variableLength() const; + virtual int wireSize() const; + virtual Ice::OptionalType optionalType() const; + + virtual void marshal(PyObject*, const Ice::OutputStreamPtr&, ObjectMap*, bool, const Ice::StringSeq* = 0); + virtual void unmarshal(const Ice::InputStreamPtr&, const UnmarshalCallbackPtr&, PyObject*, void*, bool, const Ice::StringSeq* = 0); virtual void print(PyObject*, IceUtilInternal::Output&, PrintObjectHistory*); - std::string id; - EnumeratorList enumerators; - PyObjectHandle pythonType; + const std::string id; + const EnumeratorList enumerators; + const PyObjectHandle pythonType; }; typedef IceUtil::Handle<EnumInfo> EnumInfoPtr; @@ -194,6 +210,8 @@ public: std::string name; std::vector<std::string> metaData; TypeInfoPtr type; + bool optional; + int tag; }; typedef IceUtil::Handle<DataMember> DataMemberPtr; typedef std::vector<DataMemberPtr> DataMemberList; @@ -205,23 +223,34 @@ class StructInfo : public TypeInfo { public: + StructInfo(const std::string&, PyObject*, PyObject*); + virtual std::string getId() const; virtual bool validate(PyObject*); + virtual bool variableLength() const; + virtual int wireSize() const; + virtual Ice::OptionalType optionalType() const; + virtual bool usesClasses(); - virtual void marshal(PyObject*, const Ice::OutputStreamPtr&, ObjectMap*, const Ice::StringSeq* = 0); - virtual void unmarshal(const Ice::InputStreamPtr&, const UnmarshalCallbackPtr&, PyObject*, void*, + virtual void marshal(PyObject*, const Ice::OutputStreamPtr&, ObjectMap*, bool, const Ice::StringSeq* = 0); + virtual void unmarshal(const Ice::InputStreamPtr&, const UnmarshalCallbackPtr&, PyObject*, void*, bool, const Ice::StringSeq* = 0); virtual void print(PyObject*, IceUtilInternal::Output&, PrintObjectHistory*); virtual void destroy(); - std::string id; - DataMemberList members; - PyObjectHandle pythonType; + const std::string id; + const DataMemberList members; + const PyObjectHandle pythonType; + +private: + + bool _variableLength; + int _wireSize; }; typedef IceUtil::Handle<StructInfo> StructInfoPtr; @@ -232,20 +261,28 @@ class SequenceInfo : public TypeInfo { public: + SequenceInfo(const std::string&, PyObject*, PyObject*); + virtual std::string getId() const; virtual bool validate(PyObject*); + virtual bool variableLength() const; + virtual int wireSize() const; + virtual Ice::OptionalType optionalType() const; + virtual bool usesClasses(); - virtual void marshal(PyObject*, const Ice::OutputStreamPtr&, ObjectMap*, const Ice::StringSeq* = 0); - virtual void unmarshal(const Ice::InputStreamPtr&, const UnmarshalCallbackPtr&, PyObject*, void*, + virtual void marshal(PyObject*, const Ice::OutputStreamPtr&, ObjectMap*, bool, const Ice::StringSeq* = 0); + virtual void unmarshal(const Ice::InputStreamPtr&, const UnmarshalCallbackPtr&, PyObject*, void*, bool, const Ice::StringSeq* = 0); virtual void print(PyObject*, IceUtilInternal::Output&, PrintObjectHistory*); virtual void destroy(); +private: + struct SequenceMapping : public UnmarshalCallback { enum Type { SEQ_DEFAULT, SEQ_TUPLE, SEQ_LIST }; @@ -264,15 +301,16 @@ public: }; typedef IceUtil::Handle<SequenceMapping> SequenceMappingPtr; - std::string id; - SequenceMappingPtr mapping; - TypeInfoPtr elementType; - -private: - + PyObject* getSequence(const PrimitiveInfoPtr&, PyObject*); void marshalPrimitiveSequence(const PrimitiveInfoPtr&, PyObject*, const Ice::OutputStreamPtr&); void unmarshalPrimitiveSequence(const PrimitiveInfoPtr&, const Ice::InputStreamPtr&, const UnmarshalCallbackPtr&, PyObject*, void*, const SequenceMappingPtr&); + +public: + + const std::string id; + const SequenceMappingPtr mapping; + const TypeInfoPtr elementType; }; typedef IceUtil::Handle<SequenceInfo> SequenceInfoPtr; @@ -283,22 +321,28 @@ class CustomInfo : public TypeInfo { public: + CustomInfo(const std::string&, PyObject*); + virtual std::string getId() const; virtual bool validate(PyObject*); + virtual bool variableLength() const; + virtual int wireSize() const; + virtual Ice::OptionalType optionalType() const; + virtual bool usesClasses(); - virtual void marshal(PyObject*, const Ice::OutputStreamPtr&, ObjectMap*, const Ice::StringSeq* = 0); - virtual void unmarshal(const Ice::InputStreamPtr&, const UnmarshalCallbackPtr&, PyObject*, void*, + virtual void marshal(PyObject*, const Ice::OutputStreamPtr&, ObjectMap*, bool, const Ice::StringSeq* = 0); + virtual void unmarshal(const Ice::InputStreamPtr&, const UnmarshalCallbackPtr&, PyObject*, void*, bool, const Ice::StringSeq* = 0); virtual void print(PyObject*, IceUtilInternal::Output&, PrintObjectHistory*); virtual void destroy(); - std::string id; - PyObjectHandle pythonType; + const std::string id; + const PyObjectHandle pythonType; }; typedef IceUtil::Handle<CustomInfo> CustomInfoPtr; @@ -309,14 +353,20 @@ class DictionaryInfo : public TypeInfo { public: + DictionaryInfo(const std::string&, PyObject*, PyObject*); + virtual std::string getId() const; virtual bool validate(PyObject*); + virtual bool variableLength() const; + virtual int wireSize() const; + virtual Ice::OptionalType optionalType() const; + virtual bool usesClasses(); - virtual void marshal(PyObject*, const Ice::OutputStreamPtr&, ObjectMap*, const Ice::StringSeq* = 0); - virtual void unmarshal(const Ice::InputStreamPtr&, const UnmarshalCallbackPtr&, PyObject*, void*, + virtual void marshal(PyObject*, const Ice::OutputStreamPtr&, ObjectMap*, bool, const Ice::StringSeq* = 0); + virtual void unmarshal(const Ice::InputStreamPtr&, const UnmarshalCallbackPtr&, PyObject*, void*, bool, const Ice::StringSeq* = 0); virtual void unmarshaled(PyObject*, PyObject*, void*); @@ -337,6 +387,11 @@ public: std::string id; TypeInfoPtr keyType; TypeInfoPtr valueType; + +private: + + bool _variableLength; + int _wireSize; }; typedef IceUtil::Handle<DictionaryInfo> DictionaryInfoPtr; @@ -346,14 +401,22 @@ class ClassInfo : public TypeInfo { public: + ClassInfo(const std::string&); + + void define(PyObject*, bool, bool, PyObject*, PyObject*, PyObject*); + virtual std::string getId() const; virtual bool validate(PyObject*); virtual bool usesClasses(); - virtual void marshal(PyObject*, const Ice::OutputStreamPtr&, ObjectMap*, const Ice::StringSeq* = 0); - virtual void unmarshal(const Ice::InputStreamPtr&, const UnmarshalCallbackPtr&, PyObject*, void*, + virtual bool variableLength() const; + virtual int wireSize() const; + virtual Ice::OptionalType optionalType() const; + + virtual void marshal(PyObject*, const Ice::OutputStreamPtr&, ObjectMap*, bool, const Ice::StringSeq* = 0); + virtual void unmarshal(const Ice::InputStreamPtr&, const UnmarshalCallbackPtr&, PyObject*, void*, bool, const Ice::StringSeq* = 0); virtual void print(PyObject*, IceUtilInternal::Output&, PrintObjectHistory*); @@ -362,15 +425,16 @@ public: void printMembers(PyObject*, IceUtilInternal::Output&, PrintObjectHistory*); - std::string id; - bool isAbstract; - bool preserve; - ClassInfoPtr base; - ClassInfoList interfaces; - DataMemberList members; - PyObjectHandle pythonType; - PyObjectHandle typeObj; - bool defined; + const std::string id; + const bool isAbstract; + const bool preserve; + const ClassInfoPtr base; + const ClassInfoList interfaces; + const DataMemberList members; + const DataMemberList optionalMembers; + const PyObjectHandle pythonType; + const PyObjectHandle typeObj; + const bool defined; }; // @@ -380,21 +444,29 @@ class ProxyInfo : public TypeInfo { public: + ProxyInfo(const std::string&); + + void define(PyObject*); + virtual std::string getId() const; virtual bool validate(PyObject*); - virtual void marshal(PyObject*, const Ice::OutputStreamPtr&, ObjectMap*, const Ice::StringSeq* = 0); - virtual void unmarshal(const Ice::InputStreamPtr&, const UnmarshalCallbackPtr&, PyObject*, void*, + virtual bool variableLength() const; + virtual int wireSize() const; + virtual Ice::OptionalType optionalType() const; + + virtual void marshal(PyObject*, const Ice::OutputStreamPtr&, ObjectMap*, bool, const Ice::StringSeq* = 0); + virtual void unmarshal(const Ice::InputStreamPtr&, const UnmarshalCallbackPtr&, PyObject*, void*, bool, const Ice::StringSeq* = 0); virtual void print(PyObject*, IceUtilInternal::Output&, PrintObjectHistory*); virtual void destroy(); - std::string id; - PyObjectHandle pythonType; - PyObjectHandle typeObj; + const std::string id; + const PyObjectHandle pythonType; + const PyObjectHandle typeObj; }; typedef IceUtil::Handle<ProxyInfo> ProxyInfoPtr; @@ -415,8 +487,13 @@ public: bool preserve; ExceptionInfoPtr base; DataMemberList members; + DataMemberList optionalMembers; bool usesClasses; PyObjectHandle pythonType; + +private: + + void writeMembers(PyObject*, const Ice::OutputStreamPtr&, const DataMemberList&, ObjectMap*) const; }; // @@ -435,6 +512,8 @@ public: private: + void writeMembers(const Ice::OutputStreamPtr&, const DataMemberList&) const; + PyObject* _object; ObjectMap* _map; ClassInfoPtr _info; @@ -481,7 +560,7 @@ public: virtual bool usesClasses() const; virtual std::string ice_name() const; - virtual ExceptionWriter* ice_clone() const; + virtual Ice::UserException* ice_clone() const; virtual void ice_throw() const; private: @@ -507,7 +586,7 @@ public: virtual void usesClasses(bool); virtual std::string ice_name() const; - virtual ExceptionReader* ice_clone() const; + virtual Ice::UserException* ice_clone() const; virtual void ice_throw() const; PyObject* getException() const; // Borrowed reference. @@ -524,6 +603,8 @@ private: ClassInfoPtr lookupClassInfo(const std::string&); ExceptionInfoPtr lookupExceptionInfo(const std::string&); +extern PyObject* Unset; + bool initTypes(PyObject*); PyObject* createType(const TypeInfoPtr&); diff --git a/py/modules/IcePy/Util.cpp b/py/modules/IcePy/Util.cpp index 5f7eb639f9f..d254f5a3e1c 100644 --- a/py/modules/IcePy/Util.cpp +++ b/py/modules/IcePy/Util.cpp @@ -486,11 +486,7 @@ IcePy::PyException::getTraceback() string IcePy::PyException::getTypeName() { -#ifdef ICEPY_OLD_EXCEPTIONS - PyObject* cls = reinterpret_cast<PyObject*>(reinterpret_cast<PyInstanceObject*>(ex.get())->in_class); -#else PyObject* cls = reinterpret_cast<PyObject*>(ex.get()->ob_type); -#endif PyObjectHandle name = PyObject_GetAttrString(cls, "__name__"); assert(name.get()); PyObjectHandle mod = PyObject_GetAttrString(cls, "__module__"); @@ -685,11 +681,7 @@ IcePy::lookupType(const string& typeName) PyObject* IcePy::createExceptionInstance(PyObject* type) { -#ifdef ICEPY_OLD_EXCEPTIONS - assert(PyClass_Check(type)); -#else assert(PyExceptionClass_Check(type)); -#endif IcePy::PyObjectHandle args = PyTuple_New(0); if(!args.get()) { @@ -945,13 +937,8 @@ IcePy::setPythonException(PyObject* ex) // // PyErr_Restore steals references to the type and exception. // -#ifdef ICEPY_OLD_EXCEPTIONS - PyObject* type = reinterpret_cast<PyObject*>(reinterpret_cast<PyInstanceObject*>(ex)->in_class); - Py_INCREF(type); -#else PyObject* type = PyObject_Type(ex); assert(type); -#endif Py_INCREF(ex); PyErr_Restore(type, ex, 0); } @@ -970,11 +957,7 @@ IcePy::handleSystemExit(PyObject* ex) // This code is similar to handle_system_exit in pythonrun.c. // PyObjectHandle code; -#ifdef ICEPY_OLD_EXCEPTIONS - if(PyInstance_Check(ex)) -#else if(PyExceptionInstance_Check(ex)) -#endif { code = PyObject_GetAttrString(ex, STRCAST("code")); } diff --git a/py/python/Ice.py b/py/python/Ice.py index 0a63e2db3a8..ab0c26f0830 100644 --- a/py/python/Ice.py +++ b/py/python/Ice.py @@ -68,6 +68,7 @@ encodingVersionToString = IcePy.encodingVersionToString generateUUID = IcePy.generateUUID loadSlice = IcePy.loadSlice AsyncResult = IcePy.AsyncResult +Unset = IcePy.Unset # # This value is used as the default value for struct types in the constructors @@ -199,6 +200,13 @@ class SliceInfo(object): # objects - tuple of Ice.Object pass +class UnknownSlicedObject(Object): + # + # Members: + # + # unknownTypeId - string + pass + def getSliceDir(): '''Convenience function for locating the directory containing the Slice files.''' @@ -1314,13 +1322,16 @@ IcePy._t_Object = IcePy.defineClass('::Ice::Object', Object, (), False, False, N IcePy._t_ObjectPrx = IcePy.defineProxy('::Ice::Object', ObjectPrx) Object._ice_type = IcePy._t_Object -Object._op_ice_isA = IcePy.Operation('ice_isA', OperationMode.Idempotent, OperationMode.Nonmutating, False, None, (), (((), IcePy._t_string),), (), IcePy._t_bool, ()) +Object._op_ice_isA = IcePy.Operation('ice_isA', OperationMode.Idempotent, OperationMode.Nonmutating, False, None, (), (((), IcePy._t_string, False, 0),), (), ((), IcePy._t_bool, False, 0), ()) Object._op_ice_ping = IcePy.Operation('ice_ping', OperationMode.Idempotent, OperationMode.Nonmutating, False, None, (), (), (), None, ()) -Object._op_ice_ids = IcePy.Operation('ice_ids', OperationMode.Idempotent, OperationMode.Nonmutating, False, None, (), (), (), _t_StringSeq, ()) -Object._op_ice_id = IcePy.Operation('ice_id', OperationMode.Idempotent, OperationMode.Nonmutating, False, None, (), (), (), IcePy._t_string, ()) +Object._op_ice_ids = IcePy.Operation('ice_ids', OperationMode.Idempotent, OperationMode.Nonmutating, False, None, (), (), (), ((), _t_StringSeq, False, 0), ()) +Object._op_ice_id = IcePy.Operation('ice_id', OperationMode.Idempotent, OperationMode.Nonmutating, False, None, (), (), (), ((), IcePy._t_string, False, 0), ()) IcePy._t_LocalObject = IcePy.defineClass('::Ice::LocalObject', object, (), False, False, None, (), ()) +IcePy._t_UnknownSlicedObject = IcePy.defineClass('::Ice::UnknownSlicedObject', UnknownSlicedObject, (), False, True, None, (), ()) +UnknownSlicedObject._ice_type = IcePy._t_UnknownSlicedObject + # # Annotate some exceptions. # diff --git a/py/test/Ice/optional/AllTests.py b/py/test/Ice/optional/AllTests.py new file mode 100644 index 00000000000..2ff309a1d7a --- /dev/null +++ b/py/test/Ice/optional/AllTests.py @@ -0,0 +1,724 @@ +# ********************************************************************** +# +# Copyright (c) 2003-2012 ZeroC, Inc. All rights reserved. +# +# This copy of Ice is licensed to you under the terms described in the +# ICE_LICENSE file included in this distribution. +# +# ********************************************************************** + +import Ice, Test, sys + +def test(b): + if not b: + raise RuntimeError('test assertion failed') + +def allTests(communicator): + sys.stdout.write("testing stringToProxy... ") + sys.stdout.flush() + ref = "initial:default -p 12010" + base = communicator.stringToProxy(ref) + test(base) + print("ok") + + sys.stdout.write("testing checked cast... ") + sys.stdout.flush() + initial = Test.InitialPrx.checkedCast(base) + test(initial) + test(initial == base) + print("ok") + + sys.stdout.write("testing optional data members... ") + sys.stdout.flush() + + oo1 = Test.OneOptional() + test(oo1.a == Ice.Unset) + oo1.a = 15 + + oo2 = Test.OneOptional(16) + test(oo2.a == 16) + + mo1 = Test.MultiOptional() + test(mo1.a == Ice.Unset) + test(mo1.b == Ice.Unset) + test(mo1.c == Ice.Unset) + test(mo1.d == Ice.Unset) + test(mo1.e == Ice.Unset) + test(mo1.f == Ice.Unset) + test(mo1.g == Ice.Unset) + test(mo1.h == Ice.Unset) + test(mo1.i == Ice.Unset) + test(mo1.j == Ice.Unset) + test(mo1.k == Ice.Unset) + test(mo1.bs == Ice.Unset) + test(mo1.ss == Ice.Unset) + test(mo1.iid == Ice.Unset) + test(mo1.sid == Ice.Unset) + test(mo1.fs == Ice.Unset) + test(mo1.vs == Ice.Unset) + + test(mo1.shs == Ice.Unset) + test(mo1.es == Ice.Unset) + test(mo1.fss == Ice.Unset) + test(mo1.vss == Ice.Unset) + test(mo1.oos == Ice.Unset) + test(mo1.oops == Ice.Unset) + + test(mo1.ied == Ice.Unset) + test(mo1.ifsd == Ice.Unset) + test(mo1.ivsd == Ice.Unset) + test(mo1.iood == Ice.Unset) + test(mo1.ioopd == Ice.Unset) + + test(mo1.bos == Ice.Unset) + + fs = Test.FixedStruct(78) + vs = Test.VarStruct("hello") + mo1 = Test.MultiOptional(15, True, 19, 78, 99, 5.5, 1.0, "test", Test.MyEnum.MyEnumMember, \ + Test.MultiOptionalPrx.uncheckedCast(communicator.stringToProxy("test")), \ + None, [5], ["test", "test2"], {4:3}, {"test":10}, fs, vs, [1], \ + [Test.MyEnum.MyEnumMember, Test.MyEnum.MyEnumMember], \ + [ fs ], [ vs ], [ oo1 ], \ + [ Test.OneOptionalPrx.uncheckedCast(communicator.stringToProxy("test")) ], \ + {4:Test.MyEnum.MyEnumMember}, {4:fs}, {5:vs}, {5:Test.OneOptional(15)}, \ + {5:Test.OneOptionalPrx.uncheckedCast(communicator.stringToProxy("test"))}, \ + [False, True, False]) + + test(mo1.a == 15) + test(mo1.b == True) + test(mo1.c == 19) + test(mo1.d == 78) + test(mo1.e == 99) + test(mo1.f == 5.5) + test(mo1.g == 1.0) + test(mo1.h == "test") + test(mo1.i == Test.MyEnum.MyEnumMember) + test(mo1.j == Test.MultiOptionalPrx.uncheckedCast(communicator.stringToProxy("test"))) + test(mo1.k == None) + test(mo1.bs == [5]) + test(mo1.ss == ["test", "test2"]) + test(mo1.iid[4] == 3) + test(mo1.sid["test"] == 10) + test(mo1.fs == Test.FixedStruct(78)) + test(mo1.vs == Test.VarStruct("hello")) + + test(mo1.shs[0] == 1) + test(mo1.es[0] == Test.MyEnum.MyEnumMember and mo1.es[1] == Test.MyEnum.MyEnumMember) + test(mo1.fss[0] == Test.FixedStruct(78)) + test(mo1.vss[0] == Test.VarStruct("hello")) + test(mo1.oos[0] == oo1) + test(mo1.oops[0] == Test.OneOptionalPrx.uncheckedCast(communicator.stringToProxy("test"))) + + test(mo1.ied[4] == Test.MyEnum.MyEnumMember) + test(mo1.ifsd[4] == Test.FixedStruct(78)) + test(mo1.ivsd[5] == Test.VarStruct("hello")) + test(mo1.iood[5].a == 15) + test(mo1.ioopd[5] == Test.OneOptionalPrx.uncheckedCast(communicator.stringToProxy("test"))) + + test(mo1.bos == [False, True, False]) + + print("ok") + + sys.stdout.write("testing marshaling... ") + sys.stdout.flush() + + oo4 = initial.pingPong(Test.OneOptional()) + test(oo4.a == Ice.Unset) + + oo5 = initial.pingPong(oo1) + test(oo1.a == oo5.a) + + mo4 = initial.pingPong(Test.MultiOptional()) + test(mo4.a == Ice.Unset) + test(mo4.b == Ice.Unset) + test(mo4.c == Ice.Unset) + test(mo4.d == Ice.Unset) + test(mo4.e == Ice.Unset) + test(mo4.f == Ice.Unset) + test(mo4.g == Ice.Unset) + test(mo4.h == Ice.Unset) + test(mo4.i == Ice.Unset) + test(mo4.j == Ice.Unset) + test(mo4.k == Ice.Unset) + test(mo4.bs == Ice.Unset) + test(mo4.ss == Ice.Unset) + test(mo4.iid == Ice.Unset) + test(mo4.sid == Ice.Unset) + test(mo4.fs == Ice.Unset) + test(mo4.vs == Ice.Unset) + + test(mo4.shs == Ice.Unset) + test(mo4.es == Ice.Unset) + test(mo4.fss == Ice.Unset) + test(mo4.vss == Ice.Unset) + test(mo4.oos == Ice.Unset) + test(mo4.oops == Ice.Unset) + + test(mo4.ied == Ice.Unset) + test(mo4.ifsd == Ice.Unset) + test(mo4.ivsd == Ice.Unset) + test(mo4.iood == Ice.Unset) + test(mo4.ioopd == Ice.Unset) + + test(mo4.bos == Ice.Unset) + + mo5 = initial.pingPong(mo1) + test(mo5.a == mo1.a) + test(mo5.b == mo1.b) + test(mo5.c == mo1.c) + test(mo5.d == mo1.d) + test(mo5.e == mo1.e) + test(mo5.f == mo1.f) + test(mo5.g == mo1.g) + test(mo5.h == mo1.h) + test(mo5.i == mo1.i) + test(mo5.j == mo1.j) + test(mo5.k == None) + test(mo5.bs == "\x05") + test(mo5.ss == mo1.ss) + test(mo5.iid[4] == 3) + test(mo5.sid["test"] == 10) + test(mo5.fs == mo1.fs) + test(mo5.vs == mo1.vs) + test(mo5.shs == mo1.shs) + test(mo5.es[0] == Test.MyEnum.MyEnumMember and mo1.es[1] == Test.MyEnum.MyEnumMember) + test(mo5.fss[0] == Test.FixedStruct(78)) + test(mo5.vss[0] == Test.VarStruct("hello")) + test(mo5.oos[0].a == 15) + test(mo5.oops[0] == Test.OneOptionalPrx.uncheckedCast(communicator.stringToProxy("test"))) + + test(mo5.ied[4] == Test.MyEnum.MyEnumMember) + test(mo5.ifsd[4] == Test.FixedStruct(78)) + test(mo5.ivsd[5] == Test.VarStruct("hello")) + test(mo5.iood[5].a == 15) + test(mo5.ioopd[5] == Test.OneOptionalPrx.uncheckedCast(communicator.stringToProxy("test"))) + + test(mo5.bos == mo1.bos) + + # Clear the first half of the optional members + mo6 = Test.MultiOptional() + mo6.b = mo5.b + mo6.d = mo5.d + mo6.f = mo5.f + mo6.h = mo5.h + mo6.j = mo5.j + mo6.bs = mo5.bs + mo6.iid = mo5.iid + mo6.fs = mo5.fs + mo6.shs = mo5.shs + mo6.fss = mo5.fss + mo6.oos = mo5.oos + mo6.ifsd = mo5.ifsd + mo6.iood = mo5.iood + mo6.bos = mo5.bos + + mo7 = initial.pingPong(mo6) + test(mo7.a == Ice.Unset) + test(mo7.b == mo1.b) + test(mo7.c == Ice.Unset) + test(mo7.d == mo1.d) + test(mo7.e == Ice.Unset) + test(mo7.f == mo1.f) + test(mo7.g == Ice.Unset) + test(mo7.h == mo1.h) + test(mo7.i == Ice.Unset) + test(mo7.j == mo1.j) + test(mo7.k == Ice.Unset) + test(mo7.bs == "\x05") + test(mo7.ss == Ice.Unset) + test(mo7.iid[4] == 3) + test(mo7.sid == Ice.Unset) + test(mo7.fs == mo1.fs) + test(mo7.vs == Ice.Unset) + + test(mo7.shs == mo1.shs) + test(mo7.es == Ice.Unset) + test(mo7.fss[0] == Test.FixedStruct(78)) + test(mo7.vss == Ice.Unset) + test(mo7.oos[0].a == 15) + test(mo7.oops == Ice.Unset) + + test(mo7.ied == Ice.Unset) + test(mo7.ifsd[4] == Test.FixedStruct(78)) + test(mo7.ivsd == Ice.Unset) + test(mo7.iood[5].a == 15) + test(mo7.ioopd == Ice.Unset) + + test(mo7.bos == [False, True, False]) + + # Clear the second half of the optional members + mo8 = Test.MultiOptional() + mo8.a = mo5.a + mo8.c = mo5.c + mo8.e = mo5.e + mo8.g = mo5.g + mo8.i = mo5.i + mo8.k = mo8 + mo8.ss = mo5.ss + mo8.sid = mo5.sid + mo8.vs = mo5.vs + + mo8.es = mo5.es + mo8.vss = mo5.vss + mo8.oops = mo5.oops + + mo8.ied = mo5.ied + mo8.ivsd = mo5.ivsd + mo8.ioopd = mo5.ioopd + + mo9 = initial.pingPong(mo8) + test(mo9.a == mo1.a) + test(mo9.b == Ice.Unset) + test(mo9.c == mo1.c) + test(mo9.d == Ice.Unset) + test(mo9.e == mo1.e) + test(mo9.f == Ice.Unset) + test(mo9.g == mo1.g) + test(mo9.h == Ice.Unset) + test(mo9.i == mo1.i) + test(mo9.j == Ice.Unset) + test(mo9.k == mo9) + test(mo9.bs == Ice.Unset) + test(mo9.ss == mo1.ss) + test(mo9.iid == Ice.Unset) + test(mo9.sid["test"] == 10) + test(mo9.fs == Ice.Unset) + test(mo9.vs == mo1.vs) + + test(mo9.shs == Ice.Unset) + test(mo9.es[0] == Test.MyEnum.MyEnumMember and mo1.es[1] == Test.MyEnum.MyEnumMember) + test(mo9.fss == Ice.Unset) + test(mo9.vss[0] == Test.VarStruct("hello")) + test(mo9.oos == Ice.Unset) + test(mo9.oops[0] == Test.OneOptionalPrx.uncheckedCast(communicator.stringToProxy("test"))) + + test(mo9.ied[4] == Test.MyEnum.MyEnumMember) + test(mo9.ifsd == Ice.Unset) + test(mo9.ivsd[5] == Test.VarStruct("hello")) + test(mo9.iood == Ice.Unset) + test(mo9.ioopd[5] == Test.OneOptionalPrx.uncheckedCast(communicator.stringToProxy("test"))) + + test(mo9.bos == Ice.Unset) + + print("ok") + + sys.stdout.write("testing marshaling of large containers with fixed size elements... ") + sys.stdout.flush() + + mc = Test.MultiOptional() + + mc.bs = [] + for i in range(1000): + mc.bs.append(0) + mc.shs = [] + for i in range(300): + mc.shs.append(0) + + mc.fss = [] + for i in range(300): + mc.fss.append(Test.FixedStruct()) + + mc.ifsd = {} + for i in range(300): + mc.ifsd[i] = Test.FixedStruct() + + mc = initial.pingPong(mc) + test(len(mc.bs) == 1000) + test(len(mc.shs) == 300) + test(len(mc.fss) == 300) + test(len(mc.ifsd) == 300) + + print("ok") + + sys.stdout.write("testing tag marshaling... ") + sys.stdout.flush() + + b = Test.B() + b2 = initial.pingPong(b) + test(b2.ma == Ice.Unset) + test(b2.mb == Ice.Unset) + test(b2.mc == Ice.Unset) + + b.ma = 10 + b.mb = 11 + b.mc = 12 + b.md = 13 + + b2 = initial.pingPong(b) + test(b2.ma == 10) + test(b2.mb == 11) + test(b2.mc == 12) + test(b2.md == 13) + + print("ok") + + sys.stdout.write("testing optional with default values... ") + sys.stdout.flush() + + wd = initial.pingPong(Test.WD()) + test(wd.a == 5) + test(wd.s == "test") + wd.a = Ice.Unset + wd.s = Ice.Unset + wd = initial.pingPong(wd) + test(wd.a == Ice.Unset) + test(wd.s == Ice.Unset) + + print("ok") + + if communicator.getProperties().getPropertyAsInt("Ice.Default.SlicedFormat") > 0: + sys.stdout.write("testing marshaling with unknown class slices... ") + sys.stdout.flush() + + c = Test.C() + c.ss = "test" + c.ms = "testms" + c = initial.pingPong(c) + test(c.ma == Ice.Unset) + test(c.mb == Ice.Unset) + test(c.mc == Ice.Unset) + test(c.md == Ice.Unset) + test(c.ss == "test") + test(c.ms == "testms") + + print("ok") + + sys.stdout.write("testing optionals with unknown classes... ") + sys.stdout.flush() + + initial2 = Test.Initial2Prx.uncheckedCast(base) + d = Test.D() + d.ds = "test" + d.seq = ["test1", "test2", "test3", "test4"] + d.ao = Test.A(18) + d.requiredB = 14; + d.requiredA = 14; + initial2.opClassAndUnknownOptional(Test.A(), d) + + print("ok") + + sys.stdout.write("testing optional parameters... ") + sys.stdout.flush() + + (p2, p3) = initial.opByte(Ice.Unset) + test(p2 == Ice.Unset and p3 == Ice.Unset) + (p2, p3) = initial.opByte(56) + test(p2 == 56 and p3 == 56) + r = initial.begin_opByte(56) + (p2, p3) = initial.end_opByte(r) + test(p2 == 56 and p3 == 56) + + (p2, p3) = initial.opBool(Ice.Unset) + test(p2 == Ice.Unset and p3 == Ice.Unset) + (p2, p3) = initial.opBool(True) + test(p2 == True and p3 == True) + r = initial.begin_opBool(True) + (p2, p3) = initial.end_opBool(r) + test(p2 == True and p3 == True) + + (p2, p3) = initial.opShort(Ice.Unset) + test(p2 == Ice.Unset and p3 == Ice.Unset) + (p2, p3) = initial.opShort(56) + test(p2 == 56 and p3 == 56) + r = initial.begin_opShort(56) + (p2, p3) = initial.end_opShort(r) + test(p2 == 56 and p3 == 56) + + (p2, p3) = initial.opInt(Ice.Unset) + test(p2 == Ice.Unset and p3 == Ice.Unset) + (p2, p3) = initial.opInt(56) + test(p2 == 56 and p3 == 56) + r = initial.begin_opInt(56) + (p2, p3) = initial.end_opInt(r) + test(p2 == 56 and p3 == 56) + + (p2, p3) = initial.opLong(Ice.Unset) + test(p2 == Ice.Unset and p3 == Ice.Unset) + (p2, p3) = initial.opLong(56) + test(p2 == 56 and p3 == 56) + r = initial.begin_opLong(56) + (p2, p3) = initial.end_opLong(r) + test(p2 == 56 and p3 == 56) + + (p2, p3) = initial.opFloat(Ice.Unset) + test(p2 == Ice.Unset and p3 == Ice.Unset) + (p2, p3) = initial.opFloat(1.0) + test(p2 == 1.0 and p3 == 1.0) + r = initial.begin_opFloat(1.0) + (p2, p3) = initial.end_opFloat(r) + test(p2 == 1.0 and p3 == 1.0) + + (p2, p3) = initial.opDouble(Ice.Unset) + test(p2 == Ice.Unset and p3 == Ice.Unset) + (p2, p3) = initial.opDouble(1.0) + test(p2 == 1.0 and p3 == 1.0) + r = initial.begin_opDouble(1.0) + (p2, p3) = initial.end_opDouble(r) + test(p2 == 1.0 and p3 == 1.0) + + (p2, p3) = initial.opString(Ice.Unset) + test(p2 == Ice.Unset and p3 == Ice.Unset) + (p2, p3) = initial.opString("test") + test(p2 == "test" and p3 == "test") + r = initial.begin_opString("test") + (p2, p3) = initial.end_opString(r) + test(p2 == "test" and p3 == "test") + + (p2, p3) = initial.opMyEnum(Ice.Unset) + test(p2 == Ice.Unset and p3 == Ice.Unset) + (p2, p3) = initial.opMyEnum(Test.MyEnum.MyEnumMember) + test(p2 == Test.MyEnum.MyEnumMember and p3 == Test.MyEnum.MyEnumMember) + r = initial.begin_opMyEnum(Test.MyEnum.MyEnumMember) + (p2, p3) = initial.end_opMyEnum(r) + test(p2 == Test.MyEnum.MyEnumMember and p3 == Test.MyEnum.MyEnumMember) + + (p2, p3) = initial.opSmallStruct(Ice.Unset) + test(p2 == Ice.Unset and p3 == Ice.Unset) + p1 = Test.SmallStruct(56) + (p2, p3) = initial.opSmallStruct(p1) + test(p2 == p1 and p3 == p1) + r = initial.begin_opSmallStruct(p1) + (p2, p3) = initial.end_opSmallStruct(r) + test(p2 == p1 and p3 == p1) + + (p2, p3) = initial.opFixedStruct(Ice.Unset) + test(p2 == Ice.Unset and p3 == Ice.Unset) + p1 = Test.FixedStruct(56) + (p2, p3) = initial.opFixedStruct(p1) + test(p2 == p1 and p3 == p1) + r = initial.begin_opFixedStruct(p1) + (p2, p3) = initial.end_opFixedStruct(r) + test(p2 == p1 and p3 == p1) + + (p2, p3) = initial.opVarStruct(Ice.Unset) + test(p2 == Ice.Unset and p3 == Ice.Unset) + p1 = Test.VarStruct("test") + (p2, p3) = initial.opVarStruct(p1) + test(p2 == p1 and p3 == p1) + r = initial.begin_opVarStruct(p1) + (p2, p3) = initial.end_opVarStruct(r) + test(p2 == p1 and p3 == p1) + + (p2, p3) = initial.opOneOptional(Ice.Unset) + test(p2 == Ice.Unset and p3 == Ice.Unset) + p1 = Test.OneOptional(58) + (p2, p3) = initial.opOneOptional(p1) + test(p2.a == p1.a and p3.a == p1.a) + r = initial.begin_opOneOptional(p1) + (p2, p3) = initial.end_opOneOptional(r) + test(p2.a == p1.a and p3.a == p1.a) + + (p2, p3) = initial.opOneOptionalProxy(Ice.Unset) + test(p2 == Ice.Unset and p3 == Ice.Unset) + p1 = Test.OneOptionalPrx.uncheckedCast(communicator.stringToProxy("test")) + (p2, p3) = initial.opOneOptionalProxy(p1) + test(p2 == p1 and p3 == p1) + r = initial.begin_opOneOptionalProxy(p1) + (p2, p3) = initial.end_opOneOptionalProxy(r) + test(p2 == p1 and p3 == p1) + + (p2, p3) = initial.opByteSeq(Ice.Unset) + test(p2 == Ice.Unset and p3 == Ice.Unset) + p1 = [56 for x in range(100)] + (p2, p3) = initial.opByteSeq(p1) + test(len(p2) == len(p1) and len(p3) == len(p1)) + if sys.version_info[0] == 2: + test(p2[0] == '\x38') + test(p3[0] == '\x38') + else: + test(p2[0] == 0x38) + test(p3[0] == 0x38) + r = initial.begin_opByteSeq(p1) + (p2, p3) = initial.end_opByteSeq(r) + test(len(p2) == len(p1) and len(p3) == len(p1)) + if sys.version_info[0] == 2: + test(p2[0] == '\x38') + test(p3[0] == '\x38') + else: + test(p2[0] == 0x38) + test(p3[0] == 0x38) + + (p2, p3) = initial.opBoolSeq(Ice.Unset) + test(p2 == Ice.Unset and p3 == Ice.Unset) + p1 = [True for x in range(100)] + (p2, p3) = initial.opBoolSeq(p1) + test(p2 == p1 and p3 == p1) + r = initial.begin_opBoolSeq(p1) + (p2, p3) = initial.end_opBoolSeq(r) + test(p2 == p1 and p3 == p1) + + (p2, p3) = initial.opShortSeq(Ice.Unset) + test(p2 == Ice.Unset and p3 == Ice.Unset) + p1 = [56 for x in range(100)] + (p2, p3) = initial.opShortSeq(p1) + test(p2 == p1 and p3 == p1) + r = initial.begin_opShortSeq(p1) + (p2, p3) = initial.end_opShortSeq(r) + test(p2 == p1 and p3 == p1) + + (p2, p3) = initial.opIntSeq(Ice.Unset) + test(p2 == Ice.Unset and p3 == Ice.Unset) + p1 = [56 for x in range(100)] + (p2, p3) = initial.opIntSeq(p1) + test(p2 == p1 and p3 == p1) + r = initial.begin_opIntSeq(p1) + (p2, p3) = initial.end_opIntSeq(r) + test(p2 == p1 and p3 == p1) + + (p2, p3) = initial.opLongSeq(Ice.Unset) + test(p2 == Ice.Unset and p3 == Ice.Unset) + p1 = [56 for x in range(100)] + (p2, p3) = initial.opLongSeq(p1) + test(p2 == p1 and p3 == p1) + r = initial.begin_opLongSeq(p1) + (p2, p3) = initial.end_opLongSeq(r) + test(p2 == p1 and p3 == p1) + + (p2, p3) = initial.opFloatSeq(Ice.Unset) + test(p2 == Ice.Unset and p3 == Ice.Unset) + p1 = [1.0 for x in range(100)] + (p2, p3) = initial.opFloatSeq(p1) + test(p2 == p1 and p3 == p1) + r = initial.begin_opFloatSeq(p1) + (p2, p3) = initial.end_opFloatSeq(r) + test(p2 == p1 and p3 == p1) + + (p2, p3) = initial.opDoubleSeq(Ice.Unset) + test(p2 == Ice.Unset and p3 == Ice.Unset) + p1 = [1.0 for x in range(100)] + (p2, p3) = initial.opDoubleSeq(p1) + test(p2 == p1 and p3 == p1) + r = initial.begin_opDoubleSeq(p1) + (p2, p3) = initial.end_opDoubleSeq(r) + test(p2 == p1 and p3 == p1) + + (p2, p3) = initial.opStringSeq(Ice.Unset) + test(p2 == Ice.Unset and p3 == Ice.Unset) + p1 = ["test1" for x in range(100)] + (p2, p3) = initial.opStringSeq(p1) + test(p2 == p1 and p3 == p1) + r = initial.begin_opStringSeq(p1) + (p2, p3) = initial.end_opStringSeq(r) + test(p2 == p1 and p3 == p1) + + (p2, p3) = initial.opSmallStructSeq(Ice.Unset) + test(p2 == Ice.Unset and p3 == Ice.Unset) + p1 = [Test.SmallStruct(1) for x in range(10)] + (p2, p3) = initial.opSmallStructSeq(p1) + test(p2 == p1 and p3 == p1) + r = initial.begin_opSmallStructSeq(p1) + (p2, p3) = initial.end_opSmallStructSeq(r) + test(p2 == p1 and p3 == p1) + + (p2, p3) = initial.opSmallStructList(Ice.Unset) + test(p2 == Ice.Unset and p3 == Ice.Unset) + p1 = tuple([Test.SmallStruct(1) for x in range(10)]) + (p2, p3) = initial.opSmallStructList(p1) + test(p2 == p1 and p3 == p1) + r = initial.begin_opSmallStructList(p1) + (p2, p3) = initial.end_opSmallStructList(r) + test(p2 == p1 and p3 == p1) + + (p2, p3) = initial.opFixedStructSeq(Ice.Unset) + test(p2 == Ice.Unset and p3 == Ice.Unset) + p1 = [Test.FixedStruct(1) for x in range(10)] + (p2, p3) = initial.opFixedStructSeq(p1) + test(p2 == p1 and p3 == p1) + r = initial.begin_opFixedStructSeq(p1) + (p2, p3) = initial.end_opFixedStructSeq(r) + test(p2 == p1 and p3 == p1) + + (p2, p3) = initial.opFixedStructList(Ice.Unset) + test(p2 == Ice.Unset and p3 == Ice.Unset) + p1 = tuple([Test.FixedStruct(1) for x in range(10)]) + (p2, p3) = initial.opFixedStructList(p1) + test(p2 == p1 and p3 == p1) + r = initial.begin_opFixedStructList(p1) + (p2, p3) = initial.end_opFixedStructList(r) + test(p2 == p1 and p3 == p1) + + (p2, p3) = initial.opVarStructSeq(Ice.Unset) + test(p2 == Ice.Unset and p3 == Ice.Unset) + p1 = [Test.VarStruct("test") for x in range(10)] + (p2, p3) = initial.opVarStructSeq(p1) + test(p2 == p1 and p3 == p1) + r = initial.begin_opVarStructSeq(p1) + (p2, p3) = initial.end_opVarStructSeq(r) + test(p2 == p1 and p3 == p1) + + (p2, p3) = initial.opIntIntDict(Ice.Unset) + test(p2 == Ice.Unset and p3 == Ice.Unset) + p1 = {1:2, 2:3} + (p2, p3) = initial.opIntIntDict(p1) + test(p2 == p1 and p3 == p1) + r = initial.begin_opIntIntDict(p1) + (p2, p3) = initial.end_opIntIntDict(r) + test(p2 == p1 and p3 == p1) + + (p2, p3) = initial.opStringIntDict(Ice.Unset) + test(p2 == Ice.Unset and p3 == Ice.Unset) + p1 = {"1":2, "2":3} + (p2, p3) = initial.opStringIntDict(p1) + test(p2 == p1 and p3 == p1) + r = initial.begin_opStringIntDict(p1) + (p2, p3) = initial.end_opStringIntDict(r) + test(p2 == p1 and p3 == p1) + + print("ok") + + sys.stdout.write("testing exception optionals... ") + sys.stdout.flush() + + try: + initial.opOptionalException(Ice.Unset, Ice.Unset, Ice.Unset) + except Test.OptionalException as ex: + test(ex.a == Ice.Unset) + test(ex.b == Ice.Unset) + test(ex.o == Ice.Unset) + + try: + initial.opOptionalException(30, "test", Test.OneOptional(53)) + except Test.OptionalException as ex: + test(ex.a == 30) + test(ex.b == "test") + test(ex.o.a == 53) + + try: + initial.opDerivedException(Ice.Unset, Ice.Unset, Ice.Unset) + except Test.DerivedException as ex: + test(ex.a == Ice.Unset) + test(ex.b == Ice.Unset) + test(ex.o == Ice.Unset) + test(ex.ss == Ice.Unset) + test(ex.o2 == Ice.Unset) + + try: + initial.opDerivedException(30, "test", Test.OneOptional(53)) + except Test.DerivedException as ex: + test(ex.a == 30) + test(ex.b == "test") + test(ex.o.a == 53) + test(ex.ss == "test") + test(ex.o2 == ex.o) + + try: + initial.opRequiredException(Ice.Unset, Ice.Unset, Ice.Unset) + except Test.RequiredException as ex: + test(ex.a == Ice.Unset) + test(ex.b == Ice.Unset) + test(ex.o == Ice.Unset) + test(ex.ss != Ice.Unset) + test(ex.o2 != Ice.Unset) + + try: + initial.opRequiredException(30, "test", Test.OneOptional(53)) + except Test.RequiredException as ex: + test(ex.a == 30) + test(ex.b == "test") + test(ex.o.a == 53) + test(ex.ss == "test") + test(ex.o2 == ex.o) + + print("ok") + + return initial diff --git a/py/test/Ice/optional/Client.py b/py/test/Ice/optional/Client.py new file mode 100755 index 00000000000..5bd5e0b393b --- /dev/null +++ b/py/test/Ice/optional/Client.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python +# ********************************************************************** +# +# Copyright (c) 2003-2012 ZeroC, Inc. All rights reserved. +# +# This copy of Ice is licensed to you under the terms described in the +# ICE_LICENSE file included in this distribution. +# +# ********************************************************************** + +import os, sys, traceback + +import Ice +Ice.loadSlice('--all -I. ClientPrivate.ice') +import AllTests + +def run(args, communicator): + initial = AllTests.allTests(communicator) + initial.shutdown() + return True + +try: + communicator = Ice.initialize(sys.argv) + status = run(sys.argv, communicator) +except: + traceback.print_exc() + status = False + +if communicator: + try: + communicator.destroy() + except: + traceback.print_exc() + status = False + +sys.exit(not status) diff --git a/py/test/Ice/optional/ClientPrivate.ice b/py/test/Ice/optional/ClientPrivate.ice new file mode 100644 index 00000000000..a456124b4ec --- /dev/null +++ b/py/test/Ice/optional/ClientPrivate.ice @@ -0,0 +1,37 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2012 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +#pragma once + +#include <Test.ice> + +module Test +{ + +// +// The server doesn't know this class. +// +class D extends B +{ + string ds; + optional(990) StringSeq seq; + optional(1000) A ao; +}; + +// +// This class is a hack that allows us to invoke the opClassAndUnknownOptional operation +// on the server and pass an optional argument. This isn't necessary in other language +// mappings where the public stream API is available. +// +class Initial2 +{ + void opClassAndUnknownOptional(A p, optional(1) Object o); +}; + +}; diff --git a/py/test/Ice/optional/Server.py b/py/test/Ice/optional/Server.py new file mode 100755 index 00000000000..be177eebc9f --- /dev/null +++ b/py/test/Ice/optional/Server.py @@ -0,0 +1,156 @@ +#!/usr/bin/env python +# ********************************************************************** +# +# Copyright (c) 2003-2012 ZeroC, Inc. All rights reserved. +# +# This copy of Ice is licensed to you under the terms described in the +# ICE_LICENSE file included in this distribution. +# +# ********************************************************************** + +import os, sys, traceback + +import Ice +Ice.loadSlice('Test.ice') +import Test + +class InitialI(Test.Initial): + + def shutdown(self, current=None): + current.adapter.getCommunicator().shutdown() + + def pingPong(self, o, current=None): + return o + + def opOptionalException(self, a, b, o, current=None): + raise Test.OptionalException(a, b, o) + + def opDerivedException(self, a, b, o, current=None): + raise Test.DerivedException(a, b, o, b, o) + + def opRequiredException(self, a, b, o, current=None): + if b == Ice.Unset: + ss = "none" + else: + ss = b + if o == Ice.Unset: + o2 = None + else: + o2 = o + raise Test.RequiredException(a, b, o, ss, o2) + + def opByte(self, p1, current=None): + return (p1, p1) + + def opBool(self, p1, current=None): + return (p1, p1) + + def opShort(self, p1, current=None): + return (p1, p1) + + def opInt(self, p1, current=None): + return (p1, p1) + + def opLong(self, p1, current=None): + return (p1, p1) + + def opFloat(self, p1, current=None): + return (p1, p1) + + def opDouble(self, p1, current=None): + return (p1, p1) + + def opString(self, p1, current=None): + return (p1, p1) + + def opMyEnum(self, p1, current=None): + return (p1, p1) + + def opSmallStruct(self, p1, current=None): + return (p1, p1) + + def opFixedStruct(self, p1, current=None): + return (p1, p1) + + def opVarStruct(self, p1, current=None): + return (p1, p1) + + def opOneOptional(self, p1, current=None): + return (p1, p1) + + def opOneOptionalProxy(self, p1, current=None): + return (p1, p1) + + def opByteSeq(self, p1, current=None): + return (p1, p1) + + def opBoolSeq(self, p1, current=None): + return (p1, p1) + + def opShortSeq(self, p1, current=None): + return (p1, p1) + + def opIntSeq(self, p1, current=None): + return (p1, p1) + + def opLongSeq(self, p1, current=None): + return (p1, p1) + + def opFloatSeq(self, p1, current=None): + return (p1, p1) + + def opDoubleSeq(self, p1, current=None): + return (p1, p1) + + def opStringSeq(self, p1, current=None): + return (p1, p1) + + def opSmallStructSeq(self, p1, current=None): + return (p1, p1) + + def opSmallStructList(self, p1, current=None): + return (p1, p1) + + def opFixedStructSeq(self, p1, current=None): + return (p1, p1) + + def opFixedStructList(self, p1, current=None): + return (p1, p1) + + def opVarStructSeq(self, p1, current=None): + return (p1, p1) + + def opIntIntDict(self, p1, current=None): + return (p1, p1) + + def opStringIntDict(self, p1, current=None): + return (p1, p1) + + def opClassAndUnknownOptional(self, p, current=None): + pass + +def run(args, communicator): + communicator.getProperties().setProperty("TestAdapter.Endpoints", "default -p 12010:udp") + adapter = communicator.createObjectAdapter("TestAdapter") + initial = InitialI() + adapter.add(initial, communicator.stringToIdentity("initial")) + adapter.activate() + + communicator.waitForShutdown() + return True + +try: + communicator = Ice.initialize(sys.argv) + status = run(sys.argv, communicator) +except: + traceback.print_exc() + status = False + +if communicator: + try: + communicator.destroy() + except: + traceback.print_exc() + status = False + +sys.exit(not status) diff --git a/py/test/Ice/optional/ServerAMD.py b/py/test/Ice/optional/ServerAMD.py new file mode 100755 index 00000000000..bfdfa7369f6 --- /dev/null +++ b/py/test/Ice/optional/ServerAMD.py @@ -0,0 +1,157 @@ +#!/usr/bin/env python +# ********************************************************************** +# +# Copyright (c) 2003-2012 ZeroC, Inc. All rights reserved. +# +# This copy of Ice is licensed to you under the terms described in the +# ICE_LICENSE file included in this distribution. +# +# ********************************************************************** + +import os, sys, traceback + +import Ice +Ice.loadSlice('TestAMD.ice') +import Test + +class InitialI(Test.Initial): + + def shutdown_async(self, cb, current=None): + current.adapter.getCommunicator().shutdown() + cb.ice_response() + + def pingPong_async(self, cb, o, current=None): + cb.ice_response(o) + + def opOptionalException_async(self, cb, a, b, o, current=None): + cb.ice_exception(Test.OptionalException(a, b, o)) + + def opDerivedException_async(self, cb, a, b, o, current=None): + cb.ice_exception(Test.DerivedException(a, b, o, b, o)) + + def opRequiredException_async(self, cb, a, b, o, current=None): + if b == Ice.Unset: + ss = "none" + else: + ss = b + if o == Ice.Unset: + o2 = None + else: + o2 = o + cb.ice_exception(Test.RequiredException(a, b, o, ss, o2)) + + def opByte_async(self, cb, p1, current=None): + cb.ice_response(p1, p1) + + def opBool_async(self, cb, p1, current=None): + cb.ice_response(p1, p1) + + def opShort_async(self, cb, p1, current=None): + cb.ice_response(p1, p1) + + def opInt_async(self, cb, p1, current=None): + cb.ice_response(p1, p1) + + def opLong_async(self, cb, p1, current=None): + cb.ice_response(p1, p1) + + def opFloat_async(self, cb, p1, current=None): + cb.ice_response(p1, p1) + + def opDouble_async(self, cb, p1, current=None): + cb.ice_response(p1, p1) + + def opString_async(self, cb, p1, current=None): + cb.ice_response(p1, p1) + + def opMyEnum_async(self, cb, p1, current=None): + cb.ice_response(p1, p1) + + def opSmallStruct_async(self, cb, p1, current=None): + cb.ice_response(p1, p1) + + def opFixedStruct_async(self, cb, p1, current=None): + cb.ice_response(p1, p1) + + def opVarStruct_async(self, cb, p1, current=None): + cb.ice_response(p1, p1) + + def opOneOptional_async(self, cb, p1, current=None): + cb.ice_response(p1, p1) + + def opOneOptionalProxy_async(self, cb, p1, current=None): + cb.ice_response(p1, p1) + + def opByteSeq_async(self, cb, p1, current=None): + cb.ice_response(p1, p1) + + def opBoolSeq_async(self, cb, p1, current=None): + cb.ice_response(p1, p1) + + def opShortSeq_async(self, cb, p1, current=None): + cb.ice_response(p1, p1) + + def opIntSeq_async(self, cb, p1, current=None): + cb.ice_response(p1, p1) + + def opLongSeq_async(self, cb, p1, current=None): + cb.ice_response(p1, p1) + + def opFloatSeq_async(self, cb, p1, current=None): + cb.ice_response(p1, p1) + + def opDoubleSeq_async(self, cb, p1, current=None): + cb.ice_response(p1, p1) + + def opStringSeq_async(self, cb, p1, current=None): + cb.ice_response(p1, p1) + + def opSmallStructSeq_async(self, cb, p1, current=None): + cb.ice_response(p1, p1) + + def opSmallStructList_async(self, cb, p1, current=None): + cb.ice_response(p1, p1) + + def opFixedStructSeq_async(self, cb, p1, current=None): + cb.ice_response(p1, p1) + + def opFixedStructList_async(self, cb, p1, current=None): + cb.ice_response(p1, p1) + + def opVarStructSeq_async(self, cb, p1, current=None): + cb.ice_response(p1, p1) + + def opIntIntDict_async(self, cb, p1, current=None): + cb.ice_response(p1, p1) + + def opStringIntDict_async(self, cb, p1, current=None): + cb.ice_response(p1, p1) + + def opClassAndUnknownOptional_async(self, cb, p, current=None): + cb.ice_response() + +def run(args, communicator): + communicator.getProperties().setProperty("TestAdapter.Endpoints", "default -p 12010:udp") + adapter = communicator.createObjectAdapter("TestAdapter") + initial = InitialI() + adapter.add(initial, communicator.stringToIdentity("initial")) + adapter.activate() + + communicator.waitForShutdown() + return True + +try: + communicator = Ice.initialize(sys.argv) + status = run(sys.argv, communicator) +except: + traceback.print_exc() + status = False + +if communicator: + try: + communicator.destroy() + except: + traceback.print_exc() + status = False + +sys.exit(not status) diff --git a/py/test/Ice/optional/Test.ice b/py/test/Ice/optional/Test.ice new file mode 100644 index 00000000000..55cfeb85531 --- /dev/null +++ b/py/test/Ice/optional/Test.ice @@ -0,0 +1,236 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2012 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +#pragma once + +module Test +{ + +class OneOptional +{ + optional(1) int a; +}; + +enum MyEnum +{ + MyEnumMember +}; + +struct SmallStruct +{ + byte m; +}; + +struct FixedStruct +{ + int m; +}; + +struct VarStruct +{ + string m; +}; + +struct ClassVarStruct +{ + int a; +}; + +sequence<byte> ByteSeq; +sequence<bool> BoolSeq; +sequence<short> ShortSeq; +sequence<int> IntSeq; +sequence<long> LongSeq; +sequence<float> FloatSeq; +sequence<double> DoubleSeq; +sequence<string> StringSeq; +sequence<MyEnum> MyEnumSeq; +sequence<SmallStruct> SmallStructSeq; +["python:seq:tuple"] sequence<SmallStruct> SmallStructList; +sequence<FixedStruct> FixedStructSeq; +["python:seq:tuple"] sequence<FixedStruct> FixedStructList; +sequence<VarStruct> VarStructSeq; +sequence<OneOptional> OneOptionalSeq; +sequence<OneOptional*> OneOptionalPrxSeq; + +dictionary<int, int> IntIntDict; +dictionary<string, int> StringIntDict; +dictionary<int, MyEnum> IntEnumDict; +dictionary<int, FixedStruct> IntFixedStructDict; +dictionary<int, VarStruct> IntVarStructDict; +dictionary<int, OneOptional> IntOneOptionalDict; +dictionary<int, OneOptional*> IntOneOptionalPrxDict; + +class MultiOptional +{ + optional(1) byte a; + optional(2) bool b; + optional(3) short c; + optional(4) int d; + optional(5) long e; + optional(6) float f; + optional(7) double g; + optional(8) string h; + optional(9) MyEnum i; + optional(10) MultiOptional* j; + optional(11) MultiOptional k; + optional(12) ByteSeq bs; + optional(13) StringSeq ss; + optional(14) IntIntDict iid; + optional(15) StringIntDict sid; + optional(16) FixedStruct fs; + optional(17) VarStruct vs; + + optional(18) ShortSeq shs; + optional(19) MyEnumSeq es; + optional(20) FixedStructSeq fss; + optional(21) VarStructSeq vss; + optional(22) OneOptionalSeq oos; + optional(23) OneOptionalPrxSeq oops; + + optional(24) IntEnumDict ied; + optional(25) IntFixedStructDict ifsd; + optional(26) IntVarStructDict ivsd; + optional(27) IntOneOptionalDict iood; + optional(28) IntOneOptionalPrxDict ioopd; + + optional(29) BoolSeq bos; +}; + +class A +{ + int requiredA; + optional(1) int ma; + optional(50) int mb; + optional(500) int mc; +}; + +["preserve-slice"] +class B extends A +{ + int requiredB; + optional(10) int md; +}; + +class C extends B +{ + string ss; + optional(890) string ms; +}; + +class WD +{ + optional(1) int a = 5; + optional(2) string s = "test"; +}; + +exception OptionalException +{ + optional(1) int a = 5; + optional(2) string b; + optional(50) OneOptional o; +}; + +exception DerivedException extends OptionalException +{ + optional(600) string ss = "test"; + optional(601) OneOptional o2; +}; + +exception RequiredException extends OptionalException +{ + string ss = "test"; + OneOptional o2; +}; + +class OptionalWithCustom +{ + optional(1) SmallStructList l; + ["protected"] optional(2) SmallStructList lp; + optional(3) ClassVarStruct s; +}; + +["ami"] +class Initial +{ + void shutdown(); + + Object pingPong(Object o); + + void opOptionalException(optional(1) int a, optional(2) string b, optional(3) OneOptional o) + throws OptionalException; + + void opDerivedException(optional(1) int a, optional(2) string b, optional(3) OneOptional o) + throws OptionalException; + + void opRequiredException(optional(1) int a, optional(2) string b, optional(3) OneOptional o) + throws OptionalException; + + optional(1) byte opByte(optional(2) byte p1, out optional(3) byte p3); + + optional(1) bool opBool(optional(2) bool p1, out optional(3) bool p3); + + optional(1) short opShort(optional(2) short p1, out optional(3) short p3); + + optional(1) int opInt(optional(2) int p1, out optional(3) int p3); + + optional(3) long opLong(optional(1) long p1, out optional(2) long p3); + + optional(1) float opFloat(optional(2) float p1, out optional(3) float p3); + + optional(1) double opDouble(optional(2) double p1, out optional(3) double p3); + + optional(1) string opString(optional(2) string p1, out optional(3) string p3); + + optional(1) MyEnum opMyEnum(optional(2) MyEnum p1, out optional(3) MyEnum p3); + + optional(1) SmallStruct opSmallStruct(optional(2) SmallStruct p1, out optional(3) SmallStruct p3); + + optional(1) FixedStruct opFixedStruct(optional(2) FixedStruct p1, out optional(3) FixedStruct p3); + + optional(1) VarStruct opVarStruct(optional(2) VarStruct p1, out optional(3) VarStruct p3); + + optional(1) OneOptional opOneOptional(optional(2) OneOptional p1, out optional(3) OneOptional p3); + + optional(1) OneOptional* opOneOptionalProxy(optional(2) OneOptional* p1, out optional(3) OneOptional* p3); + + optional(1) ByteSeq opByteSeq(optional(2) ByteSeq p1, out optional(3) ByteSeq p3); + + optional(1) BoolSeq opBoolSeq(optional(2) BoolSeq p1, out optional(3) BoolSeq p3); + + optional(1) ShortSeq opShortSeq(optional(2) ShortSeq p1, out optional(3) ShortSeq p3); + + optional(1) IntSeq opIntSeq(optional(2) IntSeq p1, out optional(3) IntSeq p3); + + optional(1) LongSeq opLongSeq(optional(2) LongSeq p1, out optional(3) LongSeq p3); + + optional(1) FloatSeq opFloatSeq(optional(2) FloatSeq p1, out optional(3) FloatSeq p3); + + optional(1) DoubleSeq opDoubleSeq(optional(2) DoubleSeq p1, out optional(3) DoubleSeq p3); + + optional(1) StringSeq opStringSeq(optional(2) StringSeq p1, out optional(3) StringSeq p3); + + optional(1) SmallStructSeq opSmallStructSeq(optional(2) SmallStructSeq p1, out optional(3) SmallStructSeq p3); + + optional(1) SmallStructList opSmallStructList(optional(2) SmallStructList p1, out optional(3) SmallStructList p3); + + optional(1) FixedStructSeq opFixedStructSeq(optional(2) FixedStructSeq p1, out optional(3) FixedStructSeq p3); + + optional(1) FixedStructList opFixedStructList(optional(2) FixedStructList p1, out optional(3) FixedStructList p3); + + optional(1) VarStructSeq opVarStructSeq(optional(2) VarStructSeq p1, out optional(3) VarStructSeq p3); + + optional(1) IntIntDict opIntIntDict(optional(2) IntIntDict p1, out optional(3) IntIntDict p3); + + optional(1) StringIntDict opStringIntDict(optional(2) StringIntDict p1, out optional(3) StringIntDict p3); + + void opClassAndUnknownOptional(A p); +}; + +}; diff --git a/py/test/Ice/optional/TestAMD.ice b/py/test/Ice/optional/TestAMD.ice new file mode 100644 index 00000000000..871804cc143 --- /dev/null +++ b/py/test/Ice/optional/TestAMD.ice @@ -0,0 +1,236 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2012 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +#pragma once + +module Test +{ + +class OneOptional +{ + optional(1) int a; +}; + +enum MyEnum +{ + MyEnumMember +}; + +struct SmallStruct +{ + byte m; +}; + +struct FixedStruct +{ + int m; +}; + +struct VarStruct +{ + string m; +}; + +struct ClassVarStruct +{ + int a; +}; + +sequence<byte> ByteSeq; +sequence<bool> BoolSeq; +sequence<short> ShortSeq; +sequence<int> IntSeq; +sequence<long> LongSeq; +sequence<float> FloatSeq; +sequence<double> DoubleSeq; +sequence<string> StringSeq; +sequence<MyEnum> MyEnumSeq; +sequence<SmallStruct> SmallStructSeq; +["python:seq:tuple"] sequence<SmallStruct> SmallStructList; +sequence<FixedStruct> FixedStructSeq; +["python:seq:tuple"] sequence<FixedStruct> FixedStructList; +sequence<VarStruct> VarStructSeq; +sequence<OneOptional> OneOptionalSeq; +sequence<OneOptional*> OneOptionalPrxSeq; + +dictionary<int, int> IntIntDict; +dictionary<string, int> StringIntDict; +dictionary<int, MyEnum> IntEnumDict; +dictionary<int, FixedStruct> IntFixedStructDict; +dictionary<int, VarStruct> IntVarStructDict; +dictionary<int, OneOptional> IntOneOptionalDict; +dictionary<int, OneOptional*> IntOneOptionalPrxDict; + +class MultiOptional +{ + optional(1) byte a; + optional(2) bool b; + optional(3) short c; + optional(4) int d; + optional(5) long e; + optional(6) float f; + optional(7) double g; + optional(8) string h; + optional(9) MyEnum i; + optional(10) MultiOptional* j; + optional(11) MultiOptional k; + optional(12) ByteSeq bs; + optional(13) StringSeq ss; + optional(14) IntIntDict iid; + optional(15) StringIntDict sid; + optional(16) FixedStruct fs; + optional(17) VarStruct vs; + + optional(18) ShortSeq shs; + optional(19) MyEnumSeq es; + optional(20) FixedStructSeq fss; + optional(21) VarStructSeq vss; + optional(22) OneOptionalSeq oos; + optional(23) OneOptionalPrxSeq oops; + + optional(24) IntEnumDict ied; + optional(25) IntFixedStructDict ifsd; + optional(26) IntVarStructDict ivsd; + optional(27) IntOneOptionalDict iood; + optional(28) IntOneOptionalPrxDict ioopd; + + optional(29) BoolSeq bos; +}; + +class A +{ + int requiredA; + optional(1) int ma; + optional(50) int mb; + optional(500) int mc; +}; + +["preserve-slice"] +class B extends A +{ + int requiredB; + optional(10) int md; +}; + +class C extends B +{ + string ss; + optional(890) string ms; +}; + +class WD +{ + optional(1) int a = 5; + optional(2) string s = "test"; +}; + +exception OptionalException +{ + optional(1) int a = 5; + optional(2) string b; + optional(50) OneOptional o; +}; + +exception DerivedException extends OptionalException +{ + optional(600) string ss = "test"; + optional(601) OneOptional o2; +}; + +exception RequiredException extends OptionalException +{ + string ss = "test"; + OneOptional o2; +}; + +class OptionalWithCustom +{ + optional(1) SmallStructList l; + ["protected"] optional(2) SmallStructList lp; + optional(3) ClassVarStruct s; +}; + +["ami", "amd"] +class Initial +{ + void shutdown(); + + Object pingPong(Object o); + + void opOptionalException(optional(1) int a, optional(2) string b, optional(3) OneOptional o) + throws OptionalException; + + void opDerivedException(optional(1) int a, optional(2) string b, optional(3) OneOptional o) + throws OptionalException; + + void opRequiredException(optional(1) int a, optional(2) string b, optional(3) OneOptional o) + throws OptionalException; + + optional(1) byte opByte(optional(2) byte p1, out optional(3) byte p3); + + optional(1) bool opBool(optional(2) bool p1, out optional(3) bool p3); + + optional(1) short opShort(optional(2) short p1, out optional(3) short p3); + + optional(1) int opInt(optional(2) int p1, out optional(3) int p3); + + optional(3) long opLong(optional(1) long p1, out optional(2) long p3); + + optional(1) float opFloat(optional(2) float p1, out optional(3) float p3); + + optional(1) double opDouble(optional(2) double p1, out optional(3) double p3); + + optional(1) string opString(optional(2) string p1, out optional(3) string p3); + + optional(1) MyEnum opMyEnum(optional(2) MyEnum p1, out optional(3) MyEnum p3); + + optional(1) SmallStruct opSmallStruct(optional(2) SmallStruct p1, out optional(3) SmallStruct p3); + + optional(1) FixedStruct opFixedStruct(optional(2) FixedStruct p1, out optional(3) FixedStruct p3); + + optional(1) VarStruct opVarStruct(optional(2) VarStruct p1, out optional(3) VarStruct p3); + + optional(1) OneOptional opOneOptional(optional(2) OneOptional p1, out optional(3) OneOptional p3); + + optional(1) OneOptional* opOneOptionalProxy(optional(2) OneOptional* p1, out optional(3) OneOptional* p3); + + optional(1) ByteSeq opByteSeq(optional(2) ByteSeq p1, out optional(3) ByteSeq p3); + + optional(1) BoolSeq opBoolSeq(optional(2) BoolSeq p1, out optional(3) BoolSeq p3); + + optional(1) ShortSeq opShortSeq(optional(2) ShortSeq p1, out optional(3) ShortSeq p3); + + optional(1) IntSeq opIntSeq(optional(2) IntSeq p1, out optional(3) IntSeq p3); + + optional(1) LongSeq opLongSeq(optional(2) LongSeq p1, out optional(3) LongSeq p3); + + optional(1) FloatSeq opFloatSeq(optional(2) FloatSeq p1, out optional(3) FloatSeq p3); + + optional(1) DoubleSeq opDoubleSeq(optional(2) DoubleSeq p1, out optional(3) DoubleSeq p3); + + optional(1) StringSeq opStringSeq(optional(2) StringSeq p1, out optional(3) StringSeq p3); + + optional(1) SmallStructSeq opSmallStructSeq(optional(2) SmallStructSeq p1, out optional(3) SmallStructSeq p3); + + optional(1) SmallStructList opSmallStructList(optional(2) SmallStructList p1, out optional(3) SmallStructList p3); + + optional(1) FixedStructSeq opFixedStructSeq(optional(2) FixedStructSeq p1, out optional(3) FixedStructSeq p3); + + optional(1) FixedStructList opFixedStructList(optional(2) FixedStructList p1, out optional(3) FixedStructList p3); + + optional(1) VarStructSeq opVarStructSeq(optional(2) VarStructSeq p1, out optional(3) VarStructSeq p3); + + optional(1) IntIntDict opIntIntDict(optional(2) IntIntDict p1, out optional(3) IntIntDict p3); + + optional(1) StringIntDict opStringIntDict(optional(2) StringIntDict p1, out optional(3) StringIntDict p3); + + void opClassAndUnknownOptional(A p); +}; + +}; diff --git a/py/test/Ice/optional/run.py b/py/test/Ice/optional/run.py new file mode 100755 index 00000000000..4d508c1da8e --- /dev/null +++ b/py/test/Ice/optional/run.py @@ -0,0 +1,28 @@ +#!/usr/bin/env python +# ********************************************************************** +# +# Copyright (c) 2003-2012 ZeroC, Inc. All rights reserved. +# +# This copy of Ice is licensed to you under the terms described in the +# ICE_LICENSE file included in this distribution. +# +# ********************************************************************** + +import os, sys + +path = [ ".", "..", "../..", "../../..", "../../../.." ] +head = os.path.dirname(sys.argv[0]) +if len(head) > 0: + path = [os.path.join(head, p) for p in path] +path = [os.path.abspath(p) for p in path if os.path.exists(os.path.join(p, "scripts", "TestUtil.py")) ] +if len(path) == 0: + raise RuntimeError("can't find toplevel directory!") +sys.path.append(os.path.join(path[0], "scripts")) +import TestUtil + +print("Running test with compact (default) format.") +TestUtil.clientServerTest() +print("Running test with sliced format.") +TestUtil.clientServerTest(additionalClientOptions="--Ice.Default.SlicedFormat", additionalServerOptions="--Ice.Default.SlicedFormat") +print("Running test with AMD server.") +TestUtil.clientServerTest(server="ServerAMD.py") diff --git a/py/test/Ice/slicing/objects/AllTests.py b/py/test/Ice/slicing/objects/AllTests.py index 0ae2726c152..567074be5a8 100644 --- a/py/test/Ice/slicing/objects/AllTests.py +++ b/py/test/Ice/slicing/objects/AllTests.py @@ -71,13 +71,21 @@ class Callback(CallbackBase): test(isinstance(ex, Ice.MarshalException)) self.called() - def response_SUnknownAsObject(self, o): + def response_SUnknownAsObject10(self, o): test(False) - def exception_SUnknownAsObject(self, exc): + def exception_SUnknownAsObject10(self, exc): test(exc.ice_name() == "Ice::NoObjectFactoryException") self.called() + def response_SUnknownAsObject11(self, o): + test(isinstance(o, Ice.UnknownSlicedObject)) + test(o.unknownTypeId == "::Test::SUnknown") + self.called() + + def exception_SUnknownAsObject11(self, exc): + test(False) + def response_oneElementCycle(self, b): test(b) test(b.ice_id() == "::Test::B") @@ -494,10 +502,14 @@ def allTests(communicator): sys.stdout.flush() try: o = t.SUnknownAsObject() - test(False) + test(t.ice_getEncodingVersion() != Ice.Encoding_1_0) + test(isinstance(o, Ice.UnknownSlicedObject)) + test(o.unknownTypeId == "::Test::SUnknown") + t.checkSUnknown(o) except Ice.NoObjectFactoryException: - pass - except Ice.Exception: + test(t.ice_getEncodingVersion() == Ice.Encoding_1_0) + except Ice.Exception as ex: + print ex test(False) print("ok") @@ -505,10 +517,11 @@ def allTests(communicator): sys.stdout.flush() try: cb = Callback() - t.begin_SUnknownAsObject(cb.response_SUnknownAsObject, cb.exception_SUnknownAsObject) + if t.ice_getEncodingVersion() == Ice.Encoding_1_0: + t.begin_SUnknownAsObject(cb.response_SUnknownAsObject10, cb.exception_SUnknownAsObject10) + else: + t.begin_SUnknownAsObject(cb.response_SUnknownAsObject11, cb.exception_SUnknownAsObject11) cb.check() - except Ice.NoObjectFactoryException: - pass except Ice.Exception: test(False) print("ok") diff --git a/py/test/Ice/slicing/objects/Server.py b/py/test/Ice/slicing/objects/Server.py index 181912cc2c4..8528c551bc8 100755 --- a/py/test/Ice/slicing/objects/Server.py +++ b/py/test/Ice/slicing/objects/Server.py @@ -58,6 +58,13 @@ class TestI(Test.TestIntf): su.su = "SUnknown.su" return su + def checkSUnknown(self, obj, current=None): + if current.encoding == Ice.Encoding_1_0: + test(not isinstance(obj, Test.SUnknown)) + else: + test(isinstance(obj, Test.SUnknown)) + test(obj.su == "SUnknown.su") + def oneElementCycle(self, current=None): b = Test.B() b.sb = "B1.sb" diff --git a/py/test/Ice/slicing/objects/ServerAMD.py b/py/test/Ice/slicing/objects/ServerAMD.py index defd04f96c8..b3da8242d67 100755 --- a/py/test/Ice/slicing/objects/ServerAMD.py +++ b/py/test/Ice/slicing/objects/ServerAMD.py @@ -58,6 +58,14 @@ class TestI(Test.TestIntf): su.su = "SUnknown.su" cb.ice_response(su) + def checkSUnknown_async(self, cb, obj, current=None): + if current.encoding == Ice.Encoding_1_0: + test(not isinstance(obj, Test.SUnknown)) + else: + test(isinstance(obj, Test.SUnknown)) + test(obj.su == "SUnknown.su") + cb.ice_response() + def oneElementCycle_async(self, cb, current=None): b = Test.B() b.sb = "B1.sb" diff --git a/py/test/Ice/slicing/objects/Test.ice b/py/test/Ice/slicing/objects/Test.ice index 8e20db55def..1272f947d8b 100644 --- a/py/test/Ice/slicing/objects/Test.ice +++ b/py/test/Ice/slicing/objects/Test.ice @@ -110,6 +110,7 @@ interface TestIntf ["format:compact"] SBase SBSUnknownDerivedAsSBaseCompact(); Object SUnknownAsObject(); + void checkSUnknown(Object o); B oneElementCycle(); B twoElementCycle(); diff --git a/py/test/Ice/slicing/objects/TestAMD.ice b/py/test/Ice/slicing/objects/TestAMD.ice index ccc239f69f4..97833f2a438 100644 --- a/py/test/Ice/slicing/objects/TestAMD.ice +++ b/py/test/Ice/slicing/objects/TestAMD.ice @@ -110,6 +110,7 @@ interface TestIntf ["format:compact"] SBase SBSUnknownDerivedAsSBaseCompact(); Object SUnknownAsObject(); + void checkSUnknown(Object o); B oneElementCycle(); B twoElementCycle(); |