diff options
author | Mark Spruiell <mes@zeroc.com> | 2012-10-17 12:38:03 -0700 |
---|---|---|
committer | Mark Spruiell <mes@zeroc.com> | 2012-10-17 12:38:03 -0700 |
commit | f087326373250c76fa3b7b8e68cede0cb9af01ff (patch) | |
tree | e801ec18aba93a74b373388fc947617643da0008 /py | |
parent | Fix related to ICE-4847 (diff) | |
download | ice-f087326373250c76fa3b7b8e68cede0cb9af01ff.tar.bz2 ice-f087326373250c76fa3b7b8e68cede0cb9af01ff.tar.xz ice-f087326373250c76fa3b7b8e68cede0cb9af01ff.zip |
ICE-4619 - custom enumerator values
Diffstat (limited to 'py')
-rwxr-xr-x | py/allTests.py | 3 | ||||
-rw-r--r-- | py/modules/IcePy/Types.cpp | 59 | ||||
-rw-r--r-- | py/modules/IcePy/Types.h | 5 | ||||
-rw-r--r-- | py/python/Ice.py | 64 | ||||
-rw-r--r-- | py/test/Ice/enums/AllTests.py | 128 | ||||
-rwxr-xr-x | py/test/Ice/enums/Client.py | 36 | ||||
-rwxr-xr-x | py/test/Ice/enums/Server.py | 60 | ||||
-rw-r--r-- | py/test/Ice/enums/Test.ice | 88 | ||||
-rwxr-xr-x | py/test/Ice/enums/run.py | 26 |
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() |