mpf 0.81.0.dev2__py3-none-any.whl → 0.81.0.dev3__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/config_spec.yaml +3 -3
- mpf/core/device_manager.py +14 -1
- mpf/core/events.py +9 -6
- mpf/core/placeholder_manager.py +21 -1
- mpf/core/utility_functions.py +11 -6
- mpf/devices/light_group.py +45 -13
- mpf/platforms/fast/fast.py +7 -4
- mpf/platforms/fast/fast_led.py +17 -7
- mpf/platforms/virtual_pinball/virtual_pinball.py +1 -1
- mpf/tests/machine_files/auditor/config/config.yaml +1 -1
- mpf/tests/machine_files/custom_code/code/test_code.py +4 -0
- mpf/tests/machine_files/event_manager/config/test_event_manager.yaml +6 -0
- mpf/tests/machine_files/event_manager/modes/game_mode/config/game_mode.yaml +5 -0
- mpf/tests/machine_files/light/config/light_groups.yaml +12 -0
- mpf/tests/machine_files/service_mode/config/config.yaml +1 -1
- mpf/tests/machine_files/settings/config/config.yaml +27 -0
- mpf/tests/test_CustomCode.py +7 -0
- mpf/tests/test_DeviceManager.py +63 -0
- mpf/tests/test_EventManager.py +45 -0
- mpf/tests/test_Fast_Led.py +61 -0
- mpf/tests/test_LightGroups.py +48 -16
- mpf/tests/test_LightNumbering.py +2 -3
- mpf/tests/test_RandomEventPlayer.py +4 -4
- mpf/tests/test_Settings.py +16 -0
- mpf/tests/test_Utility_Functions.py +54 -7
- {mpf-0.81.0.dev2.dist-info → mpf-0.81.0.dev3.dist-info}/METADATA +2 -2
- {mpf-0.81.0.dev2.dist-info → mpf-0.81.0.dev3.dist-info}/RECORD +33 -32
- {mpf-0.81.0.dev2.dist-info → mpf-0.81.0.dev3.dist-info}/WHEEL +1 -1
- {mpf-0.81.0.dev2.dist-info → mpf-0.81.0.dev3.dist-info}/entry_points.txt +0 -0
- {mpf-0.81.0.dev2.dist-info → mpf-0.81.0.dev3.dist-info}/licenses/AUTHORS.md +0 -0
- {mpf-0.81.0.dev2.dist-info → mpf-0.81.0.dev3.dist-info}/licenses/LICENSE.md +0 -0
- {mpf-0.81.0.dev2.dist-info → mpf-0.81.0.dev3.dist-info}/top_level.txt +0 -0
mpf/_version.py
CHANGED
mpf/config_spec.yaml
CHANGED
|
@@ -544,7 +544,7 @@ fast:
|
|
|
544
544
|
__type__: config
|
|
545
545
|
net: single|subconfig(fast_net)|None
|
|
546
546
|
exp: single|subconfig(fast_exp)|None
|
|
547
|
-
exp_int: single|subconfig(fast_exp)|None
|
|
547
|
+
exp_int: single|subconfig(fast_exp)|None
|
|
548
548
|
aud: single|subconfig(fast_aud)|None
|
|
549
549
|
seg: single|subconfig(fast_seg)|None
|
|
550
550
|
dmd: single|subconfig(fast_dmd)|None
|
|
@@ -834,7 +834,7 @@ neoseg_displays:
|
|
|
834
834
|
number_template: single|str|None
|
|
835
835
|
start_x: single|float|None
|
|
836
836
|
start_y: single|float|None
|
|
837
|
-
size: single|enum(2digit,8digit)|8digit
|
|
837
|
+
size: single|enum(2digit,8digit,2digit-rg-swapped,8digit-rg-swapped)|8digit
|
|
838
838
|
light_template: single|subconfig(lights,device)|
|
|
839
839
|
lights:
|
|
840
840
|
__valid_in__: machine
|
|
@@ -1414,7 +1414,7 @@ settings:
|
|
|
1414
1414
|
label: single|str|
|
|
1415
1415
|
sort: single|int|
|
|
1416
1416
|
values: dict|str:str|
|
|
1417
|
-
key_type: single|enum(str,float,int)|str
|
|
1417
|
+
key_type: single|enum(str,float,int,bool)|str
|
|
1418
1418
|
default: single|str|
|
|
1419
1419
|
machine_var: single|str|None
|
|
1420
1420
|
settingType: single|str|standard
|
mpf/core/device_manager.py
CHANGED
|
@@ -172,7 +172,20 @@ class DeviceManager(MpfController):
|
|
|
172
172
|
for device_name in config:
|
|
173
173
|
futures.append(collection[device_name].device_added_system_wide())
|
|
174
174
|
|
|
175
|
-
|
|
175
|
+
fs = [asyncio.create_task(future) for future in futures]
|
|
176
|
+
done, pending = await asyncio.wait(fs, return_when=asyncio.FIRST_EXCEPTION)
|
|
177
|
+
|
|
178
|
+
# Check if any of the futures returned an exception and throw it
|
|
179
|
+
for task in done:
|
|
180
|
+
if task.cancelled():
|
|
181
|
+
continue
|
|
182
|
+
|
|
183
|
+
exc = task.exception()
|
|
184
|
+
if exc is not None:
|
|
185
|
+
for pending_task in pending:
|
|
186
|
+
pending_task.cancel()
|
|
187
|
+
await asyncio.gather(*pending, return_exceptions=True)
|
|
188
|
+
raise exc
|
|
176
189
|
|
|
177
190
|
# pylint: disable-msg=too-many-nested-blocks
|
|
178
191
|
def get_device_control_events(self, config) -> Generator[Tuple[str, Callable, int, "Device"], None, None]:
|
mpf/core/events.py
CHANGED
|
@@ -224,14 +224,15 @@ class EventManager(MpfController):
|
|
|
224
224
|
'handler you passed?'.format(handler, event))
|
|
225
225
|
|
|
226
226
|
sig = inspect.signature(handler)
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
if sig.parameters['kwargs'].kind != inspect.Parameter.VAR_KEYWORD:
|
|
232
|
-
raise AssertionError("Handler {} for event '{}' param kwargs is missing '**'. "
|
|
227
|
+
catchall_name = next((name for name in ('kwargs', '_kwargs') if name in sig.parameters), None)
|
|
228
|
+
if catchall_name is None:
|
|
229
|
+
raise AssertionError("Handler {} for event '{}' is missing **kwargs. "
|
|
233
230
|
"Actual signature: {}".format(handler, event, sig))
|
|
234
231
|
|
|
232
|
+
if sig.parameters[catchall_name].kind != inspect.Parameter.VAR_KEYWORD:
|
|
233
|
+
raise AssertionError("Handler {} for event '{}' param {} is missing '**'. "
|
|
234
|
+
"Actual signature: {}".format(handler, event, catchall_name, sig))
|
|
235
|
+
|
|
235
236
|
event, condition, additional_priority = self.get_event_and_condition_from_string(event)
|
|
236
237
|
priority += additional_priority
|
|
237
238
|
|
|
@@ -457,6 +458,8 @@ class EventManager(MpfController):
|
|
|
457
458
|
_future=future,
|
|
458
459
|
_keys=keys,
|
|
459
460
|
event=event_name)))
|
|
461
|
+
|
|
462
|
+
future.add_done_callback(lambda f: [self.remove_handler_by_key(k) for k in keys])
|
|
460
463
|
return future
|
|
461
464
|
|
|
462
465
|
def _wait_handler(self, _future: asyncio.Future, _keys: List[EventHandlerKey], **kwargs):
|
mpf/core/placeholder_manager.py
CHANGED
|
@@ -4,7 +4,7 @@ import string
|
|
|
4
4
|
import asyncio
|
|
5
5
|
import operator as op
|
|
6
6
|
import abc
|
|
7
|
-
from functools import lru_cache
|
|
7
|
+
from functools import lru_cache, partial
|
|
8
8
|
|
|
9
9
|
import re
|
|
10
10
|
from typing import Tuple, List, Any, Union
|
|
@@ -860,8 +860,28 @@ class BasePlaceholderManager(MpfController):
|
|
|
860
860
|
subscriptions.append(self.machine.wait_for_stop())
|
|
861
861
|
future = Util.any(subscriptions)
|
|
862
862
|
future = asyncio.ensure_future(future)
|
|
863
|
+
|
|
864
|
+
future.add_done_callback(
|
|
865
|
+
partial(self._cleanup_placeholder_subscriptions, subscriptions=subscriptions)
|
|
866
|
+
)
|
|
863
867
|
return value, future
|
|
864
868
|
|
|
869
|
+
def _cleanup_placeholder_subscriptions(self, future, subscriptions):
|
|
870
|
+
"""Cancel child placeholder subscriptions when the parent template frame finishes."""
|
|
871
|
+
del future
|
|
872
|
+
|
|
873
|
+
for sub in subscriptions:
|
|
874
|
+
if isinstance(sub, asyncio.Future):
|
|
875
|
+
if not sub.done():
|
|
876
|
+
# Cancel outstanding asyncio Future/Task instance
|
|
877
|
+
sub.cancel()
|
|
878
|
+
elif asyncio.iscoroutine(sub):
|
|
879
|
+
try:
|
|
880
|
+
# close raw coroutines (like sleep)
|
|
881
|
+
sub.close()
|
|
882
|
+
except RuntimeWarning:
|
|
883
|
+
pass
|
|
884
|
+
|
|
865
885
|
@lru_cache(typed=True)
|
|
866
886
|
def parse_conditional_template(self, template, default_number=None):
|
|
867
887
|
"""Parse a template for condition and number and return a dict."""
|
mpf/core/utility_functions.py
CHANGED
|
@@ -57,6 +57,8 @@ class Util:
|
|
|
57
57
|
return float(value)
|
|
58
58
|
if type_name == "str":
|
|
59
59
|
return str(value)
|
|
60
|
+
if type_name == "bool":
|
|
61
|
+
return str(value).lower() in ['true', 't', 'yes', 'enable', 'on', '1']
|
|
60
62
|
|
|
61
63
|
raise AssertionError("Unknown type {}".format(type_name))
|
|
62
64
|
|
|
@@ -586,13 +588,16 @@ class Util:
|
|
|
586
588
|
if isinstance(time_string, (int, float)):
|
|
587
589
|
return int(time_string)
|
|
588
590
|
|
|
589
|
-
time_string = str(time_string).upper()
|
|
591
|
+
time_string = str(time_string).upper().strip()
|
|
590
592
|
|
|
591
|
-
if time_string
|
|
592
|
-
return
|
|
593
|
+
if time_string == 'NONE':
|
|
594
|
+
return 0
|
|
595
|
+
|
|
596
|
+
if time_string.endswith('MS'):
|
|
597
|
+
return int(float(time_string[:-2]))
|
|
593
598
|
|
|
594
599
|
if time_string.endswith('MSEC'):
|
|
595
|
-
return int(time_string[:-4])
|
|
600
|
+
return int(float(time_string[:-4]))
|
|
596
601
|
|
|
597
602
|
if time_string.endswith('D'):
|
|
598
603
|
return int(float(time_string[:-1]) * 86400 * 1000)
|
|
@@ -609,7 +614,7 @@ class Util:
|
|
|
609
614
|
if time_string.endswith('SEC'):
|
|
610
615
|
return int(float(time_string[:-3]) * 1000)
|
|
611
616
|
|
|
612
|
-
return int(time_string)
|
|
617
|
+
return int(float(time_string))
|
|
613
618
|
|
|
614
619
|
@staticmethod
|
|
615
620
|
def string_to_secs(time_string: str) -> float:
|
|
@@ -847,4 +852,4 @@ class Util:
|
|
|
847
852
|
bool: True if the bit is set, False otherwise
|
|
848
853
|
"""
|
|
849
854
|
num = int(hex_string, 16)
|
|
850
|
-
return bool(num & (1 << bit))
|
|
855
|
+
return bool(num & (1 << bit))
|
mpf/devices/light_group.py
CHANGED
|
@@ -14,6 +14,21 @@ from mpf.core.system_wide_device import SystemWideDevice
|
|
|
14
14
|
from mpf.devices.light import Light
|
|
15
15
|
|
|
16
16
|
|
|
17
|
+
NEOSEG_8DIGIT_ORDER = [
|
|
18
|
+
95, 90, 93, 82, 85, 89, 86, 91, 88, 87, 81, 92, 83, 84, 94,
|
|
19
|
+
104, 76, 79, 96, 99, 103, 100, 77, 102, 101, 75, 78, 97, 98, 80,
|
|
20
|
+
110, 105, 108, 67, 70, 74, 71, 106, 73, 72, 66, 107, 68, 69, 109,
|
|
21
|
+
119, 61, 64, 111, 114, 118, 115, 62, 117, 116, 60, 63, 112, 113, 65,
|
|
22
|
+
5, 0, 3, 52, 55, 59, 56, 1, 58, 57, 51, 2, 53, 54, 4,
|
|
23
|
+
14, 46, 49, 6, 9, 13, 10, 47, 12, 11, 45, 48, 7, 8, 50,
|
|
24
|
+
20, 15, 18, 37, 40, 44, 41, 16, 43, 42, 36, 17, 38, 39, 19,
|
|
25
|
+
29, 31, 34, 21, 24, 28, 25, 32, 27, 26, 30, 33, 22, 23, 35]
|
|
26
|
+
|
|
27
|
+
NEOSEG_2DIGIT_ORDER = [
|
|
28
|
+
5, 0, 3, 22, 25, 29, 26, 1, 28, 27, 21, 2, 23, 24, 4,
|
|
29
|
+
14, 16, 19, 6, 9, 13, 10, 17, 12, 11, 15, 18, 7, 8, 20]
|
|
30
|
+
|
|
31
|
+
|
|
17
32
|
class LightGroup(SystemWideDevice):
|
|
18
33
|
|
|
19
34
|
"""An abstract group of lights."""
|
|
@@ -92,25 +107,41 @@ class LightGroup(SystemWideDevice):
|
|
|
92
107
|
for light in self.lights:
|
|
93
108
|
light.color(color, fade_ms, priority, key)
|
|
94
109
|
|
|
110
|
+
def _swap_grb_rgb_channel_offsets(self, offsets):
|
|
111
|
+
"""Swap every first and second out of sets of three (GRB->RGB)."""
|
|
112
|
+
adjustments = {0: 1, 1: -1, 2: 0}
|
|
113
|
+
return [
|
|
114
|
+
x + adjustments[x % 3]
|
|
115
|
+
for x in offsets
|
|
116
|
+
]
|
|
117
|
+
|
|
95
118
|
def _reorder_lights(self):
|
|
96
119
|
if self.config['size'] == '8digit':
|
|
97
120
|
#Magic order for 8 digit NeoSeg displays from CobraPin
|
|
98
|
-
order =
|
|
99
|
-
|
|
100
|
-
110, 105, 108, 67, 70, 74, 71, 106, 73, 72, 66, 107, 68, 69, 109,
|
|
101
|
-
119, 61, 64, 111, 114, 118, 115, 62, 117, 116, 60, 63, 112, 113, 65,
|
|
102
|
-
5, 0, 3, 52, 55, 59, 56, 1, 58, 57, 51, 2, 53, 54, 4,
|
|
103
|
-
14, 46, 49, 6, 9, 13, 10, 47, 12, 11, 45, 48, 7, 8, 50,
|
|
104
|
-
20, 15, 18, 37, 40, 44, 41, 16, 43, 42, 36, 17, 38, 39, 19,
|
|
105
|
-
29, 31, 34, 21, 24, 28, 25, 32, 27, 26, 30, 33, 22, 23, 35]
|
|
121
|
+
order = NEOSEG_8DIGIT_ORDER
|
|
122
|
+
|
|
106
123
|
elif self.config['size'] == '2digit':
|
|
107
124
|
#Magic order for 2 digit NeoSeg displays from CobraPin
|
|
108
|
-
order =
|
|
109
|
-
|
|
125
|
+
order = NEOSEG_2DIGIT_ORDER
|
|
126
|
+
|
|
127
|
+
elif self.config['size'] == '8digit-rg-swapped':
|
|
128
|
+
#Magic order for 8 digit NeoSeg displays from CobraPin when platform numbering uses RGB channel order
|
|
129
|
+
order = self._swap_grb_rgb_channel_offsets(NEOSEG_8DIGIT_ORDER)
|
|
130
|
+
|
|
131
|
+
elif self.config['size'] == '2digit-rg-swapped':
|
|
132
|
+
#Magic order for 2 digit NeoSeg displays from CobraPin when platform numbering uses RGB channel order
|
|
133
|
+
order = self._swap_grb_rgb_channel_offsets(NEOSEG_2DIGIT_ORDER)
|
|
110
134
|
else:
|
|
111
135
|
order = range(0, len(self.lights))
|
|
112
136
|
|
|
113
|
-
|
|
137
|
+
mapped_lights = []
|
|
138
|
+
try:
|
|
139
|
+
for i in order:
|
|
140
|
+
mapped_lights.append(self.lights[i])
|
|
141
|
+
self.lights = mapped_lights
|
|
142
|
+
except IndexError:
|
|
143
|
+
self.error_log("Attempted to use light index %s but source list only had %s items", i, len(self.lights))
|
|
144
|
+
raise
|
|
114
145
|
|
|
115
146
|
def wait_for_loaded(self):
|
|
116
147
|
"""Return future."""
|
|
@@ -180,11 +211,12 @@ class NeoSegDisplay(LightGroup):
|
|
|
180
211
|
__slots__ = [] # type: List[str]
|
|
181
212
|
|
|
182
213
|
def _create_lights(self):
|
|
183
|
-
if self.config['size']
|
|
214
|
+
if self.config['size'] in ('8digit', '8digit-rg-swapped'):
|
|
184
215
|
count = 120
|
|
185
|
-
elif self.config['size']
|
|
216
|
+
elif self.config['size'] in ('2digit', '2digit-rg-swapped'):
|
|
186
217
|
count = 30
|
|
187
218
|
else:
|
|
219
|
+
self.warning_log("NeoSegDisplay %s could not determine number of lights to create.", self.name)
|
|
188
220
|
count = 0
|
|
189
221
|
|
|
190
222
|
for index in range(self.config['number_start'], self.config['number_start'] + count):
|
mpf/platforms/fast/fast.py
CHANGED
|
@@ -593,10 +593,13 @@ class FastHardwarePlatform(ServoPlatform, LightsPlatform, RgbDmdPlatform,
|
|
|
593
593
|
return FASTMatrixLight(number, self.serial_connections['net'], self.machine,
|
|
594
594
|
int(1 / self.config['net']['lamp_hz'] * 1000), self)
|
|
595
595
|
if not subtype or subtype == "led":
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
596
|
+
try:
|
|
597
|
+
# make everything lowercase and strip trailing channel number
|
|
598
|
+
parts, channel = number.lower().rsplit('-', 1)
|
|
599
|
+
# split into board name, breakout, port, led
|
|
600
|
+
parts = parts.split('-')
|
|
601
|
+
except ValueError as e:
|
|
602
|
+
raise ValueError(f"Unable to parse FAST light '{config.name}' address {number}") from e
|
|
600
603
|
|
|
601
604
|
if parts[0] in self.exp_boards_by_name: # this is an expansion board LED in config file format
|
|
602
605
|
return self._add_exp_led_with_config_format(parts, channel, config.name)
|
mpf/platforms/fast/fast_led.py
CHANGED
|
@@ -40,7 +40,11 @@ class FASTRGBLED:
|
|
|
40
40
|
channel = self.channels[index]
|
|
41
41
|
if channel:
|
|
42
42
|
brightness, _, done = channel.get_fade_and_brightness(current_time)
|
|
43
|
-
|
|
43
|
+
# Clamp to a single byte: an out-of-range brightness here would
|
|
44
|
+
# format to a 1- or 3-char hex channel and crash the downstream
|
|
45
|
+
# binascii unpacking with an "Odd-length string" error.
|
|
46
|
+
clamped_brightness = min(255, max(0, int(brightness * 255)))
|
|
47
|
+
result += f'{clamped_brightness:02X}'
|
|
44
48
|
if not done:
|
|
45
49
|
self.dirty = True
|
|
46
50
|
else:
|
|
@@ -116,6 +120,12 @@ class FASTLEDChannel(LightPlatformInterface):
|
|
|
116
120
|
fade_ms = max_fade_ms
|
|
117
121
|
ratio = ((current_time + (fade_ms / 1000.0) - start_time) /
|
|
118
122
|
(target_time - start_time))
|
|
123
|
+
# A fade's start_time and the current_time passed in come from
|
|
124
|
+
# separate clock reads, so current_time can land a hair before
|
|
125
|
+
# start_time, making this ratio slightly out of [0, 1]. That would
|
|
126
|
+
# push brightness below 0 (fade up) or above 1 (fade down); clamp
|
|
127
|
+
# the ratio so the interpolation stays in range for both directions.
|
|
128
|
+
ratio = max(0.0, min(1.0, ratio))
|
|
119
129
|
brightness = start_brightness + (target_brightness - start_brightness) * ratio
|
|
120
130
|
done = False
|
|
121
131
|
else:
|
|
@@ -125,15 +135,15 @@ class FASTLEDChannel(LightPlatformInterface):
|
|
|
125
135
|
self._last_brightness = brightness
|
|
126
136
|
done = True
|
|
127
137
|
|
|
128
|
-
#
|
|
129
|
-
#
|
|
130
|
-
#
|
|
131
|
-
if brightness < 0:
|
|
132
|
-
brightness
|
|
133
|
-
self.led.log.warning("Calculated a negative brightness (%s) for led %s channel %s. current_time: %s "
|
|
138
|
+
# Final guard in case start/target brightness themselves are ever out
|
|
139
|
+
# of [0, 1]: an out-of-range value would crash the hex formatter in
|
|
140
|
+
# current_color, so clamp both ends.
|
|
141
|
+
if brightness < 0 or brightness > 1:
|
|
142
|
+
self.led.log.warning("Calculated an out-of-range brightness (%s) for led %s channel %s. current_time: %s "
|
|
134
143
|
"start_brightness: %s, start_time: %s, target_brightness: %s, target_time: %s",
|
|
135
144
|
brightness, self.led, self.channel, current_time, start_brightness, start_time,
|
|
136
145
|
target_brightness, target_time)
|
|
146
|
+
brightness = max(0.0, min(1.0, brightness))
|
|
137
147
|
|
|
138
148
|
return brightness, fade_ms, done
|
|
139
149
|
|
|
@@ -160,7 +160,7 @@ class VirtualPinballPlatform(LightsPlatform, SwitchPlatform, DriverPlatform, Seg
|
|
|
160
160
|
|
|
161
161
|
"""VPX platform."""
|
|
162
162
|
|
|
163
|
-
__slots__ = ["_lights", "_switches", "_drivers", "_last_drivers", "_last_lights",
|
|
163
|
+
__slots__ = ["_lights", "_switches", "_drivers", "_last_drivers", "_last_lights",
|
|
164
164
|
"_started", "rules", "_configured_segment_displays", "_last_segment_text"]
|
|
165
165
|
|
|
166
166
|
def __init__(self, machine):
|
|
@@ -6,7 +6,11 @@ class TestCustomCode(CustomCode):
|
|
|
6
6
|
self.log.debug("Loaded!")
|
|
7
7
|
|
|
8
8
|
self.machine.events.add_handler('test_event', self._update)
|
|
9
|
+
self.machine.events.add_handler('test_event_2', self._alternative_kwargs)
|
|
9
10
|
|
|
10
11
|
def _update(self, **kwargs):
|
|
11
12
|
del kwargs
|
|
12
13
|
self.machine.events.post("test_response")
|
|
14
|
+
|
|
15
|
+
def _alternative_kwargs(self, **_kwargs):
|
|
16
|
+
self.machine.events.post("test_response_2")
|
|
@@ -7,6 +7,12 @@ event_player:
|
|
|
7
7
|
test_event_player_delayed:
|
|
8
8
|
- test_event_player2|2s
|
|
9
9
|
- test_event_player3:2s
|
|
10
|
+
"{machine.lifetime_earnings >= 500}": never_happens_machine
|
|
11
|
+
"{machine.switches.s_test_1.state == 1}": sometimes_happens_switch
|
|
12
|
+
|
|
13
|
+
switches:
|
|
14
|
+
s_test_1:
|
|
15
|
+
number:
|
|
10
16
|
|
|
11
17
|
random_event_player:
|
|
12
18
|
test_random_event_player1:
|
|
@@ -3,6 +3,11 @@ mode:
|
|
|
3
3
|
start_events: game_mode_start
|
|
4
4
|
stop_events: game_mode_end
|
|
5
5
|
|
|
6
|
+
event_player:
|
|
7
|
+
"{players[0].score>=99999999}": never_happens_players
|
|
8
|
+
"{current_player.score>=999999999}": never_happens_player
|
|
9
|
+
"{current_player.score<=current_player.score + 1 and current_player.score > -1}": always_happens_multiple_ast
|
|
10
|
+
|
|
6
11
|
random_event_player:
|
|
7
12
|
test_random_event_player_mode2:
|
|
8
13
|
- out1
|
|
@@ -50,3 +50,15 @@ neoseg_displays:
|
|
|
50
50
|
light_template:
|
|
51
51
|
type: w
|
|
52
52
|
subtype: led
|
|
53
|
+
neoSeg_2:
|
|
54
|
+
start_channel: 0-1-0
|
|
55
|
+
size: 8digit-rg-swapped
|
|
56
|
+
light_template:
|
|
57
|
+
type: w
|
|
58
|
+
subtype: led
|
|
59
|
+
neoSeg_3:
|
|
60
|
+
start_channel: 0-1-120
|
|
61
|
+
size: 2digit-rg-swapped
|
|
62
|
+
light_template:
|
|
63
|
+
type: w
|
|
64
|
+
subtype: led
|
|
@@ -19,3 +19,30 @@ settings:
|
|
|
19
19
|
zero: "Zero"
|
|
20
20
|
one: "One"
|
|
21
21
|
two: "Two"
|
|
22
|
+
custom_setting_float:
|
|
23
|
+
label: "Float Setting"
|
|
24
|
+
key_type: float
|
|
25
|
+
default: 0.1
|
|
26
|
+
sort: 3
|
|
27
|
+
values:
|
|
28
|
+
0: "Zero"
|
|
29
|
+
0.1: "Point One"
|
|
30
|
+
1.0: "One"
|
|
31
|
+
2.5: "Two Point Five"
|
|
32
|
+
custom_setting_bool_t:
|
|
33
|
+
label: "Boolean Setting Default True"
|
|
34
|
+
key_type: bool
|
|
35
|
+
default: true
|
|
36
|
+
sort: 4
|
|
37
|
+
values:
|
|
38
|
+
true: "yes"
|
|
39
|
+
false: "off"
|
|
40
|
+
|
|
41
|
+
custom_setting_bool_f:
|
|
42
|
+
label: "Boolean Setting Default False"
|
|
43
|
+
key_type: bool
|
|
44
|
+
default: false
|
|
45
|
+
sort: 5
|
|
46
|
+
values:
|
|
47
|
+
true: "on"
|
|
48
|
+
false: "no"
|
mpf/tests/test_CustomCode.py
CHANGED
|
@@ -15,3 +15,10 @@ class TestCustomCode(MpfTestCase):
|
|
|
15
15
|
self.machine_run()
|
|
16
16
|
|
|
17
17
|
self.assertEqual(1, self._events['test_response'])
|
|
18
|
+
|
|
19
|
+
def test_scoring_2(self):
|
|
20
|
+
self.mock_event("test_response_2")
|
|
21
|
+
self.post_event("test_event_2")
|
|
22
|
+
self.machine_run()
|
|
23
|
+
|
|
24
|
+
self.assertEqual(1, self._events['test_response_2'])
|
mpf/tests/test_DeviceManager.py
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
|
+
import asyncio
|
|
1
2
|
import inspect
|
|
2
3
|
|
|
4
|
+
from unittest.mock import patch, AsyncMock, MagicMock
|
|
5
|
+
|
|
3
6
|
from mpf.core.utility_functions import Util
|
|
4
7
|
from mpf.tests.MpfTestCase import MpfTestCase
|
|
5
8
|
|
|
@@ -37,3 +40,63 @@ class TestDeviceManager(MpfTestCase):
|
|
|
37
40
|
self.assertTrue(hasattr(method, "relative_priority"),
|
|
38
41
|
"Method {}.{} is missing a relative_priority. Did you apply the event_handler "
|
|
39
42
|
"decorator?".format(device_type, method_name))
|
|
43
|
+
|
|
44
|
+
def test_initialize_devices_re_raises_first_exception(self):
|
|
45
|
+
"""Test that initialize_devices re-raises exceptions from failed device initialization."""
|
|
46
|
+
async def test_exception_handling():
|
|
47
|
+
failing_task = asyncio.create_task(self._failing_coro())
|
|
48
|
+
slow_task = asyncio.create_task(self._slow_coro())
|
|
49
|
+
|
|
50
|
+
fs = [failing_task, slow_task]
|
|
51
|
+
done, pending = await asyncio.wait(fs, return_when=asyncio.FIRST_EXCEPTION)
|
|
52
|
+
|
|
53
|
+
for task in done:
|
|
54
|
+
if task.cancelled():
|
|
55
|
+
continue
|
|
56
|
+
exc = task.exception()
|
|
57
|
+
if exc is not None:
|
|
58
|
+
for pending_task in pending:
|
|
59
|
+
pending_task.cancel()
|
|
60
|
+
await asyncio.gather(*pending, return_exceptions=True)
|
|
61
|
+
raise exc
|
|
62
|
+
|
|
63
|
+
with self.assertRaises(RuntimeError):
|
|
64
|
+
self.loop.run_until_complete(test_exception_handling())
|
|
65
|
+
|
|
66
|
+
def test_initialize_devices_completes_when_all_succeed(self):
|
|
67
|
+
"""Test that initialize_devices completes normally when all devices succeed."""
|
|
68
|
+
async def test_success_handling():
|
|
69
|
+
success1 = asyncio.create_task(self._success_coro())
|
|
70
|
+
success2 = asyncio.create_task(self._success_coro())
|
|
71
|
+
|
|
72
|
+
fs = [success1, success2]
|
|
73
|
+
done, pending = await asyncio.wait(fs, return_when=asyncio.FIRST_EXCEPTION)
|
|
74
|
+
|
|
75
|
+
for task in done:
|
|
76
|
+
if task.cancelled():
|
|
77
|
+
continue
|
|
78
|
+
exc = task.exception()
|
|
79
|
+
if exc is not None:
|
|
80
|
+
for pending_task in pending:
|
|
81
|
+
pending_task.cancel()
|
|
82
|
+
await asyncio.gather(*pending, return_exceptions=True)
|
|
83
|
+
raise exc
|
|
84
|
+
|
|
85
|
+
return "success"
|
|
86
|
+
|
|
87
|
+
result = self.loop.run_until_complete(test_success_handling())
|
|
88
|
+
self.assertEqual(result, "success")
|
|
89
|
+
|
|
90
|
+
async def _failing_coro(self):
|
|
91
|
+
"""Async coroutine that fails."""
|
|
92
|
+
raise RuntimeError("Device initialization failed")
|
|
93
|
+
|
|
94
|
+
async def _slow_coro(self):
|
|
95
|
+
"""Async coroutine that takes time."""
|
|
96
|
+
await asyncio.sleep(10)
|
|
97
|
+
return "done"
|
|
98
|
+
|
|
99
|
+
async def _success_coro(self):
|
|
100
|
+
"""Async coroutine that succeeds."""
|
|
101
|
+
await asyncio.sleep(0)
|
|
102
|
+
return "success"
|
mpf/tests/test_EventManager.py
CHANGED
|
@@ -912,3 +912,48 @@ class TestEventManager(MpfFakeGameTestCase, MpfTestCase):
|
|
|
912
912
|
# invalid space
|
|
913
913
|
with self.assertRaises(ValueError):
|
|
914
914
|
self.machine.events.add_handler("event_name {machine.variables.test}", self._handler)
|
|
915
|
+
|
|
916
|
+
def test_handler_cleanup_on_variable_change(self):
|
|
917
|
+
self.start_game()
|
|
918
|
+
self.machine.events.post('game_mode_start')
|
|
919
|
+
self.advance_time_and_run(0.01)
|
|
920
|
+
|
|
921
|
+
initial_count_pte = len(self.machine.events.registered_handlers['player_turn_ended'])
|
|
922
|
+
initial_count_player_added = len(self.machine.events.registered_handlers['player_added'])
|
|
923
|
+
|
|
924
|
+
for i in range(100):
|
|
925
|
+
self.machine.game.player.score += 100
|
|
926
|
+
self.advance_time_and_run(0.01)
|
|
927
|
+
|
|
928
|
+
final_count_pte = len(self.machine.events.registered_handlers['player_turn_ended'])
|
|
929
|
+
final_count_player_added = len(self.machine.events.registered_handlers['player_added'])
|
|
930
|
+
self.assertEqual(initial_count_pte, final_count_pte)
|
|
931
|
+
self.assertEqual(initial_count_player_added, final_count_player_added)
|
|
932
|
+
|
|
933
|
+
def test_handler_cleanup_on_machine_variable_change(self):
|
|
934
|
+
self.start_game()
|
|
935
|
+
self.advance_time_and_run(0.01)
|
|
936
|
+
|
|
937
|
+
event_name = 'machine_var_lifetime_earnings'
|
|
938
|
+
initial_count = len(self.machine.events.registered_handlers.get(event_name, []))
|
|
939
|
+
|
|
940
|
+
for i in range(100):
|
|
941
|
+
self.machine.variables.set_machine_var('lifetime_earnings', 10 + i)
|
|
942
|
+
self.advance_time_and_run(0.01)
|
|
943
|
+
|
|
944
|
+
final_count = len(self.machine.events.registered_handlers.get(event_name, []))
|
|
945
|
+
self.assertEqual(initial_count, final_count)
|
|
946
|
+
|
|
947
|
+
def test_handler_cleanup_on_switch_state_change(self):
|
|
948
|
+
self.start_game()
|
|
949
|
+
self.advance_time_and_run(0.01)
|
|
950
|
+
|
|
951
|
+
event_name = 'switch_s_test_1_active'
|
|
952
|
+
initial_count = len(self.machine.events.registered_handlers.get(event_name, []))
|
|
953
|
+
|
|
954
|
+
for _ in range(50):
|
|
955
|
+
self.hit_switch_and_run('s_test_1', 0.01)
|
|
956
|
+
self.release_switch_and_run('s_test_1', 0.01)
|
|
957
|
+
|
|
958
|
+
final_count = len(self.machine.events.registered_handlers.get(event_name, []))
|
|
959
|
+
self.assertEqual(initial_count, final_count)
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# mpf.tests.test_Fast_Led
|
|
2
|
+
"""Unit tests for FAST LED fade/brightness math."""
|
|
3
|
+
import unittest
|
|
4
|
+
from unittest.mock import MagicMock
|
|
5
|
+
|
|
6
|
+
from mpf.platforms.fast.fast_led import FASTLEDChannel
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class _FakeLed:
|
|
10
|
+
"""Minimal stand-in for FASTRGBLED for unit-testing a single channel."""
|
|
11
|
+
|
|
12
|
+
def __init__(self, hardware_fade_ms=0):
|
|
13
|
+
self.number = '880'
|
|
14
|
+
self.hardware_fade_ms = hardware_fade_ms
|
|
15
|
+
self.dirty = False
|
|
16
|
+
self.log = MagicMock()
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class TestFastLed(unittest.TestCase):
|
|
20
|
+
|
|
21
|
+
def _channel(self, hardware_fade_ms=0):
|
|
22
|
+
return FASTLEDChannel(_FakeLed(hardware_fade_ms), 0)
|
|
23
|
+
|
|
24
|
+
def test_fade_interpolates_to_three_places(self):
|
|
25
|
+
# Half-way through a 0 -> 1 fade the brightness is 0.5.
|
|
26
|
+
ch = self._channel()
|
|
27
|
+
start = 1000.0
|
|
28
|
+
ch.set_fade(start_brightness=0.0, start_time=start,
|
|
29
|
+
target_brightness=1.0, target_time=start + 1.0)
|
|
30
|
+
|
|
31
|
+
brightness, _, _ = ch.get_fade_and_brightness(start + 0.5)
|
|
32
|
+
|
|
33
|
+
self.assertAlmostEqual(brightness, 0.5, places=3)
|
|
34
|
+
|
|
35
|
+
def test_fade_up_when_current_time_precedes_start_time(self):
|
|
36
|
+
# When current_time reads as before the fade's start_time, a fade up
|
|
37
|
+
# must not calculate a brightness below 0.
|
|
38
|
+
ch = self._channel()
|
|
39
|
+
now = 1000.0
|
|
40
|
+
ch.set_fade(start_brightness=0.0, start_time=now + 0.01,
|
|
41
|
+
target_brightness=1.0, target_time=now + 0.5)
|
|
42
|
+
|
|
43
|
+
brightness, _, _ = ch.get_fade_and_brightness(now)
|
|
44
|
+
|
|
45
|
+
self.assertGreaterEqual(brightness, 0.0)
|
|
46
|
+
self.assertLessEqual(brightness, 1.0)
|
|
47
|
+
|
|
48
|
+
def test_fade_down_when_current_time_precedes_start_time(self):
|
|
49
|
+
# The same out-of-order read while fading down must not calculate a
|
|
50
|
+
# brightness above 1, which would format to a 3-char hex channel and
|
|
51
|
+
# crash the downstream binascii unpacking.
|
|
52
|
+
ch = self._channel()
|
|
53
|
+
now = 1000.0
|
|
54
|
+
ch.set_fade(start_brightness=1.0, start_time=now + 0.01,
|
|
55
|
+
target_brightness=0.0, target_time=now + 0.5)
|
|
56
|
+
|
|
57
|
+
brightness, _, _ = ch.get_fade_and_brightness(now)
|
|
58
|
+
|
|
59
|
+
self.assertGreaterEqual(brightness, 0.0)
|
|
60
|
+
self.assertLessEqual(brightness, 1.0)
|
|
61
|
+
self.assertEqual(2, len(f'{int(brightness * 255):02X}'))
|
mpf/tests/test_LightGroups.py
CHANGED
|
@@ -20,8 +20,7 @@ class TestLightGroups(MpfTestCase):
|
|
|
20
20
|
self.assertLightColor("stripe1_light_3", "red")
|
|
21
21
|
self.assertLightColor("stripe1_light_4", "red")
|
|
22
22
|
|
|
23
|
-
def
|
|
24
|
-
# stripe 1
|
|
23
|
+
def test_config_stripe_1(self):
|
|
25
24
|
self.assertEqual("led-10-r", self.machine.lights["stripe1_light_0"].hw_drivers["red"][0].number)
|
|
26
25
|
self.assertListEqual(["test", "stripe1"], self.machine.lights["stripe1_light_0"].config['tags'])
|
|
27
26
|
self.assertEqual("led-11-r", self.machine.lights["stripe1_light_1"].hw_drivers["red"][0].number)
|
|
@@ -30,7 +29,7 @@ class TestLightGroups(MpfTestCase):
|
|
|
30
29
|
self.assertEqual("led-14-r", self.machine.lights["stripe1_light_4"].hw_drivers["red"][0].number)
|
|
31
30
|
self.assertListEqual(["test", "stripe1"], self.machine.lights["stripe1_light_4"].config['tags'])
|
|
32
31
|
|
|
33
|
-
|
|
32
|
+
def test_config_stripe_2(self):
|
|
34
33
|
self.assertEqual("led-7-200-r", self.machine.lights["stripe2_light_0"].hw_drivers["red"][0].number)
|
|
35
34
|
self.assertEqual(10, self.machine.lights["stripe2_light_0"].config['x'])
|
|
36
35
|
self.assertEqual(20, self.machine.lights["stripe2_light_0"].config['y'])
|
|
@@ -38,17 +37,14 @@ class TestLightGroups(MpfTestCase):
|
|
|
38
37
|
self.assertEqual(15, self.machine.lights["stripe2_light_1"].config['x'])
|
|
39
38
|
self.assertEqual(20, self.machine.lights["stripe2_light_1"].config['y'])
|
|
40
39
|
|
|
41
|
-
|
|
40
|
+
def test_config_stripe_3(self):
|
|
42
41
|
self.assertEqual("led-ABC-123", self.machine.lights["stripe3_light_0"].hw_drivers["red"][0].number)
|
|
43
42
|
self.assertEqual("led-ABC-123+1", self.machine.lights["stripe3_light_0"].hw_drivers["green"][0].number)
|
|
44
|
-
self.assertEqual("led-ABC-123+2",
|
|
45
|
-
|
|
46
|
-
self.assertEqual("led-ABC-123+
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
self.machine.lights["stripe3_light_1"].hw_drivers["red"][0].number)
|
|
50
|
-
|
|
51
|
-
# ring 1
|
|
43
|
+
self.assertEqual("led-ABC-123+2", self.machine.lights["stripe3_light_0"].hw_drivers["blue"][0].number)
|
|
44
|
+
self.assertEqual("led-ABC-123+3", self.machine.lights["stripe3_light_0"].hw_drivers["white"][0].number)
|
|
45
|
+
self.assertEqual("led-ABC-123+4", self.machine.lights["stripe3_light_1"].hw_drivers["red"][0].number)
|
|
46
|
+
|
|
47
|
+
def test_config_rings(self):
|
|
52
48
|
self.assertEqual("led-20-r", self.machine.lights["ring1_light_0"].hw_drivers["red"][0].number)
|
|
53
49
|
self.assertEqual("led-21-r", self.machine.lights["ring1_light_1"].hw_drivers["red"][0].number)
|
|
54
50
|
self.assertEqual("led-22-r", self.machine.lights["ring1_light_2"].hw_drivers["red"][0].number)
|
|
@@ -67,13 +63,18 @@ class TestLightGroups(MpfTestCase):
|
|
|
67
63
|
self.assertEqual(100, self.machine.lights["ring1_light_9"].config['x'])
|
|
68
64
|
self.assertEqual(53, self.machine.lights["ring1_light_9"].config['y'])
|
|
69
65
|
|
|
70
|
-
|
|
66
|
+
def test_config_neoSeg_0(self): # 8 digit
|
|
71
67
|
self.assertEqual("led-0-0-0", self.machine.lights["neoSeg_0_light_0"].hw_drivers["white"][0].number)
|
|
72
68
|
self.assertEqual("led-0-0-0+1", self.machine.lights["neoSeg_0_light_1"].hw_drivers["white"][0].number)
|
|
73
69
|
self.assertEqual("led-0-0-0+2", self.machine.lights["neoSeg_0_light_2"].hw_drivers["white"][0].number)
|
|
74
70
|
self.assertEqual("neoSeg_0_light_119", self.machine.lights["neoSeg_0_light_119"].name)
|
|
75
|
-
|
|
71
|
+
|
|
76
72
|
self.assertEqual(self.machine.neoseg_displays["neoSeg_0"].lights[0].name, self.machine.lights["neoSeg_0_light_95"].name)
|
|
73
|
+
self.assertEqual(self.machine.neoseg_displays["neoSeg_0"].lights[1].name, self.machine.lights["neoSeg_0_light_90"].name)
|
|
74
|
+
self.assertEqual(self.machine.neoseg_displays["neoSeg_0"].lights[2].name, self.machine.lights["neoSeg_0_light_93"].name)
|
|
75
|
+
self.assertEqual(self.machine.neoseg_displays["neoSeg_0"].lights[3].name, self.machine.lights["neoSeg_0_light_82"].name)
|
|
76
|
+
self.assertEqual(self.machine.neoseg_displays["neoSeg_0"].lights[4].name, self.machine.lights["neoSeg_0_light_85"].name)
|
|
77
|
+
self.assertEqual(self.machine.neoseg_displays["neoSeg_0"].lights[5].name, self.machine.lights["neoSeg_0_light_89"].name)
|
|
77
78
|
self.assertEqual(self.machine.neoseg_displays["neoSeg_0"].lights[20].name, self.machine.lights["neoSeg_0_light_103"].name)
|
|
78
79
|
self.assertEqual(self.machine.neoseg_displays["neoSeg_0"].lights[40].name, self.machine.lights["neoSeg_0_light_66"].name)
|
|
79
80
|
self.assertEqual(self.machine.neoseg_displays["neoSeg_0"].lights[60].name, self.machine.lights["neoSeg_0_light_5"].name)
|
|
@@ -81,12 +82,12 @@ class TestLightGroups(MpfTestCase):
|
|
|
81
82
|
self.assertEqual(self.machine.neoseg_displays["neoSeg_0"].lights[100].name, self.machine.lights["neoSeg_0_light_36"].name)
|
|
82
83
|
self.assertEqual(self.machine.neoseg_displays["neoSeg_0"].lights[119].name, self.machine.lights["neoSeg_0_light_35"].name)
|
|
83
84
|
|
|
84
|
-
|
|
85
|
+
def test_config_neoSeg_1(self): # 2 digit
|
|
85
86
|
self.assertEqual("led-0-0-120", self.machine.lights["neoSeg_1_light_0"].hw_drivers["white"][0].number)
|
|
86
87
|
self.assertEqual("led-0-0-120+1", self.machine.lights["neoSeg_1_light_1"].hw_drivers["white"][0].number)
|
|
87
88
|
self.assertEqual("led-0-0-120+2", self.machine.lights["neoSeg_1_light_2"].hw_drivers["white"][0].number)
|
|
88
89
|
self.assertEqual("neoSeg_1_light_29", self.machine.lights["neoSeg_1_light_29"].name)
|
|
89
|
-
|
|
90
|
+
|
|
90
91
|
self.assertEqual(self.machine.neoseg_displays["neoSeg_1"].lights[0].name, self.machine.lights["neoSeg_1_light_5"].name)
|
|
91
92
|
self.assertEqual(self.machine.neoseg_displays["neoSeg_1"].lights[5].name, self.machine.lights["neoSeg_1_light_29"].name)
|
|
92
93
|
self.assertEqual(self.machine.neoseg_displays["neoSeg_1"].lights[10].name, self.machine.lights["neoSeg_1_light_21"].name)
|
|
@@ -94,3 +95,34 @@ class TestLightGroups(MpfTestCase):
|
|
|
94
95
|
self.assertEqual(self.machine.neoseg_displays["neoSeg_1"].lights[20].name, self.machine.lights["neoSeg_1_light_13"].name)
|
|
95
96
|
self.assertEqual(self.machine.neoseg_displays["neoSeg_1"].lights[25].name, self.machine.lights["neoSeg_1_light_15"].name)
|
|
96
97
|
self.assertEqual(self.machine.neoseg_displays["neoSeg_1"].lights[29].name, self.machine.lights["neoSeg_1_light_20"].name)
|
|
98
|
+
|
|
99
|
+
def test_config_neoSeg_2(self): # 8 digit on rgb-ordered channels
|
|
100
|
+
self.assertEqual("led-0-1-0", self.machine.lights["neoSeg_2_light_0"].hw_drivers["white"][0].number)
|
|
101
|
+
self.assertEqual("led-0-1-0+1", self.machine.lights["neoSeg_2_light_1"].hw_drivers["white"][0].number)
|
|
102
|
+
self.assertEqual("neoSeg_2_light_119", self.machine.lights["neoSeg_2_light_119"].name)
|
|
103
|
+
|
|
104
|
+
self.assertEqual(self.machine.neoseg_displays["neoSeg_2"].lights[0].name, self.machine.lights["neoSeg_2_light_95"].name)
|
|
105
|
+
self.assertEqual(self.machine.neoseg_displays["neoSeg_2"].lights[1].name, self.machine.lights["neoSeg_2_light_91"].name)
|
|
106
|
+
self.assertEqual(self.machine.neoseg_displays["neoSeg_2"].lights[2].name, self.machine.lights["neoSeg_2_light_94"].name)
|
|
107
|
+
self.assertEqual(self.machine.neoseg_displays["neoSeg_2"].lights[3].name, self.machine.lights["neoSeg_2_light_81"].name)
|
|
108
|
+
self.assertEqual(self.machine.neoseg_displays["neoSeg_2"].lights[4].name, self.machine.lights["neoSeg_2_light_84"].name)
|
|
109
|
+
self.assertEqual(self.machine.neoseg_displays["neoSeg_2"].lights[5].name, self.machine.lights["neoSeg_2_light_89"].name)
|
|
110
|
+
self.assertEqual(self.machine.neoseg_displays["neoSeg_2"].lights[20].name, self.machine.lights["neoSeg_2_light_102"].name)
|
|
111
|
+
self.assertEqual(self.machine.neoseg_displays["neoSeg_2"].lights[40].name, self.machine.lights["neoSeg_2_light_67"].name)
|
|
112
|
+
self.assertEqual(self.machine.neoseg_displays["neoSeg_2"].lights[60].name, self.machine.lights["neoSeg_2_light_5"].name)
|
|
113
|
+
self.assertEqual(self.machine.neoseg_displays["neoSeg_2"].lights[80].name, self.machine.lights["neoSeg_2_light_12"].name)
|
|
114
|
+
self.assertEqual(self.machine.neoseg_displays["neoSeg_2"].lights[100].name, self.machine.lights["neoSeg_2_light_37"].name)
|
|
115
|
+
self.assertEqual(self.machine.neoseg_displays["neoSeg_2"].lights[119].name, self.machine.lights["neoSeg_2_light_35"].name)
|
|
116
|
+
|
|
117
|
+
def test_config_neoSeg_3(self): # 2 digit on rgb-ordered channels
|
|
118
|
+
self.assertEqual("led-0-1-120", self.machine.lights["neoSeg_3_light_0"].hw_drivers["white"][0].number)
|
|
119
|
+
self.assertEqual("led-0-1-120+1", self.machine.lights["neoSeg_3_light_1"].hw_drivers["white"][0].number)
|
|
120
|
+
self.assertEqual("neoSeg_3_light_29", self.machine.lights["neoSeg_3_light_29"].name)
|
|
121
|
+
|
|
122
|
+
self.assertEqual(self.machine.neoseg_displays["neoSeg_3"].lights[0].name, self.machine.lights["neoSeg_3_light_5"].name)
|
|
123
|
+
self.assertEqual(self.machine.neoseg_displays["neoSeg_3"].lights[5].name, self.machine.lights["neoSeg_3_light_29"].name)
|
|
124
|
+
self.assertEqual(self.machine.neoseg_displays["neoSeg_3"].lights[10].name, self.machine.lights["neoSeg_3_light_22"].name)
|
|
125
|
+
self.assertEqual(self.machine.neoseg_displays["neoSeg_3"].lights[15].name, self.machine.lights["neoSeg_3_light_14"].name)
|
|
126
|
+
self.assertEqual(self.machine.neoseg_displays["neoSeg_3"].lights[20].name, self.machine.lights["neoSeg_3_light_12"].name)
|
|
127
|
+
self.assertEqual(self.machine.neoseg_displays["neoSeg_3"].lights[25].name, self.machine.lights["neoSeg_3_light_16"].name)
|
|
128
|
+
self.assertEqual(self.machine.neoseg_displays["neoSeg_3"].lights[29].name, self.machine.lights["neoSeg_3_light_20"].name)
|
mpf/tests/test_LightNumbering.py
CHANGED
|
@@ -14,8 +14,7 @@ class TestLightNumbering(MpfTestCase):
|
|
|
14
14
|
led1 = self.machine.lights["first"]
|
|
15
15
|
led2 = self.machine.lights["second"]
|
|
16
16
|
led3 = self.machine.lights["third"]
|
|
17
|
-
led4 = self.machine.lights["fourth"]
|
|
18
|
-
|
|
17
|
+
led4 = self.machine.lights["fourth"]
|
|
19
18
|
|
|
20
19
|
self.assertEqual(led1.hw_drivers["green"][0].number,"led-0-0-0")
|
|
21
20
|
self.assertEqual(led1.hw_drivers["red"][0].number,"led-0-0-0+1")
|
|
@@ -35,4 +34,4 @@ class TestLightNumbering(MpfTestCase):
|
|
|
35
34
|
self.assertEqual(led4.hw_drivers["green"][0].number,"led-0-0-0+12")
|
|
36
35
|
self.assertEqual(led4.hw_drivers["red"][0].number,"led-0-0-0+13")
|
|
37
36
|
self.assertEqual(led4.hw_drivers["blue"][0].number,"led-0-0-0+14")
|
|
38
|
-
self.assertEqual(led4.hw_drivers["white"][0].number,"led-0-0-0+15")
|
|
37
|
+
self.assertEqual(led4.hw_drivers["white"][0].number,"led-0-0-0+15")
|
|
@@ -100,17 +100,17 @@ class TestRandomEventPlayerBase():
|
|
|
100
100
|
self.runner.advance_time_and_run()
|
|
101
101
|
self.runner.assertNotEqual(self.prevEvent, self.lastEvent)
|
|
102
102
|
self.runner.assertEqual(self.lastEvent, self.events[expectedIdx])
|
|
103
|
-
|
|
103
|
+
|
|
104
104
|
def _test_conditional_random(self):
|
|
105
105
|
self._reset()
|
|
106
|
-
|
|
106
|
+
|
|
107
107
|
# Only one event is true
|
|
108
108
|
results = list()
|
|
109
109
|
for x in range(RANDOM_RUNS):
|
|
110
110
|
self.runner.post_event("test_{}_conditional_random".format(self.scope))
|
|
111
111
|
self.runner.advance_time_and_run()
|
|
112
112
|
self.assertEqual(RANDOM_RUNS, results.count('event1'))
|
|
113
|
-
|
|
113
|
+
|
|
114
114
|
# Conditional event kwarg is true
|
|
115
115
|
results = list()
|
|
116
116
|
for x in range(RANDOM_RUNS):
|
|
@@ -126,4 +126,4 @@ class TestRandomEventPlayerBase():
|
|
|
126
126
|
self.runner.post_event("test_{}_conditional_random".format(self.scope))
|
|
127
127
|
self.runner.advance_time_and_run()
|
|
128
128
|
self.assertAlmostEqual(RANDOM_RUNS / 2, results.count('event1'), delta=3)
|
|
129
|
-
self.assertAlmostEqual(RANDOM_RUNS / 2, results.count('event4'), delta=3)
|
|
129
|
+
self.assertAlmostEqual(RANDOM_RUNS / 2, results.count('event4'), delta=3)
|
mpf/tests/test_Settings.py
CHANGED
|
@@ -24,3 +24,19 @@ class TestSettings(MpfTestCase):
|
|
|
24
24
|
self.assertEqual("one", self.machine.settings.custom_setting_str)
|
|
25
25
|
self.machine.settings.set_setting_value("custom_setting_str", "zero")
|
|
26
26
|
self.assertEqual("zero", self.machine.settings.custom_setting_str)
|
|
27
|
+
|
|
28
|
+
self.assertEqual(0.1, self.machine.settings.custom_setting_float)
|
|
29
|
+
self.machine.settings.set_setting_value("custom_setting_float", 2.5)
|
|
30
|
+
self.assertEqual(2.5, self.machine.settings.custom_setting_float)
|
|
31
|
+
self.machine.settings.set_setting_value("custom_setting_float", 0)
|
|
32
|
+
self.assertEqual(0, self.machine.settings.custom_setting_float)
|
|
33
|
+
|
|
34
|
+
self.assertEqual(True, self.machine.settings.custom_setting_bool_t)
|
|
35
|
+
self.machine.settings.set_setting_value("custom_setting_bool_t", False)
|
|
36
|
+
self.assertEqual(False, self.machine.settings.custom_setting_bool_t)
|
|
37
|
+
self.machine.settings.set_setting_value("custom_setting_bool_t", True)
|
|
38
|
+
self.assertEqual(True, self.machine.settings.custom_setting_bool_t)
|
|
39
|
+
|
|
40
|
+
self.assertEqual(False, self.machine.settings.custom_setting_bool_f)
|
|
41
|
+
self.machine.settings.set_setting_value("custom_setting_bool_f", True)
|
|
42
|
+
self.assertEqual(True, self.machine.settings.custom_setting_bool_f)
|
|
@@ -5,13 +5,60 @@ from mpf.core.utility_functions import Util
|
|
|
5
5
|
class TestUtil(unittest.TestCase):
|
|
6
6
|
|
|
7
7
|
def test_string_to_ms(self):
|
|
8
|
-
|
|
9
|
-
self.assertEqual(
|
|
10
|
-
self.assertEqual(
|
|
11
|
-
self.assertEqual(
|
|
12
|
-
self.assertEqual(
|
|
13
|
-
self.assertEqual(
|
|
14
|
-
|
|
8
|
+
# Base Units
|
|
9
|
+
self.assertEqual(Util.string_to_ms('1d'), 86400000)
|
|
10
|
+
self.assertEqual(Util.string_to_ms('1h'), 3600000)
|
|
11
|
+
self.assertEqual(Util.string_to_ms('1m'), 60000)
|
|
12
|
+
self.assertEqual(Util.string_to_ms('1s'), 1000)
|
|
13
|
+
self.assertEqual(Util.string_to_ms('1ms'), 1)
|
|
14
|
+
|
|
15
|
+
# Quirky Units
|
|
16
|
+
self.assertEqual(Util.string_to_ms('200msec'), 200)
|
|
17
|
+
self.assertEqual(Util.string_to_ms('200Msec'), 200)
|
|
18
|
+
self.assertEqual(Util.string_to_ms('2sec'), 2000)
|
|
19
|
+
self.assertEqual(Util.string_to_ms('2Sec'), 2000)
|
|
20
|
+
self.assertEqual(Util.string_to_ms('1.5S'), 1500)
|
|
21
|
+
self.assertEqual(Util.string_to_ms('100.0ms'), 100)
|
|
22
|
+
|
|
23
|
+
# Unitless int/floats as strings
|
|
24
|
+
self.assertEqual(Util.string_to_ms('200'), 200)
|
|
25
|
+
self.assertEqual(Util.string_to_ms('100.0'), 100)
|
|
26
|
+
|
|
27
|
+
# Actual int/float
|
|
28
|
+
self.assertEqual(Util.string_to_ms(500), 500)
|
|
29
|
+
self.assertEqual(Util.string_to_ms(1.5), 1)
|
|
30
|
+
|
|
31
|
+
# Strings implying zero
|
|
32
|
+
self.assertEqual(Util.string_to_ms('None'), 0)
|
|
33
|
+
self.assertEqual(Util.string_to_ms('NONE'), 0)
|
|
34
|
+
|
|
35
|
+
# T/F/N native behavior
|
|
36
|
+
self.assertEqual(Util.string_to_ms(True), 1)
|
|
37
|
+
self.assertEqual(Util.string_to_ms(False), 0)
|
|
38
|
+
self.assertEqual(Util.string_to_ms(None), 0)
|
|
39
|
+
|
|
40
|
+
# Whitespace handling
|
|
41
|
+
self.assertEqual(Util.string_to_ms(' 500ms '), 500)
|
|
42
|
+
self.assertEqual(Util.string_to_ms('2s '), 2000)
|
|
43
|
+
|
|
44
|
+
def test_string_to_ms_unhandled(self):
|
|
45
|
+
with self.assertRaises(ValueError):
|
|
46
|
+
Util.string_to_ms('')
|
|
47
|
+
|
|
48
|
+
with self.assertRaises(ValueError):
|
|
49
|
+
Util.string_to_ms('no')
|
|
50
|
+
|
|
51
|
+
with self.assertRaises(ValueError):
|
|
52
|
+
Util.string_to_ms('pinball')
|
|
53
|
+
|
|
54
|
+
with self.assertRaises(ValueError):
|
|
55
|
+
Util.string_to_ms('True')
|
|
56
|
+
|
|
57
|
+
with self.assertRaises(ValueError):
|
|
58
|
+
Util.string_to_ms('200mss')
|
|
59
|
+
|
|
60
|
+
with self.assertRaises(ValueError):
|
|
61
|
+
Util.string_to_ms('2s 1s')
|
|
15
62
|
|
|
16
63
|
def test_keys_to_lower(self):
|
|
17
64
|
inner_dict = dict(key1=1, Key2=2)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mpf
|
|
3
|
-
Version: 0.81.0.
|
|
3
|
+
Version: 0.81.0.dev3
|
|
4
4
|
Summary: The Mission Pinball Framework (MPF)
|
|
5
5
|
Author-email: The Mission Pinball Framework Team <brian@missionpinball.org>
|
|
6
6
|
License: MIT
|
|
@@ -85,7 +85,7 @@ What is Mission Pinball Framework?
|
|
|
85
85
|
Mission Pinball Framework (MPF) is open source, cross-platform software for powering real pinball
|
|
86
86
|
machines. MPF is a community-developed project released under the MIT license. It's supported by volunteers in their spare time.
|
|
87
87
|
|
|
88
|
-
[](https://coveralls.io/github/missionpinball/mpf?branch=dev)
|
|
89
89
|
[](https://github.com/missionpinball/mpf/actions/workflows/run_tests.yml)
|
|
90
90
|
[](https://bestpractices.coreinfrastructure.org/projects/1687)
|
|
91
91
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
mpf/__init__.py,sha256=ycmoyzDc1kSASShp-FwsBhnBrCuVw3uXr58b_MbffIE,73
|
|
2
2
|
mpf/__main__.py,sha256=8eo0swsTb94xUqTnjo7uE0oyz9ita3Pqpk85t2BYs1w,294
|
|
3
|
-
mpf/_version.py,sha256=
|
|
4
|
-
mpf/config_spec.yaml,sha256=
|
|
3
|
+
mpf/_version.py,sha256=YJAG6WLo_IBHGOBCSPa4MjktqgHH2JlWbH9I6E165JU,1789
|
|
4
|
+
mpf/config_spec.yaml,sha256=j2nIb18HQAzE2ePjjKvNx7wwfAkJ1vh3IGi7l74xqUU,71074
|
|
5
5
|
mpf/mpfconfig.yaml,sha256=JZ_X-Uvm1JaXOy6_fxLauzBuCu99aClAQTs4J9I20XA,14757
|
|
6
6
|
mpf/assets/__init__.py,sha256=AhIAlZFZRmGQzlTDD7nfOfrjF1pE82FNhWVnuTb8MFA,58
|
|
7
7
|
mpf/assets/show.py,sha256=lHKhCGmsF1PN52lQ_XnMMCPYNq7On5J9YXm_05P4fQY,31350
|
|
@@ -72,10 +72,10 @@ mpf/core/custom_code.py,sha256=Zoxo8u5l0vwLjbe8D5SoHzcDIPi5mdx4mXbSTK_EojE,891
|
|
|
72
72
|
mpf/core/data_manager.py,sha256=GeeuRpDRL-pEkCBz_2YZOihNZCE0Kv1-2I4ymYnz1kc,4775
|
|
73
73
|
mpf/core/delays.py,sha256=iv9Hyj28897mdGVLv0c6oTRDpupI4PGkuWhC1JDncfg,6709
|
|
74
74
|
mpf/core/device.py,sha256=jnUiuTmTdKryS_rwptipWvEVJ7_OSOPL0Jau1bMMthg,4924
|
|
75
|
-
mpf/core/device_manager.py,sha256=
|
|
75
|
+
mpf/core/device_manager.py,sha256=Nt0DnRO3qmYmxVCs-NlpyIXQ5-fnGxqnCL60-pYtuE4,13668
|
|
76
76
|
mpf/core/device_monitor.py,sha256=EbscdXm0DK7PPwWkJFdCkIWHoIEHOrM3c5aBMIPIojU,4399
|
|
77
77
|
mpf/core/enable_disable_mixin.py,sha256=twqqbA0U1W2ipNmMdDPu4vSeEU47Op3m5Z2HL-xqP-0,5621
|
|
78
|
-
mpf/core/events.py,sha256=
|
|
78
|
+
mpf/core/events.py,sha256=jIpaiDKe2imqiPYC9qLnZdxd3kQk3kVG4ThGZPMwFXg,42260
|
|
79
79
|
mpf/core/file_interface.py,sha256=vGon_Mrj5z6rFohXJJT-smRE9X1iE21nxIfwTeZgJAU,1644
|
|
80
80
|
mpf/core/file_manager.py,sha256=0wP2bE_zI9w1Z9o2tklyjmPt5mDGrPu7sN4Sv_gQon8,4087
|
|
81
81
|
mpf/core/light_controller.py,sha256=vFvKSY3fq6VbgRHpFP1eeCsU0zVvUQ5kf1kNtj7jc_k,4752
|
|
@@ -86,7 +86,7 @@ mpf/core/mode.py,sha256=YlGj7VczEUwD1ESDStkZhKaqxNYctqR5MmFICdSAYDM,23375
|
|
|
86
86
|
mpf/core/mode_controller.py,sha256=7eaK2-LxcVlOX0QK2oefDMNQbNLNSunCwOtPwMAbeGU,14053
|
|
87
87
|
mpf/core/mode_device.py,sha256=C9E9eiKPX9R9RgBDpuwUwuObeYvkkgM7Qs62gONlS2o,2589
|
|
88
88
|
mpf/core/mpf_controller.py,sha256=R_kfMHKD6xYzGEpnIJgxY0GCtqBlxK7dE7ysyE5BxDg,1170
|
|
89
|
-
mpf/core/placeholder_manager.py,sha256=
|
|
89
|
+
mpf/core/placeholder_manager.py,sha256=YmHiZeOp7baPrRhmc8r69SUMO1KKOLbhiCkIJKTThTs,32447
|
|
90
90
|
mpf/core/platform.py,sha256=_9eh9ybl2ep6JNgOaOqpsXjslCorf18NQH1_hwFCEk4,27086
|
|
91
91
|
mpf/core/platform_batch_light_system.py,sha256=YQXNmXJkdP41Gw7PgVk92gnu1eaMn3YdHjDSUAqLoew,7892
|
|
92
92
|
mpf/core/platform_controller.py,sha256=oniy9CgK3ki9ENsMJJqvTF6NA5IxaJWPca2Fj5OLJoc,23725
|
|
@@ -102,7 +102,7 @@ mpf/core/show_controller.py,sha256=C9wtABHGZZ78vyHuFtS0gj6qFaXl_YTiLaGMf2iMMZg,6
|
|
|
102
102
|
mpf/core/switch_controller.py,sha256=xwY7uc0UuixfeYtraUbh-XfpFitNzU3W2E6w-9bsyGc,30662
|
|
103
103
|
mpf/core/system_wide_device.py,sha256=5e_nB3zYZSTjq_wTcbckSw7vxLtW7idIGk44Yby-cXE,431
|
|
104
104
|
mpf/core/text_ui.py,sha256=sQNIqzTpkBS1gtjsQ3qDO_YcyzCuz0X6ViHgLhaH2jY,19088
|
|
105
|
-
mpf/core/utility_functions.py,sha256=
|
|
105
|
+
mpf/core/utility_functions.py,sha256=XILkH65fVA4g0ikCEHoYeTyIT2pNw6WN89HCaE17_G0,30414
|
|
106
106
|
mpf/core/bcp/__init__.py,sha256=MdDZJevywlYvFsmDNEOveGV-IiYMlR11c8bcIflo3zw,47
|
|
107
107
|
mpf/core/bcp/bcp.py,sha256=CVJSVqDhDghJAQcL_hG6eiG9ukzEhGqF7OIq-nvYx0Y,4750
|
|
108
108
|
mpf/core/bcp/bcp_client.py,sha256=o9sCF34Er-_c8aS5llok1bUoN9zk94lEZn8yTvGUpAI,1085
|
|
@@ -135,7 +135,7 @@ mpf/devices/flipper.py,sha256=QZIy0Zvkxhs3wlmp-uTd59awGF46_XuLYhyyTEOGMbg,12209
|
|
|
135
135
|
mpf/devices/hardware_sound_system.py,sha256=XFq8LtyxwlDyCtZYvk-JSOms-CTAnTK4KXGOjeV60MQ,2406
|
|
136
136
|
mpf/devices/kickback.py,sha256=ZkXvGDojfCF0w3Y4-QE6qX963tDDAN6zQ-XZ1bckG3g,748
|
|
137
137
|
mpf/devices/light.py,sha256=pPBMlx0GM9OYiJfXxMmUV0IDUscPYidqEv7BGAnVE-g,36608
|
|
138
|
-
mpf/devices/light_group.py,sha256=
|
|
138
|
+
mpf/devices/light_group.py,sha256=PcujFBLSL1fCSOI7kQSQ-bu87n8ordvGBLbctGwpe4Y,7912
|
|
139
139
|
mpf/devices/logic_blocks.py,sha256=paZV6FOuqSOEq2o4-bKNxKNJCUzbO0SNLDIbp9mnKPQ,24340
|
|
140
140
|
mpf/devices/magnet.py,sha256=GsTTg4Te4OHRz-ZQJxIr8vTj86_VVg2xBXdx6iK88o0,5420
|
|
141
141
|
mpf/devices/motor.py,sha256=014xbRpO6Je-glD1jz9hz7MuafBw_q2aKm2yrPHxZ5E,9728
|
|
@@ -266,7 +266,7 @@ mpf/platforms/virtual.py,sha256=NfyI80ZEnnAspDmy92K7AMjjisQ4KaCmzD7SuplzoWo,2608
|
|
|
266
266
|
mpf/platforms/zedmd.py,sha256=hx0PXXbxJa35vufUgHByDLdpwMbkQaOmrcCz76YvFk4,4139
|
|
267
267
|
mpf/platforms/fast/TODO.md,sha256=WzddBMV7jfNwzkzkYovpmYGX_NMGMQhTL0R7fkKLmIY,3087
|
|
268
268
|
mpf/platforms/fast/__init__.py,sha256=79CsU79usuvjebPggPmvlZg5DrzdQ_nCTHGow-2T_V4,30
|
|
269
|
-
mpf/platforms/fast/fast.py,sha256=
|
|
269
|
+
mpf/platforms/fast/fast.py,sha256=9fD00hzeRpd274TYDoUVIYKpZWA9NCdOM41pIeaIJe0,43553
|
|
270
270
|
mpf/platforms/fast/fast_audio.py,sha256=OpSJZ1bU3qyLP_xWDPOfsGZYkmQHYhOOvcs4V5Ee17c,10281
|
|
271
271
|
mpf/platforms/fast/fast_defines.py,sha256=tDHaJzF4i3PmQDf3Ymn06xC17irDkFsVcmXrrPaADTA,7300
|
|
272
272
|
mpf/platforms/fast/fast_dmd.py,sha256=2wmbj95htWMRQWK2T83E9KCcRT2Q4sfJ5BkKOZQHy2M,662
|
|
@@ -274,7 +274,7 @@ mpf/platforms/fast/fast_driver.py,sha256=7mnn4_6WNjI8auWgIQXCfu7nUV3cA_umfQtH-n3
|
|
|
274
274
|
mpf/platforms/fast/fast_exp_board.py,sha256=SC0h_SYkOsuwYLhOwIlt9U3P1Evy_6kKFr33-RjxTiQ,14904
|
|
275
275
|
mpf/platforms/fast/fast_gi.py,sha256=daV7B7X1ApGkjzbd4YGxJ1AoRgoIC1Fx0UcBRquTzqU,1630
|
|
276
276
|
mpf/platforms/fast/fast_io_board.py,sha256=psNIrZ3GooNejhfXy1Z7_KXtv6jdw6j4vzsj81CjSx0,1275
|
|
277
|
-
mpf/platforms/fast/fast_led.py,sha256=
|
|
277
|
+
mpf/platforms/fast/fast_led.py,sha256=HdgmqOAkGRR4v1bN2WFR8UO608kMDPZ2m5u7EiRmFcc,7605
|
|
278
278
|
mpf/platforms/fast/fast_light.py,sha256=UeUdeRHgfrRpdZDd1KtNlmClkk3C0oRBQJahQHoMZSE,1905
|
|
279
279
|
mpf/platforms/fast/fast_port_detector.py,sha256=jt8L3aIey1HZXiLUnnSSlg3aze2mzp8Cjb7ci_a-QQw,5022
|
|
280
280
|
mpf/platforms/fast/fast_segment_display.py,sha256=DOrzzAWF0ztJHYK2yl2kLx_MUghBEbMVzungeOxSoyo,1739
|
|
@@ -350,7 +350,7 @@ mpf/platforms/trinamics/README,sha256=en6fywA6uVtkVWtnSh99qA7lIGBqtg-57xudNqRG1O
|
|
|
350
350
|
mpf/platforms/trinamics/TMCL.py,sha256=yKzBBHqbFFw8_quIldt2oh1iVtSkX-xChLLlgRa3f2A,30543
|
|
351
351
|
mpf/platforms/trinamics/__init__.py,sha256=w8UfkzSsOjidkOajJVAkRw1AXeFRN77jHPCyVh7YK18,30
|
|
352
352
|
mpf/platforms/virtual_pinball/__init__.py,sha256=YBWkKGkc5GItvkPUFb6LMn5VYDoKH6uAPaQ0CDmNHU4,27
|
|
353
|
-
mpf/platforms/virtual_pinball/virtual_pinball.py,sha256=
|
|
353
|
+
mpf/platforms/virtual_pinball/virtual_pinball.py,sha256=TK5Zse36u98mGXBUebXZLouqZrJLFgg-oTBSPWyTgTI,19163
|
|
354
354
|
mpf/platforms/visual_pinball_engine/__init__.py,sha256=8nICCe2NaXpfTUSTIA8VEVzuYxQaR9U232_9VoHTGNI,27
|
|
355
355
|
mpf/platforms/visual_pinball_engine/generate.py,sha256=2xofapyggJEstxbOsCfdFvVsM7QZxeEgEuAeJAH0qwQ,588
|
|
356
356
|
mpf/platforms/visual_pinball_engine/platform_pb2.py,sha256=5pPiv7pKibQ0GuPCv-CPZubwJUroKqcfXqCST1ofZvg,8781
|
|
@@ -450,7 +450,7 @@ mpf/tests/test_ConfigOldVersion.py,sha256=l1Uf-ZAxHGTbfIwJZRPggearqyD075MzKa7VTd
|
|
|
450
450
|
mpf/tests/test_ConfigPlayers.py,sha256=hiNYK0puN0IE_hPfhVMrYQ5MSryUdI0xNY8ah86afSg,4919
|
|
451
451
|
mpf/tests/test_ConfigProcessor.py,sha256=xzZ-kSooPX-AewZoDwU3sTXSFOPZ_QR5032igowoh3U,2497
|
|
452
452
|
mpf/tests/test_CreditsMode.py,sha256=fR4kCC2HTTA9-bcZ2SNsM925mT9xAPJzA85NN8sHjHQ,17788
|
|
453
|
-
mpf/tests/test_CustomCode.py,sha256=
|
|
453
|
+
mpf/tests/test_CustomCode.py,sha256=xPsQ6Ijs-kKbu05kWBRYm20olNXF8EuLdI21tWeYFrY,648
|
|
454
454
|
mpf/tests/test_DataManager.py,sha256=WOC_AwrtXt5mzBBCqZ4Z2UWyZiP6fjn6I-iURwfYRJA,5350
|
|
455
455
|
mpf/tests/test_Delay.py,sha256=r-ijAjNm4QQ5YRj8iA5ACQ14M2drU-nqir6fqFrBTos,4931
|
|
456
456
|
mpf/tests/test_DeviceCollection.py,sha256=twCg7qAY6CYMw9F3rwxI0NP64gMHe9WhOlhsAgckvXE,1770
|
|
@@ -458,7 +458,7 @@ mpf/tests/test_DeviceDriver.py,sha256=Un6fAW_-wjmjX-GiiwdhuDXz8kTgW5r6jjASh-gdYe
|
|
|
458
458
|
mpf/tests/test_DeviceFlasher.py,sha256=DbBULJDCL2KBsAepLtKXEUwP38Zb0aJVA42ncgNfNog,2201
|
|
459
459
|
mpf/tests/test_DeviceGI.py,sha256=8IlcdwJPf1rMaofHYPBX8m82fwUgystmPyDjBbGicqw,1358
|
|
460
460
|
mpf/tests/test_DeviceLight.py,sha256=LW2XoIBCh8O2U3eSE1eRvYcQD7n2_Fqf7v7fApa1M5c,22534
|
|
461
|
-
mpf/tests/test_DeviceManager.py,sha256=
|
|
461
|
+
mpf/tests/test_DeviceManager.py,sha256=6BnNBgdNywipOwaRDzuqNwCbu_vPgjBGr9JSmTfA9pg,4153
|
|
462
462
|
mpf/tests/test_DeviceMatrixLight.py,sha256=siJaDyaickqj9Vv1Qr5oD9Yf0YrZl-OIZPk1sOfdGiQ,2513
|
|
463
463
|
mpf/tests/test_DigitalOutput.py,sha256=INYIhtJW0OVDsoUdq--4Fb-iHiqcKUfpbXbzV8cEzFQ,1256
|
|
464
464
|
mpf/tests/test_DigitalScoreReels.py,sha256=BrCj_VovVvFi84ewPaFPKL6AO-p9Nnu6LBTkmCZJbLI,1905
|
|
@@ -466,7 +466,7 @@ mpf/tests/test_Diverter.py,sha256=12BHmcDmZz2yEuz4O6RvhHKdWO_SnZ0MdfJHZTuSKhE,26
|
|
|
466
466
|
mpf/tests/test_Dmd.py,sha256=3caBAYOPNynnLzNZzjTvwxJApoiRRzdQlWoStIyEZRo,1332
|
|
467
467
|
mpf/tests/test_DropTargets.py,sha256=BjowOQFA5fTkLR15StArXD_FBZxkrq86dtZ_GHsPNSc,18671
|
|
468
468
|
mpf/tests/test_DualWoundCoil.py,sha256=rBfL56OOnY1ZzBxlZlPUeGsLtf9UlkyAdQRiGd2W28U,1883
|
|
469
|
-
mpf/tests/test_EventManager.py,sha256=
|
|
469
|
+
mpf/tests/test_EventManager.py,sha256=9KLT-zC9MBzhLhCAdKBQfv834ZyPHpEd_utPiOlK8po,37799
|
|
470
470
|
mpf/tests/test_EventPlayer.py,sha256=rV1HK2C6iPvace-aD1zlLkdsUfYCvbBh1eNeVnY0G9M,10354
|
|
471
471
|
mpf/tests/test_ExtraBall.py,sha256=xAt2s8IP4Eh7fAi2kPbKrw7pchpXsfVrLKEaPbcZiCQ,16388
|
|
472
472
|
mpf/tests/test_Fadecandy.py,sha256=y7ZQkdGYmG6WXoi6kKMTxdRYymPhOc9SqHzbrkK9V60,8133
|
|
@@ -474,6 +474,7 @@ mpf/tests/test_Fast.py,sha256=6bbS_z3Dv6KP9GDirL7IhEnzCZ_2JfEkQNGPWDTCUGc,10711
|
|
|
474
474
|
mpf/tests/test_Fast_Audio.py,sha256=50O_tWU350s1WXrre5X0TY9wmwgKRsyKph1Wvikr8Fg,6008
|
|
475
475
|
mpf/tests/test_Fast_Dmd.py,sha256=0htPLOemtTi1EZa7LKVkANaP5RH_HpmknFKBKvePhFI,800
|
|
476
476
|
mpf/tests/test_Fast_Exp.py,sha256=sxUe48fvFdzwqE_C4L7A9G1J5T96HuMWFkA4tzYdd7U,11324
|
|
477
|
+
mpf/tests/test_Fast_Led.py,sha256=c26fRdwODDlsC1M6sue9CHCDyq0pdhr9d4wrUc7QTbs,2240
|
|
477
478
|
mpf/tests/test_Fast_Nano.py,sha256=OcxiGiche1BfTulxchyePdbmJat6tTxVWyugNnAnBzw,33999
|
|
478
479
|
mpf/tests/test_Fast_Neuron.py,sha256=c038-jFbv3f3TF_fPnNhRm-PY55jF_5uXOWwNz2QViA,40225
|
|
479
480
|
mpf/tests/test_Fast_Retro.py,sha256=N-xiiNnMdY-KwB2zFyXhd1u9L0yMAGoPqS-i76bNAeA,19814
|
|
@@ -489,8 +490,8 @@ mpf/tests/test_HighScoreModeWithVars.py,sha256=zGrpvxJbxUteanOttPwmCLqUhPBPmQ-Xc
|
|
|
489
490
|
mpf/tests/test_I2cServoController.py,sha256=osRF2mqK5BcYikb5iHTQVfkFCxN5T5vPlukSOR93lJ8,2493
|
|
490
491
|
mpf/tests/test_InfoLights.py,sha256=ahslOuYGEDKwIyZ4lWU-4iwInHimfN0TnYwTxjqerpA,3370
|
|
491
492
|
mpf/tests/test_Kickback.py,sha256=VQXMmVnfVNgfuKf9UnSjfJKOxcQfzznDqKBDykZIuY0,2119
|
|
492
|
-
mpf/tests/test_LightGroups.py,sha256=
|
|
493
|
-
mpf/tests/test_LightNumbering.py,sha256=
|
|
493
|
+
mpf/tests/test_LightGroups.py,sha256=jIGBCrL63Mi6Oplq8P6pS3qw_WvXWARJ_2VnaXA5LU0,10570
|
|
494
|
+
mpf/tests/test_LightNumbering.py,sha256=Hpgv0e5YbszlZJF_ZNEtcI3_FxssJJTsXdRqPaHZyC8,1701
|
|
494
495
|
mpf/tests/test_LightPlayer.py,sha256=KieLKDzYtNF6XMHnHu1ez3f7AtjnuSh3EeB40buyRNo,15265
|
|
495
496
|
mpf/tests/test_LightPositions.py,sha256=zAbifSeIqEQmNU5gZS3ImXuJY5PtrVW_qhrKjxhmQE0,834
|
|
496
497
|
mpf/tests/test_LightSegmentDisplays.py,sha256=vvTIZQGQhzFOilWcKa_GwIulYyJS1pOHHdVV7dgRWKI,8866
|
|
@@ -523,7 +524,7 @@ mpf/tests/test_PololuMaestro.py,sha256=guKXqbW92Yu-FodrjRyr8Y1dBw6Y8lJvE48LMxpy5
|
|
|
523
524
|
mpf/tests/test_PololuTic.py,sha256=WaKHMazooOok5PcQjaSurScO9FgUjc7aALd8DebQmi4,5033
|
|
524
525
|
mpf/tests/test_QueueEventPlayer.py,sha256=hWX0sScrDgTVPr5q9vwH6lpe5lif6rhjTlc_kv9qGqM,4786
|
|
525
526
|
mpf/tests/test_RGBColor.py,sha256=upiXfSN0rtDpgwFjPCC1jutuRwVcPfgWjYBgT8X7IKM,6517
|
|
526
|
-
mpf/tests/test_RandomEventPlayer.py,sha256=
|
|
527
|
+
mpf/tests/test_RandomEventPlayer.py,sha256=7L46cleZtx-Ka2mu0DaYOKweOl3iv267jmymfUI0mO0,4953
|
|
527
528
|
mpf/tests/test_Randomizer.py,sha256=-LuhPfvDHyX0jkC3LZdZBUO7Dg1iKYSlpfsJwAzsj9o,11692
|
|
528
529
|
mpf/tests/test_Rpi.py,sha256=QhHuLo7SsUtLfU8mNl_3HktGHn0pKLNG5VoT2-jWN0E,5703
|
|
529
530
|
mpf/tests/test_RpiDmd.py,sha256=khG8rV34wZJ0mNSW0CCqNolXonGaBFojk5AUKLDeaT0,1584
|
|
@@ -535,7 +536,7 @@ mpf/tests/test_SequenceShot.py,sha256=cjgz717-fpfzyjr1nKueJncRqgfqXV9KIu5pp0UqbM
|
|
|
535
536
|
mpf/tests/test_ServiceCli.py,sha256=vC5ph_zFMxRx5Jnet7ZY4LRSwACusbYUpie1S4AyxzM,5184
|
|
536
537
|
mpf/tests/test_ServiceMode.py,sha256=Ohh6kcPBaha5xUL3ilay2YO-ZHJQOLdU2HDlJcMimL0,17058
|
|
537
538
|
mpf/tests/test_Servo.py,sha256=Ge5qjUCFUkUgz2LeeN2XiHiD2A4jZnCB-UmlPWuYKCE,2927
|
|
538
|
-
mpf/tests/test_Settings.py,sha256=
|
|
539
|
+
mpf/tests/test_Settings.py,sha256=3MbSiIZnXelcaxqbHRXCP0_8worAWL-BFdKLjNQmkYY,1839
|
|
539
540
|
mpf/tests/test_ShotGroups.py,sha256=mwSa8z2wcg02IeecQCrROZRutsGyb9Y1bjuoP0dzESE,18353
|
|
540
541
|
mpf/tests/test_Shots.py,sha256=tftWsVXkiCXhNJ0EcUd92pDd5f8KHvBxYRnuor7xyRs,37943
|
|
541
542
|
mpf/tests/test_ShowPools.py,sha256=kPdZLW0bqLeji60_kInCFA4ZWY8YyhewH38tZDoP5Mg,2485
|
|
@@ -561,7 +562,7 @@ mpf/tests/test_TooLongExitCountDelay.py,sha256=2qpMlq1lif4xmPn-VXj3vQG5QDufhJz2G
|
|
|
561
562
|
mpf/tests/test_TrinamicsStepRocker.py,sha256=KWUD1JVf4R81f5Du1xyX2oQYOonxyInoItO5QzafscM,3289
|
|
562
563
|
mpf/tests/test_TroughEntranceSwitch.py,sha256=PRCTPxtJ2D4j0zZhY9SXO7SFUkJcUF1zHgE_uRKPsgc,1654
|
|
563
564
|
mpf/tests/test_TwitchClient.py,sha256=2XJNcaNkgsfyZCk0BaVFsJCRus5nSg4hHE6-uHaGil0,6993
|
|
564
|
-
mpf/tests/test_Utility_Functions.py,sha256=
|
|
565
|
+
mpf/tests/test_Utility_Functions.py,sha256=_JTtApKS6_hvmEEKm9vpuzMeTORQCDdfZkZ2PzPvsJo,10230
|
|
565
566
|
mpf/tests/test_VPX.py,sha256=-RhGgzWHCFfv0meRY4jMXDaltmSs5J4b5ba8qkzrtU0,7802
|
|
566
567
|
mpf/tests/test_VariablePlayer.py,sha256=Pe2TihiarrjsL1knzViv52gu5jo5BlurNH8GCczPXvc,10282
|
|
567
568
|
mpf/tests/test_Virtual.py,sha256=hiiUjIVY3bmFZvRKgBTOhVmlV2ASzfML4o8pRhsz3CI,612
|
|
@@ -592,7 +593,7 @@ mpf/tests/machine_files/asset_manager/shows/custom1/show13.yaml,sha256=_P-fejT-l
|
|
|
592
593
|
mpf/tests/machine_files/asset_manager/shows/on_demand/show5.yaml,sha256=_P-fejT-lM_Ri5FA0GP9tAY7ILw9h6oaW4nbt-kbIjw,527
|
|
593
594
|
mpf/tests/machine_files/asset_manager/shows/preload/show4.yaml,sha256=_P-fejT-lM_Ri5FA0GP9tAY7ILw9h6oaW4nbt-kbIjw,527
|
|
594
595
|
mpf/tests/machine_files/asset_manager/shows/preload/subfolder/show4b.yaml,sha256=_P-fejT-lM_Ri5FA0GP9tAY7ILw9h6oaW4nbt-kbIjw,527
|
|
595
|
-
mpf/tests/machine_files/auditor/config/config.yaml,sha256=
|
|
596
|
+
mpf/tests/machine_files/auditor/config/config.yaml,sha256=Ao7PrPMiBrRXk0WEdp3-0TsSKZ4_PtVnsE_4vsqtD0s,387
|
|
596
597
|
mpf/tests/machine_files/auditor/modes/base/config/base.yaml,sha256=HcnCQGbaVT6i9NJwUNL5fWj36Jhcnl7zykghnPGrY6A,261
|
|
597
598
|
mpf/tests/machine_files/autofire/config/config.yaml,sha256=7LL4RB24kSi7eQICGRdWbRxFmLIWKJZ7DSEHuZYyAFs,1487
|
|
598
599
|
mpf/tests/machine_files/ball_controller/config/config.yaml,sha256=a6DMjD4_Xts1KJ3UBDDtDgbybYKdDaEHjOHN6feYdyE,1068
|
|
@@ -697,7 +698,7 @@ mpf/tests/machine_files/credits/config/config_freeplay.yaml,sha256=6JMbjmjsS8yK8
|
|
|
697
698
|
mpf/tests/machine_files/credits/config/config_inhibit.yaml,sha256=MYAjgeSHE6iV6rh1YV4a3-WEI_5qv-3QrYYn_35YOkY,367
|
|
698
699
|
mpf/tests/machine_files/credits/modes/credits/config/config.yaml,sha256=N9dGGiwQH67CsEhAtWE31OwumVGyoztTVzaGkRXs9zY,107
|
|
699
700
|
mpf/tests/machine_files/custom_code/code/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
700
|
-
mpf/tests/machine_files/custom_code/code/test_code.py,sha256=
|
|
701
|
+
mpf/tests/machine_files/custom_code/code/test_code.py,sha256=KHrkCVTVhvoW_uCmhA2JoI6XcTXneLCKLSVxg90Dk_E,490
|
|
701
702
|
mpf/tests/machine_files/custom_code/config/config.yaml,sha256=roJzS_8FhnvK1UzWG9DyqPpG0N1NMmZm7PtbQSR4az8,380
|
|
702
703
|
mpf/tests/machine_files/data_manager/config/config.yaml,sha256=I0aiEhNSdlLMRlJKtcbAgPV_48725L7lDWr3wbqjx70,164
|
|
703
704
|
mpf/tests/machine_files/device/config/coils.yaml,sha256=HlzikHgj_AGzGp0oll3IITEkRONMEkKN8gZP8cq67zQ,533
|
|
@@ -726,8 +727,8 @@ mpf/tests/machine_files/dmd/config/testRgbDmd.yaml,sha256=3bgVH7UjPRHLZbYw1q_n43
|
|
|
726
727
|
mpf/tests/machine_files/drop_targets/config/test_drop_targets.yaml,sha256=58vBTtYMhdwkjW9TpJDWQQWFdjkRcYUyKlK3BXQeXFE,1710
|
|
727
728
|
mpf/tests/machine_files/drop_targets/config/test_multiple_drop_resets_on_startup.yaml,sha256=ht-FfB-8ZjujnGSWcW9DN4F9zKIcp82AQaj90ElYNSU,337
|
|
728
729
|
mpf/tests/machine_files/drop_targets/modes/mode1/config/mode1.yaml,sha256=znSa7PmrvBTspwQ34o7fSlCl3n5NtvLWizI-3_0Su4Q,186
|
|
729
|
-
mpf/tests/machine_files/event_manager/config/test_event_manager.yaml,sha256=
|
|
730
|
-
mpf/tests/machine_files/event_manager/modes/game_mode/config/game_mode.yaml,sha256=
|
|
730
|
+
mpf/tests/machine_files/event_manager/config/test_event_manager.yaml,sha256=r0bFMKucXaxG68fqCThIGBCPXSUWHRNaktlnx0RpX88,582
|
|
731
|
+
mpf/tests/machine_files/event_manager/modes/game_mode/config/game_mode.yaml,sha256=Wcvh7mSDILzKTrv7Lh3IPjtlCAnFgs7AsC2TGu9lBr4,421
|
|
731
732
|
mpf/tests/machine_files/event_manager/modes/test_mode/config/test_mode.yaml,sha256=8_LOBAMFabPcT1u-fncfQ0NsPW0UatSsUxquU4FOgVA,552
|
|
732
733
|
mpf/tests/machine_files/event_players/config/test_event_player.yaml,sha256=oxWJElrLOfctXEXz_cDyabFYpJgfyh9qCNM3lYHGCYY,2092
|
|
733
734
|
mpf/tests/machine_files/event_players/config/test_queue_event_player.yaml,sha256=-guARDhqONBsw__GRqBKwxwAufnehQrBz7YK0sQYWwg,414
|
|
@@ -763,7 +764,7 @@ mpf/tests/machine_files/kickback/config/config.yaml,sha256=VTfx491DKfYxcDdCnB2th
|
|
|
763
764
|
mpf/tests/machine_files/light/config/light.yaml,sha256=4NjJ-yL1O9o_jNYO6NGy6DTt2BGzDMs86usnrBDVJ0o,964
|
|
764
765
|
mpf/tests/machine_files/light/config/light_autonumber.yaml,sha256=ZAwGXze2wlk0FFBKgTAxz_beRFpItKSNRrwabX5dr4I,213
|
|
765
766
|
mpf/tests/machine_files/light/config/light_default_color_correction.yaml,sha256=h7ZSv7uSJRG57hpxUqy7SMX4VqWftBk0b12YjuZ4fu0,309
|
|
766
|
-
mpf/tests/machine_files/light/config/light_groups.yaml,sha256=
|
|
767
|
+
mpf/tests/machine_files/light/config/light_groups.yaml,sha256=GEwMtLaa3OXUlkOMh4oCssYnBXz2q9-CZgahZJE6rvY,1071
|
|
767
768
|
mpf/tests/machine_files/light/config/lights_on_drivers.yaml,sha256=Wc6GPnlAdL8D9H58SZQtjDY9Pc4c0Bz7ASMvafAwrPo,215
|
|
768
769
|
mpf/tests/machine_files/light/config/matrix_lights.yaml,sha256=ntmFDNeNg8XLopCeyWwD3quh1qm7cxyylrK8zrFDBgs,178
|
|
769
770
|
mpf/tests/machine_files/light_player/config/light_player.yaml,sha256=HhgenUx6hk65xibQwjXb08LGulu5fi_b25otcYU50DY,1177
|
|
@@ -881,9 +882,9 @@ mpf/tests/machine_files/segment_display/config/game.yaml,sha256=xCGQxOFaqm1mSl-K
|
|
|
881
882
|
mpf/tests/machine_files/segment_display/modes/mode1/config/mode1.yaml,sha256=30Xo3grYQG3zypICRnb1mbz8mY78BDweMcajpINhkC0,173
|
|
882
883
|
mpf/tests/machine_files/sequence_shot/config/config.yaml,sha256=ate99LsEy9czRLDJSyC1PFxxvxC15TsdlQ1xr-ZIiNA,2028
|
|
883
884
|
mpf/tests/machine_files/sequence_shot/modes/mode1/config/mode1.yaml,sha256=jufw8bwnOoPtAwyGpouWNnmcpqvWxflb9zWYGWZcKxg,489
|
|
884
|
-
mpf/tests/machine_files/service_mode/config/config.yaml,sha256=
|
|
885
|
+
mpf/tests/machine_files/service_mode/config/config.yaml,sha256=3tLwdjr6YR_vezJywbEAZvRj9hWF4F3glzl-vQlSYCw,1416
|
|
885
886
|
mpf/tests/machine_files/servo/config/config.yaml,sha256=iJXZsC5xVrQnRkwF9adAxsuiBGiVBqGA4gSpFlKAFIQ,481
|
|
886
|
-
mpf/tests/machine_files/settings/config/config.yaml,sha256=
|
|
887
|
+
mpf/tests/machine_files/settings/config/config.yaml,sha256=wqNkyp6lIGb5ds9OFKbTOl2yLJmnxIEo9J4Cm5Pbq-w,1064
|
|
887
888
|
mpf/tests/machine_files/shots/config/test_shot_group_rotate_with_exclude.yaml,sha256=rDXihcEySJErepBjUEewpaPDm4xoVGPZ1pcZv3SYin8,209
|
|
888
889
|
mpf/tests/machine_files/shots/config/test_shot_groups.yaml,sha256=pT808F42hPuEquQxRfpiClVZU336ZKYIU9GKCoP1wjQ,1678
|
|
889
890
|
mpf/tests/machine_files/shots/config/test_shots.yaml,sha256=7nXSIgBmq75TumSfXAWlul5EzIxwCg_d-oYtA8Zbkjs,2461
|
|
@@ -960,10 +961,10 @@ mpf/tests/regression_tests/shots_with_token_in_profile_and_shot.yaml,sha256=uyRp
|
|
|
960
961
|
mpf/tests/regression_tests/show_player_subscriptions.yaml,sha256=JJJ72Kmc6p4dQB9NA78DcR8JEbHTpurclYUCpTX8Cug,2206
|
|
961
962
|
mpf/wire/base.py,sha256=6AsVN7gxAdSP40T1SIABplUbiYRqOp37x-2w_CE8fcQ,11581
|
|
962
963
|
mpf/wire/fast.py,sha256=XmqBuwM1CZ102LQXNy26SqTy75HuOuCmfkQA9Xc2MiM,20521
|
|
963
|
-
mpf-0.81.0.
|
|
964
|
-
mpf-0.81.0.
|
|
965
|
-
mpf-0.81.0.
|
|
966
|
-
mpf-0.81.0.
|
|
967
|
-
mpf-0.81.0.
|
|
968
|
-
mpf-0.81.0.
|
|
969
|
-
mpf-0.81.0.
|
|
964
|
+
mpf-0.81.0.dev3.dist-info/licenses/AUTHORS.md,sha256=izUqN5WUC6FV2pUURPUiD308hYo_JREH_ENeTsEstLg,1445
|
|
965
|
+
mpf-0.81.0.dev3.dist-info/licenses/LICENSE.md,sha256=dMfwSWLbBdRZPIahHwQoMq_dxiZxOxVRLiTZ6GE_5wo,1119
|
|
966
|
+
mpf-0.81.0.dev3.dist-info/METADATA,sha256=haS2MRSNrSOH-fSfOUwTQQHGzpnACGP6VeUiWETzw_0,6013
|
|
967
|
+
mpf-0.81.0.dev3.dist-info/WHEEL,sha256=K260EYznzXsJYBQGqmI8VTxEdiZYNvDZwW9cBh9-_MA,91
|
|
968
|
+
mpf-0.81.0.dev3.dist-info/entry_points.txt,sha256=FMGV1EnYmb_MOBOb2nMg-kpgMbqk5HItDSA1rkkjnAM,59
|
|
969
|
+
mpf-0.81.0.dev3.dist-info/top_level.txt,sha256=K6To2MlFIMFjYIQIVaql2hOPCpu_yzao6_OotT3n5pw,4
|
|
970
|
+
mpf-0.81.0.dev3.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|