mpf 0.58.0.dev3__py3-none-any.whl → 0.58.0.dev4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- mpf/_version.py +1 -1
- mpf/assets/show.py +3 -3
- mpf/commands/__init__.py +3 -2
- mpf/commands/game.py +51 -30
- mpf/config_players/hardware_sound_player.py +3 -3
- mpf/config_players/segment_display_player.py +4 -2
- mpf/config_spec.yaml +24 -12
- mpf/core/async_mode.py +3 -3
- mpf/core/ball_search.py +3 -3
- mpf/core/bcp/bcp.py +3 -3
- mpf/core/bcp/bcp_transport.py +3 -3
- mpf/core/config_player.py +3 -3
- mpf/core/config_spec_loader.py +6 -4
- mpf/core/config_validator.py +3 -4
- mpf/core/data_manager.py +14 -12
- mpf/core/delays.py +3 -3
- mpf/core/device.py +3 -3
- mpf/core/device_manager.py +3 -3
- mpf/core/enable_disable_mixin.py +3 -3
- mpf/core/events.py +3 -3
- mpf/core/file_interface.py +4 -4
- mpf/core/file_manager.py +16 -12
- mpf/core/logging.py +3 -4
- mpf/core/machine.py +100 -20
- mpf/core/machine_vars.py +3 -3
- mpf/core/mode.py +3 -2
- mpf/core/mpf_controller.py +4 -2
- mpf/core/placeholder_manager.py +3 -3
- mpf/core/platform.py +53 -3
- mpf/core/platform_controller.py +3 -3
- mpf/core/segment_mappings.py +3 -3
- mpf/core/text_ui.py +4 -2
- mpf/devices/achievement_group.py +3 -3
- mpf/devices/autofire.py +4 -2
- mpf/devices/ball_device/ball_device_ejector.py +4 -2
- mpf/devices/ball_device/outgoing_balls_handler.py +5 -4
- mpf/devices/ball_device/physical_ball_counter.py +3 -3
- mpf/devices/ball_routing.py +3 -3
- mpf/devices/ball_save.py +3 -3
- mpf/devices/blinkenlight.py +3 -2
- mpf/devices/combo_switch.py +11 -0
- mpf/devices/dc_motor.py +90 -0
- mpf/devices/digital_output.py +3 -3
- mpf/devices/driver.py +12 -10
- mpf/devices/drop_target.py +3 -4
- mpf/devices/light.py +25 -11
- mpf/devices/multiball_lock.py +3 -3
- mpf/devices/segment_display/segment_display.py +3 -3
- mpf/devices/shaker.py +12 -9
- mpf/devices/shot.py +20 -12
- mpf/devices/show_queue.py +3 -2
- mpf/devices/spinner.py +2 -2
- mpf/devices/switch.py +8 -5
- mpf/devices/timer.py +3 -3
- mpf/file_interfaces/pickle_interface.py +1 -1
- mpf/file_interfaces/yaml_interface.py +23 -7
- mpf/mpfconfig.yaml +2 -1
- mpf/platforms/base_serial_communicator.py +2 -3
- mpf/platforms/fadecandy.py +3 -3
- mpf/platforms/fast/communicators/base.py +92 -14
- mpf/platforms/fast/communicators/exp.py +5 -3
- mpf/platforms/fast/communicators/net_neuron.py +30 -1
- mpf/platforms/fast/communicators/seg.py +3 -2
- mpf/platforms/fast/fast.py +56 -12
- mpf/platforms/fast/fast_defines.py +5 -0
- mpf/platforms/fast/fast_driver.py +3 -2
- mpf/platforms/fast/fast_exp_board.py +1 -1
- mpf/platforms/fast/fast_motor.py +59 -0
- mpf/platforms/fast/fast_shaker.py +1 -2
- mpf/platforms/fast/fast_switch.py +0 -2
- mpf/platforms/interfaces/motor_platform_interface.py +34 -0
- mpf/platforms/lisy/lisy.py +1 -1
- mpf/platforms/mypinballs/mypinballs.py +1 -1
- mpf/platforms/openpixel.py +3 -3
- mpf/platforms/opp/opp.py +3 -2
- mpf/platforms/opp/opp_coil.py +3 -3
- mpf/platforms/opp/opp_serial_communicator.py +3 -2
- mpf/platforms/opp/opp_servo.py +3 -2
- mpf/platforms/p3_roc.py +3 -3
- mpf/platforms/p_roc.py +3 -3
- mpf/platforms/p_roc_common.py +2 -2
- mpf/platforms/p_roc_devices.py +3 -3
- mpf/platforms/pkone/pkone_coil.py +3 -3
- mpf/platforms/pkone/pkone_lights.py +4 -2
- mpf/platforms/pkone/pkone_serial_communicator.py +4 -2
- mpf/platforms/pkone/pkone_servo.py +3 -2
- mpf/platforms/pkone/pkone_switch.py +3 -2
- mpf/platforms/pololu_maestro.py +1 -1
- mpf/platforms/smart_virtual.py +8 -3
- mpf/platforms/spike/spike.py +3 -3
- mpf/platforms/system11.py +3 -3
- mpf/platforms/virtual.py +40 -2
- mpf/plugins/auditor.py +3 -2
- mpf/plugins/virtual_segment_display_connector.py +3 -2
- mpf/tests/machine_files/auditor/config/config.yaml +2 -0
- mpf/tests/machine_files/data_manager/config/config.yaml +4 -1
- mpf/tests/machine_files/dc_motor/config/config.yaml +18 -0
- mpf/tests/machine_files/shots/config/test_shots.yaml +2 -0
- mpf/tests/machine_files/shots/modes/base2/config/base2.yaml +4 -0
- mpf/tests/machine_files/soft_power_down/config/config.yaml +1 -0
- mpf/tests/platforms/fast.py +3 -3
- mpf/tests/test_BcpInterface.py +6 -6
- mpf/tests/test_ComboSwitches.py +78 -0
- mpf/tests/test_DCMotor.py +37 -0
- mpf/tests/test_Fast_Communicator.py +183 -0
- mpf/tests/test_Fast_Exp.py +13 -0
- mpf/tests/test_Fast_Power.py +82 -0
- mpf/tests/test_FileManager.py +75 -0
- mpf/tests/test_ServiceCli.py +1 -1
- mpf/tests/test_Shots.py +14 -0
- mpf/tests/test_SoftPowerDown.py +69 -0
- mpf/tests/test_VirtualPinball.py +2 -2
- mpf/tests/test_YamlInterface.py +33 -0
- {mpf-0.58.0.dev3.dist-info → mpf-0.58.0.dev4.dist-info}/METADATA +2 -4
- {mpf-0.58.0.dev3.dist-info → mpf-0.58.0.dev4.dist-info}/RECORD +120 -115
- {mpf-0.58.0.dev3.dist-info → mpf-0.58.0.dev4.dist-info}/WHEEL +1 -1
- mpf/plugins/twitch/__init__.py +0 -1
- mpf/plugins/twitch/twitch_client.py +0 -254
- mpf/plugins/twitch_bot.py +0 -57
- mpf/tests/machine_files/twitch_client/config/config.yaml +0 -6
- mpf/tests/test_TwitchClient.py +0 -175
- {mpf-0.58.0.dev3.dist-info → mpf-0.58.0.dev4.dist-info}/entry_points.txt +0 -0
- {mpf-0.58.0.dev3.dist-info → mpf-0.58.0.dev4.dist-info}/licenses/AUTHORS.md +0 -0
- {mpf-0.58.0.dev3.dist-info → mpf-0.58.0.dev4.dist-info}/licenses/LICENSE.md +0 -0
- {mpf-0.58.0.dev3.dist-info → mpf-0.58.0.dev4.dist-info}/top_level.txt +0 -0
mpf/_version.py
CHANGED
|
@@ -10,7 +10,7 @@ PyPI.
|
|
|
10
10
|
|
|
11
11
|
"""
|
|
12
12
|
|
|
13
|
-
__version__ = '0.58.0.
|
|
13
|
+
__version__ = '0.58.0.dev4' # Also consider whether MPF-MC pyproject.toml should be updated
|
|
14
14
|
'''The full version of MPF.'''
|
|
15
15
|
|
|
16
16
|
__short_version__ = '0.58'
|
mpf/assets/show.py
CHANGED
|
@@ -2,15 +2,15 @@
|
|
|
2
2
|
import re
|
|
3
3
|
from collections import namedtuple
|
|
4
4
|
|
|
5
|
-
from typing import List, Dict, Any, Optional
|
|
5
|
+
from typing import List, Dict, Any, Optional, TYPE_CHECKING
|
|
6
6
|
|
|
7
7
|
from mpf.core.assets import AssetPool
|
|
8
8
|
from mpf.core.config_validator import RuntimeToken
|
|
9
9
|
from mpf.core.utility_functions import Util
|
|
10
10
|
from mpf.exceptions.config_file_error import ConfigFileError
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
if
|
|
12
|
+
|
|
13
|
+
if TYPE_CHECKING:
|
|
14
14
|
from typing import NoReturn # pylint: disable-msg=cyclic-import,unused-import
|
|
15
15
|
|
|
16
16
|
__api__ = ['Show', 'RunningShow', 'ShowPool']
|
mpf/commands/__init__.py
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"""MPF CLI commands."""
|
|
2
2
|
import argparse
|
|
3
3
|
from importlib import import_module
|
|
4
|
+
import importlib.metadata
|
|
4
5
|
import os
|
|
5
6
|
import sys
|
|
6
|
-
from pkg_resources import iter_entry_points
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
import mpf.core
|
|
@@ -137,7 +137,8 @@ class CommandLineUtility(MpfCommandLineParser):
|
|
|
137
137
|
|
|
138
138
|
This is used from mpf mc.
|
|
139
139
|
"""
|
|
140
|
-
|
|
140
|
+
eps = importlib.metadata.entry_points(group='mpf.command')
|
|
141
|
+
for entry_point in eps:
|
|
141
142
|
command, function_ref = entry_point.load()()
|
|
142
143
|
self.external_commands[command] = function_ref
|
|
143
144
|
|
mpf/commands/game.py
CHANGED
|
@@ -31,13 +31,11 @@ class Command:
|
|
|
31
31
|
self.machine = None
|
|
32
32
|
self._sigint_count = 0
|
|
33
33
|
|
|
34
|
-
parser = argparse.ArgumentParser(
|
|
35
|
-
description='Starts the MPF game engine')
|
|
34
|
+
parser = argparse.ArgumentParser(description='Starts the MPF game engine')
|
|
36
35
|
|
|
37
36
|
parser.add_argument("-a",
|
|
38
37
|
action="store_true", dest="no_load_cache",
|
|
39
|
-
help="Forces the config to be loaded from files "
|
|
40
|
-
"and not cache")
|
|
38
|
+
help="Forces the config to be loaded from files and not cache")
|
|
41
39
|
|
|
42
40
|
parser.add_argument("-A",
|
|
43
41
|
action="store_false", dest="create_config_cache",
|
|
@@ -45,24 +43,24 @@ class Command:
|
|
|
45
43
|
|
|
46
44
|
parser.add_argument("-b",
|
|
47
45
|
action="store_false", dest="bcp", default=True,
|
|
48
|
-
help="Runs MPF without making a connection "
|
|
49
|
-
"attempt to a BCP Server")
|
|
46
|
+
help="Runs MPF without making a connection attempt to a BCP Server")
|
|
50
47
|
|
|
51
48
|
parser.add_argument("-c",
|
|
52
49
|
action="store", dest="configfile",
|
|
53
50
|
default="config.yaml", metavar='config_file',
|
|
54
|
-
help="The name of a config file to load. Default "
|
|
55
|
-
"
|
|
56
|
-
"config.yaml. Multiple files can be used "
|
|
57
|
-
"via a comma-"
|
|
51
|
+
help="The name of a config file to load. Default is "
|
|
52
|
+
"config.yaml. Multiple files can be used via a comma-"
|
|
58
53
|
"separated list (no spaces between)")
|
|
59
54
|
|
|
55
|
+
parser.add_argument("-e",
|
|
56
|
+
action="store_false", dest="echo_args", default=True,
|
|
57
|
+
help="Stop logging the raw command line arguments on startup.")
|
|
58
|
+
|
|
60
59
|
parser.add_argument("-f",
|
|
61
60
|
action="store_true", dest="force_assets_load",
|
|
62
61
|
default=False,
|
|
63
62
|
help="Load all assets upon startup. Useful for "
|
|
64
|
-
"ensuring all assets are set up properly "
|
|
65
|
-
"during development.")
|
|
63
|
+
"ensuring all assets are set up properly during development.")
|
|
66
64
|
|
|
67
65
|
parser.add_argument("-pit", action="store", dest="platform_integration_test",
|
|
68
66
|
metavar='pit_file', default=False,
|
|
@@ -91,8 +89,8 @@ class Command:
|
|
|
91
89
|
|
|
92
90
|
parser.add_argument("-P",
|
|
93
91
|
action="store_true", dest="production", default=False,
|
|
94
|
-
help="Production mode. Will suppress errors, wait for hardware on start
|
|
95
|
-
"try to exit when startup fails. Run this inside a loop.")
|
|
92
|
+
help="Production mode. Will suppress errors, wait for hardware on start "
|
|
93
|
+
"and try to exit when startup fails. Run this inside a loop.")
|
|
96
94
|
|
|
97
95
|
parser.add_argument("-t",
|
|
98
96
|
action="store_false", dest='text_ui', default=True,
|
|
@@ -102,43 +100,35 @@ class Command:
|
|
|
102
100
|
action="store_const", dest="loglevel",
|
|
103
101
|
const=logging.DEBUG,
|
|
104
102
|
default=15,
|
|
105
|
-
help="Enables verbose logging to the"
|
|
106
|
-
" log file")
|
|
103
|
+
help="Enables verbose logging to the log file")
|
|
107
104
|
|
|
108
105
|
parser.add_argument("-V",
|
|
109
106
|
action="store_const", dest="consoleloglevel",
|
|
110
107
|
const=logging.DEBUG,
|
|
111
108
|
default=logging.INFO,
|
|
112
109
|
help="Enables verbose logging to the console. DO "
|
|
113
|
-
"NOTE: you must also use -v for "
|
|
114
|
-
"this to work.")
|
|
110
|
+
"NOTE: you must also use -v for this to work.")
|
|
115
111
|
|
|
116
112
|
parser.add_argument("-x",
|
|
117
113
|
action="store_const", dest="force_platform",
|
|
118
114
|
const='virtual',
|
|
119
|
-
help="Forces the virtual platform to be "
|
|
120
|
-
"used for all devices")
|
|
115
|
+
help="Forces the virtual platform to be used for all devices")
|
|
121
116
|
|
|
122
117
|
parser.add_argument("--vpx",
|
|
123
118
|
action="store_const", dest="force_platform",
|
|
124
119
|
const='virtual_pinball',
|
|
125
|
-
help="Forces the virtual_pinball platform to be "
|
|
126
|
-
"used for all devices")
|
|
120
|
+
help="Forces the virtual_pinball platform to be used for all devices")
|
|
127
121
|
|
|
128
122
|
parser.add_argument("--syslog_address",
|
|
129
123
|
action="store", dest="syslog_address",
|
|
130
|
-
help="Log to the specified syslog address. This "
|
|
131
|
-
"
|
|
132
|
-
"
|
|
133
|
-
"Alternatively, you an specify host:port for "
|
|
134
|
-
"remote logging over UDP.")
|
|
124
|
+
help="Log to the specified syslog address. This can be a domain socket "
|
|
125
|
+
"such as /dev/og on Linux or /var/run/syslog on Mac. Alternatively, "
|
|
126
|
+
"you an specify host:port for remote logging over UDP.")
|
|
135
127
|
|
|
136
128
|
parser.add_argument("-X",
|
|
137
129
|
action="store_const", dest="force_platform",
|
|
138
130
|
const='smart_virtual',
|
|
139
|
-
help="Forces the smart virtual platform to be "
|
|
140
|
-
"used for all"
|
|
141
|
-
" devices")
|
|
131
|
+
help="Forces the smart virtual platform to be used for all devices")
|
|
142
132
|
|
|
143
133
|
# The following are just included for full compatibility with mc
|
|
144
134
|
# which is needed when using "mpf both".
|
|
@@ -180,6 +170,8 @@ class Command:
|
|
|
180
170
|
console_log.setFormatter(logging.Formatter(
|
|
181
171
|
'%(asctime)s.%(msecs)03d : %(levelname)s [%(name)s] %(message)s', "%H:%M:%S"))
|
|
182
172
|
|
|
173
|
+
console_log.addFilter(ConsoleCustomLevelFilter())
|
|
174
|
+
|
|
183
175
|
# initialize async handler for console
|
|
184
176
|
console_log_queue = Queue()
|
|
185
177
|
console_queue_handler = QueueHandler(console_log_queue)
|
|
@@ -194,6 +186,7 @@ class Command:
|
|
|
194
186
|
else:
|
|
195
187
|
formatter = logging.Formatter('%(asctime)s : %(levelname)s : %(name)s : %(message)s')
|
|
196
188
|
file_log.setFormatter(formatter)
|
|
189
|
+
file_log.addFilter(FileCustomLevelFilter())
|
|
197
190
|
|
|
198
191
|
# initialize async handler for file log
|
|
199
192
|
file_log_queue = Queue()
|
|
@@ -221,6 +214,10 @@ class Command:
|
|
|
221
214
|
|
|
222
215
|
signal.signal(signal.SIGINT, self.sigint_handler)
|
|
223
216
|
|
|
217
|
+
if self.args.echo_args:
|
|
218
|
+
raw_cmd = " ".join(args) if args else "[None]"
|
|
219
|
+
logger.info("Raw command line: %s", raw_cmd)
|
|
220
|
+
|
|
224
221
|
if not self.args.production:
|
|
225
222
|
config_loader = YamlMultifileConfigLoader(machine_path, self.args.configfile,
|
|
226
223
|
not self.args.no_load_cache, self.args.create_config_cache)
|
|
@@ -248,6 +245,8 @@ class Command:
|
|
|
248
245
|
def sigint_handler(self, signum=None, frame=None):
|
|
249
246
|
"""Handle SIGINT."""
|
|
250
247
|
del signum, frame
|
|
248
|
+
if self.machine:
|
|
249
|
+
self.machine.error_log("SIGINT received")
|
|
251
250
|
self._sigint_count += 1
|
|
252
251
|
if self._sigint_count > 1:
|
|
253
252
|
self.exit("Received second SIGINT. Will exit ungracefully!")
|
|
@@ -280,3 +279,25 @@ class Command:
|
|
|
280
279
|
input('Press ENTER to continue...') # nosec
|
|
281
280
|
|
|
282
281
|
sys.exit()
|
|
282
|
+
|
|
283
|
+
|
|
284
|
+
class ConsoleCustomLevelFilter(logging.Filter):
|
|
285
|
+
|
|
286
|
+
"""Filters out custom levels meant strictly for files."""
|
|
287
|
+
|
|
288
|
+
def filter(self, record):
|
|
289
|
+
"""Filters: 11 = DEBUG (File Only), 21 = INFO (File Only)."""
|
|
290
|
+
if record.levelno in (11, 21):
|
|
291
|
+
return False
|
|
292
|
+
return True
|
|
293
|
+
|
|
294
|
+
|
|
295
|
+
class FileCustomLevelFilter(logging.Filter):
|
|
296
|
+
|
|
297
|
+
"""Filters out custom levels meant strictly for console."""
|
|
298
|
+
|
|
299
|
+
def filter(self, record):
|
|
300
|
+
"""Filters: 12 = DEBUG (Console Only), 22 = INFO (Console Only)."""
|
|
301
|
+
if record.levelno in (12, 22):
|
|
302
|
+
return False
|
|
303
|
+
return True
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
"""Config player for sounds on an external sound card."""
|
|
2
|
-
from typing import List
|
|
2
|
+
from typing import List, TYPE_CHECKING
|
|
3
3
|
|
|
4
4
|
from mpf.config_players.device_config_player import DeviceConfigPlayer
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
if
|
|
6
|
+
|
|
7
|
+
if TYPE_CHECKING:
|
|
8
8
|
from mpf.devices.hardware_sound_system import HardwareSoundSystem # pylint: disable-msg=cyclic-import,unused-import; # noqa
|
|
9
9
|
|
|
10
10
|
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
"""Config player for text on segment displays."""
|
|
2
|
+
from typing import TYPE_CHECKING
|
|
3
|
+
|
|
2
4
|
from mpf.core.delays import DelayManager
|
|
3
5
|
|
|
4
6
|
from mpf.config_players.device_config_player import DeviceConfigPlayer
|
|
5
7
|
from mpf.platforms.interfaces.segment_display_platform_interface import FlashingType
|
|
6
8
|
from mpf.devices.segment_display.transition_manager import TransitionManager
|
|
7
9
|
|
|
8
|
-
|
|
9
|
-
if
|
|
10
|
+
|
|
11
|
+
if TYPE_CHECKING:
|
|
10
12
|
from typing import Dict # pylint: disable-msg=cyclic-import,unused-import
|
|
11
13
|
from mpf.devices.segment_display.segment_display import \
|
|
12
14
|
SegmentDisplay # pylint: disable-msg=cyclic-import,unused-import
|
mpf/config_spec.yaml
CHANGED
|
@@ -98,8 +98,8 @@ auditor:
|
|
|
98
98
|
audit: list|str|None
|
|
99
99
|
autosave: single|bool|true
|
|
100
100
|
autosave_events: single|bool|true
|
|
101
|
-
events:
|
|
102
|
-
player:
|
|
101
|
+
events: set|event_handler|None
|
|
102
|
+
player: set|str|None
|
|
103
103
|
audit_shots: single|bool|true
|
|
104
104
|
missing_switch_min_games: single|int|10
|
|
105
105
|
num_player_top_records: single|int|1
|
|
@@ -326,6 +326,18 @@ coils:
|
|
|
326
326
|
custom_code:
|
|
327
327
|
__valid_in__: machine
|
|
328
328
|
__type__: list
|
|
329
|
+
dc_motors:
|
|
330
|
+
__valid_in__: machine
|
|
331
|
+
__type__: device
|
|
332
|
+
default_power: single|float|0.0
|
|
333
|
+
number: single|str|
|
|
334
|
+
control_events: dict|str:subconfig(dc_motors_pulse_settings)|None
|
|
335
|
+
platform: single|str|None
|
|
336
|
+
platform_settings: single|dict|None
|
|
337
|
+
dc_motors_pulse_settings:
|
|
338
|
+
action: single|enum(pulse,reverse_pulse,stop)|pulse
|
|
339
|
+
power: single|float|None
|
|
340
|
+
duration: single|template_secs|None
|
|
329
341
|
digital_outputs:
|
|
330
342
|
__valid_in__: machine
|
|
331
343
|
__type__: device
|
|
@@ -639,7 +651,7 @@ fast_net:
|
|
|
639
651
|
console_log: single|enum(none,basic,full)|none
|
|
640
652
|
file_log: single|enum(none,basic,full)|basic
|
|
641
653
|
controller: single|enum(neuron,nano,sys11,wpc89,wpc95)|
|
|
642
|
-
watchdog: single|ms|
|
|
654
|
+
watchdog: single|ms|500
|
|
643
655
|
default_quick_debounce_open: single|ms|2
|
|
644
656
|
default_quick_debounce_close: single|ms|2
|
|
645
657
|
default_normal_debounce_open: single|ms|4
|
|
@@ -647,6 +659,8 @@ fast_net:
|
|
|
647
659
|
mute_unconfigured_switches: single|bool|false
|
|
648
660
|
gi_hz: single|int|30
|
|
649
661
|
lamp_hz: single|int|30
|
|
662
|
+
soft_power_hold_ms: single|ms|2500
|
|
663
|
+
soft_power_powerdown_delay: single|ms|4000
|
|
650
664
|
fast_io_loop:
|
|
651
665
|
model: single|str| # FP-I/O-0804, etc.
|
|
652
666
|
order: single|enum(1,2,3,4,5,6,7,8,9)|
|
|
@@ -814,6 +828,7 @@ hardware:
|
|
|
814
828
|
i2c: list|str|default
|
|
815
829
|
stepper_controllers: list|str|default
|
|
816
830
|
shaker_controllers: list|str|default
|
|
831
|
+
motor_controllers: list|str|default
|
|
817
832
|
hardware_sound_system: list|str|default
|
|
818
833
|
hardware_sound_systems:
|
|
819
834
|
__valid_in__: machine
|
|
@@ -1039,6 +1054,7 @@ machine:
|
|
|
1039
1054
|
__type__: config
|
|
1040
1055
|
balls_installed: single|int|1
|
|
1041
1056
|
min_balls: single|int|1
|
|
1057
|
+
soft_shutdown_exit_command: single|str|None
|
|
1042
1058
|
machine_vars:
|
|
1043
1059
|
__valid_in__: machine
|
|
1044
1060
|
__type__: config_dict
|
|
@@ -1129,6 +1145,10 @@ mpf:
|
|
|
1129
1145
|
mpf-mc:
|
|
1130
1146
|
__valid_in__: machine # todo add to validator
|
|
1131
1147
|
__type__: config
|
|
1148
|
+
data_manager:
|
|
1149
|
+
__valid_in__: machine
|
|
1150
|
+
__type__: config
|
|
1151
|
+
use_fsync: single|bool|None
|
|
1132
1152
|
multiballs:
|
|
1133
1153
|
__valid_in__: machine, mode
|
|
1134
1154
|
__type__: device
|
|
@@ -1585,6 +1605,7 @@ shots:
|
|
|
1585
1605
|
switches: list|machine(switches)|None
|
|
1586
1606
|
start_enabled: single|bool|None
|
|
1587
1607
|
delay_switch: dict|machine(switches):ms|None
|
|
1608
|
+
delay_event_list: dict|event_handler:ms|None
|
|
1588
1609
|
persist_enable: single|bool|true
|
|
1589
1610
|
playfield: single|machine(playfields)|playfield
|
|
1590
1611
|
priority: single|int|0
|
|
@@ -2150,15 +2171,6 @@ trinamics_steprocker:
|
|
|
2150
2171
|
__valid_in__: machine
|
|
2151
2172
|
__type__: config
|
|
2152
2173
|
port: single|str|
|
|
2153
|
-
twitch_client:
|
|
2154
|
-
__valid_in__: machine
|
|
2155
|
-
__type__: config
|
|
2156
|
-
user: single|str|None
|
|
2157
|
-
password: single|str|None
|
|
2158
|
-
channel: single|str|None
|
|
2159
|
-
user_var: single|str|None
|
|
2160
|
-
password_var: single|str|None
|
|
2161
|
-
channel_var: single|str|None
|
|
2162
2174
|
variable_player:
|
|
2163
2175
|
__valid_in__: machine, mode
|
|
2164
2176
|
__type__: config_player
|
mpf/core/async_mode.py
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
"""Base class for asyncio modes."""
|
|
2
|
-
from typing import Optional
|
|
2
|
+
from typing import Optional, TYPE_CHECKING
|
|
3
3
|
|
|
4
4
|
import abc
|
|
5
5
|
import asyncio
|
|
6
6
|
|
|
7
7
|
from mpf.core.mode import Mode
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
if
|
|
9
|
+
|
|
10
|
+
if TYPE_CHECKING:
|
|
11
11
|
from mpf.core.machine import MachineController # pylint: disable-msg=cyclic-import,unused-import
|
|
12
12
|
|
|
13
13
|
|
mpf/core/ball_search.py
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
"""Implements the ball search procedure."""
|
|
2
2
|
from collections import namedtuple
|
|
3
3
|
|
|
4
|
-
from typing import List
|
|
4
|
+
from typing import List, TYPE_CHECKING
|
|
5
5
|
|
|
6
6
|
from mpf.core.delays import DelayManager
|
|
7
7
|
from mpf.core.machine import MachineController
|
|
8
8
|
from mpf.core.mpf_controller import MpfController
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
if
|
|
10
|
+
|
|
11
|
+
if TYPE_CHECKING:
|
|
12
12
|
from mpf.devices.playfield import Playfield # pylint: disable-msg=cyclic-import,unused-import
|
|
13
13
|
|
|
14
14
|
BallSearchCallback = namedtuple("BallSearchCallback", ["priority", "callback", "name", "restore_callback"])
|
mpf/core/bcp/bcp.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"""BCP module."""
|
|
2
2
|
import asyncio
|
|
3
3
|
from functools import partial
|
|
4
|
-
from typing import List
|
|
4
|
+
from typing import List, TYPE_CHECKING
|
|
5
5
|
|
|
6
6
|
from mpf.core.events import QueuedEvent
|
|
7
7
|
from mpf.core.mpf_controller import MpfController
|
|
@@ -12,8 +12,8 @@ from mpf.core.utility_functions import Util
|
|
|
12
12
|
from mpf.core.bcp.bcp_interface import BcpInterface
|
|
13
13
|
from mpf.core.bcp.bcp_transport import BcpTransportManager
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
if
|
|
15
|
+
|
|
16
|
+
if TYPE_CHECKING:
|
|
17
17
|
from mpf.core.machine import MachineController # pylint: disable-msg=cyclic-import,unused-import
|
|
18
18
|
|
|
19
19
|
|
mpf/core/bcp/bcp_transport.py
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
"""Classes which manage BCP transports."""
|
|
2
2
|
from collections import defaultdict
|
|
3
3
|
|
|
4
|
-
from typing import Union
|
|
4
|
+
from typing import Union, TYPE_CHECKING
|
|
5
5
|
|
|
6
6
|
from mpf.core.bcp.bcp_client import BaseBcpClient
|
|
7
7
|
from mpf.core.utility_functions import Util
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
if
|
|
9
|
+
# noqa
|
|
10
|
+
if TYPE_CHECKING:
|
|
11
11
|
from mpf.core.machine import MachineController # pylint: disable-msg=cyclic-import,unused-import
|
|
12
12
|
|
|
13
13
|
|
mpf/core/config_player.py
CHANGED
|
@@ -3,7 +3,7 @@ import abc
|
|
|
3
3
|
import asyncio
|
|
4
4
|
import re
|
|
5
5
|
from functools import partial
|
|
6
|
-
from typing import List
|
|
6
|
+
from typing import List, TYPE_CHECKING
|
|
7
7
|
|
|
8
8
|
from mpf.core.machine import MachineController
|
|
9
9
|
from mpf.core.mode import Mode
|
|
@@ -11,8 +11,8 @@ from mpf.core.logging import LogMixin
|
|
|
11
11
|
from mpf.exceptions.config_file_error import ConfigFileError
|
|
12
12
|
from mpf.core.placeholder_manager import ConditionalEvent
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
if
|
|
14
|
+
|
|
15
|
+
if TYPE_CHECKING:
|
|
16
16
|
from mpf.core.placeholder_manager import BoolTemplate # pylint: disable-msg=cyclic-import,unused-import
|
|
17
17
|
from typing import Dict # pylint: disable-msg=cyclic-import,unused-import
|
|
18
18
|
|
mpf/core/config_spec_loader.py
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
"""Parse config_spec."""
|
|
2
|
-
from
|
|
2
|
+
from typing import TYPE_CHECKING
|
|
3
|
+
import importlib.metadata
|
|
3
4
|
|
|
4
5
|
from mpf.core.utility_functions import Util
|
|
5
6
|
from mpf.file_interfaces.yaml_interface import YamlInterface
|
|
6
7
|
|
|
7
|
-
|
|
8
|
-
if
|
|
8
|
+
|
|
9
|
+
if TYPE_CHECKING:
|
|
9
10
|
from mpf.core.device import Device # pylint: disable-msg=cyclic-import,unused-import
|
|
10
11
|
|
|
11
12
|
|
|
@@ -37,7 +38,8 @@ class ConfigSpecLoader:
|
|
|
37
38
|
@staticmethod
|
|
38
39
|
def load_external_platform_config_specs(config):
|
|
39
40
|
"""Load config spec for external platforms."""
|
|
40
|
-
|
|
41
|
+
eps = importlib.metadata.entry_points(group='mpf.platforms')
|
|
42
|
+
for platform_entry in eps:
|
|
41
43
|
config_spec = platform_entry.load().get_config_spec()
|
|
42
44
|
|
|
43
45
|
if config_spec:
|
mpf/core/config_validator.py
CHANGED
|
@@ -6,8 +6,7 @@ import re
|
|
|
6
6
|
from collections import namedtuple
|
|
7
7
|
from copy import deepcopy
|
|
8
8
|
|
|
9
|
-
from typing import Any
|
|
10
|
-
from typing import Dict
|
|
9
|
+
from typing import Any, Dict, TYPE_CHECKING
|
|
11
10
|
|
|
12
11
|
from mpf.core.config_spec_loader import ConfigSpecLoader
|
|
13
12
|
from mpf.core.rgb_color import NAMED_RGB_COLORS, RGBColor
|
|
@@ -15,8 +14,8 @@ from mpf.exceptions.config_file_error import ConfigFileError
|
|
|
15
14
|
from mpf.file_interfaces.yaml_interface import YamlInterface
|
|
16
15
|
from mpf.core.utility_functions import Util
|
|
17
16
|
|
|
18
|
-
|
|
19
|
-
if
|
|
17
|
+
|
|
18
|
+
if TYPE_CHECKING:
|
|
20
19
|
from mpf.core.machine import MachineController # pylint: disable-msg=cyclic-import,unused-import
|
|
21
20
|
|
|
22
21
|
|
mpf/core/data_manager.py
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
import copy
|
|
4
4
|
import os
|
|
5
5
|
import errno
|
|
6
|
+
import sys
|
|
6
7
|
import threading
|
|
7
8
|
import time
|
|
8
9
|
import _thread
|
|
@@ -17,10 +18,10 @@ class DataManager(MpfController):
|
|
|
17
18
|
|
|
18
19
|
config_name = "data_manager"
|
|
19
20
|
|
|
20
|
-
__slots__ = ["name", "min_wait_secs", "filename", "data", "_dirty"]
|
|
21
|
+
__slots__ = ["config", "name", "min_wait_secs", "filename", "data", "_dirty", "use_fsync"]
|
|
21
22
|
|
|
22
23
|
def __init__(self, machine, name, min_wait_secs=1):
|
|
23
|
-
"""Initialize data
|
|
24
|
+
"""Initialize data manager.
|
|
24
25
|
|
|
25
26
|
The DataManager is responsible for reading and writing data to/from a
|
|
26
27
|
file on disk.
|
|
@@ -48,6 +49,14 @@ class DataManager(MpfController):
|
|
|
48
49
|
else:
|
|
49
50
|
raise AssertionError("Invalid path {} for {}".format(config_path, name))
|
|
50
51
|
|
|
52
|
+
self.config = self.machine.config_validator.validate_config(
|
|
53
|
+
"data_manager", self.machine.config.get('data_manager'))
|
|
54
|
+
|
|
55
|
+
maybe_use_fsync = self.config.get('use_fsync', None)
|
|
56
|
+
if maybe_use_fsync is None:
|
|
57
|
+
maybe_use_fsync = sys.platform != 'win32'
|
|
58
|
+
self.use_fsync = maybe_use_fsync
|
|
59
|
+
|
|
51
60
|
self.data = dict()
|
|
52
61
|
self._dirty = threading.Event()
|
|
53
62
|
|
|
@@ -116,29 +125,22 @@ class DataManager(MpfController):
|
|
|
116
125
|
|
|
117
126
|
def _writing_thread(self): # pragma: no cover
|
|
118
127
|
# prevent early writes at start-up
|
|
119
|
-
data = None
|
|
120
128
|
time.sleep(self.min_wait_secs)
|
|
121
129
|
while not self.machine.thread_stopper.is_set():
|
|
122
130
|
if not self._dirty.wait(1):
|
|
123
131
|
continue
|
|
124
|
-
while FileManager.is_busy:
|
|
125
|
-
time.sleep(0.2)
|
|
126
132
|
self._dirty.clear()
|
|
127
133
|
|
|
128
|
-
data = copy.deepcopy(self.data)
|
|
129
134
|
# save data
|
|
130
135
|
try:
|
|
131
|
-
FileManager.save(self.filename, data)
|
|
136
|
+
FileManager.save(self.filename, copy.deepcopy(self.data), self.use_fsync)
|
|
132
137
|
except Exception as e: # pylint: disable=broad-exception-caught
|
|
133
138
|
# If the file writer has an exception handle it here. Otherwise
|
|
134
139
|
# this thread will die and all subsequent write attempts will no-op.
|
|
135
140
|
self.info_log("ERROR writing file %s: %s", self.filename, e)
|
|
136
|
-
data = None
|
|
137
141
|
# prevent too many writes
|
|
138
142
|
time.sleep(self.min_wait_secs)
|
|
139
143
|
|
|
140
144
|
# if dirty write data one last time during shutdown
|
|
141
|
-
if
|
|
142
|
-
|
|
143
|
-
time.sleep(0.2)
|
|
144
|
-
FileManager.save(self.filename, data)
|
|
145
|
+
if self._dirty.is_set():
|
|
146
|
+
FileManager.save(self.filename, copy.deepcopy(self.data), self.use_fsync)
|
mpf/core/delays.py
CHANGED
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
import uuid
|
|
4
4
|
from functools import partial
|
|
5
|
-
from typing import Any, Callable, Dict, Tuple
|
|
5
|
+
from typing import Any, Callable, Dict, Tuple, TYPE_CHECKING
|
|
6
6
|
from mpf.core.mpf_controller import MpfController
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
if
|
|
8
|
+
|
|
9
|
+
if TYPE_CHECKING:
|
|
10
10
|
from mpf.core.machine import MachineController # pylint: disable-msg=cyclic-import,unused-import
|
|
11
11
|
|
|
12
12
|
__api__ = ['DelayManager']
|
mpf/core/device.py
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
"""Contains the Device base class."""
|
|
2
2
|
import abc
|
|
3
3
|
|
|
4
|
-
from typing import List, Any, Optional
|
|
4
|
+
from typing import List, Any, Optional, TYPE_CHECKING
|
|
5
5
|
|
|
6
6
|
from mpf.core.machine import MachineController
|
|
7
7
|
from mpf.core.logging import LogMixin
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
if
|
|
9
|
+
|
|
10
|
+
if TYPE_CHECKING:
|
|
11
11
|
from mpf.core.mode import Mode # pylint: disable-msg=cyclic-import,unused-import
|
|
12
12
|
from mpf.core.platform import BasePlatform # pylint: disable-msg=cyclic-import,unused-import; # noqa
|
|
13
13
|
|
mpf/core/device_manager.py
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
"""Contains the DeviceManager base class."""
|
|
2
2
|
import asyncio
|
|
3
3
|
|
|
4
|
-
from typing import Callable, Tuple, List, Generator, Dict
|
|
4
|
+
from typing import Callable, Tuple, List, Generator, Dict, TYPE_CHECKING
|
|
5
5
|
|
|
6
6
|
from mpf.core.utility_functions import Util
|
|
7
7
|
from mpf.core.mpf_controller import MpfController
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
if
|
|
9
|
+
|
|
10
|
+
if TYPE_CHECKING:
|
|
11
11
|
from mpf.core.device import Device # pylint: disable-msg=cyclic-import,unused-import
|
|
12
12
|
|
|
13
13
|
|
mpf/core/enable_disable_mixin.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"""Implements enable and disable events for devices."""
|
|
2
|
-
from typing import Optional
|
|
2
|
+
from typing import Optional, TYPE_CHECKING
|
|
3
3
|
|
|
4
4
|
import abc
|
|
5
5
|
|
|
@@ -12,8 +12,8 @@ from mpf.core.events import event_handler
|
|
|
12
12
|
from mpf.core.mode_device import ModeDevice
|
|
13
13
|
from mpf.core.machine import MachineController
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
if
|
|
15
|
+
|
|
16
|
+
if TYPE_CHECKING:
|
|
17
17
|
from mpf.core.mode import Mode # pylint: disable-msg=cyclic-import,unused-import
|
|
18
18
|
from mpf.core.player import Player # pylint: disable-msg=cyclic-import,unused-import
|
|
19
19
|
|
mpf/core/events.py
CHANGED
|
@@ -7,12 +7,12 @@ import asyncio
|
|
|
7
7
|
from functools import partial, lru_cache
|
|
8
8
|
from unittest.mock import MagicMock
|
|
9
9
|
|
|
10
|
-
from typing import Dict, Any, Tuple, Optional, Callable, List
|
|
10
|
+
from typing import Dict, Any, Tuple, Optional, Callable, List, TYPE_CHECKING
|
|
11
11
|
|
|
12
12
|
from mpf.core.mpf_controller import MpfController
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
if
|
|
14
|
+
|
|
15
|
+
if TYPE_CHECKING:
|
|
16
16
|
from mpf.core.machine import MachineController # pylint: disable-msg=cyclic-import,unused-import
|
|
17
17
|
from mpf.core.placeholder_manager import BaseTemplate # pylint: disable-msg=cyclic-import,unused-import
|
|
18
18
|
from typing import Deque # pylint: disable-msg=cyclic-import,unused-import
|