tools/tryselect/preset.py
author Mike Hommey <mh+mozilla@glandium.org>
Wed, 20 Mar 2019 22:46:10 +0000
changeset 465312 22c1c1ddce35f15335233c4c07f3590a19448fe2
parent 461996 74de0c0022dc572d9a6aab43e723942836eb8afd
permissions -rw-r--r--
Bug 1524429 - MOZ_ANDROID_CPU_ARCH doesn't need MOZ_ARCH. r=nalexander It hasn't needed it since bug 1397776. Differential Revision: https://phabricator.services.mozilla.com/D24000

# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

from __future__ import absolute_import, print_function, unicode_literals

import ConfigParser
import os
import subprocess
from collections import defaultdict

import yaml
from mozboot.util import get_state_dir


class PresetHandler(object):

    def __init__(self, path):
        self.path = path
        self._presets = {}

    @property
    def presets(self):
        if not self._presets and os.path.isfile(self.path):
            with open(self.path, 'r') as fh:
                self._presets = yaml.safe_load(fh) or {}

        return self._presets

    def __contains__(self, name):
        return name in self.presets

    def __getitem__(self, name):
        return self.presets[name]

    def __len__(self):
        return len(self.presets)

    def __str__(self):
        if not self.presets:
            return ''
        return yaml.safe_dump(self.presets, default_flow_style=False)

    def list(self):
        if not self.presets:
            print("no presets found")
        else:
            print(self)

    def edit(self):
        if 'EDITOR' not in os.environ:
            print("error: must set the $EDITOR environment variable to use --edit-presets")
            return

        subprocess.call([os.environ['EDITOR'], self.path])

    def save(self, name, **data):
        self.presets[name] = data

        with open(self.path, "w") as fh:
            fh.write(str(self))


class MergedHandler(object):
    def __init__(self, *paths):
        """Helper class for dealing with multiple preset files."""
        self.handlers = [PresetHandler(p) for p in paths]

    def __contains__(self, name):
        return any(name in handler for handler in self.handlers)

    def __getitem__(self, name):
        for handler in self.handlers:
            if name in handler:
                return handler[name]
        raise KeyError(name)

    def __len__(self):
        return sum(len(h) for h in self.handlers)

    def __str__(self):
        all_presets = {
            k: v
            for handler in self.handlers
            for k, v in handler.presets.items()
        }
        return yaml.safe_dump(all_presets, default_flow_style=False)

    def list(self):
        if len(self) == 0:
            print("no presets found")
            return

        for handler in self.handlers:
            val = str(handler)
            if val:
                val = '\n  '.join([''] + val.splitlines() + [''])  # indent all lines by 2 spaces
                print("Presets from {}:".format(handler.path))
                print(val)


def migrate_old_presets(presets):
    """Move presets from the old `autotry.ini` format to the new
    `try_presets.yml` one.

    Args:
        presets (PresetHandler): Handler to migrate old presets into.
    """
    from .selectors.syntax import AutoTry, SyntaxParser
    old_preset_path = os.path.join(get_state_dir(), 'autotry.ini')
    if os.path.isfile(presets.path) or not os.path.isfile(old_preset_path):
        return

    print("migrating saved presets from '{}' to '{}'".format(old_preset_path, presets.path))
    config = ConfigParser.ConfigParser()
    config.read(old_preset_path)

    unknown = defaultdict(list)
    for section in config.sections():
        for name, value in config.items(section):
            kwargs = {}
            if section == 'fuzzy':  # try fuzzy
                kwargs['query'] = [value]
                kwargs['selector'] = 'fuzzy'

            elif section == 'try':  # try syntax
                parser = SyntaxParser()
                kwargs = vars(parser.parse_args(AutoTry.split_try_string(value)))
                kwargs = {k: v for k, v in kwargs.items() if v != parser.get_default(k)}
                kwargs['selector'] = 'syntax'

            else:
                unknown[section].append("{} = {}".format(name, value))
                continue

            presets.save(name, **kwargs)

    os.remove(old_preset_path)

    if unknown:
        for section, values in unknown.items():
            print("""
warning: unknown section '{}', the following presets were not migrated:
  {}
""".format(section, '\n  '.join(values)).lstrip())