mirror of
https://github.com/yt-dlp/yt-dlp.git
synced 2024-11-29 18:51:24 +01:00
Compare commits
No commits in common. "261b2be36e917675a282f669de2cbeb52d87e579" and "3fe9657fc3462cdee1665b89a2f5f12d39fd1c51" have entirely different histories.
261b2be36e
...
3fe9657fc3
|
@ -216,23 +216,5 @@
|
||||||
"action": "add",
|
"action": "add",
|
||||||
"when": "d784464399b600ba9516bbcec6286f11d68974dd",
|
"when": "d784464399b600ba9516bbcec6286f11d68974dd",
|
||||||
"short": "[priority] **The minimum *required* Python version has been raised to 3.9**\nPython 3.8 reached its end-of-life on 2024.10.07, and yt-dlp has now removed support for it. As an unfortunate side effect, the official `yt-dlp.exe` and `yt-dlp_x86.exe` binaries are no longer supported on Windows 7. [Read more](https://github.com/yt-dlp/yt-dlp/issues/10086)"
|
"short": "[priority] **The minimum *required* Python version has been raised to 3.9**\nPython 3.8 reached its end-of-life on 2024.10.07, and yt-dlp has now removed support for it. As an unfortunate side effect, the official `yt-dlp.exe` and `yt-dlp_x86.exe` binaries are no longer supported on Windows 7. [Read more](https://github.com/yt-dlp/yt-dlp/issues/10086)"
|
||||||
},
|
|
||||||
{
|
|
||||||
"action": "change",
|
|
||||||
"when": "914af9a0cf51c9a3f74aa88d952bee8334c67511",
|
|
||||||
"short": "Expand paths in `--plugin-dirs` (#11334)",
|
|
||||||
"authors": ["bashonly"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"action": "change",
|
|
||||||
"when": "c29f5a7fae93a08f3cfbb6127b2faa75145b06a0",
|
|
||||||
"short": "[ie/generic] Do not impersonate by default (#11336)",
|
|
||||||
"authors": ["bashonly"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"action": "change",
|
|
||||||
"when": "57212a5f97ce367590aaa5c3e9a135eead8f81f7",
|
|
||||||
"short": "[ie/vimeo] Fix API retries (#11351)",
|
|
||||||
"authors": ["bashonly"]
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -71,13 +71,14 @@ class CommitGroup(enum.Enum):
|
||||||
def get(cls, value: str) -> tuple[CommitGroup | None, str | None]:
|
def get(cls, value: str) -> tuple[CommitGroup | None, str | None]:
|
||||||
group, _, subgroup = (group.strip().lower() for group in value.partition('/'))
|
group, _, subgroup = (group.strip().lower() for group in value.partition('/'))
|
||||||
|
|
||||||
if result := cls.group_lookup().get(group):
|
result = cls.group_lookup().get(group)
|
||||||
return result, subgroup or None
|
if not result:
|
||||||
|
|
||||||
if subgroup:
|
if subgroup:
|
||||||
return None, value
|
return None, value
|
||||||
|
subgroup = group
|
||||||
|
result = cls.subgroup_lookup().get(subgroup)
|
||||||
|
|
||||||
return cls.subgroup_lookup().get(group), group or None
|
return result, subgroup or None
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
|
@ -135,7 +136,8 @@ class Changelog:
|
||||||
first = False
|
first = False
|
||||||
yield '\n<details><summary><h3>Changelog</h3></summary>\n'
|
yield '\n<details><summary><h3>Changelog</h3></summary>\n'
|
||||||
|
|
||||||
if group := groups[item]:
|
group = groups[item]
|
||||||
|
if group:
|
||||||
yield self.format_module(item.value, group)
|
yield self.format_module(item.value, group)
|
||||||
|
|
||||||
if self._collapsible:
|
if self._collapsible:
|
||||||
|
@ -251,7 +253,7 @@ class CommitRange:
|
||||||
''', re.VERBOSE | re.DOTALL)
|
''', re.VERBOSE | re.DOTALL)
|
||||||
EXTRACTOR_INDICATOR_RE = re.compile(r'(?:Fix|Add)\s+Extractors?', re.IGNORECASE)
|
EXTRACTOR_INDICATOR_RE = re.compile(r'(?:Fix|Add)\s+Extractors?', re.IGNORECASE)
|
||||||
REVERT_RE = re.compile(r'(?:\[[^\]]+\]\s+)?(?i:Revert)\s+([\da-f]{40})')
|
REVERT_RE = re.compile(r'(?:\[[^\]]+\]\s+)?(?i:Revert)\s+([\da-f]{40})')
|
||||||
FIXES_RE = re.compile(r'(?i:(?:bug\s*)?fix(?:es)?(?:\s+bugs?)?(?:\s+in|\s+for)?|Improve)\s+([\da-f]{40})')
|
FIXES_RE = re.compile(r'(?i:Fix(?:es)?(?:\s+bugs?)?(?:\s+in|\s+for)?|Revert|Improve)\s+([\da-f]{40})')
|
||||||
UPSTREAM_MERGE_RE = re.compile(r'Update to ytdl-commit-([\da-f]+)')
|
UPSTREAM_MERGE_RE = re.compile(r'Update to ytdl-commit-([\da-f]+)')
|
||||||
|
|
||||||
def __init__(self, start, end, default_author=None):
|
def __init__(self, start, end, default_author=None):
|
||||||
|
@ -285,16 +287,11 @@ class CommitRange:
|
||||||
short = next(lines)
|
short = next(lines)
|
||||||
skip = short.startswith('Release ') or short == '[version] update'
|
skip = short.startswith('Release ') or short == '[version] update'
|
||||||
|
|
||||||
fix_commitish = None
|
|
||||||
if match := self.FIXES_RE.search(short):
|
|
||||||
fix_commitish = match.group(1)
|
|
||||||
|
|
||||||
authors = [default_author] if default_author else []
|
authors = [default_author] if default_author else []
|
||||||
for line in iter(lambda: next(lines), self.COMMIT_SEPARATOR):
|
for line in iter(lambda: next(lines), self.COMMIT_SEPARATOR):
|
||||||
if match := self.AUTHOR_INDICATOR_RE.match(line):
|
match = self.AUTHOR_INDICATOR_RE.match(line)
|
||||||
|
if match:
|
||||||
authors = sorted(map(str.strip, line[match.end():].split(',')), key=str.casefold)
|
authors = sorted(map(str.strip, line[match.end():].split(',')), key=str.casefold)
|
||||||
if not fix_commitish and (match := self.FIXES_RE.fullmatch(line)):
|
|
||||||
fix_commitish = match.group(1)
|
|
||||||
|
|
||||||
commit = Commit(commit_hash, short, authors)
|
commit = Commit(commit_hash, short, authors)
|
||||||
if skip and (self._start or not i):
|
if skip and (self._start or not i):
|
||||||
|
@ -304,17 +301,21 @@ class CommitRange:
|
||||||
logger.debug(f'Reached Release commit, breaking: {commit}')
|
logger.debug(f'Reached Release commit, breaking: {commit}')
|
||||||
break
|
break
|
||||||
|
|
||||||
if match := self.REVERT_RE.fullmatch(commit.short):
|
revert_match = self.REVERT_RE.fullmatch(commit.short)
|
||||||
reverts[match.group(1)] = commit
|
if revert_match:
|
||||||
|
reverts[revert_match.group(1)] = commit
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if fix_commitish:
|
fix_match = self.FIXES_RE.search(commit.short)
|
||||||
fixes[fix_commitish].append(commit)
|
if fix_match:
|
||||||
|
commitish = fix_match.group(1)
|
||||||
|
fixes[commitish].append(commit)
|
||||||
|
|
||||||
commits[commit.hash] = commit
|
commits[commit.hash] = commit
|
||||||
|
|
||||||
for commitish, revert_commit in reverts.items():
|
for commitish, revert_commit in reverts.items():
|
||||||
if reverted := commits.pop(commitish, None):
|
reverted = commits.pop(commitish, None)
|
||||||
|
if reverted:
|
||||||
logger.debug(f'{commitish} fully reverted {reverted}')
|
logger.debug(f'{commitish} fully reverted {reverted}')
|
||||||
else:
|
else:
|
||||||
commits[revert_commit.hash] = revert_commit
|
commits[revert_commit.hash] = revert_commit
|
||||||
|
@ -460,7 +461,8 @@ def create_changelog(args):
|
||||||
|
|
||||||
logger.info(f'Loaded {len(commits)} commits')
|
logger.info(f'Loaded {len(commits)} commits')
|
||||||
|
|
||||||
if new_contributors := get_new_contributors(args.contributors_path, commits):
|
new_contributors = get_new_contributors(args.contributors_path, commits)
|
||||||
|
if new_contributors:
|
||||||
if args.contributors:
|
if args.contributors:
|
||||||
write_file(args.contributors_path, '\n'.join(new_contributors) + '\n', mode='a')
|
write_file(args.contributors_path, '\n'.join(new_contributors) + '\n', mode='a')
|
||||||
logger.info(f'New contributors: {", ".join(new_contributors)}')
|
logger.info(f'New contributors: {", ".join(new_contributors)}')
|
||||||
|
|
|
@ -12,86 +12,53 @@ from ..utils import (
|
||||||
|
|
||||||
|
|
||||||
class CCMAIE(InfoExtractor):
|
class CCMAIE(InfoExtractor):
|
||||||
IE_DESC = '3Cat, TV3 and Catalunya Ràdio'
|
_VALID_URL = r'https?://(?:www\.)?ccma\.cat/(?:[^/]+/)*?(?P<type>video|audio)/(?P<id>\d+)'
|
||||||
_VALID_URL = r'https?://(?:www\.)?3cat\.cat/(?:3cat|tv3/sx3)/[^/?#]+/(?P<type>video|audio)/(?P<id>\d+)'
|
|
||||||
_TESTS = [{
|
_TESTS = [{
|
||||||
# ccma.cat/tv3/alacarta/ URLs redirect to 3cat.cat/3cat/
|
'url': 'http://www.ccma.cat/tv3/alacarta/lespot-de-la-marato-de-tv3/lespot-de-la-marato-de-tv3/video/5630208/',
|
||||||
'url': 'https://www.3cat.cat/3cat/lespot-de-la-marato-de-tv3/video/5630208/',
|
|
||||||
'md5': '7296ca43977c8ea4469e719c609b0871',
|
'md5': '7296ca43977c8ea4469e719c609b0871',
|
||||||
'info_dict': {
|
'info_dict': {
|
||||||
'id': '5630208',
|
'id': '5630208',
|
||||||
'ext': 'mp4',
|
'ext': 'mp4',
|
||||||
'title': 'L\'espot de La Marató 2016: Ictus i les lesions medul·lars i cerebrals traumàtiques',
|
'title': 'L\'espot de La Marató de TV3',
|
||||||
'description': 'md5:f12987f320e2f6e988e9908e4fe97765',
|
'description': 'md5:f12987f320e2f6e988e9908e4fe97765',
|
||||||
'timestamp': 1478608140,
|
'timestamp': 1478608140,
|
||||||
'upload_date': '20161108',
|
'upload_date': '20161108',
|
||||||
'age_limit': 0,
|
'age_limit': 0,
|
||||||
'alt_title': 'EsportMarató2016WEB_PerPublicar',
|
|
||||||
'duration': 79,
|
|
||||||
'thumbnail': 'https://img.3cat.cat/multimedia/jpg/4/6/1478536106664.jpg',
|
|
||||||
'series': 'Dedicada a l\'ictus i les lesions medul·lars i cerebrals traumàtiques',
|
|
||||||
'categories': ['Divulgació'],
|
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
# ccma.cat/catradio/alacarta/ URLs redirect to 3cat.cat/3cat/
|
'url': 'http://www.ccma.cat/catradio/alacarta/programa/el-consell-de-savis-analitza-el-derbi/audio/943685/',
|
||||||
'url': 'https://www.3cat.cat/3cat/el-consell-de-savis-analitza-el-derbi/audio/943685/',
|
|
||||||
'md5': 'fa3e38f269329a278271276330261425',
|
'md5': 'fa3e38f269329a278271276330261425',
|
||||||
'info_dict': {
|
'info_dict': {
|
||||||
'id': '943685',
|
'id': '943685',
|
||||||
'ext': 'mp3',
|
'ext': 'mp3',
|
||||||
'title': 'El Consell de Savis analitza el derbi',
|
'title': 'El Consell de Savis analitza el derbi',
|
||||||
'description': 'md5:e2a3648145f3241cb9c6b4b624033e53',
|
'description': 'md5:e2a3648145f3241cb9c6b4b624033e53',
|
||||||
'upload_date': '20161217',
|
'upload_date': '20170512',
|
||||||
'timestamp': 1482011700,
|
'timestamp': 1494622500,
|
||||||
'vcodec': 'none',
|
'vcodec': 'none',
|
||||||
'categories': ['Esports'],
|
'categories': ['Esports'],
|
||||||
'series': 'Tot gira',
|
|
||||||
'duration': 821,
|
|
||||||
'thumbnail': 'https://img.3cat.cat/multimedia/jpg/8/9/1482002602598.jpg',
|
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
'url': 'https://www.3cat.cat/3cat/crims-josep-tallada-lespereu-me-part-1/video/6031387/',
|
'url': 'http://www.ccma.cat/tv3/alacarta/crims/crims-josep-tallada-lespereu-me-capitol-1/video/6031387/',
|
||||||
'md5': '27493513d08a3e5605814aee9bb778d2',
|
'md5': 'b43c3d3486f430f3032b5b160d80cbc3',
|
||||||
'info_dict': {
|
'info_dict': {
|
||||||
'id': '6031387',
|
'id': '6031387',
|
||||||
'ext': 'mp4',
|
'ext': 'mp4',
|
||||||
'title': 'T1xC5 - Josep Talleda, l\'"Espereu-me" (part 1)',
|
'title': 'Crims - Josep Talleda, l\'"Espereu-me" (capítol 1)',
|
||||||
'description': 'md5:7cbdafb640da9d0d2c0f62bad1e74e60',
|
'description': 'md5:7cbdafb640da9d0d2c0f62bad1e74e60',
|
||||||
'timestamp': 1582577919,
|
'timestamp': 1582577700,
|
||||||
'upload_date': '20200224',
|
'upload_date': '20200224',
|
||||||
'subtitles': 'mincount:1',
|
'subtitles': 'mincount:4',
|
||||||
'age_limit': 13,
|
'age_limit': 16,
|
||||||
'series': 'Crims',
|
'series': 'Crims',
|
||||||
'thumbnail': 'https://img.3cat.cat/multimedia/jpg/1/9/1582564376991.jpg',
|
|
||||||
'duration': 3203,
|
|
||||||
'categories': ['Divulgació'],
|
|
||||||
'alt_title': 'Crims - 5 - Josep Talleda, l\'"Espereu-me" (1a part) - Josep Talleda, l\'"Espereu-me" (part 1)',
|
|
||||||
'episode_number': 5,
|
|
||||||
'episode': 'Episode 5',
|
|
||||||
},
|
|
||||||
}, {
|
|
||||||
'url': 'https://www.3cat.cat/tv3/sx3/una-mosca-volava-per-la-llum/video/5759227/',
|
|
||||||
'info_dict': {
|
|
||||||
'id': '5759227',
|
|
||||||
'ext': 'mp4',
|
|
||||||
'title': 'Una mosca volava per la llum',
|
|
||||||
'alt_title': '17Z004Ç UNA MOSCA VOLAVA PER LA LLUM',
|
|
||||||
'description': 'md5:9ab64276944b0825336f4147f13f7854',
|
|
||||||
'series': 'Mic',
|
|
||||||
'upload_date': '20180411',
|
|
||||||
'timestamp': 1523440105,
|
|
||||||
'duration': 160,
|
|
||||||
'age_limit': 0,
|
|
||||||
'thumbnail': 'https://img.3cat.cat/multimedia/jpg/6/1/1524071667216.jpg',
|
|
||||||
'categories': ['Música'],
|
|
||||||
},
|
},
|
||||||
}]
|
}]
|
||||||
|
|
||||||
def _real_extract(self, url):
|
def _real_extract(self, url):
|
||||||
media_type, media_id = self._match_valid_url(url).group('type', 'id')
|
media_type, media_id = self._match_valid_url(url).groups()
|
||||||
|
|
||||||
media = self._download_json(
|
media = self._download_json(
|
||||||
'http://api-media.3cat.cat/pvideo/media.jsp', media_id, query={
|
'http://dinamics.ccma.cat/pvideo/media.jsp', media_id, query={
|
||||||
'media': media_type,
|
'media': media_type,
|
||||||
'idint': media_id,
|
'idint': media_id,
|
||||||
'format': 'dm',
|
'format': 'dm',
|
||||||
|
|
|
@ -208,6 +208,7 @@ class SoundcloudBaseIE(InfoExtractor):
|
||||||
|
|
||||||
def _extract_info_dict(self, info, full_title=None, secret_token=None, extract_flat=False):
|
def _extract_info_dict(self, info, full_title=None, secret_token=None, extract_flat=False):
|
||||||
track_id = str(info['id'])
|
track_id = str(info['id'])
|
||||||
|
title = info['title']
|
||||||
|
|
||||||
format_urls = set()
|
format_urls = set()
|
||||||
formats = []
|
formats = []
|
||||||
|
@ -366,7 +367,7 @@ class SoundcloudBaseIE(InfoExtractor):
|
||||||
'uploader_id': str_or_none(user.get('id')) or user.get('permalink'),
|
'uploader_id': str_or_none(user.get('id')) or user.get('permalink'),
|
||||||
'uploader_url': user.get('permalink_url'),
|
'uploader_url': user.get('permalink_url'),
|
||||||
'timestamp': unified_timestamp(info.get('created_at')),
|
'timestamp': unified_timestamp(info.get('created_at')),
|
||||||
'title': info.get('title'),
|
'title': title,
|
||||||
'description': info.get('description'),
|
'description': info.get('description'),
|
||||||
'thumbnails': thumbnails,
|
'thumbnails': thumbnails,
|
||||||
'duration': float_or_none(info.get('duration'), 1000),
|
'duration': float_or_none(info.get('duration'), 1000),
|
||||||
|
@ -376,8 +377,7 @@ class SoundcloudBaseIE(InfoExtractor):
|
||||||
'like_count': extract_count('favoritings') or extract_count('likes'),
|
'like_count': extract_count('favoritings') or extract_count('likes'),
|
||||||
'comment_count': extract_count('comment'),
|
'comment_count': extract_count('comment'),
|
||||||
'repost_count': extract_count('reposts'),
|
'repost_count': extract_count('reposts'),
|
||||||
'genres': traverse_obj(info, ('genre', {str}, filter, all, filter)),
|
'genres': traverse_obj(info, ('genre', {str}, {lambda x: x or None}, all)),
|
||||||
'artists': traverse_obj(info, ('publisher_metadata', 'artist', {str}, filter, all, filter)),
|
|
||||||
'formats': formats if not extract_flat else None,
|
'formats': formats if not extract_flat else None,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -429,6 +429,7 @@ class SoundcloudIE(SoundcloudBaseIE):
|
||||||
'repost_count': int,
|
'repost_count': int,
|
||||||
'thumbnail': 'https://i1.sndcdn.com/artworks-000031955188-rwb18x-original.jpg',
|
'thumbnail': 'https://i1.sndcdn.com/artworks-000031955188-rwb18x-original.jpg',
|
||||||
'uploader_url': 'https://soundcloud.com/ethmusic',
|
'uploader_url': 'https://soundcloud.com/ethmusic',
|
||||||
|
'genres': [],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
# geo-restricted
|
# geo-restricted
|
||||||
|
@ -452,7 +453,6 @@ class SoundcloudIE(SoundcloudBaseIE):
|
||||||
'uploader_url': 'https://soundcloud.com/the-concept-band',
|
'uploader_url': 'https://soundcloud.com/the-concept-band',
|
||||||
'thumbnail': 'https://i1.sndcdn.com/artworks-v8bFHhXm7Au6-0-original.jpg',
|
'thumbnail': 'https://i1.sndcdn.com/artworks-v8bFHhXm7Au6-0-original.jpg',
|
||||||
'genres': ['Alternative'],
|
'genres': ['Alternative'],
|
||||||
'artists': ['The Royal Concept'],
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
# private link
|
# private link
|
||||||
|
@ -525,7 +525,6 @@ class SoundcloudIE(SoundcloudBaseIE):
|
||||||
'repost_count': int,
|
'repost_count': int,
|
||||||
'view_count': int,
|
'view_count': int,
|
||||||
'genres': ['Dance & EDM'],
|
'genres': ['Dance & EDM'],
|
||||||
'artists': ['80M'],
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
# private link, downloadable format
|
# private link, downloadable format
|
||||||
|
@ -550,7 +549,6 @@ class SoundcloudIE(SoundcloudBaseIE):
|
||||||
'thumbnail': 'https://i1.sndcdn.com/artworks-000240712245-kedn4p-original.jpg',
|
'thumbnail': 'https://i1.sndcdn.com/artworks-000240712245-kedn4p-original.jpg',
|
||||||
'uploader_url': 'https://soundcloud.com/oriuplift',
|
'uploader_url': 'https://soundcloud.com/oriuplift',
|
||||||
'genres': ['Trance'],
|
'genres': ['Trance'],
|
||||||
'artists': ['Ori Uplift'],
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
# no album art, use avatar pic for thumbnail
|
# no album art, use avatar pic for thumbnail
|
||||||
|
@ -574,7 +572,7 @@ class SoundcloudIE(SoundcloudBaseIE):
|
||||||
'comment_count': int,
|
'comment_count': int,
|
||||||
'repost_count': int,
|
'repost_count': int,
|
||||||
'uploader_url': 'https://soundcloud.com/garyvee',
|
'uploader_url': 'https://soundcloud.com/garyvee',
|
||||||
'artists': ['MadReal'],
|
'genres': [],
|
||||||
},
|
},
|
||||||
'params': {
|
'params': {
|
||||||
'skip_download': True,
|
'skip_download': True,
|
||||||
|
|
|
@ -5165,7 +5165,6 @@ class _UnsafeExtensionError(Exception):
|
||||||
'ico',
|
'ico',
|
||||||
'image',
|
'image',
|
||||||
'jng',
|
'jng',
|
||||||
'jpe',
|
|
||||||
'jpeg',
|
'jpeg',
|
||||||
'jxl',
|
'jxl',
|
||||||
'svg',
|
'svg',
|
||||||
|
|
|
@ -391,13 +391,14 @@ def find_element(*, tag: str, html=False): ...
|
||||||
def find_element(*, tag=None, id=None, cls=None, attr=None, value=None, html=False):
|
def find_element(*, tag=None, id=None, cls=None, attr=None, value=None, html=False):
|
||||||
# deliberately using `id=` and `cls=` for ease of readability
|
# deliberately using `id=` and `cls=` for ease of readability
|
||||||
assert tag or id or cls or (attr and value), 'One of tag, id, cls or (attr AND value) is required'
|
assert tag or id or cls or (attr and value), 'One of tag, id, cls or (attr AND value) is required'
|
||||||
ANY_TAG = r'[\w:.-]+'
|
if not tag:
|
||||||
|
tag = r'[\w:.-]+'
|
||||||
|
|
||||||
if attr and value:
|
if attr and value:
|
||||||
assert not cls, 'Cannot match both attr and cls'
|
assert not cls, 'Cannot match both attr and cls'
|
||||||
assert not id, 'Cannot match both attr and id'
|
assert not id, 'Cannot match both attr and id'
|
||||||
func = get_element_html_by_attribute if html else get_element_by_attribute
|
func = get_element_html_by_attribute if html else get_element_by_attribute
|
||||||
return functools.partial(func, attr, value, tag=tag or ANY_TAG)
|
return functools.partial(func, attr, value, tag=tag)
|
||||||
|
|
||||||
elif cls:
|
elif cls:
|
||||||
assert not id, 'Cannot match both cls and id'
|
assert not id, 'Cannot match both cls and id'
|
||||||
|
@ -407,7 +408,7 @@ def find_element(*, tag=None, id=None, cls=None, attr=None, value=None, html=Fal
|
||||||
|
|
||||||
elif id:
|
elif id:
|
||||||
func = get_element_html_by_id if html else get_element_by_id
|
func = get_element_html_by_id if html else get_element_by_id
|
||||||
return functools.partial(func, id, tag=tag or ANY_TAG)
|
return functools.partial(func, id, tag=tag)
|
||||||
|
|
||||||
index = int(bool(html))
|
index = int(bool(html))
|
||||||
return lambda html: get_element_text_and_html_by_tag(tag, html)[index]
|
return lambda html: get_element_text_and_html_by_tag(tag, html)[index]
|
||||||
|
|
Loading…
Reference in New Issue
Block a user