1import glob
2import os
3
4import pytest
5
6from flexget import plugin, plugins
7from flexget.event import event, fire_event
8
9
10class TestPluginApi:
11    """
12    Contains plugin api related tests
13    """
14
15    config = 'tasks: {}'
16
17    def test_unknown_plugin(self):
18        with pytest.raises(plugin.DependencyError):
19            plugin.get_plugin_by_name('nonexisting_plugin')
20
21    def test_unknown_plugin(self):
22        with pytest.raises(plugin.DependencyError):
23            plugin.get('nonexisting_plugin', 'test')
24
25    def test_no_dupes(self):
26        plugin.load_plugins()
27
28        assert plugin.PluginInfo.dupe_counter == 0, "Duplicate plugin names, see log"
29
30    def test_load(self):
31        plugin.load_plugins()
32        plugin_path = os.path.dirname(plugins.__file__)
33        plugin_modules = set(
34            os.path.basename(i) for k in ("/*.py", "/*/*.py") for i in glob.glob(plugin_path + k)
35        )
36        assert len(plugin_modules) >= 10, "Less than 10 plugin modules looks fishy"
37        # Hmm, this test isn't good, because we have plugin modules that don't register a class (like cli ones)
38        # and one module can load multiple plugins TODO: Maybe consider some replacement
39        # assert len(plugin.plugins) >= len(plugin_modules) - 1, "Less plugins than plugin modules"
40
41    def test_register_by_class(self, execute_task):
42        class TestPlugin:
43            pass
44
45        class Oneword:
46            pass
47
48        class TestHTML:
49            pass
50
51        assert 'test_plugin' not in plugin.plugins
52
53        @event('plugin.register')
54        def rp():
55            plugin.register(TestPlugin, api_ver=2)
56            plugin.register(Oneword, api_ver=2)
57            plugin.register(TestHTML, api_ver=2)
58
59        # Call load_plugins again to register our new plugins
60        plugin.load_plugins()
61        assert 'test_plugin' in plugin.plugins
62        assert 'oneword' in plugin.plugins
63        assert 'test_html' in plugin.plugins
64
65
66class TestExternalPluginLoading:
67    _config = """
68        tasks:
69          ext_plugin:
70            external_plugin: yes
71    """
72
73    @pytest.fixture()
74    def config(self, request):
75        os.environ['FLEXGET_PLUGIN_PATH'] = (
76            request.fspath.dirpath().join('external_plugins').strpath
77        )
78        plugin.load_plugins()
79        # fire the config register event again so that task schema is rebuilt with new plugin
80        fire_event('config.register')
81        yield self._config
82        del os.environ['FLEXGET_PLUGIN_PATH']
83
84    def test_external_plugin_loading(self, execute_task):
85        # TODO: This isn't working because calling load_plugins again doesn't cause the schema for tasks to regenerate
86        task = execute_task('ext_plugin')
87        assert task.find_entry(title='test entry'), 'External plugin did not create entry'
88