Taylor Fox Dahlin
commited on
Consolidate import sections (#952)
Browse files* Squashes some import lines to reduce clutter at the top of files
- pytube/__init__.py +1 -2
- pytube/__main__.py +18 -33
- pytube/captions.py +2 -4
- pytube/cipher.py +2 -8
- pytube/cli.py +8 -13
- pytube/contrib/playlist.py +5 -15
- pytube/exceptions.py +1 -2
- pytube/extract.py +5 -15
- pytube/helpers.py +1 -6
- pytube/metadata.py +1 -3
- pytube/monostate.py +1 -3
- pytube/query.py +4 -9
- pytube/request.py +2 -3
- pytube/streams.py +3 -8
- tests/conftest.py +1 -2
- tests/test_captions.py +3 -8
- tests/test_cli.py +2 -6
- tests/test_exceptions.py +24 -29
- tests/test_helpers.py +3 -8
- tests/test_request.py +1 -2
- tests/test_streams.py +2 -3
pytube/__init__.py
CHANGED
@@ -12,7 +12,6 @@ __js_url__ = None
|
|
12 |
from pytube.version import __version__
|
13 |
from pytube.streams import Stream
|
14 |
from pytube.captions import Caption
|
15 |
-
from pytube.query import CaptionQuery
|
16 |
-
from pytube.query import StreamQuery
|
17 |
from pytube.__main__ import YouTube
|
18 |
from pytube.contrib.playlist import Playlist
|
|
|
12 |
from pytube.version import __version__
|
13 |
from pytube.streams import Stream
|
14 |
from pytube.captions import Caption
|
15 |
+
from pytube.query import CaptionQuery, StreamQuery
|
|
|
16 |
from pytube.__main__ import YouTube
|
17 |
from pytube.contrib.playlist import Playlist
|
pytube/__main__.py
CHANGED
@@ -9,28 +9,13 @@ smaller peripheral modules and functions.
|
|
9 |
"""
|
10 |
import json
|
11 |
import logging
|
12 |
-
from typing import Any
|
13 |
-
from typing import Callable
|
14 |
-
from typing import Dict
|
15 |
-
from typing import List
|
16 |
-
from typing import Optional
|
17 |
from urllib.parse import parse_qsl
|
18 |
|
19 |
import pytube
|
20 |
-
|
21 |
-
from pytube import
|
22 |
-
from pytube import
|
23 |
-
from pytube import request
|
24 |
-
from pytube import Stream
|
25 |
-
from pytube import StreamQuery
|
26 |
-
from pytube.exceptions import MembersOnly
|
27 |
-
from pytube.exceptions import RecordingUnavailable
|
28 |
-
from pytube.exceptions import VideoUnavailable
|
29 |
-
from pytube.exceptions import VideoPrivate
|
30 |
-
from pytube.exceptions import VideoRegionBlocked
|
31 |
-
from pytube.extract import apply_descrambler
|
32 |
-
from pytube.extract import apply_signature
|
33 |
-
from pytube.extract import get_ytplayer_config
|
34 |
from pytube.helpers import install_proxy
|
35 |
from pytube.metadata import YouTubeMetadata
|
36 |
from pytube.monostate import Monostate
|
@@ -204,7 +189,7 @@ class YouTube:
|
|
204 |
# On pre-signed videos, we need to use get_ytplayer_config to fix
|
205 |
# the player_response item
|
206 |
if 'streamingData' not in self.player_config_args['player_response']:
|
207 |
-
config_response = get_ytplayer_config(self.watch_html)
|
208 |
if 'args' in config_response:
|
209 |
self.player_config_args['player_response'] = config_response['args']['player_response'] # noqa: E501
|
210 |
else:
|
@@ -232,10 +217,10 @@ class YouTube:
|
|
232 |
# unscramble the progressive and adaptive stream manifests.
|
233 |
for fmt in stream_maps:
|
234 |
if not self.age_restricted and fmt in self.vid_info:
|
235 |
-
apply_descrambler(self.vid_info, fmt)
|
236 |
-
apply_descrambler(self.player_config_args, fmt)
|
237 |
|
238 |
-
apply_signature(self.player_config_args, fmt, self.js)
|
239 |
|
240 |
# build instances of :class:`Stream <Stream>`
|
241 |
# Initialize stream objects
|
@@ -267,23 +252,23 @@ class YouTube:
|
|
267 |
'Join this channel to get access to members-only content '
|
268 |
'like this video, and other exclusive perks.'
|
269 |
):
|
270 |
-
raise MembersOnly(video_id=self.video_id)
|
271 |
elif reason == 'This live stream recording is not available.':
|
272 |
-
raise RecordingUnavailable(video_id=self.video_id)
|
273 |
else:
|
274 |
if reason == 'Video unavailable':
|
275 |
if extract.is_region_blocked(self.watch_html):
|
276 |
-
raise VideoRegionBlocked(video_id=self.video_id)
|
277 |
-
raise VideoUnavailable(video_id=self.video_id)
|
278 |
elif status == 'LOGIN_REQUIRED':
|
279 |
if reason == (
|
280 |
'This is a private video. '
|
281 |
'Please sign in to verify that you may see it.'
|
282 |
):
|
283 |
-
raise VideoPrivate(video_id=self.video_id)
|
284 |
elif status == 'ERROR':
|
285 |
if reason == 'Video unavailable':
|
286 |
-
raise VideoUnavailable(video_id=self.video_id)
|
287 |
|
288 |
@property
|
289 |
def vid_info(self):
|
@@ -294,7 +279,7 @@ class YouTube:
|
|
294 |
return dict(parse_qsl(self.vid_info_raw))
|
295 |
|
296 |
@property
|
297 |
-
def caption_tracks(self) -> List[Caption]:
|
298 |
"""Get a list of :class:`Caption <Caption>`.
|
299 |
|
300 |
:rtype: List[Caption]
|
@@ -304,15 +289,15 @@ class YouTube:
|
|
304 |
.get("playerCaptionsTracklistRenderer", {})
|
305 |
.get("captionTracks", [])
|
306 |
)
|
307 |
-
return [Caption(track) for track in raw_tracks]
|
308 |
|
309 |
@property
|
310 |
-
def captions(self) -> CaptionQuery:
|
311 |
"""Interface to query caption tracks.
|
312 |
|
313 |
:rtype: :class:`CaptionQuery <CaptionQuery>`.
|
314 |
"""
|
315 |
-
return CaptionQuery(self.caption_tracks)
|
316 |
|
317 |
@property
|
318 |
def streams(self) -> StreamQuery:
|
|
|
9 |
"""
|
10 |
import json
|
11 |
import logging
|
12 |
+
from typing import Any, Callable, Dict, List, Optional
|
|
|
|
|
|
|
|
|
13 |
from urllib.parse import parse_qsl
|
14 |
|
15 |
import pytube
|
16 |
+
import pytube.exceptions as exceptions
|
17 |
+
from pytube import extract, request
|
18 |
+
from pytube import Stream, StreamQuery
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
19 |
from pytube.helpers import install_proxy
|
20 |
from pytube.metadata import YouTubeMetadata
|
21 |
from pytube.monostate import Monostate
|
|
|
189 |
# On pre-signed videos, we need to use get_ytplayer_config to fix
|
190 |
# the player_response item
|
191 |
if 'streamingData' not in self.player_config_args['player_response']:
|
192 |
+
config_response = extract.get_ytplayer_config(self.watch_html)
|
193 |
if 'args' in config_response:
|
194 |
self.player_config_args['player_response'] = config_response['args']['player_response'] # noqa: E501
|
195 |
else:
|
|
|
217 |
# unscramble the progressive and adaptive stream manifests.
|
218 |
for fmt in stream_maps:
|
219 |
if not self.age_restricted and fmt in self.vid_info:
|
220 |
+
extract.apply_descrambler(self.vid_info, fmt)
|
221 |
+
extract.apply_descrambler(self.player_config_args, fmt)
|
222 |
|
223 |
+
extract.apply_signature(self.player_config_args, fmt, self.js)
|
224 |
|
225 |
# build instances of :class:`Stream <Stream>`
|
226 |
# Initialize stream objects
|
|
|
252 |
'Join this channel to get access to members-only content '
|
253 |
'like this video, and other exclusive perks.'
|
254 |
):
|
255 |
+
raise exceptions.MembersOnly(video_id=self.video_id)
|
256 |
elif reason == 'This live stream recording is not available.':
|
257 |
+
raise exceptions.RecordingUnavailable(video_id=self.video_id)
|
258 |
else:
|
259 |
if reason == 'Video unavailable':
|
260 |
if extract.is_region_blocked(self.watch_html):
|
261 |
+
raise exceptions.VideoRegionBlocked(video_id=self.video_id)
|
262 |
+
raise exceptions.VideoUnavailable(video_id=self.video_id)
|
263 |
elif status == 'LOGIN_REQUIRED':
|
264 |
if reason == (
|
265 |
'This is a private video. '
|
266 |
'Please sign in to verify that you may see it.'
|
267 |
):
|
268 |
+
raise exceptions.VideoPrivate(video_id=self.video_id)
|
269 |
elif status == 'ERROR':
|
270 |
if reason == 'Video unavailable':
|
271 |
+
raise exceptions.VideoUnavailable(video_id=self.video_id)
|
272 |
|
273 |
@property
|
274 |
def vid_info(self):
|
|
|
279 |
return dict(parse_qsl(self.vid_info_raw))
|
280 |
|
281 |
@property
|
282 |
+
def caption_tracks(self) -> List[pytube.Caption]:
|
283 |
"""Get a list of :class:`Caption <Caption>`.
|
284 |
|
285 |
:rtype: List[Caption]
|
|
|
289 |
.get("playerCaptionsTracklistRenderer", {})
|
290 |
.get("captionTracks", [])
|
291 |
)
|
292 |
+
return [pytube.Caption(track) for track in raw_tracks]
|
293 |
|
294 |
@property
|
295 |
+
def captions(self) -> pytube.CaptionQuery:
|
296 |
"""Interface to query caption tracks.
|
297 |
|
298 |
:rtype: :class:`CaptionQuery <CaptionQuery>`.
|
299 |
"""
|
300 |
+
return pytube.CaptionQuery(self.caption_tracks)
|
301 |
|
302 |
@property
|
303 |
def streams(self) -> StreamQuery:
|
pytube/captions.py
CHANGED
@@ -4,12 +4,10 @@ import os
|
|
4 |
import time
|
5 |
import xml.etree.ElementTree as ElementTree
|
6 |
from html import unescape
|
7 |
-
from typing import Dict
|
8 |
-
from typing import Optional
|
9 |
|
10 |
from pytube import request
|
11 |
-
from pytube.helpers import safe_filename
|
12 |
-
from pytube.helpers import target_directory
|
13 |
|
14 |
|
15 |
class Caption:
|
|
|
4 |
import time
|
5 |
import xml.etree.ElementTree as ElementTree
|
6 |
from html import unescape
|
7 |
+
from typing import Dict, Optional
|
|
|
8 |
|
9 |
from pytube import request
|
10 |
+
from pytube.helpers import safe_filename, target_directory
|
|
|
11 |
|
12 |
|
13 |
class Caption:
|
pytube/cipher.py
CHANGED
@@ -16,16 +16,10 @@ signature and decoding it.
|
|
16 |
import logging
|
17 |
import re
|
18 |
from itertools import chain
|
19 |
-
from typing import Any
|
20 |
-
from typing import Callable
|
21 |
-
from typing import Dict
|
22 |
-
from typing import List
|
23 |
-
from typing import Optional
|
24 |
-
from typing import Tuple
|
25 |
|
26 |
from pytube.exceptions import RegexMatchError
|
27 |
-
from pytube.helpers import cache
|
28 |
-
from pytube.helpers import regex_search
|
29 |
|
30 |
logger = logging.getLogger(__name__)
|
31 |
|
|
|
16 |
import logging
|
17 |
import re
|
18 |
from itertools import chain
|
19 |
+
from typing import Any, Callable, Dict, List, Optional, Tuple
|
|
|
|
|
|
|
|
|
|
|
20 |
|
21 |
from pytube.exceptions import RegexMatchError
|
22 |
+
from pytube.helpers import cache, regex_search
|
|
|
23 |
|
24 |
logger = logging.getLogger(__name__)
|
25 |
|
pytube/cli.py
CHANGED
@@ -2,25 +2,20 @@
|
|
2 |
# -*- coding: utf-8 -*-
|
3 |
"""A simple command line application to download youtube videos."""
|
4 |
import argparse
|
5 |
-
import datetime as dt
|
6 |
import gzip
|
7 |
import json
|
8 |
import logging
|
9 |
import os
|
10 |
import shutil
|
11 |
-
import subprocess # nosec
|
12 |
import sys
|
13 |
-
|
14 |
-
|
|
|
15 |
|
|
|
16 |
from pytube import __version__
|
17 |
-
from pytube import CaptionQuery
|
18 |
-
from pytube import
|
19 |
-
from pytube import Stream
|
20 |
-
from pytube import YouTube
|
21 |
-
from pytube.exceptions import PytubeError, VideoUnavailable
|
22 |
-
from pytube.helpers import safe_filename
|
23 |
-
from pytube.helpers import setup_logger
|
24 |
|
25 |
|
26 |
def main():
|
@@ -47,7 +42,7 @@ def main():
|
|
47 |
for youtube_video in playlist.videos:
|
48 |
try:
|
49 |
_perform_args_on_youtube(youtube_video, args)
|
50 |
-
except PytubeError as e:
|
51 |
print(f"There was an error with video: {youtube_video}")
|
52 |
print(e)
|
53 |
else:
|
@@ -476,7 +471,7 @@ def download_highest_resolution_progressive(
|
|
476 |
youtube.register_on_progress_callback(on_progress)
|
477 |
try:
|
478 |
stream = youtube.streams.get_highest_resolution()
|
479 |
-
except VideoUnavailable as err:
|
480 |
print(f"No video streams available: {err}")
|
481 |
else:
|
482 |
try:
|
|
|
2 |
# -*- coding: utf-8 -*-
|
3 |
"""A simple command line application to download youtube videos."""
|
4 |
import argparse
|
|
|
5 |
import gzip
|
6 |
import json
|
7 |
import logging
|
8 |
import os
|
9 |
import shutil
|
|
|
10 |
import sys
|
11 |
+
import datetime as dt
|
12 |
+
import subprocess # nosec
|
13 |
+
from typing import List, Optional
|
14 |
|
15 |
+
import pytube.exceptions as exceptions
|
16 |
from pytube import __version__
|
17 |
+
from pytube import CaptionQuery, Playlist, Stream, YouTube
|
18 |
+
from pytube.helpers import safe_filename, setup_logger
|
|
|
|
|
|
|
|
|
|
|
19 |
|
20 |
|
21 |
def main():
|
|
|
42 |
for youtube_video in playlist.videos:
|
43 |
try:
|
44 |
_perform_args_on_youtube(youtube_video, args)
|
45 |
+
except exceptions.PytubeError as e:
|
46 |
print(f"There was an error with video: {youtube_video}")
|
47 |
print(e)
|
48 |
else:
|
|
|
471 |
youtube.register_on_progress_callback(on_progress)
|
472 |
try:
|
473 |
stream = youtube.streams.get_highest_resolution()
|
474 |
+
except exceptions.VideoUnavailable as err:
|
475 |
print(f"No video streams available: {err}")
|
476 |
else:
|
477 |
try:
|
pytube/contrib/playlist.py
CHANGED
@@ -4,21 +4,11 @@ import json
|
|
4 |
import logging
|
5 |
import re
|
6 |
from collections.abc import Sequence
|
7 |
-
from datetime import date
|
8 |
-
from
|
9 |
-
|
10 |
-
from
|
11 |
-
from
|
12 |
-
from typing import Optional
|
13 |
-
from typing import Union
|
14 |
-
|
15 |
-
from pytube import extract
|
16 |
-
from pytube import request
|
17 |
-
from pytube import YouTube
|
18 |
-
from pytube.helpers import cache
|
19 |
-
from pytube.helpers import install_proxy
|
20 |
-
from pytube.helpers import regex_search
|
21 |
-
from pytube.helpers import uniqueify
|
22 |
|
23 |
logger = logging.getLogger(__name__)
|
24 |
|
|
|
4 |
import logging
|
5 |
import re
|
6 |
from collections.abc import Sequence
|
7 |
+
from datetime import date, datetime
|
8 |
+
from typing import Dict, Iterable, List, Optional, Tuple, Union
|
9 |
+
|
10 |
+
from pytube import extract, request, YouTube
|
11 |
+
from pytube.helpers import cache, install_proxy, regex_search, uniqueify
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
12 |
|
13 |
logger = logging.getLogger(__name__)
|
14 |
|
pytube/exceptions.py
CHANGED
@@ -1,7 +1,6 @@
|
|
1 |
# -*- coding: utf-8 -*-
|
2 |
"""Library specific exception definitions."""
|
3 |
-
from typing import Pattern
|
4 |
-
from typing import Union
|
5 |
|
6 |
|
7 |
class PytubeError(Exception):
|
|
|
1 |
# -*- coding: utf-8 -*-
|
2 |
"""Library specific exception definitions."""
|
3 |
+
from typing import Pattern, Union
|
|
|
4 |
|
5 |
|
6 |
class PytubeError(Exception):
|
pytube/extract.py
CHANGED
@@ -6,25 +6,15 @@ import urllib.parse
|
|
6 |
import re
|
7 |
from collections import OrderedDict
|
8 |
from datetime import datetime
|
9 |
-
from typing import Any
|
10 |
-
from
|
11 |
-
from typing import List
|
12 |
-
from typing import Optional
|
13 |
-
from typing import Tuple
|
14 |
-
from urllib.parse import parse_qs
|
15 |
-
from urllib.parse import parse_qsl
|
16 |
-
from urllib.parse import quote
|
17 |
-
from urllib.parse import unquote
|
18 |
-
from urllib.parse import urlencode
|
19 |
|
20 |
from pytube.cipher import Cipher
|
21 |
-
from pytube.exceptions import HTMLParseError
|
22 |
-
from pytube.exceptions import LiveStreamError
|
23 |
-
from pytube.exceptions import RegexMatchError
|
24 |
from pytube.helpers import regex_search
|
25 |
from pytube.metadata import YouTubeMetadata
|
26 |
-
from pytube.parser import parse_for_object
|
27 |
-
|
28 |
|
29 |
logger = logging.getLogger(__name__)
|
30 |
|
|
|
6 |
import re
|
7 |
from collections import OrderedDict
|
8 |
from datetime import datetime
|
9 |
+
from typing import Any, Dict, List, Optional, Tuple
|
10 |
+
from urllib.parse import parse_qs, parse_qsl, quote, unquote, urlencode
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
11 |
|
12 |
from pytube.cipher import Cipher
|
13 |
+
from pytube.exceptions import HTMLParseError, LiveStreamError, RegexMatchError
|
|
|
|
|
14 |
from pytube.helpers import regex_search
|
15 |
from pytube.metadata import YouTubeMetadata
|
16 |
+
from pytube.parser import parse_for_object, parse_for_all_objects
|
17 |
+
|
18 |
|
19 |
logger = logging.getLogger(__name__)
|
20 |
|
pytube/helpers.py
CHANGED
@@ -7,12 +7,7 @@ import logging
|
|
7 |
import os
|
8 |
import re
|
9 |
import warnings
|
10 |
-
from typing import Any
|
11 |
-
from typing import Callable
|
12 |
-
from typing import Dict
|
13 |
-
from typing import List
|
14 |
-
from typing import Optional
|
15 |
-
from typing import TypeVar
|
16 |
from urllib import request
|
17 |
|
18 |
from pytube.exceptions import RegexMatchError
|
|
|
7 |
import os
|
8 |
import re
|
9 |
import warnings
|
10 |
+
from typing import Any, Callable, Dict, List, Optional, TypeVar
|
|
|
|
|
|
|
|
|
|
|
11 |
from urllib import request
|
12 |
|
13 |
from pytube.exceptions import RegexMatchError
|
pytube/metadata.py
CHANGED
@@ -1,9 +1,7 @@
|
|
1 |
# -*- coding: utf-8 -*-
|
2 |
"""This module contains the YouTubeMetadata class."""
|
3 |
import json
|
4 |
-
from typing import Dict
|
5 |
-
from typing import List
|
6 |
-
from typing import Optional
|
7 |
|
8 |
|
9 |
class YouTubeMetadata:
|
|
|
1 |
# -*- coding: utf-8 -*-
|
2 |
"""This module contains the YouTubeMetadata class."""
|
3 |
import json
|
4 |
+
from typing import Dict, List, Optional
|
|
|
|
|
5 |
|
6 |
|
7 |
class YouTubeMetadata:
|
pytube/monostate.py
CHANGED
@@ -1,7 +1,5 @@
|
|
1 |
# -*- coding: utf-8 -*-
|
2 |
-
from typing import Any
|
3 |
-
from typing import Callable
|
4 |
-
from typing import Optional
|
5 |
|
6 |
|
7 |
class Monostate:
|
|
|
1 |
# -*- coding: utf-8 -*-
|
2 |
+
from typing import Any, Callable, Optional
|
|
|
|
|
3 |
|
4 |
|
5 |
class Monostate:
|
pytube/query.py
CHANGED
@@ -1,14 +1,9 @@
|
|
1 |
# -*- coding: utf-8 -*-
|
2 |
"""This module provides a query interface for media streams and captions."""
|
3 |
-
from collections.abc import Mapping
|
4 |
-
from
|
5 |
-
|
6 |
-
from
|
7 |
-
from typing import Optional
|
8 |
-
from typing import Union
|
9 |
-
|
10 |
-
from pytube import Caption
|
11 |
-
from pytube import Stream
|
12 |
from pytube.helpers import deprecated
|
13 |
|
14 |
|
|
|
1 |
# -*- coding: utf-8 -*-
|
2 |
"""This module provides a query interface for media streams and captions."""
|
3 |
+
from collections.abc import Mapping, Sequence
|
4 |
+
from typing import Callable, List, Optional, Union
|
5 |
+
|
6 |
+
from pytube import Caption, Stream
|
|
|
|
|
|
|
|
|
|
|
7 |
from pytube.helpers import deprecated
|
8 |
|
9 |
|
pytube/request.py
CHANGED
@@ -2,13 +2,12 @@
|
|
2 |
"""Implements a simple wrapper around urlopen."""
|
3 |
import json
|
4 |
import logging
|
5 |
-
from functools import lru_cache
|
6 |
import re
|
7 |
import socket
|
|
|
8 |
from urllib import parse
|
9 |
from urllib.error import URLError
|
10 |
-
from urllib.request import Request
|
11 |
-
from urllib.request import urlopen
|
12 |
|
13 |
from pytube.exceptions import RegexMatchError, MaxRetriesExceeded
|
14 |
from pytube.helpers import regex_search
|
|
|
2 |
"""Implements a simple wrapper around urlopen."""
|
3 |
import json
|
4 |
import logging
|
|
|
5 |
import re
|
6 |
import socket
|
7 |
+
from functools import lru_cache
|
8 |
from urllib import parse
|
9 |
from urllib.error import URLError
|
10 |
+
from urllib.request import Request, urlopen
|
|
|
11 |
|
12 |
from pytube.exceptions import RegexMatchError, MaxRetriesExceeded
|
13 |
from pytube.helpers import regex_search
|
pytube/streams.py
CHANGED
@@ -10,17 +10,12 @@ separately).
|
|
10 |
import logging
|
11 |
import os
|
12 |
from datetime import datetime
|
13 |
-
from typing import BinaryIO
|
14 |
-
from typing import Dict
|
15 |
-
from typing import Optional
|
16 |
-
from typing import Tuple
|
17 |
from urllib.error import HTTPError
|
18 |
from urllib.parse import parse_qs
|
19 |
|
20 |
-
from pytube import extract
|
21 |
-
from pytube import
|
22 |
-
from pytube.helpers import safe_filename
|
23 |
-
from pytube.helpers import target_directory
|
24 |
from pytube.itags import get_format_profile
|
25 |
from pytube.monostate import Monostate
|
26 |
|
|
|
10 |
import logging
|
11 |
import os
|
12 |
from datetime import datetime
|
13 |
+
from typing import BinaryIO, Dict, Optional, Tuple
|
|
|
|
|
|
|
14 |
from urllib.error import HTTPError
|
15 |
from urllib.parse import parse_qs
|
16 |
|
17 |
+
from pytube import extract, request
|
18 |
+
from pytube.helpers import safe_filename, target_directory
|
|
|
|
|
19 |
from pytube.itags import get_format_profile
|
20 |
from pytube.monostate import Monostate
|
21 |
|
tests/conftest.py
CHANGED
@@ -3,9 +3,8 @@
|
|
3 |
import gzip
|
4 |
import json
|
5 |
import os
|
6 |
-
from unittest import mock
|
7 |
-
|
8 |
import pytest
|
|
|
9 |
|
10 |
from pytube import YouTube
|
11 |
|
|
|
3 |
import gzip
|
4 |
import json
|
5 |
import os
|
|
|
|
|
6 |
import pytest
|
7 |
+
from unittest import mock
|
8 |
|
9 |
from pytube import YouTube
|
10 |
|
tests/test_captions.py
CHANGED
@@ -1,15 +1,10 @@
|
|
1 |
# -*- coding: utf-8 -*-
|
2 |
import os
|
3 |
-
from unittest import mock
|
4 |
-
from unittest.mock import MagicMock
|
5 |
-
from unittest.mock import mock_open
|
6 |
-
from unittest.mock import patch
|
7 |
-
|
8 |
import pytest
|
|
|
|
|
9 |
|
10 |
-
from pytube import Caption
|
11 |
-
from pytube import CaptionQuery
|
12 |
-
from pytube import captions
|
13 |
|
14 |
|
15 |
def test_float_to_srt_time_format():
|
|
|
1 |
# -*- coding: utf-8 -*-
|
2 |
import os
|
|
|
|
|
|
|
|
|
|
|
3 |
import pytest
|
4 |
+
from unittest import mock
|
5 |
+
from unittest.mock import MagicMock, mock_open, patch
|
6 |
|
7 |
+
from pytube import Caption, CaptionQuery, captions
|
|
|
|
|
8 |
|
9 |
|
10 |
def test_float_to_srt_time_format():
|
tests/test_cli.py
CHANGED
@@ -2,15 +2,11 @@
|
|
2 |
import argparse
|
3 |
import os
|
4 |
from unittest import mock
|
5 |
-
from unittest.mock import MagicMock
|
6 |
-
from unittest.mock import patch
|
7 |
|
8 |
import pytest
|
9 |
|
10 |
-
from pytube import Caption
|
11 |
-
from pytube import CaptionQuery
|
12 |
-
from pytube import cli
|
13 |
-
from pytube import StreamQuery
|
14 |
from pytube.exceptions import PytubeError
|
15 |
|
16 |
parse_args = cli._parse_args
|
|
|
2 |
import argparse
|
3 |
import os
|
4 |
from unittest import mock
|
5 |
+
from unittest.mock import MagicMock, patch
|
|
|
6 |
|
7 |
import pytest
|
8 |
|
9 |
+
from pytube import Caption, CaptionQuery, cli, StreamQuery
|
|
|
|
|
|
|
10 |
from pytube.exceptions import PytubeError
|
11 |
|
12 |
parse_args = cli._parse_args
|
tests/test_exceptions.py
CHANGED
@@ -2,70 +2,65 @@
|
|
2 |
import pytest
|
3 |
from unittest import mock
|
4 |
|
|
|
5 |
from pytube import YouTube
|
6 |
-
from pytube.exceptions import LiveStreamError
|
7 |
-
from pytube.exceptions import RecordingUnavailable
|
8 |
-
from pytube.exceptions import RegexMatchError
|
9 |
-
from pytube.exceptions import VideoUnavailable
|
10 |
-
from pytube.exceptions import VideoPrivate
|
11 |
-
from pytube.exceptions import VideoRegionBlocked
|
12 |
|
13 |
|
14 |
def test_video_unavailable():
|
15 |
try:
|
16 |
-
raise VideoUnavailable(video_id="YLnZklYFe7E")
|
17 |
-
except VideoUnavailable as e:
|
18 |
assert e.video_id == "YLnZklYFe7E" # noqa: PT017
|
19 |
assert str(e) == "YLnZklYFe7E is unavailable"
|
20 |
|
21 |
|
22 |
def test_regex_match_error():
|
23 |
try:
|
24 |
-
raise RegexMatchError(caller="hello", pattern="*")
|
25 |
-
except RegexMatchError as e:
|
26 |
assert str(e) == "hello: could not find match for *"
|
27 |
|
28 |
|
29 |
def test_live_stream_error():
|
30 |
# Ensure this can be caught as generic VideoUnavailable exception
|
31 |
-
with pytest.raises(VideoUnavailable):
|
32 |
-
raise LiveStreamError(video_id='YLnZklYFe7E')
|
33 |
try:
|
34 |
-
raise LiveStreamError(video_id='YLnZklYFe7E')
|
35 |
-
except LiveStreamError as e:
|
36 |
assert e.video_id == 'YLnZklYFe7E' # noqa: PT017
|
37 |
assert str(e) == 'YLnZklYFe7E is streaming live and cannot be loaded'
|
38 |
|
39 |
|
40 |
def test_recording_unavailable_error():
|
41 |
# Ensure this can be caught as generic VideoUnavailable exception
|
42 |
-
with pytest.raises(VideoUnavailable):
|
43 |
-
raise RecordingUnavailable(video_id='5YceQ8YqYMc')
|
44 |
try:
|
45 |
-
raise RecordingUnavailable(video_id='5YceQ8YqYMc')
|
46 |
-
except RecordingUnavailable as e:
|
47 |
assert e.video_id == '5YceQ8YqYMc' # noqa: PT017
|
48 |
assert str(e) == '5YceQ8YqYMc does not have a live stream recording available'
|
49 |
|
50 |
|
51 |
def test_private_error():
|
52 |
# Ensure this can be caught as generic VideoUnavailable exception
|
53 |
-
with pytest.raises(VideoUnavailable):
|
54 |
-
raise VideoPrivate('m8uHb5jIGN8')
|
55 |
try:
|
56 |
-
raise VideoPrivate('m8uHb5jIGN8')
|
57 |
-
except VideoPrivate as e:
|
58 |
assert e.video_id == 'm8uHb5jIGN8' # noqa: PT017
|
59 |
assert str(e) == 'm8uHb5jIGN8 is a private video'
|
60 |
|
61 |
|
62 |
def test_region_locked_error():
|
63 |
# Ensure this can be caught as generic VideoUnavailable exception
|
64 |
-
with pytest.raises(VideoUnavailable):
|
65 |
-
raise VideoRegionBlocked('hZpzr8TbF08')
|
66 |
try:
|
67 |
-
raise VideoRegionBlocked('hZpzr8TbF08')
|
68 |
-
except VideoRegionBlocked as e:
|
69 |
assert e.video_id == 'hZpzr8TbF08' # noqa: PT017
|
70 |
assert str(e) == 'hZpzr8TbF08 is not available in your region'
|
71 |
|
@@ -78,7 +73,7 @@ def test_raises_video_private(private):
|
|
78 |
private['watch_html'].encode('utf-8'),
|
79 |
]
|
80 |
mock_url_open.return_value = mock_url_open_object
|
81 |
-
with pytest.raises(VideoPrivate):
|
82 |
YouTube('https://youtube.com/watch?v=m8uHb5jIGN8').streams
|
83 |
|
84 |
|
@@ -90,7 +85,7 @@ def test_raises_recording_unavailable(missing_recording):
|
|
90 |
missing_recording['watch_html'].encode('utf-8'),
|
91 |
]
|
92 |
mock_url_open.return_value = mock_url_open_object
|
93 |
-
with pytest.raises(RecordingUnavailable):
|
94 |
YouTube('https://youtube.com/watch?v=5YceQ8YqYMc').streams
|
95 |
|
96 |
|
@@ -102,5 +97,5 @@ def test_raises_video_region_blocked(region_blocked):
|
|
102 |
region_blocked['watch_html'].encode('utf-8')
|
103 |
]
|
104 |
mock_url_open.return_value = mock_url_open_object
|
105 |
-
with pytest.raises(VideoRegionBlocked):
|
106 |
YouTube('https://youtube.com/watch?v=hZpzr8TbF08').streams
|
|
|
2 |
import pytest
|
3 |
from unittest import mock
|
4 |
|
5 |
+
import pytube.exceptions as exceptions
|
6 |
from pytube import YouTube
|
|
|
|
|
|
|
|
|
|
|
|
|
7 |
|
8 |
|
9 |
def test_video_unavailable():
|
10 |
try:
|
11 |
+
raise exceptions.VideoUnavailable(video_id="YLnZklYFe7E")
|
12 |
+
except exceptions.VideoUnavailable as e:
|
13 |
assert e.video_id == "YLnZklYFe7E" # noqa: PT017
|
14 |
assert str(e) == "YLnZklYFe7E is unavailable"
|
15 |
|
16 |
|
17 |
def test_regex_match_error():
|
18 |
try:
|
19 |
+
raise exceptions.RegexMatchError(caller="hello", pattern="*")
|
20 |
+
except exceptions.RegexMatchError as e:
|
21 |
assert str(e) == "hello: could not find match for *"
|
22 |
|
23 |
|
24 |
def test_live_stream_error():
|
25 |
# Ensure this can be caught as generic VideoUnavailable exception
|
26 |
+
with pytest.raises(exceptions.VideoUnavailable):
|
27 |
+
raise exceptions.LiveStreamError(video_id='YLnZklYFe7E')
|
28 |
try:
|
29 |
+
raise exceptions.LiveStreamError(video_id='YLnZklYFe7E')
|
30 |
+
except exceptions.LiveStreamError as e:
|
31 |
assert e.video_id == 'YLnZklYFe7E' # noqa: PT017
|
32 |
assert str(e) == 'YLnZklYFe7E is streaming live and cannot be loaded'
|
33 |
|
34 |
|
35 |
def test_recording_unavailable_error():
|
36 |
# Ensure this can be caught as generic VideoUnavailable exception
|
37 |
+
with pytest.raises(exceptions.VideoUnavailable):
|
38 |
+
raise exceptions.RecordingUnavailable(video_id='5YceQ8YqYMc')
|
39 |
try:
|
40 |
+
raise exceptions.RecordingUnavailable(video_id='5YceQ8YqYMc')
|
41 |
+
except exceptions.RecordingUnavailable as e:
|
42 |
assert e.video_id == '5YceQ8YqYMc' # noqa: PT017
|
43 |
assert str(e) == '5YceQ8YqYMc does not have a live stream recording available'
|
44 |
|
45 |
|
46 |
def test_private_error():
|
47 |
# Ensure this can be caught as generic VideoUnavailable exception
|
48 |
+
with pytest.raises(exceptions.VideoUnavailable):
|
49 |
+
raise exceptions.VideoPrivate('m8uHb5jIGN8')
|
50 |
try:
|
51 |
+
raise exceptions.VideoPrivate('m8uHb5jIGN8')
|
52 |
+
except exceptions.VideoPrivate as e:
|
53 |
assert e.video_id == 'm8uHb5jIGN8' # noqa: PT017
|
54 |
assert str(e) == 'm8uHb5jIGN8 is a private video'
|
55 |
|
56 |
|
57 |
def test_region_locked_error():
|
58 |
# Ensure this can be caught as generic VideoUnavailable exception
|
59 |
+
with pytest.raises(exceptions.VideoUnavailable):
|
60 |
+
raise exceptions.VideoRegionBlocked('hZpzr8TbF08')
|
61 |
try:
|
62 |
+
raise exceptions.VideoRegionBlocked('hZpzr8TbF08')
|
63 |
+
except exceptions.VideoRegionBlocked as e:
|
64 |
assert e.video_id == 'hZpzr8TbF08' # noqa: PT017
|
65 |
assert str(e) == 'hZpzr8TbF08 is not available in your region'
|
66 |
|
|
|
73 |
private['watch_html'].encode('utf-8'),
|
74 |
]
|
75 |
mock_url_open.return_value = mock_url_open_object
|
76 |
+
with pytest.raises(exceptions.VideoPrivate):
|
77 |
YouTube('https://youtube.com/watch?v=m8uHb5jIGN8').streams
|
78 |
|
79 |
|
|
|
85 |
missing_recording['watch_html'].encode('utf-8'),
|
86 |
]
|
87 |
mock_url_open.return_value = mock_url_open_object
|
88 |
+
with pytest.raises(exceptions.RecordingUnavailable):
|
89 |
YouTube('https://youtube.com/watch?v=5YceQ8YqYMc').streams
|
90 |
|
91 |
|
|
|
97 |
region_blocked['watch_html'].encode('utf-8')
|
98 |
]
|
99 |
mock_url_open.return_value = mock_url_open_object
|
100 |
+
with pytest.raises(exceptions.VideoRegionBlocked):
|
101 |
YouTube('https://youtube.com/watch?v=hZpzr8TbF08').streams
|
tests/test_helpers.py
CHANGED
@@ -3,18 +3,13 @@ import gzip
|
|
3 |
import io
|
4 |
import json
|
5 |
import os
|
6 |
-
from unittest import mock
|
7 |
-
|
8 |
import pytest
|
|
|
9 |
|
10 |
from pytube import helpers
|
11 |
from pytube.exceptions import RegexMatchError
|
12 |
-
from pytube.helpers import cache
|
13 |
-
from pytube.helpers import
|
14 |
-
from pytube.helpers import deprecated
|
15 |
-
from pytube.helpers import setup_logger
|
16 |
-
from pytube.helpers import target_directory
|
17 |
-
from pytube.helpers import uniqueify
|
18 |
|
19 |
|
20 |
def test_regex_search_no_match():
|
|
|
3 |
import io
|
4 |
import json
|
5 |
import os
|
|
|
|
|
6 |
import pytest
|
7 |
+
from unittest import mock
|
8 |
|
9 |
from pytube import helpers
|
10 |
from pytube.exceptions import RegexMatchError
|
11 |
+
from pytube.helpers import cache, create_mock_html_json, deprecated, setup_logger
|
12 |
+
from pytube.helpers import target_directory, uniqueify
|
|
|
|
|
|
|
|
|
13 |
|
14 |
|
15 |
def test_regex_search_no_match():
|
tests/test_request.py
CHANGED
@@ -1,11 +1,10 @@
|
|
1 |
# -*- coding: utf-8 -*-
|
2 |
import socket
|
3 |
import os
|
|
|
4 |
from unittest import mock
|
5 |
from urllib.error import URLError
|
6 |
|
7 |
-
import pytest
|
8 |
-
|
9 |
from pytube import request
|
10 |
from pytube.exceptions import MaxRetriesExceeded
|
11 |
|
|
|
1 |
# -*- coding: utf-8 -*-
|
2 |
import socket
|
3 |
import os
|
4 |
+
import pytest
|
5 |
from unittest import mock
|
6 |
from urllib.error import URLError
|
7 |
|
|
|
|
|
8 |
from pytube import request
|
9 |
from pytube.exceptions import MaxRetriesExceeded
|
10 |
|
tests/test_streams.py
CHANGED
@@ -1,14 +1,13 @@
|
|
1 |
# -*- coding: utf-8 -*-
|
2 |
import os
|
3 |
import random
|
4 |
-
from datetime import datetime
|
5 |
import pytest
|
|
|
6 |
from unittest import mock
|
7 |
from unittest.mock import MagicMock, Mock
|
8 |
from urllib.error import HTTPError
|
9 |
|
10 |
-
from pytube import request
|
11 |
-
from pytube import Stream
|
12 |
|
13 |
|
14 |
@mock.patch("pytube.streams.request")
|
|
|
1 |
# -*- coding: utf-8 -*-
|
2 |
import os
|
3 |
import random
|
|
|
4 |
import pytest
|
5 |
+
from datetime import datetime
|
6 |
from unittest import mock
|
7 |
from unittest.mock import MagicMock, Mock
|
8 |
from urllib.error import HTTPError
|
9 |
|
10 |
+
from pytube import request, Stream
|
|
|
11 |
|
12 |
|
13 |
@mock.patch("pytube.streams.request")
|