Skip to content
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

PR: Check there is one empty line at the end of the file #371

Merged
merged 7 commits into from
Nov 8, 2016
Merged

PR: Check there is one empty line at the end of the file #371

merged 7 commits into from
Nov 8, 2016

Conversation

goanpeca
Copy link
Member

@goanpeca goanpeca commented Nov 7, 2016

Checks that there is one and only one empty line in the meta.yaml file

@jakirkham

@goanpeca goanpeca changed the title PR: Feature/check empty line PR: Check there is one empty line at the end of the file Nov 7, 2016
Copy link
Member

@jakirkham jakirkham left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks pretty good. Thanks for writing this @goanpeca . 😄

Thinking if we can simplify the check a little bit more. Also giving some thought to Python 2/3 compatibility and unicode. If you have some thoughts along these lines, please feel free to share.

# 11: There should be one empty line at the end of the file.
if recipe_dir is not None and os.path.exists(meta_fname):
with open(meta_fname, 'r') as f:
lines = f.read().split('\n')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think splitlines behaves a little better when it comes to Python 2/3 compatibility and unicode. However, I don't know that we will get the behavior we want then. Not sure what we should do about it.

Maybe we need start using unicode literals with the linter. That has fixed some problems in other areas. Also I expect this will fix some other linter issues with unicode that we have experienced.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I thought of this, will use splitlines 👍

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So the trick I found at least is splitlines with one terminal newline and zero ends up being the same. 😞 Not sure if it is better in that case.

We can keep the the end line characters though. I'm just not sure if that makes it better or not.

lines = f.read().split('\n')

end_empty_lines_count = 0
for i, line in enumerate(reversed(lines)):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could use start=1 with enumerate to simplify this a bit.

end_empty_lines_count = 0
for i, line in enumerate(reversed(lines)):
if line != '':
break
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wondering if we can reduce this some application of a function from itertools.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe, this is a naive but working execution, I can optimize

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You mean something like sum(1 for _ in itertools.takewhile(lambda x: x == '', reversed(lines))) but if that's really better? 😄

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hehe, yeah, maybe there is a super pythonic and readable way of making that a one liner, but yeah, I dont know if it is really better. Thanks for the example @MSeifert04 :-)

Copy link

@MSeifert04 MSeifert04 Nov 7, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe two lines:

trailing_empty_lines = itertools.takewhile(lambda x: x == '', reversed(lines))
num_trailing_empty_lines = sum(1 for _ in trailing_empty_lines) # or len(list(trailing_empty_lines))

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 :-)

for i, line in enumerate(reversed(lines)):
if line != '':
break
end_empty_lines_count = i + 1
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With start=1 this is then just end_empty_lines_count = i.

break
end_empty_lines_count = i + 1

if lines[-1] != '' or end_empty_lines_count != 1:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need both checks? Are they not always the same?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, check 1 takes into account that there is no empty line at the end

Check 2 takes into account more than 1 empty line at the end

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah yes you are right check 2 is enough :-p

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No worries. Was wondering again if I was missing something. 😄

if content == valid_content:
self.assertNotIn(expected_message, lints)
else:
self.assertIn(expected_message, lints)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice tests! 👍

@@ -122,6 +122,20 @@ def lintify(meta, recipe_dir=None):
lints.append('The recipe `license` should not include the word '
'"License".')

# 11: There should be one empty line at the end of the file.
if recipe_dir is not None and os.path.exists(meta_fname):
with open(meta_fname, 'r') as f:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should switch to io.open.

b'extra:\n recipe-maintainers:\n - goanpeca\n\n\n',
b'extra:\r recipe-maintainers:\r - goanpeca\r\r\r',
b'extra:\r\n recipe-maintainers:\r\n - goanpeca\r\n\r\n\r\n',
]
Copy link
Member Author

@goanpeca goanpeca Nov 7, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you feel safer now @jakirkham ?

Not sure what you meant by unicode py2/3 problems, python always transforms the correct ending into '\n' (as the test shows)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, was trying to save you from going down this road by trying to handle unicode cleanly throughout the linter and associated tests. ( #372 )

I think it should be ok to make these explicitly unicode. Though I'll let you be the judge.

The \r* tests open an interesting question of should we permit this. 😄 Though I see no harm in allowing it for now and tightening down later. For a related problem, please see issue ( conda-forge/conda-forge-maintenance#8 ).

Copy link
Member Author

@goanpeca goanpeca Nov 7, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not add .gitattributes to all repos upon creation and enforce a particular line ending?

End-of-line conversion
While Git normally leaves file contents alone, it can be configured to normalize line endings to LF in the repository and, optionally, to convert them to CRLF when files are checked out.

If you simply want to have CRLF line endings in your working directory regardless of the repository you are working with, you can set the config variable "core.autocrlf" without using any attributes.

[core]
    autocrlf = true

This does not force normalization of text files, but does ensure that text files that you introduce to the repository have their line endings normalized to LF when they are added, and that files that are already normalized in the repository stay normalized.

If you want to ensure that text files that any contributor introduces to the repository have their line endings normalized, you can set the text attribute to "auto" for all files.

*   text=auto

@jakirkham do you want me to change anything else at this point on this PR?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nope. Looks good. Thanks.

Adding .gitattributes sounds like a good idea. Maybe we should write up an issue. Alternatively, if you would like to lead the way with a PR, that would be welcome too.

@goanpeca
Copy link
Member Author

goanpeca commented Nov 7, 2016

@jakirkham made the suggested changes

@jakirkham jakirkham merged commit cf182da into conda-forge:master Nov 8, 2016
@jakirkham
Copy link
Member

Thanks @goanpeca .

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants