Remove union types to fix python 3.8 compat

This commit is contained in:
Ivan Habunek 2024-04-23 17:14:27 +02:00
parent e50499351b
commit a0ad66ee69
No known key found for this signature in database
GPG Key ID: F5F0623FF5EBCB3D
8 changed files with 51 additions and 48 deletions

View File

@ -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,
): ):

View File

@ -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

View File

@ -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,
): ):

View File

@ -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

View File

@ -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))

View File

@ -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

View File

@ -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(

View File

@ -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)