-
Notifications
You must be signed in to change notification settings - Fork 24
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
run conversion: Use context manager only in append mode #1180
Conversation
@@ -131,23 +131,13 @@ def test_run_conversion_with_backend(self, setup_interface, tmp_path, backend): | |||
io.read() | |||
|
|||
@pytest.mark.parametrize("backend", ["hdf5", "zarr"]) | |||
def test_run_conversion_with_backend_configuration(self, setup_interface, tmp_path, backend): | |||
def test_create_backend_configuration(self, setup_interface, tmp_path, backend): |
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.
Those tests were not doing anything. See the bug described here:
And if we were to make them work they would be duplicating a test that is already run in two other places.
So I changed the name to reflect what the test was actually doing but I would be fine with removing them entirely.
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.
Shouldn't this test be checking that run_conversion runs properly when you pass a custom backend_configuration? How is this redundant with the other tests? What am I missing 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.
Yes, you are right, it is not redundant especially if I change both converter and interface versions.
Thinking about this I do want to get rid of these tests completely but I will open another PR describing my reasoning as I don't want this to get in the way.
I will revert this to just eliminate the passing of the nwbfile which does not make sense.
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.
Overall looks good!
I just suggested a small fix for the ValueError and some clarification about test_run_conversion_with_backend_configuration
src/neuroconv/basedatainterface.py
Outdated
if appending_to_disk_nwbfile: | ||
raise ValueError( | ||
"Cannot append to an existing file while also providing an in-memory NWBFile. " | ||
"Either set overwrite=True to replace the existing file, or remove the nwbfile parameter to append to the existing file on disk." | ||
) |
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 would prefer to raise this value error right at the beginning for clarity. Also, I think it should be
if appending_to_disk_nwbfile and appending_to_in_memory_nwbfile:
raise ValueError(...)
right?
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 condition was wrong, I fixed it now. Thanks.
I would like the error to be nested in the apend mode branch. I am also coming at this from the clarity angle but with a different reasoning.
People who read the code should not be bothered with the complexities of the apend case unless they get to that branch. In most cases, run_conversion
is working as a write_to_nwbfile
(which I think should be a method!) and I don't want the first reading of the function to introduce unrelated complexities.
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 really disagree. This is input validation for the function, so it should go right at the top with the inputs. By having in the append branch it's more nested, and to understand the condition you have to combine an else with a not: else(not appending_to_in_disk_nwbfile) + appending_to_in_memory_file
. In contrast, I don't think it is hard to understand at all that appending_to_in_memory_nwbfile
and appending_to_in_disk_nwbfile
can't both be true at the same time --> ValueError, even without understanding anything about the details of those branches.
With all that being said, this is just style, so if you are still adamant about keeping it where it is, I won't insist.
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.
Those are good points. I will move it.
I still have the lingering feeling of wanting to push the complexities of appending mode outside of the happy path but maybe I should push for a write_to_nwbfile
functionality outside of this PR. I think should be easier to read, use, and document for both developers and users.
run_conversion
, like the context manager here, has too many responsibilities which leads to too many arguments an anti-pattern and a code smell.
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 still have the lingering feeling of wanting to push the complexities of appending mode outside of the happy path but maybe I should push for a
write_to_nwbfile
functionality outside of this PR. I think should be easier to read, use, and document for both developers and users.
run_conversion
, like the context manager here, has too many responsibilities which leads to too many arguments an anti-pattern and a code smell.
Yep, isolating the complexity of append mode makes sense to me. I look forward to seeing those changes, and lmk if you need any help.
src/neuroconv/nwbconverter.py
Outdated
if appending_to_disk_nwbfile: | ||
raise ValueError( | ||
"Cannot append to an existing file while also providing an in-memory NWBFile. " | ||
"Either set overwrite=True to replace the existing file, or remove the nwbfile parameter to append to the existing file on disk." | ||
) |
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.
Same as with basedatainterface
@@ -131,23 +131,13 @@ def test_run_conversion_with_backend(self, setup_interface, tmp_path, backend): | |||
io.read() | |||
|
|||
@pytest.mark.parametrize("backend", ["hdf5", "zarr"]) | |||
def test_run_conversion_with_backend_configuration(self, setup_interface, tmp_path, backend): | |||
def test_create_backend_configuration(self, setup_interface, tmp_path, backend): |
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.
Shouldn't this test be checking that run_conversion runs properly when you pass a custom backend_configuration? How is this redundant with the other tests? What am I missing here?
This will also fix #1183 |
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #1180 +/- ##
==========================================
- Coverage 90.69% 89.58% -1.11%
==========================================
Files 129 129
Lines 8189 8357 +168
==========================================
+ Hits 7427 7487 +60
- Misses 762 870 +108
Flags with carried forward coverage won't be shown. Click here to find out more.
|
This change addresses issues like bug #1114.
This also fixes #1159 by adding proper error messages.
Moreover, this fixes #1183 as the context manager interprets a faulty file on nwbfile_path as intent to use append mode.
To add more description to #1114, the core problem lies in the risk of creating a new interface without adhering to the implicit contract for importing extensions during initialization. This PR eliminates the possibility of unintentionally introducing subtle, hard-to-detect bugs. Furthermore, as highlighted in the discussion of #1143, the logic without a context manager is simpler to understand and covers approximately 95% of use cases.