def test_interval_constructor_period_smaller_than_bu(self): clnd = tb.Timeboard( base_unit_freq='H', start='04 Oct 2017', end='04 Oct 2017 23:59', layout=[0, 1], ) clnd2 = tb.Timeboard(base_unit_freq='H', start='04 Oct 2017', end='04 Oct 2017 23:59', layout=[0, 1], workshift_ref='end') # no ws reference time falls within this period: with pytest.raises(VoidIntervalError): clnd.get_interval('04 Oct 2017 01:15', period='T') with pytest.raises(VoidIntervalError): clnd2.get_interval('04 Oct 2017 01:15', period='T') # reference time of clnd.ws 1 (01:00) falls within this period: ivl = clnd.get_interval('04 Oct 2017 01:00', period='T') assert ivl._loc == (1, 1) # but not within this with pytest.raises(VoidIntervalError): clnd.get_interval('04 Oct 2017 01:59', period='T') # vice versa for clnd 2 with pytest.raises(VoidIntervalError): clnd2.get_interval('04 Oct 2017 01:00', period='T') ivl = clnd2.get_interval('04 Oct 2017 01:59', period='T') assert ivl._loc == (1, 1)
def test_tb_constructor_week5x8(self): week5x8 = tb.Organizer(marker='W', structure=[[1, 1, 1, 1, 1, 0, 0]]) amendments = pd.Series(index=pd.date_range(start='01 Jan 2017', end='10 Jan 2017', freq='D'), data=0).to_dict() clnd = tb.Timeboard(base_unit_freq='D', start='28 Dec 2016', end='02 Apr 2017', layout=week5x8, amendments=amendments) assert clnd.start_time == datetime.datetime(2016, 12, 28, 0, 0, 0) assert clnd.end_time > datetime.datetime(2017, 4, 2, 23, 59, 59) assert clnd.end_time < datetime.datetime(2017, 4, 3, 0, 0, 0) assert clnd.base_unit_freq == 'D' assert clnd('28 Dec 2016').is_on_duty() assert clnd('30 Dec 2016').is_on_duty() assert clnd('31 Dec 2016').is_off_duty() assert clnd('01 Jan 2017').is_off_duty() assert clnd('10 Jan 2017').is_off_duty() assert clnd('11 Jan 2017').is_on_duty() assert clnd('27 Mar 2017').is_on_duty() assert clnd('31 Mar 2017').is_on_duty() assert clnd('01 Apr 2017').is_off_duty() assert clnd('02 Apr 2017').is_off_duty()
def test_tb_set_worktime_source(self): clnd = tb.Timeboard(base_unit_freq='D', start='31 Dec 2016', end='12 Jan 2017', layout=[0, 1, 0, 0, 2, 0], worktime_source='labels') assert clnd.worktime_source == 'labels'
def test_tb_bad_worktime_source(self): with pytest.raises(ValueError): tb.Timeboard(base_unit_freq='D', start='31 Dec 2016', end='12 Jan 2017', layout=[0, 1, 0, 0, 2, 0], worktime_source='bad_source')
def test_timeboard_to_dataframe_selected_ws(self): clnd = tb.Timeboard(base_unit_freq='D', start='01 Jan 2017', end='12 Jan 2017', layout=[0, 1, 0, 2]) df = clnd.to_dataframe(1, 5) assert len(df) == 5
def test_tb_constructor_bad_amendments(self): with pytest.raises(TypeError): tb.Timeboard(base_unit_freq='D', start='01 Jan 2017', end='12 Jan 2017', layout=[1], amendments=[0])
def test_rollforward_no_such_duty(self): clnd = tb.Timeboard(base_unit_freq='D', start='31 Dec 2016', end='12 Jan 2017', layout=[0]) with pytest.raises(OutOfBoundsError): clnd('31 Dec 2016').rollforward()
def test_rollback_only_alt(self): clnd = tb.Timeboard(base_unit_freq='D', start='31 Dec 2016', end='12 Jan 2017', layout=[0]) with pytest.raises(OutOfBoundsError): clnd('10 Jan 2017').rollback()
def test_tb_add_schedule(self): clnd = tb.Timeboard( base_unit_freq='D', start='31 Dec 2016', end='12 Jan 2017', #layout=[0, 1, 0, 0, 2, 0]) layout=['O', 'A', 'O', 'O', 'B', 'O']) assert len(clnd.schedules) == 1 assert 'on_duty' in clnd.schedules clnd.add_schedule(name='sdl1', selector=lambda x: x == 'B') clnd.add_schedule(name='sdl2', selector=lambda x: x == 'C') assert len(clnd.schedules) == 3 assert 'sdl1' in clnd.schedules sdl1 = clnd.schedules['sdl1'] assert sdl1.name == 'sdl1' assert not sdl1.is_on_duty(1) assert sdl1.is_on_duty(4) assert 'sdl2' in clnd.schedules sdl2 = clnd.schedules['sdl2'] assert sdl2.name == 'sdl2' assert not sdl2.is_on_duty(1) assert not sdl2.is_on_duty(4) assert clnd.default_schedule.name == 'on_duty' assert clnd.default_schedule.is_on_duty(1) assert clnd.default_schedule.is_on_duty(4)
def test_timeboard_to_dataframe_reversed_ws(self): clnd = tb.Timeboard(base_unit_freq='D', start='01 Jan 2017', end='12 Jan 2017', layout=[0, 1, 0, 2]) # This is ok. This way an empty df for a void interval is created. df = clnd.to_dataframe(5, 1) assert df.empty
def tb_10_8_6_hours(workshift_ref='start', worktime_source='duration'): shifts = tb.Marker(each='D', at=[{'hours': 2}, {'hours': 8}, {'hours': 18}]) daily = tb.Organizer(marker=shifts, structure=[1, 0]) return tb.Timeboard(base_unit_freq='H', start='01 Oct 2017', end='06 Oct 2017', layout=daily, workshift_ref=workshift_ref, worktime_source=worktime_source)
def test_ws_worktime_in_label(self): clnd = tb.Timeboard(base_unit_freq='D', start='31 Dec 2016', end='12 Jan 2017', layout=[0, 1, 0, 0, 2, 0], worktime_source='labels') ws = Workshift(clnd, 4) assert ws.worktime() == 2 assert ws.worktime(duty='off') == 0 assert ws.worktime(duty='any') == 2
def test_tb_bad_schedule(self): clnd = tb.Timeboard(base_unit_freq='D', start='31 Dec 2016', end='12 Jan 2017', layout=[0, 1, 0, 0, 2, 0]) with pytest.raises(ValueError): clnd.add_schedule(name='sdl', selector='selector') with pytest.raises(TypeError): clnd.add_schedule(name='sdl', selector=lambda x, y: x + y)
def test_ivl_sum_numbers(self): clnd = tb.Timeboard('D', '01 Oct 2017', '10 Oct 2017', layout=[1, 2], default_selector=lambda label: label > 1) ivl = tb.Interval(clnd, (2, 9)) assert ivl._sum_labels() == 8 assert ivl._sum_labels(duty='off') == 4 assert ivl._sum_labels(duty='any') == 12 clnd = tb.Timeboard('D', '01 Oct 2017', '10 Oct 2017', layout=[-2, 1.5], default_selector=lambda label: label > 0) assert clnd()._sum_labels() == 7.5 assert clnd()._sum_labels(duty='off') == -10.0 assert clnd()._sum_labels(duty='any') == -2.5
def test_ivl_sum_strings(self): clnd = tb.Timeboard('D', '01 Oct 2017', '10 Oct 2017', layout=['a', 'b'], default_selector=lambda label: label == 'b') ivl = tb.Interval(clnd, (2, 9)) assert ivl._sum_labels() == 'bbbb' assert ivl._sum_labels(duty='off') == 'aaaa' assert ivl._sum_labels(duty='any') == 'abababab'
def test_tb_constructor_duplicate_amendments(self): with pytest.raises(KeyError): tb.Timeboard(base_unit_freq='D', start='01 Jan 2017', end='12 Jan 2017', layout=[1], amendments={ '02 Jan 2017 12:00': 2, '02 Jan 2017 15:15': 3 })
def test_tb_constructor_trivial(self): clnd = tb.Timeboard(base_unit_freq='D', start='01 Jan 2017', end='12 Jan 2017', layout=[1]) assert clnd._timeline.labels.eq([1] * 12).all() assert clnd.start_time == datetime.datetime(2017, 1, 1, 0, 0, 0) assert clnd.end_time > datetime.datetime(2017, 1, 12, 23, 59, 59) assert clnd.end_time < datetime.datetime(2017, 1, 13, 0, 0, 0) assert clnd.base_unit_freq == 'D'
def test_ivl_total_dur_numbers(self): clnd = tb.Timeboard('D', '01 Oct 2017', '10 Oct 2017', layout=[1, 2], default_selector=lambda label: label > 1) ivl = tb.Interval(clnd, (2, 9)) assert ivl.total_duration() == 4 assert ivl.total_duration(duty='off') == 4 assert ivl.total_duration(duty='any') == 8 clnd = tb.Timeboard('D', '01 Oct 2017', '10 Oct 2017', layout=[-2, 1.5], default_selector=lambda label: label > 0) assert clnd().total_duration() == 5 assert clnd().total_duration(duty='off') == 5 assert clnd().total_duration(duty='any') == 10
def test_tb_schedule_names(self): clnd = tb.Timeboard(base_unit_freq='D', start='31 Dec 2016', end='12 Jan 2017', layout=[0, 1, 0, 0, 2, 0]) clnd.add_schedule(name=1, selector=lambda x: x > 1) assert len(clnd.schedules) == 2 assert clnd.schedules['1'].name == '1' with pytest.raises(KeyError): clnd.add_schedule(name='1', selector=lambda x: x > 2)
def test_interval_find_my_bounds_no_off_duty_in_tb(self): clnd = tb.Timeboard(base_unit_freq='D', start='31 Dec 2016', end='12 Jan 2017', layout=[1]) ivl = Interval(clnd, (1, 2), clnd.default_schedule) _, duty_loc = ivl._get_duty_idx('on', ivl.schedule) assert duty_loc == (1, 2) _, duty_loc = ivl._get_duty_idx('off', ivl.schedule) assert duty_loc == (None, None)
def test_interval_constructor_default_closed_leads_to_void(self): clnd = tb.Timeboard(base_unit_freq='D', start='01 Jan 2017', end='01 Jan 2017', layout=[1]) with pytest.raises(VoidIntervalError): ivl = clnd.get_interval(closed='01') with pytest.raises(VoidIntervalError): ivl = clnd.get_interval(closed='10') with pytest.raises(VoidIntervalError): ivl = clnd.get_interval(closed='00')
def test_ivl_sum_no_such_duty(self): clnd = tb.Timeboard( 'D', '01 Oct 2017', '10 Oct 2017', layout=[1, 2], ) ivl = tb.Interval(clnd, (2, 9)) assert ivl._sum_labels() == 12 assert ivl._sum_labels(duty='off') == 0 assert ivl._sum_labels(duty='any') == 12
def test_tb_constructor_empty_layout_with_default_label(self): clnd = tb.Timeboard(base_unit_freq='D', start='01 Jan 2017', end='12 Jan 2017', layout=[], default_label=100) assert clnd._timeline.labels.eq([100] * 12).all() assert clnd.start_time == datetime.datetime(2017, 1, 1, 0, 0, 0) assert clnd.end_time > datetime.datetime(2017, 1, 12, 23, 59, 59) assert clnd.end_time < datetime.datetime(2017, 1, 13, 0, 0, 0) assert clnd.base_unit_freq == 'D'
def test_ivl_total_dur_no_such_duty(self): clnd = tb.Timeboard( 'D', '01 Oct 2017', '10 Oct 2017', layout=[1, 2], ) ivl = tb.Interval(clnd, (2, 9)) assert ivl.total_duration() == 8 assert ivl.total_duration(duty='off') == 0 assert ivl.total_duration(duty='any') == 8
def test_ivl_worktime_in_labels(self): clnd = tb.Timeboard('D', '01 Oct 2017', '10 Oct 2017', layout=[1, 2], default_selector=lambda label: label > 1, worktime_source='labels') ivl = tb.Interval(clnd, (2, 9)) assert ivl.worktime() == 8 assert ivl.worktime(duty='off') == 4 assert ivl.worktime(duty='any') == 12
def test_ws_worktime_in_labels_strings(self): clnd = tb.Timeboard(base_unit_freq='D', start='31 Dec 2016', end='12 Jan 2017', layout=[0, 1, 0, 0, 'a', 0], worktime_source='labels') ws = Workshift(clnd, 4) with pytest.raises(TypeError): ws.worktime() with pytest.raises(TypeError): ws.worktime(duty='any') assert ws.worktime(duty='off') == 0
def test_ivl_worktime_in_labels_other_schedule(self): clnd = tb.Timeboard('D', '01 Oct 2017', '10 Oct 2017', layout=[1, 2], worktime_source='labels') other_sdl = clnd.add_schedule('other', lambda x: x > 2) ivl = tb.Interval(clnd, (2, 9)) assert ivl.worktime(schedule=other_sdl) == 0 assert ivl.worktime(duty='off', schedule=other_sdl) == 12 assert ivl.worktime(duty='any', schedule=other_sdl) == 12
def tb_281116_020517_8x5(): week5x8 = tb.Organizer(marker='W', structure=[[1, 1, 1, 1, 1, 0, 0]]) amendments = pd.Series(index=pd.date_range(start='01 Jan 2017', end='10 Jan 2017', freq='D'), data=0).to_dict() return tb.Timeboard(base_unit_freq='D', start='28 Nov 2016', end='02 May 2017', layout=week5x8, amendments=amendments)
def test_rollback_off_0(self): org = Organizer(marker='W', structure=[False, [0, 0, 1, 1]]) clnd = tb.Timeboard(base_unit_freq='D', start='31 Dec 2016', end='12 Jan 2017', layout=org) ws = clnd('12 Jan 2017') new_ws_list = [] for duty in ('on', 'off', 'same', 'alt', 'any'): new_ws_list.append(ws.rollback(duty=duty)._loc) assert new_ws_list == [7, 8, 8, 7, 8]
def test_interval_constructor_period_start_aligned_end_inside_ws(self): shifts = tb.Organizer(marker='90T', structure=[0, 1, 0, 2]) clnd = tb.Timeboard( base_unit_freq='T', start='04 Oct 2017', end='04 Oct 2017 23:59', layout=shifts, ) # period (00:00 - 00:59) is inside ws 0 (00:00 - 01:29) # ref time of ws 0 falls into the period ivl = clnd.get_interval('04 Oct 2017 00:00', period='H') assert ivl._loc == (0, 0) # now ref time is end time and ws 0 ref time is outside the period clnd = tb.Timeboard(base_unit_freq='T', start='04 Oct 2017', end='04 Oct 2017 23:59', layout=shifts, workshift_ref='end') with pytest.raises(VoidIntervalError): clnd.get_interval('04 Oct 2017 00:00', period='H')