diff --git a/rota_generator/shifts.py b/rota_generator/shifts.py index 382d377..a8c34d4 100644 --- a/rota_generator/shifts.py +++ b/rota_generator/shifts.py @@ -470,6 +470,34 @@ class RotaBuilder(object): setattr(self.constraint_options_model, constraint, value) + @property + def constraint_options(self): + """Backward-compat dict-like proxy for the typed + `constraint_options_model`. This keeps older code/tests working + while the canonical storage is `constraint_options_model`. + """ + + class _Proxy: + def __init__(self, model): + self._m = model + + def __getitem__(self, key): + return getattr(self._m, key) + + def __setitem__(self, key, value): + setattr(self._m, key, value) + + def get(self, key, default=None): + return getattr(self._m, key, default) + + def items(self): + return self._m.model_dump().items() + + def __contains__(self, key): + return hasattr(self._m, key) + + return _Proxy(self.constraint_options_model) + def set_rota_dates(self, start_date: datetime.date, weeks_to_rota: int): self.weeks_to_rota = weeks_to_rota @@ -4663,7 +4691,7 @@ class RotaBuilder(object):

Rota settings

-        {json.dumps({k: _pydantic_to_dict(v) for k, v in self.constraint_options.items()}, indent=4)}
+        {json.dumps({k: _pydantic_to_dict(v) for k, v in self.constraint_options_model.model_dump().items()}, indent=4)}
         
diff --git a/test/rota_constraints/test_summed_shift_grade_constraints.py b/test/rota_constraints/test_summed_shift_grade_constraints.py index 5c847b4..5fd5274 100644 --- a/test/rota_constraints/test_summed_shift_grade_constraints.py +++ b/test/rota_constraints/test_summed_shift_grade_constraints.py @@ -47,7 +47,7 @@ def test_summed_shift_grade_constraints(): ) # Add summed shift grade constraints - Rota.constraint_options["min_summed_grade_by_shifts_per_day"].append( + Rota.constraint_options_model.min_summed_grade_by_shifts_per_day.append( MinSummedGradeByShiftsPerDayConstraint( shifts=["a", "b"], min_grade_sum=4, @@ -78,7 +78,7 @@ def test_summed_shift_grade_constraints(): for summed_grade in summed_grades: assert summed_grade >= 4, f"Summed grade {summed_grade} is less than 4" - Rota.constraint_options["min_summed_grade_by_shifts_per_day"] = [ + Rota.constraint_options_model.min_summed_grade_by_shifts_per_day = [ MinSummedGradeByShiftsPerDayConstraint( shifts=["a", "b"], min_grade_sum=5, diff --git a/test/test_limit_constraints.py b/test/test_limit_constraints.py index f4f5633..9cadc21 100644 --- a/test/test_limit_constraints.py +++ b/test/test_limit_constraints.py @@ -257,7 +257,7 @@ def test_constraint_require_remote_site_presence_week2(limit_constraint_rota): Rota = limit_constraint_rota Rota.constraint_options["minimise_shift_diffs"] = False Rota.constraint_options["balance_shifts_quadratic"] = False - Rota.constraint_options["balance_shift"] = False + Rota.constraint_options["balance_shifts"] = False Rota.constraint_options["balance_nights_across_sites"] = True Rota.shifts = [] Rota.add_shifts( diff --git a/test/test_remote.py b/test/test_remote.py index f3f52d5..6076e1f 100644 --- a/test/test_remote.py +++ b/test/test_remote.py @@ -51,7 +51,7 @@ class TestRemoteRotas: Rota.constraint_options["balance_blocks"] = False Rota.constraint_options["balance_weekends"] = False Rota.constraint_options["balance_nights"] = False - Rota.constraint_options["minimse_shift_diffs"] = False + Rota.constraint_options["minimise_shift_diffs"] = False Rota.add_workers( [Worker( @@ -111,7 +111,7 @@ class TestRemoteRotas: Rota.constraint_options["balance_blocks"] = False Rota.constraint_options["balance_weekends"] = False Rota.constraint_options["balance_nights"] = False - Rota.constraint_options["minimse_shift_diffs"] = False + Rota.constraint_options["minimise_shift_diffs"] = False Rota.add_workers( [Worker( diff --git a/test/test_rota.py b/test/test_rota.py index a954000..bc3cd51 100644 --- a/test/test_rota.py +++ b/test/test_rota.py @@ -19,16 +19,16 @@ def demo_rota(): weeks_to_rota=weeks_to_rota, balance_offset_modifier=1, ) - Rota.constraint_options["max_shifts_per_week"] = 5 - Rota.constraint_options["max_shifts_per_month"] = 31 - Rota.constraint_options["constrain_time_off_after_nights"] = False - Rota.constraint_options["balance_nights_across_site"] = False - Rota.constraint_options["balance_shifts_quadratic"] = True - Rota.constraint_options["balance_shifts_over_workers"] = True - Rota.constraint_options["balance_nights"] = False - Rota.constraint_options["minimise_shift_diffs"] = False - Rota.constraint_options["balance_blocks"] = False - Rota.constraint_options["balance_bank_holidays"] = False + Rota.constraint_options_model.max_shifts_per_week = 5 + Rota.constraint_options_model.max_shifts_per_month = 31 + Rota.constraint_options_model.constrain_time_off_after_nights = False + Rota.constraint_options_model.balance_nights_across_sites = False + Rota.constraint_options_model.balance_shifts_quadratic = True + Rota.constraint_options_model.balance_shifts_over_workers = True + Rota.constraint_options_model.balance_nights = False + Rota.constraint_options_model.minimise_shift_diffs = False + Rota.constraint_options_model.balance_blocks = False + Rota.constraint_options_model.balance_bank_holidays = False # Add a few workers workers = [ diff --git a/test/test_rota_clear.py b/test/test_rota_clear.py index 90b7057..f18e7e9 100644 --- a/test/test_rota_clear.py +++ b/test/test_rota_clear.py @@ -34,7 +34,7 @@ def demo_rota_clear(): weeks_to_rota=weeks_to_rota, balance_offset_modifier=1, ) - Rota.constraint_options["max_shifts_per_month"] = 20 + Rota.constraint_options_model.max_shifts_per_month = 20 workers = [ Worker(name="worker1", site="group1", grade=1), diff --git a/test/test_rota_nights.py b/test/test_rota_nights.py index ee9ceec..d1b71ed 100644 --- a/test/test_rota_nights.py +++ b/test/test_rota_nights.py @@ -3,7 +3,7 @@ import pytest from pytest import approx from rota_generator.shifts import PostShiftConstraint, RotaBuilder, SingleShift, days from rota_generator.workers import Worker -from web.rota.shifts import PreShiftConstraint +from rota_generator.shifts import PreShiftConstraint @pytest.fixture def demo_rota_nights(): @@ -16,17 +16,17 @@ def demo_rota_nights(): balance_offset_modifier=1, ) - Rota.constraint_options["max_shifts_per_week"] = 5 - Rota.constraint_options["max_shifts_per_month"] = 31 - Rota.constraint_options["limit_to_1_st2_on_nights"] = False - Rota.constraint_options["constrain_time_off_after_nights"] = False - Rota.constraint_options["balance_nights_across_site"] = False - Rota.constraint_options["balance_shifts"] = True - Rota.constraint_options["balance_shifts_over_workers"] = True - Rota.constraint_options["balance_nights"] = False - Rota.constraint_options["minimise_shift_diffs"] = False - Rota.constraint_options["balance_blocks"] = False - Rota.constraint_options["max_night_frequency"] = 0 + Rota.constraint_options_model.max_shifts_per_week = 5 + Rota.constraint_options_model.max_shifts_per_month = 31 + # legacy option `limit_to_1_st2_on_nights` removed; test omits it + Rota.constraint_options_model.constrain_time_off_after_nights = False + Rota.constraint_options_model.balance_nights_across_sites = False + Rota.constraint_options_model.balance_shifts = True + Rota.constraint_options_model.balance_shifts_over_workers = True + Rota.constraint_options_model.balance_nights = False + Rota.constraint_options_model.minimise_shift_diffs = False + Rota.constraint_options_model.balance_blocks = False + Rota.constraint_options_model.max_night_frequency = 0 # Add workers workers = [ diff --git a/test/test_shift_constraints.py b/test/test_shift_constraints.py index 5593e23..1da3fd1 100644 --- a/test/test_shift_constraints.py +++ b/test/test_shift_constraints.py @@ -36,36 +36,36 @@ def rota_3workers(rota_2workers): return Rota3 def test_max_shifts(rota_2workers): - rota_2workers.constraint_options["max_shifts_per_month"] = 14 + rota_2workers.constraint_options_model.max_shifts_per_month = 14 rota_2workers.build_and_solve() assert rota_2workers.results.solver.status == "ok" assert rota_2workers.results.solver.termination_condition == "optimal" def test_max_shifts_fail(rota_2workers): - rota_2workers.constraint_options["max_shifts_per_month"] = 13 + rota_2workers.constraint_options_model.max_shifts_per_month = 13 rota_2workers.build_and_solve() assert rota_2workers.results.solver.status in ("warning", "error") assert rota_2workers.results.solver.termination_condition == "infeasible" def test_max_shifts_extra_worker(rota_3workers): - rota_3workers.constraint_options["max_shifts_per_month"] = 12 + rota_3workers.constraint_options_model.max_shifts_per_month = 12 rota_3workers.build_and_solve() assert rota_3workers.results.solver.status == "ok" assert rota_3workers.results.solver.termination_condition == "optimal" def test_max_shifts_per_week_fail(rota_2workers): - rota_2workers.constraint_options["max_shifts_per_week"] = 3 + rota_2workers.constraint_options_model.max_shifts_per_week = 3 rota_2workers.build_and_solve() assert rota_2workers.results.solver.status in ("warning", "error") assert rota_2workers.results.solver.termination_condition == "infeasible" def test_max_shifts_per_week_pass(rota_2workers): - rota_2workers.constraint_options["max_shifts_per_month"] = 14 - rota_2workers.constraint_options["max_shifts_per_week"] = 4 + rota_2workers.constraint_options_model.max_shifts_per_month = 14 + rota_2workers.constraint_options_model.max_shifts_per_week = 4 rota_2workers.build_and_solve() assert rota_2workers.results.solver.status == "ok" def test_max_shifts_per_week_extra_worker_pass(rota_3workers): - rota_3workers.constraint_options["max_shifts_per_week"] = 3 + rota_3workers.constraint_options_model.max_shifts_per_week = 3 rota_3workers.build_and_solve() assert rota_3workers.results.solver.status == "ok" \ No newline at end of file diff --git a/test/test_weekend_padding.py b/test/test_weekend_padding.py index 95e2800..572fbde 100644 --- a/test/test_weekend_padding.py +++ b/test/test_weekend_padding.py @@ -20,7 +20,7 @@ class TestDemoRota: start_date, weeks_to_rota=weeks_to_rota, ) - self.Rota.constraint_options["balance_weekends"] = True + self.Rota.constraint_options_model.balance_weekends = True # Add a few workers worker1 = Worker(name="worker1", site="group1", grade=1) @@ -77,7 +77,7 @@ class TestDemoRota: start_date, weeks_to_rota=weeks_to_rota, ) - self.Rota.constraint_options["balance_weekends"] = True + self.Rota.constraint_options_model.balance_weekends = True # Add a few workers worker1 = Worker(name="worker1", site="group1", grade=1) @@ -136,7 +136,7 @@ class TestDemoRota: start_date, weeks_to_rota=weeks_to_rota, ) - self.Rota.constraint_options["prevent_monday_and_tuesday_after_full_weekends"] = ["group1",] + self.Rota.constraint_options_model.prevent_monday_and_tuesday_after_full_weekends = ["group1",] # Add a few workers worker1 = Worker(name="worker1", site="group1", grade=1) @@ -182,7 +182,7 @@ class TestDemoRota: start_date, weeks_to_rota=weeks_to_rota, ) - self.Rota.constraint_options["prevent_monday_and_tuesday_after_full_weekends"] = ["group1",] + self.Rota.constraint_options_model.prevent_monday_and_tuesday_after_full_weekends = ["group1",] # Add a few workers worker1 = Worker(name="worker1", site="group1", grade=1) @@ -221,7 +221,7 @@ class TestDemoRota: start_date, weeks_to_rota=weeks_to_rota, ) - self.Rota.constraint_options["prevent_monday_after_full_weekends"] = ["group1",] + self.Rota.constraint_options_model.prevent_monday_after_full_weekends = ["group1",] # Add a few workers worker1 = Worker(name="worker1", site="group1", grade=1) @@ -271,7 +271,7 @@ class TestDemoRota: start_date, weeks_to_rota=weeks_to_rota, ) - self.Rota.constraint_options["prevent_monday_after_full_weekends"] = ["group1",] + self.Rota.constraint_options_model.prevent_monday_after_full_weekends = ["group1",] # Add a few workers worker1 = Worker(name="worker1", site="group1", grade=1) @@ -312,7 +312,7 @@ class TestDemoRota: start_date, weeks_to_rota=weeks_to_rota, ) - self.Rota.constraint_options["prevent_monday_after_full_weekends"] = ["group1",] + self.Rota.constraint_options_model.prevent_monday_after_full_weekends = ["group1",] # Add a few workers worker1 = Worker(name="worker1", site="group1", grade=1) diff --git a/test/test_worker_requests.py b/test/test_worker_requests.py index 38b96e3..b4354d6 100644 --- a/test/test_worker_requests.py +++ b/test/test_worker_requests.py @@ -224,7 +224,7 @@ class TestWorkerRequests: """_summary_""" Rota = generate_basic_rota() - Rota.constraint_options["balance_bank_holidays"] = False + Rota.constraint_options_model.balance_bank_holidays = False Rota.add_worker( Worker( @@ -311,7 +311,7 @@ class TestWorkerRequests: def test_work_requests(self): """_summary_""" Rota = generate_basic_rota() - Rota.constraint_options["balance_bank_holidays"] = False + Rota.constraint_options_model.balance_bank_holidays = False Rota.add_workers( [Worker( @@ -362,7 +362,7 @@ class TestWorkerRequests: def test_work_requests_invalid(self): """_summary_""" Rota = generate_basic_rota() - Rota.constraint_options["balance_bank_holidays"] = False + Rota.constraint_options_model.balance_bank_holidays = False Rota.add_worker( Worker( @@ -433,7 +433,7 @@ class TestWorkerRequests: def test_work_requests_generic(self): """_summary_""" Rota = generate_basic_rota() - Rota.constraint_options["balance_bank_holidays"] = False + Rota.constraint_options_model.balance_bank_holidays = False Rota.add_workers( [Worker( @@ -484,7 +484,7 @@ class TestWorkerRequests: def test_work_requests_generic2(self): """_summary_""" Rota = generate_basic_rota() - Rota.constraint_options["balance_bank_holidays"] = False + Rota.constraint_options_model.balance_bank_holidays = False Rota.add_workers( [Worker( diff --git a/test/test_workers.py b/test/test_workers.py index d8b31d3..d7029a2 100644 --- a/test/test_workers.py +++ b/test/test_workers.py @@ -4,7 +4,7 @@ from rota_generator.shifts import InvalidShift, MaxShiftsPerWeekConstraint, NoWo import datetime from rota_generator.workers import NonWorkingDays, NotAvailableToWork, Worker, generate_not_available_to_works from rota_generator.workers import WorkRequests -from web.rota.shifts import PreShiftConstraint +from rota_generator.shifts import PreShiftConstraint def generate_basic_rota( weeks_to_rota=10, workers=0, start_date=datetime.date(2022, 3, 7) @@ -357,7 +357,7 @@ def test_worker_pairs(): ] ) - Rota.constraint_options["hard_constrain_pair_separation"] = True + Rota.constraint_options_model.hard_constrain_pair_separation = True Rota.build_and_solve()