summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Spruiell <mes@zeroc.com>2012-09-14 15:30:12 -0700
committerMark Spruiell <mes@zeroc.com>2012-09-14 15:30:12 -0700
commitc912d30d47799bbba77d0f2532704d8aaba12a4a (patch)
tree8611fdb0b73a9a78f7c319ca4bb08f1f9d2e9cd0
parentFixed optional test issues (diff)
downloadice-c912d30d47799bbba77d0f2532704d8aaba12a4a.tar.bz2
ice-c912d30d47799bbba77d0f2532704d8aaba12a4a.tar.xz
ice-c912d30d47799bbba77d0f2532704d8aaba12a4a.zip
Python support for optionals
-rw-r--r--cpp/include/Ice/BasicStream.h15
-rw-r--r--cpp/include/Ice/SlicedData.h2
-rw-r--r--cpp/include/Ice/Stream.h9
-rwxr-xr-xcpp/src/Ice/BasicStream.cpp39
-rw-r--r--cpp/src/Ice/SlicedData.cpp6
-rw-r--r--cpp/src/Ice/StreamI.cpp16
-rw-r--r--cpp/src/Ice/StreamI.h5
-rwxr-xr-xcpp/src/Slice/PythonUtil.cpp47
-rw-r--r--cs/test/Ice/optional/AllTests.cs4
-rw-r--r--cs/test/Ice/optional/Test.ice2
-rw-r--r--cs/test/Ice/optional/TestAMD.ice2
-rw-r--r--cs/test/Ice/optional/TestI.cs19
-rw-r--r--java/test/Ice/optional/AllTests.java4
-rw-r--r--java/test/Ice/optional/Test.ice4
-rw-r--r--java/test/Ice/optional/TestAMD.ice4
-rwxr-xr-xpy/allTests.py3
-rw-r--r--py/modules/IcePy/ObjectFactory.cpp15
-rw-r--r--py/modules/IcePy/Operation.cpp414
-rw-r--r--py/modules/IcePy/Types.cpp1178
-rw-r--r--py/modules/IcePy/Types.h191
-rw-r--r--py/modules/IcePy/Util.cpp17
-rw-r--r--py/python/Ice.py17
-rw-r--r--py/test/Ice/optional/AllTests.py724
-rwxr-xr-xpy/test/Ice/optional/Client.py36
-rw-r--r--py/test/Ice/optional/ClientPrivate.ice37
-rwxr-xr-xpy/test/Ice/optional/Server.py156
-rwxr-xr-xpy/test/Ice/optional/ServerAMD.py157
-rw-r--r--py/test/Ice/optional/Test.ice236
-rw-r--r--py/test/Ice/optional/TestAMD.ice236
-rwxr-xr-xpy/test/Ice/optional/run.py28
-rw-r--r--py/test/Ice/slicing/objects/AllTests.py29
-rwxr-xr-xpy/test/Ice/slicing/objects/Server.py7
-rwxr-xr-xpy/test/Ice/slicing/objects/ServerAMD.py8
-rw-r--r--py/test/Ice/slicing/objects/Test.ice1
-rw-r--r--py/test/Ice/slicing/objects/TestAMD.ice1
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();