Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
P
pybind11
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
open
pybind11
Commits
414ee163
Commit
414ee163
authored
Mar 03, 2017
by
Jason Rhinelander
Committed by
GitHub
Mar 03, 2017
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #666 from mdcb/master
Expose enum_ entries as new "__members__" attribute
parents
11c9f32c
af936e19
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
38 additions
and
16 deletions
+38
-16
docs/classes.rst
+6
-0
include/pybind11/pybind11.h
+23
-16
tests/test_enum.py
+9
-0
No files found.
docs/classes.rst
View file @
414ee163
...
@@ -423,6 +423,12 @@ typed enums.
...
@@ -423,6 +423,12 @@ typed enums.
>>> int(p.type)
>>> int(p.type)
1L
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::
.. note::
...
...
include/pybind11/pybind11.h
View file @
414ee163
...
@@ -1116,24 +1116,32 @@ private:
...
@@ -1116,24 +1116,32 @@ private:
template
<
typename
Type
>
class
enum_
:
public
class_
<
Type
>
{
template
<
typename
Type
>
class
enum_
:
public
class_
<
Type
>
{
public
:
public
:
using
class_
<
Type
>::
def
;
using
class_
<
Type
>::
def
;
using
class_
<
Type
>::
def_property_readonly_static
;
using
Scalar
=
typename
std
::
underlying_type
<
Type
>::
type
;
using
Scalar
=
typename
std
::
underlying_type
<
Type
>::
type
;
template
<
typename
T
>
using
arithmetic_tag
=
std
::
is_same
<
T
,
arithmetic
>
;
template
<
typename
T
>
using
arithmetic_tag
=
std
::
is_same
<
T
,
arithmetic
>
;
template
<
typename
...
Extra
>
template
<
typename
...
Extra
>
enum_
(
const
handle
&
scope
,
const
char
*
name
,
const
Extra
&
...
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
=
constexpr
bool
is_arithmetic
=
!
std
::
is_same
<
detail
::
first_of_t
<
arithmetic_tag
,
void
,
Extra
...
>
,
!
std
::
is_same
<
detail
::
first_of_t
<
arithmetic_tag
,
void
,
Extra
...
>
,
void
>::
value
;
void
>::
value
;
auto
entries
=
new
std
::
unordered_map
<
Scalar
,
const
char
*>
();
auto
m_entries_ptr
=
m_entries
.
inc_ref
().
ptr
();
def
(
"__repr__"
,
[
name
,
entries
](
Type
value
)
->
std
::
string
{
def
(
"__repr__"
,
[
name
,
m_entries_ptr
](
Type
value
)
->
pybind11
::
str
{
auto
it
=
entries
->
find
((
Scalar
)
value
);
for
(
const
auto
&
kv
:
reinterpret_borrow
<
dict
>
(
m_entries_ptr
))
{
return
std
::
string
(
name
)
+
"."
+
if
(
pybind11
::
cast
<
Type
>
(
kv
.
second
)
==
value
)
((
it
==
entries
->
end
())
?
std
::
string
(
"???"
)
return
pybind11
::
str
(
"{}.{}"
).
format
(
name
,
kv
.
first
);
:
std
::
string
(
it
->
second
));
}
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
)
{
value
=
(
Type
)
i
;
});
def
(
"__init__"
,
[](
Type
&
value
,
Scalar
i
)
{
new
(
&
value
)
Type
((
Type
)
i
);
});
def
(
"__init__"
,
[](
Type
&
value
,
Scalar
i
)
{
new
(
&
value
)
Type
((
Type
)
i
);
});
def
(
"__int__"
,
[](
Type
value
)
{
return
(
Scalar
)
value
;
});
def
(
"__int__"
,
[](
Type
value
)
{
return
(
Scalar
)
value
;
});
...
@@ -1172,26 +1180,25 @@ public:
...
@@ -1172,26 +1180,25 @@ public:
// Pickling and unpickling -- needed for use with the 'multiprocessing' module
// Pickling and unpickling -- needed for use with the 'multiprocessing' module
def
(
"__getstate__"
,
[](
const
Type
&
value
)
{
return
pybind11
::
make_tuple
((
Scalar
)
value
);
});
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
>
());
});
def
(
"__setstate__"
,
[](
Type
&
p
,
tuple
t
)
{
new
(
&
p
)
Type
((
Type
)
t
[
0
].
cast
<
Scalar
>
());
});
m_entries
=
entries
;
}
}
/// Export enumeration entries into the parent scope
/// Export enumeration entries into the parent scope
enum_
&
export_values
()
{
enum_
&
export_values
()
{
for
(
auto
item
:
reinterpret_borrow
<
dict
>
(((
PyTypeObject
*
)
this
->
m_ptr
)
->
tp_dict
))
{
for
(
const
auto
&
kv
:
m_entries
)
if
(
isinstance
(
item
.
second
,
this
->
m_ptr
))
m_parent
.
attr
(
kv
.
first
)
=
kv
.
second
;
m_parent
.
attr
(
item
.
first
)
=
item
.
second
;
}
return
*
this
;
return
*
this
;
}
}
/// Add an enumeration entry
/// Add an enumeration entry
enum_
&
value
(
char
const
*
name
,
Type
value
)
{
enum_
&
value
(
char
const
*
name
,
Type
value
)
{
this
->
attr
(
name
)
=
pybind11
::
cast
(
value
,
return_value_policy
::
copy
);
auto
v
=
pybind11
::
cast
(
value
,
return_value_policy
::
copy
);
(
*
m_entries
)[(
Scalar
)
value
]
=
name
;
this
->
attr
(
name
)
=
v
;
m_entries
[
pybind11
::
str
(
name
)]
=
v
;
return
*
this
;
return
*
this
;
}
}
private
:
private
:
std
::
unordered_map
<
Scalar
,
const
char
*>
*
m_entries
;
dict
m_entries
;
handle
m_parent
;
handle
m_parent
;
};
};
...
...
tests/test_enum.py
View file @
414ee163
...
@@ -7,6 +7,15 @@ def test_unscoped_enum():
...
@@ -7,6 +7,15 @@ def test_unscoped_enum():
assert
str
(
UnscopedEnum
.
EOne
)
==
"UnscopedEnum.EOne"
assert
str
(
UnscopedEnum
.
EOne
)
==
"UnscopedEnum.EOne"
assert
str
(
UnscopedEnum
.
ETwo
)
==
"UnscopedEnum.ETwo"
assert
str
(
UnscopedEnum
.
ETwo
)
==
"UnscopedEnum.ETwo"
assert
str
(
EOne
)
==
"UnscopedEnum.EOne"
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
# no TypeError exception for unscoped enum ==/!= int comparisons
y
=
UnscopedEnum
.
ETwo
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