-
Notifications
You must be signed in to change notification settings - Fork 596
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Format enums with one value per line #216
Conversation
I'm not particularly confident that the punctuation parameter is the proper approach. Perhaps I should call |
Incomplete tests, fixing them and fixing a bug with 'empty' enums such as used in typedefs. |
@@ -280,6 +281,25 @@ def test_compound_literal(self): | |||
self._assert_ctoc_correct('int i = ++(int){ 1 };') | |||
self._assert_ctoc_correct('struct foo_s foo = (struct foo_s){ 1, 2 };') | |||
|
|||
def test_enum(self): | |||
s = textwrap.dedent(r''' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this dedent necessary? none of the other tests use it since the code is being parsed anyway
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
_assert_ctoc_correct()
is not checking the formatting and my change is a formatting change so it would seem that my test should do at least something different. I just verified this by checking that all three of the following tests pass.
def test_enum_a(self):
s = textwrap.dedent(r'''
enum e
{
a = 1,
b = 2,
c = 3
};
'''[1:])
self._assert_ctoc_correct(s)
def test_enum_b(self):
s = r'''
enum e
{
a = 1,
b = 2,
c = 3
};
'''
self._assert_ctoc_correct(s)
def test_enum_c(self):
s = r'''enum e {a = 1, b = 2, c = 3};'''
self._assert_ctoc_correct(s)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, I see. If that's the case, no problem. The other tests don't tend to do one-to-one comparison of actual formatting, but I guess it's OK in this case. I'm a bit worried that this test will be fragile because it compares large strings, but we can fix it if it becomes and issue.
pycparser/c_generator.py
Outdated
if name in ('struct', 'union'): | ||
members = n.decls | ||
body_function = self._generate_struct_union_body | ||
elif name in ('enum',): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this should probably be:
else:
assert name == 'enum'
... rest of code
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is my understanding that assert
is only proper in test code. But, the gist that an exception should be raised for an invalid input does sound good. How about leaving the elif
and adding an else
that raises a to-be-defined exception?
UnknownTypeError('`{name}` not recognized'.format(name=name))
Given that this is an internal method it seems that we may not need a nice user error. I'll note that as is we'd get an UnboundLocalError
for the following access to members
. I added a test for that and will adjust it based on the implementation decision.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I actually think assert
is fine in this case, since it's checking an invariant in the code - it's a bug if this place is reached, so assert
is appropriate.
pycparser/c_generator.py
Outdated
body_function = self._generate_struct_union_body | ||
elif name in ('enum',): | ||
if n.values is None: | ||
members = () |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
members = () if n.values is None else n.values.enumerators
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pending above possibilities I'll change this.
pycparser/c_generator.py
Outdated
if i == len(members) - 1: | ||
punctuation = '' | ||
|
||
s.append(self._generate_stmt( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder why you need to build an AST node again here, why won't just emitting the text do?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was trying to make it look like how struct
and union
were done, but failing. I removed the punctuation parameter from _generate_stmt()
and added visit_Enumerator()
. Perhaps this will fit better with the existing code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the very prompt review.
I pushed a couple commits but let me know how you want to proceed on the remaining points.
@@ -280,6 +281,25 @@ def test_compound_literal(self): | |||
self._assert_ctoc_correct('int i = ++(int){ 1 };') | |||
self._assert_ctoc_correct('struct foo_s foo = (struct foo_s){ 1, 2 };') | |||
|
|||
def test_enum(self): | |||
s = textwrap.dedent(r''' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
_assert_ctoc_correct()
is not checking the formatting and my change is a formatting change so it would seem that my test should do at least something different. I just verified this by checking that all three of the following tests pass.
def test_enum_a(self):
s = textwrap.dedent(r'''
enum e
{
a = 1,
b = 2,
c = 3
};
'''[1:])
self._assert_ctoc_correct(s)
def test_enum_b(self):
s = r'''
enum e
{
a = 1,
b = 2,
c = 3
};
'''
self._assert_ctoc_correct(s)
def test_enum_c(self):
s = r'''enum e {a = 1, b = 2, c = 3};'''
self._assert_ctoc_correct(s)
pycparser/c_generator.py
Outdated
if name in ('struct', 'union'): | ||
members = n.decls | ||
body_function = self._generate_struct_union_body | ||
elif name in ('enum',): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is my understanding that assert
is only proper in test code. But, the gist that an exception should be raised for an invalid input does sound good. How about leaving the elif
and adding an else
that raises a to-be-defined exception?
UnknownTypeError('`{name}` not recognized'.format(name=name))
Given that this is an internal method it seems that we may not need a nice user error. I'll note that as is we'd get an UnboundLocalError
for the following access to members
. I added a test for that and will adjust it based on the implementation decision.
pycparser/c_generator.py
Outdated
body_function = self._generate_struct_union_body | ||
elif name in ('enum',): | ||
if n.values is None: | ||
members = () |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pending above possibilities I'll change this.
pycparser/c_generator.py
Outdated
if i == len(members) - 1: | ||
punctuation = '' | ||
|
||
s.append(self._generate_stmt( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was trying to make it look like how struct
and union
were done, but failing. I removed the punctuation parameter from _generate_stmt()
and added visit_Enumerator()
. Perhaps this will fit better with the existing code.
@@ -280,6 +281,25 @@ def test_compound_literal(self): | |||
self._assert_ctoc_correct('int i = ++(int){ 1 };') | |||
self._assert_ctoc_correct('struct foo_s foo = (struct foo_s){ 1, 2 };') | |||
|
|||
def test_enum(self): | |||
s = textwrap.dedent(r''' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, I see. If that's the case, no problem. The other tests don't tend to do one-to-one comparison of actual formatting, but I guess it's OK in this case. I'm a bit worried that this test will be fragile because it compares large strings, but we can fix it if it becomes and issue.
pycparser/c_generator.py
Outdated
|
||
def _generate_enum_body(self, members): | ||
s = [] | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Python usually prefers denser style - none of the empty lines in this function are really necessary
pycparser/c_generator.py
Outdated
def _generate_enum_body(self, members): | ||
s = [] | ||
|
||
for value in members: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, this loop can be turned into a simple list comprehension, no?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I refactored and it got simpler and I missed that last step.
pycparser/c_generator.py
Outdated
|
||
s.append(line) | ||
|
||
return ''.join(s)[:-2] + '\n' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A comment should say why the [:-2]
is needed here
Issue #213