Beispiel #1
0
class CaseInsensitiveDict(MutableMapping):
    """
    Inspired by requests' case-insensitive dict implementation, but works with
    non-string keys as well.
    """

    def __init__(self, init=None, **kwargs):
        """
        Force internal dict to be ordered to ensure a consistent iteration
        order, irrespective of case.
        """
        self._data = OrderedDict()
        self.update(init or {}, **kwargs)

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

    def __setitem__(self, key, value):
        # Store the case-sensitive key so it is available for dict iteration
        self._data[to_lowercase(key)] = (key, value)

    def __delitem__(self, key):
        del self._data[to_lowercase(key)]

    def __getitem__(self, key):
        return self._data[to_lowercase(key)][1]

    def __iter__(self):
        return (item[0] for item in self._data.values())

    def __eq__(self, rval):
        if not isinstance(rval, Mapping):
            # Comparing to non-mapping type (e.g. int) is always False
            return False
        return dict(self.items_lower()) == dict(CaseInsensitiveDict(rval).items_lower())

    def __repr__(self):
        return repr(dict(self.items()))

    def items_lower(self):
        """
        Returns a generator iterating over keys and values, with the keys all
        being lowercase.
        """
        return ((key, val[1]) for key, val in self._data.items())

    def copy(self):
        """
        Returns a copy of the object
        """
        return CaseInsensitiveDict(self._data.items())
class PathInfoDict(fileinfo.FileInfo):
    def __init__(self, match_each=True, **patterns):
        '''
        match_each:
            If True, each file path is matched which prevents uses less memory
            but sacrifices performance a little bit.  If False, the complete
            list is matched after all the file information has been added to
            pathinfo.

        patterns:
            Contains the patterns to match.
            Example:
                { 'saltenv': 'base', 'relpath': ['*.sls'] }
        '''
        super(PathInfoDict, self).__init__(
            fields=PATHINFO_FIELDS,
            match_each=match_each,
            **patterns
        )
        self._elements = OrderedDict()

    @property
    def as_sequence(self):
        if self.pattern and not self.match_each:
            return list(
                matcher.ifilter(
                    self._elements.values(),
                    _pattern=self.pattern
                )
            )
        return self._elements.values()

    def element(self, root=None, abspath=None, **kwargs):
        '''
        kwargs contain extra information for custom methods.

        This method must return a valid empty object if no vars are passed
        to allow introspection to create patterns.

        :param root:
        :param abspath:
        '''
        if root is None and abspath is None:
            root = os.path.abspath('.')
            abspath = os.path.abspath('.')
        relpath = os.path.relpath(abspath, root)

        try:
            element = self._elements.get(relpath, OrderedDict())
        except AttributeError:
            element = OrderedDict()

        if not element:
            for field in PATHINFO_FIELDS:
                element.setdefault(field, '')
            element['saltenv'] = kwargs.get('saltenv', 'base')
            element['relpath'] = relpath
            element['abspath'] = abspath
            element['is_pillar'] = kwargs.get('is_pillar', False)

        cachedir = kwargs.get('cachedir', '')
        if cachedir and os.path.commonprefix([abspath, cachedir]) == cachedir:
            element['cache_root'] = root
        else:
            element['file_root'] = root

        element_hook = kwargs.get('_element_hook', None)
        if element_hook:
            element = element_hook(self, element, **kwargs)

        return element

    def add_element(self, element, **kwargs):
        add_hook = kwargs.get('_add_hook', None)
        if add_hook:
            element = add_hook(self, element, **kwargs)

        if element['relpath'] not in self._elements:
            self._elements[element['relpath']] = element

    def filelist(self, roots, **kwargs):
        '''
        :param roots:
            file_roots, pillar_roots, cache_roots, etc to walk.

        kwargs:
            Contains any extra variables to pass to element.

        '''
        for env, destdirs in six.iteritems(roots):
            kwargs['saltenv'] = env
            super(PathInfoDict, self).filelist(destdirs, **kwargs)

        return self.as_sequence
Beispiel #3
0
    def patch(self, force_load=True, kinds=None, **kwargs):
        '''
        opts
            overriden opts
        context
            overriden context
        pillar
            overriden pillar
        grains
            overriden grains
        funcs
            override something in the dunders indexed by kind (modules,
            runners, etc)

        .. code-block:: python

            with self.patch(grains={1:2}, context={3: 4}):
                ret1 = self._('mc_remote.sls')()

        .. code-block:: python

            with self.patch(opts={1: 2}, pillar={'secret': 'secret'}):
                ret1 = self._('mc_remote.sls')()

        .. code-block:: python

            def _do(*args, **kw):
                return {}

            with self.patch(funcs={
                'modules': {'mc_remote.salt_call': Mock(side_effect=_do)},
                'pillars': {'mc_remote.salt_call': Mock(side_effect=_do)}
            }):
                ret1 = self._('mc_remote.sls')()

        '''
        tpatchs = OrderedDict()
        globs = kwargs.get('globs', {})
        mod_globs = {}
        funcs = kwargs.get('funcs', {})
        for module, funcsdata in funcs.items():
            for fun, callback in funcsdata.items():
                if '.' in fun:
                    module, sfun = fun.split('.')
                    mglobs = mod_globs.setdefault(module, copy.deepcopy(globs))
                    mglobs[sfun] = callback
                    k = 'patch_fun_{0}{1}'.format(module, fun)
                    tpatchs[k] = patch.dict(self.salt, {fun: callback})
        for opt in self.contextual:
            overriden = kwargs.get(opt, {})
            tpatchs[opt] = patch.dict(getattr(self, opt+'_'), overriden)
        if not kinds:
            kinds = [a for a in self.dunders_]
        for kind in kinds:
            mods = self.dunders_[kind]
            # force lazyloader to load all
            if force_load:
                mods = [a for a in self.dunders_[kind]]
            filtered = kwargs.get('filtered', None)
            if filtered is None:
                filtered = mods[:]
            if not filtered:
                continue
            for mod in mods:
                matched = False
                for match in filtered:
                    rmatch = re_cache.get(match)
                    if not rmatch:
                        rmatch = re_cache[match] = re.compile(match)
                    if rmatch.search(mod):
                        matched = True
                        break
                if not matched:
                    continue
                func = self.dunders_[kind][mod]
                if not isinstance(func, dict):
                    try:
                        _globals = func.__globals__
                    except AttributeError:
                        continue
                    thismod = mod.split('.')[0]
                    globspatch = mod_globs.setdefault(thismod, {})
                    for i in globs:
                        globspatch[i] = globs[i]
                    k = '{0}.{1}'.format(kind, mod)
                    for opt in self.contextual:
                        gopt = '__{0}__'.format(opt)
                        if gopt in _globals:
                            globspatch[gopt] = getattr(self, opt+'_')
                    tpatchs[k] = patch.dict(func.__globals__, globspatch)
        return contextlib.nested(*tuple(tpatchs.values()))
class PathInfoDict(fileinfo.FileInfo):
    def __init__(self, match_each=True, **patterns):
        '''
        match_each:
            If True, each file path is matched which prevents uses less memory
            but sacrifices performance a little bit.  If False, the complete
            list is matched after all the file information has been added to
            pathinfo.

        patterns:
            Contains the patterns to match.
            Example:
                { 'saltenv': 'base', 'relpath': ['*.sls'] }
        '''
        super(PathInfoDict, self).__init__(fields=PATHINFO_FIELDS,
                                           match_each=match_each,
                                           **patterns)
        self._elements = OrderedDict()

    @property
    def as_sequence(self):
        if self.pattern and not self.match_each:
            return list(
                matcher.ifilter(self._elements.values(),
                                _pattern=self.pattern))
        return self._elements.values()

    def element(self, root=None, abspath=None, **kwargs):
        '''
        kwargs contain extra information for custom methods.

        This method must return a valid empty object if no vars are passed
        to allow introspection to create patterns.

        :param root:
        :param abspath:
        '''
        if root is None and abspath is None:
            root = os.path.abspath('.')
            abspath = os.path.abspath('.')
        relpath = os.path.relpath(abspath, root)

        try:
            element = self._elements.get(relpath, OrderedDict())
        except AttributeError:
            element = OrderedDict()

        if not element:
            for field in PATHINFO_FIELDS:
                element.setdefault(field, '')
            element['saltenv'] = kwargs.get('saltenv', 'base')
            element['relpath'] = relpath
            element['abspath'] = abspath
            element['is_pillar'] = kwargs.get('is_pillar', False)

        cachedir = kwargs.get('cachedir', '')
        if cachedir and os.path.commonprefix([abspath, cachedir]) == cachedir:
            element['cache_root'] = root
        else:
            element['file_root'] = root

        element_hook = kwargs.get('_element_hook', None)
        if element_hook:
            element = element_hook(self, element, **kwargs)

        return element

    def add_element(self, element, **kwargs):
        add_hook = kwargs.get('_add_hook', None)
        if add_hook:
            element = add_hook(self, element, **kwargs)

        if element['relpath'] not in self._elements:
            self._elements[element['relpath']] = element

    def filelist(self, roots, **kwargs):
        '''
        :param roots:
            file_roots, pillar_roots, cache_roots, etc to walk.

        kwargs:
            Contains any extra variables to pass to element.

        '''
        for env, destdirs in six.iteritems(roots):
            kwargs['saltenv'] = env
            super(PathInfoDict, self).filelist(destdirs, **kwargs)

        return self.as_sequence