move coverage
Browse files- README.rst +1 -1
- pytube/request.py +1 -3
- tests/conftest.py +24 -15
- tests/mocks/yt-video-zRbsm3e2ltw-1507777044.json.tar.gz +0 -0
- tests/test_cipher.py +0 -0
- tests/test_cli.py +0 -0
- tests/test_extract.py +14 -6
- tests/test_main.py +0 -0
- tests/test_mixins.py +2 -2
- tests/test_query.py +22 -20
- tests/test_request.py +42 -0
- tests/test_streams.py +24 -24
README.rst
CHANGED
@@ -14,7 +14,7 @@ pytube
|
|
14 |
:alt: Documentation Status
|
15 |
:target: http://python-pytube.readthedocs.io/en/latest/?badge=latest
|
16 |
|
17 |
-
.. image:: https://coveralls.io/repos/github/nficano/pytube/badge.svg?branch=master#
|
18 |
:alt: Code Coverage
|
19 |
:target: https://coveralls.io/github/nficano/pytube?branch=master
|
20 |
|
|
|
14 |
:alt: Documentation Status
|
15 |
:target: http://python-pytube.readthedocs.io/en/latest/?badge=latest
|
16 |
|
17 |
+
.. image:: https://coveralls.io/repos/github/nficano/pytube/badge.svg?branch=master#23e6f7ac5623e
|
18 |
:alt: Code Coverage
|
19 |
:target: https://coveralls.io/github/nficano/pytube?branch=master
|
20 |
|
pytube/request.py
CHANGED
@@ -4,7 +4,7 @@ from pytube.compat import urlopen
|
|
4 |
|
5 |
|
6 |
def get(
|
7 |
-
url=None,
|
8 |
streaming=False, chunk_size=8 * 1024,
|
9 |
):
|
10 |
"""Send an http GET request.
|
@@ -13,8 +13,6 @@ def get(
|
|
13 |
The URL to perform the GET request for.
|
14 |
:param list urls:
|
15 |
List of URLs to perform the GET request for concurrently.
|
16 |
-
:param int processes:
|
17 |
-
How many worker processes to start.
|
18 |
:param bool headers:
|
19 |
Only return the http headers.
|
20 |
:param bool streaming:
|
|
|
4 |
|
5 |
|
6 |
def get(
|
7 |
+
url=None, headers=False,
|
8 |
streaming=False, chunk_size=8 * 1024,
|
9 |
):
|
10 |
"""Send an http GET request.
|
|
|
13 |
The URL to perform the GET request for.
|
14 |
:param list urls:
|
15 |
List of URLs to perform the GET request for concurrently.
|
|
|
|
|
16 |
:param bool headers:
|
17 |
Only return the http headers.
|
18 |
:param bool streaming:
|
tests/conftest.py
CHANGED
@@ -11,32 +11,41 @@ import pytest
|
|
11 |
from pytube import YouTube
|
12 |
|
13 |
|
14 |
-
def
|
15 |
-
|
|
|
16 |
fp = os.path.join(cur_dir, 'mocks', filename)
|
17 |
-
video = None
|
18 |
with gzip.open(fp, 'rb') as fh:
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
yt
|
26 |
-
yt.
|
|
|
|
|
27 |
yt.init()
|
28 |
return yt
|
29 |
|
30 |
|
31 |
@pytest.fixture
|
32 |
-
def
|
33 |
"""Youtube instance initialized with video id 9bZkp7q19f0."""
|
34 |
filename = 'yt-video-9bZkp7q19f0-1507588332.json.tar.gz'
|
35 |
-
return
|
36 |
|
37 |
|
38 |
@pytest.fixture
|
39 |
-
def
|
40 |
"""Youtube instance initialized with video id QRS8MkLhQmM."""
|
41 |
filename = 'yt-video-QRS8MkLhQmM-1507588031.json.tar.gz'
|
42 |
-
return
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
11 |
from pytube import YouTube
|
12 |
|
13 |
|
14 |
+
def load_playback_file(filename):
|
15 |
+
cur_fp = os.path.realpath(__file__)
|
16 |
+
cur_dir = os.path.dirname(cur_fp)
|
17 |
fp = os.path.join(cur_dir, 'mocks', filename)
|
|
|
18 |
with gzip.open(fp, 'rb') as fh:
|
19 |
+
content = fh.read().decode('utf-8')
|
20 |
+
return json.loads(content)
|
21 |
+
|
22 |
+
|
23 |
+
def load_and_init_from_playback_file(filename):
|
24 |
+
pb = load_playback_file(filename)
|
25 |
+
yt = YouTube(pb['url'], defer_prefetch_init=True)
|
26 |
+
yt.watch_html = pb['watch_html']
|
27 |
+
yt.js = pb['js']
|
28 |
+
yt.vid_info = pb['video_info']
|
29 |
yt.init()
|
30 |
return yt
|
31 |
|
32 |
|
33 |
@pytest.fixture
|
34 |
+
def cipher_signature():
|
35 |
"""Youtube instance initialized with video id 9bZkp7q19f0."""
|
36 |
filename = 'yt-video-9bZkp7q19f0-1507588332.json.tar.gz'
|
37 |
+
return load_and_init_from_playback_file(filename)
|
38 |
|
39 |
|
40 |
@pytest.fixture
|
41 |
+
def presigned_video():
|
42 |
"""Youtube instance initialized with video id QRS8MkLhQmM."""
|
43 |
filename = 'yt-video-QRS8MkLhQmM-1507588031.json.tar.gz'
|
44 |
+
return load_and_init_from_playback_file(filename)
|
45 |
+
|
46 |
+
|
47 |
+
@pytest.fixture
|
48 |
+
def age_restricted():
|
49 |
+
"""Youtube instance initialized with video id zRbsm3e2ltw."""
|
50 |
+
filename = 'yt-video-zRbsm3e2ltw-1507777044.json.tar.gz'
|
51 |
+
return load_playback_file(filename)
|
tests/mocks/yt-video-zRbsm3e2ltw-1507777044.json.tar.gz
ADDED
Binary file (20.6 kB). View file
|
|
tests/test_cipher.py
ADDED
File without changes
|
tests/test_cli.py
ADDED
File without changes
|
tests/test_extract.py
CHANGED
@@ -15,11 +15,11 @@ def test_extract_watch_url():
|
|
15 |
assert watch_url == 'https://youtube.com/watch?v=9bZkp7q19f0'
|
16 |
|
17 |
|
18 |
-
def test_info_url(
|
19 |
video_info_url = extract.video_info_url(
|
20 |
-
video_id=
|
21 |
-
watch_url=
|
22 |
-
watch_html=
|
23 |
)
|
24 |
expected = (
|
25 |
'https://youtube.com/get_video_info?video_id=9bZkp7q19f0&el=%24el'
|
@@ -29,7 +29,15 @@ def test_info_url(gangnam_style):
|
|
29 |
assert video_info_url == expected
|
30 |
|
31 |
|
32 |
-
def test_js_url(
|
33 |
expected = 'https://youtube.com/yts/jsbin/player-vflOdyxa4/en_US/base.js'
|
34 |
-
result = extract.js_url(
|
35 |
assert expected == result
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
15 |
assert watch_url == 'https://youtube.com/watch?v=9bZkp7q19f0'
|
16 |
|
17 |
|
18 |
+
def test_info_url(cipher_signature):
|
19 |
video_info_url = extract.video_info_url(
|
20 |
+
video_id=cipher_signature.video_id,
|
21 |
+
watch_url=cipher_signature.watch_url,
|
22 |
+
watch_html=cipher_signature.watch_html,
|
23 |
)
|
24 |
expected = (
|
25 |
'https://youtube.com/get_video_info?video_id=9bZkp7q19f0&el=%24el'
|
|
|
29 |
assert video_info_url == expected
|
30 |
|
31 |
|
32 |
+
def test_js_url(cipher_signature):
|
33 |
expected = 'https://youtube.com/yts/jsbin/player-vflOdyxa4/en_US/base.js'
|
34 |
+
result = extract.js_url(cipher_signature.watch_html)
|
35 |
assert expected == result
|
36 |
+
|
37 |
+
|
38 |
+
def test_age_restricted(age_restricted):
|
39 |
+
assert extract.is_age_restricted(age_restricted['watch_html'])
|
40 |
+
|
41 |
+
|
42 |
+
def test_non_age_restricted(cipher_signature):
|
43 |
+
assert not extract.is_age_restricted(cipher_signature.watch_html)
|
tests/test_main.py
ADDED
File without changes
|
tests/test_mixins.py
CHANGED
@@ -1,3 +1,3 @@
|
|
1 |
# -*- coding: utf-8 -*-
|
2 |
-
def test_pre_signed_video(
|
3 |
-
assert
|
|
|
1 |
# -*- coding: utf-8 -*-
|
2 |
+
def test_pre_signed_video(presigned_video):
|
3 |
+
assert presigned_video.streams.count() == 15
|
tests/test_query.py
CHANGED
@@ -3,8 +3,8 @@
|
|
3 |
import pytest
|
4 |
|
5 |
|
6 |
-
def test_count(
|
7 |
-
assert
|
8 |
|
9 |
|
10 |
@pytest.mark.parametrize(
|
@@ -27,29 +27,31 @@ def test_count(gangnam_style):
|
|
27 |
({'custom_filter_functions': [lambda s: s.itag == '22']}, ['22']),
|
28 |
],
|
29 |
)
|
30 |
-
def test_filters(test_input, expected,
|
31 |
-
result = [s.itag for s in
|
|
|
|
|
32 |
assert result == expected
|
33 |
|
34 |
|
35 |
@pytest.mark.parametrize('test_input', ['first', 'last'])
|
36 |
-
def test_empty(test_input,
|
37 |
-
query =
|
38 |
fn = getattr(query, test_input)
|
39 |
assert fn() is None
|
40 |
|
41 |
|
42 |
-
def test_get_last(
|
43 |
-
assert
|
44 |
|
45 |
|
46 |
-
def test_get_first(
|
47 |
-
assert
|
48 |
|
49 |
|
50 |
-
def test_order_by(
|
51 |
itags = [
|
52 |
-
s.itag for s in
|
53 |
.filter(progressive=True)
|
54 |
.order_by('itag')
|
55 |
.all()
|
@@ -58,9 +60,9 @@ def test_order_by(gangnam_style):
|
|
58 |
assert itags == ['17', '18', '22', '36', '43']
|
59 |
|
60 |
|
61 |
-
def test_order_by_descending(
|
62 |
itags = [
|
63 |
-
s.itag for s in
|
64 |
.filter(progressive=True)
|
65 |
.order_by('itag')
|
66 |
.desc()
|
@@ -70,9 +72,9 @@ def test_order_by_descending(gangnam_style):
|
|
70 |
assert itags == ['43', '36', '22', '18', '17']
|
71 |
|
72 |
|
73 |
-
def test_order_by_ascending(
|
74 |
itags = [
|
75 |
-
s.itag for s in
|
76 |
.filter(progressive=True)
|
77 |
.order_by('itag')
|
78 |
.asc()
|
@@ -82,9 +84,9 @@ def test_order_by_ascending(gangnam_style):
|
|
82 |
assert itags == ['17', '18', '22', '36', '43']
|
83 |
|
84 |
|
85 |
-
def test_get_by_itag(
|
86 |
-
assert
|
87 |
|
88 |
|
89 |
-
def test_get_by_non_existent_itag(
|
90 |
-
assert not
|
|
|
3 |
import pytest
|
4 |
|
5 |
|
6 |
+
def test_count(cipher_signature):
|
7 |
+
assert cipher_signature.streams.count() == 22
|
8 |
|
9 |
|
10 |
@pytest.mark.parametrize(
|
|
|
27 |
({'custom_filter_functions': [lambda s: s.itag == '22']}, ['22']),
|
28 |
],
|
29 |
)
|
30 |
+
def test_filters(test_input, expected, cipher_signature):
|
31 |
+
result = [s.itag for s in cipher_signature.streams.filter(
|
32 |
+
**test_input
|
33 |
+
).all()]
|
34 |
assert result == expected
|
35 |
|
36 |
|
37 |
@pytest.mark.parametrize('test_input', ['first', 'last'])
|
38 |
+
def test_empty(test_input, cipher_signature):
|
39 |
+
query = cipher_signature.streams.filter(video_codec='vp20')
|
40 |
fn = getattr(query, test_input)
|
41 |
assert fn() is None
|
42 |
|
43 |
|
44 |
+
def test_get_last(cipher_signature):
|
45 |
+
assert cipher_signature.streams.last().itag == '251'
|
46 |
|
47 |
|
48 |
+
def test_get_first(cipher_signature):
|
49 |
+
assert cipher_signature.streams.first().itag == '22'
|
50 |
|
51 |
|
52 |
+
def test_order_by(cipher_signature):
|
53 |
itags = [
|
54 |
+
s.itag for s in cipher_signature.streams
|
55 |
.filter(progressive=True)
|
56 |
.order_by('itag')
|
57 |
.all()
|
|
|
60 |
assert itags == ['17', '18', '22', '36', '43']
|
61 |
|
62 |
|
63 |
+
def test_order_by_descending(cipher_signature):
|
64 |
itags = [
|
65 |
+
s.itag for s in cipher_signature.streams
|
66 |
.filter(progressive=True)
|
67 |
.order_by('itag')
|
68 |
.desc()
|
|
|
72 |
assert itags == ['43', '36', '22', '18', '17']
|
73 |
|
74 |
|
75 |
+
def test_order_by_ascending(cipher_signature):
|
76 |
itags = [
|
77 |
+
s.itag for s in cipher_signature.streams
|
78 |
.filter(progressive=True)
|
79 |
.order_by('itag')
|
80 |
.asc()
|
|
|
84 |
assert itags == ['17', '18', '22', '36', '43']
|
85 |
|
86 |
|
87 |
+
def test_get_by_itag(cipher_signature):
|
88 |
+
assert cipher_signature.streams.get_by_itag(22).itag == '22'
|
89 |
|
90 |
|
91 |
+
def test_get_by_non_existent_itag(cipher_signature):
|
92 |
+
assert not cipher_signature.streams.get_by_itag(22983)
|
tests/test_request.py
ADDED
@@ -0,0 +1,42 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# -*- coding: utf-8 -*-
|
2 |
+
import os
|
3 |
+
|
4 |
+
import mock
|
5 |
+
|
6 |
+
from pytube import request
|
7 |
+
|
8 |
+
|
9 |
+
@mock.patch('pytube.request.urlopen')
|
10 |
+
def test_get_streaming(mock_urlopen):
|
11 |
+
fake_stream_binary = [
|
12 |
+
iter(os.urandom(8 * 1024)),
|
13 |
+
iter(os.urandom(8 * 1024)),
|
14 |
+
iter(os.urandom(8 * 1024)),
|
15 |
+
None,
|
16 |
+
]
|
17 |
+
response = mock.Mock()
|
18 |
+
response.read.side_effect = fake_stream_binary
|
19 |
+
mock_urlopen.return_value = response
|
20 |
+
response = request.get('fakeassurl.gov', streaming=True)
|
21 |
+
call_count = 0
|
22 |
+
for i in response:
|
23 |
+
call_count += 1
|
24 |
+
assert call_count == 3
|
25 |
+
|
26 |
+
|
27 |
+
@mock.patch('pytube.request.urlopen')
|
28 |
+
def test_get_headers(mock_urlopen):
|
29 |
+
response = mock.Mock()
|
30 |
+
response.info.return_value = {'Content-Length': '16384'}
|
31 |
+
mock_urlopen.return_value = response
|
32 |
+
response = request.get('fakeassurl.gov', headers=True)
|
33 |
+
assert response == {'Content-Length': '16384'}
|
34 |
+
|
35 |
+
|
36 |
+
@mock.patch('pytube.request.urlopen')
|
37 |
+
def test_get(mock_urlopen):
|
38 |
+
response = mock.Mock()
|
39 |
+
response.read.return_value = '<html></html>'.encode('utf-8')
|
40 |
+
mock_urlopen.return_value = response
|
41 |
+
response = request.get('fakeassurl.gov')
|
42 |
+
assert response == '<html></html>'
|
tests/test_streams.py
CHANGED
@@ -7,19 +7,19 @@ from pytube import request
|
|
7 |
from pytube import Stream
|
8 |
|
9 |
|
10 |
-
def test_filesize(
|
11 |
mocker.patch.object(request, 'get')
|
12 |
request.get.return_value = {'Content-Length': '6796391'}
|
13 |
-
assert
|
14 |
|
15 |
|
16 |
-
def test_default_filename(
|
17 |
expected = 'PSY - GANGNAM STYLE(강남스타일) MV.mp4'
|
18 |
-
stream =
|
19 |
assert stream.default_filename == expected
|
20 |
|
21 |
|
22 |
-
def test_download(
|
23 |
mocker.patch.object(request, 'get')
|
24 |
request.get.side_effect = [
|
25 |
{'Content-Length': '16384'},
|
@@ -27,23 +27,23 @@ def test_download(gangnam_style, mocker):
|
|
27 |
iter([str(random.getrandbits(8 * 1024))]),
|
28 |
]
|
29 |
with mock.patch('pytube.streams.open', mock.mock_open(), create=True):
|
30 |
-
stream =
|
31 |
stream.download()
|
32 |
|
33 |
|
34 |
-
def test_progressive_streams_return_includes_audio_track(
|
35 |
-
stream =
|
36 |
assert stream.includes_audio_track
|
37 |
|
38 |
|
39 |
-
def test_progressive_streams_return_includes_video_track(
|
40 |
-
stream =
|
41 |
assert stream.includes_video_track
|
42 |
|
43 |
|
44 |
-
def test_on_progress_hook(
|
45 |
callback_fn = mock.MagicMock()
|
46 |
-
|
47 |
|
48 |
mocker.patch.object(request, 'get')
|
49 |
request.get.side_effect = [
|
@@ -52,7 +52,7 @@ def test_on_progress_hook(gangnam_style, mocker):
|
|
52 |
iter([str(random.getrandbits(8 * 1024))]),
|
53 |
]
|
54 |
with mock.patch('pytube.streams.open', mock.mock_open(), create=True):
|
55 |
-
stream =
|
56 |
stream.download()
|
57 |
assert callback_fn.called
|
58 |
args, _ = callback_fn.call_args
|
@@ -61,9 +61,9 @@ def test_on_progress_hook(gangnam_style, mocker):
|
|
61 |
assert isinstance(stream, Stream)
|
62 |
|
63 |
|
64 |
-
def test_on_complete_hook(
|
65 |
callback_fn = mock.MagicMock()
|
66 |
-
|
67 |
|
68 |
mocker.patch.object(request, 'get')
|
69 |
request.get.side_effect = [
|
@@ -72,13 +72,13 @@ def test_on_complete_hook(gangnam_style, mocker):
|
|
72 |
iter([str(random.getrandbits(8 * 1024))]),
|
73 |
]
|
74 |
with mock.patch('pytube.streams.open', mock.mock_open(), create=True):
|
75 |
-
stream =
|
76 |
stream.download()
|
77 |
assert callback_fn.called
|
78 |
|
79 |
|
80 |
-
def test_repr_for_audio_streams(
|
81 |
-
stream = str(
|
82 |
expected = (
|
83 |
'<Stream: itag="140" mime_type="audio/mp4" abr="128kbps" '
|
84 |
'acodec="mp4a.40.2">'
|
@@ -86,8 +86,8 @@ def test_repr_for_audio_streams(gangnam_style):
|
|
86 |
assert stream == expected
|
87 |
|
88 |
|
89 |
-
def test_repr_for_video_streams(
|
90 |
-
stream = str(
|
91 |
expected = (
|
92 |
'<Stream: itag="137" mime_type="video/mp4" res="1080p" '
|
93 |
'fps="30fps" vcodec="avc1.640028">'
|
@@ -95,8 +95,8 @@ def test_repr_for_video_streams(gangnam_style):
|
|
95 |
assert stream == expected
|
96 |
|
97 |
|
98 |
-
def test_repr_for_progressive_streams(
|
99 |
-
stream = str(
|
100 |
expected = (
|
101 |
'<Stream: itag="22" mime_type="video/mp4" res="720p" '
|
102 |
'fps="30fps" vcodec="avc1.64001F" acodec="mp4a.40.2">'
|
@@ -104,8 +104,8 @@ def test_repr_for_progressive_streams(gangnam_style):
|
|
104 |
assert stream == expected
|
105 |
|
106 |
|
107 |
-
def test_repr_for_adaptive_streams(
|
108 |
-
stream = str(
|
109 |
expected = (
|
110 |
'<Stream: itag="137" mime_type="video/mp4" res="1080p" '
|
111 |
'fps="30fps" vcodec="avc1.640028">'
|
|
|
7 |
from pytube import Stream
|
8 |
|
9 |
|
10 |
+
def test_filesize(cipher_signature, mocker):
|
11 |
mocker.patch.object(request, 'get')
|
12 |
request.get.return_value = {'Content-Length': '6796391'}
|
13 |
+
assert cipher_signature.streams.first().filesize == 6796391
|
14 |
|
15 |
|
16 |
+
def test_default_filename(cipher_signature):
|
17 |
expected = 'PSY - GANGNAM STYLE(강남스타일) MV.mp4'
|
18 |
+
stream = cipher_signature.streams.first()
|
19 |
assert stream.default_filename == expected
|
20 |
|
21 |
|
22 |
+
def test_download(cipher_signature, mocker):
|
23 |
mocker.patch.object(request, 'get')
|
24 |
request.get.side_effect = [
|
25 |
{'Content-Length': '16384'},
|
|
|
27 |
iter([str(random.getrandbits(8 * 1024))]),
|
28 |
]
|
29 |
with mock.patch('pytube.streams.open', mock.mock_open(), create=True):
|
30 |
+
stream = cipher_signature.streams.first()
|
31 |
stream.download()
|
32 |
|
33 |
|
34 |
+
def test_progressive_streams_return_includes_audio_track(cipher_signature):
|
35 |
+
stream = cipher_signature.streams.filter(progressive=True).first()
|
36 |
assert stream.includes_audio_track
|
37 |
|
38 |
|
39 |
+
def test_progressive_streams_return_includes_video_track(cipher_signature):
|
40 |
+
stream = cipher_signature.streams.filter(progressive=True).first()
|
41 |
assert stream.includes_video_track
|
42 |
|
43 |
|
44 |
+
def test_on_progress_hook(cipher_signature, mocker):
|
45 |
callback_fn = mock.MagicMock()
|
46 |
+
cipher_signature.register_on_progress_callback(callback_fn)
|
47 |
|
48 |
mocker.patch.object(request, 'get')
|
49 |
request.get.side_effect = [
|
|
|
52 |
iter([str(random.getrandbits(8 * 1024))]),
|
53 |
]
|
54 |
with mock.patch('pytube.streams.open', mock.mock_open(), create=True):
|
55 |
+
stream = cipher_signature.streams.first()
|
56 |
stream.download()
|
57 |
assert callback_fn.called
|
58 |
args, _ = callback_fn.call_args
|
|
|
61 |
assert isinstance(stream, Stream)
|
62 |
|
63 |
|
64 |
+
def test_on_complete_hook(cipher_signature, mocker):
|
65 |
callback_fn = mock.MagicMock()
|
66 |
+
cipher_signature.register_on_complete_callback(callback_fn)
|
67 |
|
68 |
mocker.patch.object(request, 'get')
|
69 |
request.get.side_effect = [
|
|
|
72 |
iter([str(random.getrandbits(8 * 1024))]),
|
73 |
]
|
74 |
with mock.patch('pytube.streams.open', mock.mock_open(), create=True):
|
75 |
+
stream = cipher_signature.streams.first()
|
76 |
stream.download()
|
77 |
assert callback_fn.called
|
78 |
|
79 |
|
80 |
+
def test_repr_for_audio_streams(cipher_signature):
|
81 |
+
stream = str(cipher_signature.streams.filter(only_audio=True).first())
|
82 |
expected = (
|
83 |
'<Stream: itag="140" mime_type="audio/mp4" abr="128kbps" '
|
84 |
'acodec="mp4a.40.2">'
|
|
|
86 |
assert stream == expected
|
87 |
|
88 |
|
89 |
+
def test_repr_for_video_streams(cipher_signature):
|
90 |
+
stream = str(cipher_signature.streams.filter(only_video=True).first())
|
91 |
expected = (
|
92 |
'<Stream: itag="137" mime_type="video/mp4" res="1080p" '
|
93 |
'fps="30fps" vcodec="avc1.640028">'
|
|
|
95 |
assert stream == expected
|
96 |
|
97 |
|
98 |
+
def test_repr_for_progressive_streams(cipher_signature):
|
99 |
+
stream = str(cipher_signature.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">'
|
|
|
104 |
assert stream == expected
|
105 |
|
106 |
|
107 |
+
def test_repr_for_adaptive_streams(cipher_signature):
|
108 |
+
stream = str(cipher_signature.streams.filter(adaptive=True).first())
|
109 |
expected = (
|
110 |
'<Stream: itag="137" mime_type="video/mp4" res="1080p" '
|
111 |
'fps="30fps" vcodec="avc1.640028">'
|