예제 #1
0
    def load(self):
        """Load configuration from the configured YAML file."""
        try:
            with open(self._filename, 'r', encoding='utf-8') as f:
                yaml_data = utils.yaml_load(f)
        except FileNotFoundError:
            return {}
        except OSError as e:
            desc = configexc.ConfigErrorDesc("While reading", e)
            raise configexc.ConfigFileErrors('autoconfig.yml', [desc])
        except yaml.YAMLError as e:
            desc = configexc.ConfigErrorDesc("While parsing", e)
            raise configexc.ConfigFileErrors('autoconfig.yml', [desc])

        try:
            global_obj = yaml_data['global']
        except KeyError:
            desc = configexc.ConfigErrorDesc(
                "While loading data",
                "Toplevel object does not contain 'global' key")
            raise configexc.ConfigFileErrors('autoconfig.yml', [desc])
        except TypeError:
            desc = configexc.ConfigErrorDesc("While loading data",
                                             "Toplevel object is not a dict")
            raise configexc.ConfigFileErrors('autoconfig.yml', [desc])

        if not isinstance(global_obj, dict):
            desc = configexc.ConfigErrorDesc("While loading data",
                                             "'global' object is not a dict")
            raise configexc.ConfigFileErrors('autoconfig.yml', [desc])

        self._values = global_obj
        self._dirty = False

        self._handle_migrations()
예제 #2
0
def _parse_file(test_name):
    """Parse the given HTML file."""
    file_path = (pathlib.Path(__file__).parent.resolve() / 'data' / 'hints' /
                 'html' / test_name)
    with file_path.open('r', encoding='utf-8') as html:
        soup = bs4.BeautifulSoup(html, 'html.parser')

    comment = str(soup.find(text=lambda text: isinstance(text, bs4.Comment)))

    if comment is None:
        raise InvalidFile(test_name, "no comment found")

    data = utils.yaml_load(comment)

    if not isinstance(data, dict):
        raise InvalidFile(
            test_name,
            "expected yaml dict but got {}".format(type(data).__name__))

    allowed_keys = {'target', 'qtwebengine_todo'}
    if not set(data.keys()).issubset(allowed_keys):
        raise InvalidFile(
            test_name, "expected keys {} but found {}".format(
                ', '.join(allowed_keys), ', '.join(set(data.keys()))))

    if 'target' not in data:
        raise InvalidFile(test_name, "'target' key not found")

    qtwebengine_todo = data.get('qtwebengine_todo', None)

    return ParsedFile(target=data['target'], qtwebengine_todo=qtwebengine_todo)
예제 #3
0
    def load(self) -> None:
        """Load configuration from the configured YAML file."""
        try:
            with open(self._filename, 'r', encoding='utf-8') as f:
                yaml_data = utils.yaml_load(f)
        except FileNotFoundError:
            return
        except OSError as e:
            desc = configexc.ConfigErrorDesc("While reading", e)
            raise configexc.ConfigFileErrors('autoconfig.yml', [desc])
        except yaml.YAMLError as e:
            desc = configexc.ConfigErrorDesc("While parsing", e)
            raise configexc.ConfigFileErrors('autoconfig.yml', [desc])

        config_version = self._pop_object(yaml_data, 'config_version', int)
        if config_version == 1:
            settings = self._load_legacy_settings_object(yaml_data)
            self._mark_changed()
        elif config_version > self.VERSION:
            desc = configexc.ConfigErrorDesc(
                "While reading",
                "Can't read config from incompatible newer version")
            raise configexc.ConfigFileErrors('autoconfig.yml', [desc])
        else:
            settings = self._load_settings_object(yaml_data)
            self._dirty = False

        settings = self._handle_migrations(settings)
        self._validate(settings)
        self._build_values(settings)
예제 #4
0
    def load(self) -> None:
        """Load configuration from the configured YAML file."""
        try:
            with open(self._filename, 'r', encoding='utf-8') as f:
                yaml_data = utils.yaml_load(f)
        except FileNotFoundError:
            return
        except OSError as e:
            desc = configexc.ConfigErrorDesc("While reading", e)
            raise configexc.ConfigFileErrors('autoconfig.yml', [desc])
        except yaml.YAMLError as e:
            desc = configexc.ConfigErrorDesc("While parsing", e)
            raise configexc.ConfigFileErrors('autoconfig.yml', [desc])

        config_version = self._pop_object(yaml_data, 'config_version', int)
        if config_version == 1:
            settings = self._load_legacy_settings_object(yaml_data)
            self._mark_changed()
        elif config_version > self.VERSION:
            desc = configexc.ConfigErrorDesc(
                "While reading",
                "Can't read config from incompatible newer version")
            raise configexc.ConfigFileErrors('autoconfig.yml', [desc])
        else:
            settings = self._load_settings_object(yaml_data)
            self._dirty = False

        settings = self._handle_migrations(settings)
        self._validate(settings)
        self._build_values(settings)
예제 #5
0
    def load(self, name, temp=False):
        """Load a named session.

        Args:
            name: The name of the session to load.
            temp: If given, don't set the current session.
        """
        path = self._get_session_path(name, check_exists=True)
        try:
            with open(path, encoding='utf-8') as f:
                data = utils.yaml_load(f)
        except (OSError, UnicodeDecodeError, yaml.YAMLError) as e:
            raise SessionError(e)

        log.sessions.debug("Loading session {} from {}...".format(name, path))
        if data is None:
            raise SessionError("Got empty session file")

        if qtutils.is_single_process():
            if any(win.get('private') for win in data['windows']):
                raise SessionError("Can't load a session with private windows "
                                   "in single process mode.")

        for win in data['windows']:
            self._load_window(win)

        if data['windows']:
            self.did_load = True
        if not name.startswith('_') and not temp:
            self.current = name
예제 #6
0
    def load(self):
        """Load self.values from the configured YAML file."""
        try:
            with open(self._filename, 'r', encoding='utf-8') as f:
                yaml_data = utils.yaml_load(f)
        except FileNotFoundError:
            return
        except OSError as e:
            desc = configexc.ConfigErrorDesc("While reading", e)
            raise configexc.ConfigFileErrors('autoconfig.yml', [desc])
        except yaml.YAMLError as e:
            desc = configexc.ConfigErrorDesc("While parsing", e)
            raise configexc.ConfigFileErrors('autoconfig.yml', [desc])

        try:
            global_obj = yaml_data['global']
        except KeyError:
            desc = configexc.ConfigErrorDesc(
                "While loading data",
                "Toplevel object does not contain 'global' key")
            raise configexc.ConfigFileErrors('autoconfig.yml', [desc])
        except TypeError:
            desc = configexc.ConfigErrorDesc("While loading data",
                                             "Toplevel object is not a dict")
            raise configexc.ConfigFileErrors('autoconfig.yml', [desc])

        if not isinstance(global_obj, dict):
            desc = configexc.ConfigErrorDesc(
                "While loading data",
                "'global' object is not a dict")
            raise configexc.ConfigFileErrors('autoconfig.yml', [desc])

        self.values = global_obj
예제 #7
0
def _parse_file(test_name):
    """Parse the given HTML file."""
    file_path = os.path.join(os.path.abspath(os.path.dirname(__file__)),
                             'data', 'hints', 'html', test_name)
    with open(file_path, 'r', encoding='utf-8') as html:
        soup = bs4.BeautifulSoup(html, 'html.parser')

    comment = str(soup.find(text=lambda text: isinstance(text, bs4.Comment)))

    if comment is None:
        raise InvalidFile(test_name, "no comment found")

    data = utils.yaml_load(comment)

    if not isinstance(data, dict):
        raise InvalidFile(test_name, "expected yaml dict but got {}".format(
            type(data).__name__))

    allowed_keys = {'target', 'qtwebengine_todo'}
    if not set(data.keys()).issubset(allowed_keys):
        raise InvalidFile(test_name, "expected keys {} but found {}".format(
            ', '.join(allowed_keys),
            ', '.join(set(data.keys()))))

    if 'target' not in data:
        raise InvalidFile(test_name, "'target' key not found")

    qtwebengine_todo = data.get('qtwebengine_todo', None)

    return ParsedFile(target=data['target'], qtwebengine_todo=qtwebengine_todo)
예제 #8
0
def _read_yaml(yaml_data):
    """Read config data from a YAML file.

    Args:
        yaml_data: The YAML string to parse.

    Return:
        A tuple with two elements:
            - A dict mapping option names to Option elements.
            - A Migrations object.
    """
    parsed = {}
    migrations = Migrations()
    data = utils.yaml_load(yaml_data)

    keys = {'type', 'default', 'desc', 'backend', 'restart',
            'supports_pattern', 'no_autoconfig'}

    for name, option in data.items():
        if set(option.keys()) == {'renamed'}:
            migrations.renamed[name] = option['renamed']
            continue
        if set(option.keys()) == {'deleted'}:
            value = option['deleted']
            if value is not True:
                raise ValueError("Invalid deleted value: {}".format(value))
            migrations.deleted.append(name)
            continue

        if not set(option.keys()).issubset(keys):
            raise ValueError("Invalid keys {} for {}".format(
                option.keys(), name))

        backends = option.get('backend', None)

        parsed[name] = Option(
            name=name,
            typ=_parse_yaml_type(name, option['type']),
            default=option['default'],
            backends=_parse_yaml_backends(name, backends),
            raw_backends=backends if isinstance(backends, dict) else None,
            description=option['desc'],
            restart=option.get('restart', False),
            supports_pattern=option.get('supports_pattern', False),
            no_autoconfig=option.get('no_autoconfig', False),
        )

    # Make sure no key shadows another.
    for key1 in parsed:
        for key2 in parsed:
            if key2.startswith(key1 + '.'):
                raise ValueError("Shadowing keys {} and {}".format(key1, key2))

    # Make sure rename targets actually exist.
    for old, new in migrations.renamed.items():
        if new not in parsed:
            raise ValueError("Renaming {} to unknown {}".format(old, new))

    return parsed, migrations
예제 #9
0
def _read_yaml(yaml_data):
    """Read config data from a YAML file.

    Args:
        yaml_data: The YAML string to parse.

    Return:
        A tuple with two elements:
            - A dict mapping option names to Option elements.
            - A Migrations object.
    """
    parsed = {}
    migrations = Migrations()
    data = utils.yaml_load(yaml_data)

    keys = {
        'type', 'default', 'desc', 'backend', 'restart', 'supports_pattern'
    }

    for name, option in data.items():
        if set(option.keys()) == {'renamed'}:
            migrations.renamed[name] = option['renamed']
            continue
        if set(option.keys()) == {'deleted'}:
            value = option['deleted']
            if value is not True:
                raise ValueError("Invalid deleted value: {}".format(value))
            migrations.deleted.append(name)
            continue

        if not set(option.keys()).issubset(keys):
            raise ValueError("Invalid keys {} for {}".format(
                option.keys(), name))

        backends = option.get('backend', None)

        parsed[name] = Option(
            name=name,
            typ=_parse_yaml_type(name, option['type']),
            default=option['default'],
            backends=_parse_yaml_backends(name, backends),
            raw_backends=backends if isinstance(backends, dict) else None,
            description=option['desc'],
            restart=option.get('restart', False),
            supports_pattern=option.get('supports_pattern', False),
        )

    # Make sure no key shadows another.
    for key1 in parsed:
        for key2 in parsed:
            if key2.startswith(key1 + '.'):
                raise ValueError("Shadowing keys {} and {}".format(key1, key2))

    # Make sure rename targets actually exist.
    for old, new in migrations.renamed.items():
        if new not in parsed:
            raise ValueError("Renaming {} to unknown {}".format(old, new))

    return parsed, migrations
예제 #10
0
    def get_session(self):
        """Save the session and get the parsed session data."""
        with tempfile.TemporaryDirectory() as tdir:
            session = pathlib.Path(tdir) / 'session.yml'
            self.send_cmd(':session-save --with-private "{}"'.format(session))
            self.wait_for(category='message', loglevel=logging.INFO,
                          message='Saved session {}.'.format(session))
            data = session.read_text(encoding='utf-8')

        self._log('\nCurrent session data:\n' + data)
        return utils.yaml_load(data)
예제 #11
0
    def get_session(self):
        """Save the session and get the parsed session data."""
        with tempfile.TemporaryDirectory() as tmpdir:
            session = os.path.join(tmpdir, 'session.yml')
            self.send_cmd(':session-save --with-private "{}"'.format(session))
            self.wait_for(category='message', loglevel=logging.INFO,
                          message='Saved session {}.'.format(session))
            with open(session, encoding='utf-8') as f:
                data = f.read()

        self._log('\nCurrent session data:\n' + data)
        return utils.yaml_load(data)
예제 #12
0
    def get_session(self):
        """Save the session and get the parsed session data."""
        with tempfile.TemporaryDirectory() as tmpdir:
            session = os.path.join(tmpdir, 'session.yml')
            self.send_cmd(':session-save --with-private "{}"'.format(session))
            self.wait_for(category='message', loglevel=logging.INFO,
                          message='Saved session {}.'.format(session))
            with open(session, encoding='utf-8') as f:
                data = f.read()

        self._log('\nCurrent session data:\n' + data)
        return utils.yaml_load(data)
예제 #13
0
    def from_str(self, value):
        self._basic_str_validation(value)
        if not value:
            return None

        try:
            yaml_val = utils.yaml_load(value)
        except yaml.YAMLError as e:
            raise configexc.ValidationError(value, str(e))

        # For the values, we actually want to call to_py, as we did parse them
        # from YAML, so they are numbers/booleans/... already.
        self.to_py(yaml_val)
        return yaml_val
예제 #14
0
    def from_str(self, value):
        self._basic_str_validation(value)
        if not value:
            return None

        try:
            yaml_val = utils.yaml_load(value)
        except yaml.YAMLError as e:
            raise configexc.ValidationError(value, str(e))

        # For the values, we actually want to call to_py, as we did parse them
        # from YAML, so they are numbers/booleans/... already.
        self.to_py(yaml_val)
        return yaml_val
예제 #15
0
    def load(self, name, temp=False):
        """Load a named session.

        Args:
            name: The name of the session to load.
            temp: If given, don't set the current session.
        """
        path = self._get_session_path(name, check_exists=True)
        try:
            with open(path, encoding='utf-8') as f:
                data = utils.yaml_load(f)
        except (OSError, UnicodeDecodeError, yaml.YAMLError) as e:
            raise SessionError(e)

        log.sessions.debug("Loading session {} from {}...".format(name, path))
        if data is None:
            raise SessionError("Got empty session file")

        for win in data['windows']:
            window = mainwindow.MainWindow(geometry=win['geometry'],
                                           private=win.get('private', None))
            window.show()
            tabbed_browser = objreg.get('tabbed-browser',
                                        scope='window',
                                        window=window.win_id)
            tab_to_focus = None
            for i, tab in enumerate(win['tabs']):
                new_tab = tabbed_browser.tabopen(background=False)
                self._load_tab(new_tab, tab)
                if tab.get('active', False):
                    tab_to_focus = i
                if new_tab.data.pinned:
                    tabbed_browser.widget.set_tab_pinned(
                        new_tab, new_tab.data.pinned)
            if tab_to_focus is not None:
                tabbed_browser.widget.setCurrentIndex(tab_to_focus)
            if win.get('active', False):
                QTimer.singleShot(0, tabbed_browser.widget.activateWindow)

        if data['windows']:
            self.did_load = True
        if not name.startswith('_') and not temp:
            self._current = name
예제 #16
0
    def load(self, name, temp=False):
        """Load a named session.

        Args:
            name: The name of the session to load.
            temp: If given, don't set the current session.
        """
        path = self._get_session_path(name, check_exists=True)
        try:
            with open(path, encoding='utf-8') as f:
                data = utils.yaml_load(f)
        except (OSError, UnicodeDecodeError, yaml.YAMLError) as e:
            raise SessionError(e)

        log.sessions.debug("Loading session {} from {}...".format(name, path))
        if data is None:
            raise SessionError("Got empty session file")

        for win in data['windows']:
            window = mainwindow.MainWindow(geometry=win['geometry'],
                                           private=win.get('private', None))
            window.show()
            tabbed_browser = objreg.get('tabbed-browser', scope='window',
                                        window=window.win_id)
            tab_to_focus = None
            for i, tab in enumerate(win['tabs']):
                new_tab = tabbed_browser.tabopen(background=False)
                self._load_tab(new_tab, tab)
                if tab.get('active', False):
                    tab_to_focus = i
                if new_tab.data.pinned:
                    tabbed_browser.widget.set_tab_pinned(new_tab,
                                                         new_tab.data.pinned)
            if tab_to_focus is not None:
                tabbed_browser.widget.setCurrentIndex(tab_to_focus)
            if win.get('active', False):
                QTimer.singleShot(0, tabbed_browser.widget.activateWindow)

        if data['windows']:
            self.did_load = True
        if not name.startswith('_') and not temp:
            self._current = name
예제 #17
0
    def load(self):
        """Load configuration from the configured YAML file."""
        try:
            with open(self._filename, 'r', encoding='utf-8') as f:
                yaml_data = utils.yaml_load(f)
        except FileNotFoundError:
            return {}
        except OSError as e:
            desc = configexc.ConfigErrorDesc("While reading", e)
            raise configexc.ConfigFileErrors('autoconfig.yml', [desc])
        except yaml.YAMLError as e:
            desc = configexc.ConfigErrorDesc("While parsing", e)
            raise configexc.ConfigFileErrors('autoconfig.yml', [desc])

        try:
            global_obj = yaml_data['global']
        except KeyError:
            desc = configexc.ConfigErrorDesc(
                "While loading data",
                "Toplevel object does not contain 'global' key")
            raise configexc.ConfigFileErrors('autoconfig.yml', [desc])
        except TypeError:
            desc = configexc.ConfigErrorDesc("While loading data",
                                             "Toplevel object is not a dict")
            raise configexc.ConfigFileErrors('autoconfig.yml', [desc])

        if not isinstance(global_obj, dict):
            desc = configexc.ConfigErrorDesc(
                "While loading data",
                "'global' object is not a dict")
            raise configexc.ConfigFileErrors('autoconfig.yml', [desc])

        # Delete unknown values
        # (e.g. options which were removed from configdata.yml)
        for name in list(global_obj):
            if name not in configdata.DATA:
                del global_obj[name]

        self._values = global_obj
        self._dirty = False
def _read_yaml(yaml_data):
    """Read config data from a YAML file.

    Args:
        yaml_data: The YAML string to parse.

    Return:
        A dict mapping option names to Option elements.
    """
    parsed = {}
    data = utils.yaml_load(yaml_data)

    keys = {'type', 'default', 'desc', 'backend'}

    for name, option in data.items():
        if not set(option.keys()).issubset(keys):
            raise ValueError("Invalid keys {} for {}".format(
                option.keys(), name))

        backends = option.get('backend', None)

        parsed[name] = Option(
            name=name,
            typ=_parse_yaml_type(name, option['type']),
            default=option['default'],
            backends=_parse_yaml_backends(name, backends),
            raw_backends=backends if isinstance(backends, dict) else None,
            description=option['desc'])

    # Make sure no key shadows another.
    for key1 in parsed:
        for key2 in parsed:
            if key2.startswith(key1 + '.'):
                raise ValueError("Shadowing keys {} and {}".format(key1, key2))

    return parsed
예제 #19
0
def _read_yaml(yaml_data):
    """Read config data from a YAML file.

    Args:
        yaml_data: The YAML string to parse.

    Return:
        A dict mapping option names to Option elements.
    """
    parsed = {}
    data = utils.yaml_load(yaml_data)

    keys = {'type', 'default', 'desc', 'backend'}

    for name, option in data.items():
        if not set(option.keys()).issubset(keys):
            raise ValueError("Invalid keys {} for {}".format(
                option.keys(), name))

        backends = option.get('backend', None)

        parsed[name] = Option(
            name=name,
            typ=_parse_yaml_type(name, option['type']),
            default=option['default'],
            backends=_parse_yaml_backends(name, backends),
            raw_backends=backends if isinstance(backends, dict) else None,
            description=option['desc'])

    # Make sure no key shadows another.
    for key1 in parsed:
        for key2 in parsed:
            if key2.startswith(key1 + '.'):
                raise ValueError("Shadowing keys {} and {}".format(key1, key2))

    return parsed
예제 #20
0
 def read_toplevel(self):
     with self.fobj.open('r', encoding='utf-8') as f:
         data = utils.yaml_load(f)
         assert data['config_version'] == 2
         return data
예제 #21
0
 def read_toplevel(self):
     with self.fobj.open('r', encoding='utf-8') as f:
         data = utils.yaml_load(f)
         assert data['config_version'] == 2
         return data