ronantakizawa/codereview-bench huggingface dataset:
Repository: yt-dlp/yt-dlp
File: yt_dlp/extractor/lci.py (Python)

Code before:
from .common import InfoExtractor

from ..utils.traversal import traverse_obj


class LCIIE(InfoExtractor):
    _VALID_URL = r'https?://(?:www\.)?(?:lci|tf1info)\.fr(?:/[^/]+)+/[\w-]+-(?P<id>\d+)\.html'
    _TESTS = [
        {
            'url': 'https://www.tf1info.fr/replay-lci/videos/video-24h-pujadas-du-vendredi-24-mai-6708-2300831.html',
            'info_dict': {
                'id': '14113788',
                'ext': 'mp4',
                'title': '24H Pujadas du vendredi 24 mai 2024',
                'thumbnail': 'https://photos.tf1.fr/1280/720/24h-pujadas-du-24-mai-2024-55bf2d-0@1x.jpg',
                'upload_date': '20240524',
                'duration': 6158,
            },
            'params': {
                'skip_download': True,
            },
        }, {
            'url': 'https://www.tf1info.fr/politique/election-presidentielle-2022-second-tour-j-2-marine-le-pen-et-emmanuel-macron-en-interview-de-lci-vendredi-soir-2217486.html',
            'info_dict': {
                'id': '13875948',
                'ext': 'mp4',
                'title': 'md5:660df5481fd418bc3bbb0d070e6fdb5a',
                'thumbnail': 'https://photos.tf1.fr/1280/720/presidentielle-2022-marine-le-pen-et-emmanuel-macron-invites-de-lci-ce-vendredi-9c0e73-e1a036-0@1x.jpg',

Review comment (refactor):
```suggestion
from .wat import WatIE
from ..utils import ExtractorError, int_or_none
from ..utils.traversal import traverse_obj
```

Code after:
from .common import InfoExtractor
from .wat import WatIE
from ..utils import ExtractorError, int_or_none
from ..utils.traversal import traverse_obj


class LCIIE(InfoExtractor):
    _VALID_URL = r'https?://(?:www\.)?(?:lci|tf1info)\.fr/(?:[^/?#]+/)+[\w-]+-(?P<id>\d+)\.html'
    _TESTS = [{
        'url': 'https://www.tf1info.fr/replay-lci/videos/video-24h-pujadas-du-vendredi-24-mai-6708-2300831.html',
        'info_dict': {
            'id': '14113788',
            'ext': 'mp4',
            'title': '24H Pujadas du vendredi 24 mai 2024',
            'thumbnail': 'https://photos.tf1.fr/1280/720/24h-pujadas-du-24-mai-2024-55bf2d-0@1x.jpg',
            'upload_date': '20240524',
            'duration': 6158,
        },
        'params': {
            'skip_download': True,
        },
    }, {
        'url': 'https://www.tf1info.fr/politique/election-presidentielle-2022-second-tour-j-2-marine-le-pen-et-emmanuel-macron-en-interview-de-lci-vendredi-soir-2217486.html',
        'info_dict': {
            'id': '13875948',
            'ext': 'mp4',
            'title': 'md5:660df5481fd418bc3bbb0d070e6fdb5a',
            'thumbnail': 'https://photos.tf1.fr/1280/720/presidentielle-2022-marine-le-pen-et-emmanuel-macron-invites-de-lci-ce-vendredi-9c0e73-e1a036-0@1x.jpg',
Repository: yt-dlp/yt-dlp
File: yt_dlp/extractor/lci.py (Python)

Code before:
from .common import InfoExtractor
from .wat import WatIE
from ..utils import ExtractorError, int_or_none
from ..utils.traversal import traverse_obj


class LCIIE(InfoExtractor):
    _VALID_URL = r'https?://(?:www\.)?(?:lci|tf1info)\.fr(?:/[^/]+)+/[\w-]+-(?P<id>\d+)\.html'
    _TESTS = [
        {
            'url': 'https://www.tf1info.fr/replay-lci/videos/video-24h-pujadas-du-vendredi-24-mai-6708-2300831.html',
            'info_dict': {
                'id': '14113788',
                'ext': 'mp4',
                'title': '24H Pujadas du vendredi 24 mai 2024',
                'thumbnail': 'https://photos.tf1.fr/1280/720/24h-pujadas-du-24-mai-2024-55bf2d-0@1x.jpg',
                'upload_date': '20240524',
                'duration': 6158,
            },
            'params': {
                'skip_download': True,
            },
        }, {
            'url': 'https://www.tf1info.fr/politique/election-presidentielle-2022-second-tour-j-2-marine-le-pen-et-emmanuel-macron-en-interview-de-lci-vendredi-soir-2217486.html',
            'info_dict': {
                'id': '13875948',
                'ext': 'mp4',
                'title': 'md5:660df5481fd418bc3bbb0d070e6fdb5a',
                'thumbnail': 'https://photos.tf1.fr/1280/720/presidentielle-2022-marine-le-pen-et-emmanuel-macron-invites-de-lci-ce-vendredi-9c0e73-e1a036-0@1x.jpg',
                'upload_date': '20220422',
                'duration': 33,
            },
            'params': {

Review comment (suggestion):
```suggestion
    _VALID_URL = r'https?://(?:www\.)?(?:lci|tf1info)\.fr/(?:[^/?#]+/)+[\w-]+-(?P<id>\d+)\.html'
```

Code after:
from .common import InfoExtractor
from .wat import WatIE
from ..utils import ExtractorError, int_or_none
from ..utils.traversal import traverse_obj


class LCIIE(InfoExtractor):
    _VALID_URL = r'https?://(?:www\.)?(?:lci|tf1info)\.fr/(?:[^/?#]+/)+[\w-]+-(?P<id>\d+)\.html'
    _TESTS = [{
        'url': 'https://www.tf1info.fr/replay-lci/videos/video-24h-pujadas-du-vendredi-24-mai-6708-2300831.html',
        'info_dict': {
            'id': '14113788',
            'ext': 'mp4',
            'title': '24H Pujadas du vendredi 24 mai 2024',
            'thumbnail': 'https://photos.tf1.fr/1280/720/24h-pujadas-du-24-mai-2024-55bf2d-0@1x.jpg',
            'upload_date': '20240524',
            'duration': 6158,
        },
        'params': {
            'skip_download': True,
        },
    }, {
        'url': 'https://www.tf1info.fr/politique/election-presidentielle-2022-second-tour-j-2-marine-le-pen-et-emmanuel-macron-en-interview-de-lci-vendredi-soir-2217486.html',
        'info_dict': {
            'id': '13875948',
            'ext': 'mp4',
            'title': 'md5:660df5481fd418bc3bbb0d070e6fdb5a',
            'thumbnail': 'https://photos.tf1.fr/1280/720/presidentielle-2022-marine-le-pen-et-emmanuel-macron-invites-de-lci-ce-vendredi-9c0e73-e1a036-0@1x.jpg',
            'upload_date': '20220422',
            'duration': 33,
        },
        'params': {
            'skip_download': True,
Repository: yt-dlp/yt-dlp
File: yt_dlp/extractor/laracasts.py (Python)

Code before:
from .common import InfoExtractor
from .vimeo import VimeoIE


class LaracastsPlaylistIE(InfoExtractor):
    IE_NAME = 'laracasts:series'
    _VALID_URL = r'https?://(?:www\.)?laracasts\.com/series/(?P<series>[^/?#]+)'
    _TESTS = [{
        'url': 'https://laracasts.com/series/30-days-to-learn-laravel-11',
        'info_dict': {
            'title': '30 Days to Learn Laravel',
            'id': 210,
        },
        'only_matching': True,
    }]

    def _entries(self, series, episode_count):
        for current_episode in range(1, episode_count + 1):
            webpage_url = f'https://laracasts.com/series/{series}/episodes/{current_episode}'
            yield self.url_result(webpage_url, LaracastsIE)

    def _real_extract(self, url):
        mobj = self._match_valid_url(url)
        display_id = mobj.group('series')
        webpage = self._download_webpage(url, display_id)
        episode_count = int(self._search_regex(r'episodeCount&quot;:(?P<episode_count>[0-9]+)', webpage, 'episode_count'))
        playlist_title = self._search_regex(r'title&quot;:&quot;(?P<playlist_title>[^&]+)&quot;,', webpage, 'playlist_title')
        playlist_id = self._search_regex(r'id&quot;:(?P<playlist_id>[0-9]+)', webpage, 'playlist_id')
        return self.playlist_result(self._entries(display_id, episode_count), playlist_id, playlist_title)

class LaracastsIE(InfoExtractor):
    IE_NAME = 'laracasts'

Review comment (suggestion):
```suggestion
    _VALID_URL = r'https?://(?:www\.)?laracasts\.com/series/(?P<series>[^/?#]+)/?(?:$|[?#])'
```

Code after:
import json

from .common import InfoExtractor
from .vimeo import VimeoIE
from ..utils import (
    clean_html,
    extract_attributes,
    get_element_html_by_id,
    int_or_none,
    parse_duration,
    str_or_none,
    unified_strdate,
    url_or_none,
    urljoin,
)
from ..utils.traversal import traverse_obj


class LaracastsBaseIE(InfoExtractor):
    def _get_prop_data(self, url, display_id):
        webpage = self._download_webpage(url, display_id)
        return traverse_obj(
            get_element_html_by_id('app', webpage),
            ({extract_attributes}, 'data-page', {json.loads}, 'props'))

    def _parse_episode(self, episode):
        if not traverse_obj(episode, 'vimeoId'):
            self.raise_login_required('This video is only available for subscribers.')
        return self.url_result(
            VimeoIE._smuggle_referrer(
                f'https://player.vimeo.com/video/{episode["vimeoId"]}', 'https://laracasts.com/'),
            VimeoIE, url_transparent=True,
Repository: yt-dlp/yt-dlp
File: yt_dlp/extractor/laracasts.py (Python)

Code before:
            'description': 'md5:27c260a1668a450984e8f901579912dd',
            'categories': ['Frameworks'],
            'tags': ['Laravel'],
            'display_id': '30-days-to-learn-laravel-11',
        },
        'playlist_count': 30,
    }]

    def _entries(self, series, episode_count):
        for current_episode in range(1, episode_count + 1):
            webpage_url = f'https://laracasts.com/series/{series}/episodes/{current_episode}'
            yield self.url_result(webpage_url, LaracastsIE)

    def _real_extract(self, url):
        display_id = self._match_id(url)
        series = self.get_prop_data(url, display_id)['series']

        metadata = {
            'display_id': display_id,
            **traverse_obj(series, {
                'title': ('title', {str}),
                'id': ('id', {int}, {str_or_none}),
                'description': ('body', {clean_html}),
                'thumbnail': (('large_thumbnail', 'thumbnail'), any, {url_or_none}),
                'duration': ('runTime', {parse_duration}),
                'categories': ('taxonomy', 'name', {lambda x: x and [x]}),
                'tags': ('topics', ..., 'name', {str}),
                'modified_date': ('lastUpdated', {unified_strdate}),
            }),
        }

        return self.playlist_result(traverse_obj(
            series, ('chapters', ..., 'episodes', ..., {self.parse_episode})), **metadata)


Review comment (suggestion):
```suggestion
                'categories': ('taxonomy', 'name', {str}, {lambda x: x and [x]}),
```

Code after:
            'duration': 30600.0,
            'modified_date': '20240511',
            'description': 'md5:27c260a1668a450984e8f901579912dd',
            'categories': ['Frameworks'],
            'tags': ['Laravel'],
            'display_id': '30-days-to-learn-laravel-11',
        },
        'playlist_count': 30,
    }]

    def _real_extract(self, url):
        display_id = self._match_id(url)
        series = self._get_prop_data(url, display_id)['series']

        metadata = {
            'display_id': display_id,
            **traverse_obj(series, {
                'title': ('title', {str}),
                'id': ('id', {int}, {str_or_none}),
                'description': ('body', {clean_html}),
                'thumbnail': (('large_thumbnail', 'thumbnail'), {url_or_none}, any),
                'duration': ('runTime', {parse_duration}),
                'categories': ('taxonomy', 'name', {str}, {lambda x: x and [x]}),
                'tags': ('topics', ..., 'name', {str}),
                'modified_date': ('lastUpdated', {unified_strdate}),
            }),
        }

        return self.playlist_result(traverse_obj(
            series, ('chapters', ..., 'episodes', lambda _, v: v['vimeoId'], {self._parse_episode})), **metadata)
Repository: yt-dlp/yt-dlp
File: yt_dlp/networking/_curlcffi.py (Python)

Code before:

from ._helper import InstanceStoreMixin, select_proxy
from .common import (
    Features,
    Request,
    Response,
    register_preference,
    register_rh,
)
from .exceptions import (
    CertificateVerifyError,
    HTTPError,
    IncompleteRead,
    ProxyError,
    SSLError,
    TransportError,
)
from .impersonate import ImpersonateRequestHandler, ImpersonateTarget
from ..dependencies import curl_cffi, certifi
from ..utils import int_or_none

if curl_cffi is None:
    raise ImportError('curl_cffi is not installed')


curl_cffi_version = tuple(int_or_none(re.match(r'(\d+)?', n).group(), default=0) for n in curl_cffi.__version__.split('.'))

if curl_cffi_version != (0, 5, 10) and not ((0, 7, 0) <= curl_cffi_version < (0, 8, 0)):
    curl_cffi._yt_dlp__version = f'{curl_cffi.__version__} (unsupported)'
    raise ImportError('Only curl_cffi versions 0.5.10, 0.7.X are supported')

import curl_cffi.requests
from curl_cffi.const import CurlECode, CurlOpt


class CurlCFFIResponseReader(io.IOBase):
    def __init__(self, response: curl_cffi.requests.Response):
        self._response = response
        self._iterator = response.iter_content()
        self._buffer = b''
        self.bytes_read = 0

    def readable(self):
        return True

    def read(self, size=None):
        exception_raised = True
        try:
            while self._iterator and (size is None or len(self._buffer) < size):
                chunk = next(self._iterator, None)
                if chunk is None:

Review comment (suggestion):
```suggestion
curl_cffi_version = tuple(map(int, re.split(r'[^\d]+', curl_cffi.__version__)[:3]))
```

Code after:

from ._helper import InstanceStoreMixin, select_proxy
from .common import (
    Features,
    Request,
    Response,
    register_preference,
    register_rh,
)
from .exceptions import (
    CertificateVerifyError,
    HTTPError,
    IncompleteRead,
    ProxyError,
    SSLError,
    TransportError,
)
from .impersonate import ImpersonateRequestHandler, ImpersonateTarget
from ..dependencies import curl_cffi, certifi
from ..utils import int_or_none

if curl_cffi is None:
    raise ImportError('curl_cffi is not installed')


curl_cffi_version = tuple(map(int, re.split(r'[^\d]+', curl_cffi.__version__)[:3]))

if curl_cffi_version != (0, 5, 10) and not ((0, 7, 0) <= curl_cffi_version < (0, 8, 0)):
    curl_cffi._yt_dlp__version = f'{curl_cffi.__version__} (unsupported)'
    raise ImportError('Only curl_cffi versions 0.5.10, 0.7.X are supported')

import curl_cffi.requests
from curl_cffi.const import CurlECode, CurlOpt


class CurlCFFIResponseReader(io.IOBase):
    def __init__(self, response: curl_cffi.requests.Response):
        self._response = response
        self._iterator = response.iter_content()
        self._buffer = b''
        self.bytes_read = 0

    def readable(self):
        return True

    def read(self, size=None):
        exception_raised = True
        try:
            while self._iterator and (size is None or len(self._buffer) < size):
                chunk = next(self._iterator, None)
                if chunk is None:
Repository: yt-dlp/yt-dlp
File: yt_dlp/extractor/digitalconcerthall.py (Python)

Code before:
    def _real_extract(self, url):
        language, type_, video_id, part = self._match_valid_url(url).group('language', 'type', 'id', 'part')
        if not language:
            language = 'en'

        api_type = 'concert' if type_ == 'work' else type_
        vid_info = self._download_json(
            f'https://api.digitalconcerthall.com/v2/{api_type}/{video_id}', video_id, headers={
                'Accept': 'application/json',
                'Accept-Language': language,
            })
        album_artists = traverse_obj(vid_info, ('_links', 'artist', ..., 'name'))
        videos = [vid_info] if type_ == 'film' else traverse_obj(vid_info, ('_embedded', ..., ...))

        if type_ == 'work':
            videos = [videos[int(part) - 1]]

        thumbnail = traverse_obj(vid_info, (
            'image', ..., {lambda x: f'https:{x}' if x.startswith('//') else x},
            {lambda x: x.replace('{width}x{height}', '0x0')}, {url_or_none}, any))  # NB: 0x0 is the original size

        return {
            '_type': 'playlist',
            'id': video_id,
            'title': vid_info.get('title'),
            'entries': self._entries(videos, language, thumbnail=thumbnail, album_artists=album_artists, type_=type_),
            'thumbnail': thumbnail,
            'album_artists': album_artists,
        }


Review comment (suggestion):
```suggestion
            'entries': self._entries(
                videos, language, type_, thumbnail=thumbnail, album_artists=album_artists),
```

Code after:
    def _real_extract(self, url):
        language, type_, video_id, part = self._match_valid_url(url).group('language', 'type', 'id', 'part')
        if not language:
            language = 'en'

        api_type = 'concert' if type_ == 'work' else type_
        vid_info = self._download_json(
            f'https://api.digitalconcerthall.com/v2/{api_type}/{video_id}', video_id, headers={
                'Accept': 'application/json',
                'Accept-Language': language,
            })
        album_artists = traverse_obj(vid_info, ('_links', 'artist', ..., 'name'))
        videos = [vid_info] if type_ == 'film' else traverse_obj(vid_info, ('_embedded', ..., ...))

        if type_ == 'work':
            videos = [videos[int(part) - 1]]

        thumbnail = traverse_obj(vid_info, (
            'image', ..., {self._proto_relative_url}, {url_or_none},
            {lambda x: x.format(width=0, height=0)}, any))  # NB: 0x0 is the original size

        return {
            '_type': 'playlist',
            'id': video_id,
            'title': vid_info.get('title'),
            'entries': self._entries(
                videos, language, type_, thumbnail=thumbnail, album_artists=album_artists),
            'thumbnail': thumbnail,
            'album_artists': album_artists,
        }
Repository: yt-dlp/yt-dlp
File: yt_dlp/extractor/cnn.py (Python)

Code before:
from .common import InfoExtractor
from ..utils import extract_attributes, merge_dicts, try_call, url_or_none
from ..utils.traversal import find_element, traverse_obj


class CNNIE(InfoExtractor):
    _VALID_URL = r'https?://(?:(?:edition|www|money)\.)?cnn\.com/(?!audio)(?P<display_id>[^?#]+?)(?:[?#]|$|/index\.html)'

    _TESTS = [{
        'url': 'https://www.cnn.com/2024/05/31/sport/video/jadon-sancho-borussia-dortmund-champions-league-exclusive-spt-intl',
        'info_dict': {
            'id': 'med0e97ad0d154f56e29aa96e57192a14226734b6b',
            'display_id': '2024/05/31/sport/video/jadon-sancho-borussia-dortmund-champions-league-exclusive-spt-intl',
            'ext': 'mp4',
            'upload_date': '20240531',
            'description': 'md5:bea833dc9ab0711351d82fd014a9466c',
            'thumbnail': 'https://media.cnn.com/api/v1/images/stellar/prod/gettyimages-2151936122.jpg?c=original',
            'duration': 373.0,
            'timestamp': 1717148586,
            'title': 'Borussia Dortmund star Jadon Sancho seeks Wembley redemption after 2020 Euros hurt',
        },
    }, {
        'url': 'https://edition.cnn.com/2024/06/11/politics/video/inmates-vote-jail-nevada-murray-dnt-ac360-digvid',
        'info_dict': {
            'id': 'me522945c4709b299e5cb8657900a7a21ad3b559f9',
            'display_id': '2024/06/11/politics/video/inmates-vote-jail-nevada-murray-dnt-ac360-digvid',
            'ext': 'mp4',
            'description': 'md5:e0120fe5da9ad8259fd707c1cbb64a60',
            'title': 'Here’s how some inmates in closely divided state are now able to vote from jail',
            'timestamp': 1718158269,
            'upload_date': '20240612',
            'thumbnail': 'https://media.cnn.com/api/v1/images/stellar/prod/still-20701554-13565-571-still.jpg?c=original',

Review comment (suggestion):
```suggestion
    _VALID_URL = r'https?://(?:(?:edition|www|money)\.)?cnn\.com/(?!audio/)(?P<display_id>[^?#]+?)(?:[?#]|$|/index\.html)'
```

Code after:
import functools
import json
import re

from .common import InfoExtractor
from ..utils import (
    clean_html,
    extract_attributes,
    int_or_none,
    merge_dicts,
    parse_duration,
    parse_iso8601,
    parse_resolution,
    try_call,
    update_url,
    url_or_none,
)
from ..utils.traversal import find_elements, traverse_obj


class CNNIE(InfoExtractor):
    _VALID_URL = r'https?://(?:(?:edition|www|money|cnnespanol)\.)?cnn\.com/(?!audio/)(?P<display_id>[^?#]+?)(?:[?#]|$|/index\.html)'

    _TESTS = [{
        'url': 'https://www.cnn.com/2024/05/31/sport/video/jadon-sancho-borussia-dortmund-champions-league-exclusive-spt-intl',
        'info_dict': {
            'id': 'med0e97ad0d154f56e29aa96e57192a14226734b6b',
            'display_id': '2024/05/31/sport/video/jadon-sancho-borussia-dortmund-champions-league-exclusive-spt-intl',
            'ext': 'mp4',
            'upload_date': '20240531',
            'description': 'md5:844bcdb0629e1877a7a466c913f4c19c',
            'thumbnail': 'https://media.cnn.com/api/v1/images/stellar/prod/gettyimages-2151936122.jpg?c=original',
Repository: yt-dlp/yt-dlp
File: yt_dlp/extractor/matchtv.py (Python)

Code before:
from .common import InfoExtractor

class MatchTVIE(InfoExtractor):
    _VALID_URL = r'https?://matchtv\.ru/on-air'
    _TESTS = [{
        'url': 'http://matchtv.ru/on-air/',
        'info_dict': {
            'id': 'matchtv-live',
            'ext': 'mp4',
            'title': r're:^Матч ТВ - Прямой эфир \d{4}-\d{2}-\d{2} \d{2}:\d{2}$',
            'is_live': True,
        },
        'params': {
            'skip_download': True,
        },
    }]

    def _real_extract(self, url):
        video_id = 'matchtv-live'
        webpage_url = 'https://video.matchtv.ru/iframe/channel/106'
        webpage = self._download_webpage(webpage_url, video_id)
        video_url = self._html_search_regex(
            r'data-config="config=([^?]*)?', webpage, 'video URL').replace('feed', 'media') + '.m3u8'
        formats = self._extract_m3u8_formats(video_url, video_id, 'mp4')
        return {
            'id': video_id,
            'title': 'Матч ТВ - Прямой эфир',

Review comment (suggestion):
You are missing a new line after your imports.
```suggestion


```
You can also run ruff locally to automatically fix these things.

Code after:
from .common import InfoExtractor


class MatchTVIE(InfoExtractor):
    _VALID_URL = [
        r'https?://matchtv\.ru/on-air/?(?:$|[?#])',
        r'https?://video\.matchtv\.ru/iframe/channel/106/?(?:$|[?#])',
    ]
    _TESTS = [{
        'url': 'http://matchtv.ru/on-air/',
        'info_dict': {
            'id': 'matchtv-live',
            'ext': 'mp4',
            'title': r're:^Матч ТВ - Прямой эфир \d{4}-\d{2}-\d{2} \d{2}:\d{2}$',
            'live_status': 'is_live',
        },
        'params': {
            'skip_download': True,
        },
    }, {
        'url': 'https://video.matchtv.ru/iframe/channel/106',
        'only_matching': True,
    }]

    def _real_extract(self, url):
        video_id = 'matchtv-live'
        webpage = self._download_webpage('https://video.matchtv.ru/iframe/channel/106', video_id)