Skip to content

session: replace usage of deprecated imp module #3366

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Dec 3, 2020

Conversation

bastimeyer
Copy link
Member

Refactor utils.load_module:

  • move it to the top and add it to __all__
  • move imports and loader_details to the global scope

Refactor session:

  • replace plugin imports via imp with utils.load_module
  • fix incorrect plugin module names
    "streamlink.plugin.{name}" -> "streamlink.plugins.{name}"
  • use log.exception() to print plugin load failures
  • remove unused print_small_exception

Add / fix tests:

  • remove session dependency from test_plugins
  • add proper assertions for plugin modules, methods and their signatures
  • add tests for invalid and for overridden plugins

Based on the changes of #2570

Things to note

  • I've decided to keep the implementation of importlib.machinery.FileFinder in the utils module and use that for loading the plugins, as I had some issues with the module names while trying out the pkgutils-based imports of session: use importlib to load plugins in Python 3 #2570, which led to plugins log calls not being recognized by the StreamlinkLogger, as their module names did not begin with streamlink..
  • test_session is really messy as it imports everything in tests.plugins, including all plugin test modules, which are irrelevant there. The actual testplugins should be moved somewhere else. Mocking certain things is also impossible when everything is run in the test's setUp, and I couldn't mock the log call of the plugin override without patching the whole test class which would require adding an unused argument to every test method. That's why plugin load failures are also not tested.
  • Why does plugin.api.support_plugin even exist? It's not being used and it looks totally unnecessary. This module is the reason why utils.load_module existed, but now it's being used by session as well.

Refactor `utils.load_module`:
- move it to the top and add it to `__all__`
- move imports and loader_details to the global scope

Refactor `session`:
- replace plugin imports via `imp` with `utils.load_module`
- fix incorrect plugin module names
  "streamlink.plugin.{name}" -> "streamlink.plugins.{name}"
- use `log.exception()` to print plugin load failures
- remove unused `print_small_exception`

Add / fix tests:
- remove session dependency from test_plugins
- add proper assertions for plugin modules, methods and their signatures
- add tests for invalid and for overridden plugins
@bastimeyer bastimeyer mentioned this pull request Nov 26, 2020
25 tasks
@back-to
Copy link
Collaborator

back-to commented Nov 27, 2020

try:
mod = load_module(module_name, path)
except ImportError:
log.exception(f"Failed to load plugin {name} from {path}\n")
continue

it is not always ImportError which will change the behavior of Streamlink a bit,
broken plugins will error Streamlink instead of skipping the plugin.

Not that important but just to be noted.


Why does plugin.api.support_plugin even exist?

we don't need it, could probably be removed,
same for the common_ plugins

@bastimeyer
Copy link
Member Author

it is not always ImportError

According to the docs, both the finder and loader will raise an ImportError (or one of their subclasses) on failure. Same does the load_module method if there's no spec or spec.loader. What else is there to be aware of?

@back-to
Copy link
Collaborator

back-to commented Nov 27, 2020

Example: if you sideload a broken plugin


Traceback (most recent call last):
  File "venv/bin/streamlink", line 33, in <module>
    sys.exit(load_entry_point('streamlink', 'console_scripts', 'streamlink')())
  File "src/streamlink_cli/main.py", line 1012, in main
    setup_plugins(args.plugin_dirs)
  File "src/streamlink_cli/main.py", line 739, in setup_plugins
    load_plugins([PLUGINS_DIR])
  File "src/streamlink_cli/main.py", line 640, in load_plugins
    streamlink.load_plugins(directory)
  File "src/streamlink/session.py", line 414, in load_plugins
    mod = load_module(module_name, path)
  File "src/streamlink/utils/__init__.py", line 25, in load_module
    spec.loader.exec_module(mod)
  File "<frozen importlib._bootstrap_external>", line 779, in exec_module
  File "<frozen importlib._bootstrap_external>", line 916, in get_code
  File "<frozen importlib._bootstrap_external>", line 846, in source_to_code
  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
  File "/home/.../.config/streamlink/plugins/testplugin.py", line 36
    __plu gin__ = Teamliquid
          ^
SyntaxError: invalid syntax
Traceback (most recent call last):
  File "venv/bin/streamlink", line 33, in <module>
    sys.exit(load_entry_point('streamlink', 'console_scripts', 'streamlink')())
  File "src/streamlink_cli/main.py", line 1012, in main
    setup_plugins(args.plugin_dirs)
  File "src/streamlink_cli/main.py", line 739, in setup_plugins
    load_plugins([PLUGINS_DIR])
  File "src/streamlink_cli/main.py", line 640, in load_plugins
    streamlink.load_plugins(directory)
  File "src/streamlink/session.py", line 414, in load_plugins
    mod = load_module(module_name, path)
  File "src/streamlink/utils/__init__.py", line 25, in load_module
    spec.loader.exec_module(mod)
  File "<frozen importlib._bootstrap_external>", line 779, in exec_module
  File "<frozen importlib._bootstrap_external>", line 916, in get_code
  File "<frozen importlib._bootstrap_external>", line 846, in source_to_code
  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
  File "/home/.../.config/streamlink/plugins/testplugin.py", line 19
    def _get_streams(self):
                          ^
IndentationError: unindent does not match any outer indentation level

@bastimeyer
Copy link
Member Author

bastimeyer commented Nov 27, 2020

If you want, I can "revert" this change of logic by adding a secondary except SyntaxError: block and adding back print_small_exception, so that custom plugin errors can be written to stderr while continuing Streamlink's execution.

I personally am OK though with Streamlink failing if code of a custom plugin causes a parsing error.

@back-to
Copy link
Collaborator

back-to commented Nov 27, 2020

If you want, I can "revert" this change

no it's fine, can stay like this.

@OlMon OlMon mentioned this pull request Dec 3, 2020
2 tasks
@back-to
Copy link
Collaborator

back-to commented Dec 3, 2020

well, lets test this with a large user base.

@back-to back-to merged commit 156d870 into streamlink:master Dec 3, 2020
@bastimeyer
Copy link
Member Author

Maybe we should add a note to the sideloading plugins section in the docs that plugins which fail parsing will make Streamlink terminate its process beginning with 2.0.0.
I'll open a PR later or tomorrow. Maybe I'll also refactor the tests (see my comment above).

Will also take a look at the support_plugin thing again. I don't think it makes sense keeping it.

back-to added a commit to back-to/streamlink that referenced this pull request Dec 14, 2020
since streamlink#3366
https://github.com/streamlink/streamlink/blob/5e7a04b006d0e4d7a884b13bf2aa8047791b837b/src/streamlink/session.py#L412
the logger is `[plugins.afreeca]` which was `[plugin.afreeca]` before

update the cls.logger so it will be `[plugins.afreeca]` also

after this PR

```
[plugins.afreeca][debug] Restored cookies: ...
...
[plugins.afreeca][debug] Attempting to authenticate using cached cookies
```
gravyboat pushed a commit that referenced this pull request Dec 14, 2020
since #3366
https://github.com/streamlink/streamlink/blob/5e7a04b006d0e4d7a884b13bf2aa8047791b837b/src/streamlink/session.py#L412
the logger is `[plugins.afreeca]` which was `[plugin.afreeca]` before

update the cls.logger so it will be `[plugins.afreeca]` also

after this PR

```
[plugins.afreeca][debug] Restored cookies: ...
...
[plugins.afreeca][debug] Attempting to authenticate using cached cookies
```
Billy2011 pushed a commit to Billy2011/streamlink-27 that referenced this pull request Dec 15, 2020
since streamlink#3366
https://github.com/streamlink/streamlink/blob/5e7a04b006d0e4d7a884b13bf2aa8047791b837b/src/streamlink/session.py#L412
the logger is `[plugins.afreeca]` which was `[plugin.afreeca]` before

update the cls.logger so it will be `[plugins.afreeca]` also

after this PR

```
[plugins.afreeca][debug] Restored cookies: ...
...
[plugins.afreeca][debug] Attempting to authenticate using cached cookies
```
Billy2011 pushed a commit to Billy2011/streamlink-27 that referenced this pull request Dec 17, 2020
since streamlink#3366
https://github.com/streamlink/streamlink/blob/5e7a04b006d0e4d7a884b13bf2aa8047791b837b/src/streamlink/session.py#L412
the logger is `[plugins.afreeca]` which was `[plugin.afreeca]` before

update the cls.logger so it will be `[plugins.afreeca]` also

after this PR

```
[plugins.afreeca][debug] Restored cookies: ...
...
[plugins.afreeca][debug] Attempting to authenticate using cached cookies
```
@bastimeyer bastimeyer deleted the deprecations/imp branch January 19, 2021 23:16
Billy2011 added a commit to Billy2011/streamlink-27 that referenced this pull request Feb 8, 2021
- add proper assertions for plugin modules, methods and their signatures
- add tests for invalid and for overridden plugins

based on streamlink#3366
Billy2011 added a commit to Billy2011/streamlink-27 that referenced this pull request Feb 8, 2021
- add proper assertions for plugin modules, methods and their signatures
- add tests for invalid and for overridden plugins

based on streamlink#3366
Billy2011 added a commit to Billy2011/streamlink-27 that referenced this pull request Feb 8, 2021
- add proper assertions for plugin modules, methods and their signatures
- add tests for invalid and for overridden plugins

based on streamlink#3366
Billy2011 added a commit to Billy2011/streamlink-27 that referenced this pull request Feb 9, 2021
- add proper assertions for plugin modules, methods and their signatures
- add tests for invalid and for overridden plugins

based on streamlink#3366

Update test_plugins.py
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants