-
Notifications
You must be signed in to change notification settings - Fork 20
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
Improve TimeRecurrence class #183
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.
Looks ok, a quick test would be nice. (Outdated)
f496ee8
to
51da3f5
Compare
Codacy is complaining about
in a test. Can we change pylint to flake8 on there, and if so, how? |
I can't see a setup file so I think that you need to get a product owner on Codacy to change things there. I wouldn't worry too much about codacy failures. I've proposed a change of the testing to use flake8, on the grounds of consistency with other projects at #185 |
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.
Essential
- works
- tests test what they should test
Non-essential
- tests could look nicer. TBH I think there is a case for an entirely separate PR to refactor the tests for isodatetime into a pytest format. Don't worry about it here if you don't want to.
metomi/isodatetime/tests/test_00.py
Outdated
repetitions=rep, duration=dur, | ||
end_point=data.TimePoint(year=2020, month_of_year=4, | ||
day_of_month=3)) | ||
assert recurrence_fmt3 == recurrence_fmt4 |
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.
Why are you asserting equality here, when this is test for adding?
Is it to establish equality before you operate on these recurrences?
Should you also be asserting that recurrence_fmt3 == recurrence_fmt1
assert recurrence_fmt3 == recurrence_fmt4 | |
# check that all three recurrence formats are seen as equal. | |
assert recurrence_fmt1 == recurrence_fmt3 == recurrence_fmt4 |
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, I figured as they are meant to be the same it would help to check that in case something breaks (although there is a separate test for the TimeRecurrence comparison operators, at least it should let the developer know it's not a problem with the add/sub methods).
Format 1 might have been missed out because I hadn't yet fixed that format when writing the test, not sure
expected = data.TimeRecurrence( | ||
repetitions=rep, start_point=new_start_pt, duration=dur) | ||
for recurrence in (recurrence_fmt1, recurrence_fmt3, recurrence_fmt4): | ||
assert recurrence + offset == expected |
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 feels to me like it would be a lot cleaner parameterized. Sorry - hobby horse.
for recurrence in (recurrence_fmt1, recurrence_fmt3, recurrence_fmt4): | ||
assert recurrence - offset == expected | ||
|
||
with pytest.raises(TypeError): |
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.
IMO you should not be testing for success and failure in the same test as success.
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.
meh 😄
with pytest.raises(TypeError): | ||
recurrence_fmt3 + data.TimePoint(year=2049, month_of_year=2) | ||
|
||
def test_invalid_timerecurrence(self): |
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.
My view is that this would look nicer as
STUFF = {
'start_pt': data.TimePoint(year=2020, day_of_month=9),
'end_pt': data.TimePoint(year=2020, day_of_month=30),
'dur': data.Duration(hours=36)
}
@pytest.mark.parametrize(
'kwargs',
[
{
"repetitions": 4,
"start_point": STUFF['start_pt'],
"end_point": STUFF['end_pt'],
"duration": STUFF['dur']
},
{
"repetitions": None,
"start_point": STUFF['start_pt'],
"end_point": STUFF['end_pt'],
"duration": STUFF['dur']
},
]
)
def test_invalid_timerecurrence(kwargs):
"""Test that init'ing a TimeRecurrence with bad inputs raises error."""
with pytest.raises(BadInputError):
data.TimeRecurrence(**kwargs)
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.
Just tried that but it seems you can't parametrize methods of a class that extends unittest.TestCase
. At some point we'll overhaul these tests... at some point... But I imagine it makes sense to leave the tests grouped together until such a time
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.
Not too fussed, however, easy enough to dedent and remove the self argument.
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.
Looks ok to me:
- Could do with a couple of simple
str
tests since that logic has changed slightly. - Couple of docs changes may require a little thought.
The old behaviour was quite nice for arbitrary "chunking":
R5/2000/2001 # split 2000 into five chunks
So there is a risk it may be in use somewhere. I've done a scan on our site and can't find any active uses so hopefully we are safe on that one. It would be a good idea to come up with an alternative (even if it uses Jinja2) we can document somewhere [in Cylc].
Reminder (to myself or whoever updates isodatetime in Cylc) to run though the recurrence docs (which could do with some TLC), check examples and document this.
repetitions (int): The number of repetitions in the recurrence. If set | ||
to 1, the recurrence simply consists of one date-time, with no | ||
duration (i.e., the number of repetitions is inclusive of the first | ||
occurrence). If omitted, the number of repetitions is unbounded. |
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.
TODO:
Check that R/2000
and R1/2000
still do the same thing.
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.
Isn't R/2000
invalid, as that means it's unbounded, but then no duration is specified so it's impossible to make a sequence out of it?
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.
Sorry, this was a note to myself. Just checked R/2000
and R1/2000
still do the same thing they did before.
51da3f5
to
a8473fc
Compare
Updated/added relevant tests
Plus add TimeRecurrence __add__ test cases for fmt 1
Plus raise exception for a couple of cases of invalid TimeRecurrence inputs
a8473fc
to
71b6e6d
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.
Good to go here I think.
Running the cylc test battery against this branch I get the same number of failures as for the master branch which is hopefully a good sign that this is unlikely to have broken anything.
Follow up to #165
Implements an
__add__
&__sub__
methods in TimeRecurrence, allowing Durations to be added to TimeRecurrences. This takes the recurrence series and offsets it by the given duration.Fixes a longstanding bug Fix the implementation of recurrence format number 1 #45 where the implementation of TimeRecurrence format no. 1 was incorrect. This format seems rarely used in Cylc so hopefully we can get away with this breaking change.