晋太元中,武陵人捕鱼为业。缘溪行,忘路之远近。忽逢桃花林,夹岸数百步,中无杂树,芳草鲜美,落英缤纷。渔人甚异之,复前行,欲穷其林。   林尽水源,便得一山,山有小口,仿佛若有光。便舍船,从口入。初极狭,才通人。复行数十步,豁然开朗。土地平旷,屋舍俨然,有良田、美池、桑竹之属。阡陌交通,鸡犬相闻。其中往来种作,男女衣着,悉如外人。黄发垂髫,并怡然自乐。   见渔人,乃大惊,问所从来。具答之。便要还家,设酒杀鸡作食。村中闻有此人,咸来问讯。自云先世避秦时乱,率妻子邑人来此绝境,不复出焉,遂与外人间隔。问今是何世,乃不知有汉,无论魏晋。此人一一为具言所闻,皆叹惋。余人各复延至其家,皆出酒食。停数日,辞去。此中人语云:“不足为外人道也。”(间隔 一作:隔绝)   既出,得其船,便扶向路,处处志之。及郡下,诣太守,说如此。太守即遣人随其往,寻向所志,遂迷,不复得路。   南阳刘子骥,高尚士也,闻之,欣然规往。未果,寻病终。后遂无问津者。 sh-3ll

HOME


sh-3ll 1.0
DIR:/opt/cloudlinux/venv/lib64/python3.11/site-packages/prospector/
Upload File :
Current File : //opt/cloudlinux/venv/lib64/python3.11/site-packages/prospector/blender.py
# This module contains the logic for "blending" of errors.
# Since prospector runs multiple tools with overlapping functionality, this
# module exists to merge together equivalent warnings from different tools for
# the same line. For example, both pyflakes and pylint will generate an
# "Unused Import" warning on the same line. This is obviously redundant, so we
# remove duplicates.
from collections import defaultdict

import pkg_resources
import yaml

__all__ = (
    "blend",
    "BLEND_COMBOS",
)


def blend_line(messages, blend_combos=None):
    """
    Given a list of messages on the same line, blend them together so that we
    end up with one message per actual problem. Note that we can still return
    more than one message here if there are two or more different errors for
    the line.
    """
    blend_combos = blend_combos or BLEND_COMBOS
    blend_lists = [[] for _ in range(len(blend_combos))]
    blended = []

    # first we split messages into each of the possible blendable categories
    # so that we have a list of lists of messages which can be blended together
    for message in messages:
        key = (message.source, message.code)
        found = False
        for blend_combo_idx, blend_combo in enumerate(blend_combos):
            if key in blend_combo:
                found = True
                blend_lists[blend_combo_idx].append(message)

        # note: we use 'found=True' here rather than a simple break/for-else
        # because this allows the same message to be put into more than one
        # 'bucket'. This means that the same message from pycodestyle can 'subsume'
        # two from pylint, for example.

        if not found:
            # if we get here, then this is not a message which can be blended,
            # so by definition is already blended
            blended.append(message)

    # we should now have a list of messages which all represent the same
    # problem on the same line, so we will sort them according to the priority
    # in BLEND and pick the first one
    for blend_combo_idx, blend_list in enumerate(blend_lists):
        if len(blend_list) == 0:
            continue
        # pylint:disable=cell-var-from-loop
        blend_list.sort(
            key=lambda msg: blend_combos[blend_combo_idx].index(
                (msg.source, msg.code),
            ),
        )
        if blend_list[0] not in blended:
            # We may have already added this message if it represents
            # several messages in other tools which are not being run -
            # for example, pylint missing-docstring is blended with pydocstyle
            # D100, D101 and D102, but should not appear 3 times!
            blended.append(blend_list[0])

        # Some messages from a tool point out an error that in another tool is handled by two
        # different errors or more. For example, pylint emits the same warning (multiple-statements)
        # for "two statements on a line" separated by a colon and a semi-colon, while pycodestyle has E701
        # and E702 for those cases respectively. In this case, the pylint error will not be 'blended' as
        # it will appear in two blend_lists. Therefore we mark anything not taken from the blend list
        # as "consumed" and then filter later, to avoid such cases.
        for now_used in blend_list[1:]:
            now_used.used = True

    return [m for m in blended if not getattr(m, "used", False)]


def blend(messages, blend_combos=None):
    blend_combos = blend_combos or BLEND_COMBOS

    # group messages by file and then line number
    msgs_grouped = defaultdict(lambda: defaultdict(list))

    for message in messages:
        msgs_grouped[message.location.path][message.location.line].append(
            message,
        )

    # now blend together all messages on the same line
    out = []
    for by_line in msgs_grouped.values():
        for messages_on_line in by_line.values():
            out += blend_line(messages_on_line, blend_combos)

    return out


def get_default_blend_combinations():
    combos = yaml.safe_load(pkg_resources.resource_string(__name__, "blender_combinations.yaml"))
    combos = combos.get("combinations", [])

    defaults = []
    for combo in combos:
        toblend = []
        for msg in combo:
            toblend += msg.items()
        defaults.append(tuple(toblend))

    return tuple(defaults)


BLEND_COMBOS = get_default_blend_combinations()