Skip to content

Conversation

@bastimeyer
Copy link
Member

@bastimeyer bastimeyer commented Dec 9, 2023

This explicitly adds all keywords which are passed to argparse.ArgumentParser.add_argument() to the pluginargument decorator (Argument class). It also turns all options except for name into mandatory keywords (which is technically a breaking change, but I don't think anyone with common sense has defined custom plugin arguments using positional args).

The intention here is simplifying the parsing of the plugin module AST when building a plugins JSON file with all matchers and arguments (#4741), so Streamlink doesn't have to load all plugins at once. This is what I've been working on again in the past couple of days. It also improves type checking of all plugin arguments.


Opening this as a draft for now, because I don't want these changes to be included in the next release yet.

Unrelated to this PR, there's also one issue left with these changes which I will have to think about, namely the argument's type option.

The type option is currently defined as Callable[[Any], Any] | None, but this makes it impossible to serialize when building the plugins JSON data.

The data serializer needs to implement an import path lookup, so the type option can reference the actual callable again, e.g. streamlink.utils.args.keyvalue or streamlink.utils.times.hours_minutes_seconds. These are currently the two functions being used by Streamlink's plugins, but other callables like builtin ones need to be supported as well, like int for example. It will however restrict any custom functions defined in plugin modules, should this ever be required. Third party plugins won't be affected by the pluginargument serialization/deserialization, because those have to be loaded all at once beforehand anyway.

@bastimeyer bastimeyer force-pushed the options/argument/refactor branch 2 times, most recently from 19ab00d to a1f8ec9 Compare December 11, 2023 14:20
@gravyboat
Copy link
Member

It will however restrict any custom functions defined in plugin modules

I don't think this potential edge case should be high on the list of considerations. The restriction trade off for the clarity we'll gain is worth it.

@bastimeyer
Copy link
Member Author

Going to update and rebase this PR after #5778 got merged.

mandatory keywords

I will remove this again, because it's not important.

The pluginargument() decorator (not the Argument class though) will then be updated, so that the type keyword can receive a string value. This string value then gets mapped onto the functions in utils.args, so that all plugins can reference these argument-type functions. For those functions which receive additional args, I will add the type_args keyword to pluginargument(), which must consist of simple literals that can be parsed on the module's AST.

This way, plugins can have custom argument types and the script which parses the plugin matchers and plugin arguments can properly serialize the plugin arguments data into JSON.

- Explicitly define keywords passed to `ArgumentParser.add_argument()`
  so they can be properly type-checked
- Update `Argument.options` accordingly and add tests
- Fix `Argument.requires` value
- Update docstrings
@bastimeyer bastimeyer force-pushed the options/argument/refactor branch from a1f8ec9 to 5b243a5 Compare January 16, 2024 13:30
@bastimeyer bastimeyer marked this pull request as ready for review January 16, 2024 13:30
@bastimeyer bastimeyer merged commit e56adac into streamlink:master Jan 16, 2024
@bastimeyer bastimeyer deleted the options/argument/refactor branch January 16, 2024 13:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants