ytdl-sub/tools/docgen/plugins.py
Jesse Bannon 1abe2a44f5
[BACKEND] Refactor validation, preparation for subscription dissect (#1398)
Completely rewrite how subscription validation is performed. Optimizes it quite a bit while also adding backend support for the upcoming `dissect` sub-command, where you can resolve any subscription into its 'raw' form for easier debugging when making scripting changes.
2025-12-30 17:03:59 -08:00

96 lines
2.9 KiB
Python

import inspect
from pathlib import Path
from typing import Any
from typing import Dict
from typing import Type
from tools.docgen.docgen import DocGen
from tools.docgen.utils import line_section
from tools.docgen.utils import properties
from tools.docgen.utils import section
from ytdl_sub.config.overrides import Overrides
from ytdl_sub.config.plugin.plugin_mapping import PluginMapping
from ytdl_sub.config.preset_options import OutputOptions
from ytdl_sub.config.preset_options import YTDLOptions
from ytdl_sub.config.validators.options import OptionsValidator
from ytdl_sub.downloaders.url.validators import MultiUrlValidator
def should_filter_all_properties(plugin_name: str) -> bool:
return plugin_name in (
"format",
"match_filters",
"music_tags",
"filter_include",
"filter_exclude",
"embed_thumbnail",
"square_thumbnail",
"video_tags",
"download",
)
def should_filter_property(property_name: str) -> bool:
return property_name.startswith("_") or property_name in (
"value",
"source_variable_capture_dict",
"dict",
"keys",
"dict_with_format_strings",
"dict_with_parsed_format_strings",
"subscription_name",
"list",
"script",
"unresolvable",
"leaf_name",
)
def get_function_docs(function_name: str, obj: Any, level: int) -> str:
docs = f"\n``{function_name}``\n\n"
docs += inspect.cleandoc(getattr(obj, function_name).__doc__)
docs += "\n\n"
return docs
def generate_plugin_docs(name: str, options: Type[OptionsValidator], offset: int) -> str:
docs = ""
docs += section(name, level=offset + 0)
docs += inspect.cleandoc(options.__doc__)
docs += "\n"
if should_filter_all_properties(name):
return docs
property_names = [prop for prop in properties(options) if not should_filter_property(prop)]
for property_name in sorted(property_names):
docs += get_function_docs(function_name=property_name, obj=options, level=offset + 1)
return docs
class PluginsDocGen(DocGen):
LOCATION = Path("docs/source/config_reference/plugins.rst")
DOCSTRING_LOCATION = "The respective plugin files under src/ytdl_sub/plugins/"
@classmethod
def generate(cls):
options_dict: Dict[str, Type[OptionsValidator]] = {
"output_options": OutputOptions,
"ytdl_options": YTDLOptions,
"overrides": Overrides,
"download": MultiUrlValidator,
}
for plugin_name, plugin_type in PluginMapping._MAPPING.items():
if plugin_name.startswith("_"):
continue
options_dict[plugin_name] = plugin_type.plugin_options_type
docs = section("Plugins", level=0)
for idx, name in enumerate(sorted(options_dict.keys())):
docs += line_section(section_idx=idx)
docs += generate_plugin_docs(name, options_dict[name], offset=1)
return docs