import pytest

from detectem.core import Detector, Result, ResultCollection
from detectem.plugin import Plugin, PluginCollection
from detectem.settings import INDICATOR_TYPE, HINT_TYPE, MAIN_ENTRY, GENERIC_TYPE
from detectem.plugins.helpers import meta_generator


class TestDetector():
    HAR_ENTRY_1 = {
        'request': {
            'url': 'http://domain.tld/libA-1.4.2.js'
        },
        'response': {
            'url': 'http://domain.tld/libA-1.4.2.js'
        },
    }

    HAR_NO_URL_REDIRECT = [
        {
            'request': {'url': 'http://domain.tld/'},
            'response': {},
        },
        {
            'request': {'url': 'http://domain.tld/js/script.js'},
            'response': {},
        }
    ]
    HAR_URL_REDIRECT_PATH = [
        {
            'request': {'url': 'http://domain.tld/'},
            'response': {'headers': [
                {'name': 'Location', 'value': '/new/default.html'}
            ]},
        },
        {
            'request': {'url': 'http://domain.tld/new/default.html'},
            'response': {},
        }
    ]
    HAR_URL_REDIRECT_ABS = [
        {
            'request': {'url': 'http://domain.tld/'},
            'response': {'headers': [
                {'name': 'Location', 'value': 'http://other-domain.tld/'}
            ]},
        },
        {
            'request': {'url': 'http://other-domain.tld/'},
            'response': {},
        }
    ]

    URL = 'http://domain.tld/'

    FOO_PLUGIN = {
        'name': 'foo',
        'homepage': 'foo',
        'matchers': {
            'url': 'foo.*-(?P<version>[0-9\.]+)\.js',
            'header': ('FooHeader', 'Foo.* v(?P<version>[0-9\.]+)'),
            'body': 'Foo.* v(?P<version>[0-9\.]+)',
            'xpath': (meta_generator('foo-min'), '(?P<version>[0-9\.]+)'),
        },
        'indicators': {
            'url': 'foo.*\.js',
            'header': ('FooHeader', 'Foo'),
            'body': 'Foo',
            'xpath': "//meta[@name='generator']",
        },
        'modular_matchers': {
            'url': 'foo-(?P<name>\w+)-.*\.js',
            'header': ('FooHeader', 'Foo-(?P<name>\w+)'),
            'body': 'Foo-(?P<name>\w+)',
            'xpath': (meta_generator('foo-min'), 'foo-(?P<name>\w+)'),
        },
    }

    FOO_RESULTS = [
        [{'name': 'foo', 'version': '1.1'}],
        [{'name': 'foo'}],
        [{'name': 'foo-min', 'version': '1.1'}],
    ]

    MATCHER_SOURCES = [
        ['matchers'],
        ['indicators'],
        ['matchers', 'modular_matchers'],
    ]

    def test_detector_starts_with_empty_results(self):
        d = Detector({'har': None, 'softwares': None}, [], None)
        assert not d._results.get_results()

    @pytest.mark.parametrize("har,index", [
        (HAR_NO_URL_REDIRECT, 0),
        (HAR_URL_REDIRECT_PATH, 1),
        (HAR_URL_REDIRECT_ABS, 1),
    ])
    def test_mark_main_entry(self, har, index):
        d = self._create_detector(har, [])
        assert d.har[index]['detectem']['type'] == MAIN_ENTRY

    def test_convert_inline_script_to_har_entry(self):
        script = 'Inline script'

        d = Detector({'har': [], 'softwares': [], 'scripts': [script]}, None, self.URL)
        e = d.har[0]

        assert e['request']['url'] == self.URL
        assert e['response']['content']['text'] == script

    @pytest.mark.parametrize("scripts,n_entries", [
        ([], 0),
        (['script1', 'script2'], 2),
    ])
    def test_add_inline_scripts_to_har(self, scripts, n_entries):
        d = Detector({'har': [], 'softwares': [], 'scripts': scripts}, None, self.URL)
        assert len(d.har) == n_entries

    def _create_plugin(self, template, sources, matchers):
        class TestPlugin(Plugin):
            name = template['name']
            homepage = template['homepage']

        p = TestPlugin()
        for s in sources:
            g = [{m: template[s][m]} for m in matchers]
            setattr(p, s, g)
        return p

    def _create_detector(self, har, plugins):
        pc = PluginCollection()
        for p in plugins:
            pc.add(p)
        return Detector({'har': har, 'softwares': []}, pc, self.URL)

    @pytest.mark.parametrize('sources,result', zip(MATCHER_SOURCES, FOO_RESULTS))
    def test_match_from_headers(self, sources, result):
        har = [
            {
                'request': {'url': self.URL},
                'response': {
                    'url': self.URL,
                    'headers': [
                        {'name': 'FooHeader', 'value': 'Foo-min v1.1'}
                    ]
                },
            },
        ]
        p = self._create_plugin(self.FOO_PLUGIN, sources, ['header'])
        d = self._create_detector(har, [p])

        assert d.get_results() == result

    @pytest.mark.parametrize('sources', MATCHER_SOURCES)
    def test_match_from_headers_ignores_resource_entries(self, sources):
        har = [
            {
                'request': {'url': self.URL},
                'response': {
                    'url': self.URL,
                    'headers': [],
                },
            },
            {
                'request': {'url': 'http://foo.org/lib/foo.js'},
                'response': {
                    'url': 'http://foo.org/lib/foo.js',
                    'headers': [
                        {'name': 'FooHeader', 'value': 'Foo-min v1.1'}
                    ]
                },
            },
        ]
        p = self._create_plugin(self.FOO_PLUGIN, sources, ['header'])
        d = self._create_detector(har, [p])

        assert not d.get_results()

    @pytest.mark.parametrize('sources,result', zip(MATCHER_SOURCES, FOO_RESULTS))
    def test_match_from_body(self, sources, result):
        har = [
            {
                'request': {'url': self.URL},
                'response': {
                    'url': self.URL,
                    'content': {'text': 'Main content'},
                },
            },
            {
                'request': {'url': 'http://foo.org/lib/foo.js'},
                'response': {
                    'url': 'http://foo.org/lib/foo.js',
                    'content': {'text': 'Plugin Foo-min v1.1'},
                },
            },
        ]
        p = self._create_plugin(self.FOO_PLUGIN, sources, ['body'])
        d = self._create_detector(har, [p])

        assert d.get_results() == result

    @pytest.mark.parametrize('sources', MATCHER_SOURCES)
    def test_match_from_body_excludes_main_entry(self, sources):
        har = [
            {
                'request': {'url': self.URL},
                'response': {
                    'url': self.URL,
                    'content': {'text': 'About Foo-min v1.1'},
                },
            },
        ]
        p = self._create_plugin(self.FOO_PLUGIN, sources, ['body'])
        d = self._create_detector(har, [p])

        assert not d.get_results()

    @pytest.mark.parametrize('sources,result', zip(MATCHER_SOURCES, FOO_RESULTS))
    def test_match_from_url(self, sources, result):
        har = [
            {
                'request': {'url': self.URL},
                'response': {'url': self.URL},
            },
            {
                'request': {'url': 'http://foo.org/lib/foo-min-1.1.js'},
                'response': {
                    'url': 'http://foo.org/lib/foo-min-1.1.js',
                },
            },
        ]
        p = self._create_plugin(self.FOO_PLUGIN, sources, ['url'])
        d = self._create_detector(har, [p])

        assert d.get_results() == result

    @pytest.mark.parametrize('sources,result', zip(MATCHER_SOURCES, FOO_RESULTS))
    def test_match_from_xpath(self, sources, result):
        har = [
            {
                'request': {'url': self.URL},
                'response': {
                    'url': self.URL,
                    'content': {
                        'text': '<meta name="generator" content="foo-min 1.1">'
                    },
                },
            },
        ]
        p = self._create_plugin(self.FOO_PLUGIN, sources, ['xpath'])
        d = self._create_detector(har, [p])

        assert d.get_results() == result

    def test_get_hints_with_valid_hint(self):
        class TestPlugin(Plugin):
            name = 'test'
            homepage = 'test'

        class BlaPlugin(Plugin):
            name = 'bla'
            hints = ['test']

        detector = self._create_detector(None, [TestPlugin()])

        hints = detector.get_hints(BlaPlugin())
        assert hints

    def test_get_hints_with_invalid_hint(self):
        class BlaPlugin(Plugin):
            name = 'bla'
            hints = ['test']

        detector = self._create_detector(None, [])
        hints = detector.get_hints(BlaPlugin())
        assert not hints


class TestResultCollection():

    @staticmethod
    def _assert_results(detected, results):
        c = ResultCollection()
        for d in detected:
            c.add_result(d)
        assert set(c.get_results()) == set(results)

    @pytest.mark.parametrize('detected,results', [
        (
            [Result('pluginA', '1.1'), Result('pluginB', '3.8.7'), Result('pluginC', '4.0')],
            [Result('pluginA', '1.1'), Result('pluginB', '3.8.7'), Result('pluginC', '4.0')]
        ),
        (
            [Result('pluginA', '1.3'), Result('pluginA', '1.2'), Result('pluginA', '1.1')],
            [Result('pluginA', '1.1'), Result('pluginA', '1.2'), Result('pluginA', '1.3')],
        ),
        (
            [
                Result('pluginA', '1.1'),
                Result('pluginC', type=HINT_TYPE),
                Result('pluginB', type=INDICATOR_TYPE),
                Result('pluginD', type=GENERIC_TYPE),
            ],
            [
                Result('pluginA', '1.1'),
                Result('pluginB', type=INDICATOR_TYPE),
                Result('pluginC', type=HINT_TYPE),
                Result('pluginD', type=GENERIC_TYPE),
            ]
        ),
    ])
    def test_get_all_detected_plugins(self, detected, results):
        self._assert_results(detected, results)

    @pytest.mark.parametrize('detected,results', [
        (
            [Result('pluginA', '1.1'), Result('pluginA', '1.2'), Result('pluginA', '1.1')],
            [Result('pluginA', '1.1'), Result('pluginA', '1.2')]
        ),
        (
            [
                Result('pluginA', '1.1'),
                Result('pluginA', type=INDICATOR_TYPE),
                Result('pluginA', type=HINT_TYPE),
            ],
            [Result('pluginA', '1.1')]
        ),
        (
            [Result('pluginB', type=HINT_TYPE), Result('pluginB', type=HINT_TYPE)],
            [Result('pluginB', type=HINT_TYPE)]
        ),
        (
            [Result('pluginB', type=INDICATOR_TYPE), Result('pluginB', type=INDICATOR_TYPE)],
            [Result('pluginB', type=INDICATOR_TYPE)]
        ),
        (
            [Result('pluginB', type=INDICATOR_TYPE), Result('pluginB', type=HINT_TYPE)],
            [Result('pluginB', type=INDICATOR_TYPE)]
        ),
        (
            [Result('pluginB', type=INDICATOR_TYPE), Result('pluginB', type=GENERIC_TYPE)],
            [Result('pluginB', type=INDICATOR_TYPE)]
        ),
    ])
    def test_remove_duplicated_results(self, detected, results):
        self._assert_results(detected, results)

[((2707, 2831), 'pytest.mark.parametrize', 'pytest.mark.parametrize', (['"""har,index"""', '[(HAR_NO_URL_REDIRECT, 0), (HAR_URL_REDIRECT_PATH, 1), (\n    HAR_URL_REDIRECT_ABS, 1)]'], {}), "('har,index', [(HAR_NO_URL_REDIRECT, 0), (\n    HAR_URL_REDIRECT_PATH, 1), (HAR_URL_REDIRECT_ABS, 1)])\n", (2730, 2831), False, 'import pytest\n'), ((3322, 3410), 'pytest.mark.parametrize', 'pytest.mark.parametrize', (['"""scripts,n_entries"""', "[([], 0), (['script1', 'script2'], 2)]"], {}), "('scripts,n_entries', [([], 0), (['script1',\n    'script2'], 2)])\n", (3345, 3410), False, 'import pytest\n'), ((4760, 4811), 'pytest.mark.parametrize', 'pytest.mark.parametrize', (['"""sources"""', 'MATCHER_SOURCES'], {}), "('sources', MATCHER_SOURCES)\n", (4783, 4811), False, 'import pytest\n'), ((6385, 6436), 'pytest.mark.parametrize', 'pytest.mark.parametrize', (['"""sources"""', 'MATCHER_SOURCES'], {}), "('sources', MATCHER_SOURCES)\n", (6408, 6436), False, 'import pytest\n'), ((2604, 2656), 'detectem.core.Detector', 'Detector', (["{'har': None, 'softwares': None}", '[]', 'None'], {}), "({'har': None, 'softwares': None}, [], None)\n", (2612, 2656), False, 'from detectem.core import Detector, Result, ResultCollection\n'), ((3113, 3188), 'detectem.core.Detector', 'Detector', (["{'har': [], 'softwares': [], 'scripts': [script]}", 'None', 'self.URL'], {}), "({'har': [], 'softwares': [], 'scripts': [script]}, None, self.URL)\n", (3121, 3188), False, 'from detectem.core import Detector, Result, ResultCollection\n'), ((3508, 3582), 'detectem.core.Detector', 'Detector', (["{'har': [], 'softwares': [], 'scripts': scripts}", 'None', 'self.URL'], {}), "({'har': [], 'softwares': [], 'scripts': scripts}, None, self.URL)\n", (3516, 3582), False, 'from detectem.core import Detector, Result, ResultCollection\n'), ((4010, 4028), 'detectem.plugin.PluginCollection', 'PluginCollection', ([], {}), '()\n', (4026, 4028), False, 'from detectem.plugin import Plugin, PluginCollection\n'), ((4092, 4145), 'detectem.core.Detector', 'Detector', (["{'har': har, 'softwares': []}", 'pc', 'self.URL'], {}), "({'har': har, 'softwares': []}, pc, self.URL)\n", (4100, 4145), False, 'from detectem.core import Detector, Result, ResultCollection\n'), ((8893, 8911), 'detectem.core.ResultCollection', 'ResultCollection', ([], {}), '()\n', (8909, 8911), False, 'from detectem.core import Detector, Result, ResultCollection\n'), ((1753, 1778), 'detectem.plugins.helpers.meta_generator', 'meta_generator', (['"""foo-min"""'], {}), "('foo-min')\n", (1767, 1778), False, 'from detectem.plugins.helpers import meta_generator\n'), ((2203, 2228), 'detectem.plugins.helpers.meta_generator', 'meta_generator', (['"""foo-min"""'], {}), "('foo-min')\n", (2217, 2228), False, 'from detectem.plugins.helpers import meta_generator\n'), ((9094, 9118), 'detectem.core.Result', 'Result', (['"""pluginA"""', '"""1.1"""'], {}), "('pluginA', '1.1')\n", (9100, 9118), False, 'from detectem.core import Detector, Result, ResultCollection\n'), ((9120, 9146), 'detectem.core.Result', 'Result', (['"""pluginB"""', '"""3.8.7"""'], {}), "('pluginB', '3.8.7')\n", (9126, 9146), False, 'from detectem.core import Detector, Result, ResultCollection\n'), ((9148, 9172), 'detectem.core.Result', 'Result', (['"""pluginC"""', '"""4.0"""'], {}), "('pluginC', '4.0')\n", (9154, 9172), False, 'from detectem.core import Detector, Result, ResultCollection\n'), ((9188, 9212), 'detectem.core.Result', 'Result', (['"""pluginA"""', '"""1.1"""'], {}), "('pluginA', '1.1')\n", (9194, 9212), False, 'from detectem.core import Detector, Result, ResultCollection\n'), ((9214, 9240), 'detectem.core.Result', 'Result', (['"""pluginB"""', '"""3.8.7"""'], {}), "('pluginB', '3.8.7')\n", (9220, 9240), False, 'from detectem.core import Detector, Result, ResultCollection\n'), ((9242, 9266), 'detectem.core.Result', 'Result', (['"""pluginC"""', '"""4.0"""'], {}), "('pluginC', '4.0')\n", (9248, 9266), False, 'from detectem.core import Detector, Result, ResultCollection\n'), ((9302, 9326), 'detectem.core.Result', 'Result', (['"""pluginA"""', '"""1.3"""'], {}), "('pluginA', '1.3')\n", (9308, 9326), False, 'from detectem.core import Detector, Result, ResultCollection\n'), ((9328, 9352), 'detectem.core.Result', 'Result', (['"""pluginA"""', '"""1.2"""'], {}), "('pluginA', '1.2')\n", (9334, 9352), False, 'from detectem.core import Detector, Result, ResultCollection\n'), ((9354, 9378), 'detectem.core.Result', 'Result', (['"""pluginA"""', '"""1.1"""'], {}), "('pluginA', '1.1')\n", (9360, 9378), False, 'from detectem.core import Detector, Result, ResultCollection\n'), ((9394, 9418), 'detectem.core.Result', 'Result', (['"""pluginA"""', '"""1.1"""'], {}), "('pluginA', '1.1')\n", (9400, 9418), False, 'from detectem.core import Detector, Result, ResultCollection\n'), ((9420, 9444), 'detectem.core.Result', 'Result', (['"""pluginA"""', '"""1.2"""'], {}), "('pluginA', '1.2')\n", (9426, 9444), False, 'from detectem.core import Detector, Result, ResultCollection\n'), ((9446, 9470), 'detectem.core.Result', 'Result', (['"""pluginA"""', '"""1.3"""'], {}), "('pluginA', '1.3')\n", (9452, 9470), False, 'from detectem.core import Detector, Result, ResultCollection\n'), ((9524, 9548), 'detectem.core.Result', 'Result', (['"""pluginA"""', '"""1.1"""'], {}), "('pluginA', '1.1')\n", (9530, 9548), False, 'from detectem.core import Detector, Result, ResultCollection\n'), ((9566, 9599), 'detectem.core.Result', 'Result', (['"""pluginC"""'], {'type': 'HINT_TYPE'}), "('pluginC', type=HINT_TYPE)\n", (9572, 9599), False, 'from detectem.core import Detector, Result, ResultCollection\n'), ((9617, 9655), 'detectem.core.Result', 'Result', (['"""pluginB"""'], {'type': 'INDICATOR_TYPE'}), "('pluginB', type=INDICATOR_TYPE)\n", (9623, 9655), False, 'from detectem.core import Detector, Result, ResultCollection\n'), ((9673, 9709), 'detectem.core.Result', 'Result', (['"""pluginD"""'], {'type': 'GENERIC_TYPE'}), "('pluginD', type=GENERIC_TYPE)\n", (9679, 9709), False, 'from detectem.core import Detector, Result, ResultCollection\n'), ((9756, 9780), 'detectem.core.Result', 'Result', (['"""pluginA"""', '"""1.1"""'], {}), "('pluginA', '1.1')\n", (9762, 9780), False, 'from detectem.core import Detector, Result, ResultCollection\n'), ((9798, 9836), 'detectem.core.Result', 'Result', (['"""pluginB"""'], {'type': 'INDICATOR_TYPE'}), "('pluginB', type=INDICATOR_TYPE)\n", (9804, 9836), False, 'from detectem.core import Detector, Result, ResultCollection\n'), ((9854, 9887), 'detectem.core.Result', 'Result', (['"""pluginC"""'], {'type': 'HINT_TYPE'}), "('pluginC', type=HINT_TYPE)\n", (9860, 9887), False, 'from detectem.core import Detector, Result, ResultCollection\n'), ((9905, 9941), 'detectem.core.Result', 'Result', (['"""pluginD"""'], {'type': 'GENERIC_TYPE'}), "('pluginD', type=GENERIC_TYPE)\n", (9911, 9941), False, 'from detectem.core import Detector, Result, ResultCollection\n'), ((10162, 10186), 'detectem.core.Result', 'Result', (['"""pluginA"""', '"""1.1"""'], {}), "('pluginA', '1.1')\n", (10168, 10186), False, 'from detectem.core import Detector, Result, ResultCollection\n'), ((10188, 10212), 'detectem.core.Result', 'Result', (['"""pluginA"""', '"""1.2"""'], {}), "('pluginA', '1.2')\n", (10194, 10212), False, 'from detectem.core import Detector, Result, ResultCollection\n'), ((10214, 10238), 'detectem.core.Result', 'Result', (['"""pluginA"""', '"""1.1"""'], {}), "('pluginA', '1.1')\n", (10220, 10238), False, 'from detectem.core import Detector, Result, ResultCollection\n'), ((10254, 10278), 'detectem.core.Result', 'Result', (['"""pluginA"""', '"""1.1"""'], {}), "('pluginA', '1.1')\n", (10260, 10278), False, 'from detectem.core import Detector, Result, ResultCollection\n'), ((10280, 10304), 'detectem.core.Result', 'Result', (['"""pluginA"""', '"""1.2"""'], {}), "('pluginA', '1.2')\n", (10286, 10304), False, 'from detectem.core import Detector, Result, ResultCollection\n'), ((10357, 10381), 'detectem.core.Result', 'Result', (['"""pluginA"""', '"""1.1"""'], {}), "('pluginA', '1.1')\n", (10363, 10381), False, 'from detectem.core import Detector, Result, ResultCollection\n'), ((10399, 10437), 'detectem.core.Result', 'Result', (['"""pluginA"""'], {'type': 'INDICATOR_TYPE'}), "('pluginA', type=INDICATOR_TYPE)\n", (10405, 10437), False, 'from detectem.core import Detector, Result, ResultCollection\n'), ((10455, 10488), 'detectem.core.Result', 'Result', (['"""pluginA"""'], {'type': 'HINT_TYPE'}), "('pluginA', type=HINT_TYPE)\n", (10461, 10488), False, 'from detectem.core import Detector, Result, ResultCollection\n'), ((10518, 10542), 'detectem.core.Result', 'Result', (['"""pluginA"""', '"""1.1"""'], {}), "('pluginA', '1.1')\n", (10524, 10542), False, 'from detectem.core import Detector, Result, ResultCollection\n'), ((10578, 10611), 'detectem.core.Result', 'Result', (['"""pluginB"""'], {'type': 'HINT_TYPE'}), "('pluginB', type=HINT_TYPE)\n", (10584, 10611), False, 'from detectem.core import Detector, Result, ResultCollection\n'), ((10613, 10646), 'detectem.core.Result', 'Result', (['"""pluginB"""'], {'type': 'HINT_TYPE'}), "('pluginB', type=HINT_TYPE)\n", (10619, 10646), False, 'from detectem.core import Detector, Result, ResultCollection\n'), ((10662, 10695), 'detectem.core.Result', 'Result', (['"""pluginB"""'], {'type': 'HINT_TYPE'}), "('pluginB', type=HINT_TYPE)\n", (10668, 10695), False, 'from detectem.core import Detector, Result, ResultCollection\n'), ((10731, 10769), 'detectem.core.Result', 'Result', (['"""pluginB"""'], {'type': 'INDICATOR_TYPE'}), "('pluginB', type=INDICATOR_TYPE)\n", (10737, 10769), False, 'from detectem.core import Detector, Result, ResultCollection\n'), ((10771, 10809), 'detectem.core.Result', 'Result', (['"""pluginB"""'], {'type': 'INDICATOR_TYPE'}), "('pluginB', type=INDICATOR_TYPE)\n", (10777, 10809), False, 'from detectem.core import Detector, Result, ResultCollection\n'), ((10825, 10863), 'detectem.core.Result', 'Result', (['"""pluginB"""'], {'type': 'INDICATOR_TYPE'}), "('pluginB', type=INDICATOR_TYPE)\n", (10831, 10863), False, 'from detectem.core import Detector, Result, ResultCollection\n'), ((10899, 10937), 'detectem.core.Result', 'Result', (['"""pluginB"""'], {'type': 'INDICATOR_TYPE'}), "('pluginB', type=INDICATOR_TYPE)\n", (10905, 10937), False, 'from detectem.core import Detector, Result, ResultCollection\n'), ((10939, 10972), 'detectem.core.Result', 'Result', (['"""pluginB"""'], {'type': 'HINT_TYPE'}), "('pluginB', type=HINT_TYPE)\n", (10945, 10972), False, 'from detectem.core import Detector, Result, ResultCollection\n'), ((10988, 11026), 'detectem.core.Result', 'Result', (['"""pluginB"""'], {'type': 'INDICATOR_TYPE'}), "('pluginB', type=INDICATOR_TYPE)\n", (10994, 11026), False, 'from detectem.core import Detector, Result, ResultCollection\n'), ((11062, 11100), 'detectem.core.Result', 'Result', (['"""pluginB"""'], {'type': 'INDICATOR_TYPE'}), "('pluginB', type=INDICATOR_TYPE)\n", (11068, 11100), False, 'from detectem.core import Detector, Result, ResultCollection\n'), ((11102, 11138), 'detectem.core.Result', 'Result', (['"""pluginB"""'], {'type': 'GENERIC_TYPE'}), "('pluginB', type=GENERIC_TYPE)\n", (11108, 11138), False, 'from detectem.core import Detector, Result, ResultCollection\n'), ((11154, 11192), 'detectem.core.Result', 'Result', (['"""pluginB"""'], {'type': 'INDICATOR_TYPE'}), "('pluginB', type=INDICATOR_TYPE)\n", (11160, 11192), False, 'from detectem.core import Detector, Result, ResultCollection\n')]