def test_shift_ast_ymd_with_diff_months_in_leap_and_common_years(self): days_in_common_year_months = FAKE.random_choices( elements=[x for x in range(200)], length=11) days_in_leap_year_months = FAKE.random_choices( elements=[x for x in range(200)], length=12) days_in_common_year_months.append(30) days_in_leap_year_months.append(31) calendar = self.calendar_factory.build( common_year_month_names=FAKE.words(nb=12), days_in_common_year_months=days_in_common_year_months, leap_year_month_names=FAKE.words(nb=13), days_in_leap_year_months=days_in_leap_year_months, leap_year_cycles=[4], leap_year_cycle_start=1, leap_year_cycle_ordinals=[4], special_common_years=(), special_leap_years=(), leap_year_offset=0, ) cd = ConvertibleDate(calendar=calendar) plus_one_year = [[1, DateUnit.YEAR]] sub_one_year = [[-1, DateUnit.YEAR]] with self.session: self.session.add(calendar) self.session.flush() assert cd.shift_ast_ymd((4, 13, 1), plus_one_year) == (5, 12, 1) assert cd.shift_ast_ymd((8, 13, 1), sub_one_year) == (7, 12, 1) assert cd.shift_ast_ymd((0, 13, 31), plus_one_year) == (1, 12, 30) assert cd.shift_ast_ymd((-4, 13, 31), sub_one_year) == (-5, 12, 30)
def test_next_day_for_invalid_frequency(self): calendar = self.calendar_factory.build(days_in_common_year_months=[30], days_in_leap_year_months=[31]) bad_frequency = FAKE.random_int(min=32) cd = ConvertibleDate(calendar=calendar) with pytest.raises(ValueError): cd.next_day(FAKE.pytuple(), bad_frequency)
def test_is_valid_month(self, _): year, month, _ = self.random_ymd() negative_month = FAKE.random_int(min=-9999, max=-1) too_big_month = FAKE.random_int(min=13) assert self.gregorian_cd.is_valid_month(year, month) assert self.gregorian_cd.is_valid_month(year, negative_month) is False assert self.gregorian_cd.is_valid_month(year, too_big_month) is False
def test_convertible_clocks(self): params = { "seconds_in_minute": 60, "minutes_in_hour": 60, "hours_in_day": 24, } with self.session: clock = self.clock_factory.build(**params) convertible_clocks = set( self.clock_factory.build_batch( FAKE.random_int(min=1, max=10), **params, ) ) nonconvertible_clocks = set( self.clock_factory.build_batch( FAKE.random_int(min=1, max=10), **{ "seconds_in_minute": FAKE.random_int(min=61, max=100), "minutes_in_hour": FAKE.random_int(min=61, max=100), "hours_in_day": FAKE.random_int(min=24, max=100), }, ) ) self.session.add_all([*convertible_clocks, *nonconvertible_clocks]) self.session.add(clock) self.session.commit() fetched_clocks = set(clock.convertible_clocks()) assert convertible_clocks.issubset(fetched_clocks) # assert fetched_clocks == convertible_clocks assert fetched_clocks.isdisjoint(nonconvertible_clocks)
def test_ast_ymd_to_ordinal_date_with_no_months(self, _): monthless_calendar, days_in_year = self.random_monthless_calendar() day_of_year = FAKE.random_int(min=1, max=days_in_year) ast_year = FAKE.random_int() monthless_ast_ymd = ast_year, None, day_of_year ordinal_date = ast_year, day_of_year cdt = ConvertibleDate(calendar=monthless_calendar) assert cdt.ast_ymd_to_ordinal_date(monthless_ast_ymd) == ordinal_date
def test_are_valid_hour_labels(self): hours_in_day = FAKE.random_int(min=1, max=100) bad_hour_labels = FAKE.words(nb=hours_in_day + 1, unique=True) ct = self.time_factory.build( clock=self.clock_factory.build(hours_in_day=hours_in_day), ) assert ct.are_valid_hour_labels(bad_hour_labels) is False assert ct.are_valid_hour_labels([]) is True assert self.earth_ct.are_valid_hour_labels(["AM", "PM"]) is True
def test_weekday_start_maximum_constraint(self): week_len = FAKE.random_int(min=1) too_big_weekday_start_calendar = self.calendar_factory.build( weekday_names=FAKE.words(nb=week_len), weekday_start=FAKE.random_int(min=week_len + 1, max=week_len + 99), ) with pytest.raises(IntegrityError), self.session: self.session.add(too_big_weekday_start_calendar) self.session.commit()
def test__sanitize_month_names(self, patch_ss): weekday_names, calendar, patch_ss = self.rand_cal_with_patched_ss( patch_ss) bad_month_names1 = FAKE.random_elements(elements=[1, 2, 3, 4, 5, 6, 7]) bad_month_names2 = FAKE.random_elements(elements=[0, 8, 9, 10, 11, 12]) calendar.common_year_month_names = bad_month_names1 calendar.leap_year_month_names = bad_month_names2 patch_ss.assert_any_call(bad_month_names1) patch_ss.assert_any_call(bad_month_names2)
def random_bad_days_in_months() -> tuple[int, tuple]: num_months = FAKE.random_int(min=1, max=20) length = num_months + FAKE.random_int(min=1) num_elements = length + FAKE.random_int(min=1) bad_days_in_months = FAKE.random_elements( length=length, elements=[days for days in range(1, num_elements)], ) return num_months, bad_days_in_months
def test_extend_od_for_day_interval(self, patch_shift_od): delta = FAKE.random_int(min=-9999) interval = [delta, DateUnit.DAY] cd = ConvertibleDate(calendar=self.calendar_factory.build()) cdt = ConvertibleDateTime(date=cd, time=self.time_factory.build()) od = FAKE.pyfloat() assert cdt.extend_od(od, interval) == od + delta patch_shift_od.assert_not_called()
def test_extend_od_for_non_day_interval(self, patch_shift_od): units = [DateUnit.YEAR, DateUnit.MONTH] units.extend(TimeUnit) interval = [FAKE.random_int(), FAKE.random_element(elements=units)] cd = ConvertibleDate(calendar=self.calendar_factory.build()) cdt = ConvertibleDateTime(date=cd, time=self.time_factory.build()) ordinal_decimal = FAKE.pyfloat() cdt.extend_od(ordinal_decimal, interval) patch_shift_od.assert_called_once_with(ordinal_decimal, [interval])
def test_completed_cycles_for_ce_year(self, _): completed_cycles = FAKE.random_int() start_year = self.make_cycle_start_year(completed_cycles) end_year = self.make_cycle_end_year(completed_cycles) cycle_year = FAKE.random_int(min=start_year, max=end_year) assert self.gregorian_cd.completed_cycles(1) == 0 assert self.gregorian_cd.completed_cycles(400) == 0 assert self.gregorian_cd.completed_cycles(401) == 1 assert ( self.gregorian_cd.completed_cycles(cycle_year) == completed_cycles)
def test___repr__(self): name = FAKE.word() seconds_in_day = FAKE.random_int(min=1) convertible_clock = self.clock_factory.build( name=name, seconds_in_day=seconds_in_day ) assert ( repr(convertible_clock) == f"{name}(Seconds in a Day: {seconds_in_day})" )
def test_era_for_one_year_range(self): """human readable years unless labeled otherwise""" first_era_end_year = FAKE.random_int(min=1, max=9999) second_era_start_year = FAKE.random_int(min=1, max=9999) second_era_end_year = FAKE.random_int(min=1, max=9999) years_in_second_era = ( abs(second_era_end_year - second_era_start_year) + 1) tiny_era_year = FAKE.random_int(min=1, max=9999) final_era_start_year = FAKE.random_int(min=1, max=9999) era_ranges = ( ("-inf", first_era_end_year), (second_era_start_year, second_era_end_year), (tiny_era_year, tiny_era_year), (final_era_start_year, "inf"), ) first_era_ast_year = FAKE.random_int(min=-9999, max=0) second_era_ast_year = FAKE.random_int(min=1, max=years_in_second_era) tiny_era_ast_year = years_in_second_era + 1 final_era_ast_year = FAKE.random_int( min=years_in_second_era + 2, # + tiny era span and off by 1 offset max=years_in_second_era + 2 + FAKE.random_int(min=1), ) eras = ("BCE", "Second", "Tiny", "CE") calendar = self.calendar_factory.build(era_ranges=era_ranges, eras=eras) cdt = ConvertibleDate(calendar=calendar) assert cdt.era(first_era_ast_year) == eras[0] assert cdt.era(second_era_ast_year) == eras[1] assert cdt.era(tiny_era_ast_year) == eras[2] assert cdt.era(final_era_ast_year) == eras[3]
def test_completed_cycles_for_bce_year(self, _): completed_cycles = FAKE.random_int() start_year = self.make_cycle_start_year(completed_cycles, proleptic=True) end_year = self.make_cycle_end_year(completed_cycles, proleptic=True) cycle_year = FAKE.random_int(min=end_year, max=start_year) assert self.gregorian_cd.completed_cycles(0) == 0 assert self.gregorian_cd.completed_cycles(-399) == 0 assert self.gregorian_cd.completed_cycles(-400) == 1 assert ( self.gregorian_cd.completed_cycles(cycle_year) == completed_cycles)
def test_extend_od_raises(self): units = list(DateUnit) units.extend(TimeUnit) interval = [FAKE.random_int(), FAKE.random_element(elements=units)] bad_factor = FAKE.random_int(min=-9999, max=0) cd = ConvertibleDate(calendar=self.calendar_factory.build()) cdt = ConvertibleDateTime(date=cd, time=self.time_factory.build()) ordinal_decimal = FAKE.pyfloat() with pytest.raises(ValueError): cdt.extend_od(ordinal_decimal, interval, bad_factor)
def test_eras_constraint(self): no_eras_calendar = self.calendar_factory.build(eras=()) mismatch_eras_and_ranges_calendar = self.calendar_factory.build( eras=(FAKE.word(), FAKE.word()), era_ranges=(("-inf", "inf"), )) with pytest.raises(IntegrityError), self.session: self.session.add(no_eras_calendar) self.session.commit() with pytest.raises(IntegrityError), self.session: self.session.add(mismatch_eras_and_ranges_calendar) self.session.commit()
def test_ast_to_hr_for_finite_descending_era(self): calendar = self.calendar_factory.build() descending_era_range = ( FAKE.random_int(min=10000, max=20000), FAKE.random_int(min=1), ) calendar.era_ranges.insert(1, descending_era_range) hr_year = self.random_hr_year(descending_era_range) ast_year = self.make_ast_year(descending_era_range, hr_year, 0) cdt = ConvertibleDate(calendar=calendar) assert cdt.ast_to_hr(ast_year) == (hr_year, 1)
def test_ast_ymd_to_od(self, *patches): patch_ordinal_date_to_ordinal = patches[0] patch_ast_ymd_to_ordinal_date = patches[1] fake_ast_ymd = FAKE.random_int(), FAKE.random_int(), FAKE.random_int() fake_ord_date = FAKE.random_int(), FAKE.random_int() patch_ast_ymd_to_ordinal_date.return_value = fake_ord_date cd = ConvertibleDate(calendar=self.calendar_factory.build()) cdt = ConvertibleDateTime(date=cd, time=self.time_factory.build()) assert isinstance(cdt.ast_ymd_to_od(fake_ast_ymd), float) patch_ast_ymd_to_ordinal_date.assert_called_once_with(fake_ast_ymd) patch_ordinal_date_to_ordinal.assert_called_once_with(fake_ord_date)
def test__validates_cycle_ordinals(self, patch_integer_sanitization): leap_year_cycle_ordinals = FAKE.random_elements( elements=[x for x in range(1, FAKE.random_int(min=2))]) patch_integer_sanitization.return_value = leap_year_cycle_ordinals calendar = self.calendar_factory.build( leap_year_cycle_ordinals=leap_year_cycle_ordinals) bad_leap_ords = [x for x in range(FAKE.random_int(min=-99, max=-1), 0)] patch_integer_sanitization.return_value = bad_leap_ords with pytest.raises(AssertionError): calendar.leap_year_cycle_ordinals = bad_leap_ords patch_integer_sanitization.assert_any_call(leap_year_cycle_ordinals) patch_integer_sanitization.assert_any_call(bad_leap_ords)
def test_is_valid_hms(self, *_): big_second = FAKE.random_int(min=60) negative_second = FAKE.random_int(min=-9999, max=-1) big_second_hms = self.py_dt.hour, self.py_dt.minute, big_second negative_second_hms = ( self.py_dt.hour, self.py_dt.minute, negative_second, ) assert not self.earth_ct.is_valid_hms(big_second_hms) assert not self.earth_ct.is_valid_hms(negative_second_hms) assert self.earth_ct.is_valid_hms(self.hms)
def test_shift_hms(self, _): plus_one_sec = [[1, TimeUnit.SECOND]] minus_one_sec = [[-1, TimeUnit.SECOND]] plus_one_min = [[1, TimeUnit.MINUTE]] minus_one_min = [[-1, TimeUnit.MINUTE]] plus_one_hour = [[1, TimeUnit.HOUR]] minus_one_hour = [[-1, TimeUnit.HOUR]] hours = FAKE.random_int(min=-9999) mins = FAKE.random_int(min=-9999) secs = FAKE.random_int(min=-9999) pydelta = datetime.timedelta(hours=hours, minutes=mins, seconds=secs) day_delta = pydelta.days shifted_pydt = self.py_dt + pydelta expected_hms = ( shifted_pydt.hour, shifted_pydt.minute, shifted_pydt.second, ) intervals = [ [hours, TimeUnit.HOUR], [mins, TimeUnit.MINUTE], [secs, TimeUnit.SECOND], ] earth_ct = self.earth_ct assert earth_ct.shift_hms((0, 0, 0), plus_one_sec) == ((0, 0, 1), 0) assert earth_ct.shift_hms((23, 59, 59), plus_one_sec) == ( (0, 0, 0), 1, ) assert earth_ct.shift_hms((0, 0, 1), minus_one_sec) == ((0, 0, 0), 0) assert earth_ct.shift_hms((0, 0, 0), minus_one_sec) == ( (23, 59, 59), -1, ) assert earth_ct.shift_hms((0, 0, 0), plus_one_min) == ((0, 1, 0), 0) assert earth_ct.shift_hms((23, 59, 0), plus_one_min) == ((0, 0, 0), 1) assert earth_ct.shift_hms((0, 1, 0), minus_one_min) == ((0, 0, 0), 0) assert earth_ct.shift_hms((0, 0, 0), minus_one_min) == ( (23, 59, 0), -1, ) assert earth_ct.shift_hms((0, 0, 0), plus_one_hour) == ((1, 0, 0), 0) assert earth_ct.shift_hms((23, 0, 0), plus_one_hour) == ((0, 0, 0), 1) assert earth_ct.shift_hms((1, 0, 0), minus_one_hour) == ((0, 0, 0), 0) assert earth_ct.shift_hms((0, 0, 0), minus_one_hour) == ( (23, 0, 0), -1, ) assert earth_ct.shift_hms(self.hms, intervals) == ( expected_hms, day_delta, )
def test_is_valid_month_with_no_months(self, patch_months_in_year): monthless_calendar, _ = self.random_monthless_calendar() monthless_cd = ConvertibleDate(calendar=monthless_calendar) year = FAKE.random_int(min=-9999) none_is_valid_for_monthless = monthless_cd.is_valid_month(year, None) calendar = self.calendar_factory.build() cd = ConvertibleDate(calendar=calendar) patch_months_in_year.return_value = FAKE.random_int(min=1) none_is_invalid_for_normal_cal = not cd.is_valid_month(year, None) assert none_is_valid_for_monthless assert none_is_invalid_for_normal_cal
def random_hr_year(era_range: tuple) -> int: era_start_hr_year = float(era_range[0]) era_end_hr_year = float(era_range[1]) if era_end_hr_year == float("inf"): return int(era_start_hr_year + FAKE.random_int()) elif era_start_hr_year == float("-inf"): return int(era_end_hr_year + FAKE.random_int()) else: return FAKE.random_int( min=min(era_start_hr_year, era_end_hr_year), max=max(era_start_hr_year, era_end_hr_year), )
def test_next_month_for_invalid_frequency(self, *patches): patch_days_in_common_year, patch_days_in_leap_year = patches days_in_leap_year = FAKE.random_int(min=1) days_in_common_year = FAKE.random_int(min=1) patch_days_in_leap_year.__get__ = lambda *_: days_in_leap_year patch_days_in_common_year.__get__ = lambda *_: days_in_common_year calendar = self.calendar_factory.build() cd = ConvertibleDate(calendar=calendar) bad_frequency = FAKE.random_int(min=10000, max=19999) with pytest.raises(ValueError): cd.next_month(FAKE.pyint(), FAKE.pyint(), bad_frequency)
def test_shift_ast_ymd_can_raise_with_monthelss_calendar(self, _): monthless_calendar, days_in_year = self.random_monthless_calendar() cd = ConvertibleDate(calendar=monthless_calendar) month_interval = [[FAKE.random_int(min=1), DateUnit.MONTH]] day_interval = [[FAKE.random_int(min=1), DateUnit.DAY]] year = FAKE.random_int(min=-9999) day_of_year = FAKE.random_int(min=1, max=days_in_year) ymd = year, None, day_of_year with pytest.raises(ValueError): cd.shift_ast_ymd(ymd, month_interval) with pytest.raises(ValueError): cd.shift_ast_ymd(ymd, day_interval)
def test_next_hms_raises_other_errors(self, _): fake_timeunit = FAKE.random_int() fake_interval = [FAKE.random_int(), fake_timeunit] timeunit = FAKE.random_element(elements=TimeUnit) big_frequency = FAKE.random_int(min=61) fake_float = FAKE.pyfloat(max_value=-1) earth_ct = self.earth_ct with pytest.raises(ValueError): assert earth_ct.next_hms(self.hms, fake_interval) with pytest.raises(ValueError): assert earth_ct.next_hms(self.hms, [big_frequency, timeunit]) with pytest.raises(ValueError): assert earth_ct.next_hms(self.hms, [fake_float, timeunit])
def test_labeled_hour_raises(self): num_hour_labels = FAKE.random_int(min=1, max=20) hours_in_day = FAKE.random_int(min=1, max=100) * num_hour_labels clock = self.clock_factory.create(hours_in_day=hours_in_day) no_hour_label_ct = self.time_factory.build(clock=clock, hour_labels=list()) ct = self.time_factory.build( clock=clock, hour_labels=FAKE.words(nb=num_hour_labels)) with pytest.raises(ValueError): no_hour_label_ct.labeled_hour( FAKE.random_int(min=1, max=hours_in_day - 1)) with pytest.raises(RuntimeError): ct.labeled_hour(hours_in_day + 1)
def test_cycle_index_for_ce_year(self, _): completed_cycles = FAKE.random_int() cycle_index = FAKE.random_int(max=self.cycle_length) ad_start_year = self.make_cycle_start_year(completed_cycles) ad_year = ad_start_year + cycle_index assert self.gregorian_cd.cycle_index(1) == 0 assert self.gregorian_cd.cycle_index(100) == 99 assert self.gregorian_cd.cycle_index(200) == 199 assert self.gregorian_cd.cycle_index(300) == 299 assert self.gregorian_cd.cycle_index(400) == 399 assert self.gregorian_cd.cycle_index(401) == 0 assert (self.gregorian_cd.cycle_index(ad_year, completed_cycles, 1, 1) == cycle_index)
def test_ordinal_date_to_ast_ymd_with_no_months_are_reversible(self, *_): monthless_calendar, days_in_year = self.random_monthless_calendar() day_of_year = FAKE.random_int(min=1, max=days_in_year) ast_year = FAKE.random_int() monthless_ast_ymd = ast_year, None, day_of_year ordinal_date = ast_year, day_of_year cd = ConvertibleDate(calendar=monthless_calendar) assert cd.ordinal_date_to_ast_ymd(ordinal_date) == monthless_ast_ymd assert cd.ast_ymd_to_ordinal_date(monthless_ast_ymd) == ordinal_date assert (cd.ordinal_date_to_ast_ymd( cd.ast_ymd_to_ordinal_date(monthless_ast_ymd)) == monthless_ast_ymd ) assert (cd.ast_ymd_to_ordinal_date( cd.ordinal_date_to_ast_ymd(ordinal_date)) == ordinal_date)