|
|
|
|
|
from __future__ import unicode_literals |
|
|
|
import warnings |
|
|
|
import mock |
|
from nose.tools import eq_ |
|
from nose.tools import raises |
|
|
|
from pytube import api |
|
from pytube.exceptions import AgeRestricted |
|
from pytube.exceptions import DoesNotExist |
|
from pytube.exceptions import MultipleObjectsReturned |
|
from pytube.exceptions import PytubeError |
|
|
|
|
|
class TestPytube(object): |
|
def setUp(self): |
|
url = 'http://www.youtube.com/watch?v=9bZkp7q19f0' |
|
|
|
with open('tests/mock_data/youtube_gangnam_style.html') as fh: |
|
self.mock_html = fh.read() |
|
|
|
with open('tests/mock_data/youtube_gangnam_style.js') as fh: |
|
self.mock_js = fh.read() |
|
|
|
with mock.patch('pytube.api.urlopen') as urlopen: |
|
urlopen.return_value.read.return_value = self.mock_html |
|
self.yt = api.YouTube() |
|
self.yt._js_cache = self.mock_js |
|
self.yt.from_url(url) |
|
|
|
def test_get_video_id(self): |
|
"""Resolve the video id from url""" |
|
eq_(self.yt.video_id, '9bZkp7q19f0') |
|
|
|
def test_auto_filename(self): |
|
"""Generate safe filename based on video title""" |
|
expected = 'PSY - GANGNAM STYLE(\uac15\ub0a8\uc2a4\ud0c0\uc77c) MV' |
|
|
|
eq_(self.yt.filename, expected) |
|
|
|
def test_manual_filename(self): |
|
"""Manually set a filename""" |
|
expected = 'PSY - Gangnam Style' |
|
|
|
self.yt.set_filename(expected) |
|
eq_(self.yt.filename, expected) |
|
|
|
def test_get_all_videos(self): |
|
"""Get all videos""" |
|
eq_(len(self.yt.get_videos()), 6) |
|
|
|
def test_filter_video_by_extension(self): |
|
"""Filter videos by filetype""" |
|
eq_(len(self.yt.filter('mp4')), 2) |
|
eq_(len(self.yt.filter('3gp')), 2) |
|
eq_(len(self.yt.filter('webm')), 1) |
|
eq_(len(self.yt.filter('flv')), 1) |
|
|
|
def test_filter_video_by_extension_and_resolution(self): |
|
"""Filter videos by file extension and resolution""" |
|
eq_(len(self.yt.filter('mp4', '720p')), 1) |
|
eq_(len(self.yt.filter('mp4', '1080p')), 0) |
|
|
|
def test_filter_video_by_extension_resolution_profile(self): |
|
"""Filter videos by file extension, resolution, and profile""" |
|
eq_(len(self.yt.filter('mp4', '360p', 'Baseline')), 1) |
|
|
|
def test_filter_video_by_profile(self): |
|
"""Filter videos by file profile""" |
|
eq_(len(self.yt.filter(profile='Simple')), 2) |
|
|
|
def test_filter_video_by_resolution(self): |
|
"""Filter videos by resolution""" |
|
eq_(len(self.yt.filter(resolution='360p')), 2) |
|
|
|
@raises(MultipleObjectsReturned) |
|
def test_get_multiple_items(self): |
|
"""get(...) cannot return more than one video""" |
|
self.yt.get(profile='Simple') |
|
self.yt.get('mp4') |
|
self.yt.get(resolution='240p') |
|
|
|
@raises(DoesNotExist) |
|
def test_get_does_not_exist(self): |
|
"""get(...) must return something""" |
|
self.yt.get('mp4', '1080p') |
|
|
|
@raises(AgeRestricted) |
|
def test_age_restricted_video(self): |
|
"""Raise exception on age restricted video""" |
|
url = 'http://www.youtube.com/watch?v=nzNgkc6t260' |
|
|
|
with open('tests/mock_data/youtube_age_restricted.html') as fh: |
|
mock_html = fh.read() |
|
|
|
with mock.patch('pytube.api.urlopen') as urlopen: |
|
urlopen.return_value.read.return_value = mock_html |
|
yt = api.YouTube() |
|
yt.from_url(url) |
|
|
|
def test_deprecation_warnings_on_url_set(self): |
|
"""Deprecation warnings get triggered on url set""" |
|
with warnings.catch_warnings(record=True) as w: |
|
|
|
warnings.simplefilter('always') |
|
with mock.patch('pytube.api.urlopen') as urlopen: |
|
urlopen.return_value.read.return_value = self.mock_html |
|
yt = api.YouTube() |
|
yt._js_cache = self.mock_js |
|
yt.url = 'http://www.youtube.com/watch?v=9bZkp7q19f0' |
|
eq_(len(w), 1) |
|
|
|
def test_deprecation_warnings_on_filename_set(self): |
|
"""Deprecation warnings get triggered on filename set""" |
|
with warnings.catch_warnings(record=True) as w: |
|
|
|
warnings.simplefilter('always') |
|
self.yt.filename = 'Gangnam Style' |
|
eq_(len(w), 1) |
|
|
|
def test_deprecation_warnings_on_videos_get(self): |
|
"""Deprecation warnings get triggered on video getter""" |
|
with warnings.catch_warnings(record=True) as w: |
|
|
|
warnings.simplefilter('always') |
|
self.yt.videos |
|
eq_(len(w), 1) |
|
|
|
def test_get_json_offset(self): |
|
"""Find the offset in the html for where the js starts""" |
|
offset = self.yt._get_json_offset(self.mock_html) |
|
eq_(offset, 312) |
|
|
|
@raises(PytubeError) |
|
def test_get_json_offset_with_bad_html(self): |
|
"""Raise exception if json offset cannot be found""" |
|
self.yt._get_json_offset('asdfasdf') |
|
|