Improve typing consistency in codebase#1311
Conversation
resolves typing error for later "molecule_data[i] = ..." as NoneType is not sub-scriptable
Raises valueError if molecule_data is None
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #1311 +/- ##
==========================================
- Coverage 89.25% 87.97% -1.29%
==========================================
Files 30 31 +1
Lines 5810 6047 +237
==========================================
+ Hits 5186 5320 +134
- Misses 624 727 +103 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
ns-rse
left a comment
There was a problem hiding this comment.
Good work tackling this behemoth of a task @ubdbra001 and apologies for it being so messy (typing only came onto my radar way after I'd started).
Some comments in-line from a quick scan, don't have time to investigate more deeply I'm afraid.
| Returns | ||
| ------- | ||
| np.array | ||
| npt.ArrayLike |
There was a problem hiding this comment.
I've not come across npt.ArrayLike before so had to look it up.
In this instance the function return np.asarray(filtered_arr1) and so whilst it could be considered as something that could be converted to an array it is already an array so I wonder if npt.NDArray is more appropriate as we (should) know what the dtype should be although it's currently missing.
Disclaimer typing is not one of my strong points!
There was a problem hiding this comment.
Here's a post about it that seems to opine that npt.NDArray is marginally better.
npt.ArrayLike seems to be for objects that can be cast to arrays, including arrays.
There was a problem hiding this comment.
npt.NDArray sounds more sensible, and I suspect I've used it elsewhere, so I'll stick to that one. Thanks!
| A dictionary with keys 'image', 'img_path' and 'pixel_to_nm_scaling' containing a file or frames' image, it's | ||
| path and it's pixel to namometre scaling value. | ||
| topostats_object : Topostats | ||
| TopoStats object - Needs further info |
There was a problem hiding this comment.
How about...
| TopoStats object - Needs further info | |
| An object of type ``TopoStats`` class. |
There was a problem hiding this comment.
That works, I was wondering if there should be a little more, e.g. run_curvature_stats has:
``TopoStats`` object post splining, all ``Molecules`` within the ``grain_crops`` attribute (a dictionary of
``GrainCrop`` should have ``splined_coords`` attributes populated.
There was a problem hiding this comment.
Hmmm, typically these will be newly instantiated but there is nothing stopping an existing TopoStats (e.g. loaded from disk / .topostats file) object being passed in here
An object of type ``TopoStats`` class with a minimum of ``image_original``, ``filename`` and ``pixel_to_nm_scaling`` attributes which allow filtering to be run.
I think those are the bare minimum but could be wrong.
There was a problem hiding this comment.
Okay, I'll add those, and we can update it in future if required.
| grain_stats_df.index.set_names(["grain_number", "class", "subgrain"], inplace=True) | ||
| else: | ||
| grain_stats_df = None | ||
| return topostats_object.filename, topostats_object, grain_stats_df |
There was a problem hiding this comment.
Not for this work but I thought I'd removed returning of dataframes as they are instead pulled out of the topostats_objects and collated into a dictionary before converting to pd.DataFrame.
There was a problem hiding this comment.
This was the only one I've spotted so far, happy to open an issue to be addressed later
There was a problem hiding this comment.
Note it as an issue, its at least then recorded and can be addressed if anyone has time/inclination.
SylviaWhittle
left a comment
There was a problem hiding this comment.
Just a thing I noticed skim-reading this.
| Returns | ||
| ------- | ||
| tuple[str, pd.DataFrame] | ||
| tuple[str, pd.DataFrame] - Deprecated, needs updating |
There was a problem hiding this comment.
Alas, Ty sees that filename property can be None despite (I think) a TopoStats object without filename should not be possible?
There was a problem hiding this comment.
So currently, according to the types specified in the TopoStats class, filename is optional, and so it can be None: filename: str | None = None
Which is why Ty complains.
I've had a go at changing this already, but if I remember correctly it caused a bunch of tests to fail, and I didn't want to deal with that quite yet. That'll be the next round of updates (when I have got as much of the low handing fruit as possible)
Adds correct return typehint Co-authored-by: Neil Shephard <n.shephard@sheffield.ac.uk>
Add correct return type hint Co-authored-by: Sylvia Whittle <86117496+SylviaWhittle@users.noreply.github.com>
| @@ -214,7 +214,7 @@ def compile_images( | |||
| @staticmethod | |||
| def remove_common_values( | |||
| ordered_array: npt.NDArray, common_value_check_array: npt.NDArray, retain: list = () | |||
There was a problem hiding this comment.
On this:
retainis typed aslisttype but being assigned an emptytupleby default 🤔- Setting the default value to an empty
listmay cause issues (see here).
I'll probably set it as None and add a check so that it get re-set to an empty list if the arg is not supplied.
Any objections?
| molecule_data : dict[int, Molecule], optional | ||
| Dictionary of ``Molecule`` objects indexed by molecule number. | ||
| tracing_stats : dict | None | ||
| tracing_stats : dict, optional |
There was a problem hiding this comment.
I have been going around replacing | None with , optional in the docstrings. Probably doesn't have a real impact but I thought I'd make it all consistent.
Let me know if you'd prefer to retain | None
| Dictionary, indexed by molecule where the value is the molecules statistics for the given molecule. | ||
| """ | ||
| if self.molecule_data is None: | ||
| raise ValueError("No molecule data found") |
There was a problem hiding this comment.
Let me know if you'd like me to change this to something else
Correct to a tuple of str and dict
Corrects the type hint and the docstring
ns-rse
left a comment
There was a problem hiding this comment.
Some responses in-line...
| A dictionary with keys 'image', 'img_path' and 'pixel_to_nm_scaling' containing a file or frames' image, it's | ||
| path and it's pixel to namometre scaling value. | ||
| topostats_object : Topostats | ||
| TopoStats object - Needs further info |
There was a problem hiding this comment.
Hmmm, typically these will be newly instantiated but there is nothing stopping an existing TopoStats (e.g. loaded from disk / .topostats file) object being passed in here
An object of type ``TopoStats`` class with a minimum of ``image_original``, ``filename`` and ``pixel_to_nm_scaling`` attributes which allow filtering to be run.
I think those are the bare minimum but could be wrong.
| grain_stats_df.index.set_names(["grain_number", "class", "subgrain"], inplace=True) | ||
| else: | ||
| grain_stats_df = None | ||
| return topostats_object.filename, topostats_object, grain_stats_df |
There was a problem hiding this comment.
Note it as an issue, its at least then recorded and can be addressed if anyone has time/inclination.
|
Just a thought but it might be worth adding commits to |
Docstring for second value in return tuple needs to be updated
These specify that the values in the dict are not None after processing
However, I don' see these being used anywhere, so it may be worth just deleting?
To match return value type hint
Currently very broad value type, I couldn't parse what they could be from the code
|
I think I've got all the low hanging typing fruit, anything else this will cause tests to fail and so I suspect will require a bit more discussion. |
Fix #1299
This PR addresses the inconsistent typing in the codebase.
Given the size of this I'm going to do it incrementally in this PR. The initial stage of this is picking out the "easy wins" e.g. cases where the type hints are missing or incorrect and are easy/obvious to update.
At this stage all the tests still pass.
Before submitting a Pull Request please check the following.
docs/configuration.mddocs/usage.mddocs/data_dictionary.mddocs/advanced.mdand new pages it should link to.