Blame libnmstate/state.py

Packit Service 0535c1
#
Packit Service 0535c1
# Copyright (c) 2020 Red Hat, Inc.
Packit Service 0535c1
#
Packit Service 0535c1
# This file is part of nmstate
Packit Service 0535c1
#
Packit Service 0535c1
# This program is free software: you can redistribute it and/or modify
Packit Service 0535c1
# it under the terms of the GNU Lesser General Public License as published by
Packit Service 0535c1
# the Free Software Foundation, either version 2.1 of the License, or
Packit Service 0535c1
# (at your option) any later version.
Packit Service 0535c1
#
Packit Service 0535c1
# This program is distributed in the hope that it will be useful,
Packit Service 0535c1
# but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 0535c1
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service 0535c1
# GNU Lesser General Public License for more details.
Packit Service 0535c1
#
Packit Service 0535c1
# You should have received a copy of the GNU Lesser General Public License
Packit Service 0535c1
# along with this program. If not, see <https://www.gnu.org/licenses/>.
Packit Service 0535c1
#
Packit Service 0535c1
Packit Service 0535c1
from abc import ABCMeta
Packit Service 0535c1
from abc import abstractmethod
Packit Service 0535c1
from collections.abc import Sequence
Packit Service 0535c1
from collections.abc import Mapping
Packit Service 0535c1
from functools import total_ordering
Packit Service 0535c1
Packit Service 0535c1
Packit Service 0535c1
@total_ordering
Packit Service 0535c1
class StateEntry(metaclass=ABCMeta):
Packit Service 0535c1
    @abstractmethod
Packit Service 0535c1
    def _keys(self):
Packit Service 0535c1
        """
Packit Service 0535c1
        Return the tuple representing this entry, will be used for hashing or
Packit Service 0535c1
        comparing.
Packit Service 0535c1
        """
Packit Service 0535c1
        pass
Packit Service 0535c1
Packit Service 0535c1
    def __hash__(self):
Packit Service 0535c1
        return hash(self._keys())
Packit Service 0535c1
Packit Service 0535c1
    def __eq__(self, other):
Packit Service 0535c1
        return self is other or self._keys() == other._keys()
Packit Service 0535c1
Packit Service 0535c1
    def __lt__(self, other):
Packit Service 0535c1
        return self._keys() < other._keys()
Packit Service 0535c1
Packit Service 0535c1
    def __repr__(self):
Packit Service 0535c1
        return str(self.to_dict())
Packit Service 0535c1
Packit Service 0535c1
    @property
Packit Service 0535c1
    @abstractmethod
Packit Service 0535c1
    def absent(self):
Packit Service 0535c1
        pass
Packit Service 0535c1
Packit Service 0535c1
    def to_dict(self):
Packit Service 0535c1
        return {
Packit Service 0535c1
            key.replace("_", "-"): value
Packit Service 0535c1
            for key, value in vars(self).items()
Packit Service 0535c1
            if (not key.startswith("_")) and (value is not None)
Packit Service 0535c1
        }
Packit Service 0535c1
Packit Service 0535c1
    def match(self, other):
Packit Service 0535c1
        """
Packit Service 0535c1
        Match self against other. Treat self None attributes as wildcards,
Packit Service 0535c1
        matching against any value in others.
Packit Service 0535c1
        Return True for a match, False otherwise.
Packit Service 0535c1
        """
Packit Service 0535c1
        for self_value, other_value in zip(self._keys(), other._keys()):
Packit Service 0535c1
            if self_value is not None and self_value != other_value:
Packit Service 0535c1
                return False
Packit Service 0535c1
        return True
Packit Service 0535c1
Packit Service 0535c1
Packit Service 0535c1
def state_match(desire, current):
Packit Service 0535c1
    """
Packit Service 0535c1
    Return True when all values defined in desire equal to value in current,
Packit Service 0535c1
    else False:
Packit Service 0535c1
        * For mapping(e.g. dict), desire could have less value than current.
Packit Service 0535c1
        * For sequnce(e.g. list), desire should equal to current.
Packit Service 0535c1
    """
Packit Service 0535c1
    if isinstance(desire, Mapping):
Packit Service 0535c1
        return isinstance(current, Mapping) and all(
Packit Service 0535c1
            state_match(val, current.get(key)) for key, val in desire.items()
Packit Service 0535c1
        )
Packit Service 0535c1
    elif isinstance(desire, Sequence) and not isinstance(desire, str):
Packit Service 0535c1
        return (
Packit Service 0535c1
            isinstance(current, Sequence)
Packit Service 0535c1
            and not isinstance(current, str)
Packit Service 0535c1
            and len(current) == len(desire)
Packit Service 0535c1
            and all(state_match(d, c) for d, c in zip(desire, current))
Packit Service 0535c1
        )
Packit Service 0535c1
    else:
Packit Service 0535c1
        return desire == current
Packit Service 0535c1
Packit Service 0535c1
Packit Service 0535c1
def merge_dict(dict_to, dict_from):
Packit Service 0535c1
    """
Packit Service 0535c1
    Data will copy from `dict_from` if undefined in `dict_to`.
Packit Service 0535c1
    For list, the whole list is copied instead of merging.
Packit Service 0535c1
    """
Packit Service 0535c1
    for key, from_value in dict_from.items():
Packit Service 0535c1
        if key not in dict_to:
Packit Service 0535c1
            dict_to[key] = from_value
Packit Service 0535c1
        elif isinstance(dict_to[key], Mapping):
Packit Service 0535c1
            merge_dict(dict_to[key], from_value)