mirror of
https://github.com/ihabunek/twitch-dl
synced 2024-08-30 18:32:25 +00:00
Remove union types to fix python 3.8 compat
This commit is contained in:
parent
e50499351b
commit
a0ad66ee69
@ -2,6 +2,7 @@ import logging
|
|||||||
import platform
|
import platform
|
||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
import click
|
import click
|
||||||
|
|
||||||
@ -30,13 +31,13 @@ json_option = click.option(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def validate_positive(_ctx: click.Context, _param: click.Parameter, value: int | None):
|
def validate_positive(_ctx: click.Context, _param: click.Parameter, value: Optional[int]):
|
||||||
if value is not None and value <= 0:
|
if value is not None and value <= 0:
|
||||||
raise click.BadParameter("must be greater than 0")
|
raise click.BadParameter("must be greater than 0")
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
|
||||||
def validate_time(_ctx: click.Context, _param: click.Parameter, value: str) -> int | None:
|
def validate_time(_ctx: click.Context, _param: click.Parameter, value: str) -> Optional[int]:
|
||||||
"""Parse a time string (hh:mm or hh:mm:ss) to number of seconds."""
|
"""Parse a time string (hh:mm or hh:mm:ss) to number of seconds."""
|
||||||
if not value:
|
if not value:
|
||||||
return None
|
return None
|
||||||
@ -56,7 +57,7 @@ def validate_time(_ctx: click.Context, _param: click.Parameter, value: str) -> i
|
|||||||
return hours * 3600 + minutes * 60 + seconds
|
return hours * 3600 + minutes * 60 + seconds
|
||||||
|
|
||||||
|
|
||||||
def validate_rate(_ctx: click.Context, _param: click.Parameter, value: str) -> int | None:
|
def validate_rate(_ctx: click.Context, _param: click.Parameter, value: str) -> Optional[int]:
|
||||||
if not value:
|
if not value:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@ -143,8 +144,8 @@ def clips(
|
|||||||
compact: bool,
|
compact: bool,
|
||||||
download: bool,
|
download: bool,
|
||||||
json: bool,
|
json: bool,
|
||||||
limit: int | None,
|
limit: Optional[int],
|
||||||
pager: int | None,
|
pager: Optional[int],
|
||||||
period: ClipsPeriod,
|
period: ClipsPeriod,
|
||||||
):
|
):
|
||||||
"""List or download clips for given CHANNEL_NAME."""
|
"""List or download clips for given CHANNEL_NAME."""
|
||||||
@ -255,19 +256,19 @@ def clips(
|
|||||||
)
|
)
|
||||||
def download(
|
def download(
|
||||||
ids: tuple[str, ...],
|
ids: tuple[str, ...],
|
||||||
auth_token: str | None,
|
auth_token: Optional[str],
|
||||||
chapter: int | None,
|
chapter: Optional[int],
|
||||||
concat: bool,
|
concat: bool,
|
||||||
dry_run: bool,
|
dry_run: bool,
|
||||||
end: int | None,
|
end: Optional[int],
|
||||||
format: str,
|
format: str,
|
||||||
keep: bool,
|
keep: bool,
|
||||||
no_join: bool,
|
no_join: bool,
|
||||||
overwrite: bool,
|
overwrite: bool,
|
||||||
output: str,
|
output: str,
|
||||||
quality: str | None,
|
quality: Optional[str],
|
||||||
rate_limit: int | None,
|
rate_limit: Optional[int],
|
||||||
start: int | None,
|
start: Optional[int],
|
||||||
max_workers: int,
|
max_workers: int,
|
||||||
):
|
):
|
||||||
"""Download videos or clips.
|
"""Download videos or clips.
|
||||||
@ -375,8 +376,8 @@ def videos(
|
|||||||
compact: bool,
|
compact: bool,
|
||||||
games_tuple: tuple[str, ...],
|
games_tuple: tuple[str, ...],
|
||||||
json: bool,
|
json: bool,
|
||||||
limit: int | None,
|
limit: Optional[int],
|
||||||
pager: int | None,
|
pager: Optional[int],
|
||||||
sort: VideosSort,
|
sort: VideosSort,
|
||||||
type: VideosType,
|
type: VideosType,
|
||||||
):
|
):
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
from os import path
|
from os import path
|
||||||
from typing import Callable, Generator
|
from typing import Callable, Generator, Optional
|
||||||
|
|
||||||
import click
|
import click
|
||||||
|
|
||||||
@ -9,7 +9,7 @@ from twitchdl import twitch, utils
|
|||||||
from twitchdl.commands.download import get_clip_authenticated_url
|
from twitchdl.commands.download import get_clip_authenticated_url
|
||||||
from twitchdl.download import download_file
|
from twitchdl.download import download_file
|
||||||
from twitchdl.output import green, print_clip, print_clip_compact, print_json, print_paged, yellow
|
from twitchdl.output import green, print_clip, print_clip_compact, print_json, print_paged, yellow
|
||||||
from twitchdl.twitch import Clip
|
from twitchdl.twitch import Clip, ClipsPeriod
|
||||||
|
|
||||||
|
|
||||||
def clips(
|
def clips(
|
||||||
@ -19,9 +19,9 @@ def clips(
|
|||||||
compact: bool = False,
|
compact: bool = False,
|
||||||
download: bool = False,
|
download: bool = False,
|
||||||
json: bool = False,
|
json: bool = False,
|
||||||
limit: int | None = None,
|
limit: Optional[int] = None,
|
||||||
pager: int | None = None,
|
pager: Optional[int] = None,
|
||||||
period: twitch.ClipsPeriod = "all_time",
|
period: ClipsPeriod = "all_time",
|
||||||
):
|
):
|
||||||
# Set different defaults for limit for compact display
|
# Set different defaults for limit for compact display
|
||||||
default_limit = 40 if compact else 10
|
default_limit = 40 if compact else 10
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import sys
|
import sys
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
import click
|
import click
|
||||||
|
|
||||||
@ -14,8 +15,8 @@ def videos(
|
|||||||
compact: bool,
|
compact: bool,
|
||||||
games: list[str],
|
games: list[str],
|
||||||
json: bool,
|
json: bool,
|
||||||
limit: int | None,
|
limit: Optional[int],
|
||||||
pager: int | None,
|
pager: Optional[int],
|
||||||
sort: twitch.VideosSort,
|
sort: twitch.VideosSort,
|
||||||
type: twitch.VideosType,
|
type: twitch.VideosType,
|
||||||
):
|
):
|
||||||
|
@ -1,22 +1,22 @@
|
|||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from typing import Any
|
from typing import Any, Optional
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class DownloadOptions:
|
class DownloadOptions:
|
||||||
auth_token: str | None
|
auth_token: Optional[str]
|
||||||
chapter: int | None
|
chapter: Optional[int]
|
||||||
concat: bool
|
concat: bool
|
||||||
dry_run: bool
|
dry_run: bool
|
||||||
end: int | None
|
end: Optional[int]
|
||||||
format: str
|
format: str
|
||||||
keep: bool
|
keep: bool
|
||||||
no_join: bool
|
no_join: bool
|
||||||
overwrite: bool
|
overwrite: bool
|
||||||
output: str
|
output: str
|
||||||
quality: str | None
|
quality: Optional[str]
|
||||||
rate_limit: int | None
|
rate_limit: Optional[int]
|
||||||
start: int | None
|
start: Optional[int]
|
||||||
max_workers: int
|
max_workers: int
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import json
|
import json
|
||||||
from itertools import islice
|
from itertools import islice
|
||||||
from typing import Any, Callable, Generator, TypeVar
|
from typing import Any, Callable, Generator, Optional, TypeVar
|
||||||
|
|
||||||
import click
|
import click
|
||||||
|
|
||||||
@ -49,7 +49,7 @@ def print_paged(
|
|||||||
generator: Generator[T, Any, Any],
|
generator: Generator[T, Any, Any],
|
||||||
print_fn: Callable[[T], None],
|
print_fn: Callable[[T], None],
|
||||||
page_size: int,
|
page_size: int,
|
||||||
total_count: int | None = None,
|
total_count: Optional[int] = None,
|
||||||
):
|
):
|
||||||
iterator = iter(generator)
|
iterator = iter(generator)
|
||||||
page = list(islice(iterator, page_size))
|
page = list(islice(iterator, page_size))
|
||||||
|
@ -3,7 +3,7 @@ Parse and manipulate m3u8 playlists.
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from typing import Generator, OrderedDict
|
from typing import Generator, Optional, OrderedDict
|
||||||
|
|
||||||
import click
|
import click
|
||||||
import m3u8
|
import m3u8
|
||||||
@ -15,7 +15,7 @@ from twitchdl.output import bold, dim
|
|||||||
@dataclass
|
@dataclass
|
||||||
class Playlist:
|
class Playlist:
|
||||||
name: str
|
name: str
|
||||||
resolution: str | None
|
resolution: Optional[str]
|
||||||
url: str
|
url: str
|
||||||
|
|
||||||
|
|
||||||
@ -53,8 +53,8 @@ def load_m3u8(playlist_m3u8: str) -> m3u8.M3U8:
|
|||||||
|
|
||||||
def enumerate_vods(
|
def enumerate_vods(
|
||||||
document: m3u8.M3U8,
|
document: m3u8.M3U8,
|
||||||
start: int | None = None,
|
start: Optional[int] = None,
|
||||||
end: int | None = None,
|
end: Optional[int] = None,
|
||||||
) -> list[Vod]:
|
) -> list[Vod]:
|
||||||
"""Extract VODs for download from document."""
|
"""Extract VODs for download from document."""
|
||||||
vods = []
|
vods = []
|
||||||
@ -97,7 +97,7 @@ def make_join_playlist(
|
|||||||
return playlist
|
return playlist
|
||||||
|
|
||||||
|
|
||||||
def select_playlist(playlists: list[Playlist], quality: str | None) -> Playlist:
|
def select_playlist(playlists: list[Playlist], quality: Optional[str]) -> Playlist:
|
||||||
return (
|
return (
|
||||||
select_playlist_by_name(playlists, quality)
|
select_playlist_by_name(playlists, quality)
|
||||||
if quality is not None
|
if quality is not None
|
||||||
|
@ -3,7 +3,7 @@ Twitch API access.
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import json
|
import json
|
||||||
from typing import Dict, Generator, Literal, TypedDict
|
from typing import Dict, Generator, Literal, TypedDict, Optional
|
||||||
|
|
||||||
import click
|
import click
|
||||||
import httpx
|
import httpx
|
||||||
@ -163,7 +163,7 @@ CLIP_FIELDS = """
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
def get_video(video_id: str) -> Video | None:
|
def get_video(video_id: str) -> Optional[Video]:
|
||||||
query = f"""
|
query = f"""
|
||||||
{{
|
{{
|
||||||
video(id: "{video_id}") {{
|
video(id: "{video_id}") {{
|
||||||
@ -176,7 +176,7 @@ def get_video(video_id: str) -> Video | None:
|
|||||||
return response["data"]["video"]
|
return response["data"]["video"]
|
||||||
|
|
||||||
|
|
||||||
def get_clip(slug: str) -> Clip | None:
|
def get_clip(slug: str) -> Optional[Clip]:
|
||||||
query = f"""
|
query = f"""
|
||||||
{{
|
{{
|
||||||
clip(slug: "{slug}") {{
|
clip(slug: "{slug}") {{
|
||||||
@ -209,7 +209,7 @@ def get_clip_access_token(slug: str) -> ClipAccessToken:
|
|||||||
return response["data"]["clip"]
|
return response["data"]["clip"]
|
||||||
|
|
||||||
|
|
||||||
def get_channel_clips(channel_id: str, period: ClipsPeriod, limit: int, after: str | None = None):
|
def get_channel_clips(channel_id: str, period: ClipsPeriod, limit: int, after: Optional[str] = None):
|
||||||
"""
|
"""
|
||||||
List channel clips.
|
List channel clips.
|
||||||
|
|
||||||
@ -294,8 +294,8 @@ def get_channel_videos(
|
|||||||
limit: int,
|
limit: int,
|
||||||
sort: str,
|
sort: str,
|
||||||
type: str = "archive",
|
type: str = "archive",
|
||||||
game_ids: list[str] | None = None,
|
game_ids: Optional[list[str]] = None,
|
||||||
after: str | None = None,
|
after: Optional[str] = None,
|
||||||
):
|
):
|
||||||
game_ids = game_ids or []
|
game_ids = game_ids or []
|
||||||
|
|
||||||
@ -339,7 +339,7 @@ def channel_videos_generator(
|
|||||||
max_videos: int,
|
max_videos: int,
|
||||||
sort: VideosSort,
|
sort: VideosSort,
|
||||||
type: VideosType,
|
type: VideosType,
|
||||||
game_ids: list[str] | None = None,
|
game_ids: Optional[list[str]] = None,
|
||||||
) -> tuple[int, Generator[Video, None, None]]:
|
) -> tuple[int, Generator[Video, None, None]]:
|
||||||
game_ids = game_ids or []
|
game_ids = game_ids or []
|
||||||
|
|
||||||
@ -364,7 +364,7 @@ def channel_videos_generator(
|
|||||||
return videos["totalCount"], _generator(videos, max_videos)
|
return videos["totalCount"], _generator(videos, max_videos)
|
||||||
|
|
||||||
|
|
||||||
def get_access_token(video_id: str, auth_token: str | None = None) -> AccessToken:
|
def get_access_token(video_id: str, auth_token: Optional[str] = None) -> AccessToken:
|
||||||
query = f"""
|
query = f"""
|
||||||
{{
|
{{
|
||||||
videoPlaybackAccessToken(
|
videoPlaybackAccessToken(
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import re
|
import re
|
||||||
|
from typing import Optional, Union
|
||||||
import unicodedata
|
import unicodedata
|
||||||
|
|
||||||
import click
|
import click
|
||||||
@ -11,7 +12,7 @@ def _format_size(value: float, digits: int, unit: str):
|
|||||||
return f"{int(value)}{unit}"
|
return f"{int(value)}{unit}"
|
||||||
|
|
||||||
|
|
||||||
def format_size(bytes_: int | float, digits: int = 1):
|
def format_size(bytes_: Union[int, float], digits: int = 1):
|
||||||
if bytes_ < 1024:
|
if bytes_ < 1024:
|
||||||
return _format_size(bytes_, digits, "B")
|
return _format_size(bytes_, digits, "B")
|
||||||
|
|
||||||
@ -26,7 +27,7 @@ def format_size(bytes_: int | float, digits: int = 1):
|
|||||||
return _format_size(mega / 1024, digits, "GB")
|
return _format_size(mega / 1024, digits, "GB")
|
||||||
|
|
||||||
|
|
||||||
def format_duration(total_seconds: int | float) -> str:
|
def format_duration(total_seconds: Union[int, float]) -> str:
|
||||||
total_seconds = int(total_seconds)
|
total_seconds = int(total_seconds)
|
||||||
hours = total_seconds // 3600
|
hours = total_seconds // 3600
|
||||||
remainder = total_seconds % 3600
|
remainder = total_seconds % 3600
|
||||||
@ -42,7 +43,7 @@ def format_duration(total_seconds: int | float) -> str:
|
|||||||
return f"{seconds} sec"
|
return f"{seconds} sec"
|
||||||
|
|
||||||
|
|
||||||
def format_time(total_seconds: int | float, force_hours: bool = False) -> str:
|
def format_time(total_seconds: Union[int, float], force_hours: bool = False) -> str:
|
||||||
total_seconds = int(total_seconds)
|
total_seconds = int(total_seconds)
|
||||||
hours = total_seconds // 3600
|
hours = total_seconds // 3600
|
||||||
remainder = total_seconds % 3600
|
remainder = total_seconds % 3600
|
||||||
@ -55,7 +56,7 @@ def format_time(total_seconds: int | float, force_hours: bool = False) -> str:
|
|||||||
return f"{minutes:02}:{seconds:02}"
|
return f"{minutes:02}:{seconds:02}"
|
||||||
|
|
||||||
|
|
||||||
def read_int(msg: str, min: int, max: int, default: int | None = None) -> int:
|
def read_int(msg: str, min: int, max: int, default: Optional[int] = None) -> int:
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
val = click.prompt(msg, default=default, type=int)
|
val = click.prompt(msg, default=default, type=int)
|
||||||
@ -93,7 +94,7 @@ CLIP_PATTERNS = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
def parse_video_identifier(identifier: str) -> str | None:
|
def parse_video_identifier(identifier: str) -> Optional[str]:
|
||||||
"""Given a video ID or URL returns the video ID, or null if not matched"""
|
"""Given a video ID or URL returns the video ID, or null if not matched"""
|
||||||
for pattern in VIDEO_PATTERNS:
|
for pattern in VIDEO_PATTERNS:
|
||||||
match = re.match(pattern, identifier)
|
match = re.match(pattern, identifier)
|
||||||
@ -101,7 +102,7 @@ def parse_video_identifier(identifier: str) -> str | None:
|
|||||||
return match.group("id")
|
return match.group("id")
|
||||||
|
|
||||||
|
|
||||||
def parse_clip_identifier(identifier: str) -> str | None:
|
def parse_clip_identifier(identifier: str) -> Optional[str]:
|
||||||
"""Given a clip slug or URL returns the clip slug, or null if not matched"""
|
"""Given a clip slug or URL returns the clip slug, or null if not matched"""
|
||||||
for pattern in CLIP_PATTERNS:
|
for pattern in CLIP_PATTERNS:
|
||||||
match = re.match(pattern, identifier)
|
match = re.match(pattern, identifier)
|
||||||
|
Loading…
Reference in New Issue
Block a user