Skip to content

Commit b4dc047

Browse files
[yt-dlp] Check common code in extractor subpackage with stubtest (#14682)
1 parent 3542650 commit b4dc047

File tree

4 files changed

+59
-39
lines changed

4 files changed

+59
-39
lines changed

stubs/yt-dlp/@tests/stubtest_allowlist.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# Extractors will not be stubbed at this time.
2-
yt_dlp.extractor.*
2+
yt_dlp.extractor\.(?!__init__|common*).*
33
# Postprocessors will not be stubbed at this time.
44
yt_dlp.postprocessor.*
55
# Won't be covered.

stubs/yt-dlp/yt_dlp/extractor/common.pyi

Lines changed: 48 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,16 @@ from _typeshed import Unused
33
from collections.abc import Callable, Collection, Iterable, Iterator, Mapping, Sequence
44
from functools import cached_property
55
from json.decoder import JSONDecoder
6-
from typing import Any, Literal, TypedDict, TypeVar, type_check_only
7-
from typing_extensions import Required, TypeAlias
6+
from typing import Any, ClassVar, Literal, TypedDict, TypeVar, overload, type_check_only
7+
from typing_extensions import Never, Required, TypeAlias, deprecated
88
from urllib.request import Request, _DataType
99
from xml.etree import ElementTree as ET
1010

1111
from ..cache import Cache
1212
from ..cookies import LenientSimpleCookie, YoutubeDLCookieJar
1313
from ..networking.common import Response, _RequestData
1414
from ..networking.impersonate import ImpersonateTarget
15-
from ..utils._utils import NO_DEFAULT, RetryManager as _RetryManager
15+
from ..utils._utils import NO_DEFAULT, ExtractorError, FormatSorter, RetryManager as _RetryManager, classproperty
1616
from ..YoutubeDL import YoutubeDL
1717

1818
@type_check_only
@@ -37,9 +37,9 @@ _StrNoDefaultOrNone: TypeAlias = str | None | type[NO_DEFAULT]
3737
_T = TypeVar("_T")
3838

3939
class InfoExtractor:
40-
IE_DESC: str | bool
41-
SEARCH_KEY: str
42-
def _login_hint(self, method: _StrNoDefaultOrNone, netrc: str | None = None) -> dict[str, str]: ...
40+
IE_DESC: ClassVar[str | bool | None]
41+
SEARCH_KEY: ClassVar[str | None]
42+
def _login_hint(self, method: _StrNoDefaultOrNone = ..., netrc: str | None = None) -> dict[str, str]: ...
4343
def __init__(self, downloader: YoutubeDL | None = None) -> None: ...
4444
@classmethod
4545
def _match_valid_url(cls, url: str) -> re.Match[str] | None: ...
@@ -82,8 +82,8 @@ class InfoExtractor:
8282
fatal: bool = True,
8383
encoding: str | None = None,
8484
data: _DataType | None = None,
85-
headers: Mapping[str, str] | None = None,
86-
query: str | Mapping[str, str] | None = None,
85+
headers: Mapping[str, str] | None = {},
86+
query: str | Mapping[str, str] | None = {},
8787
expected_status: int | None = None,
8888
impersonate: ImpersonateTarget | str | bool | Collection[str | ImpersonateTarget] | None = None,
8989
require_impersonation: bool = False,
@@ -128,14 +128,21 @@ class InfoExtractor:
128128
parse_constant: Callable[[str], Any] | None = None,
129129
object_pairs_hook: Callable[[list[tuple[Any, Any]]], Any] | None = None,
130130
) -> Any: ...
131-
def report_warning(self, msg: str, video_id: str | None = None, only_once: bool = False) -> None: ...
131+
# *args and **kwargs are passed to self._downloader.report_warning().
132+
def report_warning(
133+
self, msg: str, video_id: str | None = None, *args: Any, only_once: bool = False, **kwargs: Any
134+
) -> None: ...
132135
def to_screen(
133136
self, msg: str, message: str, skip_eol: bool = False, quiet: bool | None = None, only_once: bool = False
134137
) -> None: ...
135138
def write_debug(self, msg: str, only_once: bool = False) -> None: ...
136139
# *args and **kwargs are passed to .params.get() where params is normally a mapping but is not required to be.
137140
def get_param(self, name: str, default: Any = None, *args: Any, **kwargs: Any) -> Any: ...
138-
def report_drm(self, video_id: str) -> None: ...
141+
@overload
142+
def report_drm(self, video_id: str, partial: type[NO_DEFAULT] = ...) -> None: ...
143+
@overload
144+
@deprecated("InfoExtractor.report_drm no longer accepts the argument partial")
145+
def report_drm(self, video_id: str, partial: bool) -> None: ...
139146
def report_extraction(self, id_or_name: str) -> None: ...
140147
def report_download_webpage(self, video_id: str) -> None: ...
141148
def report_age_confirmation(self) -> None: ...
@@ -149,7 +156,12 @@ class InfoExtractor:
149156
def raise_geo_restricted(
150157
self, msg: str = ..., countries: Collection[str] | None = None, metadata_available: bool = False
151158
) -> None: ...
152-
def raise_no_formats(self, msg: str, expected: bool = False, video_id: str | None = None) -> None: ...
159+
@overload
160+
def raise_no_formats(
161+
self, msg: str | ExtractorError, expected: Literal[False] = False, video_id: str | None = None
162+
) -> Never: ...
163+
@overload
164+
def raise_no_formats(self, msg: str | ExtractorError, expected: Literal[True], video_id: str | None = None) -> None: ...
153165
@staticmethod
154166
def url_result(
155167
url: str,
@@ -169,7 +181,6 @@ class InfoExtractor:
169181
getter: Callable[..., Any] = ...,
170182
ie: InfoExtractor | None = None,
171183
video_kwargs: Mapping[str, Any] | None = None,
172-
multi_video: bool = False,
173184
**kwargs: Any, # Added to the dict return value.
174185
) -> dict[str, Any]: ...
175186
@staticmethod
@@ -212,7 +223,7 @@ class InfoExtractor:
212223
headers: Mapping[str, str] = {},
213224
query: Mapping[str, str] = {},
214225
expected_status: int | None = None,
215-
impersonate: str | None = None,
226+
impersonate: ImpersonateTarget | str | bool | Collection[str | ImpersonateTarget] | None = None,
216227
require_impersonation: bool = False,
217228
) -> tuple[ET.ElementTree, Response]: ...
218229
def _download_xml(
@@ -228,7 +239,7 @@ class InfoExtractor:
228239
headers: Mapping[str, str] = {},
229240
query: Mapping[str, str] = {},
230241
expected_status: int | None = None,
231-
impersonate: str | None = None,
242+
impersonate: ImpersonateTarget | str | bool | Collection[str | ImpersonateTarget] | None = None,
232243
require_impersonation: bool = False,
233244
) -> ET.ElementTree: ...
234245
def _download_socket_json_handle(
@@ -244,7 +255,7 @@ class InfoExtractor:
244255
headers: Mapping[str, str] = {},
245256
query: Mapping[str, str] = {},
246257
expected_status: int | None = None,
247-
impersonate: str | None = None,
258+
impersonate: ImpersonateTarget | str | bool | Collection[str | ImpersonateTarget] | None = None,
248259
require_impersonation: bool = False,
249260
) -> tuple[dict[str, Any], Response]: ...
250261
def _download_socket_json(
@@ -260,7 +271,7 @@ class InfoExtractor:
260271
headers: Mapping[str, str] = {},
261272
query: Mapping[str, str] = {},
262273
expected_status: int | None = None,
263-
impersonate: str | None = None,
274+
impersonate: ImpersonateTarget | str | bool | Collection[str | ImpersonateTarget] | None = None,
264275
require_impersonation: bool = False,
265276
) -> dict[str, Any]: ...
266277
def _download_json_handle(
@@ -276,7 +287,7 @@ class InfoExtractor:
276287
headers: Mapping[str, str] = {},
277288
query: Mapping[str, str] = {},
278289
expected_status: int | None = None,
279-
impersonate: str | None = None,
290+
impersonate: ImpersonateTarget | str | bool | Collection[str | ImpersonateTarget] | None = None,
280291
require_impersonation: bool = False,
281292
) -> tuple[dict[str, Any], Response]: ...
282293
def _download_json(
@@ -292,7 +303,7 @@ class InfoExtractor:
292303
headers: Mapping[str, str] = {},
293304
query: Mapping[str, str] = {},
294305
expected_status: int | None = None,
295-
impersonate: str | None = None,
306+
impersonate: ImpersonateTarget | str | bool | Collection[str | ImpersonateTarget] | None = None,
296307
require_impersonation: bool = False,
297308
) -> dict[str, Any]: ...
298309
def _download_webpage(
@@ -301,14 +312,17 @@ class InfoExtractor:
301312
video_id: str,
302313
note: str | None = None,
303314
errnote: str | None = None,
304-
transform_source: Callable[..., str] | None = ...,
305315
fatal: bool = True,
316+
tries: int = 1,
317+
timeout: float | type[NO_DEFAULT] = ...,
318+
# Remaining arguments are collected with *args, **kwargs and
319+
# forwarded to _download_webpage_handle().
306320
encoding: str | None = ...,
307321
data: _DataType | None = ...,
308322
headers: Mapping[str, str] = ...,
309323
query: Mapping[str, str] = ...,
310324
expected_status: int | None = ...,
311-
impersonate: str | None = ...,
325+
impersonate: ImpersonateTarget | str | bool | Collection[str | ImpersonateTarget] | None = ...,
312326
require_impersonation: bool = ...,
313327
) -> str: ...
314328
def _parse_xml(
@@ -333,7 +347,7 @@ class InfoExtractor:
333347
) -> Literal["needs_auth", "premium_only", "private", "public", "subscriber_only", "unlisted"] | None: ...
334348
def _request_webpage(
335349
self,
336-
url_or_req: str | Request,
350+
url_or_request: str | Request,
337351
video_id: str,
338352
note: str | None = None,
339353
errnote: str | None = None,
@@ -342,6 +356,8 @@ class InfoExtractor:
342356
headers: Mapping[str, str] | None = None,
343357
query: Mapping[str, str] | None = None,
344358
expected_status: int | None = None,
359+
impersonate: ImpersonateTarget | str | bool | Collection[str | ImpersonateTarget] | None = None,
360+
require_impersonation: bool = False,
345361
) -> Response | Literal[False]: ...
346362
@classmethod
347363
def _match_id(cls, url: str) -> str: ...
@@ -418,15 +434,7 @@ class InfoExtractor:
418434
group: tuple[int, ...] | list[int] | None = None,
419435
fatal: bool = False,
420436
) -> str | None: ...
421-
def _html_search_meta(
422-
self,
423-
name: str,
424-
html: str,
425-
display_name: str | None = None,
426-
fatal: bool = False,
427-
flags: int = 0,
428-
group: tuple[int, ...] | list[int] | None = None,
429-
) -> str | None: ...
437+
def _html_search_meta(self, name: str, html: str, display_name: str | None = None, fatal: bool = False) -> str | None: ...
430438
def _dc_search_uploader(self, html: str) -> str | None: ...
431439
@staticmethod
432440
def _rta_search(html: str) -> int: ...
@@ -464,6 +472,11 @@ class InfoExtractor:
464472
@staticmethod
465473
def _hidden_inputs(html: str) -> dict[str, Any]: ...
466474
def _form_hidden_inputs(self, form_id: str, html: str) -> dict[str, Any]: ...
475+
@classproperty
476+
@deprecated(
477+
"yt_dlp.InfoExtractor.FormatSort is deprecated and may be removed in the future. Use yt_dlp.utils.FormatSorter instead"
478+
)
479+
def FormatSort(self) -> FormatSorter: ...
467480
def _check_formats(self, formats: list[dict[str, Any]], video_id: str) -> None: ...
468481
@staticmethod
469482
def _remove_duplicate_formats(formats: list[dict[str, Any]]) -> None: ...
@@ -792,7 +805,7 @@ class InfoExtractor:
792805
def _live_title(self, name: _T) -> _T: ...
793806
def _get_cookies(self, url: str) -> LenientSimpleCookie: ...
794807
def _apply_first_set_cookie_header(self, url_handle: Response, cookie: str) -> None: ...
795-
@property
808+
@classproperty
796809
def _RETURN_TYPE(cls) -> str: ...
797810
def _get_subtitles(self, *args: Any, **kwargs: Any) -> list[dict[str, Any]]: ... # Not implemented here.
798811
# Passes *args and **kwargs to _get_comments.
@@ -864,5 +877,8 @@ class SearchInfoExtractor(InfoExtractor):
864877
def _real_extract(self, query: str) -> _InfoDict: ...
865878
def _get_n_results(self, query: str, n: int) -> list[_InfoDict]: ...
866879
def _search_results(self, query: str) -> list[_InfoDict]: ...
880+
@classproperty
881+
def SEARCH_KEY(self) -> str | None: ...
867882

868-
class UnsupportedURLIE(InfoExtractor): ...
883+
class UnsupportedURLIE(InfoExtractor):
884+
IE_DESC: ClassVar[bool]
Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1+
from typing import ClassVar
2+
13
from .common import InfoExtractor
24

35
class CommonMistakesIE(InfoExtractor):
4-
IE_DESC: bool
6+
IE_DESC: ClassVar[bool]
57

68
class UnicodeBOMIE(InfoExtractor):
7-
IE_DESC: bool
9+
IE_DESC: ClassVar[bool]
810

911
class BlobIE(InfoExtractor):
10-
IE_DESC: bool
12+
IE_DESC: ClassVar[bool]
Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1+
from typing import ClassVar
2+
13
from .common import InfoExtractor
24

35
class RtmpIE(InfoExtractor):
4-
IE_DESC: bool
6+
IE_DESC: ClassVar[bool]
57

68
class MmsIE(InfoExtractor):
7-
IE_DESC: bool
9+
IE_DESC: ClassVar[bool]
810

911
class ViewSourceIE(InfoExtractor):
10-
IE_DESC: bool
12+
IE_DESC: ClassVar[bool]

0 commit comments

Comments
 (0)