<commit_before>#
# Copyright (C) 2018 - 2021 <NAME> <<EMAIL>>
# SPDX-License-Identifier: MIT
#
# pylint: disable=unidiomatic-typecheck
r"""Abstract processor module.

.. versionadded:: 0.9.5

   - Add to abstract processors such like Parsers (loaders and dumpers).
"""
import operator
import typing
import warnings

import pkg_resources

import anyconfig.ioinfo
import anyconfig.models.processor
import anyconfig.utils

from anyconfig.globals import (
    UnknownProcessorTypeError, UnknownFileTypeError, IOInfo,
    PathOrIOInfoT
)


ProcT = typing.TypeVar('ProcT', bound=anyconfig.models.processor.Processor)
ProcClsT = typing.Type[ProcT]
ProcClssT = typing.List[ProcClsT]


def load_plugins(pgroup: str) -> typing.Iterator[ProcClsT]:
    """
    A generator function to yield a class object of
    :class:`anyconfig.models.processor.Processor`.

    :param pgroup: A string represents plugin type, e.g. anyconfig_backends
    """
    for res in pkg_resources.iter_entry_points(pgroup):
        try:
            yield res.load()
        except ImportError as exc:
            warnings.warn(f'Failed to load plugin, exc={exc!s}')


def sort_by_prio(prs: ProcClssT) -> ProcClssT:
    """
    :param prs: A list of :class:`anyconfig.models.processor.Processor` classes
    :return: Sambe as above but sorted by priority
    """
    return sorted(prs, key=operator.methodcaller("priority"), reverse=True)


def select_by_key(items: typing.Iterable[
                    typing.Tuple[typing.List[str], typing.Any]
                  ],
                  sort_fn: typing.Callable[..., typing.Any] = sorted
                  ) -> typing.List[typing.Tuple[str, typing.List[typing.Any]]]:
    """
    :param items: A list of tuples of keys and values, [([key], val)]
    :return: A list of tuples of key and values, [(key, [val])]

    >>> select_by_key([(["a", "aaa"], 1), (["b", "bb"], 2), (["a"], 3)])
    [('a', [1, 3]), ('aaa', [1]), ('b', [2]), ('bb', [2])]
    """
    itr = anyconfig.utils.concat(((k, v) for k in ks) for ks, v in items)
    return list((k, sort_fn(t[1] for t in g))
                for k, g
                in anyconfig.utils.groupby(itr, operator.itemgetter(0)))<commit_msg>fix: correct a type hint for anyconfig.processors.sort_by_prio<commit_after>#
# Copyright (C) 2018 - 2021 <NAME> <<EMAIL>>
# SPDX-License-Identifier: MIT
#
# pylint: disable=unidiomatic-typecheck
r"""Abstract processor module.

.. versionadded:: 0.9.5

   - Add to abstract processors such like Parsers (loaders and dumpers).
"""
import operator
import typing
import warnings

import pkg_resources

import anyconfig.ioinfo
import anyconfig.models.processor
import anyconfig.utils

from anyconfig.globals import (
    UnknownProcessorTypeError, UnknownFileTypeError, IOInfo,
    PathOrIOInfoT
)


ProcT = typing.TypeVar('ProcT', bound=anyconfig.models.processor.Processor)
ProcClsT = typing.Type[ProcT]
ProcClssT = typing.List[ProcClsT]


def load_plugins(pgroup: str) -> typing.Iterator[ProcClsT]:
    """
    A generator function to yield a class object of
    :class:`anyconfig.models.processor.Processor`.

    :param pgroup: A string represents plugin type, e.g. anyconfig_backends
    """
    for res in pkg_resources.iter_entry_points(pgroup):
        try:
            yield res.load()
        except ImportError as exc:
            warnings.warn(f'Failed to load plugin, exc={exc!s}')


def sort_by_prio(prs: typing.Iterable[ProcClsT]) -> ProcClssT:
    """
    :param prs: A list of :class:`anyconfig.models.processor.Processor` classes
    :return: Sambe as above but sorted by priority
    """
    return sorted(prs, key=operator.methodcaller("priority"), reverse=True)


def select_by_key(items: typing.Iterable[
                    typing.Tuple[typing.List[str], typing.Any]
                  ],
                  sort_fn: typing.Callable[..., typing.Any] = sorted
                  ) -> typing.List[typing.Tuple[str, typing.List[typing.Any]]]:
    """
    :param items: A list of tuples of keys and values, [([key], val)]
    :return: A list of tuples of key and values, [(key, [val])]

    >>> select_by_key([(["a", "aaa"], 1), (["b", "bb"], 2), (["a"], 3)])
    [('a', [1, 3]), ('aaa', [1]), ('b', [2]), ('bb', [2])]
    """
    itr = anyconfig.utils.concat(((k, v) for k in ks) for ks, v in items)
    return list((k, sort_fn(t[1] for t in g))
                for k, g
                in anyconfig.utils.groupby(itr, operator.itemgetter(0)))
{'fraction_non_alphanumeric': 0.1425039334681951, 'fraction_numerical': 0.009440323668240054, 'mean_word_length': 3.2140151515151514, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '896256', 'n_tokens_mistral': 1501, 'n_tokens_neox': 1429, 'n_words': 389}