Skip to content

Commit

Permalink
Merge branch 'dev' into lights_platform
Browse files Browse the repository at this point in the history
  • Loading branch information
jabdoa2 committed Mar 5, 2017
2 parents 5426788 + 793fa0f commit 9ce1131
Show file tree
Hide file tree
Showing 14 changed files with 133 additions and 26 deletions.
3 changes: 0 additions & 3 deletions mpf/config_players/queue_relay_player.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,6 @@ class QueueRelayPlayer(ConfigPlayer):
show_section = None
device_collection = None

def _reset_instance_dict(self, context):
self.instances[context][self.config_file_section] = []

def play(self, settings, context, priority=0, **kwargs):
"""Block queue event."""
try:
Expand Down
15 changes: 15 additions & 0 deletions mpf/core/events.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import asyncio
from functools import partial
from unittest.mock import MagicMock

from mpf.core.mpf_controller import MpfController

Expand Down Expand Up @@ -113,6 +114,8 @@ def add_handler(self, event, handler, priority=1, **kwargs):

# An event 'handler' in our case is a tuple with 4 elements:
# the handler method, priority, dict of kwargs, & uuid key
if hasattr(handler, "relative_priority") and not isinstance(handler, MagicMock):
priority += handler.relative_priority

self.registered_handlers[event].append(RegisteredHandler(handler, priority, kwargs, key, condition))

Expand Down Expand Up @@ -644,3 +647,15 @@ def clear(self):
def is_empty(self):
"""Return true if unlocked."""
return not self.waiter


def event_handler(relative_priority):

"""Decorator for event handlers."""

def decorator(func):
"""Decorate a function with relative priority."""
func.relative_priority = relative_priority
return func

return decorator
13 changes: 4 additions & 9 deletions mpf/core/mode.py
Original file line number Diff line number Diff line change
Expand Up @@ -205,8 +205,7 @@ def start(self, mode_priority=None, callback=None, **kwargs):
# start and stop on the same event, the one will stop before
# the other starts
self.add_mode_event_handler(event=event, handler=self.stop,
priority=self.priority + 1 +
self.config['mode']['stop_priority'])
priority=self.config['mode']['stop_priority'] + 1)

self.start_callback = callback

Expand Down Expand Up @@ -294,10 +293,6 @@ def stop(self, callback=None, **kwargs):
self._kill_timers()
self.delay.clear()

# self.machine.events.remove_handler(self.stop)
# todo is this ok here? Or should we only remove ones that we know this
# mode added?

self.machine.events.post_queue(event='mode_' + self.name + '_stopping',
callback=self._stopped)
'''event: mode_(name)_stopping
Expand Down Expand Up @@ -465,7 +460,7 @@ def _setup_device_control_events(self):
self.add_mode_event_handler(
event=event,
handler=self._control_event_handler,
priority=self.priority + 2 + int(priority),
priority=int(priority) + 2,
callback=method,
ms_delay=delay)

Expand All @@ -490,7 +485,7 @@ def _control_event_handler(self, callback, ms_delay=0, **kwargs):
else:
callback(mode=self)

def add_mode_event_handler(self, event, handler, priority=1, **kwargs):
def add_mode_event_handler(self, event, handler, priority=0, **kwargs):
"""Register an event handler which is automatically removed when this mode stops.
This method is similar to the Event Manager's add_handler() method,
Expand Down Expand Up @@ -522,7 +517,7 @@ def add_mode_event_handler(self, event, handler, priority=1, **kwargs):
Note that if you do add a handler via this method and then remove it
manually, that's ok too.
"""
key = self.machine.events.add_handler(event, handler, priority, mode=self, **kwargs)
key = self.machine.events.add_handler(event, handler, self.priority + priority, mode=self, **kwargs)

self.event_handlers.add(key)

Expand Down
2 changes: 1 addition & 1 deletion mpf/core/mode_device.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ def add_control_events_in_mode(self, mode):
"""
if "enable_events" in self.config and not self.config['enable_events']:
mode.add_mode_event_handler("mode_{}_started".format(mode.name),
self.enable)
self.enable, priority=100)

def remove_control_events_in_mode(self):
"""Remove control events."""
Expand Down
13 changes: 10 additions & 3 deletions mpf/devices/multiball.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from mpf.core.delays import DelayManager
from mpf.core.device_monitor import DeviceMonitor
from mpf.core.events import event_handler
from mpf.core.mode_device import ModeDevice
from mpf.core.system_wide_device import SystemWideDevice

Expand Down Expand Up @@ -70,6 +71,7 @@ def _handle_balls_in_play_and_balls_live(self):
self.machine.game.balls_in_play += self.balls_added_live
self.balls_live_target = self.machine.game.balls_in_play

@event_handler(10)
def start(self, **kwargs):
"""Start multiball."""
del kwargs
Expand All @@ -82,10 +84,9 @@ def start(self, **kwargs):
return

self.shoot_again = True
self.debug_log("Starting multiball with %s balls",
self.config['ball_count'])

self._handle_balls_in_play_and_balls_live()
self.debug_log("Starting multiball with %s balls (added %s)", self.balls_live_target, self.balls_added_live)

balls_added = 0

Expand Down Expand Up @@ -114,7 +115,7 @@ def start(self, **kwargs):
callback=self.stop)

self.machine.events.post("multiball_" + self.name + "_started",
balls=self.config['ball_count'])
balls=self.balls_live_target)
'''event: multiball_(name)_started
desc: The multiball called (name) has just started.
args:
Expand Down Expand Up @@ -163,6 +164,7 @@ def _ball_drain_count_balls(self, balls, **kwargs):
'''
self.debug_log("Ball drained. MB ended.")

@event_handler(5)
def stop(self, **kwargs):
"""Stop shoot again."""
del kwargs
Expand All @@ -180,6 +182,7 @@ def stop(self, **kwargs):
# add handler for ball_drain until self.balls_ejected are drained
self.machine.events.add_handler('ball_drain', self._ball_drain_count_balls)

@event_handler(8)
def add_a_ball(self, **kwargs):
"""Add a ball if multiball has started."""
del kwargs
Expand All @@ -190,6 +193,7 @@ def add_a_ball(self, **kwargs):
self.machine.game.balls_in_play += 1
self.source_playfield.add_ball(balls=1)

@event_handler(9)
def start_or_add_a_ball(self, **kwargs):
"""Start multiball or add a ball if multiball has started."""
del kwargs
Expand All @@ -198,6 +202,7 @@ def start_or_add_a_ball(self, **kwargs):
else:
self.start()

@event_handler(20)
def enable(self, **kwargs):
"""Enable the multiball.
Expand All @@ -210,6 +215,7 @@ def enable(self, **kwargs):
self.debug_log("Enabling...")
self.enabled = True

@event_handler(1)
def disable(self, **kwargs):
"""Disable the multiball.
Expand All @@ -222,6 +228,7 @@ def disable(self, **kwargs):
self.debug_log("Disabling...")
self.enabled = False

@event_handler(2)
def reset(self, **kwargs):
"""Reset the multiball and disable it.
Expand Down
10 changes: 2 additions & 8 deletions mpf/platforms/pololu_maestro.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,8 @@ def initialize(self):

# validate our config (has to be in intialize since config_processor
# is not read in __init__)
self.machine.config_validator.validate_config("pololu_maestro",
self.config)

# load platform
self.platform = self.machine.get_platform_sections("pololu_maestro",
None)

self.serial = serial.Serial(self.platform.config['port'])
self.config = self.machine.config_validator.validate_config("pololu_maestro", self.config)
self.serial = serial.Serial(self.config['port'])

def stop(self):
"""Close serial."""
Expand Down
23 changes: 23 additions & 0 deletions mpf/tests/loop.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import selectors
import socket
from asyncio import base_events, coroutine, events
import collections
import heapq
Expand Down Expand Up @@ -82,6 +83,15 @@ def close(self):


class MockSocket(MockFd):
def __init__(self):
super().__init__()
self.family = socket.AF_INET
self.type = socket.SOCK_STREAM
self.proto = socket.IPPROTO_TCP

def setsockopt(self, *args, **kwargs):
pass

def getsockname(self):
return ""

Expand Down Expand Up @@ -214,6 +224,7 @@ def __init__(self):
self._clock_resolution = 1e-9
self._timers = NextTimers()
self._selector = TestSelector()
self._transports = {} # needed for newer asyncio on windows
self.reset_counters()

def time(self):
Expand All @@ -228,6 +239,9 @@ def advance_time(self, advance):
if advance:
self._time += advance

def _add_reader(self, *args, **kwargs):
return self.add_reader(*args, **kwargs)

def add_reader(self, fd, callback, *args):
"""Add a reader callback."""
self._check_closed()
Expand All @@ -244,6 +258,9 @@ def add_reader(self, fd, callback, *args):
if reader is not None:
reader.cancel()

def _remove_reader(self, fd):
return self.remove_reader(fd)

def remove_reader(self, fd):
"""Remove a reader callback."""
if self.is_closed():
Expand All @@ -266,6 +283,9 @@ def remove_reader(self, fd):
else:
return False

def _add_writer(self, *args, **kwargs):
return self.add_writer(*args, **kwargs)

def add_writer(self, fd, callback, *args):
"""Add a writer callback.."""
self._check_closed()
Expand All @@ -282,6 +302,9 @@ def add_writer(self, fd, callback, *args):
if writer is not None:
writer.cancel()

def _remove_writer(self, fd):
return self.remove_writer(fd)

def remove_writer(self, fd):
"""Remove a writer callback."""
if self.is_closed():
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
#config_version=4

modes:
- mode1

queue_event_player:
play:
queue_event: queue_event1
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#config_version=4
mode:
game_mode: False

queue_relay_player:
relay3:
post: relay3_start
wait_for: relay3_done
1 change: 1 addition & 0 deletions mpf/tests/machine_files/multiball/config/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ ball_devices:
modes:
- mode1
- mode2
- mode3

multiballs:
mb1:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#config_version=4
mode:
start_events: start_mode3
stop_events: stop_mode3

multiballs:
mb_autostart:
ball_count: 2
start_events: mode_mode3_started
12 changes: 12 additions & 0 deletions mpf/tests/test_MultiBall.py
Original file line number Diff line number Diff line change
Expand Up @@ -899,3 +899,15 @@ def testMultiballLockFullMultiplayer(self):
self.drain_ball()
self.advance_time_and_run()

def testModeWithMultiballAutostart(self):
# prepare game
self.fill_troughs()

# start game
self.start_game()
self.post_event("start_mode3")
self.advance_time_and_run(1)

# multiball should be enabled now but not started
self.assertTrue(self.machine.multiballs.mb_autostart.enabled)
self.assertEqual(1, self.machine.multiballs.mb_autostart.balls_added_live)
6 changes: 4 additions & 2 deletions mpf/tests/test_PololuMaestro.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@ def getConfigFile(self):
def getMachinePath(self):
return 'tests/machine_files/pololu_maestro/'

def get_platform(self):
return 'pololu_maestro'
def getOptions(self):
options = super().getOptions()
options['force_platform'] = False
return options

def setUp(self):
self.serial = MagicMock()
Expand Down
41 changes: 41 additions & 0 deletions mpf/tests/test_QueueEventPlayer.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ def test_queue_event_player(self):
self.assertEventCalled("queue_event1_finished")

def _cb(self, **kwargs):
del kwargs
self._done = True

def test_queue_relay_player(self):
Expand All @@ -68,3 +69,43 @@ def test_queue_relay_player(self):
self.post_event("relay2_done")
self.advance_time_and_run()
self.assertTrue(self._done)

def test_queue_relay_player_in_mode(self):
self._done = False
self.mock_event("relay3_start")

self.machine.modes.mode1.start()

# post queue event
self.machine.events.post_queue("relay3", callback=self._cb)
self.advance_time_and_run()

# should run the relay
self.assertFalse(self._done)
self.assertEventCalled("relay3_start")

# relay done. should trigger cb
self.post_event("relay3_done")
self.advance_time_and_run()
self.assertTrue(self._done)

# stop and start mode again
self.machine.modes.mode1.stop()
self.advance_time_and_run()

self._done = False
self.mock_event("relay3_start")
self.machine.modes.mode1.start()

# post queue event
self.machine.events.post_queue("relay3", callback=self._cb)
self.advance_time_and_run()

# should run the relay
self.assertFalse(self._done)
self.assertEventCalled("relay3_start")

# relay done. should trigger cb
self.post_event("relay3_done")
self.advance_time_and_run()
self.assertTrue(self._done)

0 comments on commit 9ce1131

Please sign in to comment.