Commit 3fed4faf authored by matham's avatar matham Committed by GitHub

Add doc support for cpdef enum (GH-3813)

parent adb44bd0
......@@ -1546,17 +1546,23 @@ class CEnumDefNode(StatNode):
# in_pxd boolean
# create_wrapper boolean
# entry Entry
# doc EncodedString or None Doc string
child_attrs = ["items", "underlying_type"]
doc = None
def declare(self, env):
doc = None
if Options.docstrings:
doc = embed_position(self.pos, self.doc)
self.entry = env.declare_enum(
self.name, self.pos,
cname=self.cname,
scoped=self.scoped,
typedef_flag=self.typedef_flag,
visibility=self.visibility, api=self.api,
create_wrapper=self.create_wrapper)
create_wrapper=self.create_wrapper, doc=doc)
def analyse_declarations(self, env):
scope = None
......
......@@ -3171,11 +3171,13 @@ def p_c_enum_definition(s, pos, ctx):
s.expect(':')
items = []
doc = None
if s.sy != 'NEWLINE':
p_c_enum_line(s, ctx, items)
else:
s.next() # 'NEWLINE'
s.expect_indent()
doc = p_doc_string(s)
while s.sy not in ('DEDENT', 'EOF'):
p_c_enum_line(s, ctx, items)
......@@ -3191,7 +3193,7 @@ def p_c_enum_definition(s, pos, ctx):
underlying_type=underlying_type,
typedef_flag=ctx.typedef_flag, visibility=ctx.visibility,
create_wrapper=ctx.overridable,
api=ctx.api, in_pxd=ctx.level == 'module_pxd')
api=ctx.api, in_pxd=ctx.level == 'module_pxd', doc=doc)
def p_c_enum_line(s, ctx, items):
if s.sy != 'pass':
......
......@@ -4028,12 +4028,14 @@ class CppClassType(CType):
class CppScopedEnumType(CType):
# name string
# doc string or None
# cname string
is_cpp_enum = True
def __init__(self, name, cname, underlying_type, namespace=None):
def __init__(self, name, cname, underlying_type, namespace=None, doc=None):
self.name = name
self.doc = doc
self.cname = cname
self.values = []
self.underlying_type = underlying_type
......@@ -4088,6 +4090,7 @@ class CppScopedEnumType(CType):
"cname": self.cname.split("::")[-1],
"items": tuple(self.values),
"underlying_type": self.underlying_type.empty_declaration_code(),
"enum_doc": self.doc,
},
outer_module_scope=env.global_scope())
......@@ -4143,6 +4146,7 @@ def is_optional_template_param(type):
class CEnumType(CIntLike, CType):
# name string
# doc string or None
# cname string or None
# typedef_flag boolean
# values [string], populated during declaration analysis
......@@ -4151,8 +4155,9 @@ class CEnumType(CIntLike, CType):
signed = 1
rank = -1 # Ranks below any integer type
def __init__(self, name, cname, typedef_flag, namespace=None):
def __init__(self, name, cname, typedef_flag, namespace=None, doc=None):
self.name = name
self.doc = doc
self.cname = cname
self.values = []
self.typedef_flag = typedef_flag
......@@ -4194,7 +4199,9 @@ class CEnumType(CIntLike, CType):
env.use_utility_code(CythonUtilityCode.load(
"EnumType", "CpdefEnums.pyx",
context={"name": self.name,
"items": tuple(self.values)},
"items": tuple(self.values),
"enum_doc": self.doc,
},
outer_module_scope=env.global_scope()))
......
......@@ -682,7 +682,7 @@ class Scope(object):
entry.name, entry.visibility))
def declare_enum(self, name, pos, cname, scoped, typedef_flag,
visibility='private', api=0, create_wrapper=0):
visibility='private', api=0, create_wrapper=0, doc=None):
if name:
if not cname:
if (self.in_cinclude or visibility == 'public'
......@@ -696,9 +696,9 @@ class Scope(object):
namespace = None
if scoped:
type = PyrexTypes.CppScopedEnumType(name, cname, namespace)
type = PyrexTypes.CppScopedEnumType(name, cname, namespace, doc=doc)
else:
type = PyrexTypes.CEnumType(name, cname, typedef_flag, namespace)
type = PyrexTypes.CEnumType(name, cname, typedef_flag, namespace, doc=doc)
else:
type = PyrexTypes.c_anon_enum_type
entry = self.declare_type(name, type, pos, cname = cname,
......
......@@ -51,12 +51,16 @@ if PY_VERSION_HEX >= 0x03040000:
('{{item}}', {{item}}),
{{endfor}}
]))
{{if enum_doc is not None}}
{{name}}.__doc__ = {{ repr(enum_doc) }}
{{endif}}
{{for item in items}}
__Pyx_globals['{{item}}'] = {{name}}.{{item}}
{{endfor}}
else:
class {{name}}(__Pyx_EnumBase):
pass
{{ repr(enum_doc) if enum_doc is not None else 'pass' }}
{{for item in items}}
__Pyx_globals['{{item}}'] = {{name}}({{item}}, '{{item}}')
{{endfor}}
......@@ -78,3 +82,7 @@ else:
{{for item in items}}
__Pyx_globals["{{name}}"](<{{underlying_type}}>({{name}}.{{item}}), '{{item}}')
{{endfor}}
{{if enum_doc is not None}}
__Pyx_globals["{{name}}"].__doc__ = {{ repr(enum_doc) }}
{{endif}}
......@@ -11,5 +11,19 @@ cpdef enum PxdEnum:
RANK_1 = 37
RANK_2 = 389
cpdef enum cpdefPxdDocEnum:
"""Home is where...
"""
RANK_6 = 159
cpdef enum cpdefPxdDocLineEnum:
"""Home is where..."""
RANK_7 = 889
cdef enum PxdSecretEnum:
RANK_3 = 5077
RANK_8 = 5077
cdef enum cdefPxdDocEnum:
"""the heart is.
"""
RANK_9 = 2458
......@@ -11,6 +11,8 @@ True
True
>>> FIVE == 5 or FIVE
True
>>> ELEVEN == 11 or ELEVEN
True
>>> SEVEN # doctest: +ELLIPSIS
Traceback (most recent call last):
NameError: ...name 'SEVEN' is not defined
......@@ -29,6 +31,10 @@ True
True
>>> RANK_2 == 389 or RANK_2
True
>>> RANK_6 == 159 or RANK_6
True
>>> RANK_7 == 889 or RANK_7
True
>>> RANK_3 # doctest: +ELLIPSIS
Traceback (most recent call last):
NameError: ...name 'RANK_3' is not defined
......@@ -48,7 +54,6 @@ Traceback (most recent call last):
NameError: ...name 'IntEnum' is not defined
"""
cdef extern from *:
cpdef enum: # ExternPyx
ONE "1"
......@@ -63,9 +68,24 @@ cpdef enum PyxEnum:
THREE = 3
FIVE = 5
cpdef enum cpdefPyxDocEnum:
"""Home is where...
"""
ELEVEN = 11
cpdef enum cpdefPyxDocLineEnum:
"""Home is where..."""
FOURTEEN = 14
cdef enum SecretPyxEnum:
SEVEN = 7
cdef enum cdefPyxDocEnum:
"""the heart is.
"""
FIVE_AND_SEVEN = 5077
def test_as_variable_from_cython():
"""
>>> test_as_variable_from_cython()
......@@ -89,3 +109,21 @@ def verify_resolution_GH1533():
"""
THREE = 100
return int(PyxEnum.THREE)
def check_docs():
"""
>>> PxdEnum.__doc__ not in ("Home is where...\\n ", "Home is where...")
True
>>> PyxEnum.__doc__ not in ("Home is where...\\n ", "Home is where...")
True
>>> cpdefPyxDocEnum.__doc__ == "Home is where...\\n "
True
>>> cpdefPxdDocEnum.__doc__ == "Home is where...\\n "
True
>>> cpdefPyxDocLineEnum.__doc__
'Home is where...'
>>> cpdefPxdDocLineEnum.__doc__
'Home is where...'
"""
pass
......@@ -7,14 +7,36 @@ cdef extern from *:
Item1 = 1,
Item2 = 2
};
enum class Enum2 {
Item4 = 4,
Item5 = 5
};
"""
cpdef enum class Enum1:
Item1
Item2
cpdef enum class Enum2:
"""Apricots and other fruits.
"""
Item4
Item5
def test_enum_to_list():
"""
>>> test_enum_to_list()
"""
assert list(Enum1) == [1, 2]
assert list(Enum2) == [4, 5]
def test_enum_doc():
"""
>>> Enum2.__doc__ == "Apricots and other fruits.\\n "
True
>>> Enum1.__doc__ != "Apricots and other fruits.\\n "
True
"""
pass
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment