From 35a84ba29c54acc6ce1afab28bb0e9edca07e301 Mon Sep 17 00:00:00 2001 From: Anthony van Winkle Date: Thu, 25 Jul 2024 19:19:17 -0700 Subject: [PATCH 1/8] Option ignore_led_errors for FAST EXP boards --- mpf/config_spec.yaml | 1 + mpf/platforms/fast/fast_exp_board.py | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/mpf/config_spec.yaml b/mpf/config_spec.yaml index 2aedefef2..ae98b7742 100644 --- a/mpf/config_spec.yaml +++ b/mpf/config_spec.yaml @@ -662,6 +662,7 @@ fast_exp_board: led_ports: list|subconfig(fast_led_port)|None led_fade_time: single|ms|0 led_hz: single|float|30 + ignore_led_errors: single|bool|false fast_breakout: port: single|enum(1,2,3)| model: single|str| diff --git a/mpf/platforms/fast/fast_exp_board.py b/mpf/platforms/fast/fast_exp_board.py index 4fc6e31c9..78adffb41 100644 --- a/mpf/platforms/fast/fast_exp_board.py +++ b/mpf/platforms/fast/fast_exp_board.py @@ -179,8 +179,9 @@ def update_leds(self): except Exception as e: self.log.error( f"Error decoding the following message for board {breakout_address} : {msg_header}{msg}") - self.log.debug("Attempted update that caused this error: %s", dirty_leds) - raise e + self.log.info("Attempted update that caused this error: %s", dirty_leds) + if not self.config['ignore_led_errors']: + raise e def set_led_fade(self, rate: int) -> None: """Set LED fade rate in ms.""" From a12184ec5bdec7ebaeb6ba1082c55e1021c26921 Mon Sep 17 00:00:00 2001 From: Anthony van Winkle Date: Sun, 28 Jul 2024 11:46:12 -0700 Subject: [PATCH 2/8] A few latent machine.switch iterations convert to values() or keys() --- mpf/platforms/fast/communicators/net_neuron.py | 2 +- mpf/platforms/virtual.py | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/mpf/platforms/fast/communicators/net_neuron.py b/mpf/platforms/fast/communicators/net_neuron.py index bb16fc1e7..34e1b5ee4 100644 --- a/mpf/platforms/fast/communicators/net_neuron.py +++ b/mpf/platforms/fast/communicators/net_neuron.py @@ -293,7 +293,7 @@ def update_switches_from_hw_data(self): This will silently sync the switch.hw_state. If the logical state changes, it will process it like any switch change. """ - for switch in self.machine.switches: + for switch in self.machine.switches.values(): hw_state = self.platform.hw_switch_data[switch.hw_switch.number] if hw_state != switch.hw_state: diff --git a/mpf/platforms/virtual.py b/mpf/platforms/virtual.py index fc04f8d6f..3ccb869d2 100644 --- a/mpf/platforms/virtual.py +++ b/mpf/platforms/virtual.py @@ -105,16 +105,16 @@ async def get_hw_switch_states(self): if 'virtual_platform_start_active_switches' in self.machine.config: initial_active_switches = [] - for switch in Util.string_to_list(self.machine.config['virtual_platform_start_active_switches']): - if switch not in self.machine.switches: + for switch_name in Util.string_to_list(self.machine.config['virtual_platform_start_active_switches']): + if switch_name not in self.machine.switches.keys(): if " " in switch: self.raise_config_error("MPF no longer supports lists separated by space in " "virtual_platform_start_active_switches. Please separate " - "switches by comma: {}.".format(switch), 1) + "switches by comma: {}.".format(switch_name), 1) else: self.raise_config_error("Switch {} used in virtual_platform_start_active_switches was not " - "found in switches section.".format(switch), 1) - initial_active_switches.append(self.machine.switches[switch].hw_switch.number) + "found in switches section.".format(switch_name), 1) + initial_active_switches.append(self.machine.switches[switch_name].hw_switch.number) for k in self.hw_switches: if k in initial_active_switches: From 73c8cc4f968779040b57c917dcebd2d594ac8be6 Mon Sep 17 00:00:00 2001 From: Alex Lobascio Date: Sun, 25 Aug 2024 01:17:21 -0700 Subject: [PATCH 3/8] add tests around shot_profile block option behavior The tests for the false and default case have the same logic, suggesting that mpf-docs:docs/config/shot_profiles.md is out of date about default block behavior. --- .../shots/config/test_shot_groups.yaml | 4 ++ .../shots/modes/base2/config/base2.yaml | 4 ++ .../shots/modes/mode1/config/mode1.yaml | 19 +++++- mpf/tests/test_Shots.py | 64 ++++++++++++++++++- 4 files changed, 89 insertions(+), 2 deletions(-) diff --git a/mpf/tests/machine_files/shots/config/test_shot_groups.yaml b/mpf/tests/machine_files/shots/config/test_shot_groups.yaml index 4b06f7f00..80767f464 100644 --- a/mpf/tests/machine_files/shots/config/test_shot_groups.yaml +++ b/mpf/tests/machine_files/shots/config/test_shot_groups.yaml @@ -12,6 +12,10 @@ switches: number: switch_4: number: + switch_5: + number: + switch_6: + number: s_rotate_l: number: s_rotate_r: diff --git a/mpf/tests/machine_files/shots/modes/base2/config/base2.yaml b/mpf/tests/machine_files/shots/modes/base2/config/base2.yaml index ddf6ae685..cf82e013d 100644 --- a/mpf/tests/machine_files/shots/modes/base2/config/base2.yaml +++ b/mpf/tests/machine_files/shots/modes/base2/config/base2.yaml @@ -20,6 +20,10 @@ shots: light: tag1 shot_4: switch: switch_1 + shot_5: + switch: switch_5 + shot_6: + switch: switch_6 led_1: switch: switch_1 show_tokens: diff --git a/mpf/tests/machine_files/shots/modes/mode1/config/mode1.yaml b/mpf/tests/machine_files/shots/modes/mode1/config/mode1.yaml index 299ab4a90..80bc73d12 100644 --- a/mpf/tests/machine_files/shots/modes/mode1/config/mode1.yaml +++ b/mpf/tests/machine_files/shots/modes/mode1/config/mode1.yaml @@ -24,6 +24,12 @@ shots: mode1_shot_3: switch: switch_3 profile: mode1_shot_3 + mode1_shot_5: + switch: switch_5 + profile: mode1_shot_5 + mode1_shot_6: + switch: switch_6 + profile: mode1_shot_6 shot_profiles: mode1_shot_2: @@ -32,10 +38,21 @@ shot_profiles: - name: mode1_one - name: mode1_two - name: mode1_three - mode1_shot_3: + mode1_shot_3: # Test block: True show: rainbow2 block: True states: - name: mode1_one - name: mode1_two - name: mode1_three + mode1_shot_5: # Test block: False + show: rainbow2 + block: False + states: + - name: mode1_one + - name: mode1_two + mode1_shot_6: # Test block default + show: rainbow2 + states: + - name: mode1_one + - name: mode1_two diff --git a/mpf/tests/test_Shots.py b/mpf/tests/test_Shots.py index 3103c28a1..bf48e916d 100644 --- a/mpf/tests/test_Shots.py +++ b/mpf/tests/test_Shots.py @@ -29,7 +29,7 @@ def stop_game(self): self.advance_time_and_run() self.assertIsNone(self.machine.game) - def test_block(self): + def test_block_true(self): self.mock_event("playfield_active") self.hit_and_release_switch("switch_3") self.advance_time_and_run(.1) @@ -60,6 +60,68 @@ def test_block(self): self.assertEqual("unlit", self.machine.shots["shot_3"].state_name) self.assertEqual("mode1_two", self.machine.shots["mode1_shot_3"].state_name) + def test_block_false(self): + self.mock_event("playfield_active") + self.hit_and_release_switch("switch_5") + self.advance_time_and_run(.1) + self.assertEventCalled("playfield_active") + + self.start_game() + self.assertEqual("unlit", self.machine.shots["shot_5"].state_name) + + self.hit_and_release_switch("switch_5") + self.advance_time_and_run(.1) + self.assertTrue(self.machine.shots["shot_5"].enabled) + self.assertEqual("lit", self.machine.shots["shot_5"].state_name) + + self.machine.shots["shot_5"].reset() + self.assertEqual("unlit", self.machine.shots["shot_5"].state_name) + + # Start the mode and make sure those shots load + self.start_mode("mode1") + + self.assertTrue(self.machine.shots["shot_5"].enabled) + self.assertTrue(self.machine.shots["mode1_shot_5"].enabled) + self.assertEqual("unlit", self.machine.shots["shot_5"].state_name) + self.assertEqual("mode1_one", self.machine.shots["mode1_shot_5"].state_name) + + self.hit_and_release_switch("switch_5") + self.advance_time_and_run(.1) + + self.assertEqual("lit", self.machine.shots["shot_5"].state_name) + self.assertEqual("mode1_two", self.machine.shots["mode1_shot_5"].state_name) + + def test_block_default(self): #Default behaves as false + self.mock_event("playfield_active") + self.hit_and_release_switch("switch_6") + self.advance_time_and_run(.1) + self.assertEventCalled("playfield_active") + + self.start_game() + self.assertEqual("unlit", self.machine.shots["shot_6"].state_name) + + self.hit_and_release_switch("switch_6") + self.advance_time_and_run(.1) + self.assertTrue(self.machine.shots["shot_6"].enabled) + self.assertEqual("lit", self.machine.shots["shot_6"].state_name) + + self.machine.shots["shot_6"].reset() + self.assertEqual("unlit", self.machine.shots["shot_6"].state_name) + + # Start the mode and make sure those shots load + self.start_mode("mode1") + + self.assertTrue(self.machine.shots["shot_6"].enabled) + self.assertTrue(self.machine.shots["mode1_shot_6"].enabled) + self.assertEqual("unlit", self.machine.shots["shot_6"].state_name) + self.assertEqual("mode1_one", self.machine.shots["mode1_shot_6"].state_name) + + self.hit_and_release_switch("switch_6") + self.advance_time_and_run(.1) + + self.assertEqual("lit", self.machine.shots["shot_6"].state_name) + self.assertEqual("mode1_two", self.machine.shots["mode1_shot_6"].state_name) + def test_loading_shots(self): # Make sure machine-wide shots load & mode-specific shots do not self.assertIn('shot_1', self.machine.shots) From 6ceda4cfe82dc5459b46d4263724985f07dafdd3 Mon Sep 17 00:00:00 2001 From: Alex Lobascio Date: Sun, 25 Aug 2024 01:28:12 -0700 Subject: [PATCH 4/8] refactor shot block tests to use common test structure --- mpf/tests/test_Shots.py | 97 +++++++++++------------------------------ 1 file changed, 25 insertions(+), 72 deletions(-) diff --git a/mpf/tests/test_Shots.py b/mpf/tests/test_Shots.py index bf48e916d..c48360421 100644 --- a/mpf/tests/test_Shots.py +++ b/mpf/tests/test_Shots.py @@ -29,98 +29,51 @@ def stop_game(self): self.advance_time_and_run() self.assertIsNone(self.machine.game) - def test_block_true(self): + def block_test(self, switch, shot, should_block): + high_priority_shot = "mode1_" + shot self.mock_event("playfield_active") - self.hit_and_release_switch("switch_3") + self.hit_and_release_switch(switch) self.advance_time_and_run(.1) self.assertEventCalled("playfield_active") self.start_game() - self.assertEqual("unlit", self.machine.shots["shot_3"].state_name) + self.assertEqual("unlit", self.machine.shots[shot].state_name) - self.hit_and_release_switch("switch_3") + self.hit_and_release_switch(switch) self.advance_time_and_run(.1) - self.assertTrue(self.machine.shots["shot_3"].enabled) - self.assertEqual("lit", self.machine.shots["shot_3"].state_name) + self.assertFalse(self.machine.shots[high_priority_shot].enabled) + self.assertTrue(self.machine.shots[shot].enabled) + self.assertEqual("lit", self.machine.shots[shot].state_name) - self.machine.shots["shot_3"].reset() - self.assertEqual("unlit", self.machine.shots["shot_3"].state_name) + self.machine.shots[shot].reset() + self.assertEqual("unlit", self.machine.shots[shot].state_name) # Start the mode and make sure those shots load self.start_mode("mode1") - self.assertTrue(self.machine.shots["shot_3"].enabled) - self.assertTrue(self.machine.shots["mode1_shot_3"].enabled) - self.assertEqual("unlit", self.machine.shots["shot_3"].state_name) - self.assertEqual("mode1_one", self.machine.shots["mode1_shot_3"].state_name) + self.assertTrue(self.machine.shots[shot].enabled) + self.assertTrue(self.machine.shots[high_priority_shot].enabled) + self.assertEqual("unlit", self.machine.shots[shot].state_name) + self.assertEqual("mode1_one", self.machine.shots[high_priority_shot].state_name) - self.hit_and_release_switch("switch_3") + self.hit_and_release_switch(switch) self.advance_time_and_run(.1) - self.assertEqual("unlit", self.machine.shots["shot_3"].state_name) - self.assertEqual("mode1_two", self.machine.shots["mode1_shot_3"].state_name) - - def test_block_false(self): - self.mock_event("playfield_active") - self.hit_and_release_switch("switch_5") - self.advance_time_and_run(.1) - self.assertEventCalled("playfield_active") + if should_block: + self.assertEqual("unlit", self.machine.shots[shot].state_name) + else: + self.assertEqual("lit", self.machine.shots[shot].state_name) - self.start_game() - self.assertEqual("unlit", self.machine.shots["shot_5"].state_name) + self.assertEqual("mode1_two", self.machine.shots[high_priority_shot].state_name) - self.hit_and_release_switch("switch_5") - self.advance_time_and_run(.1) - self.assertTrue(self.machine.shots["shot_5"].enabled) - self.assertEqual("lit", self.machine.shots["shot_5"].state_name) - - self.machine.shots["shot_5"].reset() - self.assertEqual("unlit", self.machine.shots["shot_5"].state_name) - - # Start the mode and make sure those shots load - self.start_mode("mode1") - - self.assertTrue(self.machine.shots["shot_5"].enabled) - self.assertTrue(self.machine.shots["mode1_shot_5"].enabled) - self.assertEqual("unlit", self.machine.shots["shot_5"].state_name) - self.assertEqual("mode1_one", self.machine.shots["mode1_shot_5"].state_name) - - self.hit_and_release_switch("switch_5") - self.advance_time_and_run(.1) + def test_block_true(self): + self.block_test("switch_3", "shot_3", True) - self.assertEqual("lit", self.machine.shots["shot_5"].state_name) - self.assertEqual("mode1_two", self.machine.shots["mode1_shot_5"].state_name) + def test_block_false(self): + self.block_test("switch_5", "shot_5", False) def test_block_default(self): #Default behaves as false - self.mock_event("playfield_active") - self.hit_and_release_switch("switch_6") - self.advance_time_and_run(.1) - self.assertEventCalled("playfield_active") - - self.start_game() - self.assertEqual("unlit", self.machine.shots["shot_6"].state_name) - - self.hit_and_release_switch("switch_6") - self.advance_time_and_run(.1) - self.assertTrue(self.machine.shots["shot_6"].enabled) - self.assertEqual("lit", self.machine.shots["shot_6"].state_name) - - self.machine.shots["shot_6"].reset() - self.assertEqual("unlit", self.machine.shots["shot_6"].state_name) - - # Start the mode and make sure those shots load - self.start_mode("mode1") - - self.assertTrue(self.machine.shots["shot_6"].enabled) - self.assertTrue(self.machine.shots["mode1_shot_6"].enabled) - self.assertEqual("unlit", self.machine.shots["shot_6"].state_name) - self.assertEqual("mode1_one", self.machine.shots["mode1_shot_6"].state_name) - - self.hit_and_release_switch("switch_6") - self.advance_time_and_run(.1) - - self.assertEqual("lit", self.machine.shots["shot_6"].state_name) - self.assertEqual("mode1_two", self.machine.shots["mode1_shot_6"].state_name) + self.block_test("switch_6", "shot_6", False) def test_loading_shots(self): # Make sure machine-wide shots load & mode-specific shots do not From 615c4be06217d2588dd9b2ec3dd94eac2f9638ef Mon Sep 17 00:00:00 2001 From: Anthony van Winkle Date: Sun, 1 Sep 2024 13:53:07 -0700 Subject: [PATCH 5/8] Correct calculation of bonus score for unset player vars --- mpf/modes/bonus/code/bonus.py | 9 ++++----- .../machine_files/bonus/modes/bonus/config/bonus.yaml | 4 ++++ mpf/tests/test_Bonus.py | 10 ++++++++++ 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/mpf/modes/bonus/code/bonus.py b/mpf/modes/bonus/code/bonus.py index 99ec5c270..3fe1f09a2 100644 --- a/mpf/modes/bonus/code/bonus.py +++ b/mpf/modes/bonus/code/bonus.py @@ -91,11 +91,10 @@ def _bonus_next_item(self): self._subtotal() return - # Calling player.vars.get() instead of player.get() bypasses the - # auto-fill zero and will throw if there is no player variable. - # The fallback value of 1 is used for bonus entries that don't use - # a player score, which are multiplied by one to get the bonus. - hits = self.player.vars.get(entry['player_score_entry'], 1) + # If a player_score_entry is provided, use player getattr to get a + # fallback value of zero if the variable is not set. Otherwise + # use 1 as the multiplier for non-player-score bonuses. + hits = self.player[entry['player_score_entry']] if entry['player_score_entry'] else 1 score = entry['score'].evaluate([]) * hits if (not score and entry['skip_if_zero']) or (score < 0 and entry['skip_if_negative']): diff --git a/mpf/tests/machine_files/bonus/modes/bonus/config/bonus.yaml b/mpf/tests/machine_files/bonus/modes/bonus/config/bonus.yaml index 7d9dcc207..6ee33d372 100644 --- a/mpf/tests/machine_files/bonus/modes/bonus/config/bonus.yaml +++ b/mpf/tests/machine_files/bonus/modes/bonus/config/bonus.yaml @@ -12,3 +12,7 @@ mode_settings: score: 5000 player_score_entry: modes reset_player_score_entry: False + - event: bonus_undefined_var + score: 5000 + skip_if_zero: false + player_score_entry: undefined_var diff --git a/mpf/tests/test_Bonus.py b/mpf/tests/test_Bonus.py index 098df096c..64234f340 100644 --- a/mpf/tests/test_Bonus.py +++ b/mpf/tests/test_Bonus.py @@ -38,6 +38,7 @@ def test_slam_tilt_in_service(self): def testBonus(self): self.mock_event("bonus_ramps") self.mock_event("bonus_modes") + self.mock_event("bonus_undefined_var") self.mock_event("bonus_subtotal") self.mock_event("bonus_multiplier") self.mock_event("bonus_total") @@ -78,6 +79,8 @@ def testBonus(self): self.assertEqual(3, self._last_event_kwargs["bonus_ramps"]["hits"]) self.assertEqual(10000, self._last_event_kwargs["bonus_modes"]["score"]) self.assertEqual(2, self._last_event_kwargs["bonus_modes"]["hits"]) + self.assertEqual(0, self._last_event_kwargs["bonus_undefined_var"]["score"]) + self.assertEqual(0, self._last_event_kwargs["bonus_undefined_var"]["hits"]) self.assertEqual(13000, self._last_event_kwargs["bonus_subtotal"]["score"]) self.assertEqual(5, self._last_event_kwargs["bonus_multiplier"]["multiplier"]) self.assertEqual(65000, self._last_event_kwargs["bonus_total"]["score"]) @@ -128,6 +131,7 @@ def testBonus(self): self.mock_event("bonus_start") self.mock_event("bonus_ramps") self.mock_event("bonus_modes") + self.mock_event("bonus_undefined_var") self.mock_event("bonus_subtotal") self.mock_event("bonus_multiplier") self.mock_event("bonus_total") @@ -157,6 +161,12 @@ def testBonus(self): self.assertEventNotCalled('bonus_multiplier') self.assertEventNotCalled('bonus_total') + self.advance_time_and_run(.5) + self.assertEventCalled('bonus_undefined_var') + self.assertEventNotCalled('bonus_subtotal') + self.assertEventNotCalled('bonus_multiplier') + self.assertEventNotCalled('bonus_total') + self.advance_time_and_run(.5) self.assertEventCalled('bonus_subtotal') self.assertEventNotCalled('bonus_multiplier') From 2db6840060bb1c34a343dbb6e09f88a4c38b1af6 Mon Sep 17 00:00:00 2001 From: Anthony van Winkle Date: Sun, 1 Sep 2024 13:59:27 -0700 Subject: [PATCH 6/8] Include tests for static bonuses --- .../bonus/modes/bonus/config/bonus.yaml | 2 ++ mpf/tests/test_Bonus.py | 22 ++++++++++++++----- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/mpf/tests/machine_files/bonus/modes/bonus/config/bonus.yaml b/mpf/tests/machine_files/bonus/modes/bonus/config/bonus.yaml index 6ee33d372..7c92e475e 100644 --- a/mpf/tests/machine_files/bonus/modes/bonus/config/bonus.yaml +++ b/mpf/tests/machine_files/bonus/modes/bonus/config/bonus.yaml @@ -16,3 +16,5 @@ mode_settings: score: 5000 skip_if_zero: false player_score_entry: undefined_var + - event: bonus_static + score: 2000 diff --git a/mpf/tests/test_Bonus.py b/mpf/tests/test_Bonus.py index 64234f340..5a9aba7ba 100644 --- a/mpf/tests/test_Bonus.py +++ b/mpf/tests/test_Bonus.py @@ -39,6 +39,7 @@ def testBonus(self): self.mock_event("bonus_ramps") self.mock_event("bonus_modes") self.mock_event("bonus_undefined_var") + self.mock_event("bonus_static") self.mock_event("bonus_subtotal") self.mock_event("bonus_multiplier") self.mock_event("bonus_total") @@ -81,10 +82,12 @@ def testBonus(self): self.assertEqual(2, self._last_event_kwargs["bonus_modes"]["hits"]) self.assertEqual(0, self._last_event_kwargs["bonus_undefined_var"]["score"]) self.assertEqual(0, self._last_event_kwargs["bonus_undefined_var"]["hits"]) - self.assertEqual(13000, self._last_event_kwargs["bonus_subtotal"]["score"]) + self.assertEqual(2000, self._last_event_kwargs["bonus_static"]["score"]) + self.assertEqual(1, self._last_event_kwargs["bonus_static"]["hits"]) + self.assertEqual(15000, self._last_event_kwargs["bonus_subtotal"]["score"]) self.assertEqual(5, self._last_event_kwargs["bonus_multiplier"]["multiplier"]) - self.assertEqual(65000, self._last_event_kwargs["bonus_total"]["score"]) - self.assertEqual(66337, self.machine.game.player.score) + self.assertEqual(75000, self._last_event_kwargs["bonus_total"]["score"]) + self.assertEqual(76337, self.machine.game.player.score) # check resets self.assertEqual(0, self.machine.game.player.ramps) @@ -105,10 +108,10 @@ def testBonus(self): self.assertEqual(0, self._last_event_kwargs["bonus_ramps"]["hits"]) self.assertEqual(10000, self._last_event_kwargs["bonus_modes"]["score"]) self.assertEqual(2, self._last_event_kwargs["bonus_modes"]["hits"]) - self.assertEqual(10000, self._last_event_kwargs["bonus_subtotal"]["score"]) + self.assertEqual(12000, self._last_event_kwargs["bonus_subtotal"]["score"]) self.assertEqual(5, self._last_event_kwargs["bonus_multiplier"]["multiplier"]) - self.assertEqual(50000, self._last_event_kwargs["bonus_total"]["score"]) - self.assertEqual(116337, self.machine.game.player.score) + self.assertEqual(60000, self._last_event_kwargs["bonus_total"]["score"]) + self.assertEqual(136337, self.machine.game.player.score) # multiplier should stay the same self.assertEqual(0, self.machine.game.player.ramps) @@ -132,6 +135,7 @@ def testBonus(self): self.mock_event("bonus_ramps") self.mock_event("bonus_modes") self.mock_event("bonus_undefined_var") + self.mock_event("bonus_static") self.mock_event("bonus_subtotal") self.mock_event("bonus_multiplier") self.mock_event("bonus_total") @@ -167,6 +171,12 @@ def testBonus(self): self.assertEventNotCalled('bonus_multiplier') self.assertEventNotCalled('bonus_total') + self.advance_time_and_run(.5) + self.assertEventCalled('bonus_static') + self.assertEventNotCalled('bonus_subtotal') + self.assertEventNotCalled('bonus_multiplier') + self.assertEventNotCalled('bonus_total') + self.advance_time_and_run(.5) self.assertEventCalled('bonus_subtotal') self.assertEventNotCalled('bonus_multiplier') From 6bca1af5c0cf4461c02f46641a9b9f51afcf5305 Mon Sep 17 00:00:00 2001 From: Anthony van Winkle Date: Sun, 1 Sep 2024 14:09:08 -0700 Subject: [PATCH 7/8] Fix misnamed variable in virtual switch --- mpf/platforms/virtual.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mpf/platforms/virtual.py b/mpf/platforms/virtual.py index 3ccb869d2..7d8164a69 100644 --- a/mpf/platforms/virtual.py +++ b/mpf/platforms/virtual.py @@ -107,7 +107,7 @@ async def get_hw_switch_states(self): initial_active_switches = [] for switch_name in Util.string_to_list(self.machine.config['virtual_platform_start_active_switches']): if switch_name not in self.machine.switches.keys(): - if " " in switch: + if " " in switch_name: self.raise_config_error("MPF no longer supports lists separated by space in " "virtual_platform_start_active_switches. Please separate " "switches by comma: {}.".format(switch_name), 1) From f73e649ba6dedee7115e7465369b5a6acb2b25d4 Mon Sep 17 00:00:00 2001 From: Anthony van Winkle Date: Sun, 1 Sep 2024 14:23:58 -0700 Subject: [PATCH 8/8] Linter fixes --- mpf/modes/high_score/code/high_score.py | 3 ++- mpf/platforms/fast/fast_exp_board.py | 3 ++- mpf/plugins/platform_integration_test_runner.py | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/mpf/modes/high_score/code/high_score.py b/mpf/modes/high_score/code/high_score.py index 63ab9bdcb..23aa3f7bc 100644 --- a/mpf/modes/high_score/code/high_score.py +++ b/mpf/modes/high_score/code/high_score.py @@ -196,7 +196,8 @@ async def _run(self) -> None: # ask player for initials if we do not know them if not player.initials: try: - player.initials = await self._ask_player_for_initials(player, award_names[i], value, category_name) + player.initials = await self._ask_player_for_initials(player, award_names[i], + value, category_name) except asyncio.TimeoutError: del new_list[i] # no entry when the player missed the timeout diff --git a/mpf/platforms/fast/fast_exp_board.py b/mpf/platforms/fast/fast_exp_board.py index 78adffb41..98eab1619 100644 --- a/mpf/platforms/fast/fast_exp_board.py +++ b/mpf/platforms/fast/fast_exp_board.py @@ -2,6 +2,7 @@ import asyncio from base64 import b16decode +from binascii import Error as binasciiError from importlib import import_module from packaging import version @@ -176,7 +177,7 @@ def update_leds(self): try: self.communicator.send_bytes(b16decode(f'{msg_header}{msg}'), log_msg) - except Exception as e: + except binasciiError as e: self.log.error( f"Error decoding the following message for board {breakout_address} : {msg_header}{msg}") self.log.info("Attempted update that caused this error: %s", dirty_leds) diff --git a/mpf/plugins/platform_integration_test_runner.py b/mpf/plugins/platform_integration_test_runner.py index 2155d302e..bee98468c 100644 --- a/mpf/plugins/platform_integration_test_runner.py +++ b/mpf/plugins/platform_integration_test_runner.py @@ -227,7 +227,7 @@ async def move_ball_from_drain_to_trough(self, **kwargs): drain_switches = self.machine.ball_devices.items_tagged('drain')[0].config.get('ball_switches') self.info_log("Found drain switches: %s of type %s", drain_switches, type(drain_switches)) # If there's only one drain switch it might be a single value, rather than a list - drain_switch = drain_switches if type(drain_switches) is str else drain_switches[-1] + drain_switch = drain_switches if isinstance(drain_switches, str) else drain_switches[-1] self.info_log("Setting drain switch '%s' to zero", drain_switch) self.set_switch_sync(drain_switch, 0) await asyncio.sleep(0.25)