-
Notifications
You must be signed in to change notification settings - Fork 17
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
Work on pre-commit hooks, small readme update. #401
Work on pre-commit hooks, small readme update. #401
Conversation
* Remove unused .prospector.yaml * Readme: add --tag-num option to update tag number * Flake8: add more plugins to better analyse the code: * `flake8-bugbear` for detecting bugs and potential design problems * `flake8-builtins` for verifying that builtins are not used as variable names * `flake8-comprehensions` for writing better and consistent comprehensions * `flake8-debugger` for checking that there are no forgotten breakpoints * `flake8-logging-format` for consistent logging, * pep8-naming `for verifying that PEP8 naming conventions are followed` * `pyflakes` for checking source files for various errors * `ryceratops` to avoid exception anti-patterns
Hey reviewers 👋 As you can see, I enabled a few flake8 plugins to check the code for various issues, antipatterns, etc. However, there are two types of errors I am not happy with:
My first intention is to disable those checks unless you have a different opinion. |
Here's a detailed description of these rules: They both make sense to me, but I don't know where you see these violation so cannot comment if it makes sense to fix or ignore in our context. |
@@ -111,11 +111,11 @@ def _convert_ansi_codes_to_html(msg): | |||
def _format_truncated_traceback(traceback, max_num_chars=2000): | |||
"""Truncate the traceback to the given character length.""" | |||
n = 0 | |||
for i, line in enumerate(reversed(traceback)): | |||
for _i, line in enumerate(reversed(traceback)): |
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 don't understand this change, it looks very confusing to me. Which rule is violated here?
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.
The format checker said something like: "i
was not used inside the loop, so add an underscore in front."
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.
Fair, but still looks very confusing to me, never seen a variable (not method) prefixed with underscore. Maybe call it lineno
or line_number
?
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.
Fair, but still looks very confusing to me, never seen a variable (not method) prefixed with underscore. Maybe call it
lineno
orline_number
?
You meant _lineno
/_line_number
? Cause I don’t think the name without an underscore will satisfy the checks.
Here are a few words about the use of underscore for the variable names: https://medium.com/python-features/naming-conventions-with-underscores-in-python-791251ac7097
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 misunderstood then. So be it, but I'd still use a more descriptive variable name to make things clearer. Thanks!
In the article they explain the use the use of a leading underscore to indicate private vars / methods, which I was familiar with, but I don't think that is the case here so it still looks odd to me tbh.
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.
You are right. In the end, this is only to satisfy the check. Probably, this part of the code could be written better.
Co-authored-by: Daniel Hollas <daniel.hollas@bristol.ac.uk>
Just have a look at the pre-commit ci. They are there. |
As the TC101 indicates, the try:
computer = computer_builder.new()
computer.store()
except (
ComputerBuilder.ComputerValidationError,
common.exceptions.ValidationError,
) as err:
self.message = f"{type(err).__name__}: {err}"
return False
except common.exceptions.ValidationError as err:
self.message = f"Unable to store the computer: {err}."
return False The EDIT: I just noticed that |
As for TC003, I don't know how to get rid of them since we're using the built-in exception classes. 🤷 Note that the |
@yakutovicha I would also suggest to add the nbstripout pre-commit, which automatically strips output cells from Jupyter notebooks. I am using it in my App and find it very useful, and @unkcpz recently added it to QeApp as well. |
Thanks, I've just added this. |
Thanks, fixed in 87f5f4c |
I think they propose avoiding custom strings in exceptions completely. At least, this is what I understood looking at the link you've shared above. At the same time, I don't get why the following code receives complaints: aiidalab-widgets-base/aiidalab_widgets_base/wizard.py Lines 96 to 98 in 87f5f4c
Why the code below doesn't: aiidalab-widgets-base/aiidalab_widgets_base/viewers.py Lines 791 to 794 in 87f5f4c
|
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.
@yakutovicha thanks for the additional changes. I only have a couple of comments regarding naming and docstrings to make things clearer.
return False | ||
else: | ||
return True | ||
|
||
def on_setup_computer(self, _=None): |
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 am a bit confused here. The function name is on_setup_computer
, but the doc string says Create a new computer
. What is the main purpose of this function?
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.
The main purpose of this function is when the "setup computer" button is clicked, setup (create) a new computer.
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.
The main purpose of this function is when the "setup computer" button is clicked, setup (create) a new computer.
yep, that is correct, but this is also called when running quicksetup
. So I can't rename it to something like on_setup_computer_button_clicked
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.
@yakutovicha thanks for the context. Okay, in that case it would be great to expand the doc string on this function to explain when this function is called. This widget is doing so many things that it is beneficial for things to be documented well.
One of the tests seems to be broken, looks like the |
@yakutovicha I make a commit to fix the failed notebook test, hope you don't mind. |
suggestions applied, review re-requested. |
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.
@unkcpz @yakutovicha I've looked through the code, and the only callbacks that seem to be registered in _on_setup_computer_success
are calls that refresh the widgets' state. But in that case, I don't think these should be run if the computer already exists in the first place. Also, the name on_setup_computer_success
implies to me that they should only be run when a new computer is created.
The same comment probably applies to on_setup_code_success
callbacks.
Since this PR is about linters, I do not want to block it on this issue, but it should be addressed in a separate PR since we've already dug into it anyway.
self.message = f"Unable to store the computer: {err}." | ||
return False | ||
|
||
if self._configure_computer(computer): |
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.
@yakutovicha it looks like you deleted the call to _configure_computer()
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 am also curious about this, I think this is needed. I am pretty sure this PR has some problem, I test it locally and it failed. Hope the test can catch the issue. I'll try to fix those then.
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 would be good if you could verify that your new tests fail when this line is deleted. :-)
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.
Great! that exactly manifest the bug. Add the configure function back to solve the issue. You can find the change from last commit 1c568d3
I also change a bit of the setup-configure flow, I combine the computer "setup" and "configure" in the block of a try, which only store the computer node when the setup and the configure are both successful. I did this because we only provide the widget called "Computer Setup" but no "computer configure". When the computer is setup and stored but the configure phase is not finished. The computer in the database has the UUID but leaves it in a very strange state and can not be used for further code setup.
Why you think this should not be run when the computer already exists? The function |
Well, my thinking was that if the computer already exists, it would have been in the Dropdown already so no need to refresh. But I guess the computer could be create somehow outside of the widget, making the UI not up to date. Anyway, feel free to ignore this. |
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.
@unkcpz thanks for finishing this!
@danielhollas thanks for the review. @yakutovicha I'll let you have a final check and merge the PR. |
All good, @unkcpz @danielhollas! Thanks a lot for your help! |
@@ -835,14 +835,13 @@ def _configure_computer(self, computer: orm.Computer): | |||
"use_login_shell": self.use_login_shell.value, | |||
"safe_interval": self.safe_interval.value, | |||
} | |||
if "user" in sshcfg: |
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.
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.
Ha! You are correct, that makes sense, I'll reconsider how this part of the code should work. It currently leads to two new small issues.
As mentioned in aiidalab/aiidalab-qe#388, the workchain selector is one of the sources lead to the memory leak. It uses a spare threading to update the list which is not fully necessary because the `refresh` button is already served for this purpose. In this PR we did not only remove the threading but also decouple the QeAppWorkChain specific code out as the sub-class, so the WorkChainSelector can be re-used through inherited by other apps.
flake8-bugbear
for detecting bugs and potential design problemsflake8-builtins
for verifying that builtins are not used as variable namesflake8-comprehensions
for writing better and consistent comprehensionsflake8-debugger
for checking that there are no forgotten breakpointsflake8-logging-format
for consistent logging,for verifying that PEP8 naming conventions are followed
pyflakes
for checking source files for various errors