예제 #1
0
    def _migrate_light_scripts(self):
        if 'light_scripts' not in self.fc:
            return

        YamlInterface.rename_key('light_scripts', 'shows', self.fc, self.log)

        for show_contents in self.fc['shows'].values():
            self._convert_tocks_to_time(show_contents)

            for step in show_contents:

                if 'color' in step:
                    step['color'] = self._get_color(step['color'])
                    if len(str(step['color'])) > 2:
                        YamlInterface.rename_key('color', '(leds)', step,
                                                 self.log)
                        step['leds'] = CommentedMap()
                        YamlInterface.copy_with_comments(step, '(leds)',
                                                         step['leds'], '(leds)', True, self.log)
                    else:
                        YamlInterface.rename_key('color', '(lights)', step,
                                                 self.log)
                        step['lights'] = CommentedMap()
                        YamlInterface.copy_with_comments(step, '(lights)',
                                                         step['lights'], '(lights)', True, self.log)
예제 #2
0
    def _remove_key(self, first_key, key):
        # actually removes the key from the dict, with nested dicts only
        # (no lists in there)

        if not key:  # single item
            if first_key in self.fc:

                YamlInterface.del_key_with_comments(self.fc, first_key,
                                                    self.log)
                return True

        try:
            if self.fc[first_key].mlget(key, list_ok=True) is not None:
                # mlget just verifies with a nested dict / list
                # index that the key is found.
                final_key = key.pop(-1)
                dic = self.fc[first_key]

                while key:
                    # Loop to get the parent container of the
                    # lowest level key
                    dic = dic[key.pop(0)]

                YamlInterface.del_key_with_comments(dic, final_key, self.log)
                return True
        except (KeyError, IndexError):
            pass

        return False
예제 #3
0
    def _create_window_slide(self):
        if 'window' in self.fc and 'elements' in self.fc['window']:
            elements = self.fc['window']['elements']

            if isinstance(elements, dict):
                elements = [elements]

            if 'slides' not in self.fc:
                self.log.debug("Creating 'slides:' section")
                self.fc['slides'] = CommentedMap()

            slide_name = V4Migrator._get_slide_name('window')

            self.log.debug("Creating slide: %s with %s display widget(s) from "
                           "the old window: config", slide_name, len(elements))

            self.log.debug("Adding '%s' slide", slide_name)
            self.fc['slides'][slide_name] = CommentedMap()
            self.fc['slides'][slide_name] = (
                self._migrate_elements(elements, 'window'))

            YamlInterface.del_key_with_comments(self.fc['window'], 'elements',
                                                self.log)

            if 'slide_player' not in self.fc:
                self.fc['slide_player'] = CommentedMap()
                self.log.debug("Creating slide_player: section")

            self.log.debug("Creating slide_player:machine_reset_phase3: entry"
                           "to show slide '%s' on boot", slide_name)
            self.fc['slide_player']['machine_reset_phase_3'] = CommentedMap()
            self.fc['slide_player']['machine_reset_phase_3'][slide_name] = \
                CommentedMap()
            self.fc['slide_player']['machine_reset_phase_3'][slide_name][
                'target'] = 'window'
예제 #4
0
    def _migrate_show_file(self):
        self.log.debug("Migrating show file: %s", self.file_name)

        show_name_stub = os.path.splitext(os.path.split(self.file_name)[1])[0]

        self._add_show_version()

        # Convert tocks to time
        self._convert_tocks_to_time(self.fc)

        # migrate the components in each step
        self.log.debug("Converting settings for each show step")

        slide_num = 0

        for i, step in enumerate(self.fc):

            self._remove_tags(step)

            if 'display' in step:
                self.log.debug("Show step %s: Converting 'display' section",
                               i + 1)

                found_transition = False
                for widget in step['display']:
                    if 'transition' in widget:
                        found_transition = True
                        break

                if found_transition:
                    step['display'] = CommentedMap(
                        widgets=self._migrate_elements(step['display']))

                    for widget in step['display']['widgets']:

                        self._convert_tokens(widget)

                        if 'transition' in widget:
                            YamlInterface.copy_with_comments(
                                widget, 'transition', step['display'],
                                'transition', True, self.log)

                else:
                    step['display'] = self._migrate_elements(step['display'])
                    self._convert_tokens(step['display'])

                YamlInterface.rename_key('display', 'slides', step)

                slide_num += 1
                old_slides = step['slides']
                step['slides'] = CommentedMap()
                step['slides']['{}_slide_{}'.format(show_name_stub,
                                                    slide_num)] = old_slides

        return True
예제 #5
0
    def _convert_show_call_to_tokens(cls, settings):
        token_list = ['light', 'lights', 'leds', 'led']

        for token in token_list:
            if token in settings:
                if 'show_tokens' not in settings:
                    settings['show_tokens'] = CommentedMap()

                YamlInterface.copy_with_comments(settings, token,
                                                 settings['show_tokens'],
                                                 token, True)
예제 #6
0
    def _recursive_rename(self, old, new, target):
        if isinstance(target, list):
            for item in target:
                self._recursive_rename(old, new, item)
        elif isinstance(target, dict):

            if old in target:
                YamlInterface.rename_key(old, new, target, self.log)

            for item in target.values():
                self._recursive_rename(old, new, item)
예제 #7
0
    def _migrate_shot_profiles(self):
        if 'shot_profiles' not in self.fc:
            return

        for settings in self.fc['shot_profiles'].values():
            if 'states' in settings:
                for dummy_i, state_settings in enumerate(settings['states']):
                    if 'loops' in state_settings and state_settings['loops']:
                        state_settings['loops'] = -1
                    YamlInterface.rename_key('light_script', 'show',
                                             state_settings)
예제 #8
0
    def _remove_tags(self, dic):
        found = False
        for v in dic.values():
            if isinstance(v, dict):
                for k1 in v.keys():
                    if k1.startswith('tag|'):
                        YamlInterface.rename_key(k1, k1.strip('tag|'), v)
                        found = True
                        break

        if found:
            self._remove_tags(dic)
예제 #9
0
    def _migrate_mode_timers(self):
        if 'timers' in self.fc:
            for timer_name in self.fc['timers']:
                if "start_paused" in self.fc['timers'][timer_name]:
                    if not self.fc['timers'][timer_name]['start_paused']:
                        self.fc['timers'][timer_name]["start_running"] = True
                    elif ("start_running" not in self.fc['timers'][timer_name] or
                            not self.fc['timers'][timer_name]["start_running"]):
                        self.fc['timers'][timer_name]["start_running"] = False
                    else:
                        raise ValueError("Both start_paused and start_running are true. This is impossible")

                    YamlInterface.del_key_with_comments(self.fc['timers'][timer_name], 'start_paused', self.log)
예제 #10
0
    def _migrate_fonts(self):
        # Fonts to widget_styles was already renamed, now update contents
        if 'widget_styles' in self.fc:
            self.log.debug("Converting widget_styles: from the old fonts: "
                           "settings")
            for settings in self.fc['widget_styles'].values():
                YamlInterface.rename_key('size', 'font_size', settings,
                                         self.log)
                YamlInterface.rename_key('file', 'font_name', settings,
                                         self.log)
                YamlInterface.rename_key('crop_top', 'adjust_top', settings,
                                         self.log)
                YamlInterface.rename_key('crop_bottom', 'adjust_bottom',
                                         settings, self.log)

                if 'font_name' in settings:
                    self.log.debug("Converting font_name: from file to name")
                    settings['font_name'] = os.path.splitext(
                        settings['font_name'])[0]

        if self.base_name == V4Migrator.MAIN_CONFIG_FILE:
            if 'widget_styles' not in self.fc:
                self.log.debug("Creating old default font settings as "
                               "widget_styles: section")
                self.fc['widget_styles'] = self._get_old_default_widget_styles()

            else:
                for k, v in self._get_old_default_widget_styles().items():
                    if k not in self.fc['widget_styles']:
                        self.fc['widget_styles'][k] = v

                    self.log.debug("Merging old built-in font settings '%s' "
                                   "into widget_styles: section", k)
예제 #11
0
    def _migrate_animation_assets(self):
        if 'animations' in self.fc:
            self.log.debug("Converting assets:animations to assets:images")
            if 'images' in self.fc:
                self.log.debug("Merging animations: into current "
                               "asset:images:")

                YamlInterface.copy_with_comments(self.fc, 'animations',
                                                 self.fc, 'images',
                                                 True, self.log)

            else:
                YamlInterface.rename_key('animations', 'images', self.fc,
                                         self.log)
예제 #12
0
    def send_slide_to_mc(self, value):
        del value

        try:
            settings = YamlInterface.process(self.slide_player_code.text)
        except Exception as e:
            msg = str(e).replace('"', '\n')
            Popup(title='Error in your config',
                  content=Label(text=msg, size=(750, 350)),
                  size_hint=(None, None),
                  size=(Window.width, 400)).open()
            return

        try:
            settings = (self.slide_player.validate_config_entry(
                settings, 'slides'))
        except Exception as e:
            msg = str(e).replace('"', '\n')
            Popup(title='Error in your config',
                  content=Label(text=msg, size=(750, 350)),
                  size_hint=(None, None),
                  size=(Window.width, 400)).open()
            return

        if self._initialized:
            self.slide_player.clear_context('imc')
        else:
            self._initialized = True
        self.slide_player.play(settings, 'imc', 100)
        self.clock.loop.run_until_complete(
            asyncio.sleep(.1, loop=self.clock.loop))
예제 #13
0
    def _migrate_animation(self, element):
        self.log.debug("Converting 'animation' display_element to animated "
                       "'image' widget")
        element['type'] = 'image'
        YamlInterface.rename_key('play_now', 'auto_play', element, self.log)
        YamlInterface.rename_key('animation', 'image', element, self.log)

        element.pop('drop_frames', None)

        self.log.debug('Converting animated image loops: setting')
        if element['loops']:
            element['loops'] = -1
        else:
            element['loops'] = 0

        return element
예제 #14
0
    def load_config_spec(self):
        """Load config spec."""
        if ConfigValidator.class_cache:
            self.config_spec = ConfigValidator.class_cache
            return

        cache_file = os.path.join(self.get_cache_dir(),
                                  "config_spec.mpf_cache")
        config_spec_file = os.path.abspath(
            os.path.join(mpf.core.__path__[0], os.pardir, "config_spec.yaml"))
        if os.path.isfile(cache_file) and os.path.getmtime(
                cache_file) >= os.path.getmtime(config_spec_file):
            try:
                with open(cache_file, 'rb') as f:
                    self.config_spec = pickle.load(f)  # nosec
                    ConfigValidator.class_cache = deepcopy(self.config_spec)
                    return
            except Exception:  # noqa
                pass

        with open(config_spec_file, 'rb') as f:
            config_str = f.read()

        config = YamlInterface.process(config_str)
        config = self._process_config_spec(config, "root")

        self.config_spec = config
        self.machine.load_external_platform_config_specs()

        with open(cache_file, 'wb') as f:
            pickle.dump(config, f, protocol=4)
            self.log.info('Config spec file cache created: %s', cache_file)

        ConfigValidator.class_cache = deepcopy(self.config_spec)
예제 #15
0
    def __init__(self, uri, config_type, source=None, version=None, local=True, extra_sys_path=None):
        self.uri = uri
        self.version = version
        self.path = uris.to_fs_path(uri)
        self.filename = os.path.basename(self.path)

        self._local = local
        self._source = source
        self._extra_sys_path = extra_sys_path or []
        self._config_simple = {}
        self._config_roundtrip = {}
        self._last_config_simple = {}
        self._last_config_roundtrip = {}
        self._loader_roundtrip = YamlRoundtrip()
        self._loader_simple = YamlInterface()
        self.config_type = config_type
예제 #16
0
    def test_yaml_patches(self):

        # tests our patches to the yaml processor

        config = """

str_1: +1
str_2: 032
str_3: on
str_4: off
str_5: 123e45
bool_1: yes
bool_2: no
bool_3: true
bool_4: false
str_6: hi
int_1: 123
float_1: 1.0

        """

        parsed_config = YamlInterface.process(config, True)

        for k, v in parsed_config.items():
            if not type(v) is eval(k.split('_')[0]):
                raise AssertionError('YAML value "{}" is {}, not {}'.format(
                    v, type(v), eval(k.split('_')[0])))
예제 #17
0
 def load_mode_config_spec(cls, mode_string, config_spec):
     """Load config specs for a mode."""
     if '_mode_settings' not in cls.config_spec:
         cls.config_spec['_mode_settings'] = {}
     if mode_string not in cls.config_spec['_mode_settings']:
         cls.config_spec['_mode_settings'][
             mode_string] = YamlInterface.process(config_spec)
예제 #18
0
 def load_mode_config_spec(self, mode_string, config_spec):
     """Load config specs for a mode."""
     if '_mode_settings' not in self.config_spec:
         self.config_spec['_mode_settings'] = {}
     if mode_string not in self.config_spec['_mode_settings']:
         config = YamlInterface.process(config_spec)
         self.config_spec['_mode_settings'][mode_string] = self._process_config_spec(config, mode_string)
예제 #19
0
    def _migrate_switches(self):
        if 'switches' not in self.fc:
            return

        for switch_settings in self.fc['switches'].values():
            YamlInterface.rename_key('activation_events',
                                     'events_when_activated',
                                     switch_settings, self.log)
            YamlInterface.rename_key('deactivation_events',
                                     'events_when_deactivated',
                                     switch_settings, self.log)

            if 'debounce' in switch_settings:
                if switch_settings['debounce']:
                    switch_settings['debounce'] = 'normal'
                else:
                    switch_settings['debounce'] = 'quick'
예제 #20
0
    def _do_rename(self):
        for rename in self.renames:

            if len(rename['old']) > 1:  # searching for nested key

                found_section = Util.get_from_dict(self.fc, rename['old'][:-1])

                if not found_section:
                    continue

                self.log.debug('Renaming key: %s: -> %s:',
                               ':'.join(rename['old']), rename['new'])
                YamlInterface.rename_key(rename['old'][-1], rename['new'],
                                         found_section)

            else:  # searching for a single key anywhere
                self._recursive_rename(rename['old'][0], rename['new'],
                                       self.fc)
예제 #21
0
    def load_external_platform_config_specs(self, config):
        """Load config spec for external platforms."""
        for platform_entry in iter_entry_points(group='mpf.platforms'):
            config_spec = platform_entry.load().get_config_spec()

            if config_spec:
                # add specific config spec if platform has any
                config[config_spec[1]] = self._process_config_spec(
                    YamlInterface.process(config_spec[0]), config_spec[1])
        return config
예제 #22
0
    def _do_lowercase(self, dic=None):
        # recurcisely converts all keys in dicts and nested dicts
        if not dic:
            dic = self.fc

        key_list = list(dic.keys())

        for key in key_list:
            try:
                YamlInterface.rename_key(key, key.lower(), dic, self.log)
            except AttributeError:
                pass

            try:
                if isinstance(dic[key.lower()], dict):
                    self._do_lowercase(dic[key.lower()])
            except AttributeError:
                if isinstance(dic[key], dict):
                    self._do_lowercase(dic[key])
예제 #23
0
    def load_show_from_disk(self):
        """Load show from disk."""
        show_version = YamlInterface.get_show_file_version(self.file)

        if show_version != int(__show_version__):  # pragma: no cover
            raise ValueError("Show file {} cannot be loaded. MPF v{} requires "
                             "#show_version={}".format(self.file, __version__,
                                                       __show_version__))

        return FileManager.load(self.file)
예제 #24
0
    def load_device_config_specs(config_spec, machine_config):
        """Load device config specs."""
        for device_type in machine_config['mpf']['device_modules'].values():
            device_cls = Util.string_to_class(device_type)      # type: Device
            if device_cls.get_config_spec():
                # add specific config spec if device has any
                config_spec[device_cls.config_section] = ConfigSpecLoader.process_config_spec(
                    YamlInterface.process(device_cls.get_config_spec()),
                    device_cls.config_section)

        return config_spec
예제 #25
0
    def _convert_tocks_to_time(self, show_steps):
        self.log.debug('Converting "tocks:" to "time:" and cascading entries '
                       'to the next step (since time: is for the current '
                       'step versus tocks: being for the previous step)')
        previous_tocks = 0
        for i, step in enumerate(show_steps):
            previous_tocks = step['tocks']

            if not i:
                step['tocks'] = 0
            else:
                step['tocks'] = '+{}'.format(previous_tocks)

            YamlInterface.rename_key('tocks', 'time', step, self.log)

        if len(show_steps) > 1:
            show_steps.append(CommentedMap())
            show_steps[-1]['time'] = '+{}'.format(previous_tocks)

        return show_steps
예제 #26
0
    def load_device_config_specs(self, config_spec, machine_config):
        """Load device config specs."""
        for device_type in machine_config['mpf']['device_modules']:
            device_cls = Util.string_to_class(device_type)
            if device_cls.get_config_spec():
                # add specific config spec if device has any
                config_spec[device_cls.config_section] = self._process_config_spec(
                    YamlInterface.process(device_cls.get_config_spec()),
                    device_cls.config_section)

        return config_spec
예제 #27
0
 def load_mode_config_spec(self, mode_string, config_spec):
     """Load config specs for a mode."""
     if '_mode_settings' not in self.config_spec:
         self.config_spec['_mode_settings'] = {}
     if mode_string not in self.config_spec['_mode_settings']:
         if isinstance(config_spec, dict):
             self.config_spec['_mode_settings'][mode_string] = \
                 ConfigSpecLoader.process_config_spec(config_spec, mode_string)
         else:
             config = YamlInterface.process(config_spec)
             self.config_spec['_mode_settings'][mode_string] = \
                 ConfigSpecLoader.process_config_spec(config, mode_string)
예제 #28
0
    def _migrate_assets(self, section_name):
        if section_name in self.fc:

            keys_to_keep = set(self.mpf_config_spec[section_name].keys())
            empty_entries = set()

            self.log.debug("Converting %s: section", section_name)

            if self.fc[section_name]:

                for name, settings in self.fc[section_name].items():
                    self.log.debug("Converting %s:%s:", section_name, name)
                    if isinstance(settings, dict):
                        keys = set(settings.keys())
                        keys_to_remove = keys - keys_to_keep

                        for key in keys_to_remove:
                            YamlInterface.del_key_with_comments(settings, key,
                                                                self.log)

                    if not settings:
                        self.log.debug("%s:%s: is now empty. Will remove it.",
                                       section_name, name)
                        empty_entries.add(name)

                for name in empty_entries:
                    YamlInterface.del_key_with_comments(self.fc[section_name],
                                                        name, self.log)

            if len(self.fc[section_name]) == 0:
                self.log.debug("%s: is now empty. Will remove it.",
                               section_name)
                YamlInterface.del_key_with_comments(self.fc, section_name,
                                                    self.log)
예제 #29
0
    def _migrate_element_y_and_anchor(self, element, display, height):
        if 'y' in element:
            old_y = element['y']
            element['y'] *= -1
        else:
            old_y = 'None'

        if 'anchor_y' not in element and 'y' in element:
            element['anchor_y'] = 'top'

        try:
            if 'anchor_y' not in element or element['anchor_y'] == 'bottom':
                element['y'] = self._format_anchor_and_value('bottom', element['y'])
            elif element['anchor_y'] in ('middle', 'center'):
                element['y'] = self._format_anchor_and_value('middle', element['y'])
            elif element['anchor_y'] == 'top':
                element['y'] = self._format_anchor_and_value('top', element['y'])

            self.log.debug("Changing y:%s to y:%s (Based on anchor_y:%s"
                           "and %s height:%s)", old_y, element['y'],
                           element['anchor_y'], display, height)

        except KeyError:
            pass

        try:
            if element['anchor_y'] in ('middle', 'center'):
                YamlInterface.del_key_with_comments(element, 'anchor_y',
                                                    self.log)

        except KeyError:
            pass

        if ('anchor_y' in element and 'y' not in element and
                element['anchor_y'] != 'middle'):
            element['y'] = element['anchor_y']
        return element
예제 #30
0
    def _migrate_element_x_and_anchor(self, element, display, width):
        if 'x' in element:
            old_x = element['x']
        else:
            old_x = 'None'

        if 'anchor_x' not in element and 'x' in element:
            element['anchor_x'] = 'left'

        try:
            if 'anchor_x' not in element or element['anchor_x'] == 'left':
                element['x'] = self._format_anchor_and_value('left', element['x'])

            elif element['anchor_x'] in ('middle', 'center'):
                element['x'] = self._format_anchor_and_value('center', element['x'])

            elif element['anchor_x'] == 'right':
                element['x'] = self._format_anchor_and_value('right', element['x'])

            self.log.debug("Changing x:%s to x:%s (Based on anchor_x:%s"
                           "and %s width:%s)", old_x, element['x'],
                           element['anchor_x'], display, width)

        except KeyError:
            pass

        try:
            if element['anchor_x'] in ('middle', 'center'):
                YamlInterface.del_key_with_comments(element, 'anchor_x',
                                                    self.log)
        except KeyError:
            pass

        if ('anchor_x' in element and 'x' not in element and
                element['anchor_x'] != 'center'):
            element['x'] = element['anchor_x']
        return element