summaryrefslogtreecommitdiff
path: root/py
diff options
context:
space:
mode:
authorMark Spruiell <mes@zeroc.com>2012-10-17 12:38:03 -0700
committerMark Spruiell <mes@zeroc.com>2012-10-17 12:38:03 -0700
commitf087326373250c76fa3b7b8e68cede0cb9af01ff (patch)
treee801ec18aba93a74b373388fc947617643da0008 /py
parentFix related to ICE-4847 (diff)
downloadice-f087326373250c76fa3b7b8e68cede0cb9af01ff.tar.bz2
ice-f087326373250c76fa3b7b8e68cede0cb9af01ff.tar.xz
ice-f087326373250c76fa3b7b8e68cede0cb9af01ff.zip
ICE-4619 - custom enumerator values
Diffstat (limited to 'py')
-rwxr-xr-xpy/allTests.py3
-rw-r--r--py/modules/IcePy/Types.cpp59
-rw-r--r--py/modules/IcePy/Types.h5
-rw-r--r--py/python/Ice.py64
-rw-r--r--py/test/Ice/enums/AllTests.py128
-rwxr-xr-xpy/test/Ice/enums/Client.py36
-rwxr-xr-xpy/test/Ice/enums/Server.py60
-rw-r--r--py/test/Ice/enums/Test.ice88
-rwxr-xr-xpy/test/Ice/enums/run.py26
9 files changed, 444 insertions, 25 deletions
diff --git a/py/allTests.py b/py/allTests.py
index d43e65c8c9e..8a39d497bcf 100755
--- a/py/allTests.py
+++ b/py/allTests.py
@@ -49,7 +49,8 @@ tests = [
("Ice/defaultServant", ["core"]),
("Ice/defaultValue", ["core"]),
("Ice/ami", ["core"]),
- ("Ice/optional", ["core"])
+ ("Ice/optional", ["core"]),
+ ("Ice/enums", ["core"])
]
if __name__ == "__main__":
diff --git a/py/modules/IcePy/Types.cpp b/py/modules/IcePy/Types.cpp
index d2c1696b881..c68b1f3da90 100644
--- a/py/modules/IcePy/Types.cpp
+++ b/py/modules/IcePy/Types.cpp
@@ -884,20 +884,34 @@ 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)
+ id(ident), pythonType(t), maxValue(0)
{
assert(PyType_Check(t));
- assert(PyTuple_Check(e));
+ assert(PyDict_Check(e));
Py_INCREF(t);
- Py_ssize_t sz = PyTuple_GET_SIZE(e);
- for(Py_ssize_t i = 0; i < sz; ++i)
+ Py_ssize_t pos = 0;
+ PyObject* key;
+ PyObject* value;
+ while(PyDict_Next(e, &pos, &key, &value))
{
- PyObjectHandle h = PyTuple_GET_ITEM(e, i);
- Py_INCREF(h.get());
- assert(PyObject_IsInstance(h.get(), t));
- const_cast<EnumeratorList&>(enumerators).push_back(h);
+#if PY_VERSION_HEX >= 0x03000000
+ assert(PyLong_Check(key));
+#else
+ assert(PyInt_Check(key));
+#endif
+ const Ice::Int val = static_cast<Ice::Int>(PyLong_AsLong(key));
+ assert(enumerators.find(val) == enumerators.end());
+
+ Py_INCREF(value);
+ assert(PyObject_IsInstance(value, t));
+ const_cast<EnumeratorMap&>(enumerators)[val] = value;
+
+ if(val > maxValue)
+ {
+ const_cast<Ice::Int&>(maxValue) = val;
+ }
}
}
@@ -939,46 +953,47 @@ IcePy::EnumInfo::marshal(PyObject* p, const Ice::OutputStreamPtr& os, ObjectMap*
//
// Validate value.
//
- PyObjectHandle val = PyObject_GetAttrString(p, STRCAST("value"));
- if(!val.get())
+ PyObjectHandle v = PyObject_GetAttrString(p, STRCAST("_value"));
+ if(!v.get())
{
assert(PyErr_Occurred());
throw AbortMarshaling();
}
#if PY_VERSION_HEX >= 0x03000000
- if(!PyLong_Check(val.get()))
+ if(!PyLong_Check(v.get()))
#else
- if(!PyInt_Check(val.get()))
+ if(!PyInt_Check(v.get()))
#endif
{
PyErr_Format(PyExc_ValueError, STRCAST("value for enum %s is not an int"), id.c_str());
throw AbortMarshaling();
}
- Ice::Int ival = static_cast<Ice::Int>(PyLong_AsLong(val.get()));
- Ice::Int count = static_cast<Ice::Int>(enumerators.size());
- if(ival < 0 || ival >= count)
+ const Ice::Int val = static_cast<Ice::Int>(PyLong_AsLong(v.get()));
+ if(enumerators.find(val) == enumerators.end())
{
- PyErr_Format(PyExc_ValueError, STRCAST("value %d is out of range for enum %s"), ival, id.c_str());
+ PyErr_Format(PyExc_ValueError, STRCAST("illegal value %d for enum %s"), val, id.c_str());
throw AbortMarshaling();
}
- os->writeEnum(ival, count);
+ os->writeEnum(val, maxValue);
}
void
IcePy::EnumInfo::unmarshal(const Ice::InputStreamPtr& is, const UnmarshalCallbackPtr& cb, PyObject* target,
void* closure, bool, const Ice::StringSeq*)
{
- Ice::Int count = static_cast<Ice::Int>(enumerators.size());
- Ice::Int val = is->readEnum(count);
+ Ice::Int val = is->readEnum(maxValue);
- if(val < 0 || val >= count)
+ EnumeratorMap::const_iterator p = enumerators.find(val);
+ if(p == enumerators.end())
{
- PyErr_Format(PyExc_ValueError, STRCAST("enumerator %d is out of range for enum %s"), val, id.c_str());
+ ostringstream ostr;
+ ostr << "enumerator " << val << " is out of range for enum " << id;
+ setPythonException(Ice::MarshalException(__FILE__, __LINE__, ostr.str()));
throw AbortMarshaling();
}
- PyObject* pyval = enumerators[val].get();
+ PyObject* pyval = p->second.get();
assert(pyval);
cb->unmarshaled(pyval, target, closure);
}
diff --git a/py/modules/IcePy/Types.h b/py/modules/IcePy/Types.h
index 9c76fc372cb..cf969fbb1f0 100644
--- a/py/modules/IcePy/Types.h
+++ b/py/modules/IcePy/Types.h
@@ -171,7 +171,7 @@ typedef IceUtil::Handle<PrimitiveInfo> PrimitiveInfoPtr;
//
// Enum information.
//
-typedef std::vector<PyObjectHandle> EnumeratorList;
+typedef std::map<Ice::Int, PyObjectHandle> EnumeratorMap;
class EnumInfo : public TypeInfo
{
@@ -194,8 +194,9 @@ public:
virtual void print(PyObject*, IceUtilInternal::Output&, PrintObjectHistory*);
const std::string id;
- const EnumeratorList enumerators;
const PyObjectHandle pythonType;
+ const Ice::Int maxValue;
+ const EnumeratorMap enumerators;
};
typedef IceUtil::Handle<EnumInfo> EnumInfoPtr;
diff --git a/py/python/Ice.py b/py/python/Ice.py
index 5790c64cd8a..e371ffe15fa 100644
--- a/py/python/Ice.py
+++ b/py/python/Ice.py
@@ -189,6 +189,70 @@ class UserException(Exception):
'''The base class for all user-defined exceptions.'''
pass
+class EnumBase(object):
+ def __init__(self, _n, _v):
+ self._name = _n
+ self._value = _v
+
+ def __str__(self):
+ return self._name
+
+ __repr__ = __str__
+
+ def __hash__(self):
+ return self._value
+
+ def __lt__(self, other):
+ if isinstance(other, self.__class__):
+ return self._value < other._value;
+ elif other == None:
+ return False
+ return NotImplemented
+
+ def __le__(self, other):
+ if isinstance(other, self.__class__):
+ return self._value <= other._value;
+ elif other == None:
+ return False
+ return NotImplemented
+
+ def __eq__(self, other):
+ if isinstance(other, self.__class__):
+ return self._value == other._value;
+ elif other == None:
+ return False
+ return NotImplemented
+
+ def __ne__(self, other):
+ if isinstance(other, self.__class__):
+ return self._value != other._value;
+ elif other == None:
+ return False
+ return NotImplemented
+
+ def __gt__(self, other):
+ if isinstance(other, self.__class__):
+ return self._value > other._value;
+ elif other == None:
+ return False
+ return NotImplemented
+
+ def __ge__(self, other):
+ if isinstance(other, self.__class__):
+ return self._value >= other._value;
+ elif other == None:
+ return False
+ return NotImplemented
+
+ def _getName(self):
+ return self._name
+
+ def _getValue(self):
+ return self._value
+
+ name = property(_getName)
+ value = property(_getValue)
+
class SlicedData(object):
#
# Members:
diff --git a/py/test/Ice/enums/AllTests.py b/py/test/Ice/enums/AllTests.py
new file mode 100644
index 00000000000..cf15f80411a
--- /dev/null
+++ b/py/test/Ice/enums/AllTests.py
@@ -0,0 +1,128 @@
+# **********************************************************************
+#
+# 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 sys, string, re, traceback, Ice, Test
+
+def test(b):
+ if not b:
+ raise RuntimeError('test assertion failed')
+
+def allTests(communicator):
+ ref = "test:default -p 12010"
+ base = communicator.stringToProxy(ref)
+ test(base)
+
+ proxy = Test.TestIntfPrx.checkedCast(base)
+ test(proxy)
+
+ sys.stdout.write("testing enum values... ")
+ sys.stdout.flush()
+
+ test(Test.ByteEnum.benum1.value == 0);
+ test(Test.ByteEnum.benum2.value == 1);
+ test(Test.ByteEnum.benum3.value == Test.ByteConst1);
+ test(Test.ByteEnum.benum4.value == Test.ByteConst1 + 1);
+ test(Test.ByteEnum.benum5.value == Test.ShortConst1);
+ test(Test.ByteEnum.benum6.value == Test.ShortConst1 + 1);
+ test(Test.ByteEnum.benum7.value == Test.IntConst1);
+ test(Test.ByteEnum.benum8.value == Test.IntConst1 + 1);
+ test(Test.ByteEnum.benum9.value == Test.LongConst1);
+ test(Test.ByteEnum.benum10.value == Test.LongConst1 + 1);
+ test(Test.ByteEnum.benum11.value == Test.ByteConst2);
+
+ test(Test.ByteEnum.valueOf(0) == Test.ByteEnum.benum1);
+ test(Test.ByteEnum.valueOf(1) == Test.ByteEnum.benum2);
+ test(Test.ByteEnum.valueOf(Test.ByteConst1) == Test.ByteEnum.benum3);
+ test(Test.ByteEnum.valueOf(Test.ByteConst1 + 1) == Test.ByteEnum.benum4);
+ test(Test.ByteEnum.valueOf(Test.ShortConst1) == Test.ByteEnum.benum5);
+ test(Test.ByteEnum.valueOf(Test.ShortConst1 + 1) == Test.ByteEnum.benum6);
+ test(Test.ByteEnum.valueOf(Test.IntConst1) == Test.ByteEnum.benum7);
+ test(Test.ByteEnum.valueOf(Test.IntConst1 + 1) == Test.ByteEnum.benum8);
+ test(Test.ByteEnum.valueOf(Test.LongConst1) == Test.ByteEnum.benum9);
+ test(Test.ByteEnum.valueOf(Test.LongConst1 + 1) == Test.ByteEnum.benum10);
+ test(Test.ByteEnum.valueOf(Test.ByteConst2) == Test.ByteEnum.benum11);
+
+ test(Test.ShortEnum.senum1.value == 3);
+ test(Test.ShortEnum.senum2.value == 4);
+ test(Test.ShortEnum.senum3.value == Test.ByteConst1);
+ test(Test.ShortEnum.senum4.value == Test.ByteConst1 + 1);
+ test(Test.ShortEnum.senum5.value == Test.ShortConst1);
+ test(Test.ShortEnum.senum6.value == Test.ShortConst1 + 1);
+ test(Test.ShortEnum.senum7.value == Test.IntConst1);
+ test(Test.ShortEnum.senum8.value == Test.IntConst1 + 1);
+ test(Test.ShortEnum.senum9.value == Test.LongConst1);
+ test(Test.ShortEnum.senum10.value == Test.LongConst1 + 1);
+ test(Test.ShortEnum.senum11.value == Test.ShortConst2);
+
+ test(Test.ShortEnum.valueOf(3) == Test.ShortEnum.senum1);
+ test(Test.ShortEnum.valueOf(4) == Test.ShortEnum.senum2);
+ test(Test.ShortEnum.valueOf(Test.ByteConst1) == Test.ShortEnum.senum3);
+ test(Test.ShortEnum.valueOf(Test.ByteConst1 + 1) == Test.ShortEnum.senum4);
+ test(Test.ShortEnum.valueOf(Test.ShortConst1) == Test.ShortEnum.senum5);
+ test(Test.ShortEnum.valueOf(Test.ShortConst1 + 1) == Test.ShortEnum.senum6);
+ test(Test.ShortEnum.valueOf(Test.IntConst1) == Test.ShortEnum.senum7);
+ test(Test.ShortEnum.valueOf(Test.IntConst1 + 1) == Test.ShortEnum.senum8);
+ test(Test.ShortEnum.valueOf(Test.LongConst1) == Test.ShortEnum.senum9);
+ test(Test.ShortEnum.valueOf(Test.LongConst1 + 1) == Test.ShortEnum.senum10);
+ test(Test.ShortEnum.valueOf(Test.ShortConst2) == Test.ShortEnum.senum11);
+
+ test(Test.IntEnum.ienum1.value == 0);
+ test(Test.IntEnum.ienum2.value == 1);
+ test(Test.IntEnum.ienum3.value == Test.ByteConst1);
+ test(Test.IntEnum.ienum4.value == Test.ByteConst1 + 1);
+ test(Test.IntEnum.ienum5.value == Test.ShortConst1);
+ test(Test.IntEnum.ienum6.value == Test.ShortConst1 + 1);
+ test(Test.IntEnum.ienum7.value == Test.IntConst1);
+ test(Test.IntEnum.ienum8.value == Test.IntConst1 + 1);
+ test(Test.IntEnum.ienum9.value == Test.LongConst1);
+ test(Test.IntEnum.ienum10.value == Test.LongConst1 + 1);
+ test(Test.IntEnum.ienum11.value == Test.IntConst2);
+ test(Test.IntEnum.ienum12.value == Test.LongConst2);
+
+ test(Test.IntEnum.valueOf(0) == Test.IntEnum.ienum1);
+ test(Test.IntEnum.valueOf(1) == Test.IntEnum.ienum2);
+ test(Test.IntEnum.valueOf(Test.ByteConst1) == Test.IntEnum.ienum3);
+ test(Test.IntEnum.valueOf(Test.ByteConst1 + 1) == Test.IntEnum.ienum4);
+ test(Test.IntEnum.valueOf(Test.ShortConst1) == Test.IntEnum.ienum5);
+ test(Test.IntEnum.valueOf(Test.ShortConst1 + 1) == Test.IntEnum.ienum6);
+ test(Test.IntEnum.valueOf(Test.IntConst1) == Test.IntEnum.ienum7);
+ test(Test.IntEnum.valueOf(Test.IntConst1 + 1) == Test.IntEnum.ienum8);
+ test(Test.IntEnum.valueOf(Test.LongConst1) == Test.IntEnum.ienum9);
+ test(Test.IntEnum.valueOf(Test.LongConst1 + 1) == Test.IntEnum.ienum10);
+ test(Test.IntEnum.valueOf(Test.IntConst2) == Test.IntEnum.ienum11);
+ test(Test.IntEnum.valueOf(Test.LongConst2) == Test.IntEnum.ienum12);
+
+ test(Test.SimpleEnum.red.value == 0);
+ test(Test.SimpleEnum.green.value == 1);
+ test(Test.SimpleEnum.blue.value == 2);
+
+ test(Test.SimpleEnum.valueOf(0) == Test.SimpleEnum.red);
+ test(Test.SimpleEnum.valueOf(1) == Test.SimpleEnum.green);
+ test(Test.SimpleEnum.valueOf(2) == Test.SimpleEnum.blue);
+
+ print("ok")
+
+ sys.stdout.write("testing enum operations... ")
+ sys.stdout.flush()
+
+ test(proxy.opByte(Test.ByteEnum.benum1) == (Test.ByteEnum.benum1, Test.ByteEnum.benum1));
+ test(proxy.opByte(Test.ByteEnum.benum11) == (Test.ByteEnum.benum11, Test.ByteEnum.benum11));
+
+ test(proxy.opShort(Test.ShortEnum.senum1) == (Test.ShortEnum.senum1, Test.ShortEnum.senum1));
+ test(proxy.opShort(Test.ShortEnum.senum11) == (Test.ShortEnum.senum11, Test.ShortEnum.senum11));
+
+ test(proxy.opInt(Test.IntEnum.ienum1) == (Test.IntEnum.ienum1, Test.IntEnum.ienum1));
+ test(proxy.opInt(Test.IntEnum.ienum11) == (Test.IntEnum.ienum11, Test.IntEnum.ienum11));
+ test(proxy.opInt(Test.IntEnum.ienum12) == (Test.IntEnum.ienum12, Test.IntEnum.ienum12));
+
+ test(proxy.opSimple(Test.SimpleEnum.green) == (Test.SimpleEnum.green, Test.SimpleEnum.green));
+
+ print("ok")
+
+ return proxy
diff --git a/py/test/Ice/enums/Client.py b/py/test/Ice/enums/Client.py
new file mode 100755
index 00000000000..e4423fe3d5e
--- /dev/null
+++ b/py/test/Ice/enums/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('Test.ice')
+import Test, AllTests
+
+def run(args, communicator):
+ proxy = AllTests.allTests(communicator)
+ proxy.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/enums/Server.py b/py/test/Ice/enums/Server.py
new file mode 100755
index 00000000000..f43dc1b4404
--- /dev/null
+++ b/py/test/Ice/enums/Server.py
@@ -0,0 +1,60 @@
+#!/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
+
+def test(b):
+ if not b:
+ raise RuntimeError('test assertion failed')
+
+class TestIntfI(Test.TestIntf):
+ def opByte(self, b1, current=None):
+ return (b1, b1)
+
+ def opShort(self, s1, current=None):
+ return (s1, s1)
+
+ def opInt(self, i1, current=None):
+ return (i1, i1)
+
+ def opSimple(self, s1, current=None):
+ return (s1, s1)
+
+ def shutdown(self, current=None):
+ current.adapter.getCommunicator().shutdown()
+
+def run(args, communicator):
+ communicator.getProperties().setProperty("TestAdapter.Endpoints", "default -p 12010")
+ adapter = communicator.createObjectAdapter("TestAdapter")
+ object = TestIntfI()
+ adapter.add(object, communicator.stringToIdentity("test"))
+ 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/enums/Test.ice b/py/test/Ice/enums/Test.ice
new file mode 100644
index 00000000000..cb77421cd84
--- /dev/null
+++ b/py/test/Ice/enums/Test.ice
@@ -0,0 +1,88 @@
+// **********************************************************************
+//
+// 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
+{
+
+const byte ByteConst1 = 10;
+const short ShortConst1 = 20;
+const int IntConst1 = 30;
+const long LongConst1 = 40;
+
+const byte ByteConst2 = 126;
+const short ShortConst2 = 32766;
+const int IntConst2 = 2147483647;
+const long LongConst2 = 2147483646;
+
+enum ByteEnum
+{
+ benum1,
+ benum2,
+ benum3 = ByteConst1,
+ benum4,
+ benum5 = ShortConst1,
+ benum6,
+ benum7 = IntConst1,
+ benum8,
+ benum9 = LongConst1,
+ benum10,
+ benum11 = ByteConst2
+};
+
+enum ShortEnum
+{
+ senum1 = 3,
+ senum2,
+ senum3 = ByteConst1,
+ senum4,
+ senum5 = ShortConst1,
+ senum6,
+ senum7 = IntConst1,
+ senum8,
+ senum9 = LongConst1,
+ senum10,
+ senum11 = ShortConst2
+};
+
+enum IntEnum
+{
+ ienum1,
+ ienum2,
+ ienum3 = ByteConst1,
+ ienum4,
+ ienum5 = ShortConst1,
+ ienum6,
+ ienum7 = IntConst1,
+ ienum8,
+ ienum9 = LongConst1,
+ ienum10,
+ ienum11 = IntConst2,
+ ienum12 = LongConst2
+};
+
+enum SimpleEnum
+{
+ red,
+ green,
+ blue
+};
+
+interface TestIntf
+{
+ ByteEnum opByte(ByteEnum b1, out ByteEnum b2);
+ ShortEnum opShort(ShortEnum s1, out ShortEnum s2);
+ IntEnum opInt(IntEnum i1, out IntEnum i2);
+ SimpleEnum opSimple(SimpleEnum s1, out SimpleEnum s2);
+
+ void shutdown();
+};
+
+};
diff --git a/py/test/Ice/enums/run.py b/py/test/Ice/enums/run.py
new file mode 100755
index 00000000000..ecadfca52b9
--- /dev/null
+++ b/py/test/Ice/enums/run.py
@@ -0,0 +1,26 @@
+#!/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 1.0 encoding.")
+TestUtil.clientServerTest(additionalClientOptions="--Ice.Default.EncodingVersion=1.0", additionalServerOptions="--Ice.Default.EncodingVersion=1.0")
+print("Running test with 1.1 encoding.")
+TestUtil.clientServerTest()