Skip to content

Commit f79eb57

Browse files
authored
Merge pull request #586 from ekampf/feature/enum_value_descriptions
Support from_enum description lambda
2 parents a8a6555 + 90272e5 commit f79eb57

File tree

3 files changed

+79
-5
lines changed

3 files changed

+79
-5
lines changed

graphene/types/enum.py

+11-2
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ def eq_enum(self, other):
2121

2222
class EnumOptions(BaseOptions):
2323
enum = None # type: Enum
24+
deprecation_reason = None
2425

2526

2627
class EnumMeta(SubclassWithMeta_Meta):
@@ -45,8 +46,14 @@ def __call__(cls, *args, **kwargs): # noqa: N805
4546
return super(EnumMeta, cls).__call__(*args, **kwargs)
4647
# return cls._meta.enum(*args, **kwargs)
4748

48-
def from_enum(cls, enum, description=None): # noqa: N805
49-
meta_class = type('Meta', (object,), {'enum': enum, 'description': description})
49+
def from_enum(cls, enum, description=None, deprecation_reason=None): # noqa: N805
50+
description = description or enum.__doc__
51+
meta_dict = {
52+
'enum': enum,
53+
'description': description,
54+
'deprecation_reason': deprecation_reason
55+
}
56+
meta_class = type('Meta', (object,), meta_dict)
5057
return type(meta_class.enum.__name__, (Enum,), {'Meta': meta_class})
5158

5259

@@ -56,8 +63,10 @@ class Enum(six.with_metaclass(EnumMeta, UnmountedType, BaseType)):
5663
def __init_subclass_with_meta__(cls, enum=None, **options):
5764
_meta = EnumOptions(cls)
5865
_meta.enum = enum or cls.__enum__
66+
_meta.deprecation_reason = options.pop('deprecation_reason', None)
5967
for key, value in _meta.enum.__members__.items():
6068
setattr(cls, key, value)
69+
6170
super(Enum, cls).__init_subclass_with_meta__(_meta=_meta, **options)
6271

6372
@classmethod

graphene/types/tests/test_enum.py

+54
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
import six
2+
3+
from ..schema import Schema, ObjectType
14
from ..argument import Argument
25
from ..enum import Enum, PyEnum
36
from ..field import Field
@@ -66,6 +69,57 @@ def test_enum_from_builtin_enum():
6669
assert RGB.BLUE
6770

6871

72+
def test_enum_from_builtin_enum_accepts_lambda_description():
73+
def custom_description(value):
74+
if not value:
75+
return "StarWars Episodes"
76+
77+
return 'New Hope Episode' if value == Episode.NEWHOPE else 'Other'
78+
79+
def custom_deprecation_reason(value):
80+
return 'meh' if value == Episode.NEWHOPE else None
81+
82+
PyEpisode = PyEnum('PyEpisode', 'NEWHOPE,EMPIRE,JEDI')
83+
Episode = Enum.from_enum(PyEpisode, description=custom_description, deprecation_reason=custom_deprecation_reason)
84+
85+
class Query(ObjectType):
86+
foo = Episode()
87+
88+
schema = Schema(query=Query)
89+
90+
GraphQLPyEpisode = schema._type_map['PyEpisode'].values
91+
92+
assert schema._type_map['PyEpisode'].description == "StarWars Episodes"
93+
assert GraphQLPyEpisode[0].name == 'NEWHOPE' and GraphQLPyEpisode[0].description == 'New Hope Episode'
94+
assert GraphQLPyEpisode[1].name == 'EMPIRE' and GraphQLPyEpisode[1].description == 'Other'
95+
assert GraphQLPyEpisode[2].name == 'JEDI' and GraphQLPyEpisode[2].description == 'Other'
96+
97+
assert GraphQLPyEpisode[0].name == 'NEWHOPE' and GraphQLPyEpisode[0].deprecation_reason == 'meh'
98+
assert GraphQLPyEpisode[1].name == 'EMPIRE' and GraphQLPyEpisode[1].deprecation_reason == None
99+
assert GraphQLPyEpisode[2].name == 'JEDI' and GraphQLPyEpisode[2].deprecation_reason == None
100+
101+
102+
def test_enum_from_python3_enum_uses_enum_doc():
103+
if not six.PY3:
104+
return
105+
106+
from enum import Enum as PyEnum
107+
108+
class Color(PyEnum):
109+
"""This is the description"""
110+
RED = 1
111+
GREEN = 2
112+
BLUE = 3
113+
114+
RGB = Enum.from_enum(Color)
115+
assert RGB._meta.enum == Color
116+
assert RGB._meta.description == "This is the description"
117+
assert RGB
118+
assert RGB.RED
119+
assert RGB.GREEN
120+
assert RGB.BLUE
121+
122+
69123
def test_enum_value_from_class():
70124
class RGB(Enum):
71125
RED = 1

graphene/types/typemap.py

+14-3
Original file line numberDiff line numberDiff line change
@@ -127,16 +127,27 @@ def construct_scalar(self, map, type):
127127
def construct_enum(self, map, type):
128128
values = OrderedDict()
129129
for name, value in type._meta.enum.__members__.items():
130+
description = getattr(value, 'description', None)
131+
deprecation_reason = getattr(value, 'deprecation_reason', None)
132+
if not description and callable(type._meta.description):
133+
description = type._meta.description(value)
134+
135+
if not deprecation_reason and callable(type._meta.deprecation_reason):
136+
deprecation_reason = type._meta.deprecation_reason(value)
137+
130138
values[name] = GraphQLEnumValue(
131139
name=name,
132140
value=value.value,
133-
description=getattr(value, 'description', None),
134-
deprecation_reason=getattr(value, 'deprecation_reason', None))
141+
description=description,
142+
deprecation_reason=deprecation_reason)
143+
144+
type_description = type._meta.description(None) if callable(type._meta.description) else type._meta.description
145+
135146
return GrapheneEnumType(
136147
graphene_type=type,
137148
values=values,
138149
name=type._meta.name,
139-
description=type._meta.description, )
150+
description=type_description, )
140151

141152
def construct_objecttype(self, map, type):
142153
if type._meta.name in map:

0 commit comments

Comments
 (0)