Opened 14 years ago

Closed 13 years ago

#2744 closed Patches (fixed)

boost::python does not support enums with duplicated values.

Reported by: hugo.lima@… Owned by: Dave Abrahams
Milestone: Boost 1.39.0 Component: python USE GITHUB
Version: Boost Development Trunk Severity: Problem
Keywords: boost python enum Cc: dave@…

Description

boost::python does not support enums with duplicated values.

The proposed patch do the following:

If the enum does not have duplicated values, all remains the same (the "values" attribute is a dict of value=>enum_type). If it has duplicated values, the duplicated values point to a tuple of enum_types in the values attr dict.

Remarks:

  • Maybe I should use lists instead of tuples to avoid the list <=> tuple conversion
  • I did not use tuples for all entries in the values attribute to keep the source compatibility.

Attachments (5)

enum_with_duplicated_values.patch (1.4 KB ) - added by hugo.lima@… 14 years ago.
Patch to fix the problem
enum_with_duplicated_values_v2.patch (1.3 KB ) - added by hugo.lima@… 14 years ago.
Create a new attribute called "names" that maps the name of enum to their value and fix the "enum with duplicated values" bug.
enum_with_duplicated_values_v2.2.patch (2.4 KB ) - added by hugo.lima@… 14 years ago.
enum_with_duplicated_values_unittest.patch (651 bytes ) - added by hugo.lima@… 14 years ago.
Patch to the unit test
enum_with_duplicated_values_v2.3.patch (4.2 KB ) - added by hugo.lima@… 14 years ago.
Patch to enum.cpp and their unit tests

Download all attachments as: .zip

Change History (27)

by hugo.lima@…, 14 years ago

Patch to fix the problem

comment:1 by Dave Abrahams, 14 years ago

Type: BugsPatches

Are you saying that changing the code to use tuples even when there are no duplicates would break backward compatibility with existing user code? How so?

comment:2 by hugo.lima@…, 14 years ago

The code:

for x in SomeEnum.values:

# do something with x, because I know that it is a int print x+2

because the values attribute is public.

comment:3 by Dave Abrahams, 14 years ago

Then maybe a better solution is to add a public "names" dict that maps name -> value?

comment:4 by hugo.lima@…, 14 years ago

Yeah, but I did not want to change the API or the current behaviour of the current boost::python based bindings with this patch. IMHO, values attribute should be a dict that maps name->value. But this will change the current API of all enums generated by boost python.

Adding a new "name" attribute without any real usecase may only increase the memory footprint with this dict. So, not changing the API and fixing a bug is good enough for now :-). What you think about?

comment:5 by Dave Abrahams, 14 years ago

Status: newassigned

?? The usecase is supporting your enum with multiple names for the same value

The memory footprint of this additional dict will be tiny.

The problem with the change as proposed is that it can break user code, if users are counting on "values" containing single int values, because the person using an enum is not always the same as the person exporting it.

comment:6 by hugo.lima@…, 14 years ago

I can leave the values attribute intact and create another temporary attribute, just to help the enum declaration, like the current values attribute is used, and remove then after the declaration of all enums. what you think?

Results:

  • Do not change the current API, so do not break user code, values map to a single enum_type ever, not a tuple.
  • We have the bug fixed.
  • The same memory footprint.

comment:7 by Dave Abrahams, 14 years ago

No, what I want is to increase the memory footprint by one dict per enum declaration. The names attribute would be useful in general.

comment:8 by hugo.lima@…, 14 years ago

Ok, so I must keep values attribute as is and add the names attribute?

comment:9 by Dave Abrahams, 14 years ago

That's the change that makes sense to me

comment:10 by anonymous, 14 years ago

Ok, I'll create a new patch and post it here until next weekend, because I'm too busy now

by hugo.lima@…, 14 years ago

Create a new attribute called "names" that maps the name of enum to their value and fix the "enum with duplicated values" bug.

comment:11 by hugo.lima@…, 14 years ago

patch done, any comments?

comment:12 by Dave Abrahams, 14 years ago

According to http://trac.edgewall.org/ticket/8047#comment:2 your patch is ill-formed. Could you please replace it with a well-formed one?

by hugo.lima@…, 14 years ago

comment:13 by hugo.lima@…, 14 years ago

the last version is the output of svn diff, with trailing spaces removals, blank spaces removals, etc...

comment:14 by hugo.lima@…, 14 years ago

any comments?

in reply to:  14 comment:15 by Dave Abrahams, 14 years ago

Replying to hugo.lima@openbossa.org:

any comments?

Looks great, but before I can check it in I need a testcase that fails unless this patch is applied. Do you think you could whip one up? A patch to the existing enum test case would be fine.

comment:16 by hugo.lima@…, 14 years ago

Ok, I'll do it.

by hugo.lima@…, 14 years ago

Patch to the unit test

comment:17 by hugo.lima@…, 14 years ago

Patch to the unit test added, it will fail because color.blood will overwrite color.red. the test just do not test if the blood has been declared.

comment:18 by Dave Abrahams, 14 years ago

The new test seems to fail even after application of the patch v2.2:

running...
**********************************************************************
File "enum.py", line 7, in __main__
Failed example:
    identity(color.red)
Expected:
    enum_ext.color.red
Got:
    enum_ext.color.blood
**********************************************************************
File "enum.py", line 16, in __main__
Failed example:
    identity(color(1))
Expected:
    enum_ext.color.red
Got:
    enum_ext.color.blood
**********************************************************************
File "enum.py", line 30, in __main__
Failed example:
    identity(red)
Exception raised:
    Traceback (most recent call last):
      File "/System/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/doctest.py", line 1212, in __run
        compileflags, 1) in test.globs
      File "<doctest __main__[8]>", line 1, in <module>
        identity(red)
    NameError: name 'red' is not defined
**********************************************************************
File "enum.py", line 44, in __main__
Failed example:
    c.x
Expected:
    enum_ext.color.red
Got:
    enum_ext.color.blood
**********************************************************************
1 items had failures:
   4 of  20 in __main__
***Test Failed*** 4 failures.

Note that you can replace existing patches so obsolete ones don't pile up in the ticket.

by hugo.lima@…, 14 years ago

Patch to enum.cpp and their unit tests

comment:19 by anonymous, 14 years ago

I dont have enough privileges to replace existing patches, maybe if I create a trac account.

I fixed the original patch, so enums are not integers and the tests do not fail. Just one issue, when I cast something to a enum, if the enum value is duplicated, it will ever return the last declared value. so I replaced the color.red by color.blood in the python test script. But that's not a problem, because color.red == color.blood and hash(color.red) == hash(color.blood).

comment:20 by anderson.lizardo@…, 14 years ago

Any other comments on the latest patch (v2.3) ? I'm currently using it and it seems to work without problems.

comment:21 by hugo.lima@…, 13 years ago

ping

comment:22 by Dave Abrahams, 13 years ago

Resolution: fixed
Status: assignedclosed

(In [53660]) Allow duplicate enum values. Fixes #2744 Thanks to hugo.lima@…

Note: See TracTickets for help on using tickets.