]> jfr.im git - yt-dlp.git/commitdiff
[cleanup] Misc
authorpukkandan <redacted>
Wed, 16 Nov 2022 00:57:43 +0000 (06:27 +0530)
committerpukkandan <redacted>
Wed, 16 Nov 2022 01:27:07 +0000 (06:57 +0530)
Closes #5541

75 files changed:
devscripts/lazy_load_template.py
devscripts/make_lazy_extractors.py
test/parameters.json
yt_dlp/YoutubeDL.py
yt_dlp/extractor/adobepass.py
yt_dlp/extractor/aenetworks.py
yt_dlp/extractor/afreecatv.py
yt_dlp/extractor/alura.py
yt_dlp/extractor/amcnetworks.py
yt_dlp/extractor/amp.py
yt_dlp/extractor/aol.py
yt_dlp/extractor/audius.py
yt_dlp/extractor/aws.py
yt_dlp/extractor/bandaichannel.py
yt_dlp/extractor/bandcamp.py
yt_dlp/extractor/bbc.py
yt_dlp/extractor/bfmtv.py
yt_dlp/extractor/bilibili.py
yt_dlp/extractor/cbs.py
yt_dlp/extractor/cbsinteractive.py
yt_dlp/extractor/cbslocal.py
yt_dlp/extractor/cbsnews.py
yt_dlp/extractor/cmt.py
yt_dlp/extractor/common.py
yt_dlp/extractor/corus.py
yt_dlp/extractor/daum.py
yt_dlp/extractor/dreisat.py
yt_dlp/extractor/extremetube.py
yt_dlp/extractor/fancode.py
yt_dlp/extractor/hitbox.py
yt_dlp/extractor/imgur.py
yt_dlp/extractor/jamendo.py
yt_dlp/extractor/la7.py
yt_dlp/extractor/laola1tv.py
yt_dlp/extractor/lcp.py
yt_dlp/extractor/mediaset.py
yt_dlp/extractor/mitele.py
yt_dlp/extractor/mofosex.py
yt_dlp/extractor/mtv.py
yt_dlp/extractor/murrtube.py
yt_dlp/extractor/musicdex.py
yt_dlp/extractor/nationalgeographic.py
yt_dlp/extractor/nbc.py
yt_dlp/extractor/ndr.py
yt_dlp/extractor/nextmedia.py
yt_dlp/extractor/nick.py
yt_dlp/extractor/npo.py
yt_dlp/extractor/nrk.py
yt_dlp/extractor/once.py
yt_dlp/extractor/peekvids.py
yt_dlp/extractor/radlive.py
yt_dlp/extractor/rai.py
yt_dlp/extractor/redbulltv.py
yt_dlp/extractor/rts.py
yt_dlp/extractor/rtve.py
yt_dlp/extractor/rutube.py
yt_dlp/extractor/sevenplus.py
yt_dlp/extractor/skyit.py
yt_dlp/extractor/southpark.py
yt_dlp/extractor/tele5.py
yt_dlp/extractor/theweatherchannel.py
yt_dlp/extractor/tiktok.py
yt_dlp/extractor/toutv.py
yt_dlp/extractor/tube8.py
yt_dlp/extractor/tvnow.py
yt_dlp/extractor/udemy.py
yt_dlp/extractor/uplynk.py
yt_dlp/extractor/usanetwork.py
yt_dlp/extractor/veoh.py
yt_dlp/extractor/vgtv.py
yt_dlp/extractor/vimeo.py
yt_dlp/extractor/vvvvid.py
yt_dlp/extractor/wdr.py
yt_dlp/extractor/youtube.py
yt_dlp/utils.py

index 626b85d6209ba4c49c00d388c52f2d500633371c..c8815e01bc67fd1f9cb7d4f417daa8d883d7248f 100644 (file)
@@ -10,7 +10,7 @@
 )
 
 # These bloat the lazy_extractors, so allow them to passthrough silently
-ALLOWED_CLASSMETHODS = {'get_testcases', 'extract_from_webpage'}
+ALLOWED_CLASSMETHODS = {'extract_from_webpage', 'get_testcases', 'get_webpage_testcases'}
 _WARNED = False
 
 
index 2d4530eb967ebf1881b9fc3b7277b184f988fe82..c502bdf896135f7f6b4d289ff273171cc21bc4be 100644 (file)
 
 NO_ATTR = object()
 STATIC_CLASS_PROPERTIES = [
-    'IE_NAME', 'IE_DESC', 'SEARCH_KEY', '_VALID_URL', '_WORKING', '_ENABLED', '_NETRC_MACHINE', 'age_limit'
+    'IE_NAME', '_ENABLED', '_VALID_URL',  # Used for URL matching
+    '_WORKING', 'IE_DESC', '_NETRC_MACHINE', 'SEARCH_KEY',  # Used for --extractor-descriptions
+    'age_limit',  # Used for --age-limit (evaluated)
+    '_RETURN_TYPE',  # Accessed in CLI only with instance (evaluated)
 ]
 CLASS_METHODS = [
-    'ie_key', 'working', 'description', 'suitable', '_match_valid_url', '_match_id', 'get_temp_id', 'is_suitable'
+    'ie_key', 'suitable', '_match_valid_url',  # Used for URL matching
+    'working', 'get_temp_id', '_match_id',  # Accessed just before instance creation
+    'description',  # Used for --extractor-descriptions
+    'is_suitable',  # Used for --age-limit
+    'supports_login', 'is_single_video',  # Accessed in CLI only with instance
 ]
 IE_TEMPLATE = '''
 class {name}({bases}):
index bc456137412d263118d99a1f6e3d60bcdff07a71..8789ce14b3f403ffa69aeba8c737453f230f3a6c 100644 (file)
@@ -44,5 +44,6 @@
     "writesubtitles": false,
     "allsubtitles": false,
     "listsubtitles": false,
-    "fixup": "never"
+    "fixup": "never",
+    "allow_playlist_files": false
 }
index 525d3ab6e57e97212bda3a1752c9706c2cacc8b1..20940085e843b7144164fe8853a6e923de105a88 100644 (file)
@@ -1357,7 +1357,7 @@ def prepare_filename(self, info_dict, dir_type='', *, outtmpl=None, warn=False):
         return self.get_output_path(dir_type, filename)
 
     def _match_entry(self, info_dict, incomplete=False, silent=False):
-        """ Returns None if the file should be downloaded """
+        """Returns None if the file should be downloaded"""
         _type = info_dict.get('_type', 'video')
         assert incomplete or _type == 'video', 'Only video result can be considered complete'
 
@@ -1381,6 +1381,7 @@ def check_filter():
                 if rejecttitle:
                     if re.search(rejecttitle, title, re.IGNORECASE):
                         return '"' + title + '" title matched reject pattern "' + rejecttitle + '"'
+
             date = info_dict.get('upload_date')
             if date is not None:
                 dateRange = self.params.get('daterange', DateRange())
@@ -2953,8 +2954,6 @@ def process_info(self, info_dict):
         if 'format' not in info_dict and 'ext' in info_dict:
             info_dict['format'] = info_dict['ext']
 
-        # This is mostly just for backward compatibility of process_info
-        # As a side-effect, this allows for format-specific filters
         if self._match_entry(info_dict) is not None:
             info_dict['__write_download_archive'] = 'ignore'
             return
index ec1be008a370a7402cb44bf4dea9b15d4d4e1549..e5944f7146c239cf181eac5bb3c87de373870224 100644 (file)
 }
 
 
-class AdobePassIE(InfoExtractor):
+class AdobePassIE(InfoExtractor):  # XXX: Conventionally, base classes should end with BaseIE/InfoExtractor
     _SERVICE_PROVIDER_TEMPLATE = 'https://sp.auth.adobe.com/adobe-services/%s'
     _USER_AGENT = 'Mozilla/5.0 (X11; Linux i686; rv:47.0) Gecko/20100101 Firefox/47.0'
     _MVPD_CACHE = 'ap-mvpd'
index 516cb6302ce0957f7034e05bd3341edcd036e8c7..094c57bf928e4993a8c52dc21dc42fceaa91887c 100644 (file)
@@ -8,7 +8,7 @@
 )
 
 
-class AENetworksBaseIE(ThePlatformIE):
+class AENetworksBaseIE(ThePlatformIE):  # XXX: Do not subclass from concrete IE
     _BASE_URL_REGEX = r'''(?x)https?://
         (?:(?:www|play|watch)\.)?
         (?P<domain>
@@ -304,7 +304,6 @@ def _real_extract(self, url):
 class HistoryPlayerIE(AENetworksBaseIE):
     IE_NAME = 'history:player'
     _VALID_URL = r'https?://(?:www\.)?(?P<domain>(?:history|biography)\.com)/player/(?P<id>\d+)'
-    _TESTS = []
 
     def _real_extract(self, url):
         domain, video_id = self._match_valid_url(url).groups()
index b0fd158f6164e1a6afdbfe2bb59904f4f30eb45f..bfcc0803080fc67b87abcee0e50dcf17e85f91a9 100644 (file)
@@ -380,7 +380,7 @@ def _real_extract(self, url):
         return info
 
 
-class AfreecaTVLiveIE(AfreecaTVIE):
+class AfreecaTVLiveIE(AfreecaTVIE):  # XXX: Do not subclass from concrete IE
 
     IE_NAME = 'afreecatv:live'
     _VALID_URL = r'https?://play\.afreeca(?:tv)?\.com/(?P<id>[^/]+)(?:/(?P<bno>\d+))?'
index b76ccb2a1991503860b0c5ec2e2bd9f9ce2e1889..ae7115f9f1a54a5bbfd51bc4c4c01e07fe056704 100644 (file)
@@ -113,7 +113,7 @@ def is_logged(webpage):
             raise ExtractorError('Unable to log in')
 
 
-class AluraCourseIE(AluraIE):
+class AluraCourseIE(AluraIE):  # XXX: Do not subclass from concrete IE
 
     _VALID_URL = r'https?://(?:cursos\.)?alura\.com\.br/course/(?P<id>[^/]+)'
     _LOGIN_URL = 'https://cursos.alura.com.br/loginForm?urlAfterLogin=/loginForm'
index e04ecf65f0d1feb90c7b6007f647511bd2422e5c..9369a66f7a9d4cb55100cdd751707f7af8425077 100644 (file)
@@ -9,7 +9,7 @@
 )
 
 
-class AMCNetworksIE(ThePlatformIE):
+class AMCNetworksIE(ThePlatformIE):  # XXX: Do not subclass from concrete IE
     _VALID_URL = r'https?://(?:www\.)?(?P<site>amc|bbcamerica|ifc|(?:we|sundance)tv)\.com/(?P<id>(?:movies|shows(?:/[^/]+)+)/[^/?#&]+)'
     _TESTS = [{
         'url': 'https://www.bbcamerica.com/shows/the-graham-norton-show/videos/tina-feys-adorable-airline-themed-family-dinner--51631',
index 73b72b08590878a36a9fc21b0e0be208f8c1f4d2..6015baad55e5b1dc6542fd29a840d547354ad8e6 100644 (file)
@@ -10,7 +10,7 @@
 )
 
 
-class AMPIE(InfoExtractor):
+class AMPIE(InfoExtractor):  # XXX: Conventionally, base classes should end with BaseIE/InfoExtractor
     # parse Akamai Adaptive Media Player feed
     def _extract_feed_info(self, url):
         feed = self._download_json(
index b67db2adcae026f4d0ddd623972854023e6acff3..5200f9d9d235d3df80fccfc93580de86835aba7d 100644 (file)
@@ -9,7 +9,7 @@
 )
 
 
-class AolIE(YahooIE):
+class AolIE(YahooIE):  # XXX: Do not subclass from concrete IE
     IE_NAME = 'aol.com'
     _VALID_URL = r'(?:aol-video:|https?://(?:www\.)?aol\.(?:com|ca|co\.uk|de|jp)/video/(?:[^/]+/)*)(?P<id>\d{9}|[0-9a-f]{24}|[0-9a-f]{8}-(?:[0-9a-f]{4}-){3}[0-9a-f]{12})'
 
index 0105d9db8395cd9d2110c0db32001b481d750b35..6448b449b90f844e4b26d12fc8f97454fd378e84 100644 (file)
@@ -168,7 +168,7 @@ def _real_extract(self, url):
         }
 
 
-class AudiusTrackIE(AudiusIE):
+class AudiusTrackIE(AudiusIE):  # XXX: Do not subclass from concrete IE
     _VALID_URL = r'''(?x)(?:audius:)(?:https?://(?:www\.)?.+/v1/tracks/)?(?P<track_id>\w+)'''
     IE_NAME = 'audius:track'
     IE_DESC = 'Audius track ID or API link. Prepend with "audius:"'
@@ -243,7 +243,7 @@ def _real_extract(self, url):
                                     playlist_data.get('description'))
 
 
-class AudiusProfileIE(AudiusPlaylistIE):
+class AudiusProfileIE(AudiusPlaylistIE):  # XXX: Do not subclass from concrete IE
     IE_NAME = 'audius:artist'
     IE_DESC = 'Audius.co profile/artist pages'
     _VALID_URL = r'https?://(?:www)?audius\.co/(?P<id>[^\/]+)/?(?:[?#]|$)'
index c2b22922be2e2145f3891ea55ac34af81f69f9a2..eb831a15303553f921eadd6f921429a8c9379808 100644 (file)
@@ -6,7 +6,7 @@
 from ..compat import compat_urllib_parse_urlencode
 
 
-class AWSIE(InfoExtractor):
+class AWSIE(InfoExtractor):  # XXX: Conventionally, base classes should end with BaseIE/InfoExtractor
     _AWS_ALGORITHM = 'AWS4-HMAC-SHA256'
     _AWS_REGION = 'us-east-1'
 
index 2e323337612263955e83b01b08b05df6e32fe6ea..e438d16ea48e7f7861348a0eb525ab47c73c8ce3 100644 (file)
@@ -2,7 +2,7 @@
 from ..utils import extract_attributes
 
 
-class BandaiChannelIE(BrightcoveNewIE):
+class BandaiChannelIE(BrightcoveNewIE):  # XXX: Do not subclass from concrete IE
     IE_NAME = 'bandaichannel'
     _VALID_URL = r'https?://(?:www\.)?b-ch\.com/titles/(?P<id>\d+/\d+)'
     _TESTS = [{
index a864ff9ac7a9816d9e794a6521d35954daff75ce..7dcace2c6894631343165e039304bacee79c5b22 100644 (file)
@@ -211,7 +211,7 @@ def _real_extract(self, url):
         }
 
 
-class BandcampAlbumIE(BandcampIE):
+class BandcampAlbumIE(BandcampIE):  # XXX: Do not subclass from concrete IE
     IE_NAME = 'Bandcamp:album'
     _VALID_URL = r'https?://(?:(?P<subdomain>[^.]+)\.)?bandcamp\.com/album/(?P<id>[^/?#&]+)'
 
@@ -314,7 +314,7 @@ def _real_extract(self, url):
         }
 
 
-class BandcampWeeklyIE(BandcampIE):
+class BandcampWeeklyIE(BandcampIE):  # XXX: Do not subclass from concrete IE
     IE_NAME = 'Bandcamp:weekly'
     _VALID_URL = r'https?://(?:www\.)?bandcamp\.com/?\?(?:.*?&)?show=(?P<id>\d+)'
     _TESTS = [{
index fe122af8532c3ae5ad3d1dbe49d49f885adafe54..35a7a165caa81e99425a1b38fd82630e5e847cdd 100644 (file)
@@ -588,7 +588,7 @@ def _real_extract(self, url):
         }
 
 
-class BBCIE(BBCCoUkIE):
+class BBCIE(BBCCoUkIE):  # XXX: Do not subclass from concrete IE
     IE_NAME = 'bbc'
     IE_DESC = 'BBC'
     _VALID_URL = r'''(?x)
index 48526e38b64c97646e4794d790e7bf31a4e64322..d86d283fac45e1b3a3831cee9cd9ada54bfe9a25 100644 (file)
@@ -42,7 +42,7 @@ def _real_extract(self, url):
         return self._brightcove_url_result(video_block['videoid'], video_block)
 
 
-class BFMTVLiveIE(BFMTVIE):
+class BFMTVLiveIE(BFMTVIE):  # XXX: Do not subclass from concrete IE
     IE_NAME = 'bfmtv:live'
     _VALID_URL = BFMTVBaseIE._VALID_URL_BASE + '(?P<id>(?:[^/]+/)?en-direct)'
     _TESTS = [{
index de28aa4b7041f3d49a7f1dd6662c1fa2434d455c..8a0e10da8046f25f8076925c20194f5eb8a13672 100644 (file)
@@ -65,7 +65,7 @@ def extract_formats(self, play_info):
         missing_formats = format_names.keys() - set(traverse_obj(formats, (..., 'quality')))
         if missing_formats:
             self.to_screen(f'Format(s) {", ".join(format_names[i] for i in missing_formats)} are missing; '
-                           'you have to login or become premium member to download them')
+                           f'you have to login or become premium member to download them. {self._login_hint()}')
 
         self._sort_formats(formats)
         return formats
index e32539c9e73e94ea4d4045e64eca4a0452e606fb..9515806edaf9520549e3a42475cfe0092edc9ca1 100644 (file)
@@ -10,7 +10,7 @@
 )
 
 
-class CBSBaseIE(ThePlatformFeedIE):
+class CBSBaseIE(ThePlatformFeedIE):  # XXX: Do not subclass from concrete IE
     def _parse_smil_subtitles(self, smil, namespace=None, subtitles_lang='en'):
         subtitles = {}
         for k, ext in [('sMPTE-TTCCURL', 'tt'), ('ClosedCaptionURL', 'ttml'), ('webVTTCaptionURL', 'vtt')]:
index 7abeecf78a31fb2d214e61409f6ba9c72704b84a..b09e9823ebd6905919583ed780602ec6883f851b 100644 (file)
@@ -2,7 +2,7 @@
 from ..utils import int_or_none
 
 
-class CBSInteractiveIE(CBSIE):
+class CBSInteractiveIE(CBSIE):  # XXX: Do not subclass from concrete IE
     _VALID_URL = r'https?://(?:www\.)?(?P<site>cnet|zdnet)\.com/(?:videos|video(?:/share)?)/(?P<id>[^/?]+)'
     _TESTS = [{
         'url': 'http://www.cnet.com/videos/hands-on-with-microsofts-windows-8-1-update/',
index c6495c95fedec2691d6b8d87f41bf9385b0acd4d..3d50b0499f0d144a781aeca4901131780103fd4c 100644 (file)
@@ -7,7 +7,7 @@
 )
 
 
-class CBSLocalIE(AnvatoIE):
+class CBSLocalIE(AnvatoIE):  # XXX: Do not subclass from concrete IE
     _VALID_URL_BASE = r'https?://[a-z]+\.cbslocal\.com/'
     _VALID_URL = _VALID_URL_BASE + r'video/(?P<id>\d+)'
 
@@ -47,7 +47,7 @@ def _real_extract(self, url):
             'anvato:anvato_cbslocal_app_web_prod_547f3e49241ef0e5d30c79b2efbca5d92c698f67:' + mcp_id, 'Anvato', mcp_id)
 
 
-class CBSLocalArticleIE(AnvatoIE):
+class CBSLocalArticleIE(AnvatoIE):  # XXX: Do not subclass from concrete IE
     _VALID_URL = CBSLocalIE._VALID_URL_BASE + r'\d+/\d+/\d+/(?P<id>[0-9a-z-]+)'
 
     _TESTS = [{
index 76925b4f9b5887dae9a8e3b3a144983bf1d5bce8..98ec28df0063dcd64bcb4d5346c926e3717e9c99 100644 (file)
@@ -12,7 +12,7 @@
 )
 
 
-class CBSNewsEmbedIE(CBSIE):
+class CBSNewsEmbedIE(CBSIE):  # XXX: Do not subclass from concrete IE
     IE_NAME = 'cbsnews:embed'
     _VALID_URL = r'https?://(?:www\.)?cbsnews\.com/embed/video[^#]*#(?P<id>.+)'
     _TESTS = [{
@@ -27,7 +27,7 @@ def _real_extract(self, url):
         return self._extract_video_info(item['mpxRefId'], 'cbsnews')
 
 
-class CBSNewsIE(CBSIE):
+class CBSNewsIE(CBSIE):  # XXX: Do not subclass from concrete IE
     IE_NAME = 'cbsnews'
     IE_DESC = 'CBS News'
     _VALID_URL = r'https?://(?:www\.)?cbsnews\.com/(?:news|video)/(?P<id>[\da-z_-]+)'
index 4eec066dd7eae44798eac4b7bdb28e580b71f8ee..8aed7708b1632e5d32eba414b154f3525b486262 100644 (file)
@@ -3,7 +3,7 @@
 # TODO Remove - Reason: Outdated Site
 
 
-class CMTIE(MTVIE):
+class CMTIE(MTVIE):  # XXX: Do not subclass from concrete IE
     IE_NAME = 'cmt.com'
     _VALID_URL = r'https?://(?:www\.)?cmt\.com/(?:videos|shows|(?:full-)?episodes|video-clips)/(?P<id>[^/]+)'
 
index 14984fd6f0b3aa11e82b1b3ca478609939d670fd..3a1af329011e3b72b7b68801702635a9b0bc6d17 100644 (file)
@@ -3676,12 +3676,13 @@ def _apply_first_set_cookie_header(self, url_handle, cookie):
 
     @classmethod
     def get_testcases(cls, include_onlymatching=False):
-        t = getattr(cls, '_TEST', None)
+        # Do not look in super classes
+        t = vars(cls).get('_TEST')
         if t:
             assert not hasattr(cls, '_TESTS'), f'{cls.ie_key()}IE has _TEST and _TESTS'
             tests = [t]
         else:
-            tests = getattr(cls, '_TESTS', [])
+            tests = vars(cls).get('_TESTS', [])
         for t in tests:
             if not include_onlymatching and t.get('only_matching', False):
                 continue
@@ -3690,12 +3691,12 @@ def get_testcases(cls, include_onlymatching=False):
 
     @classmethod
     def get_webpage_testcases(cls):
-        tests = getattr(cls, '_WEBPAGE_TESTS', [])
+        tests = vars(cls).get('_WEBPAGE_TESTS', [])
         for t in tests:
             t['name'] = cls.ie_key()
         return tests
 
-    @classproperty
+    @classproperty(cache=True)
     def age_limit(cls):
         """Get age limit from the testcases"""
         return max(traverse_obj(
index 7b83c0390d2a27d0b4a1b07a7afd2d8e72e25ae2..8c920e3ab889cf80ebd9393289f180e9d39c6df3 100644 (file)
@@ -7,7 +7,7 @@
 )
 
 
-class CorusIE(ThePlatformFeedIE):
+class CorusIE(ThePlatformFeedIE):  # XXX: Do not subclass from concrete IE
     _VALID_URL = r'''(?x)
                     https?://
                         (?:www\.)?
index a1f197b0bc4b0f4ef075139854972a17fe3ca846..3ef5140658f6637b67517693fc8656c0b9e84062 100644 (file)
@@ -125,7 +125,7 @@ def _real_extract(self, url):
             self._KAKAO_EMBED_BASE + video_id, 'Kakao', video_id)
 
 
-class DaumListIE(InfoExtractor):
+class DaumListIE(InfoExtractor):  # XXX: Conventionally, base classes should end with BaseIE/InfoExtractor
     def _get_entries(self, list_id, list_id_type):
         name = None
         entries = []
index 80a724607c49584a22e424a7fb2550d4c764f9a1..8a59c23ab2a245f14893c6422b5bd421ccda73ab 100644 (file)
@@ -1,7 +1,7 @@
 from .zdf import ZDFIE
 
 
-class DreiSatIE(ZDFIE):
+class DreiSatIE(ZDFIE):  # XXX: Do not subclass from concrete IE
     IE_NAME = '3sat'
     _VALID_URL = r'https?://(?:www\.)?3sat\.de/(?:[^/]+/)*(?P<id>[^/?#&]+)\.html'
     _TESTS = [{
index 99520b6a0c7694fc6f77f96861e787fb90260465..2c1969899e5d1a580296ef2d0fa819e114a59f0e 100644 (file)
@@ -2,7 +2,7 @@
 from .keezmovies import KeezMoviesIE
 
 
-class ExtremeTubeIE(KeezMoviesIE):
+class ExtremeTubeIE(KeezMoviesIE):  # XXX: Do not subclass from concrete IE
     _VALID_URL = r'https?://(?:www\.)?extremetube\.com/(?:[^/]+/)?video/(?P<id>[^/#?&]+)'
     _TESTS = [{
         'url': 'http://www.extremetube.com/video/music-video-14-british-euro-brit-european-cumshots-swallow-652431',
index 9716e581a9d060a5a4354635335c733ccd4f6dd0..1b5db818a19c3e40093ad3cc46e3569c98ff447e 100644 (file)
@@ -125,7 +125,7 @@ def _real_extract(self, url):
         }
 
 
-class FancodeLiveIE(FancodeVodIE):
+class FancodeLiveIE(FancodeVodIE):  # XXX: Do not subclass from concrete IE
     IE_NAME = 'fancode:live'
 
     _VALID_URL = r'https?://(www\.)?fancode\.com/match/(?P<id>[0-9]+).+'
index 6ecdd390c46a86bfa642c9020ee82a6ffe3c6ffa..fdcf6770d542ea9fd43bb03fad29035adb5a7949 100644 (file)
@@ -127,7 +127,7 @@ def _real_extract(self, url):
         return metadata
 
 
-class HitboxLiveIE(HitboxIE):
+class HitboxLiveIE(HitboxIE):  # XXX: Do not subclass from concrete IE
     IE_NAME = 'hitbox:live'
     _VALID_URL = r'https?://(?:www\.)?(?:hitbox|smashcast)\.tv/(?P<id>[^/?#&]+)'
     _TESTS = [{
index a3bb476154a28bdc159c2c8c927ccfda207e3bb7..21c56d8791fe8358b35c88b502bf97c5cfaf5cee 100644 (file)
@@ -138,7 +138,7 @@ def _real_extract(self, url):
         return self.url_result('http://imgur.com/%s' % gallery_id, ImgurIE.ie_key(), gallery_id)
 
 
-class ImgurAlbumIE(ImgurGalleryIE):
+class ImgurAlbumIE(ImgurGalleryIE):  # XXX: Do not subclass from concrete IE
     IE_NAME = 'imgur:album'
     _VALID_URL = r'https?://(?:i\.)?imgur\.com/a/(?P<id>[a-zA-Z0-9]+)'
 
index d960ee51c8e62d7572c7d9203ecd91ec1926e1b9..578e57a674950a2dd8e160653fb9d3a1a86e2c44 100644 (file)
@@ -134,7 +134,7 @@ def _real_extract(self, url):
         }
 
 
-class JamendoAlbumIE(JamendoIE):
+class JamendoAlbumIE(JamendoIE):  # XXX: Do not subclass from concrete IE
     _VALID_URL = r'https?://(?:www\.)?jamendo\.com/album/(?P<id>[0-9]+)'
     _TESTS = [{
         'url': 'https://www.jamendo.com/album/121486/duck-on-cover',
index 5d52decdba2b9fd19853bcee85de1e3be68d442e..8ce44cc1346b87c8e74232edda2123b7370ff187 100644 (file)
@@ -194,7 +194,7 @@ def _real_extract(self, url):
         return self._extract_info(webpage, video_id)
 
 
-class LA7PodcastIE(LA7PodcastEpisodeIE):
+class LA7PodcastIE(LA7PodcastEpisodeIE):  # XXX: Do not subclass from concrete IE
     IE_NAME = 'la7.it:podcast'
     _VALID_URL = r'(https?://)?(www\.)?la7\.it/(?P<id>[^/]+)/podcast/?(?:$|[#?])'
 
index 4014a9256fa7bb871ddac1b15888fef4361fcf2d..a90ed16a0d4785d413d36068b328605270ea10d1 100644 (file)
@@ -118,7 +118,7 @@ def get_flashvar(x, *args, **kwargs):
         }
 
 
-class Laola1TvBaseIE(Laola1TvEmbedIE):
+class Laola1TvBaseIE(Laola1TvEmbedIE):  # XXX: Do not subclass from concrete IE
     def _extract_video(self, url):
         display_id = self._match_id(url)
         webpage = self._download_webpage(url, display_id)
index 87543d56f80cad189fe2a5d815c963314dfa8b00..9846319e0c3da3e7f7e6cf3928fa678ec3c0b9d7 100644 (file)
@@ -2,7 +2,7 @@
 from .arkena import ArkenaIE
 
 
-class LcpPlayIE(ArkenaIE):
+class LcpPlayIE(ArkenaIE):  # XXX: Do not subclass from concrete IE
     _VALID_URL = r'https?://play\.lcp\.fr/embed/(?P<id>[^/]+)/(?P<account_id>[^/]+)/[^/]+/[^/]+'
     _TESTS = [{
         'url': 'http://play.lcp.fr/embed/327336/131064/darkmatter/0',
index ebe894f74033814a249e20d8b757161d6f51a11f..a3b5491d2eedd2b94f3253647aeefb751f9c4ae5 100644 (file)
@@ -286,7 +286,7 @@ def _real_extract(self, url):
         return info
 
 
-class MediasetShowIE(MediasetIE):
+class MediasetShowIE(MediasetIE):  # XXX: Do not subclass from concrete IE
     _VALID_URL = r'''(?x)
                     (?:
                         https?://
index 12b2b2432dcb5058b52c10d493f155a78ef566d3..ea29986729caf36cd9f8eda6da1174cb8499a0ad 100644 (file)
@@ -5,7 +5,7 @@
 )
 
 
-class MiTeleIE(TelecincoIE):
+class MiTeleIE(TelecincoIE):  # XXX: Do not subclass from concrete IE
     IE_DESC = 'mitele.es'
     _VALID_URL = r'https?://(?:www\.)?mitele\.es/(?:[^/]+/)+(?P<id>[^/]+)/player'
 
index 4221ef3e36eb5eb5b82d6ee39614600d84f5a364..9cb6980c1c3f83b9be2416a7f135f594e31cd52d 100644 (file)
@@ -7,7 +7,7 @@
 from .keezmovies import KeezMoviesIE
 
 
-class MofosexIE(KeezMoviesIE):
+class MofosexIE(KeezMoviesIE):  # XXX: Do not subclass from concrete IE
     _VALID_URL = r'https?://(?:www\.)?mofosex\.com/videos/(?P<id>\d+)/(?P<display_id>[^/?#&.]+)\.html'
     _TESTS = [{
         'url': 'http://www.mofosex.com/videos/318131/amateur-teen-playing-and-masturbating-318131.html',
index 10cd304eb0b011ab02376e2fdd424e48441e9ed5..b2009dc5be056473c5bc2dfb05aa64cb10c5a815 100644 (file)
@@ -536,7 +536,7 @@ def _get_feed_query(self, uri):
         }
 
 
-class MTVItaliaProgrammaIE(MTVItaliaIE):
+class MTVItaliaProgrammaIE(MTVItaliaIE):  # XXX: Do not subclass from concrete IE
     IE_NAME = 'mtv.it:programma'
     _VALID_URL = r'https?://(?:www\.)?mtv\.it/(?:programmi|playlist)/(?P<id>[0-9a-z]+)'
     _TESTS = [{
index 508d512479fc93937f3db210c56909b1a9654f81..6cdbbda1680810c0a6cb829afbe453cc3b7e4402 100644 (file)
@@ -99,7 +99,7 @@ def _real_extract(self, url):
         }
 
 
-class MurrtubeUserIE(MurrtubeIE):
+class MurrtubeUserIE(MurrtubeIE):  # XXX: Do not subclass from concrete IE
     IE_DESC = 'Murrtube user profile'
     _VALID_URL = r'https?://murrtube\.net/(?P<id>[^/]+)$'
     _TEST = {
index 4d8e74f6b4520ca0a81f593920aca8890c17293b..48f29702cf913924f441ca62a1765ddfcda74f59 100644 (file)
@@ -97,7 +97,7 @@ def _real_extract(self, url):
         }
 
 
-class MusicdexPageIE(MusicdexBaseIE):
+class MusicdexPageIE(MusicdexBaseIE):  # XXX: Conventionally, base classes should end with BaseIE/InfoExtractor
     def _entries(self, id):
         next_page_url = self._API_URL % id
         while next_page_url:
index f22317d5615a3bace47ce1996cab8d0733200353..ad525c2589981c4603e83f469fc4470bd9c8ed87 100644 (file)
@@ -59,7 +59,7 @@ def _real_extract(self, url):
         }
 
 
-class NationalGeographicTVIE(FOXIE):
+class NationalGeographicTVIE(FOXIE):  # XXX: Do not subclass from concrete IE
     _VALID_URL = r'https?://(?:www\.)?nationalgeographic\.com/tv/watch/(?P<id>[\da-fA-F]+)'
     _TESTS = [{
         'url': 'https://www.nationalgeographic.com/tv/watch/6a875e6e734b479beda26438c9f21138/',
index 3de8c15088c62193df50b194a2513c1d3d96455c..dbc82de9f4bcaf0bbe4d0afb1b0dd9fbb2c8c7c1 100644 (file)
@@ -24,7 +24,7 @@
 )
 
 
-class NBCIE(ThePlatformIE):
+class NBCIE(ThePlatformIE):  # XXX: Do not subclass from concrete IE
     _VALID_URL = r'https?(?P<permalink>://(?:www\.)?nbc\.com/(?:classic-tv/)?[^/]+/video/[^/]+/(?P<id>n?\d+))'
 
     _TESTS = [
@@ -315,7 +315,7 @@ def _real_extract(self, url):
         }
 
 
-class NBCNewsIE(ThePlatformIE):
+class NBCNewsIE(ThePlatformIE):  # XXX: Do not subclass from concrete IE
     _VALID_URL = r'(?x)https?://(?:www\.)?(?:nbcnews|today|msnbc)\.com/([^/]+/)*(?:.*-)?(?P<id>[^/?]+)'
     _EMBED_REGEX = [r'<iframe[^>]+src=(["\'])(?P<url>(?:https?:)?//www\.nbcnews\.com/widget/video-embed/[^"\']+)\1']
 
index ad8dbd7a77968fa8bfe903b184a2f370f93b237c..90a658cd803d046e274dfb828b58a7750ea21da3 100644 (file)
@@ -218,7 +218,7 @@ def _extract_embed(self, webpage, display_id, url=None):
         }
 
 
-class NDREmbedBaseIE(InfoExtractor):
+class NDREmbedBaseIE(InfoExtractor):  # XXX: Conventionally, Concrete class names do not end in BaseIE
     IE_NAME = 'ndr:embed:base'
     _VALID_URL = r'(?:ndr:(?P<id_s>[\da-z]+)|https?://www\.ndr\.de/(?P<id>[\da-z]+)-ppjson\.json)'
     _TESTS = [{
@@ -315,7 +315,7 @@ def _real_extract(self, url):
         }
 
 
-class NDREmbedIE(NDREmbedBaseIE):
+class NDREmbedIE(NDREmbedBaseIE):  # XXX: Do not subclass from concrete IE
     IE_NAME = 'ndr:embed'
     _VALID_URL = r'https?://(?:\w+\.)*ndr\.de/(?:[^/]+/)*(?P<id>[\da-z]+)-(?:(?:ard)?player|externalPlayer)\.html'
     _TESTS = [{
@@ -413,7 +413,7 @@ class NDREmbedIE(NDREmbedBaseIE):
     }]
 
 
-class NJoyEmbedIE(NDREmbedBaseIE):
+class NJoyEmbedIE(NDREmbedBaseIE):  # XXX: Do not subclass from concrete IE
     IE_NAME = 'njoy:embed'
     _VALID_URL = r'https?://(?:www\.)?n-joy\.de/(?:[^/]+/)*(?P<id>[\da-z]+)-(?:player|externalPlayer)_[^/]+\.html'
     _TESTS = [{
index 1f83089fc9265d4d22e858e24898e23f5ba43319..0e47a4d45a291ea5009c1cdce0888775d57c3e34 100644 (file)
@@ -77,7 +77,7 @@ def _fetch_description(self, page):
         return self._og_search_property('description', page)
 
 
-class NextMediaActionNewsIE(NextMediaIE):
+class NextMediaActionNewsIE(NextMediaIE):  # XXX: Do not subclass from concrete IE
     IE_DESC = '蘋果日報 - 動新聞'
     _VALID_URL = r'https?://hk\.dv\.nextmedia\.com/actionnews/[^/]+/(?P<date>\d+)/(?P<id>\d+)/\d+'
     _TESTS = [{
@@ -102,7 +102,7 @@ def _real_extract(self, url):
         return self._extract_from_nextmedia_page(news_id, url, article_page)
 
 
-class AppleDailyIE(NextMediaIE):
+class AppleDailyIE(NextMediaIE):  # XXX: Do not subclass from concrete IE
     IE_DESC = '臺灣蘋果日報'
     _VALID_URL = r'https?://(www|ent)\.appledaily\.com\.tw/[^/]+/[^/]+/[^/]+/(?P<date>\d+)/(?P<id>\d+)(/.*)?'
     _TESTS = [{
index 2a228d8de23b6f59990432ea988b0cda0b5e6ddb..de22cb8d6428a28214940c5f23a79c46c1eb7439 100644 (file)
@@ -188,7 +188,7 @@ def _get_feed_url(self, uri, url=None):
         return self._remove_template_parameter(config['feedWithQueryParams'])
 
 
-class NickNightIE(NickDeIE):
+class NickNightIE(NickDeIE):  # XXX: Do not subclass from concrete IE
     IE_NAME = 'nicknight'
     _VALID_URL = r'https?://(?:www\.)(?P<host>nicknight\.(?:de|at|tv))/(?:playlist|shows)/(?:[^/]+/)*(?P<id>[^/?#&]+)'
     _TESTS = [{
index 0b5f32c2e86197200942282f56c4ba324873bd59..b307e6a7887f3bc366f91f85ea3699b32a1217bf 100644 (file)
@@ -599,7 +599,7 @@ def _real_extract(self, url):
         }
 
 
-class NPODataMidEmbedIE(InfoExtractor):
+class NPODataMidEmbedIE(InfoExtractor):  # XXX: Conventionally, base classes should end with BaseIE/InfoExtractor
     def _real_extract(self, url):
         display_id = self._match_id(url)
         webpage = self._download_webpage(url, display_id)
@@ -653,7 +653,7 @@ class HetKlokhuisIE(NPODataMidEmbedIE):
     }
 
 
-class NPOPlaylistBaseIE(NPOIE):
+class NPOPlaylistBaseIE(NPOIE):  # XXX: Do not subclass from concrete IE
     def _real_extract(self, url):
         playlist_id = self._match_id(url)
 
index 7eb5b21cb467b8a777d35805033f6a1b10976763..14951f8e18c1b717a5622d7ce5cdd273a2dfef7f 100644 (file)
@@ -735,7 +735,7 @@ def _real_extract(self, url):
             entries, series_id, titles.get('title'), titles.get('subtitle'))
 
 
-class NRKTVDirekteIE(NRKTVIE):
+class NRKTVDirekteIE(NRKTVIE):  # XXX: Do not subclass from concrete IE
     IE_DESC = 'NRK TV Direkte and NRK Radio Direkte'
     _VALID_URL = r'https?://(?:tv|radio)\.nrk\.no/direkte/(?P<id>[^/?#&]+)'
 
index 460b82d02f13449a3c746425413f5fd11e554c74..989f10abb14ed13f4b115cd4977a453a185f030a 100644 (file)
@@ -3,7 +3,7 @@
 from .common import InfoExtractor
 
 
-class OnceIE(InfoExtractor):
+class OnceIE(InfoExtractor):  # XXX: Conventionally, base classes should end with BaseIE/InfoExtractor
     _VALID_URL = r'https?://.+?\.unicornmedia\.com/now/(?:ads/vmap/)?[^/]+/[^/]+/(?P<domain_id>[^/]+)/(?P<application_id>[^/]+)/(?:[^/]+/)?(?P<media_item_id>[^/]+)/content\.(?:once|m3u8|mp4)'
     ADAPTIVE_URL_TEMPLATE = 'http://once.unicornmedia.com/now/master/playlist/%s/%s/%s/content.m3u8'
     PROGRESSIVE_URL_TEMPLATE = 'http://once.unicornmedia.com/now/media/progressive/%s/%s/%s/%s/content.mp4'
index f1c4469d6506e524b55bcb3d8ee8bc1a1cd9f79b..fd25b5adbdbe54b14721261133791ae6bdff1b0d 100644 (file)
@@ -51,7 +51,7 @@ def _real_extract(self, url):
         return info
 
 
-class PlayVidsIE(PeekVidsIE):
+class PlayVidsIE(PeekVidsIE):  # XXX: Do not subclass from concrete IE
     _VALID_URL = r'https?://(?:www\.)?playvids\.com/(?:embed/|[^/]{2}/)?(?P<id>[^/?#]*)'
     _TESTS = [{
         'url': 'https://www.playvids.com/U3pBrYhsjXM/pc/dane-jones-cute-redhead-with-perfect-tits-with-mini-vamp',
index d89c9563b248975849b1c86530dc2b09ba799497..ed38a07f03451db9531e4002aa3433fa4a051765 100644 (file)
@@ -94,7 +94,7 @@ def _real_extract(self, url):
         return result
 
 
-class RadLiveSeasonIE(RadLiveIE):
+class RadLiveSeasonIE(RadLiveIE):  # XXX: Do not subclass from concrete IE
     IE_NAME = 'radlive:season'
     _VALID_URL = r'https?://(?:www\.)?rad\.live/content/season/(?P<id>[a-f0-9-]+)'
     _TESTS = [{
@@ -134,7 +134,7 @@ def _real_extract(self, url):
         return self.playlist_result(entries, season_id, video_info.get('title'))
 
 
-class RadLiveChannelIE(RadLiveIE):
+class RadLiveChannelIE(RadLiveIE):  # XXX: Do not subclass from concrete IE
     IE_NAME = 'radlive:channel'
     _VALID_URL = r'https?://(?:www\.)?rad\.live/content/channel/(?P<id>[a-f0-9-]+)'
     _TESTS = [{
index 6ed8227eb6ff831b40467bd781e8929fa312e4d3..cd19ec07b2d6862758b1fea4d1e607a5cc8d14bf 100644 (file)
@@ -356,7 +356,7 @@ def _real_extract(self, url):
         }
 
 
-class RaiPlayLiveIE(RaiPlayIE):
+class RaiPlayLiveIE(RaiPlayIE):  # XXX: Do not subclass from concrete IE
     _VALID_URL = r'(?P<base>https?://(?:www\.)?raiplay\.it/dirette/(?P<id>[^/?#&]+))'
     _TESTS = [{
         'url': 'http://www.raiplay.it/dirette/rainews24',
@@ -504,7 +504,7 @@ def _real_extract(self, url):
         }
 
 
-class RaiPlaySoundLiveIE(RaiPlaySoundIE):
+class RaiPlaySoundLiveIE(RaiPlaySoundIE):  # XXX: Do not subclass from concrete IE
     _VALID_URL = r'(?P<base>https?://(?:www\.)?raiplaysound\.it/(?P<id>[^/?#&]+)$)'
     _TESTS = [{
         'url': 'https://www.raiplaysound.it/radio2',
@@ -717,7 +717,7 @@ def _real_extract(self, url):
         }
 
 
-class RaiNewsIE(RaiIE):
+class RaiNewsIE(RaiIE):  # XXX: Do not subclass from concrete IE
     _VALID_URL = rf'https?://(www\.)?rainews\.it/(?!articoli)[^?#]+-(?P<id>{RaiBaseIE._UUID_RE})(?:-[^/?#]+)?\.html'
     _EMBED_REGEX = [rf'<iframe[^>]+data-src="(?P<url>/iframe/[^?#]+?{RaiBaseIE._UUID_RE}\.html)']
     _TESTS = [{
index 2f0e41c5b8dfda90b2a445fb0455582228e44821..50e61ba6e18a4675581b143a1c3d75debd92ed80 100644 (file)
@@ -110,7 +110,7 @@ def _real_extract(self, url):
         return self.extract_info(video_id)
 
 
-class RedBullEmbedIE(RedBullTVIE):
+class RedBullEmbedIE(RedBullTVIE):  # XXX: Do not subclass from concrete IE
     _VALID_URL = r'https?://(?:www\.)?redbull\.com/embed/(?P<id>rrn:content:[^:]+:[\da-f]{8}-[\da-f]{4}-[\da-f]{4}-[\da-f]{4}-[\da-f]{12}:[a-z]{2}-[A-Z]{2,3})'
     _TESTS = [{
         # HLS manifest accessible only using assetId
index e5ba1a26bd72f03af3981b68f5c3df9275483bbb..6644538ed1bac4be08191a1522157978e717f9a2 100644 (file)
@@ -12,7 +12,7 @@
 )
 
 
-class RTSIE(SRGSSRIE):
+class RTSIE(SRGSSRIE):  # XXX: Do not subclass from concrete IE
     IE_DESC = 'RTS.ch'
     _VALID_URL = r'rts:(?P<rts_id>\d+)|https?://(?:.+?\.)?rts\.ch/(?:[^/]+/){2,}(?P<id>[0-9]+)-(?P<display_id>.+?)\.html'
 
index 798dde7fa60f868dd93fa7e72f6f4035bb3cbffb..b9b181feb622837b5e4f6daa7b985db689df544d 100644 (file)
@@ -170,7 +170,7 @@ def _get_subtitles(self, video_id, sub_file):
             for s in subs)
 
 
-class RTVEAudioIE(RTVEALaCartaIE):
+class RTVEAudioIE(RTVEALaCartaIE):  # XXX: Do not subclass from concrete IE
     IE_NAME = 'rtve.es:audio'
     IE_DESC = 'RTVE audio'
     _VALID_URL = r'https?://(?:www\.)?rtve\.es/(alacarta|play)/audios/[^/]+/[^/]+/(?P<id>[0-9]+)'
@@ -257,7 +257,7 @@ def _real_extract(self, url):
         }
 
 
-class RTVEInfantilIE(RTVEALaCartaIE):
+class RTVEInfantilIE(RTVEALaCartaIE):  # XXX: Do not subclass from concrete IE
     IE_NAME = 'rtve.es:infantil'
     IE_DESC = 'RTVE infantil'
     _VALID_URL = r'https?://(?:www\.)?rtve\.es/infantil/serie/[^/]+/video/[^/]+/(?P<id>[0-9]+)/'
@@ -276,7 +276,7 @@ class RTVEInfantilIE(RTVEALaCartaIE):
     }]
 
 
-class RTVELiveIE(RTVEALaCartaIE):
+class RTVELiveIE(RTVEALaCartaIE):  # XXX: Do not subclass from concrete IE
     IE_NAME = 'rtve.es:live'
     IE_DESC = 'RTVE.es live streams'
     _VALID_URL = r'https?://(?:www\.)?rtve\.es/directo/(?P<id>[a-zA-Z0-9-]+)'
index 34af0d594bd242bcdd2e1010d0d49c76bcc5f8fd..cad3caa605ede5f327a0a72161c08f3365fa334e 100644 (file)
@@ -240,7 +240,6 @@ class RutubeMovieIE(RutubePlaylistBaseIE):
     IE_NAME = 'rutube:movie'
     IE_DESC = 'Rutube movies'
     _VALID_URL = r'https?://rutube\.ru/metainfo/tv/(?P<id>\d+)'
-    _TESTS = []
 
     _MOVIE_TEMPLATE = 'http://rutube.ru/api/metainfo/tv/%s/?format=json'
     _PAGE_TEMPLATE = 'http://rutube.ru/api/metainfo/tv/%s/video?page=%s&format=json'
index 8e95bc230dae66d8d49b6544df1d0e1b066b730e..36d1a86fddf4de9117c0b34007b16076681a44e3 100644 (file)
@@ -13,7 +13,7 @@
 )
 
 
-class SevenPlusIE(BrightcoveNewIE):
+class SevenPlusIE(BrightcoveNewIE):  # XXX: Do not subclass from concrete IE
     IE_NAME = '7plus'
     _VALID_URL = r'https?://(?:www\.)?7plus\.com\.au/(?P<path>[^?]+\?.*?\bepisode-id=(?P<id>[^&#]+))'
     _TESTS = [{
index 2daaaf75c1911e4701bf535a4055f2266b88f16b..9e4d7d35dea116554367d08ba90e9885e5e637b8 100644 (file)
@@ -70,7 +70,7 @@ def _real_extract(self, url):
         return self._parse_video(video, video_id)
 
 
-class SkyItVideoIE(SkyItPlayerIE):
+class SkyItVideoIE(SkyItPlayerIE):  # XXX: Do not subclass from concrete IE
     IE_NAME = 'video.sky.it'
     _VALID_URL = r'https?://(?:masterchef|video|xfactor)\.sky\.it(?:/[^/]+)*/video/[0-9a-z-]+-(?P<id>\d+)'
     _TESTS = [{
@@ -99,7 +99,7 @@ def _real_extract(self, url):
         return self._player_url_result(video_id)
 
 
-class SkyItVideoLiveIE(SkyItPlayerIE):
+class SkyItVideoLiveIE(SkyItPlayerIE):  # XXX: Do not subclass from concrete IE
     IE_NAME = 'video.sky.it:live'
     _VALID_URL = r'https?://video\.sky\.it/diretta/(?P<id>[^/?&#]+)'
     _TEST = {
@@ -127,7 +127,7 @@ def _real_extract(self, url):
         return self._parse_video(livestream, asset_id)
 
 
-class SkyItIE(SkyItPlayerIE):
+class SkyItIE(SkyItPlayerIE):  # XXX: Do not subclass from concrete IE
     IE_NAME = 'sky.it'
     _VALID_URL = r'https?://(?:sport|tg24)\.sky\.it(?:/[^/]+)*/\d{4}/\d{2}/\d{2}/(?P<id>[^/?&#]+)'
     _TESTS = [{
@@ -166,7 +166,7 @@ def _real_extract(self, url):
         return self._player_url_result(video_id)
 
 
-class SkyItArteIE(SkyItIE):
+class SkyItArteIE(SkyItIE):  # XXX: Do not subclass from concrete IE
     IE_NAME = 'arte.sky.it'
     _VALID_URL = r'https?://arte\.sky\.it/video/(?P<id>[^/?&#]+)'
     _TESTS = [{
@@ -187,7 +187,7 @@ class SkyItArteIE(SkyItIE):
     _VIDEO_ID_REGEX = r'"embedUrl"\s*:\s*"(?:https:)?//player\.sky\.it/player/external\.html\?[^"]*\bid=(\d+)'
 
 
-class CieloTVItIE(SkyItIE):
+class CieloTVItIE(SkyItIE):  # XXX: Do not subclass from concrete IE
     IE_NAME = 'cielotv.it'
     _VALID_URL = r'https?://(?:www\.)?cielotv\.it/video/(?P<id>[^.]+)\.html'
     _TESTS = [{
@@ -208,7 +208,7 @@ class CieloTVItIE(SkyItIE):
     _VIDEO_ID_REGEX = r'videoId\s*=\s*"(\d+)"'
 
 
-class TV8ItIE(SkyItVideoIE):
+class TV8ItIE(SkyItVideoIE):  # XXX: Do not subclass from concrete IE
     IE_NAME = 'tv8.it'
     _VALID_URL = r'https?://(?:www\.)?tv8\.it/(?:show)?video/[0-9a-z-]+-(?P<id>\d+)'
     _TESTS = [{
index 7381ac3624d296781988f04df5162a5ae9067012..e23f192a1c9eae6a49f16fd073dd037e0c70239b 100644 (file)
@@ -34,7 +34,7 @@ def _get_feed_query(self, uri):
         }
 
 
-class SouthParkEsIE(SouthParkIE):
+class SouthParkEsIE(SouthParkIE):  # XXX: Do not subclass from concrete IE
     IE_NAME = 'southpark.cc.com:español'
     _VALID_URL = r'https?://(?:www\.)?(?P<url>southpark\.cc\.com/es/episodios/(?P<id>.+?)(\?|#|$))'
     _LANG = 'es'
@@ -50,7 +50,7 @@ class SouthParkEsIE(SouthParkIE):
     }]
 
 
-class SouthParkDeIE(SouthParkIE):
+class SouthParkDeIE(SouthParkIE):  # XXX: Do not subclass from concrete IE
     IE_NAME = 'southpark.de'
     _VALID_URL = r'https?://(?:www\.)?(?P<url>southpark\.de/(?:(en/(videoclip|collections|episodes|video-clips))|(videoclip|collections|folgen))/(?P<id>(?P<unique_id>.+?)/.+?)(?:\?|#|$))'
     _TESTS = [{
@@ -109,7 +109,7 @@ def _get_feed_query(self, uri):
         return
 
 
-class SouthParkLatIE(SouthParkIE):
+class SouthParkLatIE(SouthParkIE):  # XXX: Do not subclass from concrete IE
     IE_NAME = 'southpark.lat'
     _VALID_URL = r'https?://(?:www\.)?southpark\.lat/(?:en/)?(?:video-?clips?|collections|episod(?:e|io)s)/(?P<id>[^/?#&]+)'
     _TESTS = [{
@@ -152,7 +152,7 @@ def _get_feed_query(self, uri):
         return
 
 
-class SouthParkNlIE(SouthParkIE):
+class SouthParkNlIE(SouthParkIE):  # XXX: Do not subclass from concrete IE
     IE_NAME = 'southpark.nl'
     _VALID_URL = r'https?://(?:www\.)?(?P<url>southpark\.nl/(?:clips|(?:full-)?episodes|collections)/(?P<id>.+?)(\?|#|$))'
     _FEED_URL = 'http://www.southpark.nl/feeds/video-player/mrss/'
@@ -167,7 +167,7 @@ class SouthParkNlIE(SouthParkIE):
     }]
 
 
-class SouthParkDkIE(SouthParkIE):
+class SouthParkDkIE(SouthParkIE):  # XXX: Do not subclass from concrete IE
     IE_NAME = 'southparkstudios.dk'
     _VALID_URL = r'https?://(?:www\.)?(?P<url>southparkstudios\.(?:dk|nu)/(?:clips|full-episodes|collections)/(?P<id>.+?)(\?|#|$))'
     _FEED_URL = 'http://www.southparkstudios.dk/feeds/video-player/mrss/'
index 58d343b44936ffb315da7a10cf493897d0d77e65..9260db2b44b7c9f55d1847acbbdbaf24fbd8bdfb 100644 (file)
@@ -6,7 +6,7 @@
 )
 
 
-class Tele5IE(DPlayIE):
+class Tele5IE(DPlayIE):  # XXX: Do not subclass from concrete IE
     _VALID_URL = r'https?://(?:www\.)?tele5\.de/(?:[^/]+/)*(?P<id>[^/?#&]+)'
     _GEO_COUNTRIES = ['DE']
     _TESTS = [{
index 9e94cd1ea1d2282c55e382e6b77c06a110c2ba98..4f6d2ecbad2213bbc5e5f4a50cdc4110b06bfe71 100644 (file)
@@ -8,7 +8,7 @@
 )
 
 
-class TheWeatherChannelIE(ThePlatformIE):
+class TheWeatherChannelIE(ThePlatformIE):  # XXX: Do not subclass from concrete IE
     _VALID_URL = r'https?://(?:www\.)?weather\.com(?P<asset_name>(?:/(?P<locale>[a-z]{2}-[A-Z]{2}))?/(?:[^/]+/)*video/(?P<id>[^/?#]+))'
     _TESTS = [{
         'url': 'https://weather.com/series/great-outdoors/video/ice-climber-is-in-for-a-shock',
index 4a35a241c767263dff1e8e626a0f1883968d7f7d..79a22386120dda2ff31430ed6e1f43621145acff 100644 (file)
@@ -655,7 +655,7 @@ def _real_extract(self, url):
         return self.playlist_result(self._entries_api(user_id, videos), user_id, user_name, thumbnail=thumbnail)
 
 
-class TikTokBaseListIE(TikTokBaseIE):
+class TikTokBaseListIE(TikTokBaseIE):  # XXX: Conventionally, base classes should end with BaseIE/InfoExtractor
     def _entries(self, list_id, display_id):
         query = {
             self._QUERY_NAME: list_id,
@@ -764,7 +764,7 @@ def _real_extract(self, url):
         return self.playlist_result(self._entries(tag_id, display_id), tag_id, display_id)
 
 
-class DouyinIE(TikTokIE):
+class DouyinIE(TikTokIE):  # XXX: Do not subclass from concrete IE
     _VALID_URL = r'https?://(?:www\.)?douyin\.com/video/(?P<id>[0-9]+)'
     _TESTS = [{
         'url': 'https://www.douyin.com/video/6961737553342991651',
index 349c0bded930427568f5b5a456b070f14db1b701..f60c199f0e8fb30dd4ebedbc3e235fb30358eecc 100644 (file)
@@ -9,7 +9,7 @@
 )
 
 
-class TouTvIE(RadioCanadaIE):
+class TouTvIE(RadioCanadaIE):  # XXX: Do not subclass from concrete IE
     _NETRC_MACHINE = 'toutv'
     IE_NAME = 'tou.tv'
     _VALID_URL = r'https?://ici\.tou\.tv/(?P<id>[a-zA-Z0-9_-]+(?:/S[0-9]+[EC][0-9]+)?)'
index b092ecad5a8779703de2aa5af159b0011dfffbd0..77ed05ffdadd1b1dbf7c1d1cf2474fbcaffb44e7 100644 (file)
@@ -7,7 +7,7 @@
 from .keezmovies import KeezMoviesIE
 
 
-class Tube8IE(KeezMoviesIE):
+class Tube8IE(KeezMoviesIE):  # XXX: Do not subclass from concrete IE
     _VALID_URL = r'https?://(?:www\.)?tube8\.com/(?:[^/]+/)+(?P<display_id>[^/]+)/(?P<id>\d+)'
     _EMBED_REGEX = [r'<iframe[^>]+\bsrc=["\'](?P<url>(?:https?:)?//(?:www\.)?tube8\.com/embed/(?:[^/]+/)+\d+)']
     _TESTS = [{
index 4aa558d8394b5f8a99da221be689c9c05a6a1775..24add5260575993621fef78620ba93389e7dc6bb 100644 (file)
@@ -426,7 +426,7 @@ def _real_extract(self, url):
         return self._extract_video(info, video_id, display_id)
 
 
-class TVNowFilmIE(TVNowIE):
+class TVNowFilmIE(TVNowIE):  # XXX: Do not subclass from concrete IE
     _VALID_URL = r'''(?x)
                     (?P<base_url>https?://
                         (?:www\.)?tvnow\.(?:de|at|ch)/
index 1dc2dbdc46d8143e02f79be2ba9ff71918637d51..2c8a35473cd6b8520953ff654639a0018a300ae7 100644 (file)
@@ -405,7 +405,7 @@ def extract_subtitles(track_list):
         }
 
 
-class UdemyCourseIE(UdemyIE):
+class UdemyCourseIE(UdemyIE):  # XXX: Do not subclass from concrete IE
     IE_NAME = 'udemy:course'
     _VALID_URL = r'https?://(?:[^/]+\.)?udemy\.com/(?P<id>[^/?#&]+)'
     _TESTS = [{
index 04c96f388ca69a0ff742bc8abacfa66aa339d660..9b560f719603583636180ae8945a68f2c22d937e 100644 (file)
@@ -52,10 +52,9 @@ def _real_extract(self, url):
         return self._extract_uplynk_info(url)
 
 
-class UplynkPreplayIE(UplynkIE):
+class UplynkPreplayIE(UplynkIE):  # XXX: Do not subclass from concrete IE
     IE_NAME = 'uplynk:preplay'
     _VALID_URL = r'https?://.*?\.uplynk\.com/preplay2?/(?P<path>ext/[0-9a-f]{32}/(?P<external_id>[^/?&]+)|(?P<id>[0-9a-f]{32}))\.json'
-    _TEST = None
 
     def _real_extract(self, url):
         path, external_id, video_id = self._match_valid_url(url).groups()
index d6b58a51c439acc41396042e33e1288a459df963..4a06a9ad403d5a23b3d8d1596350b696eafaf7c7 100644 (file)
@@ -1,7 +1,7 @@
 from .nbc import NBCIE
 
 
-class USANetworkIE(NBCIE):
+class USANetworkIE(NBCIE):  # XXX: Do not subclass from concrete IE
     _VALID_URL = r'https?(?P<permalink>://(?:www\.)?usanetwork\.com/(?:[^/]+/videos?|movies?)/(?:[^/]+/)?(?P<id>\d+))'
     _TESTS = [{
         'url': 'https://www.usanetwork.com/peacock-trailers/video/intelligence-trailer/4185302',
index a32c2fccb99f3380ac05e4419c0c1e286bf2eaee..d9b3ab115a2461a307eefd94e2cc7b10a7a0214c 100644 (file)
@@ -130,7 +130,7 @@ def _real_extract(self, url):
         }
 
 
-class VeohUserIE(VeohIE):
+class VeohUserIE(VeohIE):  # XXX: Do not subclass from concrete IE
     _VALID_URL = r'https?://(?:www\.)?veoh\.com/users/(?P<id>[\w-]+)'
     IE_NAME = 'veoh:user'
 
index 3e0af7fb23ec729817540f50f0db7fae2b01c556..b637afddf1e4b55c218c5532a4d48f591d99d7ca 100644 (file)
@@ -9,7 +9,7 @@
 )
 
 
-class VGTVIE(XstreamIE):
+class VGTVIE(XstreamIE):  # XXX: Do not subclass from concrete IE
     IE_DESC = 'VGTV, BTTV, FTV, Aftenposten and Aftonbladet'
     _GEO_BYPASS = False
 
index 2e36b8861a07357f9ed9a669edb9cdd7b7582a7d..1b21c00501d02015472621d26f276afc9736e105 100644 (file)
@@ -1004,7 +1004,7 @@ def is_rented():
         return merge_dicts(info_dict, info_dict_config, json_ld)
 
 
-class VimeoOndemandIE(VimeoIE):
+class VimeoOndemandIE(VimeoIE):  # XXX: Do not subclass from concrete IE
     IE_NAME = 'vimeo:ondemand'
     _VALID_URL = r'https?://(?:www\.)?vimeo\.com/ondemand/(?:[^/]+/)?(?P<id>[^/?#&]+)'
     _TESTS = [{
@@ -1129,7 +1129,7 @@ def _real_extract(self, url):
         return self._extract_videos(channel_id, self._BASE_URL_TEMPL % channel_id)
 
 
-class VimeoUserIE(VimeoChannelIE):
+class VimeoUserIE(VimeoChannelIE):  # XXX: Do not subclass from concrete IE
     IE_NAME = 'vimeo:user'
     _VALID_URL = r'https://vimeo\.com/(?!(?:[0-9]+|watchlater)(?:$|[?#/]))(?P<id>[^/]+)(?:/videos)?/?(?:$|[?#])'
     _TITLE_RE = r'<a[^>]+?class="user">([^<>]+?)</a>'
@@ -1239,7 +1239,7 @@ def _real_extract(self, url):
             entries, album_id, album.get('name'), album.get('description'))
 
 
-class VimeoGroupsIE(VimeoChannelIE):
+class VimeoGroupsIE(VimeoChannelIE):  # XXX: Do not subclass from concrete IE
     IE_NAME = 'vimeo:group'
     _VALID_URL = r'https://vimeo\.com/groups/(?P<id>[^/]+)(?:/(?!videos?/\d+)|$)'
     _TESTS = [{
@@ -1331,7 +1331,7 @@ def _real_extract(self, url):
         return info_dict
 
 
-class VimeoWatchLaterIE(VimeoChannelIE):
+class VimeoWatchLaterIE(VimeoChannelIE):  # XXX: Do not subclass from concrete IE
     IE_NAME = 'vimeo:watchlater'
     IE_DESC = 'Vimeo watch later list, ":vimeowatchlater" keyword (requires authentication)'
     _VALID_URL = r'https://vimeo\.com/(?:home/)?watchlater|:vimeowatchlater'
@@ -1354,7 +1354,7 @@ def _real_extract(self, url):
         return self._extract_videos('watchlater', 'https://vimeo.com/watchlater')
 
 
-class VimeoLikesIE(VimeoChannelIE):
+class VimeoLikesIE(VimeoChannelIE):  # XXX: Do not subclass from concrete IE
     _VALID_URL = r'https://(?:www\.)?vimeo\.com/(?P<id>[^/]+)/likes/?(?:$|[?#]|sort:)'
     IE_NAME = 'vimeo:likes'
     IE_DESC = 'Vimeo user likes'
index f0156d10caa6dd7632e31736555fe4e52acf5a7e..0c3e83a0a8f639bdbaea5bbe7b452ea56ac08dab 100644 (file)
@@ -242,7 +242,7 @@ def metadata_from_url(r_url):
         return info
 
 
-class VVVVIDShowIE(VVVVIDIE):
+class VVVVIDShowIE(VVVVIDIE):  # XXX: Do not subclass from concrete IE
     _VALID_URL = r'(?P<base_url>%s(?P<id>\d+)(?:/(?P<show_title>[^/?&#]+))?)/?(?:[?#&]|$)' % VVVVIDIE._VALID_URL_BASE
     _TESTS = [{
         'url': 'https://www.vvvvid.it/show/156/psyco-pass',
index d0ad69477df6efacec8d07245bed62893e500475..7b2e7c8e068e2b4e83cf58e020d3823ec1a05303 100644 (file)
@@ -133,7 +133,7 @@ def _real_extract(self, url):
         }
 
 
-class WDRPageIE(WDRIE):
+class WDRPageIE(WDRIE):  # XXX: Do not subclass from concrete IE
     _MAUS_REGEX = r'https?://(?:www\.)wdrmaus.de/(?:[^/]+/)*?(?P<maus_id>[^/?#.]+)(?:/?|/index\.php5|\.php5)$'
     _PAGE_REGEX = r'/(?:mediathek/)?(?:[^/]+/)*(?P<display_id>[^/]+)\.html'
     _VALID_URL = r'https?://(?:www\d?\.)?(?:(?:kinder\.)?wdr\d?|sportschau)\.de' + _PAGE_REGEX + '|' + _MAUS_REGEX
index 9d51f38ba13fdd2487da325865b73fdb307fc4c3..7e3530c0fa24c377bd7b45cc706259776b10f082 100644 (file)
@@ -1051,7 +1051,7 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
             <a\s[^>]*\bhref="(?P<url>https://www\.youtube\.com/watch\?v=[0-9A-Za-z_-]{11})"
             \s[^>]*\bclass="[^"]*\blazy-load-youtube''',
     ]
-    _RETURN_TYPE = 'video'  # While there are "multifeed" test cases, they don't seem to actually exist anymore
+    _RETURN_TYPE = 'video'  # XXX: How to handle multifeed?
 
     _PLAYER_INFO_RE = (
         r'/s/player/(?P<id>[a-zA-Z0-9_-]{8,})/player',
@@ -1582,66 +1582,99 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
             'skip': 'This live event has ended.',
         },
         {
-            # Multifeed videos (multiple cameras), URL is for Main Camera
-            'url': 'https://www.youtube.com/watch?v=jvGDaLqkpTg',
+            # Multifeed videos (multiple cameras), URL can be of any Camera
+            'url': 'https://www.youtube.com/watch?v=zaPI8MvL8pg',
             'info_dict': {
-                'id': 'jvGDaLqkpTg',
-                'title': 'Tom Clancy Free Weekend Rainbow Whatever',
-                'description': 'md5:e03b909557865076822aa169218d6a5d',
+                'id': 'zaPI8MvL8pg',
+                'title': 'Terraria 1.2 Live Stream | Let\'s Play - Part 04',
+                'description': 'md5:563ccbc698b39298481ca3c571169519',
             },
             'playlist': [{
                 'info_dict': {
-                    'id': 'jvGDaLqkpTg',
+                    'id': 'j5yGuxZ8lLU',
                     'ext': 'mp4',
-                    'title': 'Tom Clancy Free Weekend Rainbow Whatever (Main Camera)',
-                    'description': 'md5:e03b909557865076822aa169218d6a5d',
-                    'duration': 10643,
-                    'upload_date': '20161111',
-                    'uploader': 'Team PGP',
-                    'uploader_id': 'UChORY56LMMETTuGjXaJXvLg',
-                    'uploader_url': r're:https?://(?:www\.)?youtube\.com/channel/UChORY56LMMETTuGjXaJXvLg',
+                    'title': 'Terraria 1.2 Live Stream | Let\'s Play - Part 04 (Chris)',
+                    'uploader': 'WiiLikeToPlay',
+                    'description': 'md5:563ccbc698b39298481ca3c571169519',
+                    'uploader_url': 'http://www.youtube.com/user/WiiRikeToPray',
+                    'duration': 10120,
+                    'channel_follower_count': int,
+                    'channel_url': 'https://www.youtube.com/channel/UCN2XePorRokPB9TEgRZpddg',
+                    'availability': 'public',
+                    'playable_in_embed': True,
+                    'upload_date': '20131105',
+                    'uploader_id': 'WiiRikeToPray',
+                    'categories': ['Gaming'],
+                    'live_status': 'was_live',
+                    'tags': 'count:24',
+                    'release_timestamp': 1383701910,
+                    'thumbnail': 'https://i.ytimg.com/vi/j5yGuxZ8lLU/maxresdefault.jpg',
+                    'comment_count': int,
+                    'age_limit': 0,
+                    'like_count': int,
+                    'channel_id': 'UCN2XePorRokPB9TEgRZpddg',
+                    'channel': 'WiiLikeToPlay',
+                    'view_count': int,
+                    'release_date': '20131106',
                 },
             }, {
                 'info_dict': {
-                    'id': '3AKt1R1aDnw',
+                    'id': 'zaPI8MvL8pg',
                     'ext': 'mp4',
-                    'title': 'Tom Clancy Free Weekend Rainbow Whatever (Camera 2)',
-                    'description': 'md5:e03b909557865076822aa169218d6a5d',
-                    'duration': 10991,
-                    'upload_date': '20161111',
-                    'uploader': 'Team PGP',
-                    'uploader_id': 'UChORY56LMMETTuGjXaJXvLg',
-                    'uploader_url': r're:https?://(?:www\.)?youtube\.com/channel/UChORY56LMMETTuGjXaJXvLg',
+                    'title': 'Terraria 1.2 Live Stream | Let\'s Play - Part 04 (Tyson)',
+                    'uploader_id': 'WiiRikeToPray',
+                    'availability': 'public',
+                    'channel_url': 'https://www.youtube.com/channel/UCN2XePorRokPB9TEgRZpddg',
+                    'channel': 'WiiLikeToPlay',
+                    'uploader_url': 'http://www.youtube.com/user/WiiRikeToPray',
+                    'channel_follower_count': int,
+                    'description': 'md5:563ccbc698b39298481ca3c571169519',
+                    'duration': 10108,
+                    'age_limit': 0,
+                    'like_count': int,
+                    'tags': 'count:24',
+                    'channel_id': 'UCN2XePorRokPB9TEgRZpddg',
+                    'uploader': 'WiiLikeToPlay',
+                    'release_timestamp': 1383701915,
+                    'comment_count': int,
+                    'upload_date': '20131105',
+                    'thumbnail': 'https://i.ytimg.com/vi/zaPI8MvL8pg/maxresdefault.jpg',
+                    'release_date': '20131106',
+                    'playable_in_embed': True,
+                    'live_status': 'was_live',
+                    'categories': ['Gaming'],
+                    'view_count': int,
                 },
             }, {
                 'info_dict': {
-                    'id': 'RtAMM00gpVc',
+                    'id': 'R7r3vfO7Hao',
                     'ext': 'mp4',
-                    'title': 'Tom Clancy Free Weekend Rainbow Whatever (Camera 3)',
-                    'description': 'md5:e03b909557865076822aa169218d6a5d',
-                    'duration': 10995,
-                    'upload_date': '20161111',
-                    'uploader': 'Team PGP',
-                    'uploader_id': 'UChORY56LMMETTuGjXaJXvLg',
-                    'uploader_url': r're:https?://(?:www\.)?youtube\.com/channel/UChORY56LMMETTuGjXaJXvLg',
-                },
-            }, {
-                'info_dict': {
-                    'id': '6N2fdlP3C5U',
-                    'ext': 'mp4',
-                    'title': 'Tom Clancy Free Weekend Rainbow Whatever (Camera 4)',
-                    'description': 'md5:e03b909557865076822aa169218d6a5d',
-                    'duration': 10990,
-                    'upload_date': '20161111',
-                    'uploader': 'Team PGP',
-                    'uploader_id': 'UChORY56LMMETTuGjXaJXvLg',
-                    'uploader_url': r're:https?://(?:www\.)?youtube\.com/channel/UChORY56LMMETTuGjXaJXvLg',
+                    'title': 'Terraria 1.2 Live Stream | Let\'s Play - Part 04 (Spencer)',
+                    'thumbnail': 'https://i.ytimg.com/vi/R7r3vfO7Hao/maxresdefault.jpg',
+                    'channel_id': 'UCN2XePorRokPB9TEgRZpddg',
+                    'like_count': int,
+                    'availability': 'public',
+                    'playable_in_embed': True,
+                    'upload_date': '20131105',
+                    'description': 'md5:563ccbc698b39298481ca3c571169519',
+                    'uploader_id': 'WiiRikeToPray',
+                    'uploader_url': 'http://www.youtube.com/user/WiiRikeToPray',
+                    'channel_follower_count': int,
+                    'tags': 'count:24',
+                    'release_date': '20131106',
+                    'uploader': 'WiiLikeToPlay',
+                    'comment_count': int,
+                    'channel_url': 'https://www.youtube.com/channel/UCN2XePorRokPB9TEgRZpddg',
+                    'channel': 'WiiLikeToPlay',
+                    'categories': ['Gaming'],
+                    'release_timestamp': 1383701914,
+                    'live_status': 'was_live',
+                    'age_limit': 0,
+                    'duration': 10128,
+                    'view_count': int,
                 },
             }],
-            'params': {
-                'skip_download': True,
-            },
-            'skip': 'Not multifeed anymore',
+            'params': {'skip_download': True},
         },
         {
             # Multifeed video with comma in title (see https://github.com/ytdl-org/youtube-dl/issues/8536)
index a6bf897dcdc6fc54dacd135f300bf2cf0bbb10d8..7cba13678fc630fe566a5ca650dbc1a9626328af 100644 (file)
@@ -5839,7 +5839,7 @@ def wrapper(self, *args, **kwargs):
         bound_args.apply_defaults()
         key = tuple(bound_args.arguments.values())[1:]
 
-        cache = vars(self).setdefault('__cached_method__cache', {}).setdefault(f.__name__, {})
+        cache = vars(self).setdefault('_cached_method__cache', {}).setdefault(f.__name__, {})
         if key not in cache:
             cache[key] = f(self, *args, **kwargs)
         return cache[key]