Fixate
Fixate copied to clipboard
Check Functions do not display datetime comparisons helpfully
Comparing datetime functions in a chk_* will show .3g instead of the repr for the datetime object. This could overflow into other object time comparisons that are not float or integer based.
Had a go at replicating this issue but without any luck. Ended up writing some tests for chk_smaller. They're in my fix-time-checks fork in Fixate/test/core/test_checks.py if it helps.
@pazzarpj, have you got a script that shows the error? or can you write a failing test?
from datetime import datetime, timedelta
from fixate.core.checks import CheckClass, _in_range
from fixate.ui_cmdline.cmd_line import _print_comparisons
chk1 = CheckClass(_min=2, _max=3, test_val=2.5, target=_in_range)
date_thing = datetime(2019, 1, 1, 0, 0)
chk2 = CheckClass(_min=date_thing - timedelta(seconds=2), _max=datetime.now() + timedelta(seconds=2), test_val=date_thing, target=_in_range)
_print_comparisons(True, chk1, 1, None)
_print_comparisons(True, chk2, 2, None)
Expected output
Check 1: PASS when comparing 2.5 in range 2 - 3 :
Check 2: PASS when comparing 2019-01-01 00:00:00 in range 2018-12-31 23:59:58 - 2019-01-01 00:00:02 :
Actual
Check 1: PASS when comparing 2.5 in range 2 - 3 :
Check 2: PASS when comparing .3g in range .3g - .3g :
There seems to be an issue with timestruct objects as well in that script. They're displayed with their data but always pass:
t = time.localtime(time.time())
chk3 = CheckClass(_min=time.localtime(1545925760), _max=time.localtime(1545925777), test_val=t, target=_in_range)
_print_comparisons(True, chk3, 3, None)
Check 3: PASS when comparing time.struct_time(tm_year=2019, tm_mon=4,
tm_mday=5, tm_hour=19, tm_min=50, tm_sec=33, tm_wday=4, tm_yday=95,
tm_isdst=1) in range time.struct_time(tm_year=2018, tm_mon=12, tm_mday=28,
tm_hour=2, tm_min=49, tm_sec=20, tm_wday=4, tm_yday=362, tm_isdst=1) -
time.struct_time(tm_year=2018, tm_mon=12, tm_mday=28, tm_hour=2, tm_min=49,
tm_sec=37, tm_wday=4, tm_yday=362, tm_isdst=1)
However the issue doesn't seem to occur when using chk_in_range for either timestruct or datetime objects as the following tests pass:
def test_time_struct_check_true():
t = time.localtime(1545925765)
chk = chk_in_range(t, time.localtime(1545925760), time.localtime(1545925777), "Time is in range")
assert chk
def test_time_struct_check_false():
with pytest.raises(CheckFail):
t = time.localtime(1554452763)
chk = chk_in_range(t, time.localtime(1545925760), time.localtime(1545925777), "Time is NOT in range")
def test_datetime_struct_check_true():
t_min = datetime.now()
time.sleep(1)
t = datetime.now()
time.sleep(1)
t_max = datetime.now()
chk = chk_in_range(t, t_min, t_max, "DateTime is in range")
assert chk
def test_datetime_struct_check_false():
with pytest.raises(CheckFail):
t_min = datetime.now()
time.sleep(1)
t_max = datetime.now()
time.sleep(1)
t = datetime.now()
chk = chk_in_range(t, t_min, t_max, "DateTime is not in range")
assert chk
The script I provided was to demonstrate the display issue, the CheckClass doesn't actually run the check.
_print_comparisons first parameter determines if it displays as pass/fail.
The issue is that the _print_comparisons function assumes a number with the {:.3g} string formatter.
Riiight, i finally get it now. I'll stop barking up the wrong tree. Will look into it when i get a chance. Thanks for slow walking me there.
Issue found in ui_cmdline\cmd_line.py line 304:
def round_to_3_sig_figures(chk):
"""
Tries to round elements to 3 significant figures for formatting
:param chk:
:return:
"""
ret_dict = {}
for element in ["_min", "_max", "test_val", "nominal", "tol"]:
ret_dict[element] = getattr(chk, element, None)
try:
ret_dict[element] = "{:.3g}".format(ret_dict[element])
except:
pass
return ret_dict
format with decimal places does not produce the desired output but does not raise an error when datetime object is used.
Adding an assert math.isclose within the try: rejects the change of format, allowing the original formatting (standard datetime object output) to be shown:
Check 1: PASS when comparing 2.5 in range 2 - 3 :
Check 2: PASS when comparing 2019-01-01 00:00:00 in range 2018-12-31
23:59:58 - 2019-04-08 21:52:25.021197 :
Will run a few more tests and upload the code.