Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
gaoqiong
pybind11
Commits
414ee163
Commit
414ee163
authored
Mar 03, 2017
by
Jason Rhinelander
Committed by
GitHub
Mar 03, 2017
Browse files
Merge pull request #666 from mdcb/master
Expose enum_ entries as new "__members__" attribute
parents
11c9f32c
af936e19
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
38 additions
and
16 deletions
+38
-16
docs/classes.rst
docs/classes.rst
+6
-0
include/pybind11/pybind11.h
include/pybind11/pybind11.h
+23
-16
tests/test_enum.py
tests/test_enum.py
+9
-0
No files found.
docs/classes.rst
View file @
414ee163
...
...
@@ -423,6 +423,12 @@ typed enums.
>>> int(p.type)
1L
The entries defined by the enumeration type are exposed in the ``__members__`` property:
.. code-block:: pycon
>>> Pet.Kind.__members__
{'Dog': Kind.Dog, 'Cat': Kind.Cat}
.. note::
...
...
include/pybind11/pybind11.h
View file @
414ee163
...
...
@@ -1116,24 +1116,32 @@ private:
template
<
typename
Type
>
class
enum_
:
public
class_
<
Type
>
{
public:
using
class_
<
Type
>::
def
;
using
class_
<
Type
>::
def_property_readonly_static
;
using
Scalar
=
typename
std
::
underlying_type
<
Type
>::
type
;
template
<
typename
T
>
using
arithmetic_tag
=
std
::
is_same
<
T
,
arithmetic
>
;
template
<
typename
...
Extra
>
enum_
(
const
handle
&
scope
,
const
char
*
name
,
const
Extra
&
...
extra
)
:
class_
<
Type
>
(
scope
,
name
,
extra
...),
m_parent
(
scope
)
{
:
class_
<
Type
>
(
scope
,
name
,
extra
...),
m_entries
(),
m_parent
(
scope
)
{
constexpr
bool
is_arithmetic
=
!
std
::
is_same
<
detail
::
first_of_t
<
arithmetic_tag
,
void
,
Extra
...
>
,
void
>::
value
;
auto
entries
=
new
std
::
unordered_map
<
Scalar
,
const
char
*>
();
def
(
"__repr__"
,
[
name
,
entries
](
Type
value
)
->
std
::
string
{
auto
it
=
entries
->
find
((
Scalar
)
value
);
return
std
::
string
(
name
)
+
"."
+
((
it
==
entries
->
end
())
?
std
::
string
(
"???"
)
:
std
::
string
(
it
->
second
));
auto
m_entries_ptr
=
m_entries
.
inc_ref
().
ptr
();
def
(
"__repr__"
,
[
name
,
m_entries_ptr
](
Type
value
)
->
pybind11
::
str
{
for
(
const
auto
&
kv
:
reinterpret_borrow
<
dict
>
(
m_entries_ptr
))
{
if
(
pybind11
::
cast
<
Type
>
(
kv
.
second
)
==
value
)
return
pybind11
::
str
(
"{}.{}"
).
format
(
name
,
kv
.
first
);
}
return
pybind11
::
str
(
"{}.???"
).
format
(
name
);
});
def_property_readonly_static
(
"__members__"
,
[
m_entries_ptr
](
object
/* self */
)
{
dict
m
;
for
(
const
auto
&
kv
:
reinterpret_borrow
<
dict
>
(
m_entries_ptr
))
m
[
kv
.
first
]
=
kv
.
second
;
return
m
;
},
return_value_policy
::
copy
);
def
(
"__init__"
,
[](
Type
&
value
,
Scalar
i
)
{
value
=
(
Type
)
i
;
});
def
(
"__init__"
,
[](
Type
&
value
,
Scalar
i
)
{
new
(
&
value
)
Type
((
Type
)
i
);
});
def
(
"__int__"
,
[](
Type
value
)
{
return
(
Scalar
)
value
;
});
...
...
@@ -1172,26 +1180,25 @@ public:
// Pickling and unpickling -- needed for use with the 'multiprocessing' module
def
(
"__getstate__"
,
[](
const
Type
&
value
)
{
return
pybind11
::
make_tuple
((
Scalar
)
value
);
});
def
(
"__setstate__"
,
[](
Type
&
p
,
tuple
t
)
{
new
(
&
p
)
Type
((
Type
)
t
[
0
].
cast
<
Scalar
>
());
});
m_entries
=
entries
;
}
/// Export enumeration entries into the parent scope
enum_
&
export_values
()
{
for
(
auto
item
:
reinterpret_borrow
<
dict
>
(((
PyTypeObject
*
)
this
->
m_ptr
)
->
tp_dict
))
{
if
(
isinstance
(
item
.
second
,
this
->
m_ptr
))
m_parent
.
attr
(
item
.
first
)
=
item
.
second
;
}
enum_
&
export_values
()
{
for
(
const
auto
&
kv
:
m_entries
)
m_parent
.
attr
(
kv
.
first
)
=
kv
.
second
;
return
*
this
;
}
/// Add an enumeration entry
enum_
&
value
(
char
const
*
name
,
Type
value
)
{
this
->
attr
(
name
)
=
pybind11
::
cast
(
value
,
return_value_policy
::
copy
);
(
*
m_entries
)[(
Scalar
)
value
]
=
name
;
auto
v
=
pybind11
::
cast
(
value
,
return_value_policy
::
copy
);
this
->
attr
(
name
)
=
v
;
m_entries
[
pybind11
::
str
(
name
)]
=
v
;
return
*
this
;
}
private:
std
::
unordered_map
<
Scalar
,
const
char
*>
*
m_entries
;
dict
m_entries
;
handle
m_parent
;
};
...
...
tests/test_enum.py
View file @
414ee163
...
...
@@ -7,6 +7,15 @@ def test_unscoped_enum():
assert
str
(
UnscopedEnum
.
EOne
)
==
"UnscopedEnum.EOne"
assert
str
(
UnscopedEnum
.
ETwo
)
==
"UnscopedEnum.ETwo"
assert
str
(
EOne
)
==
"UnscopedEnum.EOne"
# __members__ property
assert
UnscopedEnum
.
__members__
==
{
"EOne"
:
UnscopedEnum
.
EOne
,
"ETwo"
:
UnscopedEnum
.
ETwo
}
# __members__ readonly
with
pytest
.
raises
(
AttributeError
):
UnscopedEnum
.
__members__
=
{}
# __members__ returns a copy
foo
=
UnscopedEnum
.
__members__
foo
[
"bar"
]
=
"baz"
assert
UnscopedEnum
.
__members__
==
{
"EOne"
:
UnscopedEnum
.
EOne
,
"ETwo"
:
UnscopedEnum
.
ETwo
}
# no TypeError exception for unscoped enum ==/!= int comparisons
y
=
UnscopedEnum
.
ETwo
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment