ASPN ActiveState Programmer Network
ActiveState
/ Home / Perl / PHP / Python / Tcl / XSLT /
/ Safari / My ASPN /
Cookbooks | Documentation | Mailing Lists | Modules | News Feeds | Products | User Groups


Recent Messages
List Archives
About the List
List Leaders
Subscription Options

View Subscriptions
Help

View by Topic
ActiveState
.NET Framework
Open Source
Perl
PHP
Python
Tcl
Web Services
XML & XSLT

View by Category
Database
General
SOAP
System Administration
Tools
User Interfaces
Web Programming
XML Programming


MyASPN >> Mail Archive >> c++-sig
c++-sig
[C++-sig] problem with Boost.Python enum with duplicate values
by scott snyder other posts by this author
Oct 2 2003 4:40PM messages near this date
Re: [C++-sig] On wrapping vector > | Re: [C++-sig] problem with Boost.Python enum with duplicate values
hi -

I've found that the enum support in Boost.Python does not fully
handle the case of duplicate enum values.  For example, i was
processing (with pyste) this enum:

  enum { X=0, Y=1, NUM_COORDINATES=2, SIZE=NUM_COORDINATES };

Pyste generated code to set all four enum symbols like this:

    enum_< UniqueInt<4>  >("unnamed")
        .value("Y", Hep2Vector::Y)
        .value("X", Hep2Vector::X)
        .value("SIZE", Hep2Vector::SIZE)
        .value("NUM_COORDINATES", Hep2Vector::NUM_COORDINATES)
        .export_values()
    ;

However, from python, the `SIZE' symbol was not present.

Looking at the code in enum.cpp, is see that it keeps the enum items
in a map indexed by the value --- so values added later overwrite
any added earlier.

It's common to use C++ enums to define small integral constants,
in addition to using them for things which are actual enumerations.
So the case of multiple enum symbols with the same value really should
be supported.

The following patch attempts to do this.
When value() is called, if the value is already in the map,
then we add the symbol to a (new) list instead.
export_values() then visits the list as well as the map when
exporting symbols.
The map is still used for the value-> symbol mapping (so the first
one listed is the one you'll get).

thanks,
sss


Index: src/object/enum.cpp
===================================================================
RCS file: /cvsroot/boost/boost/libs/python/src/object/enum.cpp,v
retrieving revision 1.5
diff -u -p -r1.5 enum.cpp
--- src/object/enum.cpp	20 Feb 2003 20:27:44 -0000	1.5
+++ src/object/enum.cpp	2 Oct 2003 16:23:30 -0000
@@ -148,6 +148,7 @@ namespace
       dict d;
       d["__slots__"] = tuple();
       d["values"] = dict();
+      d["othervalues"] = list();
 
       object module_name = module_prefix();
       if (module_name)
@@ -192,7 +193,12 @@ void enum_base::add_value(char const* na
     (*this).attr(name_) = x;
 
     dict d = extract<dict> (this->attr("values"))();
-    d[value] = x;
+    if (d.has_key (value)) {
+      list l = extract<list> (this->attr("othervalues"))();
+      l.append (x);
+    }
+    else
+      d[value] = x;
     
     // Set the name field in the new enum instanec
     enum_object* p = downcast<enum_object> (x.ptr());
@@ -204,11 +210,16 @@ void enum_base::export_values()
 {
     dict d = extract<dict> (this->attr("values"))();
     list values = d.values();
+    list othervalues = extract<list> (this->attr("othervalues"))();
     scope current;
     
     for (unsigned i = 0, max = len(values); i < max; ++i)
     {
         api::setattr(current, object(values[i].attr("name")), values[i]);
+    }
+    for (unsigned i = 0, max = len(othervalues); i < max; ++i)
+    {
+        api::setattr(current, object(othervalues[i].attr("name")), othervalues[i]);
     }
  }
 
Index: test/enum.cpp
===================================================================
RCS file: /cvsroot/boost/boost/libs/python/test/enum.cpp,v
retrieving revision 1.6
diff -u -p -r1.6 enum.cpp
--- test/enum.cpp	21 May 2003 22:17:22 -0000	1.6
+++ test/enum.cpp	2 Oct 2003 16:23:30 -0000
@@ -13,7 +13,7 @@
 #endif 
 using namespace boost::python;
 
-enum color { red = 1, green = 2, blue = 4 };
+enum color { red = 1, green = 2, blue = 4, blue2 = 4 };
 
 #if BOOST_WORKAROUND(__MWERKS__, <= 0x2407)
 namespace boost  // Pro7 has a hard time detecting enums
@@ -35,6 +35,7 @@ BOOST_PYTHON_MODULE(enum_ext)
         .value("red", red)
         .value("green", green)
         .value("blue", blue)
+        .value("blue2", blue2)
         .export_values()
         ;
     
Index: test/enum.py
===================================================================
RCS file: /cvsroot/boost/boost/libs/python/test/enum.py,v
retrieving revision 1.4
diff -u -p -r1.4 enum.py
--- test/enum.py	26 Aug 2003 13:11:51 -0000	1.4
+++ test/enum.py	2 Oct 2003 16:23:30 -0000
@@ -10,6 +10,15 @@ enum_ext.color.green
 > >> identity(color.blue)
 enum_ext.color.blue
 
+> >> identity(color.blue2)
+enum_ext.color.blue
+
+> >> int(color.blue)
+4
+
+> >> int(color.blue2)
+4
+
 > >> identity(color(1))
 enum_ext.color.red
 

_______________________________________________
C++-sig mailing list
C++-sig@[...].org
http://mail.python.org/mailman/listinfo/c++-sig
Thread:
scott snyder
Niall Douglas
David Abrahams

Privacy Policy | Email Opt-out | Feedback | Syndication
© ActiveState Software Inc. All rights reserved