-
Notifications
You must be signed in to change notification settings - Fork 1
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
Deprecate CubeSlice shape property #101
Conversation
warnings.warn('Deprecated. Use `get_shape` instead.', DeprecationWarning) | ||
return self.get_shape() | ||
|
||
def get_shape(self, prune=False): |
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.
Please add docstring (PEP 257) describing interface and what a shape is.
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.
Done. I've run the pylint
on the entire file, should be better now...
warnings.warn(deprecation_msg, DeprecationWarning) | ||
return self.get_shape() | ||
|
||
def get_shape(self, prune=False): |
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.
memoize this.
src/cr/cube/cube_slice.py
Outdated
"""Return the shape of the slice. | ||
|
||
This property is anloguous to numpy's 'shape' property of ndarray. It | ||
returns a tuple, returning the shape of the slice's 'as_array' method. |
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 always be preferable to avoid re-using the name of the method in its docstring. If a person doesn't know what "shape" means in this context, this docstring is going to make them work for it. So in this case, the second sentence might be better as: "It returns a tuple of ints, each representing the length of a cube dimension, in the order those dimensions appear in the cube."
I would add a blank line before the deprecated sentences. That topic is separate enough to warrant a distinct paragraph.
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 thoughtful comment. This level of code review really means much to me.
I've addressed the comment. The first line of the docstring I copied from here, and modified it a little bit. The second sentence I took as you put it.
Please also check if the other modified docstring (of the method get_shape
) is OK.
af4e8c3
to
00970ef
Compare
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.
Okay, I left some feedback for whatever it's worth to you, but changes are not required, just some suggestions for possible improvements.
tests/unit/test_cube_slice.py
Outdated
mock_sm_init.return_value = None | ||
|
||
cs = CubeSlice({}, 0) | ||
fake_axis = Mock() | ||
cs.scale_means_margin(fake_axis) | ||
assert mock_sm_margin.called_once_with(fake_axis) | ||
|
||
def test_shape(self): | ||
"""Test shape based on 'as_array' and pruning.""" |
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 looks like a good candidate for a parameterized test, maybe something like this:
def it_knows_its_shape(self, shape_fixture): # ---or named `test_shape()` if you prefer---
cube_slice, prune, expected_shape = shape_fixture
shape = cube_slice.get_shape(prune=prune)
assert shape == expected_value
@pytest.fixture(params=[
(False, None, (3, 2)),
(True, [[True, False], [True, False], [True, False]], (3,)),
etc.
])
def shape_fixture(self, request, cube_):
prune, mask_map, expected_value = request.param
cube_.ndim = 2
cube_.as_array.return_value = np.ma.masked_array(
np.zeros((3, 2)), mask=np.array(mask_map) if mask_map else None
)
cube_slice = CubeSlice(cube_, 0)
return cube_slice_, prune, expected_value
This isn't complete (or even correct) in every detail, but maybe gives you an idea. I recommend making the warning test a separate test method since its form and asserts are very different.
Using the fixture allows the test to be very clear and adding new cases is trivial and doesn't duplicate code.
|
||
This property is deprecated, use 'get_shape' instead. Pruning is not | ||
supported (supported in 'get_shape'). | ||
""" |
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.
Sweet ❤️ :)
src/cr/cube/cube_slice.py
Outdated
@@ -252,15 +266,65 @@ def is_double_mr(self): | |||
return self.dim_types == ['multiple_response'] * 2 | |||
|
|||
def scale_means(self, hs_dims=None, prune=False): | |||
"""Calculate scale means of the CubeSlice.""" |
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's a fine point, but I always use the word "Return" as the first word of the docstring for a method that returns a value. So something like "Return scale-means for this cube slice." This is the key aspect of the contract of such a method (the return value and type) and what the caller cares about most. Saying "Calculate" could just indicate a side-effect and leaves the reader to dig into the code (which often they won't have when just looking at the docs).
As an aside, in the case of a property, I leave the 'Return' word out, like "int count of foos in bar" instead of 'Return int count of foos in bar', since the semantics of a property are a value rather than a procedure.
You'll also need to say what scale-means are and what form you deliver them in. If that's not compact enough for the summary line, then in a body paragraph of the docstring. Even then, it's worth every effort not to repeat the method name in the summary because it provides no additional information. It could be something like """Return list containing scaled-mean for each slice column.""" or something and already starts to give more insight into the method contract.
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.
Done, thanks
- Deprecation warning when `shape` property is used - Implement `get_shape` method, that uses `prune` argument - Unit tests
- Improve docstrings
- Create parametrized test for checking 'get_shape' method - Create separate test for deprecating 'shape' property - Remove unittest, use pytest only
d9f028b
to
c59ecbb
Compare
shape
property is usedget_shape
method, that usesprune
argument