-
Notifications
You must be signed in to change notification settings - Fork 192
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
👌 CLI: Computer/Code export output_file
optional
#6486
👌 CLI: Computer/Code export output_file
optional
#6486
Conversation
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 @GeigerJ2 fully agree with the feature, just some comments on the implementation
@GeigerJ2 I would like to release today please and this is the last open PR. Would it be possible to wrap this up a.s.a.p.? Or shall we punt it? |
We're on a group hike today, so unfortunately cannot work on it right now. I could wrap it up tomorrow morning first thing. Otherwise, if it cannot wait, feel free to release without, don't think it's that crucial. |
4f7a280
to
db62596
Compare
Alright, so I think this is ready for a second round of reviews. I should have resolved your original comments, @sphuber. Though, there's no rush as the new version is already released. For all three commands ( After taking a closer look at the tests again, I felt like the parametrization for the sorting was actually a bit unnecessary, so I removed it in the last commit ( |
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #6486 +/- ##
==========================================
+ Coverage 77.51% 77.78% +0.28%
==========================================
Files 560 562 +2
Lines 41444 41885 +441
==========================================
+ Hits 32120 32578 +458
+ Misses 9324 9307 -17 ☔ View full report in Codecov by Sentry. |
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 @GeigerJ2 . Fine with the implementation, just some minor implementation details. I am not sure I like the approach of the tests though where you are using a single test for all possible combinations. This tends to be very fragile as later tests in the function implicitly rely on some preconditions that were created (or not) by previous asserts and calls to the command. I think it is better to have separate test functions for the various options that are well separated. You are then forced to set up the necessary pre-conditions (for example pre-creating the output file in the case you are testing the user specifying a file that already exists) and it becomes also very clear when reading.
Also, I think using parametrization and using file_regression
is a good thing. It makes for lean and easy to read tests. Now you are manually implementing the parametrization and reading/comparing outputs that is much more fragile and difficult to follow.
Thanks a lot for the review, @sphuber! Already a top-level answer, will resolve the issues soon:
Yeah, I was also not sure about that. As of now, the functions are very long. I'll split them up. Also, that's a good point that you bring up with some parts of the tests being reliant on previous calls of the function being tested, I'll definitely keep that consideration in mind!
Using Further, I also considered parametrizing all input parameters, e.g. |
ef7ee62
to
7adcf46
Compare
Still requires some clean-up. Hope I get around this tomorrow. |
8cf3d2e
to
289bab2
Compare
So As discussed with @khsrali, I'm inclined to just remove the |
It is not dependent on the backend. The order for output that is based on pydantic models will be determined by the order of the fields as they are declared in the model. However, that is currently only the case for the The test that is failing is for the configuration of the computer though, and those values are taken from the I would simply just disable the |
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 @GeigerJ2 I added some annoying comments :)
show_default=True, | ||
) | ||
@arguments.OUTPUT_FILE(type=click.Path(exists=False, path_type=pathlib.Path), required=False) | ||
@options.OVERWRITE() |
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 might be a bit of hassle and maybe unnecessarily. This is what happens to user:
- Hit the error
FileExistsError
first time, - discover there is such option as overwrite
- run again with
--overwrite
Instead one could easily just index files:
For example if file mycomputer.yaml
exists just produce mycomputer_1.yaml
if that exists just do mycomputer_2.yaml
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.
btw, this is what my browser does when I download files. They used to raise file exist in the past, and aske user for a new file name :)
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 personally not a fan of this to be honest. If the user explicitly specified the output file, I wouldn't want the command to silently change it. Of course you could get around the "silently" a bit by printing a warning that the message was changed, but this will not help in scripting use cases.
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 comments, @khsrali! There's no such thing as an annoying review :)
I see where you're coming from, but I'm not sure that I like the idea of automatically indexing the files, as that leads to the output name of the file being different from the label of the AiiDA entity, and I'd like those to be consistent. Suppose I run verdi computer list
and I'm getting the output mycomputer
. When I export it, I expect the file to be named mycomputer.yaml
. Instead, if the file is called mycomputer_1.yaml
, I might get confused (ofc we can inform the user, but still). Then, the user might still not be aware of the --overwrite
flag, and then has to either run the command again using that, or mv
his file to overwrite the original one or get the directory polluted with a bunch of files.
In the end, with all these commands that write to disk, we have to make some decisions, e.g. file names, how to handle overwriting, etc., and there's no right or wrong, and people have different preferences. I don't have a strong opinion, but slightly prefer the current behavior. Let's see what @sphuber thinks.
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 see your points, my concern was mainly when the user is not specifying an output_name
so he doesn't really care... But no strong opinion.
output_file = generate_validate_output_file( | ||
output_file=output_file, entity_label=code.label, overwrite=overwrite, appendix=f'@{code_data["computer"]}' | ||
) | ||
except (FileExistsError, IsADirectoryError) as e: |
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.
Normally you can always create files with same name as folders in OS.
I would say just ignore and still make the file.
The less unnecessarily raise, less annoyed user, 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.
Here I definitely don't agree. If I accidentally specify the filename that happens to be a directory and the command just deletes the entire directory and overwrites it with a file, I'd be pretty pissed. I think the "annoyance" of having to change the output filename or specify --overwrite
is way less than all the accidental loss of data.
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.
Personally, I would find it super confusing to have both, a file, and a directory with exactly the same name, even if it is theoretically possible. In any case, it should be very much an edge case, I don't expect users to have directories that end with .yml
. And if they do, they should be notified of that, I think :D
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.
try: | ||
output_file = generate_validate_output_file( | ||
output_file=output_file, entity_label=computer.label, overwrite=overwrite, appendix='-setup' | ||
) | ||
except (FileExistsError, IsADirectoryError) as e: | ||
echo.echo_critical(message=e) | ||
|
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.
Maybe I'm wrong, but generate_validate_output_file
seems like a redundant function :) ?
It raises two built-in errors IsADirectoryError
& FileExistsError
that are being handled all together right here.
I mean write_text
itself raises FileExistsError
, and in my opinion IsADirectoryError
doesn't need to be raised at all.
Apart from that, also has output_file
both as input and output. Feels a bit weird :)
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 other functionality of the function is to define the default value of the output file in case one hasn't been specified by the user. This is also why the function returns the output file
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 reason I created the function is because the logic was duplicated three times, for verdi computer export setup
, verdi computer export config
, and verdi code export
, including the different exception texts. So I thought it's better to move it to a single location and re-use the code, although I agree it might not be strictly necessary. Same argument with write_text
: I think if we would wait until this call to run into the FileExistsError
, the handling logic would have to be repeated, as the call happens at different places in the code, e.g. for the Computer
config there is a call to computer.get_configuration(user)
before. Probably one could restructure the overall logic a bit, but I didn't want to modify @agoscinski's logic that he put in place when implementing the verdi computer export
feature.
If passing output_file
as input and output is bad practice here in that case, I'm happy to change it :)
289bab2
to
de07f8f
Compare
Thanks for the explanation, @sphuber, that makes a lot of sense! I removed the |
@GeigerJ2 I was just about to approve and merge this until I saw the last commit? Why are you changing that? |
Wanted to be extra sure to not cause any confusion ^^ I can revert it. |
9ceddf0
to
de07f8f
Compare
de07f8f
to
491ab3e
Compare
Thanks a lot @GeigerJ2 |
Thanks for the merge, @sphuber! Sorry this took a bit longer than anticipated, but good learning experience :) |
As the title states: The
output_file
argument forverdi computer export [setup,config]
andverdi computer export
is made optional by generating a default filename based on the respective label, if not specified.I think this should be what people would probably call their files most of the time anyway.