more coverage
Browse files- pytube/__main__.py +2 -2
- pytube/streams.py +2 -1
- setup.cfg +3 -1
- tests/test_extract.py +6 -0
- tests/test_streams.py +73 -0
pytube/__main__.py
CHANGED
@@ -169,7 +169,7 @@ class YouTube(object):
|
|
169 |
A callback function that takes ``stream``, ``chunk``,
|
170 |
``file_handle``, ``bytes_remaining`` as parameters.
|
171 |
"""
|
172 |
-
self.
|
173 |
|
174 |
def register_on_complete_callback(self, func):
|
175 |
"""Register a download complete callback function post initialization.
|
@@ -177,4 +177,4 @@ class YouTube(object):
|
|
177 |
:param callable func:
|
178 |
A callback function that takes ``stream`` and ``file_handle``.
|
179 |
"""
|
180 |
-
self.
|
|
|
169 |
A callback function that takes ``stream``, ``chunk``,
|
170 |
``file_handle``, ``bytes_remaining`` as parameters.
|
171 |
"""
|
172 |
+
self.stream_monostate['on_progress'] = func
|
173 |
|
174 |
def register_on_complete_callback(self, func):
|
175 |
"""Register a download complete callback function post initialization.
|
|
|
177 |
:param callable func:
|
178 |
A callback function that takes ``stream`` and ``file_handle``.
|
179 |
"""
|
180 |
+
self.stream_monostate['on_complete'] = func
|
pytube/streams.py
CHANGED
@@ -170,6 +170,7 @@ class Stream(object):
|
|
170 |
bytes_remaining -= len(chunk)
|
171 |
# send to the on_progress callback.
|
172 |
self.on_progress(chunk, fh, bytes_remaining)
|
|
|
173 |
|
174 |
def on_progress(self, chunk, file_handler, bytes_remaining):
|
175 |
"""On progress callback function.
|
@@ -202,7 +203,7 @@ class Stream(object):
|
|
202 |
on_progress = self._monostate['on_progress']
|
203 |
if on_progress:
|
204 |
logger.debug('calling on_progress callback %s', on_progress)
|
205 |
-
on_progress(self, chunk, bytes_remaining)
|
206 |
|
207 |
def on_complete(self, file_handle):
|
208 |
"""On download complete handler function.
|
|
|
170 |
bytes_remaining -= len(chunk)
|
171 |
# send to the on_progress callback.
|
172 |
self.on_progress(chunk, fh, bytes_remaining)
|
173 |
+
self.on_complete(fh)
|
174 |
|
175 |
def on_progress(self, chunk, file_handler, bytes_remaining):
|
176 |
"""On progress callback function.
|
|
|
203 |
on_progress = self._monostate['on_progress']
|
204 |
if on_progress:
|
205 |
logger.debug('calling on_progress callback %s', on_progress)
|
206 |
+
on_progress(self, chunk, file_handler, bytes_remaining)
|
207 |
|
208 |
def on_complete(self, file_handle):
|
209 |
"""On download complete handler function.
|
setup.cfg
CHANGED
@@ -4,7 +4,7 @@ tag = True
|
|
4 |
current_version = 7.0.1
|
5 |
parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)(\-(?P<release>[a-z]+))?
|
6 |
serialize =
|
7 |
-
|
8 |
|
9 |
[metadata]
|
10 |
description-file = README.md
|
@@ -15,3 +15,5 @@ description-file = README.md
|
|
15 |
|
16 |
[coverage:run]
|
17 |
source = pytube
|
|
|
|
|
|
4 |
current_version = 7.0.1
|
5 |
parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)(\-(?P<release>[a-z]+))?
|
6 |
serialize =
|
7 |
+
{major}.{minor}.{patch}
|
8 |
|
9 |
[metadata]
|
10 |
description-file = README.md
|
|
|
15 |
|
16 |
[coverage:run]
|
17 |
source = pytube
|
18 |
+
omit =
|
19 |
+
pytube/compat.py
|
tests/test_extract.py
CHANGED
@@ -27,3 +27,9 @@ def test_info_url(gangnam_style):
|
|
27 |
'253D9bZkp7q19f0&hl=en_US&t=%252C%2522t%2522%253A%25221%2522'
|
28 |
)
|
29 |
assert video_info_url == expected
|
|
|
|
|
|
|
|
|
|
|
|
|
|
27 |
'253D9bZkp7q19f0&hl=en_US&t=%252C%2522t%2522%253A%25221%2522'
|
28 |
)
|
29 |
assert video_info_url == expected
|
30 |
+
|
31 |
+
|
32 |
+
def test_js_url(gangnam_style):
|
33 |
+
expected = 'https://youtube.com/yts/jsbin/player-vflOdyxa4/en_US/base.js'
|
34 |
+
result = extract.js_url(gangnam_style.watch_html)
|
35 |
+
assert expected == result
|
tests/test_streams.py
CHANGED
@@ -4,6 +4,7 @@ import random
|
|
4 |
import mock
|
5 |
|
6 |
from pytube import request
|
|
|
7 |
|
8 |
|
9 |
def test_filesize(gangnam_style, mocker):
|
@@ -38,3 +39,75 @@ def test_progressive_streams_return_includes_audio_track(gangnam_style):
|
|
38 |
def test_progressive_streams_return_includes_video_track(gangnam_style):
|
39 |
stream = gangnam_style.streams.filter(progressive=True).first()
|
40 |
assert stream.includes_video_track
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4 |
import mock
|
5 |
|
6 |
from pytube import request
|
7 |
+
from pytube import Stream
|
8 |
|
9 |
|
10 |
def test_filesize(gangnam_style, mocker):
|
|
|
39 |
def test_progressive_streams_return_includes_video_track(gangnam_style):
|
40 |
stream = gangnam_style.streams.filter(progressive=True).first()
|
41 |
assert stream.includes_video_track
|
42 |
+
|
43 |
+
|
44 |
+
def test_on_progress_hook(gangnam_style, mocker):
|
45 |
+
callback_fn = mock.MagicMock()
|
46 |
+
gangnam_style.register_on_progress_callback(callback_fn)
|
47 |
+
|
48 |
+
mocker.patch.object(request, 'get')
|
49 |
+
request.get.side_effect = [
|
50 |
+
{'Content-Length': '16384'},
|
51 |
+
{'Content-Length': '16384'},
|
52 |
+
iter([str(random.getrandbits(8 * 1024))]),
|
53 |
+
]
|
54 |
+
with mock.patch('pytube.streams.open', mock.mock_open(), create=True):
|
55 |
+
stream = gangnam_style.streams.first()
|
56 |
+
stream.download()
|
57 |
+
assert callback_fn.called
|
58 |
+
args, _ = callback_fn.call_args
|
59 |
+
assert len(args) == 4
|
60 |
+
stream, _, _, _ = args
|
61 |
+
assert isinstance(stream, Stream)
|
62 |
+
|
63 |
+
|
64 |
+
def test_on_complete_hook(gangnam_style, mocker):
|
65 |
+
callback_fn = mock.MagicMock()
|
66 |
+
gangnam_style.register_on_complete_callback(callback_fn)
|
67 |
+
|
68 |
+
mocker.patch.object(request, 'get')
|
69 |
+
request.get.side_effect = [
|
70 |
+
{'Content-Length': '16384'},
|
71 |
+
{'Content-Length': '16384'},
|
72 |
+
iter([str(random.getrandbits(8 * 1024))]),
|
73 |
+
]
|
74 |
+
with mock.patch('pytube.streams.open', mock.mock_open(), create=True):
|
75 |
+
stream = gangnam_style.streams.first()
|
76 |
+
stream.download()
|
77 |
+
assert callback_fn.called
|
78 |
+
|
79 |
+
|
80 |
+
def test_repr_for_audio_streams(gangnam_style):
|
81 |
+
stream = str(gangnam_style.streams.filter(only_audio=True).first())
|
82 |
+
expected = (
|
83 |
+
'<Stream: itag="140" mime_type="audio/mp4" abr="128kbps" '
|
84 |
+
'acodec="mp4a.40.2">'
|
85 |
+
)
|
86 |
+
assert stream == expected
|
87 |
+
|
88 |
+
|
89 |
+
def test_repr_for_video_streams(gangnam_style):
|
90 |
+
stream = str(gangnam_style.streams.filter(only_video=True).first())
|
91 |
+
expected = (
|
92 |
+
'<Stream: itag="137" mime_type="video/mp4" res="1080p" '
|
93 |
+
'fps="30fps" vcodec="avc1.640028">'
|
94 |
+
)
|
95 |
+
assert stream == expected
|
96 |
+
|
97 |
+
|
98 |
+
def test_repr_for_progressive_streams(gangnam_style):
|
99 |
+
stream = str(gangnam_style.streams.filter(progressive=True).first())
|
100 |
+
expected = (
|
101 |
+
'<Stream: itag="22" mime_type="video/mp4" res="720p" '
|
102 |
+
'fps="30fps" vcodec="avc1.64001F" acodec="mp4a.40.2">'
|
103 |
+
)
|
104 |
+
assert stream == expected
|
105 |
+
|
106 |
+
|
107 |
+
def test_repr_for_adaptive_streams(gangnam_style):
|
108 |
+
stream = str(gangnam_style.streams.filter(adaptive=True).first())
|
109 |
+
expected = (
|
110 |
+
'<Stream: itag="137" mime_type="video/mp4" res="1080p" '
|
111 |
+
'fps="30fps" vcodec="avc1.640028">'
|
112 |
+
)
|
113 |
+
assert stream == expected
|